Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6 
diff --git a/Documentation/aoe/mkshelf.sh b/Documentation/aoe/mkshelf.sh
index 8bacf9f..3261581 100644
--- a/Documentation/aoe/mkshelf.sh
+++ b/Documentation/aoe/mkshelf.sh
@@ -8,13 +8,15 @@
 n_partitions=${n_partitions:-16}
 dir=$1
 shelf=$2
+nslots=16
+maxslot=`echo $nslots 1 - p | dc`
 MAJOR=152
 
 set -e
 
-minor=`echo 10 \* $shelf \* $n_partitions | bc`
+minor=`echo $nslots \* $shelf \* $n_partitions | bc`
 endp=`echo $n_partitions - 1 | bc`
-for slot in `seq 0 9`; do
+for slot in `seq 0 $maxslot`; do
 	for part in `seq 0 $endp`; do
 		name=e$shelf.$slot
 		test "$part" != "0" && name=${name}p$part
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index c8f9a73..68a711f 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -17,7 +17,9 @@
 	* SA P600
 	* SA P800
 	* SA E400
-	* SA E300
+	* SA P400i
+	* SA E200
+	* SA E200i
 
 If nodes are not already created in the /dev/cciss directory, run as root:
 
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 96bea27..24adfe9 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -55,6 +55,7 @@
 aicasm
 aicdb.h*
 asm
+asm-offsets.*
 asm_offsets.*
 autoconf.h*
 bbootsect
diff --git a/Documentation/fb/intel810.txt b/Documentation/fb/intel810.txt
index fd68b16..4f0d6bc 100644
--- a/Documentation/fb/intel810.txt
+++ b/Documentation/fb/intel810.txt
@@ -5,6 +5,7 @@
 	March 17, 2002
 
 	First Released: July 2001
+	Last Update:    September 12, 2005
 ================================================================
 
 A. Introduction
@@ -44,6 +45,8 @@
 
 	- Hardware Cursor Support
  
+	- Supports EDID probing either by DDC/I2C or through the BIOS
+
 C.  List of available options
 	
    a. "video=i810fb"  
@@ -52,14 +55,17 @@
 	Recommendation: required
  
    b. "xres:<value>"  
-	select horizontal resolution in pixels
+	select horizontal resolution in pixels. (This parameter will be
+	ignored if 'mode_option' is specified.  See 'o' below).
 
 	Recommendation: user preference 
 	(default = 640)
 
    c. "yres:<value>"
 	select vertical resolution in scanlines. If Discrete Video Timings
-	is enabled, this will be ignored and computed as 3*xres/4.  
+	is enabled, this will be ignored and computed as 3*xres/4.  (This
+	parameter will be ignored if 'mode_option' is specified.  See 'o'
+	below)  
 
 	Recommendation: user preference
 	(default = 480)
@@ -86,7 +92,8 @@
    g. "hsync1/hsync2:<value>" 
 	select the minimum and maximum Horizontal Sync Frequency of the 
 	monitor in KHz.  If a using a fixed frequency monitor, hsync1 must 
-	be equal to hsync2. 
+	be equal to hsync2. If EDID probing is successful, these will be
+	ignored and values will be taken from the EDID block.
 
 	Recommendation: check monitor manual for correct values
 	default (29/30)
@@ -94,7 +101,8 @@
    h. "vsync1/vsync2:<value>" 
 	select the minimum and maximum Vertical Sync Frequency of the monitor
 	in Hz. You can also use this option to lock your monitor's refresh 
-	rate.
+	rate. If EDID probing is successful, these will be ignored and values
+	will be taken from the EDID block.
 
 	Recommendation: check monitor manual for correct values
 	(default = 60/60)
@@ -154,7 +162,11 @@
 
 	Recommendation: do not set
 	(default = not set)
-			
+   o. <xres>x<yres>[-<bpp>][@<refresh>]
+	The driver will now accept specification of boot mode option.  If this
+	is specified, the options 'xres' and 'yres' will be ignored. See
+	Documentation/fb/modedb.txt for usage.
+
 D. Kernel booting
 
 Separate each option/option-pair by commas (,) and the option from its value
@@ -176,7 +188,10 @@
 
 IMPORTANT:
 You must include hsync1, hsync2, vsync1 and vsync2 to enable video modes
-better than 640x480 at 60Hz.
+better than 640x480 at 60Hz. HOWEVER, if your chipset/display combination
+supports I2C and has an EDID block, you can safely exclude hsync1, hsync2,
+vsync1 and vsync2 parameters.  These parameters will be taken from the EDID
+block.
 
 E.  Module options
 	
@@ -217,32 +232,21 @@
 	   This is required.  The option is under "Character Devices"
 
 	d. Under "Graphics Support", select "Intel 810/815" either statically
-	   or as a module.  Choose "use VESA GTF for video timings"  if you 
-	   need to maximize the capability of your display.  To be on the 
+	   or as a module.  Choose "use VESA Generalized Timing Formula" if
+	   you need to maximize the capability of your display.  To be on the 
 	   safe side, you can leave this unselected.  
   
-        e. If you want a framebuffer console, enable it under "Console 
+	e. If you want support for DDC/I2C probing (Plug and Play Displays),
+	   set 'Enable DDC Support' to 'y'. To make this option appear, set
+	   'use VESA Generalized Timing Formula' to 'y'.
+
+        f. If you want a framebuffer console, enable it under "Console 
 	   Drivers"
 
-	f. Compile your kernel. 
+	g. Compile your kernel. 
 	  	
-	g. Load the driver as described in section D and E.
+	h. Load the driver as described in section D and E.
 	
-	Optional:	
-	h.  If you are going to run XFree86 with its native drivers, the 
-	    standard XFree86 4.1.0 and 4.2.0 drivers should work as is.
-            However, there's a bug in the XFree86 i810 drivers.  It attempts 
-	    to use XAA even when switched to the console. This will crash
-	    your server. I have a fix at this site:  
-	    
-	    http://i810fb.sourceforge.net.  
-
-	    You can either use the patch, or just replace 
-	    
-            /usr/X11R6/lib/modules/drivers/i810_drv.o
-
-	    with the one provided at the website. 	
-
 	i.  Try the DirectFB (http://www.directfb.org) + the i810 gfxdriver
 	    patch to see the chipset in action (or inaction :-).
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 784e08c..b67189a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -17,15 +17,6 @@
 
 ---------------------------
 
-What:	io_remap_page_range() (macro or function)
-When:	September 2005
-Why:	Replaced by io_remap_pfn_range() which allows more memory space
-	addressabilty (by using a pfn) and supports sparc & sparc64
-	iospace as part of the pfn.
-Who:	Randy Dunlap <rddunlap@osdl.org>
-
----------------------------
-
 What:	RAW driver (CONFIG_RAW_DRIVER)
 When:	December 2005
 Why:	declared obsolete since kernel 2.6.3
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index e1c56a7..4bef8c2 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -32,14 +32,14 @@
 	u8 buf[size+1];
 	memcpy(buf, firmware, size);
 	buf[size] = '\0';
-	printk("firmware_sample_driver: firmware: %s\n", buf);
+	printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf);
 }
 
 static void sample_probe_default(void)
 {
 	/* uses the default method to get the firmware */
         const struct firmware *fw_entry;
-	printk("firmware_sample_driver: a ghost device got inserted :)\n");
+	printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
 
         if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0)
 	{
@@ -61,7 +61,7 @@
 
 	/* NOTE: This currently doesn't work */
 
-	printk("firmware_sample_driver: a ghost device got inserted :)\n");
+	printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n");
 
         if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0)
 	{
@@ -83,7 +83,7 @@
 		return;
 	}
 
-	printk("firmware_sample_driver: device pointer \"%s\"\n",
+	printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n",
 	       (char *)context);
 	sample_firmware_load(fw->data, fw->size);
 }
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
new file mode 100644
index 0000000..b48d11d
--- /dev/null
+++ b/Documentation/input/appletouch.txt
@@ -0,0 +1,84 @@
+Apple Touchpad Driver (appletouch)
+----------------------------------
+	Copyright (C) 2005 Stelian Pop <stelian@popies.net>
+
+appletouch is a Linux kernel driver for the USB touchpad found on post
+February 2005 Apple Alu Powerbooks.
+
+This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
+been improved in some areas:
+	* appletouch is a full kernel driver, no userspace program is necessary
+	* appletouch can be interfaced with the synaptics X11 driver, in order
+	  to have touchpad acceleration, scrolling, etc.
+
+Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
+Frank Arnold for further improvements, and Alex Harper for some additional
+information about the inner workings of the touchpad sensors.
+
+Usage:
+------
+
+In order to use the touchpad in the basic mode, compile the driver and load
+the module. A new input device will be detected and you will be able to read
+the mouse data from /dev/input/mice (using gpm, or X11).
+
+In X11, you can configure the touchpad to use the synaptics X11 driver, which
+will give additional functionalities, like acceleration, scrolling, 2 finger
+tap for middle button mouse emulation, 3 finger tap for right button mouse
+emulation, etc. In order to do this, make sure you're using a recent version of
+the synaptics driver (tested with 0.14.2, available from [2]), and configure a
+new input device in your X11 configuration file (take a look below for an
+example). For additional configuration, see the synaptics driver documentation.
+
+	Section "InputDevice"
+        	Identifier      "Synaptics Touchpad"
+	        Driver          "synaptics"
+		Option          "SendCoreEvents"        "true"
+		Option          "Device"                "/dev/input/mice"
+		Option          "Protocol"              "auto-dev"
+		Option		"LeftEdge"		"0"
+		Option		"RightEdge"		"850"
+		Option		"TopEdge"		"0"
+		Option		"BottomEdge"		"645"
+		Option		"MinSpeed"		"0.4"
+		Option		"MaxSpeed"		"1"
+		Option		"AccelFactor"		"0.02"
+		Option		"FingerLow"		"0"
+		Option		"FingerHigh"		"30"
+		Option		"MaxTapMove"		"20"
+		Option		"MaxTapTime"		"100"
+		Option		"HorizScrollDelta"	"0"
+		Option		"VertScrollDelta"	"30"
+		Option		"SHMConfig"		"on"
+	EndSection
+
+	Section "ServerLayout"
+		...
+		InputDevice	"Mouse"
+		InputDevice	"Synaptics Touchpad"
+	...
+	EndSection
+
+Fuzz problems:
+--------------
+
+The touchpad sensors are very sensitive to heat, and will generate a lot of
+noise when the temperature changes. This is especially true when you power-on
+the laptop for the first time.
+
+The appletouch driver tries to handle this noise and auto adapt itself, but it
+is not perfect. If finger movements are not recognized anymore, try reloading
+the driver.
+
+You can activate debugging using the 'debug' module parameter. A value of 0
+deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
+full tracing (each sample is being traced):
+	modprobe appletouch debug=1
+		or
+	echo "1" > /sys/module/appletouch/parameters/debug
+
+Links:
+------
+
+[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
+[2]: http://web.telia.com/~u89404340/touchpad/index.html
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 1f5f7d2..5f08f9c 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -66,11 +66,11 @@
    c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
 	CONFIG_PROC_VMCORE=y
    d) Disable SMP support and build a UP kernel (Until it is fixed).
-   	CONFIG_SMP=n
+	CONFIG_SMP=n
    e) Enable "Local APIC support on uniprocessors".
-   	CONFIG_X86_UP_APIC=y
+	CONFIG_X86_UP_APIC=y
    f) Enable "IO-APIC support on uniprocessors"
-   	CONFIG_X86_UP_IOAPIC=y
+	CONFIG_X86_UP_IOAPIC=y
 
   Note:   i) Options a) and b) depend upon "Configure standard kernel features
 	     (for small systems)" (under General setup).
@@ -95,6 +95,11 @@
 	    hence have memory less than 4GB.
        iii) Specify "irqpoll" as command line parameter. This reduces driver
             initialization failures in second kernel due to shared interrupts.
+        iv) <root-dev> needs to be specified in a format corresponding to
+            the root device name in the output of mount command.
+         v) If you have built the drivers required to mount root file
+            system as modules in <second-kernel>, then, specify
+            --initrd=<initrd-for-second-kernel>.
 
 5) System reboots into the second kernel when a panic occurs. A module can be
    written to force the panic or "ALT-SysRq-c" can be used initiate a crash
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index db2603c..7086f0a 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -164,6 +164,15 @@
 			over-ride platform specific driver.
 			See also Documentation/acpi-hotkey.txt.
 
+	enable_timer_pin_1 [i386,x86-64]
+			Enable PIN 1 of APIC timer
+			Can be useful to work around chipset bugs (in particular on some ATI chipsets)
+			The kernel tries to set a reasonable default.
+
+	disable_timer_pin_1 [i386,x86-64]
+			Disable PIN 1 of APIC timer
+			Can be useful to work around chipset bugs.
+
 	ad1816=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>
 			See also Documentation/sound/oss/AD1816.
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index da71102..66eaaab 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -205,8 +205,8 @@
 Tainted kernels:
 
 Some oops reports contain the string 'Tainted: ' after the program
-counter, this indicates that the kernel has been tainted by some
-mechanism.  The string is followed by a series of position sensitive
+counter. This indicates that the kernel has been tainted by some
+mechanism.  The string is followed by a series of position-sensitive
 characters, each representing a particular tainted value.
 
   1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
@@ -214,16 +214,25 @@
      MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
      insmod as GPL compatible are assumed to be proprietary.
 
-  2: 'F' if any module was force loaded by insmod -f, ' ' if all
+  2: 'F' if any module was force loaded by "insmod -f", ' ' if all
      modules were loaded normally.
 
   3: 'S' if the oops occurred on an SMP kernel running on hardware that
-      hasn't been certified as safe to run multiprocessor.
-	  Currently this occurs only on various Athlons that are not
-	  SMP capable.
+     hasn't been certified as safe to run multiprocessor.
+     Currently this occurs only on various Athlons that are not
+     SMP capable.
+
+  4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
+     modules were unloaded normally.
+
+  5: 'M' if any processor has reported a Machine Check Exception,
+     ' ' if no Machine Check Exceptions have occurred.
+
+  6: 'B' if a page-release function has found a bad page reference or
+     some unexpected page flags.
 
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
-occurred.  Tainting is permanent, even if an offending module is
-unloading the tainted value remains to indicate that the kernel is not
+occurred.  Tainting is permanent: even if an offending module is
+unloaded, the tainted value remains to indicate that the kernel is not
 trustworthy.
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index cc63ae1..2ea1149 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -38,6 +38,12 @@
 
 Driver Interface -- OBSOLETE, DO NOT USE!
 ----------------*************************
+
+Note: pm_register(), pm_access(), pm_dev_idle() and friends are
+obsolete. Please do not use them. Instead you should properly hook
+your driver into the driver model, and use its suspend()/resume()
+callbacks to do this kind of stuff.
+
 If you are writing a new driver or maintaining an old driver, it
 should include power management support.  Without power management
 support, a single driver may prevent a system with power management
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index f9cb5bd..fef92eb 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -60,6 +60,8 @@
 	- short blurb on using SCSI support as a module.
 scsi_mid_low_api.txt
 	- info on API between SCSI layer and low level drivers
+scsi_eh.txt
+	- info on SCSI midlayer error handling infrastructure
 st.txt
 	- info on scsi tape driver
 sym53c500_cs.txt
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
new file mode 100644
index 0000000..534a509
--- /dev/null
+++ b/Documentation/scsi/scsi_eh.txt
@@ -0,0 +1,479 @@
+
+SCSI EH
+======================================
+
+ This document describes SCSI midlayer error handling infrastructure.
+Please refer to Documentation/scsi/scsi_mid_low_api.txt for more
+information regarding SCSI midlayer.
+
+TABLE OF CONTENTS
+
+[1] How SCSI commands travel through the midlayer and to EH
+    [1-1] struct scsi_cmnd
+    [1-2] How do scmd's get completed?
+	[1-2-1] Completing a scmd w/ scsi_done
+	[1-2-2] Completing a scmd w/ timeout
+    [1-3] How EH takes over
+[2] How SCSI EH works
+    [2-1] EH through fine-grained callbacks
+	[2-1-1] Overview
+	[2-1-2] Flow of scmds through EH
+	[2-1-3] Flow of control
+    [2-2] EH through hostt->eh_strategy_handler()
+	[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
+	[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+	[2-2-3] Things to consider
+
+
+[1] How SCSI commands travel through the midlayer and to EH
+
+[1-1] struct scsi_cmnd
+
+ Each SCSI command is represented with struct scsi_cmnd (== scmd).  A
+scmd has two list_head's to link itself into lists.  The two are
+scmd->list and scmd->eh_entry.  The former is used for free list or
+per-device allocated scmd list and not of much interest to this EH
+discussion.  The latter is used for completion and EH lists and unless
+otherwise stated scmds are always linked using scmd->eh_entry in this
+discussion.
+
+
+[1-2] How do scmd's get completed?
+
+ Once LLDD gets hold of a scmd, either the LLDD will complete the
+command by calling scsi_done callback passed from midlayer when
+invoking hostt->queuecommand() or SCSI midlayer will time it out.
+
+
+[1-2-1] Completing a scmd w/ scsi_done
+
+ For all non-EH commands, scsi_done() is the completion callback.  It
+does the following.
+
+ 1. Delete timeout timer.  If it fails, it means that timeout timer
+    has expired and is going to finish the command.  Just return.
+
+ 2. Link scmd to per-cpu scsi_done_q using scmd->en_entry
+
+ 3. Raise SCSI_SOFTIRQ
+
+ SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to
+determine what to do with the command.  scsi_decide_disposition()
+looks at the scmd->result value and sense data to determine what to do
+with the command.
+
+ - SUCCESS
+	scsi_finish_command() is invoked for the command.  The
+	function does some maintenance choirs and notify completion by
+	calling scmd->done() callback, which, for fs requests, would
+	be HLD completion callback - sd:sd_rw_intr, sr:rw_intr,
+	st:st_intr.
+
+ - NEEDS_RETRY
+ - ADD_TO_MLQUEUE
+	scmd is requeued to blk queue.
+
+ - otherwise
+	scsi_eh_scmd_add(scmd, 0) is invoked for the command.  See
+	[1-3] for details of this funciton.
+
+
+[1-2-2] Completing a scmd w/ timeout
+
+ The timeout handler is scsi_times_out().  When a timeout occurs, this
+function
+
+ 1. invokes optional hostt->eh_timedout() callback.  Return value can
+    be one of
+
+    - EH_HANDLED
+	This indicates that eh_timedout() dealt with the timeout.  The
+	scmd is passed to __scsi_done() and thus linked into per-cpu
+	scsi_done_q.  Normal command completion described in [1-2-1]
+	follows.
+
+    - EH_RESET_TIMER
+	This indicates that more time is required to finish the
+	command.  Timer is restarted.  This action is counted as a
+	retry and only allowed scmd->allowed + 1(!) times.  Once the
+	limit is reached, action for EH_NOT_HANDLED is taken instead.
+
+	*NOTE* This action is racy as the LLDD could finish the scmd
+	after the timeout has expired but before it's added back.  In
+	such cases, scsi_done() would think that timeout has occurred
+	and return without doing anything.  We lose completion and the
+	command will time out again.
+
+    - EH_NOT_HANDLED
+	This is the same as when eh_timedout() callback doesn't exist.
+	Step #2 is taken.
+
+ 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the
+    command.  See [1-3] for more information.
+
+
+[1-3] How EH takes over
+
+ scmds enter EH via scsi_eh_scmd_add(), which does the following.
+
+ 1. Turns on scmd->eh_eflags as requested.  It's 0 for error
+    completions and SCSI_EH_CANCEL_CMD for timeouts.
+
+ 2. Links scmd->eh_entry to shost->eh_cmd_q
+
+ 3. Sets SHOST_RECOVERY bit in shost->shost_state
+
+ 4. Increments shost->host_failed
+
+ 5. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed
+
+ As can be seen above, once any scmd is added to shost->eh_cmd_q,
+SHOST_RECOVERY shost_state bit is turned on.  This prevents any new
+scmd to be issued from blk queue to the host; eventually, all scmds on
+the host either complete normally, fail and get added to eh_cmd_q, or
+time out and get added to shost->eh_cmd_q.
+
+ If all scmds either complete or fail, the number of in-flight scmds
+becomes equal to the number of failed scmds - i.e. shost->host_busy ==
+shost->host_failed.  This wakes up SCSI EH thread.  So, once woken up,
+SCSI EH thread can expect that all in-flight commands have failed and
+are linked on shost->eh_cmd_q.
+
+ Note that this does not mean lower layers are quiescent.  If a LLDD
+completed a scmd with error status, the LLDD and lower layers are
+assumed to forget about the scmd at that point.  However, if a scmd
+has timed out, unless hostt->eh_timedout() made lower layers forget
+about the scmd, which currently no LLDD does, the command is still
+active as long as lower layers are concerned and completion could
+occur at any time.  Of course, all such completions are ignored as the
+timer has already expired.
+
+ We'll talk about how SCSI EH takes actions to abort - make LLDD
+forget about - timed out scmds later.
+
+
+[2] How SCSI EH works
+
+ LLDD's can implement SCSI EH actions in one of the following two
+ways.
+
+ - Fine-grained EH callbacks
+	LLDD can implement fine-grained EH callbacks and let SCSI
+	midlayer drive error handling and call appropriate callbacks.
+	This will be dicussed further in [2-1].
+
+ - eh_strategy_handler() callback
+	This is one big callback which should perform whole error
+	handling.  As such, it should do all choirs SCSI midlayer
+	performs during recovery.  This will be discussed in [2-2].
+
+ Once recovery is complete, SCSI EH resumes normal operation by
+calling scsi_restart_operations(), which
+
+ 1. Checks if door locking is needed and locks door.
+
+ 2. Clears SHOST_RECOVERY shost_state bit
+
+ 3. Wakes up waiters on shost->host_wait.  This occurs if someone
+    calls scsi_block_when_processing_errors() on the host.
+    (*QUESTION* why is it needed?  All operations will be blocked
+    anyway after it reaches blk queue.)
+
+ 4. Kicks queues in all devices on the host in the asses
+
+
+[2-1] EH through fine-grained callbacks
+
+[2-1-1] Overview
+
+ If eh_strategy_handler() is not present, SCSI midlayer takes charge
+of driving error handling.  EH's goals are two - make LLDD, host and
+device forget about timed out scmds and make them ready for new
+commands.  A scmd is said to be recovered if the scmd is forgotten by
+lower layers and lower layers are ready to process or fail the scmd
+again.
+
+ To achieve these goals, EH performs recovery actions with increasing
+severity.  Some actions are performed by issueing SCSI commands and
+others are performed by invoking one of the following fine-grained
+hostt EH callbacks.  Callbacks may be omitted and omitted ones are
+considered to fail always.
+
+int (* eh_abort_handler)(struct scsi_cmnd *);
+int (* eh_device_reset_handler)(struct scsi_cmnd *);
+int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+int (* eh_host_reset_handler)(struct scsi_cmnd *);
+
+ Higher-severity actions are taken only when lower-severity actions
+cannot recover some of failed scmds.  Also, note that failure of the
+highest-severity action means EH failure and results in offlining of
+all unrecovered devices.
+
+ During recovery, the following rules are followed
+
+ - Recovery actions are performed on failed scmds on the to do list,
+   eh_work_q.  If a recovery action succeeds for a scmd, recovered
+   scmds are removed from eh_work_q.
+
+   Note that single recovery action on a scmd can recover multiple
+   scmds.  e.g. resetting a device recovers all failed scmds on the
+   device.
+
+ - Higher severity actions are taken iff eh_work_q is not empty after
+   lower severity actions are complete.
+
+ - EH reuses failed scmds to issue commands for recovery.  For
+   timed-out scmds, SCSI EH ensures that LLDD forgets about a scmd
+   before reusing it for EH commands.
+
+ When a scmd is recovered, the scmd is moved from eh_work_q to EH
+local eh_done_q using scsi_eh_finish_cmd().  After all scmds are
+recovered (eh_work_q is empty), scsi_eh_flush_done_q() is invoked to
+either retry or error-finish (notify upper layer of failure) recovered
+scmds.
+
+ scmds are retried iff its sdev is still online (not offlined during
+EH), REQ_FAILFAST is not set and ++scmd->retries is less than
+scmd->allowed.
+
+
+[2-1-2] Flow of scmds through EH
+
+ 1. Error completion / time out
+    ACTION: scsi_eh_scmd_add() is invoked for scmd
+	- set scmd->eh_eflags
+	- add scmd to shost->eh_cmd_q
+	- set SHOST_RECOVERY
+	- shost->host_failed++
+    LOCKING: shost->host_lock
+
+ 2. EH starts
+    ACTION: move all scmds to EH's local eh_work_q.  shost->eh_cmd_q
+	    is cleared.
+    LOCKING: shost->host_lock (not strictly necessary, just for
+             consistency)
+
+ 3. scmd recovered
+    ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
+	- shost->host_failed--
+	- clear scmd->eh_eflags
+	- scsi_setup_cmd_retry()
+	- move from local eh_work_q to local eh_done_q
+    LOCKING: none
+
+ 4. EH completes
+    ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
+	    layer of failure.
+	- scmd is removed from eh_done_q and scmd->eh_entry is cleared
+	- if retry is necessary, scmd is requeued using
+          scsi_queue_insert()
+	- otherwise, scsi_finish_command() is invoked for scmd
+    LOCKING: queue or finish function performs appropriate locking
+
+
+[2-1-3] Flow of control
+
+ EH through fine-grained callbacks start from scsi_unjam_host().
+
+<<scsi_unjam_host>>
+
+    1. Lock shost->host_lock, splice_init shost->eh_cmd_q into local
+       eh_work_q and unlock host_lock.  Note that shost->eh_cmd_q is
+       cleared by this action.
+
+    2. Invoke scsi_eh_get_sense.
+
+    <<scsi_eh_get_sense>>
+
+	This action is taken for each error-completed
+	(!SCSI_EH_CANCEL_CMD) commands without valid sense data.  Most
+	SCSI transports/LLDDs automatically acquire sense data on
+	command failures (autosense).  Autosense is recommended for
+	performance reasons and as sense information could get out of
+	sync inbetween occurrence of CHECK CONDITION and this action.
+
+	Note that if autosense is not supported, scmd->sense_buffer
+	contains invalid sense data when error-completing the scmd
+	with scsi_done().  scsi_decide_disposition() always returns
+	FAILED in such cases thus invoking SCSI EH.  When the scmd
+	reaches here, sense data is acquired and
+	scsi_decide_disposition() is called again.
+
+	1. Invoke scsi_request_sense() which issues REQUEST_SENSE
+           command.  If fails, no action.  Note that taking no action
+           causes higher-severity recovery to be taken for the scmd.
+
+	2. Invoke scsi_decide_disposition() on the scmd
+
+	   - SUCCESS
+		scmd->retries is set to scmd->allowed preventing
+		scsi_eh_flush_done_q() from retrying the scmd and
+		scsi_eh_finish_cmd() is invoked.
+
+	   - NEEDS_RETRY
+		scsi_eh_finish_cmd() invoked
+
+	   - otherwise
+		No action.
+
+    3. If !list_empty(&eh_work_q), invoke scsi_eh_abort_cmds().
+
+    <<scsi_eh_abort_cmds>>
+
+	This action is taken for each timed out command.
+	hostt->eh_abort_handler() is invoked for each scmd.  The
+	handler returns SUCCESS if it has succeeded to make LLDD and
+	all related hardware forget about the scmd.
+
+	If a timedout scmd is successfully aborted and the sdev is
+	either offline or ready, scsi_eh_finish_cmd() is invoked for
+	the scmd.  Otherwise, the scmd is left in eh_work_q for
+	higher-severity actions.
+
+	Note that both offline and ready status mean that the sdev is
+	ready to process new scmds, where processing also implies
+	immediate failing; thus, if a sdev is in one of the two
+	states, no further recovery action is needed.
+
+	Device readiness is tested using scsi_eh_tur() which issues
+	TEST_UNIT_READY command.  Note that the scmd must have been
+	aborted successfully before reusing it for TEST_UNIT_READY.
+
+    4. If !list_empty(&eh_work_q), invoke scsi_eh_ready_devs()
+
+    <<scsi_eh_ready_devs>>
+
+	This function takes four increasingly more severe measures to
+	make failed sdevs ready for new commands.
+
+	1. Invoke scsi_eh_stu()
+
+	<<scsi_eh_stu>>
+
+	    For each sdev which has failed scmds with valid sense data
+	    of which scsi_check_sense()'s verdict is FAILED,
+	    START_STOP_UNIT command is issued w/ start=1.  Note that
+	    as we explicitly choose error-completed scmds, it is known
+	    that lower layers have forgotten about the scmd and we can
+	    reuse it for STU.
+
+	    If STU succeeds and the sdev is either offline or ready,
+	    all failed scmds on the sdev are EH-finished with
+	    scsi_eh_finish_cmd().
+
+	    *NOTE* If hostt->eh_abort_handler() isn't implemented or
+	    failed, we may still have timed out scmds at this point
+	    and STU doesn't make lower layers forget about those
+	    scmds.  Yet, this function EH-finish all scmds on the sdev
+	    if STU succeeds leaving lower layers in an inconsistent
+	    state.  It seems that STU action should be taken only when
+	    a sdev has no timed out scmd.
+
+	2. If !list_empty(&eh_work_q), invoke scsi_eh_bus_device_reset().
+
+	<<scsi_eh_bus_device_reset>>
+
+	    This action is very similar to scsi_eh_stu() except that,
+	    instead of issuing STU, hostt->eh_device_reset_handler()
+	    is used.  Also, as we're not issuing SCSI commands and
+	    resetting clears all scmds on the sdev, there is no need
+	    to choose error-completed scmds.
+
+	3. If !list_empty(&eh_work_q), invoke scsi_eh_bus_reset()
+
+	<<scsi_eh_bus_reset>>
+
+	    hostt->eh_bus_reset_handler() is invoked for each channel
+	    with failed scmds.  If bus reset succeeds, all failed
+	    scmds on all ready or offline sdevs on the channel are
+	    EH-finished.
+
+	4. If !list_empty(&eh_work_q), invoke scsi_eh_host_reset()
+
+	<<scsi_eh_host_reset>>
+
+	    This is the last resort.  hostt->eh_host_reset_handler()
+	    is invoked.  If host reset succeeds, all failed scmds on
+	    all ready or offline sdevs on the host are EH-finished.
+
+	5. If !list_empty(&eh_work_q), invoke scsi_eh_offline_sdevs()
+
+	<<scsi_eh_offline_sdevs>>
+
+	    Take all sdevs which still have unrecovered scmds offline
+	    and EH-finish the scmds.
+
+    5. Invoke scsi_eh_flush_done_q().
+
+	<<scsi_eh_flush_done_q>>
+
+	    At this point all scmds are recovered (or given up) and
+	    put on eh_done_q by scsi_eh_finish_cmd().  This function
+	    flushes eh_done_q by either retrying or notifying upper
+	    layer of failure of the scmds.
+
+
+[2-2] EH through hostt->eh_strategy_handler()
+
+ hostt->eh_strategy_handler() is invoked in the place of
+scsi_unjam_host() and it is responsible for whole recovery process.
+On completion, the handler should have made lower layers forget about
+all failed scmds and either ready for new commands or offline.  Also,
+it should perform SCSI EH maintenance choirs to maintain integrity of
+SCSI midlayer.  IOW, of the steps described in [2-1-2], all steps
+except for #1 must be implemented by eh_strategy_handler().
+
+
+[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
+
+ The following conditions are true on entry to the handler.
+
+ - Each failed scmd's eh_flags field is set appropriately.
+
+ - Each failed scmd is linked on scmd->eh_cmd_q by scmd->eh_entry.
+
+ - SHOST_RECOVERY is set.
+
+ - shost->host_failed == shost->host_busy
+
+
+[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+
+ The following conditions must be true on exit from the handler.
+
+ - shost->host_failed is zero.
+
+ - Each scmd's eh_eflags field is cleared.
+
+ - Each scmd is in such a state that scsi_setup_cmd_retry() on the
+   scmd doesn't make any difference.
+
+ - shost->eh_cmd_q is cleared.
+
+ - Each scmd->eh_entry is cleared.
+
+ - Either scsi_queue_insert() or scsi_finish_command() is called on
+   each scmd.  Note that the handler is free to use scmd->retries and
+   ->allowed to limit the number of retries.
+
+
+[2-2-3] Things to consider
+
+ - Know that timed out scmds are still active on lower layers.  Make
+   lower layers forget about them before doing anything else with
+   those scmds.
+
+ - For consistency, when accessing/modifying shost data structure,
+   grab shost->host_lock.
+
+ - On completion, each failed sdev must have forgotten about all
+   active scmds.
+
+ - On completion, each failed sdev must be ready for new commands or
+   offline.
+
+
+--
+Tejun Heo
+htejun@gmail.com
+11th September 2005
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index ebfcdf2..13cba95 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -75,7 +75,7 @@
     adsp_map	- PCM device number maps assigned to the 2st OSS device.
 		- Default: 1
     nonblock_open
-		- Don't block opening busy PCM devices.
+		- Don't block opening busy PCM devices.  Default: 1
 
     For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
     the card #0.  Similarly, when adsp_map=0, /dev/adsp will be mapped
@@ -148,6 +148,16 @@
     Module supports up to 8 cards. This module does not support autoprobe
     thus main port must be specified!!! Other ports are optional.
     
+  Module snd-ad1889
+  -----------------
+
+    Module for Analog Devices AD1889 chips.
+
+    ac97_quirk  - AC'97 workaround for strange hardware
+                  See the description of intel8x0 module for details.
+
+    This module supports up to 8 cards.
+
   Module snd-ali5451
   ------------------
 
@@ -189,15 +199,20 @@
   Module snd-atiixp
   -----------------
 
-    Module for ATI IXP 150/200/250 AC97 controllers.
+    Module for ATI IXP 150/200/250/400 AC97 controllers.
 
-    ac97_clock		- AC'97 clock (defalut = 48000)
+    ac97_clock		- AC'97 clock (default = 48000)
     ac97_quirk		- AC'97 workaround for strange hardware
-			  See the description of intel8x0 module for details.
+			  See "AC97 Quirk Option" section below.
     spdif_aclink	- S/PDIF transfer over AC-link (default = 1)
 
     This module supports up to 8 cards and autoprobe.
 
+    ATI IXP has two different methods to control SPDIF output.  One is
+    over AC-link and another is over the "direct" SPDIF output.  The
+    implementation depends on the motherboard, and you'll need to
+    choose the correct one via spdif_aclink module option.
+
   Module snd-atiixp-modem
   -----------------------
 
@@ -230,7 +245,7 @@
     The hardware EQ hardware and SPDIF is only present in the Vortex2 and 
     Advantage.
 
-    Note: Some ALSA mixer applicactions don't handle the SPDIF samplerate 
+    Note: Some ALSA mixer applications don't handle the SPDIF sample rate 
            control correctly. If you have problems regarding this, try
            another ALSA compliant mixer (alsamixer works).
 
@@ -302,7 +317,7 @@
 
     mpu_port	- 0x300,0x310,0x320,0x330, 0 = disable (default)
     fm_port     - 0x388 (default), 0 = disable (default)
-    soft_ac3    - Sofware-conversion of raw SPDIF packets (model 033 only)
+    soft_ac3    - Software-conversion of raw SPDIF packets (model 033 only)
                   (default = 1)
     joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
 
@@ -384,7 +399,7 @@
     Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
 				       CS4624/CS4630/CS4280 PCI chips.
 
-    external_amp     - Force to enable external amplifer.
+    external_amp     - Force to enable external amplifier.
     thinkpad         - Force to enable Thinkpad's CLKRUN control.
     mmap_valid       - Support OSS mmap mode (default = 0).
 
@@ -620,7 +635,7 @@
 	       VIA VT8251/VT8237A
 
     model	- force the model name
-    position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
+    position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
 
     Module supports up to 8 cards.
 
@@ -656,6 +671,11 @@
 	  allout	5-jack in back, 2-jack in front, SPDIF out
 	  auto		auto-config reading BIOS (default)
 
+    If the default configuration doesn't work and one of the above
+    matches with your device, report it together with the PCI
+    subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
+    ML (see the section "Links and Addresses").
+
     Note 2: If you get click noises on output, try the module option
 	    position_fix=1 or 2.  position_fix=1 will use the SD_LPIB
 	    register value without FIFO size correction as the current
@@ -783,20 +803,13 @@
 
     ac97_clock	  - AC'97 codec clock base (0 = auto-detect)
     ac97_quirk    - AC'97 workaround for strange hardware
-                    The following strings are accepted:
-                      default = don't override the default setting
-                      disable = disable the quirk
-                      hp_only = use headphone control as master
-                      swap_hp = swap headphone and master controls
-                      swap_surround = swap master and surround controls
-                      ad_sharing = for AD1985, turn on OMS bit and use headphone
-                      alc_jack = for ALC65x, turn on the jack sense mode
-                      inv_eapd = inverted EAPD implementation
-                      mute_led = bind EAPD bit for turning on/off mute LED
-                    For backward compatibility, the corresponding integer
-                    value -1, 0, ... are accepted, too.
+		    See "AC97 Quirk Option" section below.
     buggy_irq     - Enable workaround for buggy interrupts on some
-                    motherboards (default off)
+                    motherboards (default yes on nForce chips,
+		    otherwise off)
+    buggy_semaphore - Enable workaround for hardwares with buggy
+		    semaphores (e.g. on some ASUS laptops)
+		    (default off)
 
     Module supports autoprobe and multiple bus-master chips (max 8).
 
@@ -808,13 +821,6 @@
     motherboard has these devices, use the ns558 or snd-mpu401
     modules, respectively.
 
-    The ac97_quirk option is used to enable/override the workaround
-    for specific devices.  Some hardware have swapped output pins
-    between Master and Headphone, or Surround.  The driver provides
-    the auto-detection of known problematic devices, but some might
-    be unknown or wrongly detected.  In such a case, pass the proper
-    value with this option.
-
     The power-management is supported.
     
   Module snd-intel8x0m
@@ -966,7 +972,7 @@
     with machines with other (most likely CS423x or OPL3SAx) chips,
     even though the device is detected in lspci.  In such a case, try
     other drivers, e.g. snd-cs4232 or snd-opl3sa2.  Some has ISA-PnP
-    but some doesn't have ISA PnP.  You'll need to speicfy isapnp=0
+    but some doesn't have ISA PnP.  You'll need to specify isapnp=0
     and proper hardware parameters in the case without ISA PnP.
 
     Note: some laptops need a workaround for AC97 RESET.  For the
@@ -1302,7 +1308,7 @@
 		  channels
 		  [VIA8233/C, 8235, 8237 only]
     ac97_quirk  - AC'97 workaround for strange hardware
-                  See the description of intel8x0 module for details.
+		  See "AC97 Quirk Option" section below.
 
     Module supports autoprobe and multiple bus-master chips (max 8).
 
@@ -1327,16 +1333,17 @@
 	  "lspci -nv").
 	  If dxs_support=5 does not work, try dxs_support=4; if it
 	  doesn't work too, try dxs_support=1.  (dxs_support=1 is
-	  usually for old motherboards.  The correct implementated
+	  usually for old motherboards.  The correct implemented
 	  board should work with 4 or 5.)  If it still doesn't
 	  work and the default setting is ok, dxs_support=3 is the
 	  right choice.  If the default setting doesn't work at all,
 	  try dxs_support=2 to disable the DXS channels.
 	  In any cases, please let us know the result and the
-	  subsystem vendor/device ids.
+	  subsystem vendor/device ids.  See "Links and Addresses"
+	  below.
 
     Note: for the MPU401 on VIA823x, use snd-mpu401 driver
-	  additonally.  The mpu_port option is for VIA686 chips only.
+	  additionally.  The mpu_port option is for VIA686 chips only.
 
   Module snd-via82xx-modem
   ------------------------
@@ -1398,8 +1405,10 @@
     Module supports up to 8 cards.  The module is compiled only when
     PCMCIA is supported on kernel.
 
-    To activate the driver via the card manager, you'll need to set
-    up /etc/pcmcia/vxpocket.conf.  See the sound/pcmcia/vx/vxpocket.c.
+    With the older 2.6.x kernel, to activate the driver via the card
+    manager, you'll need to set up /etc/pcmcia/vxpocket.conf.  See the
+    sound/pcmcia/vx/vxpocket.c.  2.6.13 or later kernel requires no
+    longer require a config file.
 
     When the driver is compiled as a module and the hotplug firmware
     is supported, the firmware data is loaded via hotplug automatically.
@@ -1411,6 +1420,9 @@
 
     Note: the driver is build only when CONFIG_ISA is set.
     
+    Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
+           ALSA 1.0.10.
+
   Module snd-ymfpci
   -----------------
 
@@ -1436,6 +1448,37 @@
     Note: the driver is build only when CONFIG_ISA is set.
 
 
+AC97 Quirk Option
+=================
+
+The ac97_quirk option is used to enable/override the workaround for
+specific devices on drivers for on-board AC'97 controllers like
+snd-intel8x0.  Some hardware have swapped output pins between Master
+and Headphone, or Surround (thanks to confusion of AC'97
+specifications from version to version :-)
+
+The driver provides the auto-detection of known problematic devices,
+but some might be unknown or wrongly detected.  In such a case, pass
+the proper value with this option.
+
+The following strings are accepted:
+    - default	Don't override the default setting
+    - disable	Disable the quirk
+    - hp_only	Bind Master and Headphone controls as a single control
+    - swap_hp	Swap headphone and master controls
+    - swap_surround  Swap master and surround controls
+    - ad_sharing  For AD1985, turn on OMS bit and use headphone
+    - alc_jack	For ALC65x, turn on the jack sense mode
+    - inv_eapd	Inverted EAPD implementation
+    - mute_led	Bind EAPD bit for turning on/off mute LED
+
+For backward compatibility, the corresponding integer value -1, 0,
+... are  accepted, too.
+
+For example, if "Master" volume control has no effect on your device
+but only "Headphone" does, pass ac97_quirk=hp_only module option.
+
+
 Configuring Non-ISAPNP Cards
 ============================
 
@@ -1553,6 +1596,8 @@
 	  - whole-frag  write only whole fragments (optimization affecting
 			playback only)
 	  - no-silence  do not fill silence ahead to avoid clicks
+	  - buggy-ptr	Returns the whitespace blocks in GETOPTR ioctl
+			instead of filled blocks
 
   Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
            echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
@@ -1589,9 +1634,14 @@
     use.
 
 
-Links
-=====
+Links and Addresses
+===================
 
   ALSA project homepage
        http://www.alsa-project.org
 
+  ALSA Bug Tracking System
+       https://bugtrack.alsa-project.org/bugs/
+
+  ALSA Developers ML
+       mailto:alsa-devel@lists.sourceforge.net
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 0475478..24e8552 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -447,7 +447,7 @@
           ....
 
           /* allocate a chip-specific data with zero filled */
-          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           if (chip == NULL)
                   return -ENOMEM;
 
@@ -949,7 +949,7 @@
           After allocating a card instance via
           <function>snd_card_new()</function> (with
           <constant>NULL</constant> on the 4th arg), call
-          <function>kcalloc()</function>. 
+          <function>kzalloc()</function>. 
 
           <informalexample>
             <programlisting>
@@ -958,7 +958,7 @@
   mychip_t *chip;
   card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
   .....
-  chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 ]]>
             </programlisting>
           </informalexample>
@@ -1136,7 +1136,7 @@
                   return -ENXIO;
           }
 
-          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           if (chip == NULL) {
                   pci_disable_device(pci);
                   return -ENOMEM;
@@ -1292,7 +1292,7 @@
       need to initialize this number as -1 before actual allocation,
       since irq 0 is valid. The port address and its resource pointer
       can be initialized as null by
-      <function>kcalloc()</function> automatically, so you
+      <function>kzalloc()</function> automatically, so you
       don't have to take care of resetting them. 
       </para>
 
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index 729c72d..f86550f 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -20,7 +20,7 @@
 
 	  to /etc/fstab.  This will mount usbfs at each reboot.
 	  You can then issue `cat /proc/bus/usb/devices` to extract
-	  USB device information, and user mode drivers can use usbfs 
+	  USB device information, and user mode drivers can use usbfs
 	  to interact with USB devices.
 
 	  There are a number of mount options supported by usbfs.
@@ -32,7 +32,7 @@
 	  still see references to the older "usbdevfs" name.
 
 For more information on mounting the usbfs file system, see the
-"USB Device Filesystem" section of the USB Guide. The latest copy 
+"USB Device Filesystem" section of the USB Guide. The latest copy
 of the USB Guide can be found at http://www.linux-usb.org/
 
 
@@ -133,7 +133,7 @@
     are the only transfers that reserve bandwidth.  Control and bulk
     transfers use all other bandwidth, including reserved bandwidth that
     is not used for transfers (such as for short packets).
-    
+
     The percentage is how much of the "reserved" bandwidth is scheduled by
     those transfers.  For a low or full speed bus (loosely, "USB 1.1"),
     90% of the bus bandwidth is reserved.  For a high speed bus (loosely,
@@ -197,7 +197,7 @@
 | | |__NumberOfInterfaces
 | |__ "*" indicates the active configuration (others are " ")
 |__Config info tag
-    
+
     USB devices may have multiple configurations, each of which act
     rather differently.  For example, a bus-powered configuration
     might be much less capable than one that is self-powered.  Only
@@ -228,7 +228,7 @@
     For example, default settings may not use more than a small
     amount of periodic bandwidth.  To use significant fractions
     of bus bandwidth, drivers must select a non-default altsetting.
-    
+
     Only one setting for an interface may be active at a time, and
     only one driver may bind to an interface at a time.  Most devices
     have only one alternate setting per interface.
@@ -297,18 +297,21 @@
 C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
+
 T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
+
 T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=04b4 ProdID=0001 Rev= 0.00
 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
+
 T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0565 ProdID=0001 Rev= 1.08
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 678e8f1..ffe1c06 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -11,6 +11,11 @@
                If your BIOS doesn't do that it's a good idea to enable though
                to make sure you log even machine check events that result
                in a reboot.
+   mce=tolerancelevel (number)
+		0: always panic, 1: panic if deadlock possible,
+		2: try to avoid panic, 3: never panic or exit (for testing)
+		default is 1
+		Can be also set using sysfs which is preferable.
 
    nomce (for compatibility with i386): same as mce=off
 
diff --git a/MAINTAINERS b/MAINTAINERS
index f038dca..d1e0eb4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -370,7 +370,10 @@
 S:	Maintained
 
 AUDIT SUBSYSTEM
-L:	linux-audit@redhat.com (subscribers-only)
+P:	David Woodhouse
+M:	dwmw2@infradead.org
+L:	linux-audit@redhat.com
+W:	http://people.redhat.com/sgrubb/audit/
 S:	Maintained
 
 AX.25 NETWORK LAYER
@@ -964,6 +967,13 @@
 W:	http://www.lm-sensors.nu/
 S:	Maintained
 
+HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
+P:	Robert Love
+M:	rlove@rlove.org
+M:	linux-kernel@vger.kernel.org
+W:	http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
+S:	Maintained
+
 HARMONY SOUND DRIVER
 P:	Kyle McMartin
 M:	kyle@parisc-linux.org
diff --git a/Makefile b/Makefile
index 45e5a38..4e0d7c6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 13
-EXTRAVERSION =
+SUBLEVEL = 14
+EXTRAVERSION =-rc1
 NAME=Affluent Albatross
 
 # *DOCUMENTATION*
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 405a55f..3e5f69b 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -20,40 +20,66 @@
 	select PXA25x
 
 config PXA_SHARPSL
-	bool "SHARP SL-5600 and SL-C7xx Models"
-	select PXA25x
+	bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models"
 	select SHARP_SCOOP
 	select SHARP_PARAM
 	help
 	  Say Y here if you intend to run this kernel on a
-	  Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
-	  SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
-	  handheld computer.
+	  Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi),
+	  SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita),
+	  SL-C3000 (Spitz) or SL-C3100 (Borzoi) handheld computer.
 
 endchoice
 
+if PXA_SHARPSL
+
+choice
+	prompt "Select target Sharp Zaurus device range"
+
+config PXA_SHARPSL_25x
+	bool "Sharp PXA25x models (SL-5600 and SL-C7xx)"
+	select PXA25x
+
+config PXA_SHARPSL_27x
+	bool "Sharp PXA270 models (SL-Cxx00)"
+	select PXA27x
+
+endchoice
+
+endif
+
 endmenu
 
 config MACH_POODLE
 	bool "Enable Sharp SL-5600 (Poodle) Support"
-	depends PXA_SHARPSL
+	depends PXA_SHARPSL_25x
 	select SHARP_LOCOMO
 
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
-	depends PXA_SHARPSL
+	depends PXA_SHARPSL_25x
 	select PXA_SHARP_C7xx
 
 config MACH_SHEPHERD
 	bool "Enable Sharp SL-C750 (Shepherd) Support"
-	depends PXA_SHARPSL
+	depends PXA_SHARPSL_25x
 	select PXA_SHARP_C7xx
 
 config MACH_HUSKY
 	bool "Enable Sharp SL-C760 (Husky) Support"
-	depends PXA_SHARPSL
+	depends PXA_SHARPSL_25x
 	select PXA_SHARP_C7xx
 
+config MACH_SPITZ
+	bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
+	depends PXA_SHARPSL_27x
+	select PXA_SHARP_Cxx00
+
+config MACH_BORZOI
+	bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
+	depends PXA_SHARPSL_27x
+	select PXA_SHARP_Cxx00
+
 config PXA25x
 	bool
 	help
@@ -74,4 +100,9 @@
 	help
 	  Enable support for all Sharp C7xx models
 
+config PXA_SHARP_Cxx00
+	bool
+	help
+	  Enable common support for Sharp Cxx00 models
+
 endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 33dae99..f609a0f 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
 obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
 obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o corgi_ssp.o corgi_lcd.o ssp.o
+obj-$(CONFIG_PXA_SHARP_Cxx00)	+= spitz.o corgi_ssp.o corgi_lcd.o ssp.o
 obj-$(CONFIG_MACH_POODLE)	+= poodle.o
 
 # Support for blinky lights
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 07b5dd4..426c2bc 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -41,6 +41,7 @@
 #include <asm/hardware/scoop.h>
 
 #include "generic.h"
+#include "sharpsl.h"
 
 
 /*
@@ -94,14 +95,30 @@
 	.id		= -1,
 };
 
+struct corgissp_machinfo corgi_ssp_machinfo = {
+	.port		= 1,
+	.cs_lcdcon	= CORGI_GPIO_LCDCON_CS,
+	.cs_ads7846	= CORGI_GPIO_ADS7846_CS,
+	.cs_max1111	= CORGI_GPIO_MAX1111_CS,
+	.clk_lcdcon	= 76,
+	.clk_ads7846	= 2,
+	.clk_max1111	= 8,
+};
+
 
 /*
  * Corgi Backlight Device
  */
+static struct corgibl_machinfo corgi_bl_machinfo = {
+	.max_intensity = 0x2f,
+	.set_bl_intensity = corgi_bl_set_intensity,
+};
+
 static struct platform_device corgibl_device = {
 	.name		= "corgi-bl",
 	.dev		= {
  		.parent = &corgifb_device.dev,
+		.platform_data	= &corgi_bl_machinfo,
 	},
 	.id		= -1,
 };
@@ -119,12 +136,29 @@
 /*
  * Corgi Touch Screen Device
  */
+static struct resource corgits_resources[] = {
+	[0] = {
+		.start		= CORGI_IRQ_GPIO_TP_INT,
+		.end		= CORGI_IRQ_GPIO_TP_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct corgits_machinfo  corgi_ts_machinfo = {
+	.get_hsync_len   = corgi_get_hsync_len,
+	.put_hsync       = corgi_put_hsync,
+	.wait_hsync      = corgi_wait_hsync,
+};
+
 static struct platform_device corgits_device = {
 	.name		= "corgi-ts",
 	.dev		= {
  		.parent = &corgissp_device.dev,
+		.platform_data	= &corgi_ts_machinfo,
 	},
 	.id		= -1,
+	.num_resources	= ARRAY_SIZE(corgits_resources),
+	.resource	= corgits_resources,
 };
 
 
@@ -225,7 +259,10 @@
 
 static void __init corgi_init(void)
 {
+	corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
+
 	pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
+	pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
  	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&corgi_mci_platform_data);
 
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index deac29c..c5efcd0 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -1,10 +1,14 @@
 /*
  * linux/drivers/video/w100fb.c
  *
- * Corgi LCD Specific Code for ATI Imageon w100 (Wallaby)
+ * Corgi/Spitz LCD Specific Code
  *
  * Copyright (C) 2005 Richard Purdie
  *
+ * Connectivity:
+ *   Corgi - LCD to ATI Imageon w100 (Wallaby)
+ *   Spitz - LCD to PXA Framebuffer
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -14,9 +18,17 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/module.h>
+#include <asm/mach-types.h>
+#include <asm/arch/akita.h>
 #include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/arch/spitz.h>
+#include <asm/hardware/scoop.h>
 #include <asm/mach/sharpsl_param.h>
-#include <video/w100fb.h>
+#include "generic.h"
 
 /* Register Addresses */
 #define RESCTL_ADRS     0x00
@@ -134,10 +146,10 @@
 }
 
 /* Set Phase Adjuct */
-static void lcdtg_set_phadadj(struct w100fb_par *par)
+static void lcdtg_set_phadadj(int mode)
 {
 	int adj;
-	switch(par->xres) {
+	switch(mode) {
 		case 480:
 		case 640:
 			/* Setting for VGA */
@@ -161,7 +173,7 @@
 
 static int lcd_inited;
 
-static void lcdtg_hw_init(struct w100fb_par *par)
+static void lcdtg_hw_init(int mode)
 {
 	if (!lcd_inited) {
 		int comadj;
@@ -215,7 +227,7 @@
 		corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);
 
 		/* Set Phase Adjuct */
-		lcdtg_set_phadadj(par);
+		lcdtg_set_phadadj(mode);
 
 		/* Initialize for Input Signals from ATI */
 		corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE
@@ -224,10 +236,10 @@
 
 		lcd_inited=1;
 	} else {
-		lcdtg_set_phadadj(par);
+		lcdtg_set_phadadj(mode);
 	}
 
-	switch(par->xres) {
+	switch(mode) {
 		case 480:
 		case 640:
 			/* Set Lcd Resolution (VGA) */
@@ -242,7 +254,7 @@
 	}
 }
 
-static void lcdtg_suspend(struct w100fb_par *par)
+static void lcdtg_suspend(void)
 {
 	/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
 	mdelay(34);
@@ -276,15 +288,30 @@
 	lcd_inited = 0;
 }
 
-static struct w100_tg_info corgi_lcdtg_info = {
-	.change=lcdtg_hw_init,
-	.suspend=lcdtg_suspend,
-	.resume=lcdtg_hw_init,
-};
 
 /*
  * Corgi w100 Frame Buffer Device
  */
+#ifdef CONFIG_PXA_SHARP_C7xx
+
+#include <video/w100fb.h>
+
+static void w100_lcdtg_suspend(struct w100fb_par *par)
+{
+	lcdtg_suspend();
+}
+
+static void w100_lcdtg_init(struct w100fb_par *par)
+{
+	lcdtg_hw_init(par->xres);
+}
+
+
+static struct w100_tg_info corgi_lcdtg_info = {
+	.change  = w100_lcdtg_init,
+	.suspend = w100_lcdtg_suspend,
+	.resume  = w100_lcdtg_init,
+};
 
 static struct w100_mem_info corgi_fb_mem = {
 	.ext_cntl          = 0x00040003,
@@ -394,3 +421,145 @@
 	},
 
 };
+#endif
+
+
+/*
+ * Spitz PXA Frame Buffer Device
+ */
+#ifdef CONFIG_PXA_SHARP_Cxx00
+
+#include <asm/arch/pxafb.h>
+
+void spitz_lcd_power(int on)
+{
+	if (on)
+		lcdtg_hw_init(480);
+	else
+		lcdtg_suspend();
+}
+
+#endif
+
+
+/*
+ * Corgi/Spitz Touchscreen to LCD interface
+ */
+static unsigned long (*get_hsync_time)(struct device *dev);
+
+static void inline sharpsl_wait_sync(int gpio)
+{
+	while((GPLR(gpio) & GPIO_bit(gpio)) == 0);
+	while((GPLR(gpio) & GPIO_bit(gpio)) != 0);
+}
+
+#ifdef CONFIG_PXA_SHARP_C7xx
+unsigned long corgi_get_hsync_len(void)
+{
+	if (!get_hsync_time)
+		get_hsync_time = symbol_get(w100fb_get_hsynclen);
+	if (!get_hsync_time)
+		return 0;
+
+	return get_hsync_time(&corgifb_device.dev);
+}
+
+void corgi_put_hsync(void)
+{
+	if (get_hsync_time)
+		symbol_put(w100fb_get_hsynclen);
+}
+
+void corgi_wait_hsync(void)
+{
+	sharpsl_wait_sync(CORGI_GPIO_HSYNC);
+}
+#endif
+
+#ifdef CONFIG_PXA_SHARP_Cxx00
+unsigned long spitz_get_hsync_len(void)
+{
+	if (!get_hsync_time)
+		get_hsync_time = symbol_get(pxafb_get_hsync_time);
+	if (!get_hsync_time)
+		return 0;
+
+	return pxafb_get_hsync_time(&pxafb_device.dev);
+}
+
+void spitz_put_hsync(void)
+{
+	if (get_hsync_time)
+		symbol_put(pxafb_get_hsync_time);
+}
+
+void spitz_wait_hsync(void)
+{
+	sharpsl_wait_sync(SPITZ_GPIO_HSYNC);
+}
+#endif
+
+/*
+ * Corgi/Spitz Backlight Power
+ */
+#ifdef CONFIG_PXA_SHARP_C7xx
+void corgi_bl_set_intensity(int intensity)
+{
+	if (intensity > 0x10)
+		intensity += 0x10;
+
+	/* Bits 0-4 are accessed via the SSP interface */
+	corgi_ssp_blduty_set(intensity & 0x1f);
+
+	/* Bit 5 is via SCOOP */
+	if (intensity & 0x0020)
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+	else
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+}
+#endif
+
+
+#if defined(CONFIG_MACH_SPITZ) || defined(CONFIG_MACH_BORZOI)
+void spitz_bl_set_intensity(int intensity)
+{
+	if (intensity > 0x10)
+		intensity += 0x10;
+
+	/* Bits 0-4 are accessed via the SSP interface */
+	corgi_ssp_blduty_set(intensity & 0x1f);
+
+	/* Bit 5 is via SCOOP */
+	if (intensity & 0x0020)
+		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+	else
+		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);
+
+	if (intensity)
+		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+	else
+		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);
+}
+#endif
+
+#ifdef CONFIG_MACH_AKITA
+void akita_bl_set_intensity(int intensity)
+{
+	if (intensity > 0x10)
+		intensity += 0x10;
+
+	/* Bits 0-4 are accessed via the SSP interface */
+	corgi_ssp_blduty_set(intensity & 0x1f);
+
+	/* Bit 5 is via IO-Expander */
+	if (intensity & 0x0020)
+		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+	else
+		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);
+
+	if (intensity)
+		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+	else
+		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);
+}
+#endif
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 366a9bd..0ef4282 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -1,7 +1,7 @@
 /*
  *  SSP control code for Sharp Corgi devices
  *
- *  Copyright (c) 2004 Richard Purdie
+ *  Copyright (c) 2004-2005 Richard Purdie
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -17,14 +17,16 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 
 #include <asm/arch/ssp.h>
-#include <asm/arch/corgi.h>
 #include <asm/arch/pxa-regs.h>
+#include "sharpsl.h"
 
 static DEFINE_SPINLOCK(corgi_ssp_lock);
 static struct ssp_dev corgi_ssp_dev;
 static struct ssp_state corgi_ssp_state;
+static struct corgissp_machinfo *ssp_machinfo;
 
 /*
  * There are three devices connected to the SSP interface:
@@ -48,12 +50,12 @@
 	unsigned long ret,flag;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 
 	ssp_write_word(&corgi_ssp_dev,data);
 	ret = ssp_read_word(&corgi_ssp_dev);
 
-	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	return ret;
@@ -66,12 +68,12 @@
 void corgi_ssp_ads7846_lock(void)
 {
 	spin_lock(&corgi_ssp_lock);
-	GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 }
 
 void corgi_ssp_ads7846_unlock(void)
 {
-	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
+	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock(&corgi_ssp_lock);
 }
 
@@ -97,23 +99,27 @@
  */
 unsigned long corgi_ssp_dac_put(ulong data)
 {
-	unsigned long flag;
+	unsigned long flag, sscr1 = SSCR1_SPH;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
+	if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi())
+		sscr1 = 0;
 
 	ssp_disable(&corgi_ssp_dev);
-	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
+	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
 	ssp_enable(&corgi_ssp_dev);
 
+	GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 	ssp_write_word(&corgi_ssp_dev,data);
 	/* Read null data back from device to prevent SSP overflow */
 	ssp_read_word(&corgi_ssp_dev);
+	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 
 	ssp_disable(&corgi_ssp_dev);
-	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
 	ssp_enable(&corgi_ssp_dev);
-	GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
+
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	return 0;
@@ -141,9 +147,9 @@
 	int voltage,voltage1,voltage2;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+	GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	ssp_disable(&corgi_ssp_dev);
-	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
+	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
 	ssp_enable(&corgi_ssp_dev);
 
 	udelay(1);
@@ -161,9 +167,9 @@
 	voltage2=ssp_read_word(&corgi_ssp_dev);
 
 	ssp_disable(&corgi_ssp_dev);
-	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
 	ssp_enable(&corgi_ssp_dev);
-	GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
+	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	if (voltage1 & 0xc0 || voltage2 & 0x3f)
@@ -179,25 +185,31 @@
 /*
  *  Support Routines
  */
-int __init corgi_ssp_probe(struct device *dev)
+
+void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo)
+{
+	ssp_machinfo = machinfo;
+}
+
+static int __init corgi_ssp_probe(struct device *dev)
 {
 	int ret;
 
 	/* Chip Select - Disable All */
-	GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
-	GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);  /* High - Disable LCD Control/Timing Gen */
-	GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
-	GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);  /* High - Disable MAX1111*/
-	GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS);  /* output */
-	GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);   /* High - Disable ADS7846*/
+	GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */
+	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
+	GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */
+	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);  /* High - Disable MAX1111*/
+	GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846);  /* output */
+	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);   /* High - Disable ADS7846*/
 
-	ret=ssp_init(&corgi_ssp_dev,1);
+	ret = ssp_init(&corgi_ssp_dev,ssp_machinfo->port);
 
 	if (ret)
 		printk(KERN_ERR "Unable to register SSP handler!\n");
 	else {
 		ssp_disable(&corgi_ssp_dev);
-		ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
+		ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
 		ssp_enable(&corgi_ssp_dev);
 	}
 
@@ -222,9 +234,9 @@
 static int corgi_ssp_resume(struct device *dev, u32 level)
 {
 	if (level == RESUME_POWER_ON) {
-		GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);  /* High - Disable LCD Control/Timing Gen */
-		GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
-		GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
+		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
+		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
 		ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
 		ssp_enable(&corgi_ssp_dev);
 	}
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
new file mode 100644
index 0000000..3977a77
--- /dev/null
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -0,0 +1,34 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+struct corgissp_machinfo {
+	int port;
+	int cs_lcdcon;
+	int cs_ads7846;
+	int cs_max1111;
+	int clk_lcdcon;
+	int clk_ads7846;
+	int clk_max1111;
+};
+
+void corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo);
+
+/*
+ * SharpSL Backlight
+ */
+
+void corgi_bl_set_intensity(int intensity);
+void spitz_bl_set_intensity(int intensity);
+void akita_bl_set_intensity(int intensity);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+unsigned long corgi_get_hsync_len(void);
+unsigned long spitz_get_hsync_len(void);
+void corgi_put_hsync(void);
+void spitz_put_hsync(void);
+void corgi_wait_hsync(void);
+void spitz_wait_hsync(void);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
new file mode 100644
index 0000000..568afe3
--- /dev/null
+++ b/arch/arm/mach-pxa/spitz.c
@@ -0,0 +1,380 @@
+/*
+ * Support for Sharp SL-Cxx00 Series of PDAs
+ * Models: SL-C3000 (Spitz), SL-C1000 (Akita) and SL-C3100 (Borzoi)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches/lubbock.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/mmc/host.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/akita.h>
+#include <asm/arch/spitz.h>
+#include <asm/arch/sharpsl.h>
+
+#include <asm/mach/sharpsl_param.h>
+#include <asm/hardware/scoop.h>
+
+#include "generic.h"
+#include "sharpsl.h"
+
+/*
+ * Spitz SCOOP Device #1
+ */
+static struct resource spitz_scoop_resources[] = {
+	[0] = {
+		.start		= 0x10800000,
+		.end		= 0x10800fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct scoop_config spitz_scoop_setup = {
+	.io_dir 	= SPITZ_SCP_IO_DIR,
+	.io_out		= SPITZ_SCP_IO_OUT,
+	.suspend_clr = SPITZ_SCP_SUS_CLR,
+	.suspend_set = SPITZ_SCP_SUS_SET,
+};
+
+struct platform_device spitzscoop_device = {
+	.name		= "sharp-scoop",
+	.id		= 0,
+	.dev		= {
+ 		.platform_data	= &spitz_scoop_setup,
+	},
+	.num_resources	= ARRAY_SIZE(spitz_scoop_resources),
+	.resource	= spitz_scoop_resources,
+};
+
+/*
+ * Spitz SCOOP Device #2
+ */
+static struct resource spitz_scoop2_resources[] = {
+	[0] = {
+		.start		= 0x08800040,
+		.end		= 0x08800fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct scoop_config spitz_scoop2_setup = {
+	.io_dir 	= SPITZ_SCP2_IO_DIR,
+	.io_out		= SPITZ_SCP2_IO_OUT,
+	.suspend_clr = SPITZ_SCP2_SUS_CLR,
+	.suspend_set = SPITZ_SCP2_SUS_SET,
+};
+
+struct platform_device spitzscoop2_device = {
+	.name		= "sharp-scoop",
+	.id		= 1,
+	.dev		= {
+ 		.platform_data	= &spitz_scoop2_setup,
+	},
+	.num_resources	= ARRAY_SIZE(spitz_scoop2_resources),
+	.resource	= spitz_scoop2_resources,
+};
+
+static struct scoop_pcmcia_dev spitz_pcmcia_scoop[] = {
+{
+	.dev        = &spitzscoop_device.dev,
+	.irq        = SPITZ_IRQ_GPIO_CF_IRQ,
+	.cd_irq     = SPITZ_IRQ_GPIO_CF_CD,
+	.cd_irq_str = "PCMCIA0 CD",
+},{
+	.dev        = &spitzscoop2_device.dev,
+	.irq        = SPITZ_IRQ_GPIO_CF2_IRQ,
+	.cd_irq     = -1,
+},
+};
+
+
+/*
+ * Spitz SSP Device
+ *
+ * Set the parent as the scoop device because a lot of SSP devices
+ * also use scoop functions and this makes the power up/down order
+ * work correctly.
+ */
+struct platform_device spitzssp_device = {
+	.name		= "corgi-ssp",
+	.dev		= {
+ 		.parent = &spitzscoop_device.dev,
+	},
+	.id		= -1,
+};
+
+struct corgissp_machinfo spitz_ssp_machinfo = {
+	.port		= 2,
+	.cs_lcdcon	= SPITZ_GPIO_LCDCON_CS,
+	.cs_ads7846	= SPITZ_GPIO_ADS7846_CS,
+	.cs_max1111	= SPITZ_GPIO_MAX1111_CS,
+	.clk_lcdcon	= 520,
+	.clk_ads7846	= 14,
+	.clk_max1111	= 56,
+};
+
+
+/*
+ * Spitz Backlight Device
+ */
+static struct corgibl_machinfo spitz_bl_machinfo = {
+	.max_intensity = 0x2f,
+};
+
+static struct platform_device spitzbl_device = {
+	.name		= "corgi-bl",
+	.dev		= {
+ 		.platform_data	= &spitz_bl_machinfo,
+	},
+	.id		= -1,
+};
+
+
+/*
+ * Spitz Keyboard Device
+ */
+static struct platform_device spitzkbd_device = {
+	.name		= "spitz-keyboard",
+	.id		= -1,
+};
+
+
+/*
+ * Spitz Touch Screen Device
+ */
+static struct resource spitzts_resources[] = {
+	[0] = {
+		.start		= SPITZ_IRQ_GPIO_TP_INT,
+		.end		= SPITZ_IRQ_GPIO_TP_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct corgits_machinfo  spitz_ts_machinfo = {
+	.get_hsync_len   = spitz_get_hsync_len,
+	.put_hsync       = spitz_put_hsync,
+	.wait_hsync      = spitz_wait_hsync,
+};
+
+static struct platform_device spitzts_device = {
+	.name		= "corgi-ts",
+	.dev		= {
+ 		.parent = &spitzssp_device.dev,
+		.platform_data	= &spitz_ts_machinfo,
+	},
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(spitzts_resources),
+	.resource	= spitzts_resources,
+};
+
+
+/*
+ * MMC/SD Device
+ *
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert/eject.
+ */
+
+static struct pxamci_platform_data spitz_mci_platform_data;
+
+static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+	int err;
+
+	/* setup GPIO for PXA27x MMC controller	*/
+	pxa_gpio_mode(GPIO32_MMCCLK_MD);
+	pxa_gpio_mode(GPIO112_MMCCMD_MD);
+	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
+	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
+	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
+	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+	pxa_gpio_mode(SPITZ_GPIO_nSD_DETECT | GPIO_IN);
+	pxa_gpio_mode(SPITZ_GPIO_nSD_WP | GPIO_IN);
+
+	spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+	err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, SA_INTERRUPT,
+			     "MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "spitz_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+		return -1;
+	}
+
+	set_irq_type(SPITZ_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+	return 0;
+}
+
+/* Power control is shared with one of the CF slots so we have a mess */
+static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data* p_d = dev->platform_data;
+
+	unsigned short cpr = read_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR);
+
+	if (( 1 << vdd) & p_d->ocr_mask) {
+		/* printk(KERN_DEBUG "%s: on\n", __FUNCTION__); */
+		set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+		mdelay(2);
+		write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | 0x04);
+	} else {
+		/* printk(KERN_DEBUG "%s: off\n", __FUNCTION__); */
+		write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr & ~0x04);
+
+		if (!(cpr | 0x02)) {
+			mdelay(1);
+			reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+		}
+	}
+}
+
+static int spitz_mci_get_ro(struct device *dev)
+{
+	return GPLR(SPITZ_GPIO_nSD_WP) & GPIO_bit(SPITZ_GPIO_nSD_WP);
+}
+
+static void spitz_mci_exit(struct device *dev, void *data)
+{
+	free_irq(SPITZ_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data spitz_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init 		= spitz_mci_init,
+	.get_ro		= spitz_mci_get_ro,
+	.setpower 	= spitz_mci_setpower,
+	.exit		= spitz_mci_exit,
+};
+
+
+/*
+ * Spitz PXA Framebuffer
+ */
+static struct pxafb_mach_info spitz_pxafb_info __initdata = {
+        .pixclock       = 19231,
+        .xres           = 480,
+        .yres           = 640,
+        .bpp            = 16,
+        .hsync_len      = 40,
+        .left_margin    = 46,
+        .right_margin   = 125,
+        .vsync_len      = 3,
+        .upper_margin   = 1,
+        .lower_margin   = 0,
+        .sync           = 0,
+        .lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act | LCCR0_LDDALT | LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM,
+        .lccr3          = LCCR3_PixRsEdg | LCCR3_OutEnH,
+        .pxafb_lcd_power = spitz_lcd_power,
+};
+
+
+static struct platform_device *devices[] __initdata = {
+	&spitzscoop_device,
+	&spitzssp_device,
+	&spitzkbd_device,
+	&spitzts_device,
+	&spitzbl_device,
+	&spitzbattery_device,
+};
+
+static void __init common_init(void)
+{
+	PMCR = 0x00;
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x0158C000;
+	PGSR1 = 0x00FF0080;
+	PGSR2 = 0x0001C004;
+
+	/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
+	PCFR |= PCFR_OPDE;
+
+	corgi_ssp_set_machinfo(&spitz_ssp_machinfo);
+
+	pxa_gpio_mode(SPITZ_GPIO_HSYNC | GPIO_IN);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	pxa_set_mci_info(&spitz_mci_platform_data);
+	pxafb_device.dev.parent = &spitzssp_device.dev;
+	set_pxa_fb_info(&spitz_pxafb_info);
+}
+
+static void __init spitz_init(void)
+{
+	scoop_num = 2;
+	scoop_devs = &spitz_pcmcia_scoop[0];
+	spitz_bl_machinfo.set_bl_intensity = spitz_bl_set_intensity;
+
+	common_init();
+
+	platform_device_register(&spitzscoop2_device);
+}
+
+static void __init fixup_spitz(struct machine_desc *desc,
+		struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	sharpsl_save_param();
+	mi->nr_banks = 1;
+	mi->bank[0].start = 0xa0000000;
+	mi->bank[0].node = 0;
+	mi->bank[0].size = (64*1024*1024);
+}
+
+#ifdef CONFIG_MACH_SPITZ
+MACHINE_START(SPITZ, "SHARP Spitz")
+	.phys_ram	= 0xa0000000,
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup		= fixup_spitz,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa_init_irq,
+	.init_machine	= spitz_init,
+	.timer		= &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_BORZOI
+MACHINE_START(BORZOI, "SHARP Borzoi")
+	.phys_ram	= 0xa0000000,
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup		= fixup_spitz,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa_init_irq,
+	.init_machine	= spitz_init,
+	.timer		= &pxa_timer,
+MACHINE_END
+#endif
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index f1b9d2a..1ae2aee 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
+#include <asm/apic.h>
 
 static int __init check_bridge(int vendor, int device)
 {
@@ -15,6 +16,15 @@
 	if (vendor == PCI_VENDOR_ID_NVIDIA) {
 		acpi_skip_timer_override = 1;
 	}
+#ifdef CONFIG_X86_LOCAL_APIC
+	/*
+	 * ATI IXP chipsets get double timer interrupts.
+	 * For now just do this for all ATI chipsets.
+ 	 * FIXME: this needs to be checked for the non ACPI case too.
+	 */
+	if (vendor == PCI_VENDOR_ID_ATI)
+		disable_timer_pin_1 = 1;
+#endif
 	return 0;
 }
 
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 3aad038..9e24f7b2 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -319,7 +319,7 @@
 					# vm86-space
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp restore_all
+	jmp resume_userspace
 
 	ALIGN
 work_notifysig_v86:
@@ -329,7 +329,7 @@
 	movl %eax, %esp
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp restore_all
+	jmp resume_userspace
 
 	# perform syscall exit tracing
 	ALIGN
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 35d3ce2..378313b 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -60,6 +60,8 @@
  */
 int nr_ioapic_registers[MAX_IO_APICS];
 
+int disable_timer_pin_1 __initdata;
+
 /*
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
@@ -2211,6 +2213,8 @@
 				setup_nmi();
 				enable_8259A_irq(0);
 			}
+			if (disable_timer_pin_1 > 0)
+				clear_IO_APIC_pin(0, pin1);
 			return;
 		}
 		clear_IO_APIC_pin(0, pin1);
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 1cbb9c0..350ea66 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -11,6 +11,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/efi.h>
 #include <linux/dmi.h>
+#include <linux/ctype.h>
 #include <asm/uaccess.h>
 #include <asm/apic.h>
 #include <asm/desc.h>
@@ -28,8 +29,6 @@
 
 #ifdef CONFIG_SMP
 static int reboot_cpu = -1;
-/* shamelessly grabbed from lib/vsprintf.c for readability */
-#define is_digit(c)	((c) >= '0' && (c) <= '9')
 #endif
 static int __init reboot_setup(char *str)
 {
@@ -49,9 +48,9 @@
 			break;
 #ifdef CONFIG_SMP
 		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
-			if (is_digit(*(str+1))) {
+			if (isdigit(*(str+1))) {
 				reboot_cpu = (int) (*(str+1) - '0');
-				if (is_digit(*(str+2))) 
+				if (isdigit(*(str+2)))
 					reboot_cpu = reboot_cpu*10 + (int)(*(str+2) - '0');
 			}
 				/* we will leave sorting out the final value 
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f3d8084..dc39ca6 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -851,6 +851,11 @@
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
+		if (!memcmp(from, "disable_timer_pin_1", 19))
+			disable_timer_pin_1 = 1;
+		if (!memcmp(from, "enable_timer_pin_1", 18))
+			disable_timer_pin_1 = -1;
+
 		/* disable IO-APIC */
 		else if (!memcmp(from, "noapic", 6))
 			disable_ioapic_setup();
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index c70cd2a..5f0a95d 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -202,7 +202,7 @@
 				goto valid_k7;
 
 		/* If we get here, it's not a certified SMP capable AMD system. */
-		tainted |= TAINT_UNSAFE_SMP;
+		add_taint(TAINT_UNSAFE_SMP);
 	}
 
 valid_k7:
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 7b3b27d..516bf56 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -213,12 +213,18 @@
 		node_end_pfn[nid] = memory_chunk->end_pfn;
 }
 
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+	return pxm_to_nid_map[pxm];
+}
+
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
 	u8 *start, *end, *p;
 	int i, j, nid;
-	u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
 	u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
 	start = (u8 *)(&(sratp->reserved) + 1);	/* skip header */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 09a58cb..431a551 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -807,8 +807,9 @@
 	cwd = get_fpu_cwd(task);
 	swd = get_fpu_swd(task);
 	switch (swd & ~cwd & 0x3f) {
-		case 0x000:
-		default:
+		case 0x000: /* No unmasked exception */
+			return;
+		default:    /* Multiple exceptions */
 			break;
 		case 0x001: /* Invalid Op */
 			/*
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
index 42913f4..2941674 100644
--- a/arch/i386/pci/acpi.c
+++ b/arch/i386/pci/acpi.c
@@ -3,16 +3,31 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
+#include <asm/numa.h>
 #include "pci.h"
 
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 {
+	struct pci_bus *bus;
+
 	if (domain != 0) {
 		printk(KERN_WARNING "PCI: Multiple domains not supported\n");
 		return NULL;
 	}
 
-	return pcibios_scan_root(busnum);
+	bus = pcibios_scan_root(busnum);
+#ifdef CONFIG_ACPI_NUMA
+	if (bus != NULL) {
+		int pxm = acpi_get_pxm(device->handle);
+		if (pxm >= 0) {
+			bus->sysdata = (void *)(unsigned long)pxm_to_node(pxm);
+			printk("bus %d -> pxm %d -> node %ld\n",
+				busnum, pxm, (long)(bus->sysdata));
+		}
+	}
+#endif
+	
+	return bus;
 }
 
 extern int pci_routeirq;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 60f0e7a..dfbf80c 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -127,13 +127,6 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		goto out;
 
-	/* Kludge for now. Don't use mmconfig on AMD systems because
-	   those have some busses where mmconfig doesn't work,
-	   and we don't parse ACPI MCFG well enough to handle that. 
-	   Remove when proper handling is added. */
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-		goto out; 
-
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	raw_pci_ops = &pci_mmcfg;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index e29a8a5..3fa67ec 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2327,7 +2327,7 @@
 	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
 	set_fs(old_fs);
 
-	if (!ret && offset && put_user(of, offset))
+	if (offset && put_user(of, offset))
 		return -EFAULT;
 
 	return ret;
diff --git a/arch/m68knommu/platform/68328/head-de2.S b/arch/m68knommu/platform/68328/head-de2.S
new file mode 100644
index 0000000..94c5a16
--- /dev/null
+++ b/arch/m68knommu/platform/68328/head-de2.S
@@ -0,0 +1,135 @@
+#include <linux/config.h>
+
+#if defined(CONFIG_RAM32MB)
+#define	MEM_END	0x02000000	/* Memory size 32Mb */
+#elif defined(CONFIG_RAM16MB)
+#define	MEM_END	0x01000000	/* Memory size 16Mb */
+#else
+#define	MEM_END	0x00800000	/* Memory size 8Mb */
+#endif
+
+#undef CRT_DEBUG
+
+.macro	PUTC CHAR
+#ifdef CRT_DEBUG
+	moveq	#\CHAR, %d7
+	jsr	putc
+#endif
+.endm
+
+	.global	_start
+	.global _rambase
+	.global _ramvec
+	.global	_ramstart
+	.global	_ramend
+	
+	.data
+
+/*
+ *	Set up the usable of RAM stuff
+ */
+_rambase:
+	.long	0
+_ramvec:
+	.long	0
+_ramstart:
+	.long	0
+_ramend:
+	.long	0
+
+	.text
+
+_start:
+
+/*
+ * Setup initial stack
+ */
+	/* disable all interrupts */
+	movew	#0x2700, %sr
+	movel	#-1, 0xfffff304
+	movel	#MEM_END-4, %sp
+
+	PUTC	'\r'
+	PUTC	'\n'
+	PUTC	'A'
+	PUTC	'B'
+
+/*
+ *	Determine end of RAM
+ */
+
+	movel	#MEM_END, %a0
+	movel	%a0, _ramend
+
+	PUTC	'C'
+
+/*
+ *	Move ROM filesystem above bss :-)
+ */
+
+	moveal	#_sbss, %a0			/* romfs at the start of bss */
+	moveal	#_ebss, %a1			/* Set up destination  */
+	movel	%a0, %a2			/* Copy of bss start */
+
+	movel	8(%a0), %d1			/* Get size of ROMFS */
+	addql	#8, %d1				/* Allow for rounding */
+	andl	#0xfffffffc, %d1	/* Whole words */
+
+	addl	%d1, %a0			/* Copy from end */
+	addl	%d1, %a1			/* Copy from end */
+	movel	%a1, _ramstart		/* Set start of ram */
+
+1:
+	movel	-(%a0), %d0			/* Copy dword */
+	movel	%d0, -(%a1)
+	cmpl	%a0, %a2			/* Check if at end */
+	bne	1b
+
+	PUTC	'D'
+
+/*
+ * Initialize BSS segment to 0
+ */
+
+	lea	_sbss, %a0
+	lea	_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+2:	cmpal	%a0, %a1
+	beq	1f
+	clrl	(%a0)+
+	bra	2b
+1:
+
+	PUTC	'E'
+
+/*
+ * Load the current task pointer and stack
+ */
+
+	lea	init_thread_union, %a0
+	lea	0x2000(%a0), %sp
+
+	PUTC	'F'
+	PUTC	'\r'
+	PUTC	'\n'
+
+/*
+ * Go
+ */
+
+	jmp	start_kernel
+
+/*
+ * Local functions
+ */
+ 
+#ifdef CRT_DEBUG
+putc:
+	moveb	%d7, 0xfffff907
+1:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	1b
+	rts
+#endif
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
new file mode 100644
index 0000000..a5c639a
--- /dev/null
+++ b/arch/m68knommu/platform/68360/head-ram.S
@@ -0,0 +1,408 @@
+/* arch/m68knommu/platform/68360/head-ram.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#define ASSEMBLY
+#include <linux/config.h>
+
+.global _stext
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000002
+#define SIM_BR0_MASK                0x00000001
+
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+	
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+	.text
+_start:
+_stext:
+	nop
+	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
+	/* We should not need to setup the boot stack the reset should do it. */
+	movea.l	#__ramend, %sp			/*set up stack at the end of DRAM:*/
+
+set_mbar_register:
+	moveq.l	#0x07, %d1			/* Setup MBAR */
+	movec	%d1, %dfc
+
+	lea.l	MCU_SIM_MBAR_ADRS, %a0
+	move.l	#_dprbase, %d0
+	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
+	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
+	moves.l	%d0, %a0@
+
+	moveq.l	#0x05, %d1
+	movec.l	%d1, %dfc
+
+	/* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+	/* Set Module Configuration Register */
+	move.l	#MCU_SIM_MCR, MCR
+
+	/* to do:	Determine cause of reset */
+
+	/*
+	 *       configure system clock MC68360 p. 6-40
+	 *       (value +1)*osc/128 = system clock
+	 */
+set_sim_clock:
+	move.w	#MCU_SIM_PLLCR, PLLCR
+	move.b	#MCU_SIM_CLKOCR, CLKOCR
+	move.w	#MCU_SIM_CDVCR, CDVCR
+
+	/* Wait for the PLL to settle */
+	move.w	#16384, %d0
+pll_settle_wait:
+	subi.w	#1, %d0
+	bne	pll_settle_wait
+
+	/* Setup the system protection register, and watchdog timer register */
+	move.b	#MCU_SIM_SWIV, SWIV
+	move.w	#MCU_SIM_PICR, PICR
+	move.w	#MCU_SIM_PITR, PITR
+	move.w	#MCU_SIM_SYPCR, SYPCR
+
+	/* Clear DPRAM - system + parameter */
+	movea.l	#_dprbase, %a0
+	movea.l	#_dprbase+0x2000, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	clear_dpram
+
+configure_memory_controller:    
+	/* Set up Global Memory Register (GMR) */
+	move.l	#MCU_SIM_GMR, %d0
+	move.l	%d0, GMR
+
+configure_chip_select_0:
+	move.l	#__ramend, %d0
+	subi.l	#__ramstart, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR0_MASK, %d0
+	move.l	%d0, OR0
+
+	move.l	#__ramstart, %d0
+	ori.l	#SIM_BR0_MASK, %d0
+	move.l	%d0, BR0
+
+configure_chip_select_1:
+	move.l	#__rom_end, %d0
+	subi.l	#__rom_start, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR1_MASK, %d0
+	move.l	%d0, OR1
+
+	move.l	#__rom_start, %d0
+	ori.l	#SIM_BR1_MASK, %d0
+	move.l	%d0, BR1
+
+	move.w	#MCU_SIM_PEPAR, PEPAR 
+
+	/* point to vector table: */
+	move.l	#_romvec, %a0
+	move.l	#_ramvec, %a1
+copy_vectors:
+	move.l	%a0@, %d0
+	move.l	%d0, %a1@
+	move.l	%a0@, %a1@
+	addq.l	#0x04, %a0
+	addq.l	#0x04, %a1
+	cmp.l	#_start, %a0
+	blt	copy_vectors
+
+	move.l	#_ramvec, %a1
+	movec	%a1, %vbr
+
+
+	/* Copy data segment from ROM to RAM */
+	moveal	#_stext, %a0
+	moveal	#_sdata, %a1
+	moveal	#_edata, %a2
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+	move.l	%a0@, %d0
+	addq.l	#0x04, %a0
+	move.l	%d0, %a1@
+	addq.l	#0x04, %a1
+	cmp.l	#_edata, %a1
+	blt     LD1
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+load_quicc:
+	move.l	#_dprbase, _quicc_base
+
+store_ram_size:
+	/* Set ram size information */
+	move.l	#_sdata, _rambase
+	move.l	#_ebss, _ramstart
+	move.l	#__ramend, %d0
+	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
+	move.l	%d0, _ramend			/* Different from __ramend.*/
+
+store_flash_size:
+	/* Set rom size information */
+	move.l	#__rom_end, %d0
+	sub.l	#__rom_start, %d0
+	move.l	%d0, rom_length
+    
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+	lea	init_thread_union, %a2
+	lea	0x2000(%a2), %sp
+
+lp:
+	jsr	start_kernel
+
+_exit:
+	jmp	_exit
+
+
+	.data
+	.align 4
+env:
+	.long	0
+_quicc_base:
+	.long	0
+_periph_base:
+	.long	0
+_ramvec:
+	.long   0
+_rambase:
+	.long   0
+_ramstart:
+	.long   0
+_ramend:
+	.long   0
+_dprbase:
+	.long	0xffffe000
+
+	.text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+ 
+.section ".data.initvect","awx"
+    .long   __ramend	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
new file mode 100644
index 0000000..0da357a
--- /dev/null
+++ b/arch/m68knommu/platform/68360/head-rom.S
@@ -0,0 +1,420 @@
+/* arch/m68knommu/platform/68360/head-rom.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#include <linux/config.h>
+
+.global _stext
+.global _sbss
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+
+#define OR2                         (_dprbase + REGB + 0x0074)
+#define BR2                         (_dprbase + REGB + 0x0070)
+
+#define OR3                         (_dprbase + REGB + 0x0084)
+#define BR3                         (_dprbase + REGB + 0x0080)
+
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+
+#define OR5                         (_dprbase + REGB + 0x00A4)
+#define BR5                         (_dprbase + REGB + 0x00A0)
+
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000000
+#define SIM_BR0_MASK                0x00000001
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+	
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+	.text
+_start:
+_stext:
+	nop
+	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
+	/* We should not need to setup the boot stack the reset should do it. */
+	movea.l	#__ramend, %sp		/* set up stack at the end of DRAM:*/
+
+
+set_mbar_register:
+	moveq.l	#0x07, %d1			/* Setup MBAR */
+	movec	%d1, %dfc
+
+	lea.l	MCU_SIM_MBAR_ADRS, %a0
+	move.l	#_dprbase, %d0
+	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
+	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
+	moves.l	%d0, %a0@
+
+	moveq.l	#0x05, %d1
+	movec.l	%d1, %dfc
+
+	/* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+	/* Set Module Configuration Register */
+	move.l	#MCU_SIM_MCR, MCR
+
+	/* to do:	Determine cause of reset */
+
+	/*
+	 *	configure system clock MC68360 p. 6-40
+	 *	(value +1)*osc/128 = system clock
+	 *                    or
+	 *	(value + 1)*osc = system clock
+	 *	You do not need to divide the oscillator by 128 unless you want to.
+	 */
+set_sim_clock:
+	move.w	#MCU_SIM_PLLCR, PLLCR
+	move.b	#MCU_SIM_CLKOCR, CLKOCR
+	move.w	#MCU_SIM_CDVCR, CDVCR
+
+	/* Wait for the PLL to settle */
+	move.w	#16384, %d0
+pll_settle_wait:
+	subi.w	#1, %d0
+	bne	pll_settle_wait
+
+	/* Setup the system protection register, and watchdog timer register */
+	move.b	#MCU_SIM_SWIV, SWIV
+	move.w	#MCU_SIM_PICR, PICR
+	move.w	#MCU_SIM_PITR, PITR
+	move.w	#MCU_SIM_SYPCR, SYPCR
+
+	/* Clear DPRAM - system + parameter */
+	movea.l	#_dprbase, %a0
+	movea.l	#_dprbase+0x2000, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	clear_dpram
+
+configure_memory_controller:    
+	/* Set up Global Memory Register (GMR) */
+	move.l	#MCU_SIM_GMR, %d0
+	move.l	%d0, GMR
+
+configure_chip_select_0:
+	move.l	#0x00400000, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR0_MASK, %d0
+	move.l	%d0, OR0
+
+	move.l	#__rom_start, %d0
+	ori.l	#SIM_BR0_MASK, %d0
+	move.l	%d0, BR0
+
+	move.l	#0x0, BR1
+	move.l	#0x0, BR2
+	move.l	#0x0, BR3
+	move.l	#0x0, BR4
+	move.l	#0x0, BR5
+	move.l	#0x0, BR6
+	move.l	#0x0, BR7
+
+	move.w	#MCU_SIM_PEPAR, PEPAR 
+
+	/* point to vector table: */
+	move.l	#_romvec, %a0
+	move.l	#_ramvec, %a1
+copy_vectors:
+	move.l	%a0@, %d0
+	move.l	%d0, %a1@
+	move.l	%a0@, %a1@
+	addq.l	#0x04, %a0
+	addq.l	#0x04, %a1
+	cmp.l	#_start, %a0
+	blt	copy_vectors
+
+	move.l	#_ramvec, %a1
+	movec	%a1, %vbr
+
+
+	/* Copy data segment from ROM to RAM */
+	moveal	#_etext, %a0
+	moveal	#_sdata, %a1
+	moveal	#_edata, %a2
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+	move.l	%a0@, %d0
+	addq.l	#0x04, %a0
+	move.l	%d0, %a1@
+	addq.l	#0x04, %a1
+	cmp.l	#_edata, %a1
+	blt	LD1
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+load_quicc:
+	move.l	#_dprbase, _quicc_base
+
+store_ram_size:
+	/* Set ram size information */
+	move.l	#_sdata, _rambase
+	move.l	#_ebss, _ramstart
+	move.l	#__ramend, %d0
+	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
+	move.l	%d0, _ramend			/* Different from __ramend.*/
+
+store_flash_size:
+	/* Set rom size information */
+	move.l	#__rom_end, %d0
+	sub.l	#__rom_start, %d0
+	move.l	%d0, rom_length
+    
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+	lea	init_thread_union, %a2
+	lea	0x2000(%a2), %sp
+
+lp:
+	jsr	start_kernel
+
+_exit:
+	jmp	_exit
+
+
+	.data
+	.align 4
+env:
+	.long	0
+_quicc_base:
+	.long	0
+_periph_base:
+	.long	0
+_ramvec:
+	.long   0
+_rambase:
+	.long   0
+_ramstart:
+	.long   0
+_ramend:
+	.long   0
+_dprbase:
+	.long	0xffffe000
+
+
+	.text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+ 
+.section ".data.initvect","awx"
+    .long   __ramend	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
index fe8bb63..26bd8ea 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/ppc/kernel/temp.c
@@ -21,7 +21,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/reg.h>
 #include <asm/nvram.h>
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index a3c5281..22d7fd1 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -58,7 +58,6 @@
 #include <linux/init.h>
 #include <linux/profile.h>
 
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/nvram.h>
 #include <asm/cache.h>
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 9353584..17d2db7 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -96,6 +96,9 @@
 	*(.init.text)
 	_einittext = .;
   }
+  /* .exit.text is discarded at runtime, not link time,
+     to deal with references from __bug_table */
+  .exit.text : { *(.exit.text) }
   .init.data : {
     *(.init.data);
     __vtop_table_begin = .;
@@ -190,5 +193,6 @@
   /* Sections to be discarded. */
   /DISCARD/ : {
     *(.exitcall.exit)
+    *(.exit.data)
   }
 }
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
index 4864a7d..6037ce7 100644
--- a/arch/ppc/platforms/chrp_time.c
+++ b/arch/ppc/platforms/chrp_time.c
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/bcd.h>
 
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/nvram.h>
 #include <asm/prom.h>
diff --git a/arch/ppc/syslib/prep_nvram.c b/arch/ppc/syslib/prep_nvram.c
index 2bcf8a1..8599850 100644
--- a/arch/ppc/syslib/prep_nvram.c
+++ b/arch/ppc/syslib/prep_nvram.c
@@ -15,7 +15,6 @@
 #include <linux/ioport.h>
 
 #include <asm/sections.h>
-#include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/prep_nvram.h>
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 17e35d0..1ff4fa0 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -68,6 +68,7 @@
 	DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
 #endif /* CONFIG_ALTIVEC */
 	DEFINE(MM, offsetof(struct task_struct, mm));
+	DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
 
 	DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
 	DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size));
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index d133a49..e8c0bbf 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -276,12 +276,22 @@
 _GLOBAL(ppc32_rt_sigsuspend)
 	bl	.save_nvgprs
 	bl	.sys32_rt_sigsuspend
-	/* If sigsuspend() returns zero, we are going into a signal handler */
 70:	cmpdi	0,r3,0
-	beq	.ret_from_except
-	/* If it returned -EINTR, we need to return via syscall_exit to set
+	/* If it returned an error, we need to return via syscall_exit to set
 	   the SO bit in cr0 and potentially stop for ptrace. */
-	b	syscall_exit
+	bne	syscall_exit
+	/* If sigsuspend() returns zero, we are going into a signal handler. We
+	   may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
+#ifdef CONFIG_AUDIT
+	ld	r3,PACACURRENT(r13)
+	ld	r4,AUDITCONTEXT(r3)
+	cmpdi	0,r4,0
+	beq	.ret_from_except	/* No audit_context: Leave immediately. */
+	li	r4, 2			/* AUDITSC_FAILURE */
+	li	r5,-4			/* It's always -EINTR */
+	bl	.audit_syscall_exit
+#endif
+	b	.ret_from_except
 
 _GLOBAL(ppc_fork)
 	bl	.save_nvgprs
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index 356e4fd..fbc273c 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -252,7 +252,7 @@
 			phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
 			if (phb == NULL)
 				return -ENOMEM;
-       			pci_setup_pci_controller(phb);
+			pci_setup_pci_controller(phb);
 
 			phb->pci_mem_offset = phb->local_number = bus;
 			phb->first_busno = bus;
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
index 5a8b4d8..1d297e0 100644
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -283,7 +283,7 @@
 	 * the reg address cell, we shall fix that by killing struct
 	 * reg_property and using some accessor functions instead
 	 */
-       	hose->first_busno = 0xf0;
+	hose->first_busno = 0xf0;
 	hose->last_busno = 0xff;
 	hose->ops = &u3_agp_pci_ops;
 	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
@@ -315,24 +315,24 @@
 	char* disp_name;
 	int *bus_range;
 	int primary = 1;
- 	struct property *of_prop;
+	struct property *of_prop;
 
 	DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-       	bus_range = (int *) get_property(dev, "bus-range", &len);
-       	if (bus_range == NULL || len < 2 * sizeof(int)) {
-       		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-       			       dev->full_name);
-       	}
+	bus_range = (int *) get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+		dev->full_name);
+	}
 
 	hose = alloc_bootmem(sizeof(struct pci_controller));
 	if (hose == NULL)
 		return -ENOMEM;
-       	pci_setup_pci_controller(hose);
+	pci_setup_pci_controller(hose);
 
-       	hose->arch_data = dev;
-       	hose->first_busno = bus_range ? bus_range[0] : 0;
-       	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+	hose->arch_data = dev;
+	hose->first_busno = bus_range ? bus_range[0] : 0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	of_prop = alloc_bootmem(sizeof(struct property) +
 				sizeof(hose->global_number));
@@ -346,25 +346,25 @@
 	}
 
 	disp_name = NULL;
-       	if (device_is_compatible(dev, "u3-agp")) {
-       		setup_u3_agp(hose);
-       		disp_name = "U3-AGP";
-       		primary = 0;
-       	} else if (device_is_compatible(dev, "u3-ht")) {
-       		setup_u3_ht(hose);
-       		disp_name = "U3-HT";
-       		primary = 1;
-       	}
-       	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-       		disp_name, hose->first_busno, hose->last_busno);
+	if (device_is_compatible(dev, "u3-agp")) {
+		setup_u3_agp(hose);
+		disp_name = "U3-AGP";
+		primary = 0;
+	} else if (device_is_compatible(dev, "u3-ht")) {
+		setup_u3_ht(hose);
+		disp_name = "U3-HT";
+		primary = 1;
+	}
+	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+		disp_name, hose->first_busno, hose->last_busno);
 
-       	/* Interpret the "ranges" property */
-       	/* This also maps the I/O region and sets isa_io/mem_base */
-       	pci_process_bridge_OF_ranges(hose, dev);
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(hose, dev);
 	pci_setup_phb_io(hose, primary);
 
-       	/* Fixup "bus-range" OF property */
-       	fixup_bus_range(dev);
+	/* Fixup "bus-range" OF property */
+	fixup_bus_range(dev);
 
 	return 0;
 }
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 9490b6c..3009701 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -238,8 +238,8 @@
 
 	/* Find and initialize PCI host bridges */
 	init_pci_config_tokens();
-	eeh_init();
 	find_and_init_phbs();
+	eeh_init();
 
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
@@ -590,6 +590,13 @@
 	return 0;
 }
 
+static int pSeries_pci_probe_mode(struct pci_bus *bus)
+{
+	if (systemcfg->platform & PLATFORM_LPAR)
+		return PCI_PROBE_DEVTREE;
+	return PCI_PROBE_NORMAL;
+}
+
 struct machdep_calls __initdata pSeries_md = {
 	.probe			= pSeries_probe,
 	.setup_arch		= pSeries_setup_arch,
@@ -597,6 +604,7 @@
 	.get_cpuinfo		= pSeries_get_cpuinfo,
 	.log_error		= pSeries_log_error,
 	.pcibios_fixup		= pSeries_final_fixup,
+	.pci_probe_mode		= pSeries_pci_probe_mode,
 	.irq_bus_setup		= pSeries_irq_bus_setup,
 	.restart		= rtas_restart,
 	.power_off		= rtas_power_off,
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 79c7f32..d2c7e2c 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -272,6 +272,7 @@
 	unsigned long start_here = __pa((u32)*((unsigned long *)
 					       pSeries_secondary_smp_init));
 	unsigned int pcpu;
+	int start_cpu;
 
 	if (cpu_isset(lcpu, of_spin_map))
 		/* Already started by OF and sitting in spin loop */
@@ -282,12 +283,20 @@
 	/* Fixup atomic count: it exited inside IRQ handler. */
 	paca[lcpu].__current->thread_info->preempt_count	= 0;
 
-	status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
-			   pcpu, start_here, lcpu);
+	/* 
+	 * If the RTAS start-cpu token does not exist then presume the
+	 * cpu is already spinning.
+	 */
+	start_cpu = rtas_token("start-cpu");
+	if (start_cpu == RTAS_UNKNOWN_SERVICE)
+		return 1;
+
+	status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
 	if (status != 0) {
 		printk(KERN_ERR "start-cpu failed: %i\n", status);
 		return 0;
 	}
+
 	return 1;
 }
 
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index 8447dcc..861138a 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -51,6 +51,10 @@
 
 EXPORT_SYMBOL(io_page_mask);
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static void fixup_resource(struct resource *res, struct pci_dev *dev);
+static void do_bus_setup(struct pci_bus *bus);
+#endif
 
 unsigned int pcibios_assign_all_busses(void)
 {
@@ -225,10 +229,287 @@
 }
 #endif
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
+{
+	u32 *prop;
+	int len;
+
+	prop = (u32 *) get_property(np, name, &len);
+	if (prop && len >= 4)
+		return *prop;
+	return def;
+}
+
+static unsigned int pci_parse_of_flags(u32 addr0)
+{
+	unsigned int flags = 0;
+
+	if (addr0 & 0x02000000) {
+		flags |= IORESOURCE_MEM;
+		if (addr0 & 0x40000000)
+			flags |= IORESOURCE_PREFETCH;
+	} else if (addr0 & 0x01000000)
+		flags |= IORESOURCE_IO;
+	return flags;
+}
+
+#define GET_64BIT(prop, i)	((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
+
+static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
+{
+	u64 base, size;
+	unsigned int flags;
+	struct resource *res;
+	u32 *addrs, i;
+	int proplen;
+
+	addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
+	if (!addrs)
+		return;
+	for (; proplen >= 20; proplen -= 20, addrs += 5) {
+		flags = pci_parse_of_flags(addrs[0]);
+		if (!flags)
+			continue;
+		base = GET_64BIT(addrs, 1);
+		size = GET_64BIT(addrs, 3);
+		if (!size)
+			continue;
+		i = addrs[0] & 0xff;
+		if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
+			res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
+		} else if (i == dev->rom_base_reg) {
+			res = &dev->resource[PCI_ROM_RESOURCE];
+			flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+		} else {
+			printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
+			continue;
+		}
+		res->start = base;
+		res->end = base + size - 1;
+		res->flags = flags;
+		res->name = pci_name(dev);
+		fixup_resource(res, dev);
+	}
+}
+
+static struct pci_dev *of_create_pci_dev(struct device_node *node,
+					 struct pci_bus *bus, int devfn)
+{
+	struct pci_dev *dev;
+	const char *type;
+
+	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	type = get_property(node, "device_type", NULL);
+	if (type == NULL)
+		type = "";
+
+	memset(dev, 0, sizeof(struct pci_dev));
+	dev->bus = bus;
+	dev->sysdata = node;
+	dev->dev.parent = bus->bridge;
+	dev->dev.bus = &pci_bus_type;
+	dev->devfn = devfn;
+	dev->multifunction = 0;		/* maybe a lie? */
+
+	dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
+	dev->device = get_int_prop(node, "device-id", 0xffff);
+	dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
+	dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
+
+	dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+
+	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+	dev->class = get_int_prop(node, "class-code", 0);
+
+	dev->current_state = 4;		/* unknown power state */
+
+	if (!strcmp(type, "pci")) {
+		/* a PCI-PCI bridge */
+		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+		dev->rom_base_reg = PCI_ROM_ADDRESS1;
+	} else if (!strcmp(type, "cardbus")) {
+		dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+	} else {
+		dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+		dev->rom_base_reg = PCI_ROM_ADDRESS;
+		dev->irq = NO_IRQ;
+		if (node->n_intrs > 0) {
+			dev->irq = node->intrs[0].line;
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      dev->irq);
+		}
+	}
+
+	pci_parse_of_addrs(node, dev);
+
+	pci_device_add(dev, bus);
+
+	/* XXX pci_scan_msi_device(dev); */
+
+	return dev;
+}
+
+static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev);
+
+static void __devinit of_scan_bus(struct device_node *node,
+				  struct pci_bus *bus)
+{
+	struct device_node *child = NULL;
+	u32 *reg;
+	int reglen, devfn;
+	struct pci_dev *dev;
+
+	while ((child = of_get_next_child(node, child)) != NULL) {
+		reg = (u32 *) get_property(child, "reg", &reglen);
+		if (reg == NULL || reglen < 20)
+			continue;
+		devfn = (reg[0] >> 8) & 0xff;
+		/* create a new pci_dev for this device */
+		dev = of_create_pci_dev(child, bus, devfn);
+		if (!dev)
+			continue;
+		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+			of_scan_pci_bridge(child, dev);
+	}
+
+	do_bus_setup(bus);
+}
+
+static void __devinit of_scan_pci_bridge(struct device_node *node,
+					 struct pci_dev *dev)
+{
+	struct pci_bus *bus;
+	u32 *busrange, *ranges;
+	int len, i, mode;
+	struct resource *res;
+	unsigned int flags;
+	u64 size;
+
+	/* parse bus-range property */
+	busrange = (u32 *) get_property(node, "bus-range", &len);
+	if (busrange == NULL || len != 8) {
+		printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+		       node->full_name);
+		return;
+	}
+	ranges = (u32 *) get_property(node, "ranges", &len);
+	if (ranges == NULL) {
+		printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+		       node->full_name);
+		return;
+	}
+
+	bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+	if (!bus) {
+		printk(KERN_ERR "Failed to create pci bus for %s\n",
+		       node->full_name);
+		return;
+	}
+
+	bus->primary = dev->bus->number;
+	bus->subordinate = busrange[1];
+	bus->bridge_ctl = 0;
+	bus->sysdata = node;
+
+	/* parse ranges property */
+	/* PCI #address-cells == 3 and #size-cells == 2 always */
+	res = &dev->resource[PCI_BRIDGE_RESOURCES];
+	for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) {
+		res->flags = 0;
+		bus->resource[i] = res;
+		++res;
+	}
+	i = 1;
+	for (; len >= 32; len -= 32, ranges += 8) {
+		flags = pci_parse_of_flags(ranges[0]);
+		size = GET_64BIT(ranges, 6);
+		if (flags == 0 || size == 0)
+			continue;
+		if (flags & IORESOURCE_IO) {
+			res = bus->resource[0];
+			if (res->flags) {
+				printk(KERN_ERR "PCI: ignoring extra I/O range"
+				       " for bridge %s\n", node->full_name);
+				continue;
+			}
+		} else {
+			if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
+				printk(KERN_ERR "PCI: too many memory ranges"
+				       " for bridge %s\n", node->full_name);
+				continue;
+			}
+			res = bus->resource[i];
+			++i;
+		}
+		res->start = GET_64BIT(ranges, 1);
+		res->end = res->start + size - 1;
+		res->flags = flags;
+		fixup_resource(res, dev);
+	}
+	sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
+		bus->number);
+
+	mode = PCI_PROBE_NORMAL;
+	if (ppc_md.pci_probe_mode)
+		mode = ppc_md.pci_probe_mode(bus);
+	if (mode == PCI_PROBE_DEVTREE)
+		of_scan_bus(node, bus);
+	else if (mode == PCI_PROBE_NORMAL)
+		pci_scan_child_bus(bus);
+}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+static void __devinit scan_phb(struct pci_controller *hose)
+{
+	struct pci_bus *bus;
+	struct device_node *node = hose->arch_data;
+	int i, mode;
+	struct resource *res;
+
+	bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
+	if (bus == NULL) {
+		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+		       hose->global_number);
+		return;
+	}
+	bus->secondary = hose->first_busno;
+	hose->bus = bus;
+
+	bus->resource[0] = res = &hose->io_resource;
+	if (res->flags && request_resource(&ioport_resource, res))
+		printk(KERN_ERR "Failed to request PCI IO region "
+		       "on PCI domain %04x\n", hose->global_number);
+
+	for (i = 0; i < 3; ++i) {
+		res = &hose->mem_resources[i];
+		bus->resource[i+1] = res;
+		if (res->flags && request_resource(&iomem_resource, res))
+			printk(KERN_ERR "Failed to request PCI memory region "
+			       "on PCI domain %04x\n", hose->global_number);
+	}
+
+	mode = PCI_PROBE_NORMAL;
+#ifdef CONFIG_PPC_MULTIPLATFORM
+	if (ppc_md.pci_probe_mode)
+		mode = ppc_md.pci_probe_mode(bus);
+	if (mode == PCI_PROBE_DEVTREE) {
+		bus->subordinate = hose->last_busno;
+		of_scan_bus(node, bus);
+	}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+	if (mode == PCI_PROBE_NORMAL)
+		hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+	pci_bus_add_devices(bus);
+}
+
 static int __init pcibios_init(void)
 {
 	struct pci_controller *hose, *tmp;
-	struct pci_bus *bus;
 
 	/* For now, override phys_mem_access_prot. If we need it,
 	 * later, we may move that initialization to each ppc_md
@@ -242,13 +523,8 @@
 	printk("PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		hose->last_busno = 0xff;
-		bus = pci_scan_bus(hose->first_busno, hose->ops,
-				   hose->arch_data);
-		hose->bus = bus;
-		hose->last_busno = bus->subordinate;
-	}
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+		scan_phb(hose);
 
 #ifndef CONFIG_PPC_ISERIES
 	if (pci_probe_only)
@@ -820,104 +1096,59 @@
 /*
  * ppc64 can have multifunction devices that do not respond to function 0.
  * In this case we must scan all functions.
+ * XXX this can go now, we use the OF device tree in all the
+ * cases that caused problems. -- paulus
  */
 int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
 {
-       struct device_node *busdn, *dn;
-
-       if (bus->self)
-               busdn = pci_device_to_OF_node(bus->self);
-       else
-               busdn = bus->sysdata;   /* must be a phb */
-
-       if (busdn == NULL)
-	       return 0;
-
-       /*
-        * Check to see if there is any of the 8 functions are in the
-        * device tree.  If they are then we need to scan all the
-        * functions of this slot.
-        */
-       for (dn = busdn->child; dn; dn = dn->sibling) {
-	       struct pci_dn *pdn = dn->data;
-	       if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
-                       return 1;
-       }
-
        return 0;
 }
 
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	unsigned long start, end, mask, offset;
+
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+		start = res->start += offset;
+		end = res->end += offset;
+
+		/* Need to allow IO access to pages that are in the
+		   ISA range */
+		if (start < MAX_ISA_PORT) {
+			if (end > MAX_ISA_PORT)
+				end = MAX_ISA_PORT;
+
+			start >>= PAGE_SHIFT;
+			end >>= PAGE_SHIFT;
+
+			/* get the range of pages for the map */
+			mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
+			io_page_mask |= mask;
+		}
+	} else if (res->flags & IORESOURCE_MEM) {
+		res->start += hose->pci_mem_offset;
+		res->end += hose->pci_mem_offset;
+	}
+}
 
 void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-					   struct pci_bus *bus)
+					      struct pci_bus *bus)
 {
 	/* Update device resources.  */
-	struct pci_controller *hose = pci_bus_to_host(bus);
 	int i;
 
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		if (dev->resource[i].flags & IORESOURCE_IO) {
-			unsigned long offset = (unsigned long)hose->io_base_virt
-				- pci_io_base;
-                        unsigned long start, end, mask;
-
-                        start = dev->resource[i].start += offset;
-                        end = dev->resource[i].end += offset;
-
-                        /* Need to allow IO access to pages that are in the
-                           ISA range */
-                        if (start < MAX_ISA_PORT) {
-                                if (end > MAX_ISA_PORT)
-                                        end = MAX_ISA_PORT;
-
-                                start >>= PAGE_SHIFT;
-                                end >>= PAGE_SHIFT;
-
-                                /* get the range of pages for the map */
-                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
-                                io_page_mask |= mask;
-                        }
-		}
-                else if (dev->resource[i].flags & IORESOURCE_MEM) {
-			dev->resource[i].start += hose->pci_mem_offset;
-			dev->resource[i].end += hose->pci_mem_offset;
-		}
-        }
+	for (i = 0; i < PCI_NUM_RESOURCES; i++)
+		if (dev->resource[i].flags)
+			fixup_resource(&dev->resource[i], dev);
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+static void __devinit do_bus_setup(struct pci_bus *bus)
 {
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct pci_dev *dev = bus->self;
-	struct resource *res;
-	int i;
-
-	if (!dev) {
-		/* Root bus. */
-
-		hose->bus = bus;
-		bus->resource[0] = res = &hose->io_resource;
-
-		if (res->flags && request_resource(&ioport_resource, res))
-			printk(KERN_ERR "Failed to request IO on "
-					"PCI domain %d\n", pci_domain_nr(bus));
-
-		for (i = 0; i < 3; ++i) {
-			res = &hose->mem_resources[i];
-			bus->resource[i+1] = res;
-			if (res->flags && request_resource(&iomem_resource, res))
-				printk(KERN_ERR "Failed to request MEM on "
-						"PCI domain %d\n",
-						pci_domain_nr(bus));
-		}
-	} else if (pci_probe_only &&
-		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		/* This is a subordinate bridge */
-
-		pci_read_bridge_bases(bus);
-		pcibios_fixup_device_resources(dev, bus);
-	}
+	struct pci_dev *dev;
 
 	ppc_md.iommu_bus_setup(bus);
 
@@ -926,14 +1157,28 @@
 
 	if (ppc_md.irq_bus_setup)
 		ppc_md.irq_bus_setup(bus);
+}
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev = bus->self;
+
+	if (dev && pci_probe_only &&
+	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		/* This is a subordinate bridge */
+
+		pci_read_bridge_bases(bus);
+		pcibios_fixup_device_resources(dev, bus);
+	}
+
+	do_bus_setup(bus);
 
 	if (!pci_probe_only)
 		return;
 
-	list_for_each_entry(dev, &bus->devices, bus_list) {
+	list_for_each_entry(dev, &bus->devices, bus_list)
 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 			pcibios_fixup_device_resources(dev, bus);
-	}
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index d37bff2..dc40a0c 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -388,7 +388,7 @@
 	 * the reg address cell, we shall fix that by killing struct
 	 * reg_property and using some accessor functions instead
 	 */
-       	hose->first_busno = 0xf0;
+	hose->first_busno = 0xf0;
 	hose->last_busno = 0xff;
 	has_uninorth = 1;
 	hose->ops = &macrisc_pci_ops;
@@ -473,7 +473,7 @@
 			continue;
 		}		
 		cur++;
-       		DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+		DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
 		    cur-1, res->start - 1, cur, res->end + 1);
 		hose->mem_resources[cur].name = np->full_name;
 		hose->mem_resources[cur].flags = IORESOURCE_MEM;
@@ -603,24 +603,24 @@
 	char* disp_name;
 	int *bus_range;
 	int primary = 1;
- 	struct property *of_prop;
+	struct property *of_prop;
 
 	DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-       	bus_range = (int *) get_property(dev, "bus-range", &len);
-       	if (bus_range == NULL || len < 2 * sizeof(int)) {
-       		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-       			       dev->full_name);
-       	}
+	bus_range = (int *) get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+			dev->full_name);
+	}
 
 	hose = alloc_bootmem(sizeof(struct pci_controller));
 	if (hose == NULL)
 		return -ENOMEM;
-       	pci_setup_pci_controller(hose);
+	pci_setup_pci_controller(hose);
 
-       	hose->arch_data = dev;
-       	hose->first_busno = bus_range ? bus_range[0] : 0;
-       	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+	hose->arch_data = dev;
+	hose->first_busno = bus_range ? bus_range[0] : 0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
 	of_prop = alloc_bootmem(sizeof(struct property) +
 				sizeof(hose->global_number));
@@ -634,24 +634,24 @@
 	}
 
 	disp_name = NULL;
-       	if (device_is_compatible(dev, "u3-agp")) {
-       		setup_u3_agp(hose);
-       		disp_name = "U3-AGP";
-       		primary = 0;
-       	} else if (device_is_compatible(dev, "u3-ht")) {
-       		setup_u3_ht(hose);
-       		disp_name = "U3-HT";
-       		primary = 1;
-       	}
-       	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-       		disp_name, hose->first_busno, hose->last_busno);
+	if (device_is_compatible(dev, "u3-agp")) {
+		setup_u3_agp(hose);
+		disp_name = "U3-AGP";
+		primary = 0;
+	} else if (device_is_compatible(dev, "u3-ht")) {
+		setup_u3_ht(hose);
+		disp_name = "U3-HT";
+		primary = 1;
+	}
+	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+		disp_name, hose->first_busno, hose->last_busno);
 
-       	/* Interpret the "ranges" property */
-       	/* This also maps the I/O region and sets isa_io/mem_base */
-       	pmac_process_bridge_OF_ranges(hose, dev, primary);
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pmac_process_bridge_OF_ranges(hose, dev, primary);
 
-       	/* Fixup "bus-range" OF property */
-       	fixup_bus_range(dev);
+	/* Fixup "bus-range" OF property */
+	fixup_bus_range(dev);
 
 	return 0;
 }
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e7f695d..325426c 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -477,6 +477,18 @@
 	return 1;
 }
 
+static int pmac_probe_mode(struct pci_bus *bus)
+{
+	struct device_node *node = bus->sysdata;
+
+	/* We need to use normal PCI probing for the AGP bus,
+	   since the device for the AGP bridge isn't in the tree. */
+	if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+		return PCI_PROBE_NORMAL;
+
+	return PCI_PROBE_DEVTREE;
+}
+
 struct machdep_calls __initdata pmac_md = {
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= generic_mach_cpu_die,
@@ -488,6 +500,7 @@
 	.init_IRQ		= pmac_init_IRQ,
 	.get_irq		= mpic_get_irq,
 	.pcibios_fixup		= pmac_pcibios_fixup,
+	.pci_probe_mode		= pmac_probe_mode,
 	.restart		= pmac_restart,
 	.power_off		= pmac_power_off,
 	.halt			= pmac_halt,
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index 7a7e027..8870053 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -54,6 +54,7 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/time.h>
+#include <asm/plpar_wrappers.h>
 
 #ifndef CONFIG_SMP
 struct task_struct *last_task_used_math = NULL;
@@ -163,7 +164,30 @@
 
 #endif /* CONFIG_ALTIVEC */
 
+static void set_dabr_spr(unsigned long val)
+{
+	mtspr(SPRN_DABR, val);
+}
+
+int set_dabr(unsigned long dabr)
+{
+	int ret = 0;
+
+	if (firmware_has_feature(FW_FEATURE_XDABR)) {
+		/* We want to catch accesses from kernel and userspace */
+		unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
+		ret = plpar_set_xdabr(dabr, flags);
+	} else if (firmware_has_feature(FW_FEATURE_DABR)) {
+		ret = plpar_set_dabr(dabr);
+	} else {
+		set_dabr_spr(dabr);
+	}
+
+	return ret;
+}
+
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+static DEFINE_PER_CPU(unsigned long, current_dabr);
 
 struct task_struct *__switch_to(struct task_struct *prev,
 				struct task_struct *new)
@@ -198,6 +222,11 @@
 		new->thread.regs->msr |= MSR_VEC;
 #endif /* CONFIG_ALTIVEC */
 
+	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+		set_dabr(new->thread.dabr);
+		__get_cpu_var(current_dabr) = new->thread.dabr;
+	}
+
 	flush_tlb_pending();
 
 	new_thread = &new->thread;
@@ -334,6 +363,11 @@
 		last_task_used_altivec = NULL;
 #endif /* CONFIG_ALTIVEC */
 #endif /* CONFIG_SMP */
+
+	if (current->thread.dabr) {
+		current->thread.dabr = 0;
+		set_dabr(0);
+	}
 }
 
 void
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 2993f10..85ed318 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -206,6 +207,19 @@
 		break;
 	}
 
+	case PTRACE_GET_DEBUGREG: {
+		ret = -EINVAL;
+		/* We only support one DABR and no IABRS at the moment */
+		if (addr > 0)
+			break;
+		ret = put_user(child->thread.dabr,
+			       (unsigned long __user *)data);
+		break;
+	}
+
+	case PTRACE_SET_DEBUGREG:
+		ret = ptrace_set_debugreg(child, addr, data);
+
 	case PTRACE_DETACH:
 		ret = ptrace_detach(child, data);
 		break;
@@ -274,6 +288,20 @@
 		break;
 	}
 
+#ifdef CONFIG_ALTIVEC
+	case PTRACE_GETVRREGS:
+		/* Get the child altivec register state. */
+		flush_altivec_to_thread(child);
+		ret = get_vrregs((unsigned long __user *)data, child);
+		break;
+
+	case PTRACE_SETVRREGS:
+		/* Set the child altivec register state. */
+		flush_altivec_to_thread(child);
+		ret = set_vrregs(child, (unsigned long __user *)data);
+		break;
+#endif
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
index 1643642..fb8c22d 100644
--- a/arch/ppc64/kernel/ptrace32.c
+++ b/arch/ppc64/kernel/ptrace32.c
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -337,6 +338,19 @@
 		break;
 	}
 
+	case PTRACE_GET_DEBUGREG: {
+		ret = -EINVAL;
+		/* We only support one DABR and no IABRS at the moment */
+		if (addr > 0)
+			break;
+		ret = put_user(child->thread.dabr, (u32 __user *)data);
+		break;
+	}
+
+	case PTRACE_SET_DEBUGREG:
+		ret = ptrace_set_debugreg(child, addr, data);
+		break;
+
 	case PTRACE_DETACH:
 		ret = ptrace_detach(child, data);
 		break;
@@ -405,9 +419,23 @@
 		break;
 	}
 
-       case PTRACE_GETEVENTMSG:
-                ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-                break;
+	case PTRACE_GETEVENTMSG:
+		ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+		break;
+
+#ifdef CONFIG_ALTIVEC
+	case PTRACE_GETVRREGS:
+		/* Get the child altivec register state. */
+		flush_altivec_to_thread(child);
+		ret = get_vrregs((unsigned long __user *)data, child);
+		break;
+
+	case PTRACE_SETVRREGS:
+		/* Set the child altivec register state. */
+		flush_altivec_to_thread(child);
+		ret = set_vrregs(child, (unsigned long __user *)data);
+		break;
+#endif
 
 	default:
 		ret = ptrace_request(child, request, addr, data);
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 3c00f7b..41b97dc 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -59,8 +59,6 @@
 /* This is true if we are using the firmware NMI handler (typically LPAR) */
 extern int fwnmi_active;
 
-extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
-
 static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
 
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index bfa8791c..5ac48bd 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -1064,8 +1064,6 @@
 #define PPC64_LINUX_FUNCTION 0x0f000000
 #define PPC64_IPL_MESSAGE 0xc0000000
 #define PPC64_TERM_MESSAGE 0xb0000000
-#define PPC64_ATTN_MESSAGE 0xa0000000
-#define PPC64_DUMP_MESSAGE 0xd0000000
 
 static void ppc64_do_msg(unsigned int src, const char *msg)
 {
@@ -1093,20 +1091,6 @@
 	printk("[terminate]%04x %s\n", src, msg);
 }
 
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg)
-{
-	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
-	printk("[attention]%04x %s\n", src, msg);
-}
-
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg)
-{
-	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
-	printk("[dump]%04x %s\n", src, msg);
-}
-
 /* This should only be called on processor 0 during calibrate decr */
 void __init setup_default_decr(void)
 {
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index 49a79a5..347112c 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -550,6 +550,15 @@
 		/* Whee!  Actually deliver the signal.  */
 		if (TRAP(regs) == 0x0C00)
 			syscall_restart(regs, &ka);
+
+		/*
+		 * Reenable the DABR before delivering the signal to
+		 * user space. The DABR will have been cleared if it
+		 * triggered inside the kernel.
+		 */
+		if (current->thread.dabr)
+			set_dabr(current->thread.dabr);
+
 		return handle_signal(signr, &ka, &info, oldset, regs);
 	}
 
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index 46f4d6c..a8b7a5a 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -970,6 +970,14 @@
 		newsp = regs->gpr[1];
 	newsp &= ~0xfUL;
 
+	/*
+	 * Reenable the DABR before delivering the signal to
+	 * user space. The DABR will have been cleared if it
+	 * triggered inside the kernel.
+	 */
+	if (current->thread.dabr)
+		set_dabr(current->thread.dabr);
+
 	/* Whee!  Actually deliver the signal.  */
 	if (ka.sa.sa_flags & SA_SIGINFO)
 		ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index d9dc6f2..daf9388 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -38,7 +38,7 @@
 static void xics_end_irq(unsigned int irq);
 static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
 
-struct hw_interrupt_type xics_pic = {
+static struct hw_interrupt_type xics_pic = {
 	.typename = " XICS     ",
 	.startup = xics_startup,
 	.enable = xics_enable_irq,
@@ -48,7 +48,7 @@
 	.set_affinity = xics_set_affinity
 };
 
-struct hw_interrupt_type xics_8259_pic = {
+static struct hw_interrupt_type xics_8259_pic = {
 	.typename = " XICS/8259",
 	.ack = xics_mask_and_ack_irq,
 };
@@ -89,9 +89,8 @@
 static int xics_irq_8259_cascade = 0;
 static int xics_irq_8259_cascade_real = 0;
 static unsigned int default_server = 0xFF;
-/* also referenced in smp.c... */
-unsigned int default_distrib_server = 0;
-unsigned int interrupt_server_size = 8;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
 
 /*
  * XICS only has a single IPI, so encode the messages per CPU
@@ -99,10 +98,10 @@
 struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 /* RTAS service tokens */
-int ibm_get_xive;
-int ibm_set_xive;
-int ibm_int_on;
-int ibm_int_off;
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
 
 typedef struct {
 	int (*xirr_info_get)(int cpu);
@@ -284,16 +283,17 @@
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive "
-		       "returned %x\n", irq, call_status);
+		printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
+		       "returned %d\n", irq, call_status);
+		printk("set_xive %x, server %x\n", ibm_set_xive, server);
 		return;
 	}
 
 	/* Now unmask the interrupt (often a no-op) */
 	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on "
-		       "returned %x\n", irq, call_status);
+		printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
+		       "returned %d\n", irq, call_status);
 		return;
 	}
 }
@@ -308,8 +308,8 @@
 
 	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_disable_real_irq: irq=%d: "
-		       "ibm_int_off returned %x\n", irq, call_status);
+		printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
+		       "ibm_int_off returned %d\n", irq, call_status);
 		return;
 	}
 
@@ -317,8 +317,8 @@
 	/* Have to set XIVE to 0xff to be able to remove a slot */
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
 	if (call_status != 0) {
-		printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)"
-		       " returned %x\n", irq, call_status);
+		printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
+		       " returned %d\n", irq, call_status);
 		return;
 	}
 }
@@ -380,7 +380,7 @@
 		if (irq == NO_IRQ)
 			irq = real_irq_to_virt_slowpath(vec);
 		if (irq == NO_IRQ) {
-			printk(KERN_ERR "Interrupt %d (real) is invalid,"
+			printk(KERN_ERR "Interrupt %u (real) is invalid,"
 			       " disabling it.\n", vec);
 			xics_disable_real_irq(vec);
 		} else
@@ -622,7 +622,7 @@
 	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
 	if (status) {
-		printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive "
+		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
 		       "returns %d\n", irq, status);
 		return;
 	}
@@ -641,7 +641,7 @@
 				irq, newmask, xics_status[1]);
 
 	if (status) {
-		printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive "
+		printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
 		       "returns %d\n", irq, status);
 		return;
 	}
@@ -720,7 +720,7 @@
 
 		status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 		if (status) {
-			printk(KERN_ERR "migrate_irqs_away: irq=%d "
+			printk(KERN_ERR "migrate_irqs_away: irq=%u "
 					"ibm,get-xive returns %d\n",
 					virq, status);
 			goto unlock;
@@ -734,7 +734,7 @@
 		if (xics_status[0] != get_hard_smp_processor_id(cpu))
 			goto unlock;
 
-		printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n",
+		printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
 		       virq, cpu);
 
 		/* Reset affinity to all cpus */
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 772f071..7fbc68b 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -77,6 +77,28 @@
 	return 0;
 }
 
+static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+{
+	siginfo_t info;
+
+	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+			11, SIGSEGV) == NOTIFY_STOP)
+		return;
+
+	if (debugger_dabr_match(regs))
+		return;
+
+	/* Clear the DABR */
+	set_dabr(0);
+
+	/* Deliver the signal to userspace */
+	info.si_signo = SIGTRAP;
+	info.si_errno = 0;
+	info.si_code = TRAP_HWBKPT;
+	info.si_addr = (void __user *)regs->nip;
+	force_sig_info(SIGTRAP, &info, current);
+}
+
 /*
  * The error_code parameter is
  *  - DSISR for a non-SLB data access fault,
@@ -111,12 +133,9 @@
 	if (!user_mode(regs) && (address >= TASK_SIZE))
 		return SIGSEGV;
 
-	if (error_code & DSISR_DABRMATCH) {
-		if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
-					11, SIGSEGV) == NOTIFY_STOP)
-			return 0;
-		if (debugger_dabr_match(regs))
-			return 0;
+  	if (error_code & DSISR_DABRMATCH) {
+		do_dabr(regs, error_code);
+		return 0;
 	}
 
 	if (in_atomic() || mm == NULL) {
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h
index 183c3e4..02eb40d 100644
--- a/arch/ppc64/xmon/privinst.h
+++ b/arch/ppc64/xmon/privinst.h
@@ -46,7 +46,6 @@
 GSETSPR(1008, hid0)
 GSETSPR(1009, hid1)
 GSETSPR(1010, iabr)
-GSETSPR(1013, dabr)
 GSETSPR(1023, pir)
 
 static inline void store_inst(void *p)
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 45908b1..74e63a8 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -586,6 +586,8 @@
 {
 	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
 		return 0;
+	if (dabr.enabled == 0)
+		return 0;
 	xmon_core(regs, 0);
 	return 1;
 }
@@ -628,20 +630,6 @@
 	return 0;
 }
 
-/* On systems with a hypervisor, we can't set the DABR
-   (data address breakpoint register) directly. */
-static void set_controlled_dabr(unsigned long val)
-{
-#ifdef CONFIG_PPC_PSERIES
-	if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-		int rc = plpar_hcall_norets(H_SET_DABR, val);
-		if (rc != H_Success)
-			xmon_printf("Warning: setting DABR failed (%d)\n", rc);
-	} else
-#endif
-		set_dabr(val);
-}
-
 static struct bpt *at_breakpoint(unsigned long pc)
 {
 	int i;
@@ -728,7 +716,7 @@
 static void insert_cpu_bpts(void)
 {
 	if (dabr.enabled)
-		set_controlled_dabr(dabr.address | (dabr.enabled & 7));
+		set_dabr(dabr.address | (dabr.enabled & 7));
 	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 		set_iabr(iabr->address
 			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -756,7 +744,7 @@
 
 static void remove_cpu_bpts(void)
 {
-	set_controlled_dabr(0);
+	set_dabr(0);
 	if (cpu_has_feature(CPU_FTR_IABR))
 		set_iabr(0);
 }
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 18610ce..ed877d0 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -678,7 +678,7 @@
 	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
 	set_fs(old_fs);
 	
-	if (!ret && offset && put_user(of, offset))
+	if (offset && put_user(of, offset))
 		return -EFAULT;
 		
 	return ret;
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 7931d6f..787d5f1 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -10,6 +10,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
 
 void *module_alloc(unsigned long size)
 {
@@ -37,7 +38,7 @@
 }
 
 /* Make generic code ignore STT_REGISTER dummy undefined symbols,
- * and replace references to .func with func as in ppc64's dedotify.
+ * and replace references to .func with _Func
  */
 int module_frob_arch_sections(Elf_Ehdr *hdr,
 			      Elf_Shdr *sechdrs,
@@ -64,8 +65,10 @@
 				sym[i].st_shndx = SHN_ABS;
 			else {
 				char *name = strtab + sym[i].st_name;
-				if (name[0] == '.')
-					memmove(name, name+1, strlen(name));
+				if (name[0] == '.') {
+					name[0] = '_';
+					name[1] = toupper(name[1]);
+				}
 			}
 		}
 	}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index f848093..1c8fd0f 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -97,19 +97,12 @@
 /* Alias functions whose names begin with "." and export the aliases.
  * The module references will be fixed up by module_frob_arch_sections.
  */
-#define DOT_ALIAS2(__ret, __x, __arg1, __arg2) \
-	extern __ret __x(__arg1, __arg2); \
-	asm(".weak " #__x);\
-	asm(#__x "=." #__x);
-
-DOT_ALIAS2(int, div, int, int)
-DOT_ALIAS2(int, mul, int, int)
-DOT_ALIAS2(int, rem, int, int)
-DOT_ALIAS2(unsigned, udiv, unsigned, unsigned)
-DOT_ALIAS2(unsigned, umul, unsigned, unsigned)
-DOT_ALIAS2(unsigned, urem, unsigned, unsigned)
-
-#undef DOT_ALIAS2
+extern int _Div(int, int);
+extern int _Mul(int, int);
+extern int _Rem(int, int);
+extern unsigned _Udiv(unsigned, unsigned);
+extern unsigned _Umul(unsigned, unsigned);
+extern unsigned _Urem(unsigned, unsigned);
 
 /* used by various drivers */
 EXPORT_SYMBOL(sparc_cpu_model);
@@ -320,12 +313,12 @@
 EXPORT_SYMBOL(__muldi3);
 EXPORT_SYMBOL(__divdi3);
 
-EXPORT_SYMBOL(rem);
-EXPORT_SYMBOL(urem);
-EXPORT_SYMBOL(mul);
-EXPORT_SYMBOL(umul);
-EXPORT_SYMBOL(div);
-EXPORT_SYMBOL(udiv);
+EXPORT_SYMBOL(_Rem);
+EXPORT_SYMBOL(_Urem);
+EXPORT_SYMBOL(_Mul);
+EXPORT_SYMBOL(_Umul);
+EXPORT_SYMBOL(_Div);
+EXPORT_SYMBOL(_Udiv);
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 EXPORT_SYMBOL(do_BUG);
diff --git a/arch/sparc/lib/mul.S b/arch/sparc/lib/mul.S
index 83dffbc..da69356 100644
--- a/arch/sparc/lib/mul.S
+++ b/arch/sparc/lib/mul.S
@@ -16,7 +16,9 @@
  */
 
 	.globl .mul
+	.globl _Mul
 .mul:
+_Mul:	/* needed for export */
 	mov	%o0, %y		! multiplier -> Y
 	andncc	%o0, 0xfff, %g0	! test bits 12..31
 	be	Lmul_shortway	! if zero, can do it the short way
diff --git a/arch/sparc/lib/rem.S b/arch/sparc/lib/rem.S
index 4450814..bf015a9 100644
--- a/arch/sparc/lib/rem.S
+++ b/arch/sparc/lib/rem.S
@@ -43,7 +43,9 @@
 
 
 	.globl .rem
+	.globl _Rem
 .rem:
+_Rem:	/* needed for export */
 	! compute sign of result; if neither is negative, no problem
 	orcc	%o1, %o0, %g0	! either negative?
 	bge	2f			! no, go do the divide
diff --git a/arch/sparc/lib/sdiv.S b/arch/sparc/lib/sdiv.S
index e0ad80b..af94516 100644
--- a/arch/sparc/lib/sdiv.S
+++ b/arch/sparc/lib/sdiv.S
@@ -43,7 +43,9 @@
 
 
 	.globl .div
+	.globl _Div
 .div:
+_Div:	/* needed for export */
 	! compute sign of result; if neither is negative, no problem
 	orcc	%o1, %o0, %g0	! either negative?
 	bge	2f			! no, go do the divide
diff --git a/arch/sparc/lib/udiv.S b/arch/sparc/lib/udiv.S
index 2abfc6b..169e01d 100644
--- a/arch/sparc/lib/udiv.S
+++ b/arch/sparc/lib/udiv.S
@@ -43,7 +43,9 @@
 
 
 	.globl .udiv
+	.globl _Udiv
 .udiv:
+_Udiv:	/* needed for export */
 
 	! Ready to divide.  Compute size of quotient; scale comparand.
 	orcc	%o1, %g0, %o5
diff --git a/arch/sparc/lib/umul.S b/arch/sparc/lib/umul.S
index a784720..f0e5b20 100644
--- a/arch/sparc/lib/umul.S
+++ b/arch/sparc/lib/umul.S
@@ -21,7 +21,9 @@
  */
 
 	.globl .umul
+	.globl _Umul
 .umul:
+_Umul:	/* needed for export */
 	or	%o0, %o1, %o4
 	mov	%o0, %y		! multiplier -> Y
 
diff --git a/arch/sparc/lib/urem.S b/arch/sparc/lib/urem.S
index ec7f0c5..6b92bdc 100644
--- a/arch/sparc/lib/urem.S
+++ b/arch/sparc/lib/urem.S
@@ -41,7 +41,9 @@
  */
 
 	.globl .urem
+	.globl _Urem
 .urem:
+_Urem:	/* needed for export */
 
 	! Ready to divide.  Compute size of quotient; scale comparand.
 	orcc	%o1, %g0, %o5
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index f4399c7..18c6e91 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -46,7 +46,7 @@
 $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
 			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
-	@echo 'Kernel: $@ is ready'
+	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index b38d5b8..0e10fd8 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -83,7 +83,7 @@
 #endif
 #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
 
-extern char input_data[];
+extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
@@ -288,7 +288,7 @@
 #else
 	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
-	output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
+	output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
 }
 
@@ -305,7 +305,7 @@
 #else
 	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
 #endif	
-	mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+	mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
 	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
 	  ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
 	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index bf57e23..f8db7e5 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-git3
-# Fri Aug 12 16:40:34 2005
+# Linux kernel version: 2.6.13-git11
+# Mon Sep 12 16:16:16 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
 CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -13,6 +14,7 @@
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -37,6 +40,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -102,6 +106,7 @@
 CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=32
@@ -122,6 +127,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Power management options
@@ -194,7 +200,6 @@
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -234,7 +239,10 @@
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
@@ -244,8 +252,8 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-CONFIG_IP_TCPDIAG_IPV6=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=y
@@ -258,6 +266,11 @@
 # CONFIG_NETFILTER is not set
 
 #
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
@@ -280,9 +293,11 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -329,7 +344,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_LBD=y
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -409,6 +423,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -432,7 +447,7 @@
 #
 # SCSI Transport Attributes
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 
@@ -458,6 +473,7 @@
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
@@ -537,6 +553,11 @@
 # CONFIG_ARCNET is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -586,6 +607,7 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -595,6 +617,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
@@ -749,7 +772,6 @@
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -760,6 +782,7 @@
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -768,6 +791,10 @@
 # CONFIG_IBM_ASM is not set
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -858,9 +885,8 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=y
 
@@ -877,6 +903,7 @@
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -893,6 +920,7 @@
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
@@ -976,6 +1004,8 @@
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+CONFIG_DCDBAS=m
 
 #
 # File systems
@@ -1000,10 +1030,6 @@
 # CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1012,6 +1038,7 @@
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1037,12 +1064,11 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1074,6 +1100,7 @@
 # CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
@@ -1086,6 +1113,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1150,6 +1178,7 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1157,6 +1186,7 @@
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_INIT_DEBUG=y
 # CONFIG_IOMMU_DEBUG is not set
 CONFIG_KPROBES=y
@@ -1180,5 +1210,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5244f80..e0eb0c7 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -55,20 +55,34 @@
  * with the int 0x80 path.
  */ 	
 ENTRY(ia32_sysenter_target)
-	CFI_STARTPROC
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,0
+	CFI_REGISTER	rsp,rbp
 	swapgs
 	movq	%gs:pda_kernelstack, %rsp
 	addq	$(PDA_STACKOFFSET),%rsp	
 	sti	
  	movl	%ebp,%ebp		/* zero extension */
 	pushq	$__USER32_DS
+	CFI_ADJUST_CFA_OFFSET 8
+	/*CFI_REL_OFFSET ss,0*/
 	pushq	%rbp
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rsp,0
 	pushfq
+	CFI_ADJUST_CFA_OFFSET 8
+	/*CFI_REL_OFFSET rflags,0*/
 	movl	$VSYSCALL32_SYSEXIT, %r10d
+	CFI_REGISTER rip,r10
 	pushq	$__USER32_CS
+	CFI_ADJUST_CFA_OFFSET 8
+	/*CFI_REL_OFFSET cs,0*/
 	movl	%eax, %eax
 	pushq	%r10
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rip,0
 	pushq	%rax
+	CFI_ADJUST_CFA_OFFSET 8
 	cld
 	SAVE_ARGS 0,0,1
  	/* no need to do an access_ok check here because rbp has been
@@ -79,6 +93,7 @@
  	.previous	
 	GET_THREAD_INFO(%r10)
 	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+	CFI_REMEMBER_STATE
 	jnz  sysenter_tracesys
 sysenter_do_call:	
 	cmpl	$(IA32_NR_syscalls),%eax
@@ -94,14 +109,20 @@
 	andl  $~0x200,EFLAGS-R11(%rsp) 
 	RESTORE_ARGS 1,24,1,1,1,1
 	popfq
+	CFI_ADJUST_CFA_OFFSET -8
+	/*CFI_RESTORE rflags*/
 	popq	%rcx				/* User %esp */
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_REGISTER rsp,rcx
 	movl	$VSYSCALL32_SYSEXIT,%edx	/* User %eip */
+	CFI_REGISTER rip,rdx
 	swapgs
 	sti		/* sti only takes effect after the next instruction */
 	/* sysexit */
 	.byte	0xf, 0x35
 
 sysenter_tracesys:
+	CFI_RESTORE_STATE
 	SAVE_REST
 	CLEAR_RREGS
 	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
@@ -140,21 +161,28 @@
  * with the int 0x80 path.	
  */ 	
 ENTRY(ia32_cstar_target)
-	CFI_STARTPROC
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,0
+	CFI_REGISTER	rip,rcx
+	/*CFI_REGISTER	rflags,r11*/
 	swapgs
 	movl	%esp,%r8d
+	CFI_REGISTER	rsp,r8
 	movq	%gs:pda_kernelstack,%rsp
 	sti
 	SAVE_ARGS 8,1,1
 	movl 	%eax,%eax	/* zero extension */
 	movq	%rax,ORIG_RAX-ARGOFFSET(%rsp)
 	movq	%rcx,RIP-ARGOFFSET(%rsp)
+	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	movq	%rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
 	movl	%ebp,%ecx
 	movq	$__USER32_CS,CS-ARGOFFSET(%rsp)
 	movq	$__USER32_DS,SS-ARGOFFSET(%rsp)
 	movq	%r11,EFLAGS-ARGOFFSET(%rsp)
+	/*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
 	movq	%r8,RSP-ARGOFFSET(%rsp)	
+	CFI_REL_OFFSET rsp,RSP-ARGOFFSET
 	/* no need to do an access_ok check here because r8 has been
 	   32bit zero extended */ 
 	/* hardware stack frame is complete now */	
@@ -164,6 +192,7 @@
 	.previous	
 	GET_THREAD_INFO(%r10)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+	CFI_REMEMBER_STATE
 	jnz   cstar_tracesys
 cstar_do_call:	
 	cmpl $IA32_NR_syscalls,%eax
@@ -177,12 +206,16 @@
 	jnz  int_ret_from_sys_call
 	RESTORE_ARGS 1,-ARG_SKIP,1,1,1
 	movl RIP-ARGOFFSET(%rsp),%ecx
+	CFI_REGISTER rip,rcx
 	movl EFLAGS-ARGOFFSET(%rsp),%r11d	
+	/*CFI_REGISTER rflags,r11*/
 	movl RSP-ARGOFFSET(%rsp),%esp
+	CFI_RESTORE rsp
 	swapgs
 	sysretl
 	
 cstar_tracesys:	
+	CFI_RESTORE_STATE
 	SAVE_REST
 	CLEAR_RREGS
 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
@@ -226,11 +259,18 @@
  */ 				
 
 ENTRY(ia32_syscall)
-	CFI_STARTPROC
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,SS+8-RIP
+	/*CFI_REL_OFFSET	ss,SS-RIP*/
+	CFI_REL_OFFSET	rsp,RSP-RIP
+	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP*/
+	/*CFI_REL_OFFSET	cs,CS-RIP*/
+	CFI_REL_OFFSET	rip,RIP-RIP
 	swapgs	
 	sti
 	movl %eax,%eax
 	pushq %rax
+	CFI_ADJUST_CFA_OFFSET 8
 	cld
 	/* note the registers are not zero extended to the sf.
 	   this could be a problem. */
@@ -278,6 +318,8 @@
 	jmp  ia32_ptregs_common	
 	.endm
 
+	CFI_STARTPROC
+
 	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
 	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
 	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
@@ -290,8 +332,9 @@
 	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
 
 ENTRY(ia32_ptregs_common)
-	CFI_STARTPROC
 	popq %r11
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_REGISTER rip, r11
 	SAVE_REST
 	call *%rax
 	RESTORE_REST
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 04d8040..5389df6 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -751,7 +751,7 @@
 	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
 	set_fs(old_fs);
 	
-	if (!ret && offset && put_user(of, offset))
+	if (offset && put_user(of, offset))
 		return -EFAULT;
 		
 	return ret;
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 1579bdd..bcdd0a8 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -46,3 +46,4 @@
 intel_cacheinfo-y		+= ../../i386/kernel/cpu/intel_cacheinfo.o
 quirks-y			+= ../../i386/kernel/quirks.o
 i8237-y				+= ../../i386/kernel/i8237.o
+msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index 148f6f7..867a0eb 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/bootmem.h>
-#include <linux/irq.h>
 #include <linux/acpi.h>
 #include <asm/mpspec.h>
 #include <asm/io.h>
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index c9a6b81..962ad48 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -245,6 +245,8 @@
 		
 	if (aper_alloc) { 
 		/* Got the aperture from the AGP bridge */
+	} else if (swiotlb && !valid_agp) {
+		/* Do nothing */
 	} else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
 		   force_iommu ||
 		   valid_agp ||
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 375d369..b6e7715 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -109,11 +108,8 @@
 	if (maxlvt >= 4)
 		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
 	v = GET_APIC_VERSION(apic_read(APIC_LVR));
-	if (APIC_INTEGRATED(v)) {	/* !82489DX */
-		if (maxlvt > 3)		/* Due to Pentium errata 3AP and 11AP. */
-			apic_write(APIC_ESR, 0);
-		apic_read(APIC_ESR);
-	}
+	apic_write(APIC_ESR, 0);
+	apic_read(APIC_ESR);
 }
 
 void __init connect_bsp_APIC(void)
@@ -316,8 +312,6 @@
 	 */
 	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
 	value = APIC_DM_NMI;
-	if (!APIC_INTEGRATED(ver))		/* 82489DX */
-		value |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT1, value);
 }
 
@@ -325,14 +319,6 @@
 {
 	unsigned int value, ver, maxlvt;
 
-	/* Pound the ESR really hard over the head with a big hammer - mbligh */
-	if (esr_disable) {
-		apic_write(APIC_ESR, 0);
-		apic_write(APIC_ESR, 0);
-		apic_write(APIC_ESR, 0);
-		apic_write(APIC_ESR, 0);
-	}
-
 	value = apic_read(APIC_LVR);
 	ver = GET_APIC_VERSION(value);
 
@@ -430,15 +416,11 @@
 		value = APIC_DM_NMI;
 	else
 		value = APIC_DM_NMI | APIC_LVT_MASKED;
-	if (!APIC_INTEGRATED(ver))		/* 82489DX */
-		value |= APIC_LVT_LEVEL_TRIGGER;
 	apic_write_around(APIC_LVT1, value);
 
-	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */
+	{
 		unsigned oldvalue;
 		maxlvt = get_maxlvt();
-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
-			apic_write(APIC_ESR, 0);
 		oldvalue = apic_read(APIC_ESR);
 		value = ERROR_APIC_VECTOR;      // enables sending errors
 		apic_write_around(APIC_LVTERR, value);
@@ -452,17 +434,6 @@
 			apic_printk(APIC_VERBOSE,
 			"ESR value after enabling vector: %08x, after %08x\n",
 			oldvalue, value);
-	} else {
-		if (esr_disable)	
-			/* 
-			 * Something untraceble is creating bad interrupts on 
-			 * secondary quads ... for the moment, just leave the
-			 * ESR disabled - we can't do anything useful with the
-			 * errors anyway - mbligh
-			 */
-			apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
-		else 
-			apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
 	}
 
 	nmi_watchdog_default();
@@ -650,8 +621,7 @@
 	 * Fetch the APIC ID of the BSP in case we have a
 	 * default configuration (or the MP table is broken).
 	 */
-	if (boot_cpu_id == -1U)
-		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+	boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
 
 #ifdef CONFIG_X86_IO_APIC
 	{
@@ -693,8 +663,6 @@
 
 	ver = GET_APIC_VERSION(apic_read(APIC_LVR));
 	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-	if (!APIC_INTEGRATED(ver))
-		lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
 	apic_write_around(APIC_LVTT, lvtt_value);
 
 	/*
@@ -1081,7 +1049,7 @@
 
 	connect_bsp_APIC();
 
-	phys_cpu_present_map = physid_mask_of_physid(0);
+	phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
 	apic_write_around(APIC_ID, boot_cpu_id);
 
 	setup_local_APIC();
diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
index 35b4c3f..aaa6d38 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -39,7 +39,6 @@
 	ENTRY(kernelstack); 
 	ENTRY(oldrsp); 
 	ENTRY(pcurrent); 
-	ENTRY(irqrsp);
 	ENTRY(irqcount);
 	ENTRY(cpunumber);
 	ENTRY(irqstackptr);
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index d7fa424..535e044 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -11,7 +11,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/kexec.h>
 
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index bb0ae18..4e34b0f 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -28,6 +28,7 @@
  * PFN of last memory page.
  */
 unsigned long end_pfn; 
+EXPORT_SYMBOL(end_pfn);
 
 /* 
  * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
@@ -131,7 +132,7 @@
 
 		if (ei->type != E820_RAM || 
 		    ei->addr+ei->size <= start || 
-		    ei->addr > end)
+		    ei->addr >= end)
 			continue;
 
 		addr = round_up(ei->addr, PAGE_SIZE);
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 9631c74..9cd968d 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -5,6 +5,7 @@
 #include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <asm/fcntl.h>
 
 /* Simple VGA output */
 
@@ -158,6 +159,47 @@
 	.index =	-1,
 };
 
+/* Console interface to a host file on AMD's SimNow! */
+
+static int simnow_fd;
+
+enum {
+	MAGIC1 = 0xBACCD00A,
+	MAGIC2 = 0xCA110000,
+	XOPEN = 5,
+	XWRITE = 4,
+};
+
+static noinline long simnow(long cmd, long a, long b, long c)
+{
+	long ret;
+	asm volatile("cpuid" :
+		     "=a" (ret) :
+		     "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+	return ret;
+}
+
+void __init simnow_init(char *str)
+{
+	char *fn = "klog";
+	if (*str == '=')
+		fn = ++str;
+	/* error ignored */
+	simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
+}
+
+static void simnow_write(struct console *con, const char *s, unsigned n)
+{
+	simnow(XWRITE, simnow_fd, (unsigned long)s, n);
+}
+
+static struct console simnow_console = {
+	.name =		"simnow",
+	.write =	simnow_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
 /* Direct interface for emergencies */
 struct console *early_console = &early_vga_console;
 static int early_console_initialized = 0;
@@ -205,6 +247,10 @@
 		max_xpos = SCREEN_INFO.orig_video_cols;
 		max_ypos = SCREEN_INFO.orig_video_lines;
 		early_console = &early_vga_console; 
+ 	} else if (!strncmp(buf, "simnow", 6)) {
+ 		simnow_init(buf + 6);
+ 		early_console = &simnow_console;
+ 		keep_early = 1;
 	}
 	early_console_initialized = 1;
 	register_console(early_console);       
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 3620508..7937971 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -79,16 +79,19 @@
 	xorl %eax, %eax
 	pushq %rax /* ss */
 	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	ss,0*/
 	pushq %rax /* rsp */
 	CFI_ADJUST_CFA_OFFSET	8
-	CFI_OFFSET	rip,0
+	CFI_REL_OFFSET	rsp,0
 	pushq $(1<<9) /* eflags - interrupts on */
 	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	rflags,0*/
 	pushq $__KERNEL_CS /* cs */
 	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	cs,0*/
 	pushq \child_rip /* rip */
 	CFI_ADJUST_CFA_OFFSET	8
-	CFI_OFFSET	rip,0
+	CFI_REL_OFFSET	rip,0
 	pushq	%rax /* orig rax */
 	CFI_ADJUST_CFA_OFFSET	8
 	.endm
@@ -98,32 +101,39 @@
 	CFI_ADJUST_CFA_OFFSET	-(6*8)
 	.endm
 
-	.macro	CFI_DEFAULT_STACK
-	CFI_ADJUST_CFA_OFFSET  (SS)
-	CFI_OFFSET	r15,R15-SS
-	CFI_OFFSET	r14,R14-SS
-	CFI_OFFSET	r13,R13-SS
-	CFI_OFFSET	r12,R12-SS
-	CFI_OFFSET	rbp,RBP-SS
-	CFI_OFFSET	rbx,RBX-SS
-	CFI_OFFSET	r11,R11-SS
-	CFI_OFFSET	r10,R10-SS
-	CFI_OFFSET	r9,R9-SS
-	CFI_OFFSET	r8,R8-SS
-	CFI_OFFSET	rax,RAX-SS
-	CFI_OFFSET	rcx,RCX-SS
-	CFI_OFFSET	rdx,RDX-SS
-	CFI_OFFSET	rsi,RSI-SS
-	CFI_OFFSET	rdi,RDI-SS
-	CFI_OFFSET	rsp,RSP-SS
-	CFI_OFFSET	rip,RIP-SS
+	.macro	CFI_DEFAULT_STACK start=1
+	.if \start
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,SS+8
+	.else
+	CFI_DEF_CFA_OFFSET SS+8
+	.endif
+	CFI_REL_OFFSET	r15,R15
+	CFI_REL_OFFSET	r14,R14
+	CFI_REL_OFFSET	r13,R13
+	CFI_REL_OFFSET	r12,R12
+	CFI_REL_OFFSET	rbp,RBP
+	CFI_REL_OFFSET	rbx,RBX
+	CFI_REL_OFFSET	r11,R11
+	CFI_REL_OFFSET	r10,R10
+	CFI_REL_OFFSET	r9,R9
+	CFI_REL_OFFSET	r8,R8
+	CFI_REL_OFFSET	rax,RAX
+	CFI_REL_OFFSET	rcx,RCX
+	CFI_REL_OFFSET	rdx,RDX
+	CFI_REL_OFFSET	rsi,RSI
+	CFI_REL_OFFSET	rdi,RDI
+	CFI_REL_OFFSET	rip,RIP
+	/*CFI_REL_OFFSET	cs,CS*/
+	/*CFI_REL_OFFSET	rflags,EFLAGS*/
+	CFI_REL_OFFSET	rsp,RSP
+	/*CFI_REL_OFFSET	ss,SS*/
 	.endm
 /*
  * A newly forked process directly context switches into this.
  */ 	
 /* rdi:	prev */	
 ENTRY(ret_from_fork)
-	CFI_STARTPROC
 	CFI_DEFAULT_STACK
 	call schedule_tail
 	GET_THREAD_INFO(%rcx)
@@ -172,16 +182,21 @@
  */ 			 		
 
 ENTRY(system_call)
-	CFI_STARTPROC
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,0
+	CFI_REGISTER	rip,rcx
+	/*CFI_REGISTER	rflags,r11*/
 	swapgs
 	movq	%rsp,%gs:pda_oldrsp 
 	movq	%gs:pda_kernelstack,%rsp
 	sti					
 	SAVE_ARGS 8,1
 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
-	movq  %rcx,RIP-ARGOFFSET(%rsp)  
+	movq  %rcx,RIP-ARGOFFSET(%rsp)
+	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+	CFI_REMEMBER_STATE
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
 	ja badsys
@@ -201,9 +216,12 @@
 	cli
 	movl threadinfo_flags(%rcx),%edx
 	andl %edi,%edx
+	CFI_REMEMBER_STATE
 	jnz  sysret_careful 
 	movq RIP-ARGOFFSET(%rsp),%rcx
+	CFI_REGISTER	rip,rcx
 	RESTORE_ARGS 0,-ARG_SKIP,1
+	/*CFI_REGISTER	rflags,r11*/
 	movq	%gs:pda_oldrsp,%rsp
 	swapgs
 	sysretq
@@ -211,12 +229,15 @@
 	/* Handle reschedules */
 	/* edx:	work, edi: workmask */	
 sysret_careful:
+	CFI_RESTORE_STATE
 	bt $TIF_NEED_RESCHED,%edx
 	jnc sysret_signal
 	sti
 	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
 	call schedule
 	popq  %rdi
+	CFI_ADJUST_CFA_OFFSET -8
 	jmp sysret_check
 
 	/* Handle a signal */ 
@@ -234,8 +255,13 @@
 1:	movl $_TIF_NEED_RESCHED,%edi
 	jmp sysret_check
 	
+badsys:
+	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+	jmp ret_from_sys_call
+
 	/* Do syscall tracing */
 tracesys:			 
+	CFI_RESTORE_STATE
 	SAVE_REST
 	movq $-ENOSYS,RAX(%rsp)
 	FIXUP_TOP_OF_STACK %rdi
@@ -254,16 +280,29 @@
 	RESTORE_TOP_OF_STACK %rbx
 	RESTORE_REST
 	jmp ret_from_sys_call
+	CFI_ENDPROC
 		
-badsys:
-	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)	
-	jmp ret_from_sys_call
-
 /* 
  * Syscall return path ending with IRET.
  * Has correct top of stack, but partial stack frame.
  */ 	
-ENTRY(int_ret_from_sys_call)	
+ENTRY(int_ret_from_sys_call)
+	CFI_STARTPROC	simple
+	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
+	/*CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
+	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
+	/*CFI_REL_OFFSET	rflags,EFLAGS-ARGOFFSET*/
+	/*CFI_REL_OFFSET	cs,CS-ARGOFFSET*/
+	CFI_REL_OFFSET	rip,RIP-ARGOFFSET
+	CFI_REL_OFFSET	rdx,RDX-ARGOFFSET
+	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
+	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
+	CFI_REL_OFFSET	rdi,RDI-ARGOFFSET
+	CFI_REL_OFFSET	rsi,RSI-ARGOFFSET
+	CFI_REL_OFFSET	r8,R8-ARGOFFSET
+	CFI_REL_OFFSET	r9,R9-ARGOFFSET
+	CFI_REL_OFFSET	r10,R10-ARGOFFSET
+	CFI_REL_OFFSET	r11,R11-ARGOFFSET
 	cli
 	testl $3,CS-ARGOFFSET(%rsp)
 	je retint_restore_args
@@ -284,8 +323,10 @@
 	jnc  int_very_careful
 	sti
 	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
 	call schedule
 	popq %rdi
+	CFI_ADJUST_CFA_OFFSET -8
 	cli
 	jmp int_with_check
 
@@ -297,9 +338,11 @@
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
 	jz int_signal
 	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
 	leaq 8(%rsp),%rdi	# &ptregs -> arg1	
 	call syscall_trace_leave
 	popq %rdi
+	CFI_ADJUST_CFA_OFFSET -8
 	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
 	cli
 	jmp int_restore_rest
@@ -329,6 +372,8 @@
 	jmp	ptregscall_common
 	.endm
 
+	CFI_STARTPROC
+
 	PTREGSCALL stub_clone, sys_clone, %r8
 	PTREGSCALL stub_fork, sys_fork, %rdi
 	PTREGSCALL stub_vfork, sys_vfork, %rdi
@@ -337,40 +382,49 @@
 	PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
-	CFI_STARTPROC
 	popq %r11
-	CFI_ADJUST_CFA_OFFSET	-8
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_REGISTER rip, r11
 	SAVE_REST
 	movq %r11, %r15
+	CFI_REGISTER rip, r15
 	FIXUP_TOP_OF_STACK %r11
 	call *%rax
 	RESTORE_TOP_OF_STACK %r11
 	movq %r15, %r11
+	CFI_REGISTER rip, r11
 	RESTORE_REST
 	pushq %r11
-	CFI_ADJUST_CFA_OFFSET	8
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rip, 0
 	ret
 	CFI_ENDPROC
 	
 ENTRY(stub_execve)
 	CFI_STARTPROC
 	popq %r11
-	CFI_ADJUST_CFA_OFFSET	-8
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_REGISTER rip, r11
 	SAVE_REST
 	movq %r11, %r15
+	CFI_REGISTER rip, r15
 	FIXUP_TOP_OF_STACK %r11
 	call sys_execve
 	GET_THREAD_INFO(%rcx)
 	bt $TIF_IA32,threadinfo_flags(%rcx)
+	CFI_REMEMBER_STATE
 	jc exec_32bit
 	RESTORE_TOP_OF_STACK %r11
 	movq %r15, %r11
+	CFI_REGISTER rip, r11
 	RESTORE_REST
-	push %r11
+	pushq %r11
+	CFI_ADJUST_CFA_OFFSET 8
+	CFI_REL_OFFSET rip, 0
 	ret
 
 exec_32bit:
-	CFI_ADJUST_CFA_OFFSET	REST_SKIP
+	CFI_RESTORE_STATE
 	movq %rax,RAX(%rsp)
 	RESTORE_REST
 	jmp int_ret_from_sys_call
@@ -382,7 +436,8 @@
  */                
 ENTRY(stub_rt_sigreturn)
 	CFI_STARTPROC
-	addq $8, %rsp		
+	addq $8, %rsp
+	CFI_ADJUST_CFA_OFFSET	-8
 	SAVE_REST
 	movq %rsp,%rdi
 	FIXUP_TOP_OF_STACK %r11
@@ -392,6 +447,25 @@
 	jmp int_ret_from_sys_call
 	CFI_ENDPROC
 
+/*
+ * initial frame state for interrupts and exceptions
+ */
+	.macro _frame ref
+	CFI_STARTPROC simple
+	CFI_DEF_CFA rsp,SS+8-\ref
+	/*CFI_REL_OFFSET ss,SS-\ref*/
+	CFI_REL_OFFSET rsp,RSP-\ref
+	/*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+	/*CFI_REL_OFFSET cs,CS-\ref*/
+	CFI_REL_OFFSET rip,RIP-\ref
+	.endm
+
+/* initial frame state for interrupts (and exceptions without error code) */
+#define INTR_FRAME _frame RIP
+/* initial frame state for exceptions with error code (and interrupts with
+   vector already pushed) */
+#define XCPT_FRAME _frame ORIG_RAX
+
 /* 
  * Interrupt entry/exit.
  *
@@ -402,10 +476,6 @@
 
 /* 0(%rsp): interrupt number */ 
 	.macro interrupt func
-	CFI_STARTPROC	simple
-	CFI_DEF_CFA	rsp,(SS-RDI)
-	CFI_REL_OFFSET	rsp,(RSP-ORIG_RAX)
-	CFI_REL_OFFSET	rip,(RIP-ORIG_RAX)
 	cld
 #ifdef CONFIG_DEBUG_INFO
 	SAVE_ALL	
@@ -425,23 +495,27 @@
 	swapgs	
 1:	incl	%gs:pda_irqcount	# RED-PEN should check preempt count
 	movq %gs:pda_irqstackptr,%rax
-	cmoveq %rax,%rsp							
+	cmoveq %rax,%rsp /*todo This needs CFI annotation! */
 	pushq %rdi			# save old stack	
+	CFI_ADJUST_CFA_OFFSET	8
 	call \func
 	.endm
 
 ENTRY(common_interrupt)
+	XCPT_FRAME
 	interrupt do_IRQ
 	/* 0(%rsp): oldrsp-ARGOFFSET */
-ret_from_intr:		
+ret_from_intr:
 	popq  %rdi
+	CFI_ADJUST_CFA_OFFSET	-8
 	cli	
 	decl %gs:pda_irqcount
 #ifdef CONFIG_DEBUG_INFO
 	movq RBP(%rdi),%rbp
+	CFI_DEF_CFA_REGISTER	rsp
 #endif
-	leaq ARGOFFSET(%rdi),%rsp
-exit_intr:	 	
+	leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
+exit_intr:
 	GET_THREAD_INFO(%rcx)
 	testl $3,CS-ARGOFFSET(%rsp)
 	je retint_kernel
@@ -453,9 +527,10 @@
 	 */		
 retint_with_reschedule:
 	movl $_TIF_WORK_MASK,%edi
-retint_check:			
+retint_check:
 	movl threadinfo_flags(%rcx),%edx
 	andl %edi,%edx
+	CFI_REMEMBER_STATE
 	jnz  retint_careful
 retint_swapgs:	 	
 	swapgs 
@@ -476,14 +551,17 @@
 	jmp do_exit			
 	.previous	
 	
-	/* edi: workmask, edx: work */	
+	/* edi: workmask, edx: work */
 retint_careful:
+	CFI_RESTORE_STATE
 	bt    $TIF_NEED_RESCHED,%edx
 	jnc   retint_signal
 	sti
 	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET	8
 	call  schedule
 	popq %rdi		
+	CFI_ADJUST_CFA_OFFSET	-8
 	GET_THREAD_INFO(%rcx)
 	cli
 	jmp retint_check
@@ -523,7 +601,9 @@
  * APIC interrupts.
  */		
 	.macro apicinterrupt num,func
+	INTR_FRAME
 	pushq $\num-256
+	CFI_ADJUST_CFA_OFFSET 8
 	interrupt \func
 	jmp ret_from_intr
 	CFI_ENDPROC
@@ -536,8 +616,19 @@
 ENTRY(reschedule_interrupt)
 	apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
 
-ENTRY(invalidate_interrupt)
-	apicinterrupt INVALIDATE_TLB_VECTOR,smp_invalidate_interrupt
+	.macro INVALIDATE_ENTRY num
+ENTRY(invalidate_interrupt\num)
+	apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt	
+	.endm
+
+	INVALIDATE_ENTRY 0
+	INVALIDATE_ENTRY 1
+	INVALIDATE_ENTRY 2
+	INVALIDATE_ENTRY 3
+	INVALIDATE_ENTRY 4
+	INVALIDATE_ENTRY 5
+	INVALIDATE_ENTRY 6
+	INVALIDATE_ENTRY 7
 
 ENTRY(call_function_interrupt)
 	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
@@ -558,16 +649,23 @@
  * Exception entry points.
  */ 		
 	.macro zeroentry sym
+	INTR_FRAME
 	pushq $0	/* push error code/oldrax */ 
+	CFI_ADJUST_CFA_OFFSET 8
 	pushq %rax	/* push real oldrax to the rdi slot */ 
+	CFI_ADJUST_CFA_OFFSET 8
 	leaq  \sym(%rip),%rax
 	jmp error_entry
+	CFI_ENDPROC
 	.endm	
 
 	.macro errorentry sym
+	XCPT_FRAME
 	pushq %rax
+	CFI_ADJUST_CFA_OFFSET 8
 	leaq  \sym(%rip),%rax
 	jmp error_entry
+	CFI_ENDPROC
 	.endm
 
 	/* error code is on the stack already */
@@ -594,10 +692,7 @@
  * and the exception handler in %rax.	
  */ 		  				
 ENTRY(error_entry)
-	CFI_STARTPROC	simple
-	CFI_DEF_CFA	rsp,(SS-RDI)
-	CFI_REL_OFFSET	rsp,(RSP-RDI)
-	CFI_REL_OFFSET	rip,(RIP-RDI)
+	_frame RDI
 	/* rdi slot contains rax, oldrax contains error code */
 	cld	
 	subq  $14*8,%rsp
@@ -679,7 +774,9 @@
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
 ENTRY(load_gs_index)
+	CFI_STARTPROC
 	pushf
+	CFI_ADJUST_CFA_OFFSET 8
 	cli
         swapgs
 gs_change:     
@@ -687,7 +784,9 @@
 2:	mfence		/* workaround */
 	swapgs
         popf
+	CFI_ADJUST_CFA_OFFSET -8
         ret
+	CFI_ENDPROC
        
         .section __ex_table,"a"
         .align 8
@@ -799,7 +898,7 @@
 
 	/* runs on exception stack */
 KPROBE_ENTRY(debug)
-	CFI_STARTPROC
+ 	INTR_FRAME
 	pushq $0
 	CFI_ADJUST_CFA_OFFSET 8		
 	paranoidentry do_debug
@@ -809,9 +908,9 @@
 
 	/* runs on exception stack */	
 ENTRY(nmi)
-	CFI_STARTPROC
+	INTR_FRAME
 	pushq $-1
-	CFI_ADJUST_CFA_OFFSET 8		
+	CFI_ADJUST_CFA_OFFSET 8
 	paranoidentry do_nmi
 	/*
  	 * "Paranoid" exit path from exception stack.
@@ -877,7 +976,7 @@
 
 	/* runs on exception stack */
 ENTRY(double_fault)
-	CFI_STARTPROC
+	XCPT_FRAME
 	paranoidentry do_double_fault
 	jmp paranoid_exit
 	CFI_ENDPROC
@@ -890,7 +989,7 @@
 
 	/* runs on exception stack */
 ENTRY(stack_segment)
-	CFI_STARTPROC
+	XCPT_FRAME
 	paranoidentry do_stack_segment
 	jmp paranoid_exit
 	CFI_ENDPROC
@@ -911,7 +1010,7 @@
 #ifdef CONFIG_X86_MCE
 	/* runs on exception stack */
 ENTRY(machine_check)
-	CFI_STARTPROC
+	INTR_FRAME
 	pushq $0
 	CFI_ADJUST_CFA_OFFSET 8	
 	paranoidentry do_machine_check
@@ -923,14 +1022,19 @@
        zeroentry do_call_debug
 
 ENTRY(call_softirq)
+	CFI_STARTPROC
 	movq %gs:pda_irqstackptr,%rax
 	pushq %r15
+	CFI_ADJUST_CFA_OFFSET 8
 	movq %rsp,%r15
+	CFI_DEF_CFA_REGISTER	r15
 	incl %gs:pda_irqcount
 	cmove %rax,%rsp
 	call __do_softirq
 	movq %r15,%rsp
+	CFI_DEF_CFA_REGISTER	rsp
 	decl %gs:pda_irqcount
 	popq %r15
+	CFI_ADJUST_CFA_OFFSET -8
 	ret
-
+	CFI_ENDPROC
diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c
index b1c144f..7a64ea1 100644
--- a/arch/x86_64/kernel/genapic.c
+++ b/arch/x86_64/kernel/genapic.c
@@ -45,7 +45,7 @@
 	u8 clusters, max_cluster;
 	u8 id;
 	u8 cluster_cnt[NUM_APIC_CLUSTERS];
-	int num_cpus = 0;
+	int max_apic = 0;
 
 #if defined(CONFIG_ACPI)
 	/*
@@ -64,14 +64,15 @@
 		id = bios_cpu_apicid[i];
 		if (id == BAD_APICID)
 			continue;
-		num_cpus++;
+		if (id > max_apic)
+			max_apic = id;
 		cluster_cnt[APIC_CLUSTERID(id)]++;
 	}
 
 	/* Don't use clustered mode on AMD platforms. */
  	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
 		genapic = &apic_physflat;
-#ifndef CONFIG_CPU_HOTPLUG
+#ifndef CONFIG_HOTPLUG_CPU
 		/* In the CPU hotplug case we cannot use broadcast mode
 		   because that opens a race when a CPU is removed.
 		   Stay at physflat mode in this case.
@@ -79,7 +80,7 @@
 		   we have ACPI platform support for CPU hotplug
 		   we should detect hotplug capablity from ACPI tables and
 		   only do this when really needed. -AK */
-		if (num_cpus <= 8)
+		if (max_apic <= 8)
 			genapic = &apic_flat;
 #endif
  		goto print;
@@ -103,9 +104,14 @@
 	 * (We don't use lowest priority delivery + HW APIC IRQ steering, so
 	 * can ignore the clustered logical case and go straight to physical.)
 	 */
-	if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
+	if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
+#ifdef CONFIG_HOTPLUG_CPU
+		/* Don't use APIC shortcuts in CPU hotplug to avoid races */
+		genapic = &apic_physflat;
+#else
 		genapic = &apic_flat;
-	else
+#endif
+	} else
 		genapic = &apic_cluster;
 
 print:
diff --git a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
index f6523dd..a472d62 100644
--- a/arch/x86_64/kernel/genapic_cluster.c
+++ b/arch/x86_64/kernel/genapic_cluster.c
@@ -51,10 +51,10 @@
 		count = 3;
 	id = my_cluster | (1UL << count);
 	x86_cpu_to_log_apicid[smp_processor_id()] = id;
-	apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+	apic_write(APIC_DFR, APIC_DFR_CLUSTER);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(id);
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 /* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index 6d57da9..9da3edb 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -38,10 +38,10 @@
 	num = smp_processor_id();
 	id = 1UL << num;
 	x86_cpu_to_log_apicid[num] = id;
-	apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+	apic_write(APIC_DFR, APIC_DFR_FLAT);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(id);
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
@@ -62,7 +62,7 @@
 	 * prepare target chip field
 	 */
 	cfg = __prepare_ICR2(mask);
-	apic_write_around(APIC_ICR2, cfg);
+	apic_write(APIC_ICR2, cfg);
 
 	/*
 	 * program the ICR
@@ -72,7 +72,7 @@
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
-	apic_write_around(APIC_ICR, cfg);
+	apic_write(APIC_ICR, cfg);
 	local_irq_restore(flags);
 }
 
@@ -177,9 +177,9 @@
 
 struct genapic apic_physflat =  {
 	.name = "physical flat",
-	.int_delivery_mode = dest_LowestPrio,
+	.int_delivery_mode = dest_Fixed,
 	.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-	.int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST,
+	.int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
 	.target_cpus = physflat_target_cpus,
 	.apic_id_registered = flat_apic_id_registered,
 	.init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 98ff5eb..4592bf2 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -270,7 +270,7 @@
 .org 0x4000
 ENTRY(level2_ident_pgt)
 	/* 40MB for bootup. 	*/
-	.quad	0x0000000000000283
+	.quad	0x0000000000000183
 	.quad	0x0000000000200183
 	.quad	0x0000000000400183
 	.quad	0x0000000000600183
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index a891690..b2a238b 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -18,15 +18,12 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/apic.h>
 
-#include <linux/irq.h>
-
 /*
  * Common place to define all x86 IRQ vectors
  *
@@ -486,7 +483,14 @@
 void error_interrupt(void);
 void reschedule_interrupt(void);
 void call_function_interrupt(void);
-void invalidate_interrupt(void);
+void invalidate_interrupt0(void);
+void invalidate_interrupt1(void);
+void invalidate_interrupt2(void);
+void invalidate_interrupt3(void);
+void invalidate_interrupt4(void);
+void invalidate_interrupt5(void);
+void invalidate_interrupt6(void);
+void invalidate_interrupt7(void);
 void thermal_interrupt(void);
 void i8254_timer_resume(void);
 
@@ -562,8 +566,15 @@
 	 */
 	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
 
-	/* IPI for invalidation */
-	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+	/* IPIs for invalidation */
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
+	set_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
 
 	/* IPI for generic function call */
 	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index c4dc914..e0ba5c1 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -44,6 +44,6 @@
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
 
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 5f1529b..522944a 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -21,7 +21,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -45,6 +44,8 @@
 
 static int no_timer_check;
 
+int disable_timer_pin_1 __initdata;
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -298,6 +299,15 @@
 #endif
 					/* RED-PEN skip them on mptables too? */
 					return;
+				case PCI_VENDOR_ID_ATI:
+					/* All timer interrupts on atiixp
+				           are doubled. Disable one. */
+					if (disable_timer_pin_1 == 0) {
+						disable_timer_pin_1 = 1;
+						printk(KERN_INFO
+		"ATI board detected. Disabling timer pin 1.\n");
+					}
+					return;
 				} 
 
 				/* No multi-function device? */
@@ -1022,13 +1032,11 @@
 	v = apic_read(APIC_TASKPRI);
 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
-	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
-		v = apic_read(APIC_ARBPRI);
-		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-			v & APIC_ARBPRI_MASK);
-		v = apic_read(APIC_PROCPRI);
-		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
-	}
+	v = apic_read(APIC_ARBPRI);
+	printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+		v & APIC_ARBPRI_MASK);
+	v = apic_read(APIC_PROCPRI);
+	printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
 
 	v = apic_read(APIC_EOI);
 	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
@@ -1048,12 +1056,8 @@
 	printk(KERN_DEBUG "... APIC IRR field:\n");
 	print_APIC_bitfield(APIC_IRR);
 
-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
-			apic_write(APIC_ESR, 0);
-		v = apic_read(APIC_ESR);
-		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
-	}
+	v = apic_read(APIC_ESR);
+	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
 
 	v = apic_read(APIC_ICR);
 	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
@@ -1665,6 +1669,8 @@
 				setup_nmi();
 				enable_8259A_irq(0);
 			}
+			if (disable_timer_pin_1 > 0)
+				clear_IO_APIC_pin(0, pin1);
 			return;
 		}
 		clear_IO_APIC_pin(0, pin1);
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 849a20a..d6a04a8 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -99,7 +99,6 @@
 	unsigned irq = regs->orig_rax & 0xff;
 
 	irq_enter();
-	BUG_ON(irq > 256);
 
 	__do_IRQ(irq, regs);
 	irq_exit();
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 8aa5673..08203b0 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/cpu.h>
 #include <linux/percpu.h>
+#include <linux/ctype.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -56,15 +57,19 @@
 	smp_wmb();
 	for (;;) {
 		entry = rcu_dereference(mcelog.next);
-		/* When the buffer fills up discard new entries. Assume 
-		   that the earlier errors are the more interesting. */
-		if (entry >= MCE_LOG_LEN) {
-			set_bit(MCE_OVERFLOW, &mcelog.flags);
-			return;
+		for (;;) {
+			/* When the buffer fills up discard new entries. Assume
+			   that the earlier errors are the more interesting. */
+			if (entry >= MCE_LOG_LEN) {
+				set_bit(MCE_OVERFLOW, &mcelog.flags);
+				return;
+			}
+			/* Old left over entry. Skip. */
+			if (mcelog.entry[entry].finished) {
+				entry++;
+				continue;
+			}
 		}
-		/* Old left over entry. Skip. */
-		if (mcelog.entry[entry].finished)
-			continue;
 		smp_rmb();
 		next = entry + 1;
 		if (cmpxchg(&mcelog.next, entry, next) == entry)
@@ -212,7 +217,7 @@
 			panicm_found = 1;
 		}
 
-		tainted |= TAINT_MACHINE_CHECK;
+		add_taint(TAINT_MACHINE_CHECK);
 	}
 
 	/* Never do anything final in the polling timer */
@@ -404,9 +409,15 @@
 	}
 
 	err = 0;
-	for (i = 0; i < next; i++) {
-		if (!mcelog.entry[i].finished)
-			continue;
+	for (i = 0; i < next; i++) {		
+		unsigned long start = jiffies;
+		while (!mcelog.entry[i].finished) {
+			if (!time_before(jiffies, start + 2)) {
+				memset(mcelog.entry + i,0, sizeof(struct mce));
+				continue;
+			}
+			cpu_relax();
+		}
 		smp_rmb();
 		err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
 		buf += sizeof(struct mce); 
@@ -479,6 +490,7 @@
 
 /* mce=off disables machine check. Note you can reenable it later
    using sysfs.
+   mce=TOLERANCELEVEL (number, see above)
    mce=bootlog Log MCEs from before booting. Disabled by default to work
    around buggy BIOS that leave bogus MCEs.  */
 static int __init mcheck_enable(char *str)
@@ -489,6 +501,8 @@
 		mce_dont_init = 1;
 	else if (!strcmp(str, "bootlog"))
 		mce_bootlog = 1;
+	else if (isdigit(str[0]))
+		get_option(&str, &tolerant);
 	else
 		printk("mce= argument %s ignored. Please use /sys", str); 
 	return 0;
@@ -501,10 +515,12 @@
  * Sysfs support
  */ 
 
-/* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
+/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
+   Only one CPU is active at this time, the others get readded later using
+   CPU hotplug. */
 static int mce_resume(struct sys_device *dev)
 {
-	on_each_cpu(mce_init, NULL, 1, 1);
+	mce_init(NULL);
 	return 0;
 }
 
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 8d8ed6a..f16d38d 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/config.h>
@@ -46,8 +45,6 @@
 int apic_version [MAX_APICS];
 unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-unsigned char pci_bus_to_node [256];
-EXPORT_SYMBOL(pci_bus_to_node);
 
 static int mp_current_pci_id = 0;
 /* I/O APIC entries */
@@ -705,7 +702,7 @@
 
 	processor.mpc_type = MP_PROCESSOR;
 	processor.mpc_apicid = id;
-	processor.mpc_apicver = 0x10; /* TBD: lapic version */
+	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
 	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
 	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
 	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
deleted file mode 100644
index 598953a..0000000
--- a/arch/x86_64/kernel/msr.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *   
- *   Copyright 2000 H. Peter Anvin - All Rights Reserved
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * msr.c
- *
- * x86 MSR access device
- *
- * This device is accessed by lseek() to the appropriate register number
- * and then read/write in chunks of 8 bytes.  A larger size means multiple
- * reads or writes of the same register.
- *
- * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
- * an SMP box will direct the access to CPU %d.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* Note: "err" is handled in a funny way below.  Otherwise one version
-   of gcc or another breaks. */
-
-static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
-{
-	int err;
-
-	asm volatile ("1:	wrmsr\n"
-		      "2:\n"
-		      ".section .fixup,\"ax\"\n"
-		      "3:	movl %4,%0\n"
-		      "	jmp 2b\n"
-		      ".previous\n"
-		      ".section __ex_table,\"a\"\n"
-		      "	.align 8\n" "	.quad 1b,3b\n" ".previous":"=&bDS" (err)
-		      :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
-
-	return err;
-}
-
-static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
-{
-	int err;
-
-	asm volatile ("1:	rdmsr\n"
-		      "2:\n"
-		      ".section .fixup,\"ax\"\n"
-		      "3:	movl %4,%0\n"
-		      "	jmp 2b\n"
-		      ".previous\n"
-		      ".section __ex_table,\"a\"\n"
-		      "	.align 8\n"
-		      "	.quad 1b,3b\n"
-		      ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
-		      :"c"(reg), "i"(-EIO), "0"(0));
-
-	return err;
-}
-
-#ifdef CONFIG_SMP
-
-struct msr_command {
-	int cpu;
-	int err;
-	u32 reg;
-	u32 data[2];
-};
-
-static void msr_smp_wrmsr(void *cmd_block)
-{
-	struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-	if (cmd->cpu == smp_processor_id())
-		cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
-}
-
-static void msr_smp_rdmsr(void *cmd_block)
-{
-	struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-	if (cmd->cpu == smp_processor_id())
-		cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
-}
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-	struct msr_command cmd;
-	int ret;
-
-	preempt_disable();
-	if (cpu == smp_processor_id()) {
-		ret = wrmsr_eio(reg, eax, edx);
-	} else {
-		cmd.cpu = cpu;
-		cmd.reg = reg;
-		cmd.data[0] = eax;
-		cmd.data[1] = edx;
-
-		smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
-		ret = cmd.err;
-	}
-	preempt_enable();
-	return ret;
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
-{
-	struct msr_command cmd;
-	int ret;
-
-	preempt_disable();
-	if (cpu == smp_processor_id()) {
-		ret = rdmsr_eio(reg, eax, edx);
-	} else {
-		cmd.cpu = cpu;
-		cmd.reg = reg;
-
-		smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-
-		*eax = cmd.data[0];
-		*edx = cmd.data[1];
-
-		ret = cmd.err;
-	}
-	preempt_enable();
-	return ret;
-}
-
-#else				/* ! CONFIG_SMP */
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-	return wrmsr_eio(reg, eax, edx);
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
-{
-	return rdmsr_eio(reg, eax, edx);
-}
-
-#endif				/* ! CONFIG_SMP */
-
-static loff_t msr_seek(struct file *file, loff_t offset, int orig)
-{
-	loff_t ret = -EINVAL;
-
-	lock_kernel();
-	switch (orig) {
-	case 0:
-		file->f_pos = offset;
-		ret = file->f_pos;
-		break;
-	case 1:
-		file->f_pos += offset;
-		ret = file->f_pos;
-	}
-	unlock_kernel();
-	return ret;
-}
-
-static ssize_t msr_read(struct file *file, char __user * buf,
-			size_t count, loff_t * ppos)
-{
-	u32 __user *tmp = (u32 __user *) buf;
-	u32 data[2];
-	size_t rv;
-	u32 reg = *ppos;
-	int cpu = iminor(file->f_dentry->d_inode);
-	int err;
-
-	if (count % 8)
-		return -EINVAL;	/* Invalid chunk size */
-
-	for (rv = 0; count; count -= 8) {
-		err = do_rdmsr(cpu, reg, &data[0], &data[1]);
-		if (err)
-			return err;
-		if (copy_to_user(tmp, &data, 8))
-			return -EFAULT;
-		tmp += 2;
-	}
-
-	return ((char __user *)tmp) - buf;
-}
-
-static ssize_t msr_write(struct file *file, const char __user *buf,
-			 size_t count, loff_t *ppos)
-{
-	const u32 __user *tmp = (const u32 __user *)buf;
-	u32 data[2];
-	size_t rv;
-	u32 reg = *ppos;
-	int cpu = iminor(file->f_dentry->d_inode);
-	int err;
-
-	if (count % 8)
-		return -EINVAL;	/* Invalid chunk size */
-
-	for (rv = 0; count; count -= 8) {
-		if (copy_from_user(&data, tmp, 8))
-			return -EFAULT;
-		err = do_wrmsr(cpu, reg, data[0], data[1]);
-		if (err)
-			return err;
-		tmp += 2;
-	}
-
-	return ((char __user *)tmp) - buf;
-}
-
-static int msr_open(struct inode *inode, struct file *file)
-{
-	unsigned int cpu = iminor(file->f_dentry->d_inode);
-	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-
-	if (cpu >= NR_CPUS || !cpu_online(cpu))
-		return -ENXIO;	/* No such CPU */
-	if (!cpu_has(c, X86_FEATURE_MSR))
-		return -EIO;	/* MSR not supported */
-
-	return 0;
-}
-
-/*
- * File operations we support
- */
-static struct file_operations msr_fops = {
-	.owner = THIS_MODULE,
-	.llseek = msr_seek,
-	.read = msr_read,
-	.write = msr_write,
-	.open = msr_open,
-};
-
-static int __init msr_init(void)
-{
-	if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
-		printk(KERN_ERR "msr: unable to get major %d for msr\n",
-		       MSR_MAJOR);
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static void __exit msr_exit(void)
-{
-	unregister_chrdev(MSR_MAJOR, "cpu/msr");
-}
-
-module_init(msr_init);
-module_exit(msr_exit)
-
-MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
-MODULE_DESCRIPTION("x86 generic MSR driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index caf1649..39d445e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -14,7 +14,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -367,7 +366,7 @@
 		| K7_NMI_EVENT;
 
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-	wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+	wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= K7_EVNTSEL_ENABLE;
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
@@ -408,8 +407,8 @@
 
 	wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
 	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
-	Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+	Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz));
+	wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz));
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
 	return 1;
@@ -488,8 +487,8 @@
 							== NOTIFY_STOP) {
 				local_set(&__get_cpu_var(alert_counter), 0);
 				return;
-			} 
-			die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
+			}
+			die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
 		}
 	} else {
 		__get_cpu_var(last_irq_sum) = sum;
@@ -507,7 +506,7 @@
  			wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
  			apic_write(APIC_LVTPC, APIC_DM_NMI);
  		}
-		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+		wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
 	}
 }
 
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 57f35c6..cf0a031 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -191,11 +191,9 @@
 {
 	struct page *page;
 	int node;
-	if (dev->bus == &pci_bus_type) {
-		cpumask_t mask;
-		mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
-		node = cpu_to_node(first_cpu(mask));
-	} else
+	if (dev->bus == &pci_bus_type)
+		node = pcibus_to_node(to_pci_dev(dev)->bus);
+	else
 		node = numa_node_id();
 	page = alloc_pages_node(node, gfp, order);
 	return page ? page_address(page) : NULL;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 8661f82..b5a89c0 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -32,7 +32,6 @@
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/random.h>
@@ -123,6 +122,7 @@
 			: :
 			"i" (_TIF_NEED_RESCHED), 
 			"m" (current_thread_info()->flags));
+		clear_thread_flag(TIF_POLLING_NRFLAG);
 	} else {
 		set_need_resched();
 	}
@@ -271,8 +271,11 @@
 
 	printk("\n");
 	print_modules();
-	printk("Pid: %d, comm: %.20s %s %s\n", 
-	       current->pid, current->comm, print_tainted(), system_utsname.release);
+	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+		current->pid, current->comm, print_tainted(),
+		system_utsname.release,
+		(int)strcspn(system_utsname.version, " "),
+		system_utsname.version);
 	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
 	printk_address(regs->rip); 
 	printk("\nRSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags);
@@ -483,33 +486,6 @@
 }
 
 /*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
-			       struct task_struct *next_p)
-{
-	struct thread_info *prev, *next;
-
-	/*
-	 * gcc should eliminate the ->thread_info dereference if
-	 * has_secure_computing returns 0 at compile time (SECCOMP=n).
-	 */
-	prev = prev_p->thread_info;
-	next = next_p->thread_info;
-
-	if (has_secure_computing(prev) || has_secure_computing(next)) {
-		/* slow path here */
-		if (has_secure_computing(prev) &&
-		    !has_secure_computing(next)) {
-			write_cr4(read_cr4() & ~X86_CR4_TSD);
-		} else if (!has_secure_computing(prev) &&
-			   has_secure_computing(next))
-			write_cr4(read_cr4() | X86_CR4_TSD);
-	}
-}
-
-/*
  * This special macro can be used to load a debugging register
  */
 #define loaddebug(thread,r) set_debug(thread->debugreg ## r, r)
@@ -627,8 +603,6 @@
 		}
 	}
 
-	disable_tsc(prev_p, next_p);
-
 	return prev_p;
 }
 
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 9aec524..351d8d6 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -336,6 +336,11 @@
 #endif
 #endif
 
+		if (!memcmp(from, "disable_timer_pin_1", 19))
+			disable_timer_pin_1 = 1;
+		if (!memcmp(from, "enable_timer_pin_1", 18))
+			disable_timer_pin_1 = -1;
+
 		if (!memcmp(from, "nolapic", 7) ||
 		    !memcmp(from, "disableapic", 11))
 			disable_apic = 1;
@@ -755,6 +760,24 @@
 	}
 }
 
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+	int i;
+	for (i = apicid - 1; i >= 0; i--) {
+		int node = apicid_to_node[i];
+		if (node != NUMA_NO_NODE && node_online(node))
+			return node;
+	}
+	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+		int node = apicid_to_node[i];
+		if (node != NUMA_NO_NODE && node_online(node))
+			return node;
+	}
+	return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -763,8 +786,11 @@
 {
 #ifdef CONFIG_SMP
 	int cpu = smp_processor_id();
-	int node = 0;
 	unsigned bits;
+#ifdef CONFIG_NUMA
+	int node = 0;
+	unsigned apicid = phys_proc_id[cpu];
+#endif
 
 	bits = 0;
 	while ((1 << bits) < c->x86_num_cores)
@@ -776,20 +802,32 @@
 	phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
-	/* When an ACPI SRAT table is available use the mappings from SRAT
- 	   instead. */
-	if (acpi_numa <= 0) {
-		node = phys_proc_id[cpu];
-		if (!node_online(node))
-			node = first_node(node_online_map);
-		cpu_to_node[cpu] = node;
-	} else {
-		node = cpu_to_node[cpu];
-	}
-#endif
+  	node = phys_proc_id[cpu];
+ 	if (apicid_to_node[apicid] != NUMA_NO_NODE)
+ 		node = apicid_to_node[apicid];
+ 	if (!node_online(node)) {
+ 		/* Two possibilities here:
+ 		   - The CPU is missing memory and no node was created.
+ 		   In that case try picking one from a nearby CPU
+ 		   - The APIC IDs differ from the HyperTransport node IDs
+ 		   which the K8 northbridge parsing fills in.
+ 		   Assume they are all increased by a constant offset,
+ 		   but in the same order as the HT nodeids.
+ 		   If that doesn't result in a usable node fall back to the
+ 		   path for the previous case.  */
+ 		int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+ 		if (ht_nodeid >= 0 &&
+ 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+ 			node = apicid_to_node[ht_nodeid];
+ 		/* Pick a nearby node */
+ 		if (!node_online(node))
+ 			node = nearby_node(apicid);
+ 	}
+  	cpu_to_node[cpu] = node;
 
-	printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
-			cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
+  	printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+  			cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
+#endif
 #endif
 }
 
@@ -909,6 +947,25 @@
 		return 1;
 }
 
+static void srat_detect_node(void)
+{
+#ifdef CONFIG_NUMA
+	unsigned apicid, node;
+	int cpu = smp_processor_id();
+
+	/* Don't do the funky fallback heuristics the AMD version employs
+	   for now. */
+	apicid = phys_proc_id[cpu];
+	node = apicid_to_node[apicid];
+	if (node == NUMA_NO_NODE)
+		node = 0;
+	cpu_to_node[cpu] = node;
+
+	if (acpi_numa > 0)
+		printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
+#endif
+}
+
 static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
 	/* Cache sizes */
@@ -927,6 +984,8 @@
 	if (c->x86 >= 15)
 		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
  	c->x86_num_cores = intel_num_cpu_cores(c);
+
+	srat_detect_node();
 }
 
 static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index e3ffcac..bd33be2 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -94,7 +94,7 @@
 		size = PERCPU_ENOUGH_ROOM;
 #endif
 
-	for (i = 0; i < NR_CPUS; i++) { 
+	for_each_cpu_mask (i, cpu_possible_map) {
 		char *ptr;
 
 		if (!NODE_DATA(cpu_to_node(i))) {
@@ -119,7 +119,6 @@
 	asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); 
 	wrmsrl(MSR_GS_BASE, cpu_pda + cpu);
 
-	pda->me = pda;
 	pda->cpunumber = cpu; 
 	pda->irqcount = -1;
 	pda->kernelstack = 
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index e595822..9db9dda 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
@@ -29,6 +28,8 @@
 #include <asm/proto.h>
 #include <asm/apicdef.h>
 
+#define __cpuinit __init
+
 /*
  *	Smarter SMP flushing macros. 
  *		c/o Linus Torvalds.
@@ -37,19 +38,41 @@
  *	writing to user space from interrupts. (Its not allowed anyway).
  *
  *	Optimizations Manfred Spraul <manfred@colorfullife.com>
+ *
+ * 	More scalable flush, from Andi Kleen
+ *
+ * 	To avoid global state use 8 different call vectors.
+ * 	Each CPU uses a specific vector to trigger flushes on other
+ * 	CPUs. Depending on the received vector the target CPUs look into
+ *	the right per cpu variable for the flush data.
+ *
+ * 	With more than 8 CPUs they are hashed to the 8 available
+ * 	vectors. The limited global vector space forces us to this right now.
+ *	In future when interrupts are split into per CPU domains this could be
+ *	fixed, at the cost of triggering multiple IPIs in some cases.
  */
 
-static cpumask_t flush_cpumask;
-static struct mm_struct * flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
+union smp_flush_state {
+	struct {
+		cpumask_t flush_cpumask;
+		struct mm_struct *flush_mm;
+		unsigned long flush_va;
 #define FLUSH_ALL	-1ULL
+		spinlock_t tlbstate_lock;
+	};
+	char pad[SMP_CACHE_BYTES];
+} ____cacheline_aligned;
+
+/* State is put into the per CPU data section, but padded
+   to a full cache line because other CPUs can access it and we don't
+   want false sharing in the per cpu data segment. */
+static DEFINE_PER_CPU(union smp_flush_state, flush_state);
 
 /*
  * We cannot call mmdrop() because we are in interrupt context, 
  * instead update mm->cpu_vm_mask.
  */
-static inline void leave_mm (unsigned long cpu)
+static inline void leave_mm(int cpu)
 {
 	if (read_pda(mmu_state) == TLBSTATE_OK)
 		BUG();
@@ -101,15 +124,25 @@
  *
  * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
  * 2) Leave the mm if we are in the lazy tlb mode.
+ *
+ * Interrupts are disabled.
  */
 
-asmlinkage void smp_invalidate_interrupt (void)
+asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
 {
-	unsigned long cpu;
+	int cpu;
+	int sender;
+	union smp_flush_state *f;
 
-	cpu = get_cpu();
+	cpu = smp_processor_id();
+	/*
+	 * orig_rax contains the interrupt vector - 256.
+	 * Use that to determine where the sender put the data.
+	 */
+	sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
+	f = &per_cpu(flush_state, sender);
 
-	if (!cpu_isset(cpu, flush_cpumask))
+	if (!cpu_isset(cpu, f->flush_cpumask))
 		goto out;
 		/* 
 		 * This was a BUG() but until someone can quote me the
@@ -120,64 +153,63 @@
 		 * BUG();
 		 */
 		 
-	if (flush_mm == read_pda(active_mm)) {
+	if (f->flush_mm == read_pda(active_mm)) {
 		if (read_pda(mmu_state) == TLBSTATE_OK) {
-			if (flush_va == FLUSH_ALL)
+			if (f->flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
-				__flush_tlb_one(flush_va);
+				__flush_tlb_one(f->flush_va);
 		} else
 			leave_mm(cpu);
 	}
 out:
 	ack_APIC_irq();
-	cpu_clear(cpu, flush_cpumask);
-	put_cpu_no_resched();
+	cpu_clear(cpu, f->flush_cpumask);
 }
 
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
 						unsigned long va)
 {
-	cpumask_t tmp;
-	/*
-	 * A couple of (to be removed) sanity checks:
-	 *
-	 * - we do not send IPIs to not-yet booted CPUs.
-	 * - current CPU must not be in mask
-	 * - mask must exist :)
-	 */
-	BUG_ON(cpus_empty(cpumask));
-	cpus_and(tmp, cpumask, cpu_online_map);
-	BUG_ON(!cpus_equal(tmp, cpumask));
-	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
-	if (!mm)
-		BUG();
+	int sender;
+	union smp_flush_state *f;
 
-	/*
-	 * I'm not happy about this global shared spinlock in the
-	 * MM hot path, but we'll see how contended it is.
-	 * Temporarily this turns IRQs off, so that lockups are
-	 * detected by the NMI watchdog.
-	 */
-	spin_lock(&tlbstate_lock);
-	
-	flush_mm = mm;
-	flush_va = va;
-	cpus_or(flush_cpumask, cpumask, flush_cpumask);
+	/* Caller has disabled preemption */
+	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+	f = &per_cpu(flush_state, sender);
+
+	/* Could avoid this lock when
+	   num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+	   probably not worth checking this for a cache-hot lock. */
+	spin_lock(&f->tlbstate_lock);
+
+	f->flush_mm = mm;
+	f->flush_va = va;
+	cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
 
 	/*
 	 * We have to send the IPI only to
 	 * CPUs affected.
 	 */
-	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
 
-	while (!cpus_empty(flush_cpumask))
-		mb();	/* nothing. lockup detection does not belong here */;
+	while (!cpus_empty(f->flush_cpumask))
+		cpu_relax();
 
-	flush_mm = NULL;
-	flush_va = 0;
-	spin_unlock(&tlbstate_lock);
+	f->flush_mm = NULL;
+	f->flush_va = 0;
+	spin_unlock(&f->tlbstate_lock);
 }
+
+int __cpuinit init_smp_flush(void)
+{
+	int i;
+	for_each_cpu_mask(i, cpu_possible_map) {
+		spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+	}
+	return 0;
+}
+
+core_initcall(init_smp_flush);
 	
 void flush_tlb_current_task(void)
 {
@@ -295,8 +327,11 @@
 /*
  * this function sends a 'generic call function' IPI to one other CPU
  * in the system.
+ *
+ * cpu is a standard Linux logical CPU number.
  */
-static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+static void
+__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 				int nonatomic, int wait)
 {
 	struct call_data_struct data;
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 4fb34b5..e12d7ba 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -44,7 +44,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-#include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
@@ -58,6 +57,8 @@
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -413,8 +414,13 @@
 
 	/*
 	 * Get our bogomips.
+ 	 *
+ 	 * Need to enable IRQs because it can take longer and then
+	 * the NMI watchdog might kill us.
 	 */
+	local_irq_enable();
 	calibrate_delay();
+	local_irq_disable();
 	Dprintk("Stack at about %p\n",&cpuid);
 
 	disable_APIC_timer();
@@ -540,8 +546,8 @@
 		 */
 		apic_wait_icr_idle();
 
-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+		apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
 
 		timeout = 0;
 		do {
@@ -574,12 +580,12 @@
 	/*
 	 * Turn INIT on target chip
 	 */
-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 	/*
 	 * Send IPI
 	 */
-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
 				| APIC_DM_INIT);
 
 	Dprintk("Waiting for send to finish...\n");
@@ -595,10 +601,10 @@
 	Dprintk("Deasserting INIT.\n");
 
 	/* Target chip */
-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 	/* Send IPI */
-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
 	Dprintk("Waiting for send to finish...\n");
 	timeout = 0;
@@ -610,16 +616,7 @@
 
 	atomic_set(&init_deasserted, 1);
 
-	/*
-	 * Should we send STARTUP IPIs ?
-	 *
-	 * Determine this based on the APIC version.
-	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
-	 */
-	if (APIC_INTEGRATED(apic_version[phys_apicid]))
-		num_starts = 2;
-	else
-		num_starts = 0;
+	num_starts = 2;
 
 	/*
 	 * Run STARTUP IPI loop.
@@ -640,12 +637,11 @@
 		 */
 
 		/* Target chip */
-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 		/* Boot on the stack */
 		/* Kick the second */
-		apic_write_around(APIC_ICR, APIC_DM_STARTUP
-					| (start_rip >> 12));
+		apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
 
 		/*
 		 * Give the other CPU some time to accept the IPI.
@@ -864,17 +860,6 @@
 	 * Reset trampoline flag
 	 */
 	*((volatile int *) phys_to_virt(0x467)) = 0;
-
-#ifndef CONFIG_HOTPLUG_CPU
-	/*
-	 * Free pages reserved for SMP bootup.
-	 * When you add hotplug CPU support later remove this
-	 * Note there is more work to be done for later CPU bootup.
-	 */
-
-	free_page((unsigned long) __va(PAGE_SIZE));
-	free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
-#endif
 }
 
 /*
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index 0612640..ebb9abf 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -8,23 +8,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/sysrq.h>
-#include <linux/proc_fs.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/device.h>
+#include <linux/smp.h>
 #include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/acpi.h>
-#include <asm/tlbflush.h>
-#include <asm/io.h>
 #include <asm/proto.h>
 
 struct saved_context saved_context;
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 7b6abe0..2373cb8 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -937,7 +936,6 @@
 	vxtime.mode = VXTIME_TSC;
 	vxtime.quot = (1000000L << 32) / vxtime_hz;
 	vxtime.tsc_quot = (1000L << 32) / cpu_khz;
-	vxtime.hz = vxtime_hz;
 	rdtscll_sync(&vxtime.last_tsc);
 	setup_irq(0, &irq0);
 
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index f238d60..b5e09e6 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -47,9 +47,6 @@
 #include <asm/proto.h>
 #include <asm/nmi.h>
 
-#include <linux/irq.h>
-
-
 extern struct gate_struct idt_table[256]; 
 
 asmlinkage void divide_error(void);
@@ -324,13 +321,13 @@
 	if (__copy_from_user(&f, (struct bug_frame *) regs->rip, 
 			     sizeof(struct bug_frame)))
 		return; 
-	if ((unsigned long)f.filename < __PAGE_OFFSET || 
+	if (f.filename >= 0 ||
 	    f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
 		return;
-	if (__get_user(tmp, f.filename))
-		f.filename = "unmapped filename"; 
+	if (__get_user(tmp, (char *)(long)f.filename))
+		f.filename = (int)(long)"unmapped filename";
 	printk("----------- [cut here ] --------- [please bite here ] ---------\n");
-	printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
+	printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
 } 
 
 #ifdef CONFIG_BUG
@@ -343,30 +340,33 @@
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 
-void oops_begin(void)
+unsigned long oops_begin(void)
 {
-	int cpu = safe_smp_processor_id(); 
-	/* racy, but better than risking deadlock. */ 
-	local_irq_disable();
+	int cpu = safe_smp_processor_id();
+	unsigned long flags;
+
+	/* racy, but better than risking deadlock. */
+	local_irq_save(flags);
 	if (!spin_trylock(&die_lock)) { 
 		if (cpu == die_owner) 
 			/* nested oops. should stop eventually */;
 		else
-			spin_lock(&die_lock); 
+			spin_lock(&die_lock);
 	}
-	die_owner = cpu; 
+	die_owner = cpu;
 	console_verbose();
-	bust_spinlocks(1); 
+	bust_spinlocks(1);
+	return flags;
 }
 
-void oops_end(void)
+void oops_end(unsigned long flags)
 { 
 	die_owner = -1;
-	bust_spinlocks(0); 
-	spin_unlock(&die_lock); 
+	bust_spinlocks(0);
+	spin_unlock_irqrestore(&die_lock, flags);
 	if (panic_on_oops)
-		panic("Oops"); 
-} 
+		panic("Oops");
+}
 
 void __die(const char * str, struct pt_regs * regs, long err)
 {
@@ -392,10 +392,11 @@
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	handle_BUG(regs);
 	__die(str, regs, err);
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGSEGV); 
 }
 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -406,7 +407,8 @@
 
 void die_nmi(char *str, struct pt_regs *regs)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	/*
 	 * We are in trouble anyway, lets at least try
 	 * to get a message out.
@@ -416,7 +418,7 @@
 	if (panic_on_timeout || panic_on_oops)
 		panic("nmi watchdog");
 	printk("console shuts up ...\n");
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGSEGV);
 }
 
@@ -790,13 +792,16 @@
 	 */
 	cwd = get_fpu_cwd(task);
 	swd = get_fpu_swd(task);
-	switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+	switch (swd & ~cwd & 0x3f) {
 		case 0x000:
 		default:
 			break;
 		case 0x001: /* Invalid Op */
-		case 0x041: /* Stack Fault */
-		case 0x241: /* Stack Fault | Direction */
+			/*
+			 * swd & 0x240 == 0x040: Stack Underflow
+			 * swd & 0x240 == 0x240: Stack Overflow
+			 * User must clear the SF bit (0x40) if set
+			 */
 			info.si_code = FPE_FLTINV;
 			break;
 		case 0x002: /* Denormalize */
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 2e57344..70a0bd1 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -107,7 +107,7 @@
 	return secs;
 }
 
-static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
 	if (unlikely(!__sysctl_vsyscall))
 		return gettimeofday(tv,tz);
@@ -120,7 +120,7 @@
 
 /* This will break when the xtime seconds get inaccurate, but that is
  * unlikely */
-static time_t __vsyscall(1) vtime(time_t *t)
+time_t __vsyscall(1) vtime(time_t *t)
 {
 	if (unlikely(!__sysctl_vsyscall))
 		return time_syscall(t);
@@ -129,12 +129,12 @@
 	return __xtime.tv_sec;
 }
 
-static long __vsyscall(2) venosys_0(void)
+long __vsyscall(2) venosys_0(void)
 {
 	return -ENOSYS;
 }
 
-static long __vsyscall(3) venosys_1(void)
+long __vsyscall(3) venosys_1(void)
 {
 	return -ENOSYS;
 }
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 816732d..b75b872 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -221,12 +221,13 @@
 static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
 				 unsigned long error_code)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
 	       current->comm, address);
 	dump_pagetable(address);
 	__die("Bad pagetable", regs, error_code);
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGKILL);
 }
 
@@ -304,6 +305,7 @@
 	unsigned long address;
 	const struct exception_table_entry *fixup;
 	int write;
+	unsigned long flags;
 	siginfo_t info;
 
 #ifdef CONFIG_CHECKING
@@ -521,7 +523,7 @@
  * terminate things with extreme prejudice.
  */
 
-	oops_begin(); 
+	flags = oops_begin();
 
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
@@ -534,7 +536,7 @@
 	__die("Oops", regs, error_code);
 	/* Executive summary in case the body of the oops scrolled away */
 	printk(KERN_EMERG "CR2: %016lx\n", address);
-	oops_end(); 
+	oops_end(flags);
 	do_exit(SIGKILL);
 
 /*
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index aa4a518..e60a1a8 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -57,31 +57,31 @@
 
 void show_mem(void)
 {
-	int i, total = 0, reserved = 0;
-	int shared = 0, cached = 0;
+	long i, total = 0, reserved = 0;
+	long shared = 0, cached = 0;
 	pg_data_t *pgdat;
 	struct page *page;
 
-	printk("Mem-info:\n");
+	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 
 	for_each_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
 			page = pfn_to_page(pgdat->node_start_pfn + i);
 			total++;
-                       if (PageReserved(page))
-			reserved++;
-                       else if (PageSwapCache(page))
-			cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (page_count(page))
+				shared += page_count(page) - 1;
                }
 	}
-	printk("%d pages of RAM\n", total);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
+	printk(KERN_INFO "%lu pages of RAM\n", total);
+	printk(KERN_INFO "%lu reserved pages\n",reserved);
+	printk(KERN_INFO "%lu pages shared\n",shared);
+	printk(KERN_INFO "%lu pages swap cached\n",cached);
 }
 
 /* References to section boundaries */
@@ -381,41 +381,14 @@
 	__flush_tlb_all();
 } 
 
-static inline int page_is_ram (unsigned long pagenr)
-{
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++) {
-		unsigned long addr, end;
-
-		if (e820.map[i].type != E820_RAM)	/* not usable memory */
-			continue;
-		/*
-		 *	!!!FIXME!!! Some BIOSen report areas as RAM that
-		 *	are not. Notably the 640->1Mb area. We need a sanity
-		 *	check here.
-		 */
-		addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
-		end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
-		if  ((pagenr >= addr) && (pagenr < end))
-			return 1;
-	}
-	return 0;
-}
-
-extern int swiotlb_force;
-
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
 			 kcore_vsyscall;
 
 void __init mem_init(void)
 {
-	int codesize, reservedpages, datasize, initsize;
-	int tmp;
+	long codesize, reservedpages, datasize, initsize;
 
 #ifdef CONFIG_SWIOTLB
-	if (swiotlb_force)
-		swiotlb = 1;
 	if (!iommu_aperture &&
 	    (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
 	       swiotlb = 1;
@@ -436,25 +409,11 @@
 
 	/* this will put all low memory onto the freelists */
 #ifdef CONFIG_NUMA
-	totalram_pages += numa_free_all_bootmem();
-	tmp = 0;
-	/* should count reserved pages here for all nodes */ 
+	totalram_pages = numa_free_all_bootmem();
 #else
-
-#ifdef CONFIG_FLATMEM
-	max_mapnr = end_pfn;
-	if (!mem_map) BUG();
+	totalram_pages = free_all_bootmem();
 #endif
-
-	totalram_pages += free_all_bootmem();
-
-	for (tmp = 0; tmp < end_pfn; tmp++)
-		/*
-		 * Only count reserved RAM pages
-		 */
-		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
-			reservedpages++;
-#endif
+	reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
 
 	after_bootmem = 1;
 
@@ -471,7 +430,7 @@
 	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 
 				 VSYSCALL_END - VSYSCALL_START);
 
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+	printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
 		end_pfn << (PAGE_SHIFT-10),
 		codesize >> 10,
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index ec35747..65417b0 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -45,10 +45,12 @@
 	unsigned long prevbase;
 	struct node nodes[8];
 	int nodeid, i, nb; 
+	unsigned char nodeids[8];
 	int found = 0;
 	u32 reg;
 	unsigned numnodes;
 	nodemask_t nodes_parsed;
+	unsigned dualcore = 0;
 
 	nodes_clear(nodes_parsed);
 
@@ -67,11 +69,15 @@
 	prevbase = 0;
 	for (i = 0; i < 8; i++) { 
 		unsigned long base,limit; 
-
+		u32 nodeid;
+		
+		/* Undefined before E stepping, but hopefully 0 */
+		dualcore |= ((read_pci_config(0, nb, 3, 0xe8) >> 12) & 3) == 1;
 		base = read_pci_config(0, nb, 1, 0x40 + i*8);
 		limit = read_pci_config(0, nb, 1, 0x44 + i*8);
 
 		nodeid = limit & 7; 
+		nodeids[i] = nodeid;
 		if ((base & 3) == 0) { 
 			if (i < numnodes)
 				printk("Skipping disabled node %d\n", i); 
@@ -157,8 +163,9 @@
 
 	for (i = 0; i < 8; i++) {
 		if (nodes[i].start != nodes[i].end) { 
-			/* assume 1:1 NODE:CPU */
-			cpu_to_node[i] = i; 
+			nodeid = nodeids[i];
+			apicid_to_node[nodeid << dualcore] = i;
+			apicid_to_node[(nodeid << dualcore) + dualcore] = i;
 			setup_node_bootmem(i, nodes[i].start, nodes[i].end); 
 		} 
 	}
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 04f7a33..80a49d9 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -28,8 +28,13 @@
 int memnode_shift;
 u8  memnodemap[NODEMAPSIZE];
 
-unsigned char cpu_to_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
-cpumask_t     node_to_cpumask[MAX_NUMNODES] __read_mostly;
+unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
+	[0 ... NR_CPUS-1] = NUMA_NO_NODE
+};
+unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+ 	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
 
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 8e3d097..4b2e844 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -20,14 +20,20 @@
 
 static struct acpi_table_slit *acpi_slit;
 
-/* Internal processor count */
-static unsigned int __initdata num_processors = 0;
-
 static nodemask_t nodes_parsed __initdata;
 static nodemask_t nodes_found __initdata;
 static struct node nodes[MAX_NUMNODES] __initdata;
 static __u8  pxm2node[256] = { [0 ... 255] = 0xff };
 
+static int node_to_pxm(int n);
+
+int pxm_to_node(int pxm)
+{
+	if ((unsigned)pxm >= 256)
+		return 0;
+	return pxm2node[pxm];
+}
+
 static __init int setup_node(int pxm)
 {
 	unsigned node = pxm2node[pxm];
@@ -44,14 +50,14 @@
 static __init int conflicting_nodes(unsigned long start, unsigned long end)
 {
 	int i;
-	for_each_online_node(i) {
+	for_each_node_mask(i, nodes_parsed) {
 		struct node *nd = &nodes[i];
 		if (nd->start == nd->end)
 			continue;
 		if (nd->end > start && nd->start < end)
-			return 1;
+			return i;
 		if (nd->end == end && nd->start == start)
-			return 1;
+			return i;
 	}
 	return -1;
 }
@@ -75,8 +81,11 @@
 
 static __init void bad_srat(void)
 {
+	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		apicid_to_node[i] = NUMA_NO_NODE;
 }
 
 static __init inline int srat_disabled(void)
@@ -104,18 +113,10 @@
 		bad_srat();
 		return;
 	}
-	if (num_processors >= NR_CPUS) {
-		printk(KERN_ERR "SRAT: Processor #%d (lapic %u) INVALID. (Max ID: %d).\n",
-			num_processors, pa->apic_id, NR_CPUS);
-		bad_srat();
-		return;
-	}
-	cpu_to_node[num_processors] = node;
+	apicid_to_node[pa->apic_id] = node;
 	acpi_numa = 1;
-	printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> CPU %u -> Node %u\n",
-	       pxm, pa->apic_id, num_processors, node);
-
-	num_processors++;
+	printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+	       pxm, pa->apic_id, node);
 }
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
@@ -143,10 +144,15 @@
 		printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
 				start, end);
 	i = conflicting_nodes(start, end);
-	if (i >= 0) {
+	if (i == node) {
+		printk(KERN_WARNING
+		"SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+			pxm, start, end, nodes[i].start, nodes[i].end);
+	} else if (i >= 0) {
 		printk(KERN_ERR
-		       "SRAT: pxm %d overlap %lx-%lx with node %d(%Lx-%Lx)\n",
-		       pxm, start, end, i, nodes[i].start, nodes[i].end);
+		       "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
+		       pxm, start, end, node_to_pxm(i),
+			nodes[i].start, nodes[i].end);
 		bad_srat();
 		return;
 	}
@@ -174,6 +180,14 @@
 	int i;
 	if (acpi_numa <= 0)
 		return -1;
+
+	/* First clean up the node list */
+	for_each_node_mask(i, nodes_parsed) {
+		cutoff_node(i, start, end);
+		if (nodes[i].start == nodes[i].end)
+			node_clear(i, nodes_parsed);
+	}
+
 	memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
 	if (memnode_shift < 0) {
 		printk(KERN_ERR
@@ -181,16 +195,10 @@
 		bad_srat();
 		return -1;
 	}
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (!node_isset(i, nodes_parsed))
-			continue;
-		cutoff_node(i, start, end);
-		if (nodes[i].start == nodes[i].end) { 
-			node_clear(i, nodes_parsed);
-			continue;
-		}
+
+	/* Finally register nodes */
+	for_each_node_mask(i, nodes_parsed)
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
 	for (i = 0; i < NR_CPUS; i++) { 
 		if (cpu_to_node[i] == NUMA_NO_NODE)
 			continue;
@@ -201,7 +209,7 @@
 	return 0;
 }
 
-int node_to_pxm(int n)
+static int node_to_pxm(int n)
 {
        int i;
        if (pxm2node[n] == n)
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index d80c323..3acf60d 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -58,10 +58,16 @@
 				for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
 				     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
 				     j++) { 
-					int node = NODE_ID(nid);
+					struct pci_bus *bus;
+					long node = NODE_ID(nid);
+					/* Algorithm a bit dumb, but
+ 					   it shouldn't matter here */
+					bus = pci_find_bus(0, j);
+					if (!bus)
+						continue;
 					if (!node_online(node))
 						node = 0;
-					pci_bus_to_node[j] = node;
+					bus->sysdata = (void *)node;
 				}		
 			}
 		}
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 657e88a..a0838c4 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -111,13 +111,6 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		return 0;
 
-	/* Kludge for now. Don't use mmconfig on AMD systems because
-	   those have some busses where mmconfig doesn't work,
-	   and we don't parse ACPI MCFG well enough to handle that. 
-	   Remove when proper handling is added. */
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-		return 0; 
-
 	/* RED-PEN i386 doesn't do _nocache right now */
 	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
 	if (pci_mmcfg_virt == NULL) {
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 373e7b7..6b2eb6f 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -152,12 +152,13 @@
 
 		if (!cont->match(cont, dev))
 			continue;
-		ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+		ic = kzalloc(sizeof(*ic), GFP_KERNEL);
 		if (!ic) {
 			dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
 			continue;
 		}
-		memset(ic, 0, sizeof(struct internal_container));
+
 		ic->cont = cont;
 		class_device_initialize(&ic->classdev);
 		ic->classdev.dev = get_device(dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d164c32..3b112e3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -189,12 +189,11 @@
 	struct class *cls;
 	int retval;
 
-	cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
 	if (!cls) {
 		retval = -ENOMEM;
 		goto error;
 	}
-	memset(cls, 0x00, sizeof(struct class));
 
 	cls->name = name;
 	cls->owner = owner;
@@ -500,13 +499,13 @@
 	/* add the needed attributes to this device */
 	if (MAJOR(class_dev->devt)) {
 		struct class_device_attribute *attr;
-		attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 		if (!attr) {
 			error = -ENOMEM;
 			kobject_del(&class_dev->kobj);
 			goto register_done;
 		}
-		memset(attr, sizeof(*attr), 0x00);
+
 		attr->attr.name = "dev";
 		attr->attr.mode = S_IRUGO;
 		attr->attr.owner = parent->owner;
@@ -577,12 +576,11 @@
 	if (cls == NULL || IS_ERR(cls))
 		goto error;
 
-	class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+	class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
 	if (!class_dev) {
 		retval = -ENOMEM;
 		goto error;
 	}
-	memset(class_dev, 0x00, sizeof(struct class_device));
 
 	class_dev->devt = devt;
 	class_dev->dev = device;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 5bfa2e9..4acb2c5 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -301,9 +301,9 @@
 			 const char *fw_name, struct device *device)
 {
 	int retval;
-	struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+	struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
 						GFP_KERNEL);
-	struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+	struct class_device *class_dev = kzalloc(sizeof(*class_dev),
 						 GFP_KERNEL);
 
 	*class_dev_p = NULL;
@@ -313,8 +313,6 @@
 		retval = -ENOMEM;
 		goto error_kfree;
 	}
-	memset(fw_priv, 0, sizeof (*fw_priv));
-	memset(class_dev, 0, sizeof (*class_dev));
 
 	init_completion(&fw_priv->completion);
 	fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -402,14 +400,13 @@
 	if (!firmware_p)
 		return -EINVAL;
 
-	*firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+	*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
 	if (!firmware) {
 		printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
 		       __FUNCTION__);
 		retval = -ENOMEM;
 		goto out;
 	}
-	memset(firmware, 0, sizeof (*firmware));
 
 	retval = fw_setup_class_device(firmware, &class_dev, name, device,
 		hotplug);
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 2f455d8..b449dae 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -135,7 +135,7 @@
 struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
 {
 	struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
-	struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+	struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
 	int i;
 
 	if ((p == NULL) || (base == NULL)) {
@@ -144,7 +144,6 @@
 		return NULL;
 	}
 
-	memset(base, 0, sizeof(struct probe));
 	base->dev = 1;
 	base->range = ~0;
 	base->get = base_probe;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3a5f4c9..361e204 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -225,13 +225,12 @@
 	struct platform_object *pobj;
 	int retval;
 
-	pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+	pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);
 	if (!pobj) {
 		retval = -ENOMEM;
 		goto error;
 	}
 
-	memset(pobj, 0, sizeof(*pobj));
 	pobj->pdev.name = name;
 	pobj->pdev.id = id;
 	pobj->pdev.dev.release = platform_device_release_simple;
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 721ba80..0e9e586 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2004 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "10"
+#define VERSION "12"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -7,12 +7,12 @@
  * default is 16, which is 15 partitions plus the whole disk
  */
 #ifndef AOE_PARTITIONS
-#define AOE_PARTITIONS 16
+#define AOE_PARTITIONS (16)
 #endif
 
-#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor))
-#define AOEMAJOR(sysminor) ((sysminor) / 10)
-#define AOEMINOR(sysminor) ((sysminor) % 10)
+#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor))
+#define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF)
+#define AOEMINOR(sysminor) ((sysminor) % NPERSHELF)
 #define WHITESPACE " \t\v\f\n"
 
 enum {
@@ -83,7 +83,7 @@
 
 enum {
 	MAXATADATA = 1024,
-	NPERSHELF = 10,
+	NPERSHELF = 16,		/* number of slots per shelf address */
 	FREETAG = -1,
 	MIN_BUFS = 8,
 };
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 28f2c17..c56f995 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -47,14 +47,14 @@
 #include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.8)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
 MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
-			" SA6i P600 P800 E400 E300");
+			" SA6i P600 P800 P400 P400i E200 E200i");
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -83,12 +83,22 @@
 		0x0E11, 0x4091, 0, 0, 0},
 	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
 		0x103C, 0x3225, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
 		0x103c, 0x3223, 0, 0, 0},
 	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
-		0x103c, 0x3231, 0, 0, 0},
+		0x103c, 0x3234, 0, 0, 0},
 	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
-		0x103c, 0x3233, 0, 0, 0},
+		0x103c, 0x3235, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+		0x103c, 0x3211, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+		0x103c, 0x3212, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+		0x103c, 0x3213, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+		0x103c, 0x3214, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+		0x103c, 0x3215, 0, 0, 0},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -111,8 +121,13 @@
 	{ 0x40910E11, "Smart Array 6i", &SA5_access},
 	{ 0x3225103C, "Smart Array P600", &SA5_access},
 	{ 0x3223103C, "Smart Array P800", &SA5_access},
-	{ 0x3231103C, "Smart Array E400", &SA5_access},
-	{ 0x3233103C, "Smart Array E300", &SA5_access},
+	{ 0x3234103C, "Smart Array P400", &SA5_access},
+	{ 0x3235103C, "Smart Array P400i", &SA5_access},
+	{ 0x3211103C, "Smart Array E200i", &SA5_access},
+	{ 0x3212103C, "Smart Array E200", &SA5_access},
+	{ 0x3213103C, "Smart Array E200i", &SA5_access},
+	{ 0x3214103C, "Smart Array E200i", &SA5_access},
+	{ 0x3215103C, "Smart Array E200i", &SA5_access},
 };
 
 /* How long to wait (in millesconds) for board to go into simple mode */
@@ -140,15 +155,26 @@
 
 static int revalidate_allvol(ctlr_info_t *host);
 static int cciss_revalidate(struct gendisk *disk);
-static int deregister_disk(struct gendisk *disk);
-static int register_new_disk(ctlr_info_t *h);
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
 
+static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+	int withirq, unsigned int *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+			int withirq, unsigned int total_size,
+			unsigned int block_size, InquiryData_struct *inq_buff,
+			drive_info_struct *drv);
 static void cciss_getgeometry(int cntl_num);
 
 static void start_io( ctlr_info_t *h);
 static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
 	unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
 	unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8	cmd, int ctlr, void *buff, size_t size,
+	unsigned int use_unit_num, unsigned int log_unit, __u8	page_code,
+	int cmd_type);
+
+static void fail_all_cmds(unsigned long ctlr);
 
 #ifdef CONFIG_PROC_FS
 static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
@@ -265,7 +291,7 @@
 	for(i=0; i<=h->highest_lun; i++) {
 
                 drv = &h->drv[i];
-		if (drv->block_size == 0)
+		if (drv->heads == 0)
 			continue;
 
 		vol_sz = drv->nr_blocks;
@@ -363,6 +389,8 @@
                  	return NULL;
 		memset(c, 0, sizeof(CommandList_struct));
 
+		c->cmdindex = -1;
+
 		c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
 					h->pdev, sizeof(ErrorInfo_struct), 
 					&err_dma_handle);
@@ -393,6 +421,8 @@
 		err_dma_handle = h->errinfo_pool_dhandle 
 					+ i*sizeof(ErrorInfo_struct);
                 h->nr_allocs++;
+
+		c->cmdindex = i;
         }
 
 	c->busaddr = (__u32) cmd_dma_handle;
@@ -453,6 +483,11 @@
 	printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
 #endif /* CCISS_DEBUG */ 
 
+	if (host->busy_initializing)
+		return -EBUSY;
+
+	if (host->busy_initializing || drv->busy_configuring)
+		return -EBUSY;
 	/*
 	 * Root is allowed to open raw volume zero even if it's not configured
 	 * so array config can still work. Root is also allowed to open any
@@ -796,10 +831,10 @@
  		return(0);
  	}
 	case CCISS_DEREGDISK:
-		return deregister_disk(disk);
+		return rebuild_lun_table(host, disk);
 
 	case CCISS_REGNEWD:
-		return register_new_disk(host);
+		return rebuild_lun_table(host, NULL);
 
 	case CCISS_PASSTHRU:
 	{
@@ -1143,48 +1178,323 @@
         return 0;
 }
 
-static int deregister_disk(struct gendisk *disk)
+/* This function will check the usage_count of the drive to be updated/added.
+ * If the usage_count is zero then the drive information will be updated and
+ * the disk will be re-registered with the kernel.  If not then it will be
+ * left alone for the next reboot.  The exception to this is disk 0 which
+ * will always be left registered with the kernel since it is also the
+ * controller node.  Any changes to disk 0 will show up on the next
+ * reboot.
+*/
+static void cciss_update_drive_info(int ctlr, int drv_index)
+  {
+	ctlr_info_t *h = hba[ctlr];
+	struct gendisk *disk;
+	ReadCapdata_struct *size_buff = NULL;
+	InquiryData_struct *inq_buff = NULL;
+	unsigned int block_size;
+	unsigned int total_size;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	/* if the disk already exists then deregister it before proceeding*/
+	if (h->drv[drv_index].raid_level != -1){
+		spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+		h->drv[drv_index].busy_configuring = 1;
+		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+		ret = deregister_disk(h->gendisk[drv_index],
+			&h->drv[drv_index], 0);
+		h->drv[drv_index].busy_configuring = 0;
+	}
+
+	/* If the disk is in use return */
+	if (ret)
+		return;
+
+
+	/* Get information about the disk and modify the driver sturcture */
+	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
+        if (size_buff == NULL)
+		goto mem_msg;
+	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+	if (inq_buff == NULL)
+		goto mem_msg;
+
+	cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+		&total_size, &block_size);
+	cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+		inq_buff, &h->drv[drv_index]);
+
+	++h->num_luns;
+	disk = h->gendisk[drv_index];
+	set_capacity(disk, h->drv[drv_index].nr_blocks);
+
+
+	/* if it's the controller it's already added */
+	if (drv_index){
+		disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+
+		/* Set up queue information */
+		disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
+		blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
+
+		/* This is a hardware imposed limit. */
+		blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+
+		/* This is a limit in the driver and could be eliminated. */
+		blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+
+		blk_queue_max_sectors(disk->queue, 512);
+
+		disk->queue->queuedata = hba[ctlr];
+
+		blk_queue_hardsect_size(disk->queue,
+			hba[ctlr]->drv[drv_index].block_size);
+
+		h->drv[drv_index].queue = disk->queue;
+		add_disk(disk);
+	}
+
+freeret:
+	kfree(size_buff);
+	kfree(inq_buff);
+	return;
+mem_msg:
+	printk(KERN_ERR "cciss: out of memory\n");
+	goto freeret;
+}
+
+/* This function will find the first index of the controllers drive array
+ * that has a -1 for the raid_level and will return that index.  This is
+ * where new drives will be added.  If the index to be returned is greater
+ * than the highest_lun index for the controller then highest_lun is set
+ * to this new index.  If there are no available indexes then -1 is returned.
+*/
+static int cciss_find_free_drive_index(int ctlr)
 {
-	unsigned long flags;
-	ctlr_info_t *h = get_host(disk);
-	drive_info_struct *drv = get_drv(disk);
+	int i;
+
+	for (i=0; i < CISS_MAX_LUN; i++){
+		if (hba[ctlr]->drv[i].raid_level == -1){
+			if (i > hba[ctlr]->highest_lun)
+				hba[ctlr]->highest_lun = i;
+			return i;
+		}
+	}
+	return -1;
+}
+
+/* This function will add and remove logical drives from the Logical
+ * drive array of the controller and maintain persistancy of ordering
+ * so that mount points are preserved until the next reboot.  This allows
+ * for the removal of logical drives in the middle of the drive array
+ * without a re-ordering of those drives.
+ * INPUT
+ * h		= The controller to perform the operations on
+ * del_disk	= The disk to remove if specified.  If the value given
+ *		  is NULL then no disk is removed.
+*/
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
+{
 	int ctlr = h->ctlr;
+	int num_luns;
+	ReportLunData_struct *ld_buff = NULL;
+	drive_info_struct *drv = NULL;
+	int return_code;
+	int listlength = 0;
+	int i;
+	int drv_found;
+	int drv_index = 0;
+	__u32 lunid = 0;
+	unsigned long flags;
+
+	/* Set busy_configuring flag for this operation */
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+	if (h->num_luns >= CISS_MAX_LUN){
+		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+		return -EINVAL;
+	}
+
+	if (h->busy_configuring){
+		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+		return -EBUSY;
+	}
+	h->busy_configuring = 1;
+
+	/* if del_disk is NULL then we are being called to add a new disk
+	 * and update the logical drive table.  If it is not NULL then
+	 * we will check if the disk is in use or not.
+	 */
+	if (del_disk != NULL){
+		drv = get_drv(del_disk);
+		drv->busy_configuring = 1;
+		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+		return_code = deregister_disk(del_disk, drv, 1);
+		drv->busy_configuring = 0;
+		h->busy_configuring = 0;
+		return return_code;
+	} else {
+		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+
+		ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+		if (ld_buff == NULL)
+			goto mem_msg;
+
+		return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
+				sizeof(ReportLunData_struct), 0, 0, 0,
+				TYPE_CMD);
+
+		if (return_code == IO_OK){
+			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
+			listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+		} else{ /* reading number of logical volumes failed */
+			printk(KERN_WARNING "cciss: report logical volume"
+				" command failed\n");
+			listlength = 0;
+			goto freeret;
+		}
+
+		num_luns = listlength / 8;	/* 8 bytes per entry */
+		if (num_luns > CISS_MAX_LUN){
+			num_luns = CISS_MAX_LUN;
+			printk(KERN_WARNING "cciss: more luns configured"
+				" on controller than can be handled by"
+				" this driver.\n");
+		}
+
+		/* Compare controller drive array to drivers drive array.
+	 	* Check for updates in the drive information and any new drives
+	 	* on the controller.
+	 	*/
+		for (i=0; i < num_luns; i++){
+			int j;
+
+			drv_found = 0;
+
+	  		lunid = (0xff &
+				(unsigned int)(ld_buff->LUN[i][3])) << 24;
+        		lunid |= (0xff &
+				(unsigned int)(ld_buff->LUN[i][2])) << 16;
+        		lunid |= (0xff &
+				(unsigned int)(ld_buff->LUN[i][1])) << 8;
+        		lunid |= 0xff &
+				(unsigned int)(ld_buff->LUN[i][0]);
+
+			/* Find if the LUN is already in the drive array
+			 * of the controller.  If so then update its info
+			 * if not is use.  If it does not exist then find
+			 * the first free index and add it.
+			*/
+			for (j=0; j <= h->highest_lun; j++){
+				if (h->drv[j].LunID == lunid){
+					drv_index = j;
+					drv_found = 1;
+				}
+			}
+
+			/* check if the drive was found already in the array */
+			if (!drv_found){
+				drv_index = cciss_find_free_drive_index(ctlr);
+				if (drv_index == -1)
+					goto freeret;
+
+			}
+			h->drv[drv_index].LunID = lunid;
+			cciss_update_drive_info(ctlr, drv_index);
+		} /* end for */
+	} /* end else */
+
+freeret:
+	kfree(ld_buff);
+	h->busy_configuring = 0;
+	/* We return -1 here to tell the ACU that we have registered/updated
+	 * all of the drives that we can and to keep it from calling us
+	 * additional times.
+	*/
+	return -1;
+mem_msg:
+	printk(KERN_ERR "cciss: out of memory\n");
+	goto freeret;
+}
+
+/* This function will deregister the disk and it's queue from the
+ * kernel.  It must be called with the controller lock held and the
+ * drv structures busy_configuring flag set.  It's parameters are:
+ *
+ * disk = This is the disk to be deregistered
+ * drv  = This is the drive_info_struct associated with the disk to be
+ *        deregistered.  It contains information about the disk used
+ *        by the driver.
+ * clear_all = This flag determines whether or not the disk information
+ *             is going to be completely cleared out and the highest_lun
+ *             reset.  Sometimes we want to clear out information about
+ *             the disk in preperation for re-adding it.  In this case
+ *             the highest_lun should be left unchanged and the LunID
+ *             should not be cleared.
+*/
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+			   int clear_all)
+{
+	ctlr_info_t *h = get_host(disk);
 
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
-	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 	/* make sure logical volume is NOT is use */
-	if( drv->usage_count > 1) {
-		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+	if(clear_all || (h->gendisk[0] == disk)) {
+	if (drv->usage_count > 1)
                 return -EBUSY;
 	}
-	drv->usage_count++;
-	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+        else
+        	if( drv->usage_count > 0 )
+                	return -EBUSY;
 
-	/* invalidate the devices and deregister the disk */ 
-	if (disk->flags & GENHD_FL_UP)
+	/* invalidate the devices and deregister the disk.  If it is disk
+	 * zero do not deregister it but just zero out it's values.  This
+	 * allows us to delete disk zero but keep the controller registered.
+	*/
+	if (h->gendisk[0] != disk){
+		if (disk->flags & GENHD_FL_UP){
+			blk_cleanup_queue(disk->queue);
 		del_gendisk(disk);
+			drv->queue = NULL;
+		}
+	}
+
+	--h->num_luns;
+	/* zero out the disk size info */
+	drv->nr_blocks = 0;
+	drv->block_size = 0;
+	drv->heads = 0;
+	drv->sectors = 0;
+	drv->cylinders = 0;
+	drv->raid_level = -1;	/* This can be used as a flag variable to
+				 * indicate that this element of the drive
+				 * array is free.
+				*/
+
+	if (clear_all){
 	/* check to see if it was the last disk */
 	if (drv == h->drv + h->highest_lun) {
 		/* if so, find the new hightest lun */
 		int i, newhighest =-1;
 		for(i=0; i<h->highest_lun; i++) {
 			/* if the disk has size > 0, it is available */
-			if (h->drv[i].nr_blocks)
+				if (h->drv[i].heads)
 				newhighest = i;
 		}
 		h->highest_lun = newhighest;
-				
 	}
-	--h->num_luns;
-	/* zero out the disk size info */ 
-	drv->nr_blocks = 0;
-	drv->block_size = 0;
-	drv->cylinders = 0;
+
 	drv->LunID = 0;
+	}
 	return(0);
 }
+
 static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
 	size_t size,
 	unsigned int use_unit_num, /* 0: address the controller,
@@ -1420,8 +1730,10 @@
 		}
 	}	
 	/* unlock the buffers from DMA */
+	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
 	pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
-			size, PCI_DMA_BIDIRECTIONAL);
+			c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
 	cmd_free(h, c, 0);
         return(return_status);
 
@@ -1495,164 +1807,6 @@
 	return;
 }
 
-static int register_new_disk(ctlr_info_t *h)
-{
-        struct gendisk *disk;
-	int ctlr = h->ctlr;
-        int i;
-	int num_luns;
-	int logvol;
-	int new_lun_found = 0;
-	int new_lun_index = 0;
-	int free_index_found = 0;
-	int free_index = 0;
-	ReportLunData_struct *ld_buff = NULL;
-	ReadCapdata_struct *size_buff = NULL;
-	InquiryData_struct *inq_buff = NULL;
-	int return_code;
-	int listlength = 0;
-	__u32 lunid = 0;
-	unsigned int block_size;
-	unsigned int total_size;
-
-        if (!capable(CAP_SYS_RAWIO))
-                return -EPERM;
-	/* if we have no space in our disk array left to add anything */
-	if(  h->num_luns >= CISS_MAX_LUN)
-		return -EINVAL;
-	
-	ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
-	if (ld_buff == NULL)
-		goto mem_msg;
-	memset(ld_buff, 0, sizeof(ReportLunData_struct));
-	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
-        if (size_buff == NULL)
-		goto mem_msg;
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
-        if (inq_buff == NULL)
-		goto mem_msg;
-	
-	return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, 
-			sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
-
-	if( return_code == IO_OK)
-	{
-		
-		// printk("LUN Data\n--------------------------\n");
-
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;	
-		listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
-	} else /* reading number of logical volumes failed */
-	{
-		printk(KERN_WARNING "cciss: report logical volume"
-			" command failed\n");
-		listlength = 0;
-		goto free_err;
-	}
-	num_luns = listlength / 8; // 8 bytes pre entry
-	if (num_luns > CISS_MAX_LUN)
-	{
-		num_luns = CISS_MAX_LUN;
-	}
-#ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
-		ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
-		ld_buff->LUNListLength[3],  num_luns);
-#endif 
-	for(i=0; i<  num_luns; i++)
-	{
-		int j;
-		int lunID_found = 0;
-
-	  	lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
-        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
-        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
-        	lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-		
- 		/* check to see if this is a new lun */ 
-		for(j=0; j <= h->highest_lun; j++)
-		{
-#ifdef CCISS_DEBUG
-			printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
-						lunid);
-#endif /* CCISS_DEBUG */
-			if (h->drv[j].LunID == lunid)
-			{
-				lunID_found = 1;
-				break;
-			}
-			
-		}
-		if( lunID_found == 1)
-			continue;
-		else
-		{	/* It is the new lun we have been looking for */
-#ifdef CCISS_DEBUG
-			printk("new lun found at %d\n", i);
-#endif /* CCISS_DEBUG */
-			new_lun_index = i;
-			new_lun_found = 1;
-			break;	
-		}
-	 }
-	 if (!new_lun_found)
-	 {
-		printk(KERN_WARNING "cciss:  New Logical Volume not found\n");
-		goto free_err;
-	 }
-	 /* Now find the free index 	*/
-	for(i=0; i <CISS_MAX_LUN; i++)
-	{
-#ifdef CCISS_DEBUG
-		printk("Checking Index %d\n", i);
-#endif /* CCISS_DEBUG */
-		if(h->drv[i].LunID == 0)
-		{
-#ifdef CCISS_DEBUG
-			printk("free index found at %d\n", i);
-#endif /* CCISS_DEBUG */
-			free_index_found = 1;
-			free_index = i;
-			break;
-		}
-	}
-	if (!free_index_found)
-	{
-		printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
-		goto free_err;
-         }
-
-	logvol = free_index;
-	h->drv[logvol].LunID = lunid;
-		/* there could be gaps in lun numbers, track hightest */
-	if(h->highest_lun < lunid)
-		h->highest_lun = logvol;
-	cciss_read_capacity(ctlr, logvol, size_buff, 1,
-		&total_size, &block_size);
-	cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
-			inq_buff, &h->drv[logvol]);
-	h->drv[logvol].usage_count = 0;
-	++h->num_luns;
-	/* setup partitions per disk */
-        disk = h->gendisk[logvol];
-	set_capacity(disk, h->drv[logvol].nr_blocks);
-	/* if it's the controller it's already added */
-	if(logvol)
-		add_disk(disk);
-freeret:
-	kfree(ld_buff);
-	kfree(size_buff);
-	kfree(inq_buff);
-	return (logvol);
-mem_msg:
-	printk(KERN_ERR "cciss: out of memory\n");
-free_err:
-	logvol = -1;
-	goto freeret;
-}
-
 static int cciss_revalidate(struct gendisk *disk)
 {
 	ctlr_info_t *h = get_host(disk);
@@ -1859,8 +2013,10 @@
 		
 cleanup1:	
 	/* unlock the data buffer from DMA */
+	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
 	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
-				size, PCI_DMA_BIDIRECTIONAL);
+				c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
 	cmd_free(info_p, c, 1);
 	return (status);
 } 
@@ -2111,7 +2267,11 @@
 	/* fill in the request */ 
 	drv = creq->rq_disk->private_data;
 	c->Header.ReplyQueue = 0;  // unused in simple mode
-	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
+	/* got command from pool, so use the command block index instead */
+	/* for direct lookups. */
+	/* The first 2 bits are reserved for controller error reporting. */
+	c->Header.Tag.lower = (c->cmdindex << 3);
+	c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
 	c->Header.LUN.LogDev.VolId= drv->LunID;
 	c->Header.LUN.LogDev.Mode = 1;
 	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
@@ -2186,7 +2346,7 @@
 	ctlr_info_t *h = dev_id;
 	CommandList_struct *c;
 	unsigned long flags;
-	__u32 a, a1;
+	__u32 a, a1, a2;
 	int j;
 	int start_queue = h->next_to_run;
 
@@ -2204,10 +2364,21 @@
 		while((a = h->access.command_completed(h)) != FIFO_EMPTY) 
 		{
 			a1 = a;
+			if ((a & 0x04)) {
+				a2 = (a >> 3);
+				if (a2 >= NR_CMDS) {
+					printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+					fail_all_cmds(h->ctlr);
+					return IRQ_HANDLED;
+				}
+
+				c = h->cmd_pool + a2;
+				a = c->busaddr;
+
+			} else {
 			a &= ~3;
-			if ((c = h->cmpQ) == NULL)
-			{  
-				printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
+				if ((c = h->cmpQ) == NULL) {
+					printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
 				continue;	
 			} 
 			while(c->busaddr != a) {
@@ -2215,6 +2386,7 @@
 				if (c == h->cmpQ) 
 					break;
 			}
+			}
 			/*
 			 * If we've found the command, take it off the
 			 * completion Q and free it
@@ -2634,12 +2806,16 @@
 #endif /* CCISS_DEBUG */
 
 	hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
-	for(i=0; i<  hba[cntl_num]->num_luns; i++)
+//	for(i=0; i<  hba[cntl_num]->num_luns; i++)
+	for(i=0; i < CISS_MAX_LUN; i++)
 	{
-
-	  	lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
-        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
-        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
+		if (i < hba[cntl_num]->num_luns){
+		  	lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+				 << 24;
+        		lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+				 << 16;
+        		lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+				 << 8;
         	lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
 		
 		hba[cntl_num]->drv[i].LunID = lunid;
@@ -2647,13 +2823,18 @@
 
 #ifdef CCISS_DEBUG
 	  	printk(KERN_DEBUG "LUN[%d]:  %x %x %x %x = %x\n", i, 
-		ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], 
-		ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
+			ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+			ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+			hba[cntl_num]->drv[i].LunID);
 #endif /* CCISS_DEBUG */
 		cciss_read_capacity(cntl_num, i, size_buff, 0,
 			&total_size, &block_size);
-		cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
-			inq_buff, &hba[cntl_num]->drv[i]);
+			cciss_geometry_inquiry(cntl_num, i, 0, total_size,
+				block_size, inq_buff, &hba[cntl_num]->drv[i]);
+		} else {
+			/* initialize raid_level to indicate a free space */
+			hba[cntl_num]->drv[i].raid_level = -1;
+		}
 	}
 	kfree(ld_buff);
 	kfree(size_buff);
@@ -2727,6 +2908,9 @@
 	i = alloc_cciss_hba();
 	if(i < 0)
 		return (-1);
+
+	hba[i]->busy_initializing = 1;
+
 	if (cciss_pci_init(hba[i], pdev) != 0)
 		goto clean1;
 
@@ -2849,6 +3033,7 @@
 		add_disk(disk);
 	}
 
+	hba[i]->busy_initializing = 0;
 	return(1);
 
 clean4:
@@ -2869,6 +3054,7 @@
 clean1:
 	release_io_mem(hba[i]);
 	free_hba(i);
+	hba[i]->busy_initializing = 0;
 	return(-1);
 }
 
@@ -2913,9 +3099,10 @@
 	/* remove it from the disk list */
 	for (j = 0; j < NWD; j++) {
 		struct gendisk *disk = hba[i]->gendisk[j];
-		if (disk->flags & GENHD_FL_UP)
-			blk_cleanup_queue(disk->queue);
+		if (disk->flags & GENHD_FL_UP) {
 			del_gendisk(disk);
+			blk_cleanup_queue(disk->queue);
+		}
 	}
 
 	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
@@ -2964,5 +3151,43 @@
 	remove_proc_entry("cciss", proc_root_driver);
 }
 
+static void fail_all_cmds(unsigned long ctlr)
+{
+	/* If we get here, the board is apparently dead. */
+	ctlr_info_t *h = hba[ctlr];
+	CommandList_struct *c;
+	unsigned long flags;
+
+	printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
+	h->alive = 0;	/* the controller apparently died... */
+
+	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+	pci_disable_device(h->pdev); /* Make sure it is really dead. */
+
+	/* move everything off the request queue onto the completed queue */
+	while( (c = h->reqQ) != NULL ) {
+		removeQ(&(h->reqQ), c);
+		h->Qdepth--;
+		addQ (&(h->cmpQ), c);
+	}
+
+	/* Now, fail everything on the completed queue with a HW error */
+	while( (c = h->cmpQ) != NULL ) {
+		removeQ(&h->cmpQ, c);
+		c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+		if (c->cmd_type == CMD_RWREQ) {
+			complete_command(h, c, 0);
+		} else if (c->cmd_type == CMD_IOCTL_PEND)
+			complete(c->waiting);
+#ifdef CONFIG_CISS_SCSI_TAPE
+			else if (c->cmd_type == CMD_SCSI)
+				complete_scsi_command(c, 0, 0);
+#endif
+	}
+	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+	return;
+}
+
 module_init(cciss_init);
 module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 566587d..ef277ba 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@
 	int 	heads;
 	int	sectors;
 	int 	cylinders;
-	int	raid_level;
+	int	raid_level; /* set to -1 to indicate that
+			     * the drive is not in use/configured
+			    */
+	int	busy_configuring; /*This is set when the drive is being removed
+				   *to prevent it from being opened or it's queue
+				   *from being started.
+				  */
 } drive_info_struct;
 
 struct ctlr_info 
@@ -83,6 +89,7 @@
 	int			nr_allocs;
 	int			nr_frees; 
 	int			busy_configuring;
+	int			busy_initializing;
 
 	/* This element holds the zero based queue number of the last
 	 * queue to be started.  It is used for fairness.
@@ -94,6 +101,7 @@
 #ifdef CONFIG_CISS_SCSI_TAPE
 	void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
 #endif
+	unsigned char alive;
 };
 
 /*  Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a888..53fea54 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@
 #define CMD_MSG_DONE	0x04
 #define CMD_MSG_TIMEOUT 0x05
 
+/* This structure needs to be divisible by 8 for new
+ * indexing method.
+ */
+#define PADSIZE (sizeof(long) - 4)
 typedef struct _CommandList_struct {
   CommandListHeader_struct Header;
   RequestBlock_struct      Request;
@@ -236,14 +240,14 @@
   ErrorInfo_struct * 	   err_info; /* pointer to the allocated mem */ 
   int			   ctlr;
   int			   cmd_type; 
+  long			   cmdindex;
   struct _CommandList_struct *prev;
   struct _CommandList_struct *next;
   struct request *	   rq;
   struct completion *waiting;
   int	 retry_count;
-#ifdef CONFIG_CISS_SCSI_TAPE
   void * scsi_cmd;
-#endif
+  char   pad[PADSIZE];
 } CommandList_struct;
 
 //Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3ca..e183a3e 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@
 	CommandList_struct cmd;
 	ErrorInfo_struct Err;
 	__u32 busaddr;
+	__u32 pad;
 };
 
 #pragma pack()
@@ -877,7 +878,7 @@
 
 static int
 cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 
-		 InquiryData_struct *buf)
+		 unsigned char *buf, unsigned char bufsize)
 {
 	int rc;
 	CommandList_struct *cp;
@@ -900,11 +901,10 @@
 	cdb[1] = 0;
 	cdb[2] = 0;
 	cdb[3] = 0;
-	cdb[4] = sizeof(*buf) & 0xff;
+	cdb[4] = bufsize;
 	cdb[5] = 0;
 	rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, 
-				6, (unsigned char *) buf, 
-				sizeof(*buf), XFER_READ);
+				6, buf, bufsize, XFER_READ);
 
 	if (rc != 0) return rc; /* something went wrong */
 
@@ -1000,9 +1000,10 @@
 	   that though.  
 
 	 */
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
 	ReportLunData_struct *ld_buff;
-	InquiryData_struct *inq_buff;
+	unsigned char *inq_buff;
 	unsigned char scsi3addr[8];
 	ctlr_info_t *c;
 	__u32 num_luns=0;
@@ -1020,7 +1021,7 @@
 		return;
 	}
 	memset(ld_buff, 0, reportlunsize);
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+	inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
         if (inq_buff == NULL) {
                 printk(KERN_ERR "cciss: out of memory\n");
                 kfree(ld_buff);
@@ -1051,19 +1052,36 @@
 
 		/* for each physical lun, do an inquiry */
 		if (ld_buff->LUN[i][3] & 0xC0) continue;
-		memset(inq_buff, 0, sizeof(InquiryData_struct));
+		memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
 		memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
 
-		if (cciss_scsi_do_inquiry(hba[cntl_num], 
-			scsi3addr, inq_buff) != 0)
-		{
+		if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
+			(unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
 			/* Inquiry failed (msg printed already) */
 			devtype = 0; /* so we will skip this device. */
 		} else /* what kind of device is this? */
-			devtype = (inq_buff->data_byte[0] & 0x1f);
+			devtype = (inq_buff[0] & 0x1f);
 
 		switch (devtype)
 		{
+		  case 0x05: /* CD-ROM */ {
+
+			/* We don't *really* support actual CD-ROM devices,
+			 * just this "One Button Disaster Recovery" tape drive
+			 * which temporarily pretends to be a CD-ROM drive.
+			 * So we check that the device is really an OBDR tape
+			 * device by checking for "$DR-10" in bytes 43-48 of
+			 * the inquiry data.
+			 */
+				char obdr_sig[7];
+
+				strncpy(obdr_sig, &inq_buff[43], 6);
+				obdr_sig[6] = '\0';
+				if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+					/* Not OBDR device, ignore it. */
+					break;
+			}
+			/* fall through . . . */
 		  case 0x01: /* sequential access, (tape) */
 		  case 0x08: /* medium changer */
 			if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1144,7 @@
 
 	int buflen, datalen;
 	ctlr_info_t *ci;
+	int i;
 	int cntl_num;
 
 
@@ -1136,8 +1155,28 @@
 	cntl_num = ci->ctlr;	/* Get our index into the hba[] array */
 
 	if (func == 0) {	/* User is reading from /proc/scsi/ciss*?/?*  */
-		buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no); 	
+		buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
+				cntl_num, sh->host_no);
 
+		/* this information is needed by apps to know which cciss
+		   device corresponds to which scsi host number without
+		   having to open a scsi target device node.  The device
+		   information is not a duplicate of /proc/scsi/scsi because
+		   the two may be out of sync due to scsi hotplug, rather
+		   this info is for an app to be able to use to know how to
+		   get them back in sync. */
+
+		for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
+			struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
+			buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
+				"0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				sh->host_no, sd->bus, sd->target, sd->lun,
+				sd->devtype,
+				sd->scsi3addr[0], sd->scsi3addr[1],
+				sd->scsi3addr[2], sd->scsi3addr[3],
+				sd->scsi3addr[4], sd->scsi3addr[5],
+				sd->scsi3addr[6], sd->scsi3addr[7]);
+		}
 		datalen = buflen - offset;
 		if (datalen < 0) { 	/* they're reading past EOF. */
 			datalen = 0;
@@ -1399,7 +1438,7 @@
 
 	CPQ_TAPE_LOCK(ctlr, flags);
 	size = sprintf(buffer + *len, 
-		"       Sequential access devices: %d\n\n",
+		"Sequential access devices: %d\n\n",
 			ccissscsi[ctlr].ndevices);
 	CPQ_TAPE_UNLOCK(ctlr, flags);
 	*pos += size; *len += size;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7b83834..7e22a58 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -5,29 +5,41 @@
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  *
- * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
- * DVD-RW devices (aka an exercise in block layer masturbation)
- *
- *
- * TODO: (circa order of when I will fix it)
- * - Only able to write on CD-RW media right now.
- * - check host application code on media and set it in write page
- * - interface for UDF <-> packet to negotiate a new location when a write
- *   fails.
- * - handle OPC, especially for -RW media
+ * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
+ * DVD-RAM devices.
  *
  * Theory of operation:
  *
- * We use a custom make_request_fn function that forwards reads directly to
- * the underlying CD device. Write requests are either attached directly to
- * a live packet_data object, or simply stored sequentially in a list for
- * later processing by the kcdrwd kernel thread. This driver doesn't use
- * any elevator functionally as defined by the elevator_s struct, but the
- * underlying CD device uses a standard elevator.
+ * At the lowest level, there is the standard driver for the CD/DVD device,
+ * typically ide-cd.c or sr.c. This driver can handle read and write requests,
+ * but it doesn't know anything about the special restrictions that apply to
+ * packet writing. One restriction is that write requests must be aligned to
+ * packet boundaries on the physical media, and the size of a write request
+ * must be equal to the packet size. Another restriction is that a
+ * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
+ * command, if the previous command was a write.
  *
- * This strategy makes it possible to do very late merging of IO requests.
- * A new bio sent to pkt_make_request can be merged with a live packet_data
- * object even if the object is in the data gathering state.
+ * The purpose of the packet writing driver is to hide these restrictions from
+ * higher layers, such as file systems, and present a block device that can be
+ * randomly read and written using 2kB-sized blocks.
+ *
+ * The lowest layer in the packet writing driver is the packet I/O scheduler.
+ * Its data is defined by the struct packet_iosched and includes two bio
+ * queues with pending read and write requests. These queues are processed
+ * by the pkt_iosched_process_queue() function. The write requests in this
+ * queue are already properly aligned and sized. This layer is responsible for
+ * issuing the flush cache commands and scheduling the I/O in a good order.
+ *
+ * The next layer transforms unaligned write requests to aligned writes. This
+ * transformation requires reading missing pieces of data from the underlying
+ * block device, assembling the pieces to full packets and queuing them to the
+ * packet I/O scheduler.
+ *
+ * At the top layer there is a custom make_request_fn function that forwards
+ * read requests directly to the iosched queue and puts write requests in the
+ * unaligned write queue. A kernel thread performs the necessary read
+ * gathering to convert the unaligned writes to aligned writes and then feeds
+ * them to the packet I/O scheduler.
  *
  *************************************************************************/
 
@@ -100,10 +112,9 @@
 		goto no_bio;
 	bio_init(bio);
 
-	bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL);
+	bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
 	if (!bvl)
 		goto no_bvl;
-	memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec));
 
 	bio->bi_max_vecs = nr_iovecs;
 	bio->bi_io_vec = bvl;
@@ -125,10 +136,9 @@
 	int i;
 	struct packet_data *pkt;
 
-	pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+	pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
 	if (!pkt)
 		goto no_pkt;
-	memset(pkt, 0, sizeof(struct packet_data));
 
 	pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
 	if (!pkt->w_bio)
@@ -659,7 +669,6 @@
 		}
 		offs += CD_FRAMESIZE;
 		if (offs >= PAGE_SIZE) {
-			BUG_ON(offs > PAGE_SIZE);
 			offs = 0;
 			p++;
 		}
@@ -724,12 +733,6 @@
 	atomic_set(&pkt->io_wait, 0);
 	atomic_set(&pkt->io_errors, 0);
 
-	if (pkt->cache_valid) {
-		VPRINTK("pkt_gather_data: zone %llx cached\n",
-			(unsigned long long)pkt->sector);
-		goto out_account;
-	}
-
 	/*
 	 * Figure out which frames we need to read before we can write.
 	 */
@@ -738,6 +741,7 @@
 	for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
 		int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
 		int num_frames = bio->bi_size / CD_FRAMESIZE;
+		pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
 		BUG_ON(first_frame < 0);
 		BUG_ON(first_frame + num_frames > pkt->frames);
 		for (f = first_frame; f < first_frame + num_frames; f++)
@@ -745,6 +749,12 @@
 	}
 	spin_unlock(&pkt->lock);
 
+	if (pkt->cache_valid) {
+		VPRINTK("pkt_gather_data: zone %llx cached\n",
+			(unsigned long long)pkt->sector);
+		goto out_account;
+	}
+
 	/*
 	 * Schedule reads for missing parts of the packet.
 	 */
@@ -778,7 +788,6 @@
 		frames_read, (unsigned long long)pkt->sector);
 	pd->stats.pkt_started++;
 	pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
-	pd->stats.secs_w += pd->settings.size;
 }
 
 /*
@@ -794,10 +803,11 @@
 			list_del_init(&pkt->list);
 			if (pkt->sector != zone)
 				pkt->cache_valid = 0;
-			break;
+			return pkt;
 		}
 	}
-	return pkt;
+	BUG();
+	return NULL;
 }
 
 static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -941,12 +951,10 @@
 	}
 
 	pkt = pkt_get_packet_data(pd, zone);
-	BUG_ON(!pkt);
 
 	pd->current_sector = zone + pd->settings.size;
 	pkt->sector = zone;
 	pkt->frames = pd->settings.size >> 2;
-	BUG_ON(pkt->frames > PACKET_MAX_SIZE);
 	pkt->write_size = 0;
 
 	/*
@@ -1636,6 +1644,10 @@
 		printk("pktcdvd: detected zero packet size!\n");
 		pd->settings.size = 128;
 	}
+	if (pd->settings.size > PACKET_MAX_SECTORS) {
+		printk("pktcdvd: packet size is too big\n");
+		return -ENXIO;
+	}
 	pd->settings.fp = ti.fp;
 	pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
 
@@ -2198,7 +2210,6 @@
 	 * No matching packet found. Store the bio in the work queue.
 	 */
 	node = mempool_alloc(pd->rb_pool, GFP_NOIO);
-	BUG_ON(!node);
 	node->bio = bio;
 	spin_lock(&pd->lock);
 	BUG_ON(pd->bio_queue_size < 0);
@@ -2406,7 +2417,6 @@
 	struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
 
 	VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
-	BUG_ON(!pd);
 
 	switch (cmd) {
 	/*
@@ -2477,10 +2487,9 @@
 		return -EBUSY;
 	}
 
-	pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
+	pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
 	if (!pd)
 		return ret;
-	memset(pd, 0, sizeof(struct pktcdvd_device));
 
 	pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
 	if (!pd->rb_pool)
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index abb2df2..856c227 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -123,6 +123,7 @@
 		safe_for_read(READ_12),
 		safe_for_read(READ_16),
 		safe_for_read(READ_BUFFER),
+		safe_for_read(READ_DEFECT_DATA),
 		safe_for_read(READ_LONG),
 		safe_for_read(INQUIRY),
 		safe_for_read(MODE_SENSE),
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 67d96b5..57c48bb 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -65,13 +65,15 @@
 #endif
 
 static int ignore = 0;
+static int ignore_csr = 0;
+static int ignore_sniffer = 0;
 static int reset = 0;
 
 #ifdef CONFIG_BT_HCIUSB_SCO
 static int isoc = 2;
 #endif
 
-#define VERSION "2.8"
+#define VERSION "2.9"
 
 static struct usb_driver hci_usb_driver; 
 
@@ -98,6 +100,9 @@
 MODULE_DEVICE_TABLE (usb, bluetooth_ids);
 
 static struct usb_device_id blacklist_ids[] = {
+	/* CSR BlueCore devices */
+	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
+
 	/* Broadcom BCM2033 without firmware */
 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
 
@@ -836,6 +841,12 @@
 	if (ignore || id->driver_info & HCI_IGNORE)
 		return -ENODEV;
 
+	if (ignore_csr && id->driver_info & HCI_CSR)
+		return -ENODEV;
+
+	if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
+		return -ENODEV;
+
 	if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
 		return -ENODEV;
 
@@ -1061,6 +1072,12 @@
 module_param(ignore, bool, 0644);
 MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
 
+module_param(ignore_csr, bool, 0644);
+MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
+
+module_param(ignore_sniffer, bool, 0644);
+MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
+
 module_param(reset, bool, 0644);
 MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
 
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 29936b4..37100a6 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -31,9 +31,10 @@
 #define HCI_IGNORE		0x01
 #define HCI_RESET		0x02
 #define HCI_DIGIANSWER		0x04
-#define HCI_SNIFFER		0x08
-#define HCI_BROKEN_ISOC		0x10
+#define HCI_CSR			0x08
+#define HCI_SNIFFER		0x10
 #define HCI_BCM92035		0x20
+#define HCI_BROKEN_ISOC		0x40
 
 #define HCI_MAX_IFACE_NUM	3
 
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 2a36561..a124f8c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2053,10 +2053,6 @@
 	state->icount.rx = state->icount.tx = 0;
 	state->icount.frame = state->icount.parity = 0;
 	state->icount.overrun = state->icount.brk = 0;
-	/*
-	if(state->port && check_region(state->port,REGION_LENGTH(state)))
-	  continue;
-	*/
 
 	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
 		       state->line);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index c3898af..344001b 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -84,6 +84,17 @@
 
 	  Not sure? It's safe to say N.
 
+config IXP2000_WATCHDOG
+	tristate "IXP2000 Watchdog"
+	depends on WATCHDOG && ARCH_IXP2000
+	help
+	  Say Y here if to include support for the watchdog timer
+	  in the Intel IXP2000(2400, 2800, 2850) network processors.
+	  This driver can be built as a module by choosing M. The module
+	  will be called ixp2000_wdt.
+
+	  Say N if you are unsure.
+
 config IXP4XX_WATCHDOG
 	tristate "IXP4xx Watchdog"
 	depends on WATCHDOG && ARCH_IXP4XX
@@ -100,17 +111,6 @@
 
 	  Say N if you are unsure.
 
-config IXP2000_WATCHDOG
-	tristate "IXP2000 Watchdog"
-	depends on WATCHDOG && ARCH_IXP2000
-	help
-	  Say Y here if to include support for the watchdog timer
-	  in the Intel IXP2000(2400, 2800, 2850) network processors.
-	  This driver can be built as a module by choosing M. The module
-	  will be called ixp2000_wdt.
-
-	  Say N if you are unsure.
-
 config S3C2410_WATCHDOG
 	tristate "S3C2410 Watchdog"
 	depends on WATCHDOG && ARCH_S3C2410
@@ -139,6 +139,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called sa1100_wdt.
 
+config MPCORE_WATCHDOG
+	tristate "MPcore watchdog"
+	depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+	help
+	  Watchdog timer embedded into the MPcore system.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mpcore_wdt.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
@@ -224,6 +233,16 @@
 
 	  Most people will say N.
 
+config IBMASR
+        tristate "IBM Automatic Server Restart"
+        depends on WATCHDOG && X86
+        help
+	  This is the driver for the IBM Automatic Server Restart watchdog
+	  timer builtin into some eServer xSeries machines.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmasr.
+
 config WAFER_WDT
 	tristate "ICP Wafer 5823 Single Board Computer Watchdog"
 	depends on WATCHDOG && X86
@@ -234,6 +253,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called wafer5823wdt.
 
+config I6300ESB_WDT
+	tristate "Intel 6300ESB Timer/Watchdog"
+	depends on WATCHDOG && X86 && PCI
+	---help---
+	  Hardware driver for the watchdog timer built into the Intel
+	  6300ESB controller hub.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called i6300esb.
+
 config I8XX_TCO
 	tristate "Intel i8xx TCO Timer/Watchdog"
 	depends on WATCHDOG && (X86 || IA64) && PCI
@@ -289,6 +318,19 @@
 	  You can compile this driver directly into the kernel, or use
 	  it as a module.  The module will be called sbc60xxwdt.
 
+config SBC8360_WDT
+	tristate "SBC8360 Watchdog Timer"
+	depends on WATCHDOG && X86
+	---help---
+
+	  This is the driver for the hardware watchdog on the SBC8360 Single
+	  Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sbc8360.ko.
+
+	  Most people will say N.
+
 config CPU5_WDT
 	tristate "SMA CPU5 Watchdog"
 	depends on WATCHDOG && X86
@@ -327,6 +369,19 @@
 
 	  Most people will say N.
 
+config W83977F_WDT
+	tristate "W83977F (PCM-5335) Watchdog Timer"
+	depends on WATCHDOG && X86
+	---help---
+	  This is the driver for the hardware watchdog on the W83977F I/O chip
+	  as used in AAEON's PCM-5335 SBC (and likely others).  This
+	  watchdog simply watches your kernel to make sure it doesn't freeze,
+	  and if it does, it reboots your computer after a certain amount of
+	  time.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called w83977f_wdt.
+
 config MACHZ_WDT
 	tristate "ZF MachZ Watchdog"
 	depends on WATCHDOG && X86
@@ -346,6 +401,10 @@
 	tristate "MPC8xx Watchdog Timer"
 	depends on WATCHDOG && 8xx
 
+config MV64X60_WDT
+	tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+	depends on WATCHDOG && MV64X60
+
 config BOOKE_WDT
 	tristate "PowerPC Book-E Watchdog Timer"
 	depends on WATCHDOG && (BOOKE || 4xx)
@@ -353,6 +412,17 @@
 	  Please see Documentation/watchdog/watchdog-api.txt for
 	  more information.
 
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+	tristate "RTAS watchdog"
+	depends on WATCHDOG && PPC_RTAS
+	help
+	  This driver adds watchdog support for the RTAS watchdog.
+
+          To compile this driver as a module, choose M here. The module
+	  will be called wdrtas.
+
 # MIPS Architecture
 
 config INDYDOG
@@ -421,16 +491,6 @@
 	  machines.  The watchdog timeout period is normally one minute but
 	  can be changed with a boot-time parameter.
 
-# ppc64 RTAS watchdog
-config WATCHDOG_RTAS
-	tristate "RTAS watchdog"
-	depends on WATCHDOG && PPC_RTAS
-	help
-	  This driver adds watchdog support for the RTAS watchdog.
-
-          To compile this driver as a module, choose M here. The module
-	  will be called wdrtas.
-
 #
 # ISA-based Watchdog Cards
 #
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfeac6f..cfd0a39 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -29,6 +29,7 @@
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
+obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
 
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
@@ -38,22 +39,27 @@
 obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
 obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
 obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
 obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
 obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
 obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
 obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
 obj-$(CONFIG_MACHZ_WDT) += machzwd.o
 
 # PowerPC Architecture
 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
 
 # PPC64 Architecture
 obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
 
 # MIPS Architecture
 obj-$(CONFIG_INDYDOG) += indydog.o
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
new file mode 100644
index 0000000..93785f1
--- /dev/null
+++ b/drivers/char/watchdog/i6300esb.c
@@ -0,0 +1,527 @@
+/*
+ *	i6300esb:	Watchdog timer driver for Intel 6300ESB chipset
+ *
+ *	(c) Copyright 2004 Google Inc.
+ *	(c) Copyright 2005 David Härdeman <david@2gen.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *      based on i810-tco.c which is in turn based on softdog.c
+ *
+ * 	The timer is implemented in the following I/O controller hubs:
+ * 	(See the intel documentation on http://developer.intel.com.)
+ * 	6300ESB chip : document number 300641-003
+ *
+ *  2004YYZZ Ross Biro
+ *	Initial version 0.01
+ *  2004YYZZ Ross Biro
+ *  	Version 0.02
+ *  20050210 David Härdeman <david@2gen.com>
+ *      Ported driver to kernel 2.6
+ */
+
+/*
+ *      Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG  0x60            /* Config register                   */
+#define ESB_LOCK_REG    0x68            /* WDT lock register                 */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG  BASEADDR + 0x00 /* Timer1 value after each reset     */
+#define ESB_TIMER2_REG  BASEADDR + 0x04 /* Timer2 value after each reset     */
+#define ESB_GINTSR_REG  BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG  BASEADDR + 0x0c /* Reload register                   */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC    ( 0x01 << 2 )   /* Watchdog functionality            */
+#define ESB_WDT_ENABLE  ( 0x01 << 1 )   /* Enable WDT                        */
+#define ESB_WDT_LOCK    ( 0x01 << 0 )   /* Lock (nowayout)                   */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT  ( 0x01 << 5 )   /* Enable reboot on timeout          */
+#define ESB_WDT_FREQ    ( 0x01 << 2 )   /* Decrement frequency               */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 )   /* Interrupt type on timer1 timeout  */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 )    /* prevent timeout                   */
+
+/* Magic constants */
+#define ESB_UNLOCK1     0x80            /* Step 1 to unlock reset registers  */
+#define ESB_UNLOCK2     0x86            /* Step 2 to unlock reset registers  */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30   /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+        writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+        writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+	u8 val;
+
+	/* Enable or Enable + Lock? */
+	val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+        pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+	u8 val;
+
+	spin_lock(&esb_lock);
+	/* First, reset timers as suggested by the docs */
+	esb_unlock_registers();
+	writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+	/* Then disable the WDT */
+	pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+	pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+	spin_unlock(&esb_lock);
+
+	/* Returns 0 if the timer was disabled, non-zero otherwise */
+	return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+	spin_lock(&esb_lock);
+	esb_unlock_registers();
+	writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+        /* FIXME: Do we need to flush anything here? */
+	spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+	u32 val;
+
+	if (time < 0x1 || time > (2 * 0x03ff))
+		return -EINVAL;
+
+	spin_lock(&esb_lock);
+
+	/* We shift by 9, so if we are passed a value of 1 sec,
+	 * val will be 1 << 9 = 512, then write that to two
+	 * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+	 */
+	val = time << 9;
+
+	/* Write timer 1 */
+	esb_unlock_registers();
+	writel(val, ESB_TIMER1_REG);
+
+	/* Write timer 2 */
+	esb_unlock_registers();
+        writel(val, ESB_TIMER2_REG);
+
+        /* Reload */
+	esb_unlock_registers();
+	writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+	/* FIXME: Do we need to flush everything out? */
+
+	/* Done */
+	heartbeat = time;
+	spin_unlock(&esb_lock);
+	return 0;
+}
+
+static int esb_timer_read (void)
+{
+       	u32 count;
+
+	/* This isn't documented, and doesn't take into
+         * acount which stage is running, but it looks
+         * like a 20 bit count down, so we might as well report it.
+         */
+        pci_read_config_dword(esb_pci, 0x64, &count);
+        return (int)count;
+}
+
+/*
+ * 	/dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+        /* /dev/watchdog can only be opened once */
+        if (test_and_set_bit(0, &timer_alive))
+                return -EBUSY;
+
+        /* Reload and activate timer */
+        esb_timer_keepalive ();
+        esb_timer_start ();
+
+	return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+        /* Shut off the timer. */
+        if (esb_expect_close == 42) {
+                esb_timer_stop ();
+        } else {
+                printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+                esb_timer_keepalive ();
+        }
+        clear_bit(0, &timer_alive);
+        esb_expect_close = 0;
+        return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+			  size_t len, loff_t * ppos)
+{
+	/* See if we got the magic character 'V' and reload the timer */
+        if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			/* note: just in case someone wrote the magic character
+			 * five months ago... */
+			esb_expect_close = 0;
+
+			/* scan to see whether or not we got the magic character */
+			for (i = 0; i != len; i++) {
+				char c;
+				if(get_user(c, data+i))
+					return -EFAULT;
+				if (c == 'V')
+					esb_expect_close = 42;
+			}
+		}
+
+		/* someone wrote to us, we should reload the timer */
+		esb_timer_keepalive ();
+	}
+	return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	int new_options, retval = -EINVAL;
+	int new_heartbeat;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	static struct watchdog_info ident = {
+		.options =              WDIOF_SETTIMEOUT |
+					WDIOF_KEEPALIVEPING |
+					WDIOF_MAGICCLOSE,
+		.firmware_version =     0,
+		.identity =             ESB_MODULE_NAME,
+	};
+
+	switch (cmd) {
+		case WDIOC_GETSUPPORT:
+			return copy_to_user(argp, &ident,
+					    sizeof (ident)) ? -EFAULT : 0;
+
+		case WDIOC_GETSTATUS:
+			return put_user (esb_timer_read(), p);
+
+		case WDIOC_GETBOOTSTATUS:
+			return put_user (triggered, p);
+
+                case WDIOC_KEEPALIVE:
+                        esb_timer_keepalive ();
+                        return 0;
+
+                case WDIOC_SETOPTIONS:
+                {
+                        if (get_user (new_options, p))
+                                return -EFAULT;
+
+                        if (new_options & WDIOS_DISABLECARD) {
+                                esb_timer_stop ();
+                                retval = 0;
+                        }
+
+                        if (new_options & WDIOS_ENABLECARD) {
+                                esb_timer_keepalive ();
+                                esb_timer_start ();
+                                retval = 0;
+                        }
+
+                        return retval;
+                }
+
+                case WDIOC_SETTIMEOUT:
+                {
+                        if (get_user(new_heartbeat, p))
+                                return -EFAULT;
+
+                        if (esb_timer_set_heartbeat(new_heartbeat))
+                            return -EINVAL;
+
+                        esb_timer_keepalive ();
+                        /* Fall */
+                }
+
+                case WDIOC_GETTIMEOUT:
+                        return put_user(heartbeat, p);
+
+                default:
+                        return -ENOIOCTLCMD;
+        }
+}
+
+/*
+ *      Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+        if (code==SYS_DOWN || code==SYS_HALT) {
+                /* Turn the WDT off */
+                esb_timer_stop ();
+        }
+
+        return NOTIFY_DONE;
+}
+
+/*
+ *      Kernel Interfaces
+ */
+
+static struct file_operations esb_fops = {
+        .owner =        THIS_MODULE,
+        .llseek =       no_llseek,
+        .write =        esb_write,
+        .ioctl =        esb_ioctl,
+        .open =         esb_open,
+        .release =      esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+        .minor =        WATCHDOG_MINOR,
+        .name =         "watchdog",
+        .fops =         &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+        .notifier_call =        esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+        { 0, },                 /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ *      Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+	u8 val1;
+	unsigned short val2;
+
+        struct pci_dev *dev = NULL;
+        /*
+         *      Find the PCI device
+         */
+
+        for_each_pci_dev(dev) {
+                if (pci_match_id(esb_pci_tbl, dev)) {
+                        esb_pci = dev;
+                        break;
+                }
+	}
+
+        if (esb_pci) {
+        	if (pci_enable_device(esb_pci)) {
+			printk (KERN_ERR PFX "failed to enable device\n");
+			goto err_devput;
+		}
+
+		if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+			printk (KERN_ERR PFX "failed to request region\n");
+			goto err_disable;
+		}
+
+		BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+				   pci_resource_len(esb_pci, 0));
+		if (BASEADDR == NULL) {
+                	/* Something's wrong here, BASEADDR has to be set */
+			printk (KERN_ERR PFX "failed to get BASEADDR\n");
+                        goto err_release;
+                }
+
+		/*
+		 * The watchdog has two timers, it can be setup so that the
+		 * expiry of timer1 results in an interrupt and the expiry of
+		 * timer2 results in a reboot. We set it to not generate
+		 * any interrupts as there is not much we can do with it
+		 * right now.
+		 *
+		 * We also enable reboots and set the timer frequency to
+		 * the PCI clock divided by 2^15 (approx 1KHz).
+		 */
+		pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+		/* Check that the WDT isn't already locked */
+		pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+		if (val1 & ESB_WDT_LOCK)
+			printk (KERN_WARNING PFX "nowayout already set\n");
+
+		/* Set the timer to watchdog mode and disable it for now */
+		pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+		/* Check if the watchdog was previously triggered */
+		esb_unlock_registers();
+		val2 = readw(ESB_RELOAD_REG);
+		triggered = (val2 & (0x01 << 9) >> 9);
+
+		/* Reset trigger flag and timers */
+		esb_unlock_registers();
+		writew((0x11 << 8), ESB_RELOAD_REG);
+
+		/* Done */
+		return 1;
+
+err_release:
+		pci_release_region(esb_pci, 0);
+err_disable:
+		pci_disable_device(esb_pci);
+err_devput:
+		pci_dev_put(esb_pci);
+	}
+	return 0;
+}
+
+static int __init watchdog_init (void)
+{
+        int ret;
+
+        spin_lock_init(&esb_lock);
+
+        /* Check whether or not the hardware watchdog is there */
+        if (!esb_getdevice () || esb_pci == NULL)
+                return -ENODEV;
+
+        /* Check that the heartbeat value is within it's range ; if not reset to the default */
+        if (esb_timer_set_heartbeat (heartbeat)) {
+                esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+                printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+		       heartbeat);
+        }
+
+        ret = register_reboot_notifier(&esb_notifier);
+        if (ret != 0) {
+                printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+                        ret);
+                goto err_unmap;
+        }
+
+        ret = misc_register(&esb_miscdev);
+        if (ret != 0) {
+                printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+                        WATCHDOG_MINOR, ret);
+                goto err_notifier;
+        }
+
+        esb_timer_stop ();
+
+        printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+                BASEADDR, heartbeat, nowayout);
+
+        return 0;
+
+err_notifier:
+        unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+	iounmap(BASEADDR);
+/* err_release: */
+	pci_release_region(esb_pci, 0);
+/* err_disable: */
+	pci_disable_device(esb_pci);
+/* err_devput: */
+	pci_dev_put(esb_pci);
+        return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+	/* Stop the timer before we leave */
+	if (!nowayout)
+		esb_timer_stop ();
+
+	/* Deregister */
+	misc_deregister(&esb_miscdev);
+        unregister_reboot_notifier(&esb_notifier);
+	iounmap(BASEADDR);
+	pci_release_region(esb_pci, 0);
+	pci_disable_device(esb_pci);
+	pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
new file mode 100644
index 0000000..294c474
--- /dev/null
+++ b/drivers/char/watchdog/ibmasr.c
@@ -0,0 +1,405 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+	ASMTYPE_UNKNOWN,
+	ASMTYPE_TOPAZ,
+	ASMTYPE_JASPER,
+	ASMTYPE_PEARL,
+	ASMTYPE_JUNIPER,
+	ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET	4
+#define TOPAZ_ASR_TOGGLE	0x40
+#define TOPAZ_ASR_DISABLE	0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE	0xe04
+#define PEARL_WRITE	0xe06
+#define PEARL_READ	0xe07
+
+#define PEARL_ASR_DISABLE_MASK	0x80	/* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK	0x40	/* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET	0x38
+
+#define JASPER_ASR_DISABLE_MASK	0x01	/* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK	0x02	/* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS	0x54b	/* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01	/* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK	0x02	/* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS	0x118e	/* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK	0x01	/* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK	0x02	/* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+	unsigned char reg = inb(asr_read_addr);
+
+	outb(reg & ~asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+
+	outb(reg | asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+
+	outb(reg & ~asr_toggle_mask, asr_write_addr);
+	reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+	unsigned char reg;
+
+	if (asr_type == ASMTYPE_TOPAZ) {
+		/* asr_write_addr == asr_read_addr */
+		reg = inb(asr_read_addr);
+		outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+		     asr_read_addr);
+	} else {
+		/*
+		 * First make sure the hardware timer is reset by toggling
+		 * ASR hardware timer line.
+		 */
+		asr_toggle();
+
+		reg = inb(asr_read_addr);
+		outb(reg & ~asr_disable_mask, asr_write_addr);
+	}
+	reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+	unsigned char reg = inb(asr_read_addr);
+
+	if (asr_type == ASMTYPE_TOPAZ)
+		/* asr_write_addr == asr_read_addr */
+		outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+		     asr_read_addr);
+	else {
+		outb(reg | asr_toggle_mask, asr_write_addr);
+		reg = inb(asr_read_addr);
+
+		outb(reg | asr_disable_mask, asr_write_addr);
+	}
+	reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+	unsigned char low, high;
+	const char *type = "";
+
+	asr_length = 1;
+
+	switch (asr_type) {
+	case ASMTYPE_TOPAZ:
+		/* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+		outb(0x07, 0x2e);
+		outb(0x07, 0x2f);
+
+		/* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+		outb(0x60, 0x2e);
+		high = inb(0x2f);
+
+		/* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+		outb(0x61, 0x2e);
+		low = inb(0x2f);
+
+		asr_base = (high << 16) | low;
+		asr_read_addr = asr_write_addr =
+			asr_base + TOPAZ_ASR_REG_OFFSET;
+		asr_length = 5;
+
+		break;
+
+	case ASMTYPE_JASPER:
+		type = "Jaspers ";
+
+		/* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/*		spin_lock_irqsave(&pci_config_lock, flags);*/
+
+		/* Select the SuperIO chip in the PCI I/O port register */
+		outl(0x8000f858, 0xcf8);
+
+		/*
+		 * Read the base address for the SuperIO chip.
+		 * Only the lower 16 bits are valid, but the address is word
+		 * aligned so the last bit must be masked off.
+		 */
+		asr_base = inl(0xcfc) & 0xfffe;
+
+/*		spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+		asr_read_addr = asr_write_addr =
+			asr_base + JASPER_ASR_REG_OFFSET;
+		asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+		asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+		asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+		break;
+
+	case ASMTYPE_PEARL:
+		type = "Pearls ";
+		asr_base = PEARL_BASE;
+		asr_read_addr = PEARL_READ;
+		asr_write_addr = PEARL_WRITE;
+		asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+		asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+		asr_length = 4;
+		break;
+
+	case ASMTYPE_JUNIPER:
+		type = "Junipers ";
+		asr_base = JUNIPER_BASE_ADDRESS;
+		asr_read_addr = asr_write_addr = asr_base;
+		asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+		asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+		break;
+
+	case ASMTYPE_SPRUCE:
+		type = "Spruce's ";
+		asr_base = SPRUCE_BASE_ADDRESS;
+		asr_read_addr = asr_write_addr = asr_base;
+		asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+		asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+		break;
+	}
+
+	if (!request_region(asr_base, asr_length, "ibmasr")) {
+		printk(KERN_ERR PFX "address %#x already in use\n",
+			asr_base);
+		return -EBUSY;
+	}
+
+	printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+	return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			/* In case it was set long ago */
+			asr_expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					asr_expect_close = 42;
+			}
+		}
+		asr_toggle();
+	}
+	return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	static const struct watchdog_info ident = {
+		.options =	WDIOF_KEEPALIVEPING | 
+				WDIOF_MAGICCLOSE,
+		.identity =	"IBM ASR"
+	};
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int heartbeat;
+
+	switch (cmd) {
+		case WDIOC_GETSUPPORT:
+			return copy_to_user(argp, &ident, sizeof(ident)) ?
+				-EFAULT : 0;
+
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, p);
+
+		case WDIOC_KEEPALIVE:
+			asr_toggle();
+			return 0;
+
+		/*
+		 * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+		 * and WDIOC_GETTIMEOUT always returns 256.
+		 */
+		case WDIOC_GETTIMEOUT:
+			heartbeat = 256;
+			return put_user(heartbeat, p);
+
+		case WDIOC_SETOPTIONS: {
+			int new_options, retval = -EINVAL;
+
+			if (get_user(new_options, p))
+				return -EFAULT;
+
+			if (new_options & WDIOS_DISABLECARD) {
+				asr_disable();
+				retval = 0;
+			}
+
+			if (new_options & WDIOS_ENABLECARD) {
+				asr_enable();
+				asr_toggle();
+				retval = 0;
+			}
+
+			return retval;
+		}
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+	if(test_and_set_bit(0, &asr_is_open))
+		return -EBUSY;
+
+	asr_toggle();
+	asr_enable();
+
+	return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+	if (asr_expect_close == 42)
+		asr_disable();
+	else {
+		printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+		asr_toggle();
+	}
+	clear_bit(0, &asr_is_open);
+	asr_expect_close = 0;
+	return 0;
+}
+
+static struct file_operations asr_fops = {
+	.owner =	THIS_MODULE,
+	.llseek	=	no_llseek,
+	.write =	asr_write,
+	.ioctl =	asr_ioctl,
+	.open =		asr_open,
+	.release =	asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+	.minor =	WATCHDOG_MINOR,
+	.name =		"watchdog",
+	.fops =		&asr_fops,
+};
+
+
+struct ibmasr_id {
+	const char *desc;
+	int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+	{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+	{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+	{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+	{ "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+	{ "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+	{ NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+	struct ibmasr_id *id;
+	int rc;
+
+	for (id = ibmasr_id_table; id->desc; id++) {
+		if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+			asr_type = id->type;
+			break;
+		}
+	}
+
+	if (!asr_type)
+		return -ENODEV;
+
+	rc = misc_register(&asr_miscdev);
+	if (rc < 0) {
+		printk(KERN_ERR PFX "failed to register misc device\n");
+		return rc;
+	}
+
+	rc = asr_get_base_address();
+	if (rc) {
+		misc_deregister(&asr_miscdev);
+		return rc;
+	}
+
+	return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+	if (!nowayout)
+		asr_disable();
+
+	misc_deregister(&asr_miscdev);
+
+	release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
new file mode 100644
index 0000000..c694eee
--- /dev/null
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -0,0 +1,434 @@
+/*
+ *	Watchdog driver for the mpcore watchdog timer
+ *
+ *	(c) Copyright 2004 ARM Limited
+ *
+ *	Based on the SoftDog driver:
+ *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *				http://www.redhat.com
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
+ *
+ *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+
+struct mpcore_wdt {
+	unsigned long	timer_alive;
+	struct device	*dev;
+	void __iomem	*base;
+	int		irq;
+	unsigned int	perturb;
+	char		expect_close;
+};
+
+static struct platform_device *mpcore_wdt_dev;
+
+extern unsigned int mpcore_timer_rate;
+
+#define TIMER_MARGIN	60
+static int mpcore_margin = TIMER_MARGIN;
+module_param(mpcore_margin, int, 0);
+MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define ONLY_TESTING	0
+static int mpcore_noboot = ONLY_TESTING;
+module_param(mpcore_noboot, int, 0);
+MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, set to 1 to ignore reboots, 0 to reboot (default=" __MODULE_STRING(ONLY_TESTING) ")");
+
+/*
+ *	This is the interrupt handler.  Note that we only use this
+ *	in testing mode, so don't actually do a reboot here.
+ */
+static irqreturn_t mpcore_wdt_fire(int irq, void *arg, struct pt_regs *regs)
+{
+	struct mpcore_wdt *wdt = arg;
+
+	/* Check it really was our interrupt */
+	if (readl(wdt->base + TWD_WDOG_INTSTAT)) {
+		dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n");
+
+		/* Clear the interrupt on the watchdog */
+		writel(1, wdt->base + TWD_WDOG_INTSTAT);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ *	mpcore_wdt_keepalive - reload the timer
+ *
+ *	Note that the spec says a DIFFERENT value must be written to the reload
+ *	register each time.  The "perturb" variable deals with this by adding 1
+ *	to the count every other time the function is called.
+ */
+static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
+{
+	unsigned int count;
+
+	/* Assume prescale is set to 256 */
+	count = (mpcore_timer_rate / 256) * mpcore_margin;
+
+	/* Reload the counter */
+	writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
+
+	wdt->perturb = wdt->perturb ? 0 : 1;
+}
+
+static void mpcore_wdt_stop(struct mpcore_wdt *wdt)
+{
+	writel(0x12345678, wdt->base + TWD_WDOG_DISABLE);
+	writel(0x87654321, wdt->base + TWD_WDOG_DISABLE);
+	writel(0x0, wdt->base + TWD_WDOG_CONTROL);
+}
+
+static void mpcore_wdt_start(struct mpcore_wdt *wdt)
+{
+	dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
+
+	/* This loads the count register but does NOT start the count yet */
+	mpcore_wdt_keepalive(wdt);
+
+	if (mpcore_noboot) {
+		/* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
+		writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+	} else {
+		/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
+		writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+	}
+}
+
+static int mpcore_wdt_set_heartbeat(int t)
+{
+	if (t < 0x0001 || t > 0xFFFF)
+		return -EINVAL;
+
+	mpcore_margin = t;
+	return 0;
+}
+
+/*
+ *	/dev/watchdog handling
+ */
+static int mpcore_wdt_open(struct inode *inode, struct file *file)
+{
+	struct mpcore_wdt *wdt = dev_get_drvdata(&mpcore_wdt_dev->dev);
+
+	if (test_and_set_bit(0, &wdt->timer_alive))
+		return -EBUSY;
+
+	if (nowayout)
+		__module_get(THIS_MODULE);
+
+	file->private_data = wdt;
+
+	/*
+	 *	Activate timer
+	 */
+	mpcore_wdt_start(wdt);
+
+	return nonseekable_open(inode, file);
+}
+
+static int mpcore_wdt_release(struct inode *inode, struct file *file)
+{
+	struct mpcore_wdt *wdt = file->private_data;
+
+	/*
+	 *	Shut off the timer.
+	 * 	Lock it in if it's a module and we set nowayout
+	 */
+	if (wdt->expect_close == 42) {
+		mpcore_wdt_stop(wdt);
+	} else {
+		dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n");
+		mpcore_wdt_keepalive(wdt);
+	}
+	clear_bit(0, &wdt->timer_alive);
+	wdt->expect_close = 0;
+	return 0;
+}
+
+static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+	struct mpcore_wdt *wdt = file->private_data;
+
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	/*
+	 *	Refresh the timer.
+	 */
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			/* In case it was set long ago */
+			wdt->expect_close = 0;
+
+			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, data + i))
+					return -EFAULT;
+				if (c == 'V')
+					wdt->expect_close = 42;
+			}
+		}
+		mpcore_wdt_keepalive(wdt);
+	}
+	return len;
+}
+
+static struct watchdog_info ident = {
+	.options		= WDIOF_SETTIMEOUT |
+				  WDIOF_KEEPALIVEPING |
+				  WDIOF_MAGICCLOSE,
+	.identity		= "MPcore Watchdog",
+};
+
+static int mpcore_wdt_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	struct mpcore_wdt *wdt = file->private_data;
+	int ret;
+	union {
+		struct watchdog_info ident;
+		int i;
+	} uarg;
+
+	if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
+		return -ENOIOCTLCMD;
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
+		if (ret)
+			return -EFAULT;
+	}
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		uarg.ident = ident;
+		ret = 0;
+		break;
+
+	case WDIOC_SETOPTIONS:
+		ret = -EINVAL;
+		if (uarg.i & WDIOS_DISABLECARD) {
+			mpcore_wdt_stop(wdt);
+			ret = 0;
+		}
+		if (uarg.i & WDIOS_ENABLECARD) {
+			mpcore_wdt_start(wdt);
+			ret = 0;
+		}
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		uarg.i = 0;
+		ret = 0;
+		break;
+
+	case WDIOC_KEEPALIVE:
+		mpcore_wdt_keepalive(wdt);
+		ret = 0;
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		ret = mpcore_wdt_set_heartbeat(uarg.i);
+		if (ret)
+			break;
+
+		mpcore_wdt_keepalive(wdt);
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		uarg.i = mpcore_margin;
+		ret = 0;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+		ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd));
+		if (ret)
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+/*
+ *	System shutdown handler.  Turn off the watchdog if we're
+ *	restarting or halting the system.
+ */
+static void mpcore_wdt_shutdown(struct device *_dev)
+{
+	struct mpcore_wdt *wdt = dev_get_drvdata(_dev);
+
+	if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT)
+		mpcore_wdt_stop(wdt);
+}
+
+/*
+ *	Kernel Interfaces
+ */
+static struct file_operations mpcore_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= mpcore_wdt_write,
+	.ioctl		= mpcore_wdt_ioctl,
+	.open		= mpcore_wdt_open,
+	.release	= mpcore_wdt_release,
+};
+
+static struct miscdevice mpcore_wdt_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &mpcore_wdt_fops,
+};
+
+static int __devinit mpcore_wdt_probe(struct device *_dev)
+{
+	struct platform_device *dev = to_platform_device(_dev);
+	struct mpcore_wdt *wdt;
+	struct resource *res;
+	int ret;
+
+	/* We only accept one device, and it must have an id of -1 */
+	if (dev->id != -1)
+		return -ENODEV;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	wdt = kmalloc(sizeof(struct mpcore_wdt), GFP_KERNEL);
+	if (!wdt) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+	memset(wdt, 0, sizeof(struct mpcore_wdt));
+
+	wdt->dev = &dev->dev;
+	wdt->irq = platform_get_irq(dev, 0);
+	wdt->base = ioremap(res->start, res->end - res->start + 1);
+	if (!wdt->base) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	mpcore_wdt_miscdev.dev = &dev->dev;
+	ret = misc_register(&mpcore_wdt_miscdev);
+	if (ret) {
+		dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n",
+			   WATCHDOG_MINOR, ret);
+		goto err_misc;
+	}
+
+	ret = request_irq(wdt->irq, mpcore_wdt_fire, SA_INTERRUPT, "mpcore_wdt", wdt);
+	if (ret) {
+		dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq);
+		goto err_irq;
+	}
+
+	mpcore_wdt_stop(wdt);
+	dev_set_drvdata(&dev->dev, wdt);
+	mpcore_wdt_dev = dev;
+
+	return 0;
+
+ err_irq:
+	misc_deregister(&mpcore_wdt_miscdev);
+ err_misc:
+	iounmap(wdt->base);
+ err_free:
+	kfree(wdt);
+ err_out:
+	return ret;
+}
+
+static int __devexit mpcore_wdt_remove(struct device *dev)
+{
+	struct mpcore_wdt *wdt = dev_get_drvdata(dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	misc_deregister(&mpcore_wdt_miscdev);
+
+	mpcore_wdt_dev = NULL;
+
+	free_irq(wdt->irq, wdt);
+	iounmap(wdt->base);
+	kfree(wdt);
+	return 0;
+}
+
+static struct device_driver mpcore_wdt_driver = {
+	.name		= "mpcore_wdt",
+	.bus		= &platform_bus_type,
+	.probe		= mpcore_wdt_probe,
+	.remove		= __devexit_p(mpcore_wdt_remove),
+	.shutdown	= mpcore_wdt_shutdown,
+};
+
+static char banner[] __initdata = KERN_INFO "MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n";
+
+static int __init mpcore_wdt_init(void)
+{
+	/*
+	 * Check that the margin value is within it's range;
+	 * if not reset to the default
+	 */
+	if (mpcore_wdt_set_heartbeat(mpcore_margin)) {
+		mpcore_wdt_set_heartbeat(TIMER_MARGIN);
+		printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n",
+			TIMER_MARGIN);
+	}
+
+	printk(banner, mpcore_noboot, mpcore_margin, nowayout);
+
+	return driver_register(&mpcore_wdt_driver);
+}
+
+static void __exit mpcore_wdt_exit(void)
+{
+	driver_unregister(&mpcore_wdt_driver);
+}
+
+module_init(mpcore_wdt_init);
+module_exit(mpcore_wdt_exit);
+
+MODULE_AUTHOR("ARM Limited");
+MODULE_DESCRIPTION("MPcore Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
new file mode 100644
index 0000000..1436aea
--- /dev/null
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -0,0 +1,252 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required.  This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ * 
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/mv64x60.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* MV64x60 WDC (config) register access definitions */
+#define MV64x60_WDC_CTL1_MASK	(3 << 24)
+#define MV64x60_WDC_CTL1(val)	((val & 3) << 24)
+#define MV64x60_WDC_CTL2_MASK	(3 << 26)
+#define MV64x60_WDC_CTL2(val)	((val & 3) << 26)
+
+/* Flags bits */
+#define MV64x60_WDOG_FLAG_OPENED	0
+#define MV64x60_WDOG_FLAG_ENABLED	1
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *mv64x60_regs;
+static int mv64x60_wdt_timeout;
+
+static void mv64x60_wdt_reg_write(u32 val)
+{
+	/* Allow write only to CTL1 / CTL2 fields, retaining values in
+	 * other fields.
+	 */
+	u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
+	data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
+	data |= val;
+	writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+}
+
+static void mv64x60_wdt_service(void)
+{
+	/* Write 01 followed by 10 to CTL2 */
+	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
+	mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+}
+
+static void mv64x60_wdt_handler_disable(void)
+{
+	if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+		/* Write 01 followed by 10 to CTL1 */
+		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+		printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+	}
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+	if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+		/* Write 01 followed by 10 to CTL1 */
+		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+		mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+		printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+	}
+}
+
+static int mv64x60_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+		return -EBUSY;
+
+	mv64x60_wdt_service();
+	mv64x60_wdt_handler_enable();
+
+	return 0;
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+	mv64x60_wdt_service();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+	mv64x60_wdt_handler_disable();
+#endif
+
+	clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
+
+	return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char *data,
+				 size_t len, loff_t * ppos)
+{
+	if (*ppos != file->f_pos)
+		return -ESPIPE;
+
+	if (len)
+		mv64x60_wdt_service();
+
+	return len;
+}
+
+static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	int timeout;
+	static struct watchdog_info info = {
+		.options = WDIOF_KEEPALIVEPING,
+		.firmware_version = 0,
+		.identity = "MV64x60 watchdog",
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		if (put_user(wdt_status, (int *)arg))
+			return -EFAULT;
+		wdt_status &= ~WDIOF_KEEPALIVEPING;
+		break;
+
+	case WDIOC_GETTEMP:
+		return -EOPNOTSUPP;
+
+	case WDIOC_SETOPTIONS:
+		return -EOPNOTSUPP;
+
+	case WDIOC_KEEPALIVE:
+		mv64x60_wdt_service();
+		wdt_status |= WDIOF_KEEPALIVEPING;
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		return -EOPNOTSUPP;
+
+	case WDIOC_GETTIMEOUT:
+		timeout = mv64x60_wdt_timeout * HZ;
+		if (put_user(timeout, (int *)arg))
+			return -EFAULT;
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static struct file_operations mv64x60_wdt_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.write = mv64x60_wdt_write,
+	.ioctl = mv64x60_wdt_ioctl,
+	.open = mv64x60_wdt_open,
+	.release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct device *dev)
+{
+	struct platform_device *pd = to_platform_device(dev);
+	struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data;
+	int bus_clk = 133;
+
+	mv64x60_wdt_timeout = 10;
+	if (pdata) {
+		mv64x60_wdt_timeout = pdata->timeout;
+		bus_clk = pdata->bus_clk;
+	}
+
+	mv64x60_regs = mv64x60_get_bridge_vbase();
+
+	writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
+	       mv64x60_regs + MV64x60_WDT_WDC);
+
+	return misc_register(&mv64x60_wdt_miscdev);
+}
+
+static int __devexit mv64x60_wdt_remove(struct device *dev)
+{
+	misc_deregister(&mv64x60_wdt_miscdev);
+
+	mv64x60_wdt_service();
+	mv64x60_wdt_handler_disable();
+
+	return 0;
+}
+
+static struct device_driver mv64x60_wdt_driver = {
+	.name = MV64x60_WDT_NAME,
+	.bus = &platform_bus_type,
+	.probe = mv64x60_wdt_probe,
+	.remove = __devexit_p(mv64x60_wdt_remove),
+};
+
+static struct platform_device *mv64x60_wdt_dev;
+
+static int __init mv64x60_wdt_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+	mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
+							  -1, NULL, 0);
+	if (IS_ERR(mv64x60_wdt_dev)) {
+		ret = PTR_ERR(mv64x60_wdt_dev);
+		goto out;
+	}
+
+	ret = driver_register(&mv64x60_wdt_driver);
+      out:
+	return ret;
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+	driver_unregister(&mv64x60_wdt_driver);
+	platform_device_unregister(mv64x60_wdt_dev);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 2b13afb..5a80adb 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -29,27 +29,29 @@
  *	Includes, defines, variables, module parameters, ...
  */
 
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
+#include <linux/config.h>	/* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h>	/* For module specific items */
+#include <linux/moduleparam.h>	/* For new moduleparam's */
+#include <linux/types.h>	/* For standard types (like size_t) */
+#include <linux/errno.h>	/* For the -ENODEV/... values */
+#include <linux/kernel.h>	/* For printk/panic/... */
+#include <linux/delay.h>	/* For mdelay function */
+#include <linux/miscdevice.h>	/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h>	/* For the watchdog specific items */
+#include <linux/notifier.h>	/* For notifier support */
+#include <linux/reboot.h>	/* For reboot_notifier stuff */
+#include <linux/init.h>		/* For __init/__exit/... */
+#include <linux/fs.h>		/* For file operations */
+#include <linux/pci.h>		/* For pci functions */
+#include <linux/ioport.h>	/* For io-port access */
+#include <linux/spinlock.h>	/* For spin_lock/spin_unlock/... */
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <asm/uaccess.h>	/* For copy_to_user/put_user/... */
+#include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
 #define WATCHDOG_VERSION "1.01"
-#define WATCHDOG_DATE "15 Mar 2005"
+#define WATCHDOG_DATE "02 Sep 2005"
 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
 #define WATCHDOG_NAME "pcwd_pci"
 #define PFX WATCHDOG_NAME ": "
@@ -335,12 +337,14 @@
 				return -EFAULT;
 
 			if (new_options & WDIOS_DISABLECARD) {
-				pcipcwd_stop();
+				if (pcipcwd_stop())
+					return -EIO;
 				retval = 0;
 			}
 
 			if (new_options & WDIOS_ENABLECARD) {
-				pcipcwd_start();
+				if (pcipcwd_start())
+					return -EIO;
 				retval = 0;
 			}
 
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 8b292bf..3625b26 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -464,7 +464,7 @@
 static unsigned long wtcon_save;
 static unsigned long wtdat_save;
 
-static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level)
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
 {
 	if (level == SUSPEND_POWER_DOWN) {
 		/* Save watchdog state, and turn it off. */
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
new file mode 100644
index 0000000..c6cbf80
--- /dev/null
+++ b/drivers/char/watchdog/sbc8360.c
@@ -0,0 +1,414 @@
+/*
+ *	SBC8360 Watchdog driver
+ *
+ *	(c) Copyright 2005 Webcon, Inc.
+ *
+ *	Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ *      on acquirewdt.c which is based on wdt.c.
+ *
+ *	(c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ *      Based on advantechwdt.c which is based on acquirewdt.c which
+ *       is based on wdt.c.
+ *
+ *	(c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *	Based on acquirewdt.c which is based on wdt.c.
+ *	Original copyright messages:
+ *
+ *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *				http://www.redhat.com
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ *	warranty for any of this software. This material is provided
+ *	"AS-IS" and at no charge.
+ *
+ *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Added timeout module option to override default
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H.  To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H.  To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ *		N
+ *	M |	1	2	3	4
+ *	--|----------------------------------
+ *	0 |	0.5s	5s	50s	100s
+ *	1 |	1s	10s	100s	200s
+ *	2 |	1.5s	15s	150s	300s
+ *	3 |	2s	20s	200s	400s
+ *	4 |	2.5s	25s	250s	500s
+ *	5 |	3s	30s	300s	600s
+ *	6 |	3.5s	35s	350s	700s
+ *	7 |	4s	40s	400s	800s
+ *	8 |	4.5s	45s	450s	900s
+ *	9 |	5s	50s	500s	1000s
+ *	A |	5.5s	55s	550s	1100s
+ *	B |	6s	60s	600s	1200s
+ *	C |	6.5s	65s	650s	1300s
+ *	D |	7s	70s	700s	1400s
+ *	E |	7.5s	75s	750s	1500s
+ *	F |	8s	80s 	800s 	1600s
+ *
+ * Another way to say the same things is:
+ *  For N=1, Timeout = (M+1) * 0.5s
+ *  For N=2, Timeout = (M+1) * 5s
+ *  For N=3, Timeout = (M+1) * 50s
+ *  For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+	{0, 1},			/* 0  = 0.5s */
+	{1, 1},			/* 1  = 1s   */
+	{2, 1},			/* 2  = 1.5s */
+	{3, 1},			/* 3  = 2s   */
+	{4, 1},			/* 4  = 2.5s */
+	{5, 1},			/* 5  = 3s   */
+	{6, 1},			/* 6  = 3.5s */
+	{7, 1},			/* 7  = 4s   */
+	{8, 1},			/* 8  = 4.5s */
+	{9, 1},			/* 9  = 5s   */
+	{0xA, 1},		/* 10 = 5.5s */
+	{0xB, 1},		/* 11 = 6s   */
+	{0xC, 1},		/* 12 = 6.5s */
+	{0xD, 1},		/* 13 = 7s   */
+	{0xE, 1},		/* 14 = 7.5s */
+	{0xF, 1},		/* 15 = 8s   */
+	{0, 2},			/* 16 = 5s  */
+	{1, 2},			/* 17 = 10s */
+	{2, 2},			/* 18 = 15s */
+	{3, 2},			/* 19 = 20s */
+	{4, 2},			/* 20 = 25s */
+	{5, 2},			/* 21 = 30s */
+	{6, 2},			/* 22 = 35s */
+	{7, 2},			/* 23 = 40s */
+	{8, 2},			/* 24 = 45s */
+	{9, 2},			/* 25 = 50s */
+	{0xA, 2},		/* 26 = 55s */
+	{0xB, 2},		/* 27 = 60s */
+	{0xC, 2},		/* 28 = 65s */
+	{0xD, 2},		/* 29 = 70s */
+	{0xE, 2},		/* 30 = 75s */
+	{0xF, 2},		/* 31 = 80s */
+	{0, 3},			/* 32 = 50s  */
+	{1, 3},			/* 33 = 100s */
+	{2, 3},			/* 34 = 150s */
+	{3, 3},			/* 35 = 200s */
+	{4, 3},			/* 36 = 250s */
+	{5, 3},			/* 37 = 300s */
+	{6, 3},			/* 38 = 350s */
+	{7, 3},			/* 39 = 400s */
+	{8, 3},			/* 40 = 450s */
+	{9, 3},			/* 41 = 500s */
+	{0xA, 3},		/* 42 = 550s */
+	{0xB, 3},		/* 43 = 600s */
+	{0xC, 3},		/* 44 = 650s */
+	{0xD, 3},		/* 45 = 700s */
+	{0xE, 3},		/* 46 = 750s */
+	{0xF, 3},		/* 47 = 800s */
+	{0, 4},			/* 48 = 100s */
+	{1, 4},			/* 49 = 200s */
+	{2, 4},			/* 50 = 300s */
+	{3, 4},			/* 51 = 400s */
+	{4, 4},			/* 52 = 500s */
+	{5, 4},			/* 53 = 600s */
+	{6, 4},			/* 54 = 700s */
+	{7, 4},			/* 55 = 800s */
+	{8, 4},			/* 56 = 900s */
+	{9, 4},			/* 57 = 1000s */
+	{0xA, 4},		/* 58 = 1100s */
+	{0xB, 4},		/* 59 = 1200s */
+	{0xC, 4},		/* 60 = 1300s */
+	{0xD, 4},		/* 61 = 1400s */
+	{0xE, 4},		/* 62 = 1500s */
+	{0xF, 4}		/* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 27);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+		 "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ *	Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+	/* Enable the watchdog */
+	outb(0x0A, SBC8360_ENABLE);
+	msleep_interruptible(100);
+	outb(0x0B, SBC8360_ENABLE);
+	msleep_interruptible(100);
+	/* Set timeout multiplier */
+	outb(wd_multiplier, SBC8360_ENABLE);
+	msleep_interruptible(100);
+	/* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+	/* Write the base timer register */
+	outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+			     size_t count, loff_t * ppos)
+{
+	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			/* In case it was set long ago */
+			expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = 42;
+			}
+		}
+		sbc8360_ping();
+	}
+	return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+	spin_lock(&sbc8360_lock);
+	if (test_and_set_bit(0, &sbc8360_is_open)) {
+		spin_unlock(&sbc8360_lock);
+		return -EBUSY;
+	}
+	if (nowayout)
+		__module_get(THIS_MODULE);
+
+	/* Activate and ping once to start the countdown */
+	spin_unlock(&sbc8360_lock);
+	sbc8360_activate();
+	sbc8360_ping();
+	return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+	spin_lock(&sbc8360_lock);
+	if (expect_close == 42)
+		outb(0, SBC8360_ENABLE);
+	else
+		printk(KERN_CRIT PFX
+		       "SBC8360 device closed unexpectedly.  SBC8360 will not stop!\n");
+
+	clear_bit(0, &sbc8360_is_open);
+	expect_close = 0;
+	spin_unlock(&sbc8360_lock);
+	return 0;
+}
+
+/*
+ *	Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+			      void *unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT) {
+		/* Disable the SBC8360 Watchdog */
+		outb(0, SBC8360_ENABLE);
+	}
+	return NOTIFY_DONE;
+}
+
+/*
+ *	Kernel Interfaces
+ */
+
+static struct file_operations sbc8360_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.write = sbc8360_write,
+	.open = sbc8360_open,
+	.release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &sbc8360_fops,
+};
+
+/*
+ *	The SBC8360 needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+	.notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+	int res;
+	unsigned long int mseconds = 60000;
+
+	spin_lock_init(&sbc8360_lock);
+	res = misc_register(&sbc8360_miscdev);
+	if (res) {
+		printk(KERN_ERR PFX "failed to register misc device\n");
+		goto out_nomisc;
+	}
+
+	if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+		printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+		       SBC8360_ENABLE);
+		res = -EIO;
+		goto out_noenablereg;
+	}
+	if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+		printk(KERN_ERR PFX
+		       "BASETIME method I/O %X is not available.\n",
+		       SBC8360_BASETIME);
+		res = -EIO;
+		goto out_nobasetimereg;
+	}
+
+	res = register_reboot_notifier(&sbc8360_notifier);
+	if (res) {
+		printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+		goto out_noreboot;
+	}
+
+	if (timeout < 0 || timeout > 63) {
+		printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+		res = -EINVAL;
+		goto out_noreboot;
+	}
+
+	wd_margin = wd_times[timeout][0];
+	wd_multiplier = wd_times[timeout][1];
+
+	if (wd_multiplier == 1)
+		mseconds = (wd_margin + 1) * 500;
+	else if (wd_multiplier == 2)
+		mseconds = (wd_margin + 1) * 5000;
+	else if (wd_multiplier == 3)
+		mseconds = (wd_margin + 1) * 50000;
+	else if (wd_multiplier == 4)
+		mseconds = (wd_margin + 1) * 100000;
+
+	/* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+	printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+	return 0;
+
+      out_noreboot:
+	release_region(SBC8360_ENABLE, 1);
+	release_region(SBC8360_BASETIME, 1);
+      out_noenablereg:
+      out_nobasetimereg:
+	misc_deregister(&sbc8360_miscdev);
+      out_nomisc:
+	return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+	misc_deregister(&sbc8360_miscdev);
+	unregister_reboot_notifier(&sbc8360_notifier);
+	release_region(SBC8360_ENABLE, 1);
+	release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* end of sbc8360.c */
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c
new file mode 100644
index 0000000..a7ff64c
--- /dev/null
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -0,0 +1,543 @@
+/*
+ *	W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ *	(c) Copyright 2005  Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ *      Based on w83877f_wdt.c by Scott Jennings,
+ *           and wdt977.c by Woody Suwalski
+ *
+ *			-----------------------
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION  "1.00"
+#define WATCHDOG_NAME     "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION    WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT     0x3F0
+#define IO_DATA_PORT      (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA       0x87
+#define LOCK_DATA         0xAA
+#define DEVICE_REGISTER   0x07
+
+#define	DEFAULT_TIMEOUT   45		/* default timeout in seconds */
+
+static	int timeout = DEFAULT_TIMEOUT;
+static	int timeoutW;			/* timeout in watchdog counter units */
+static	unsigned long timer_alive;
+static	int testmode;
+static	char expect_close;
+static	spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&spinlock, flags);
+
+	/* Unlock the SuperIO chip */
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+	/*
+	 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+	 * F2 has the timeout in watchdog counter units.
+	 * F3 is set to enable watchdog LED blink at timeout.
+	 * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+	 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+	outb_p(0xF2,IO_INDEX_PORT);
+	outb_p(timeoutW,IO_DATA_PORT);
+	outb_p(0xF3,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+	outb_p(0xF4,IO_INDEX_PORT);
+	outb_p(0x00,IO_DATA_PORT);
+
+	/* Set device Aux2 active */
+	outb_p(0x30,IO_INDEX_PORT);
+	outb_p(0x01,IO_DATA_PORT);
+
+	/* 
+	 * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+	 * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+	 * Map GP16 at pin 119.
+	 * In test mode watch the bit 0 on F4 to indicate "triggered" or
+	 * check watchdog LED on SBC.
+	 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x07,IO_DATA_PORT);
+	if (!testmode)
+	{
+		unsigned pin_map;
+
+		outb_p(0xE6,IO_INDEX_PORT);
+		outb_p(0x0A,IO_DATA_PORT);
+		outb_p(0x2C,IO_INDEX_PORT);
+		pin_map = inb_p(IO_DATA_PORT);
+		pin_map |= 0x10;
+		pin_map &= ~(0x20);
+		outb_p(0x2C,IO_INDEX_PORT);
+		outb_p(pin_map,IO_DATA_PORT);
+	}
+	outb_p(0xE3,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+
+	/* Set device Aux1 active */
+	outb_p(0x30,IO_INDEX_PORT);
+	outb_p(0x01,IO_DATA_PORT);
+
+	/* Lock the SuperIO chip */
+	outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+	spin_unlock_irqrestore(&spinlock, flags);
+
+	printk(KERN_INFO PFX "activated.\n");
+
+	return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&spinlock, flags);
+
+	/* Unlock the SuperIO chip */
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+	/* 
+	 * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+	 * F2 is reset to its default value (watchdog timer disabled).
+	 * F3 is reset to its default state.
+	 * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+	 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+	outb_p(0xF2,IO_INDEX_PORT);
+	outb_p(0xFF,IO_DATA_PORT);
+	outb_p(0xF3,IO_INDEX_PORT);
+	outb_p(0x00,IO_DATA_PORT);
+	outb_p(0xF4,IO_INDEX_PORT);
+	outb_p(0x00,IO_DATA_PORT);
+	outb_p(0xF2,IO_INDEX_PORT);
+	outb_p(0x00,IO_DATA_PORT);
+
+	/*
+	 * Select device Aux1 (dev=7) to set GP16 (in reg E6) and 
+	 * Gp13 (in reg E3) as inputs.
+	 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x07,IO_DATA_PORT);
+	if (!testmode)
+	{
+		outb_p(0xE6,IO_INDEX_PORT);
+		outb_p(0x01,IO_DATA_PORT);
+	}
+	outb_p(0xE3,IO_INDEX_PORT);
+	outb_p(0x01,IO_DATA_PORT);
+
+	/* Lock the SuperIO chip */
+	outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+	spin_unlock_irqrestore(&spinlock, flags);
+
+	printk(KERN_INFO PFX "shutdown.\n");
+
+	return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&spinlock, flags);
+
+	/* Unlock the SuperIO chip */
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+	/* Select device Aux2 (device=8) to kick watchdog reg F2 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+	outb_p(0xF2,IO_INDEX_PORT);
+	outb_p(timeoutW,IO_DATA_PORT);
+
+	/* Lock the SuperIO chip */
+	outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+	spin_unlock_irqrestore(&spinlock, flags);
+
+	return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+	int tmrval;
+
+	/*
+	 * Convert seconds to watchdog counter time units, rounding up.
+	 * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup 
+	 * value. This information is supplied in the PCM-5335 manual and was
+	 * checked by me on a real board. This is a bit strange because W83977f
+	 * datasheet says counter unit is in minutes!
+	 */
+	if (t < 15)
+		return -EINVAL;
+
+	tmrval = ((t + 15) + 29) / 30;
+
+	if (tmrval > 255)
+		return -EINVAL;
+
+	/*
+	 * timeout is the timeout in seconds, 
+	 * timeoutW is the timeout in watchdog counter units.
+	 */
+	timeoutW = tmrval;
+	timeout = (timeoutW * 30) - 15;
+	return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+	int new_status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&spinlock, flags);
+
+	/* Unlock the SuperIO chip */
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+	outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+	/* Select device Aux2 (device=8) to read watchdog reg F4 */
+	outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+	outb_p(0x08,IO_DATA_PORT);
+	outb_p(0xF4,IO_INDEX_PORT);
+	new_status = inb_p(IO_DATA_PORT);
+
+	/* Lock the SuperIO chip */
+	outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+	spin_unlock_irqrestore(&spinlock, flags);
+
+	*status = 0;
+	if (new_status & 1)
+		*status |= WDIOF_CARDRESET;
+
+	return 0;
+}
+
+
+/*
+ *	/dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+	/* If the watchdog is alive we don't need to start it again */
+	if( test_and_set_bit(0, &timer_alive) )
+		return -EBUSY;
+
+	if (nowayout)
+		__module_get(THIS_MODULE);
+
+	wdt_start();
+	return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+	/*
+	 * Shut off the timer.
+	 * Lock it in if it's a module and we set nowayout
+	 */
+	if (expect_close == 42)
+	{
+		wdt_stop();
+		clear_bit(0, &timer_alive);
+	} else {
+		wdt_keepalive();
+		printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+	}
+	expect_close = 0;
+	return 0;
+}
+
+/*
+ *      wdt_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+			    size_t count, loff_t *ppos)
+{
+	/* See if we got the magic character 'V' and reload the timer */
+	if(count)
+	{
+		if (!nowayout)
+		{
+			size_t ofs;
+
+			/* note: just in case someone wrote the magic character long ago */
+			expect_close = 0;
+
+			/* scan to see whether or not we got the magic character */
+			for(ofs = 0; ofs != count; ofs++)
+			{
+				char c;
+				if (get_user(c, buf + ofs))
+					return -EFAULT;
+				if (c == 'V') {
+					expect_close = 42;
+				}
+			}
+		}
+
+		/* someone wrote to us, we should restart timer */
+		wdt_keepalive();
+	}
+	return count;
+}
+
+/*
+ *      wdt_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static struct watchdog_info ident = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.firmware_version =	1,
+	.identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	int status;
+	int new_options, retval = -EINVAL;
+	int new_timeout;
+	union {
+		struct watchdog_info __user *ident;
+		int __user *i;
+	} uarg;
+
+	uarg.i = (int __user *)arg;
+
+	switch(cmd)
+	{
+	default:
+		return -ENOIOCTLCMD;
+
+	case WDIOC_GETSUPPORT:
+		return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETSTATUS:
+		wdt_get_status(&status);
+		return put_user(status, uarg.i);
+
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, uarg.i);
+
+	case WDIOC_KEEPALIVE:
+		wdt_keepalive();
+		return 0;
+
+	case WDIOC_SETOPTIONS:
+		if (get_user (new_options, uarg.i))
+			return -EFAULT;
+
+		if (new_options & WDIOS_DISABLECARD) {
+			wdt_stop();
+			retval = 0;
+		}
+
+		if (new_options & WDIOS_ENABLECARD) {
+			wdt_start();
+			retval = 0;
+		}
+
+		return retval;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_timeout, uarg.i))
+			return -EFAULT;
+
+		if (wdt_set_timeout(new_timeout))
+		    return -EINVAL;
+
+		wdt_keepalive();
+		/* Fall */
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(timeout, uarg.i);
+
+	}
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+	void *unused)
+{
+	if (code==SYS_DOWN || code==SYS_HALT)
+		wdt_stop();
+	return NOTIFY_DONE;
+}
+
+static struct file_operations wdt_fops=
+{
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= wdt_write,
+	.ioctl		= wdt_ioctl,
+	.open		= wdt_open,
+	.release	= wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+	.notifier_call = wdt_notify_sys,
+};
+
+static int __init w83977f_wdt_init(void)
+{
+	int rc;
+
+        printk(KERN_INFO PFX DRIVER_VERSION);
+
+	spin_lock_init(&spinlock);
+
+	/*
+	 * Check that the timeout value is within it's range ; 
+	 * if not reset to the default
+	 */
+	if (wdt_set_timeout(timeout)) {
+		wdt_set_timeout(DEFAULT_TIMEOUT);
+		printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+			DEFAULT_TIMEOUT);
+	}
+
+	if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+	{
+		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+			IO_INDEX_PORT);
+		rc = -EIO;
+		goto err_out;
+	}
+
+	rc = misc_register(&wdt_miscdev);
+	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+			wdt_miscdev.minor, rc);
+		goto err_out_region;
+	}
+
+	rc = register_reboot_notifier(&wdt_notifier);
+	if (rc)
+	{
+		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+			rc);
+		goto err_out_miscdev;
+	}
+
+	printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+		timeout, nowayout, testmode);
+
+	return 0;
+
+err_out_miscdev:
+	misc_deregister(&wdt_miscdev);
+err_out_region:
+	release_region(IO_INDEX_PORT,2);
+err_out:
+	return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+	wdt_stop();
+	misc_deregister(&wdt_miscdev);
+	unregister_reboot_notifier(&wdt_notifier);
+	release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 138dc50..7e72e92 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -411,6 +411,23 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
 
+config SENSORS_HDAPS
+	tristate "IBM Hard Drive Active Protection System (hdaps)"
+	depends on HWMON && INPUT && X86
+	default n
+	help
+	  This driver provides support for the IBM Hard Drive Active Protection
+	  System (hdaps), which provides an accelerometer and other misc. data.
+	  Supported laptops include the IBM ThinkPad T41, T42, T43, and R51.
+	  The accelerometer data is readable via sysfs.
+
+	  This driver also provides an input class device, allowing the
+	  laptop to act as a pinball machine-esque mouse.  This is off by
+	  default but enabled via sysfs or the module parameter "mousedev".
+
+	  Say Y here if you have an applicable laptop and want to experience
+	  the awesome power of hdaps.
+
 config HWMON_DEBUG_CHIP
 	bool "Hardware Monitoring Chip debugging messages"
 	depends on HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 381f1bf..f7d6a2f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_SENSORS_FSCPOS)	+= fscpos.o
 obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
+obj-$(CONFIG_SENSORS_HDAPS)	+= hdaps.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
new file mode 100644
index 0000000..eaebfc1
--- /dev/null
+++ b/drivers/hwmon/hdaps.c
@@ -0,0 +1,739 @@
+/*
+ * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
+ *
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
+ * T41, T42, T43, R51, and X40, at least.  It provides a basic two-axis
+ * accelerometer and other data, such as the device's temperature.
+ *
+ * Based on the document by Mark A. Smith available at
+ * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
+ * and error.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <asm/io.h>
+
+#define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
+#define HDAPS_NR_PORTS		0x30	/* 0x1600 - 0x162f */
+
+#define STATE_FRESH		0x50	/* accelerometer data is fresh */
+
+#define REFRESH_ASYNC		0x00	/* do asynchronous refresh */
+#define REFRESH_SYNC		0x01	/* do synchronous refresh */
+
+#define HDAPS_PORT_STATE	0x1611	/* device state */
+#define HDAPS_PORT_YPOS		0x1612	/* y-axis position */
+#define	HDAPS_PORT_XPOS		0x1614	/* x-axis position */
+#define HDAPS_PORT_TEMP1	0x1616	/* device temperature, in celcius */
+#define HDAPS_PORT_YVAR		0x1617	/* y-axis variance (what is this?) */
+#define HDAPS_PORT_XVAR		0x1619	/* x-axis variance (what is this?) */
+#define HDAPS_PORT_TEMP2	0x161b	/* device temperature (again?) */
+#define HDAPS_PORT_UNKNOWN	0x161c	/* what is this? */
+#define HDAPS_PORT_KMACT	0x161d	/* keyboard or mouse activity */
+
+#define HDAPS_READ_MASK		0xff	/* some reads have the low 8 bits set */
+
+#define KEYBD_MASK		0x20	/* set if keyboard activity */
+#define MOUSE_MASK		0x40	/* set if mouse activity */
+#define KEYBD_ISSET(n)		(!! (n & KEYBD_MASK))	/* keyboard used? */
+#define MOUSE_ISSET(n)		(!! (n & MOUSE_MASK))	/* mouse used? */
+
+#define INIT_TIMEOUT_MSECS	4000	/* wait up to 4s for device init ... */
+#define INIT_WAIT_MSECS		200	/* ... in 200ms increments */
+
+static struct platform_device *pdev;
+static struct input_dev hdaps_idev;
+static struct timer_list hdaps_timer;
+static unsigned int hdaps_mousedev_threshold = 4;
+static unsigned long hdaps_poll_ms = 50;
+static unsigned int hdaps_mousedev;
+static unsigned int hdaps_invert;
+static u8 km_activity;
+static int rest_x;
+static int rest_y;
+
+static DECLARE_MUTEX(hdaps_sem);
+
+/*
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_sem.
+ */
+static inline u8 __get_latch(u16 port)
+{
+	return inb(port) & HDAPS_READ_MASK;
+}
+
+/*
+ * __check_latch - Check a port latch for a given value.  Callers must hold
+ * hdaps_sem.  Returns zero if the port contains the given value.
+ */
+static inline unsigned int __check_latch(u16 port, u8 val)
+{
+	if (__get_latch(port) == val)
+		return 0;
+	return -EINVAL;
+}
+
+/*
+ * __wait_latch - Wait up to 100us for a port latch to get a certain value,
+ * returning zero if the value is obtained.  Callers must hold hdaps_sem.
+ */
+static unsigned int __wait_latch(u16 port, u8 val)
+{
+	unsigned int i;
+
+	for (i = 0; i < 20; i++) {
+		if (!__check_latch(port, val))
+			return 0;
+		udelay(5);
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * __device_refresh - Request a refresh from the accelerometer.
+ *
+ * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
+ * Returns zero if successful and nonzero on error.
+ *
+ * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
+ * not up-to-date.  Always returns zero.
+ *
+ * Callers must hold hdaps_sem.
+ */
+static int __device_refresh(unsigned int sync)
+{
+	u8 state;
+
+	udelay(100);
+
+	state = inb(0x1604);
+	if (state == STATE_FRESH)
+		return 0;
+
+	outb(0x11, 0x1610);
+	outb(0x01, 0x161f);
+	if (sync == REFRESH_ASYNC)
+		return 0;
+
+	return __wait_latch(0x1604, STATE_FRESH);
+}
+
+/*
+ * __device_complete - Indicate to the accelerometer that we are done reading
+ * data, and then initiate an async refresh.  Callers must hold hdaps_sem.
+ */
+static inline void __device_complete(void)
+{
+	inb(0x161f);
+	inb(0x1604);
+	__device_refresh(REFRESH_ASYNC);
+}
+
+static int __hdaps_readb_one(unsigned int port, u8 *val)
+{
+	/* do a sync refresh -- we need to be sure that we read fresh data */
+	if (__device_refresh(REFRESH_SYNC))
+		return -EIO;
+
+	*val = inb(port);
+	__device_complete();
+
+	return 0;
+}
+
+/*
+ * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
+ * the given pointer.  Returns zero on success or a negative error on failure.
+ * Can sleep.
+ */
+static int hdaps_readb_one(unsigned int port, u8 *val)
+{
+	int ret;
+
+	down(&hdaps_sem);
+	ret = __hdaps_readb_one(port, val);
+	up(&hdaps_sem);
+
+	return ret;
+}
+
+static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
+			     int *x, int *y)
+{
+	/* do a sync refresh -- we need to be sure that we read fresh data */
+	if (__device_refresh(REFRESH_SYNC))
+		return -EIO;
+
+	*y = inw(port2);
+	*x = inw(port1);
+	km_activity = inb(HDAPS_PORT_KMACT);
+	__device_complete();
+
+	/* if hdaps_invert is set, negate the two values */
+	if (hdaps_invert) {
+		*x = -*x;
+		*y = -*y;
+	}
+
+	return 0;
+}
+
+/*
+ * hdaps_read_pair - reads the values from a pair of ports, placing the values
+ * in the given pointers.  Returns zero on success.  Can sleep.
+ */
+static int hdaps_read_pair(unsigned int port1, unsigned int port2,
+			   int *val1, int *val2)
+{
+	int ret;
+
+	down(&hdaps_sem);
+	ret = __hdaps_read_pair(port1, port2, val1, val2);
+	up(&hdaps_sem);
+
+	return ret;
+}
+
+/* initialize the accelerometer */
+static int hdaps_device_init(void)
+{
+	unsigned int total_msecs = INIT_TIMEOUT_MSECS;
+	int ret = -ENXIO;
+
+	down(&hdaps_sem);
+
+	outb(0x13, 0x1610);
+	outb(0x01, 0x161f);
+	if (__wait_latch(0x161f, 0x00))
+		goto out;
+
+	/*
+	 * The 0x03 value appears to only work on some thinkpads, such as the
+	 * T42p.  Others return 0x01.
+	 *
+	 * The 0x02 value occurs when the chip has been previously initialized.
+	 */
+	if (__check_latch(0x1611, 0x03) &&
+		     __check_latch(0x1611, 0x02) &&
+		     __check_latch(0x1611, 0x01))
+		goto out;
+
+	printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
+	       __get_latch(0x1611));
+
+	outb(0x17, 0x1610);
+	outb(0x81, 0x1611);
+	outb(0x01, 0x161f);
+	if (__wait_latch(0x161f, 0x00))
+		goto out;
+	if (__wait_latch(0x1611, 0x00))
+		goto out;
+	if (__wait_latch(0x1612, 0x60))
+		goto out;
+	if (__wait_latch(0x1613, 0x00))
+		goto out;
+	outb(0x14, 0x1610);
+	outb(0x01, 0x1611);
+	outb(0x01, 0x161f);
+	if (__wait_latch(0x161f, 0x00))
+		goto out;
+	outb(0x10, 0x1610);
+	outb(0xc8, 0x1611);
+	outb(0x00, 0x1612);
+	outb(0x02, 0x1613);
+	outb(0x01, 0x161f);
+	if (__wait_latch(0x161f, 0x00))
+		goto out;
+	if (__device_refresh(REFRESH_SYNC))
+		goto out;
+	if (__wait_latch(0x1611, 0x00))
+		goto out;
+
+	/* we have done our dance, now let's wait for the applause */
+	while (total_msecs > 0) {
+		u8 ignored;
+
+		/* a read of the device helps push it into action */
+		__hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+		if (!__wait_latch(0x1611, 0x02)) {
+			ret = 0;
+			break;
+		}
+
+		msleep(INIT_WAIT_MSECS);
+		total_msecs -= INIT_WAIT_MSECS;
+	}
+
+out:
+	up(&hdaps_sem);
+	return ret;
+}
+
+
+/* Input class stuff */
+
+/*
+ * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+	int x, y;
+
+	if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+		return;
+
+	rest_x = x;
+	rest_y = y;
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+	int x, y;
+
+	/* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
+	if (down_trylock(&hdaps_sem)) {
+		mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
+		return;
+	}
+
+	if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+		goto out;
+
+	x -= rest_x;
+	y -= rest_y;
+	if (abs(x) > hdaps_mousedev_threshold)
+		input_report_rel(&hdaps_idev, REL_X, x);
+	if (abs(y) > hdaps_mousedev_threshold)
+		input_report_rel(&hdaps_idev, REL_Y, y);
+	input_sync(&hdaps_idev);
+
+	mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
+
+out:
+	up(&hdaps_sem);
+}
+
+/*
+ * hdaps_mousedev_enable - enable the input class device.  Can sleep.
+ */
+static void hdaps_mousedev_enable(void)
+{
+	down(&hdaps_sem);
+
+	/* calibrate the device before enabling */
+	hdaps_calibrate();
+
+	/* initialize the input class */
+	init_input_dev(&hdaps_idev);
+	hdaps_idev.dev = &pdev->dev;
+	hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
+	input_register_device(&hdaps_idev);
+
+	/* start up our timer */
+	init_timer(&hdaps_timer);
+	hdaps_timer.function = hdaps_mousedev_poll;
+	hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
+	add_timer(&hdaps_timer);
+
+	hdaps_mousedev = 1;
+
+	up(&hdaps_sem);
+
+	printk(KERN_INFO "hdaps: input device enabled.\n");
+}
+
+/*
+ * hdaps_mousedev_disable - disable the input class device.  Caller must hold
+ * hdaps_sem.
+ */
+static void hdaps_mousedev_disable(void)
+{
+	down(&hdaps_sem);
+	if (hdaps_mousedev) {
+		hdaps_mousedev = 0;
+		del_timer_sync(&hdaps_timer);
+		input_unregister_device(&hdaps_idev);
+	}
+	up(&hdaps_sem);
+}
+
+
+/* Device model stuff */
+
+static int hdaps_probe(struct device *dev)
+{
+	int ret;
+
+	ret = hdaps_device_init();
+	if (ret)
+		return ret;
+
+	printk(KERN_INFO "hdaps: device successfully initialized.\n");
+	return 0;
+}
+
+static int hdaps_resume(struct device *dev, u32 level)
+{
+	if (level == RESUME_ENABLE)
+		return hdaps_device_init();
+	return 0;
+}
+
+static struct device_driver hdaps_driver = {
+	.name = "hdaps",
+	.bus = &platform_bus_type,
+	.owner = THIS_MODULE,
+	.probe = hdaps_probe,
+	.resume = hdaps_resume
+};
+
+
+/* Sysfs Files */
+
+static ssize_t hdaps_position_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	int ret, x, y;
+
+	ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_variance_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	int ret, x, y;
+
+	ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_temp1_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	u8 temp;
+	int ret;
+
+	ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_temp2_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	u8 temp;
+	int ret;
+
+	ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_keyboard_activity_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
+}
+
+static ssize_t hdaps_mouse_activity_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
+}
+
+static ssize_t hdaps_calibrate_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t hdaps_calibrate_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	down(&hdaps_sem);
+	hdaps_calibrate();
+	up(&hdaps_sem);
+
+	return count;
+}
+
+static ssize_t hdaps_invert_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", hdaps_invert);
+}
+
+static ssize_t hdaps_invert_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	int invert;
+
+	if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0))
+		return -EINVAL;
+
+	hdaps_invert = invert;
+	hdaps_calibrate();
+
+	return count;
+}
+
+static ssize_t hdaps_mousedev_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", hdaps_mousedev);
+}
+
+static ssize_t hdaps_mousedev_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	int enable;
+
+	if (sscanf(buf, "%d", &enable) != 1)
+		return -EINVAL;
+
+	if (enable == 1)
+		hdaps_mousedev_enable();
+	else if (enable == 0)
+		hdaps_mousedev_disable();
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t hdaps_poll_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", hdaps_poll_ms);
+}
+
+static ssize_t hdaps_poll_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	unsigned int poll;
+
+	if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
+		return -EINVAL;
+	hdaps_poll_ms = poll;
+
+	return count;
+}
+
+static ssize_t hdaps_threshold_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
+}
+
+static ssize_t hdaps_threshold_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	unsigned int threshold;
+
+	if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
+		return -EINVAL;
+	hdaps_mousedev_threshold = threshold;
+
+	return count;
+}
+
+static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
+static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
+static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
+static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
+static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
+static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
+static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
+static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
+static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
+static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
+static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
+		   hdaps_threshold_store);
+
+static struct attribute *hdaps_attributes[] = {
+	&dev_attr_position.attr,
+	&dev_attr_variance.attr,
+	&dev_attr_temp1.attr,
+	&dev_attr_temp2.attr,
+	&dev_attr_keyboard_activity.attr,
+	&dev_attr_mouse_activity.attr,
+	&dev_attr_calibrate.attr,
+	&dev_attr_mousedev.attr,
+	&dev_attr_mousedev_threshold.attr,
+	&dev_attr_mousedev_poll_ms.attr,
+	&dev_attr_invert.attr,
+	NULL,
+};
+
+static struct attribute_group hdaps_attribute_group = {
+	.attrs = hdaps_attributes,
+};
+
+
+/* Module stuff */
+
+/*
+ * XXX: We should be able to return nonzero and halt the detection process.
+ * But there is a bug in dmi_check_system() where a nonzero return from the
+ * first match will result in a return of failure from dmi_check_system().
+ * I fixed this; the patch is in 2.6-mm.  Once in Linus's tree we can make
+ * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
+ */
+static int hdaps_dmi_match(struct dmi_system_id *id)
+{
+	printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
+	return 0;
+}
+
+static int hdaps_dmi_match_invert(struct dmi_system_id *id)
+{
+	hdaps_invert = 1;
+	printk(KERN_INFO "hdaps: inverting axis readings.\n");
+	return 0;
+}
+
+#define HDAPS_DMI_MATCH_NORMAL(model)	{		\
+	.ident = "IBM " model,				\
+	.callback = hdaps_dmi_match,			\
+	.matches = {					\
+		DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),	\
+		DMI_MATCH(DMI_PRODUCT_VERSION, model)	\
+	}						\
+}
+
+#define HDAPS_DMI_MATCH_INVERT(model)	{		\
+	.ident = "IBM " model,				\
+	.callback = hdaps_dmi_match_invert,		\
+	.matches = {					\
+		DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),	\
+		DMI_MATCH(DMI_PRODUCT_VERSION, model)	\
+	}						\
+}
+
+static int __init hdaps_init(void)
+{
+	int ret;
+
+	/* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
+	struct dmi_system_id hdaps_whitelist[] = {
+		HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
+		HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
+		HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+		{ .ident = NULL }
+	};
+
+	if (!dmi_check_system(hdaps_whitelist)) {
+		printk(KERN_WARNING "hdaps: supported laptop not found!\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	ret = driver_register(&hdaps_driver);
+	if (ret)
+		goto out_region;
+
+	pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
+	if (IS_ERR(pdev)) {
+		ret = PTR_ERR(pdev);
+		goto out_driver;
+	}
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
+	if (ret)
+		goto out_device;
+
+	if (hdaps_mousedev)
+		hdaps_mousedev_enable();
+
+	printk(KERN_INFO "hdaps: driver successfully loaded.\n");
+	return 0;
+
+out_device:
+	platform_device_unregister(pdev);
+out_driver:
+	driver_unregister(&hdaps_driver);
+out_region:
+	release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+out:
+	printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
+	return ret;
+}
+
+static void __exit hdaps_exit(void)
+{
+	hdaps_mousedev_disable();
+
+	sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+	platform_device_unregister(pdev);
+	driver_unregister(&hdaps_driver);
+	release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+
+	printk(KERN_INFO "hdaps: driver unloaded.\n");
+}
+
+module_init(hdaps_init);
+module_exit(hdaps_exit);
+
+module_param_named(mousedev, hdaps_mousedev, bool, 0);
+MODULE_PARM_DESC(mousedev, "enable the input class device");
+
+module_param_named(invert, hdaps_invert, bool, 0);
+MODULE_PARM_DESC(invert, "invert data along each axis");
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 8610bce..21aa9a4 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -758,11 +758,6 @@
 		return -ENODEV;
 	}
 
-	if (!address) {
-		dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
-		return -ENODEV;
-	}
-
 	s_bridge = pci_dev_get(dev);
 	if (i2c_isa_add_driver(&sis5595_driver)) {
 		pci_dev_put(s_bridge);
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 7e699a8..c9cc683 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -2,8 +2,8 @@
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
                  for hardware monitoring
 
-    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
-    Super-I/O chips.
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
+    LPC47M15x and LPC47M192 Super-I/O chips.
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index eb84997..05ddc88 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -812,11 +812,6 @@
 		return -ENODEV;
 	}
 
-	if (!address) {
-		dev_err(&dev->dev, "No Via 686A sensors found.\n");
-		return -ENODEV;
-	}
-
 	s_bridge = pci_dev_get(dev);
 	if (i2c_isa_add_driver(&via686a_driver)) {
 		pci_dev_put(s_bridge);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 02bd5c0..3479dc5 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -64,6 +64,10 @@
 /* Insmod parameters */
 enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
 
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to reset chip on load");
+
 static int init = 1;
 module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
@@ -1279,7 +1283,15 @@
 	int type = data->type;
 	u8 tmp;
 
-	if(init) {
+	if (reset) {
+		/* Resetting the chip has been the default for a long time,
+		   but repeatedly caused problems (fans going to full
+		   speed...) so it is now optional. It might even go away if
+		   nobody reports it as being useful, as I see very little
+		   reason why this would be needed at all. */
+		dev_info(&client->dev, "If reset=1 solved a problem you were "
+			 "having, please report!\n");
+
 		/* save this register */
 		i = w83627hf_read_value(client, W83781D_REG_BEEP_CONFIG);
 		/* Reset all except Watchdog values and last conversion values
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 37b49c2..eff5896 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -611,7 +611,6 @@
 	
 	for (i=0; i<nchan; i++) {
 		struct keywest_chan* chan = &iface->channels[i];
-		u8 addr;
 		
 		sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
 		chan->iface = iface;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index e0b7a91..fe9c0f4 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -98,11 +98,6 @@
 #define NVIDIA_SMB_PRTCL_PEC			0x80
 
 
-/* Other settings */
-#define MAX_TIMEOUT 256
-
-
-
 static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
 		       unsigned short flags, char read_write,
 		       u8 command, int size, union i2c_smbus_data *data);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b443b04..0b0aa4f 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -601,44 +601,15 @@
  */
 u8 eighty_ninty_three (ide_drive_t *drive)
 {
-#if 0
-	if (!HWIF(drive)->udma_four)
+	if(HWIF(drive)->udma_four == 0)
 		return 0;
-
-	if (drive->id->major_rev_num) {
-		int hssbd = 0;
-		int i;
-		/*
-		 * Determine highest Supported SPEC
-		 */
-		for (i=1; i<=15; i++)
-			if (drive->id->major_rev_num & (1<<i))
-				hssbd++;
-
-		switch (hssbd) {
-			case 7:
-			case 6:
-			case 5:
-		/* ATA-4 and older do not support above Ultra 33 */
-			default:
-				return 0;
-		}
-	}
-
-	return ((u8) (
+	if (!(drive->id->hw_config & 0x6000))
+		return 0;
 #ifndef CONFIG_IDEDMA_IVB
-		(drive->id->hw_config & 0x4000) &&
+	if(!(drive->id->hw_config & 0x4000))
+		return 0;
 #endif /* CONFIG_IDEDMA_IVB */
-		 (drive->id->hw_config & 0x6000)) ? 1 : 0);
-
-#else
-
-	return ((u8) ((HWIF(drive)->udma_four) &&
-#ifndef CONFIG_IDEDMA_IVB
-			(drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
-			(drive->id->hw_config & 0x6000)) ? 1 : 0);
-#endif
+	return 1;
 }
 
 EXPORT_SYMBOL(eighty_ninty_three);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3de9ab8..3d9c7af 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -608,7 +608,7 @@
 
 #ifdef __i386__
 	if (dev->resource[PCI_ROM_RESOURCE].start) {
-		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
 		printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
 #endif
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index bbde462..be334da 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -173,7 +173,7 @@
 
 	if (cmd & PCI_COMMAND_MEMORY) {
 		if (pci_resource_start(dev, PCI_ROM_RESOURCE)) {
-			pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+			pci_write_config_dword(dev, PCI_ROM_ADDRESS,
 				dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
 			printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n",
 				dev->resource[PCI_ROM_RESOURCE].start);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 627af50..de88218 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -790,7 +790,7 @@
 static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
-	struct scsi_device *sdev;
+	int error;
 
 	SBP2_DEBUG("sbp2_start_device");
 
@@ -939,10 +939,10 @@
 	sbp2_max_speed_and_size(scsi_id);
 
 	/* Add this device to the scsi layer now */
-	sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
-	if (IS_ERR(sdev)) {
+	error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
+	if (error) {
 		SBP2_ERR("scsi_add_device failed");
-		return PTR_ERR(sdev);
+		return error;
 	}
 
 	return 0;
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index e55dee3..444f775 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -132,6 +132,17 @@
 	  To compile this driver as a module, choose M here: the 
 	  module will be called corgikbd.
 
+config KEYBOARD_SPITZ
+	tristate "Spitz keyboard"
+	depends on PXA_SHARPSL
+	default y
+	help
+	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+	  SL-C3000 and Sl-C3100 series of PDAs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called spitzkbd.
+
 config KEYBOARD_MAPLE
 	tristate "Maple bus keyboard"
 	depends on SH_DREAMCAST && MAPLE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b02eece..9ce0b87 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
 obj-$(CONFIG_KEYBOARD_98KBD)		+= 98kbd.o
 obj-$(CONFIG_KEYBOARD_CORGI)		+= corgikbd.o
+obj-$(CONFIG_KEYBOARD_SPITZ)		+= spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
 
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
new file mode 100644
index 0000000..1714045
--- /dev/null
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -0,0 +1,478 @@
+/*
+ *  Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
+ *
+ *  Copyright (c) 2005 Richard Purdie
+ *
+ *  Based on corgikbd.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/spitz.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define KB_ROWS			7
+#define KB_COLS			11
+#define KB_ROWMASK(r)		(1 << (r))
+#define SCANCODE(r,c)		(((r)<<4) + (c) + 1)
+#define	NR_SCANCODES		((KB_ROWS<<4) + 1)
+
+#define HINGE_SCAN_INTERVAL	(150) /* ms */
+
+#define SPITZ_KEY_CALENDER	KEY_F1
+#define SPITZ_KEY_ADDRESS	KEY_F2
+#define SPITZ_KEY_FN		KEY_F3
+#define SPITZ_KEY_CANCEL	KEY_F4
+#define SPITZ_KEY_EXOK		KEY_F5
+#define SPITZ_KEY_EXCANCEL	KEY_F6
+#define SPITZ_KEY_EXJOGDOWN	KEY_F7
+#define SPITZ_KEY_EXJOGUP	KEY_F8
+#define SPITZ_KEY_JAP1		KEY_LEFTALT
+#define SPITZ_KEY_JAP2		KEY_RIGHTCTRL
+#define SPITZ_KEY_SYNC		KEY_F9
+#define SPITZ_KEY_MAIL		KEY_F10
+#define SPITZ_KEY_OK		KEY_F11
+#define SPITZ_KEY_MENU		KEY_F12
+
+static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
+	0,                                                                                                                /* 0 */
+	KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0,  /* 1-16 */
+	0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
+	KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0,                                 /* 33-48 */
+	SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0,         /* 49-64 */
+	SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0,	  /* 65-80 */
+	SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0,      /* 81-96 */
+	KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0  /* 97-112 */
+};
+
+static int spitz_strobes[] = {
+	SPITZ_GPIO_KEY_STROBE0,
+	SPITZ_GPIO_KEY_STROBE1,
+	SPITZ_GPIO_KEY_STROBE2,
+	SPITZ_GPIO_KEY_STROBE3,
+	SPITZ_GPIO_KEY_STROBE4,
+	SPITZ_GPIO_KEY_STROBE5,
+	SPITZ_GPIO_KEY_STROBE6,
+	SPITZ_GPIO_KEY_STROBE7,
+	SPITZ_GPIO_KEY_STROBE8,
+	SPITZ_GPIO_KEY_STROBE9,
+	SPITZ_GPIO_KEY_STROBE10,
+};
+
+static int spitz_senses[] = {
+	SPITZ_GPIO_KEY_SENSE0,
+	SPITZ_GPIO_KEY_SENSE1,
+	SPITZ_GPIO_KEY_SENSE2,
+	SPITZ_GPIO_KEY_SENSE3,
+	SPITZ_GPIO_KEY_SENSE4,
+	SPITZ_GPIO_KEY_SENSE5,
+	SPITZ_GPIO_KEY_SENSE6,
+};
+
+struct spitzkbd {
+	unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
+	struct input_dev input;
+	char phys[32];
+
+	spinlock_t lock;
+	struct timer_list timer;
+	struct timer_list htimer;
+
+	unsigned int suspended;
+	unsigned long suspend_jiffies;
+};
+
+#define KB_DISCHARGE_DELAY	10
+#define KB_ACTIVATE_DELAY	10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ *       requires a function call per GPIO bit which is excessive
+ *       when we need to access 11 bits at once, multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void spitzkbd_discharge_all(void)
+{
+	/* STROBE All HiZ */
+	GPCR0  =  SPITZ_GPIO_G0_STROBE_BIT;
+	GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+	GPCR1  =  SPITZ_GPIO_G1_STROBE_BIT;
+	GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+	GPCR2  =  SPITZ_GPIO_G2_STROBE_BIT;
+	GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+	GPCR3  =  SPITZ_GPIO_G3_STROBE_BIT;
+	GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+}
+
+static inline void spitzkbd_activate_all(void)
+{
+	/* STROBE ALL -> High */
+	GPSR0  =  SPITZ_GPIO_G0_STROBE_BIT;
+	GPDR0 |=  SPITZ_GPIO_G0_STROBE_BIT;
+	GPSR1  =  SPITZ_GPIO_G1_STROBE_BIT;
+	GPDR1 |=  SPITZ_GPIO_G1_STROBE_BIT;
+	GPSR2  =  SPITZ_GPIO_G2_STROBE_BIT;
+	GPDR2 |=  SPITZ_GPIO_G2_STROBE_BIT;
+	GPSR3  =  SPITZ_GPIO_G3_STROBE_BIT;
+	GPDR3 |=  SPITZ_GPIO_G3_STROBE_BIT;
+
+	udelay(KB_DISCHARGE_DELAY);
+
+	/* Clear any interrupts we may have triggered when altering the GPIO lines */
+	GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
+	GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
+	GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
+	GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
+}
+
+static inline void spitzkbd_activate_col(int col)
+{
+	int gpio = spitz_strobes[col];
+	GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+	GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+	GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+	GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+	GPSR(gpio) = GPIO_bit(gpio);
+	GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline void spitzkbd_reset_col(int col)
+{
+	int gpio = spitz_strobes[col];
+	GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+	GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+	GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+	GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+	GPCR(gpio) = GPIO_bit(gpio);
+	GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline int spitzkbd_get_row_status(int col)
+{
+	return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
+		| ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
+		| ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
+}
+
+/*
+ * The spitz keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+{
+	unsigned int row, col, rowd;
+	unsigned long flags;
+	unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
+
+	if (spitzkbd_data->suspended)
+		return;
+
+	spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+	if (regs)
+		input_regs(&spitzkbd_data->input, regs);
+
+	num_pressed = 0;
+	for (col = 0; col < KB_COLS; col++) {
+		/*
+		 * Discharge the output driver capacitatance
+		 * in the keyboard matrix. (Yes it is significant..)
+		 */
+
+		spitzkbd_discharge_all();
+		udelay(KB_DISCHARGE_DELAY);
+
+		spitzkbd_activate_col(col);
+		udelay(KB_ACTIVATE_DELAY);
+
+		rowd = spitzkbd_get_row_status(col);
+		for (row = 0; row < KB_ROWS; row++) {
+			unsigned int scancode, pressed;
+
+			scancode = SCANCODE(row, col);
+			pressed = rowd & KB_ROWMASK(row);
+
+			input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+
+			if (pressed)
+				num_pressed++;
+		}
+		spitzkbd_reset_col(col);
+	}
+
+	spitzkbd_activate_all();
+
+	input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+	input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+
+	if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
+		input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+		spitzkbd_data->suspend_jiffies = jiffies;
+	}
+
+	input_sync(&spitzkbd_data->input);
+
+	/* if any keys are pressed, enable the timer */
+	if (num_pressed)
+		mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+
+	spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+}
+
+/*
+ * spitz keyboard interrupt handler.
+ */
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct spitzkbd *spitzkbd_data = dev_id;
+
+	if (!timer_pending(&spitzkbd_data->timer)) {
+		/** wait chattering delay **/
+		udelay(20);
+		spitzkbd_scankeyboard(spitzkbd_data, regs);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * spitz timer checking for released keys
+ */
+static void spitzkbd_timer_callback(unsigned long data)
+{
+	struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+	spitzkbd_scankeyboard(spitzkbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate an interrupt.
+ * We debounce the switches and pass them to the input system.
+ */
+
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct spitzkbd *spitzkbd_data = dev_id;
+
+	if (!timer_pending(&spitzkbd_data->htimer))
+		mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+	return IRQ_HANDLED;
+}
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void spitzkbd_hinge_timer(unsigned long data)
+{
+	struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+	unsigned long state;
+	unsigned long flags;
+
+	state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+	if (state != sharpsl_hinge_state) {
+		hinge_count = 0;
+		sharpsl_hinge_state = state;
+	} else if (hinge_count < HINGE_STABLE_COUNT) {
+		hinge_count++;
+	}
+
+	if (hinge_count >= HINGE_STABLE_COUNT) {
+		spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+		input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+		input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+		input_sync(&spitzkbd_data->input);
+
+		spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+	} else {
+		mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+	}
+}
+
+#ifdef CONFIG_PM
+static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+	if (level == SUSPEND_POWER_DOWN) {
+		int i;
+		struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+		spitzkbd->suspended = 1;
+
+		/* Set Strobe lines as inputs - *except* strobe line 0 leave this
+		   enabled so we can detect a power button press for resume */
+		for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+			pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+	}
+	return 0;
+}
+
+static int spitzkbd_resume(struct device *dev, uint32_t level)
+{
+	if (level == RESUME_POWER_ON) {
+		int i;
+		struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+		for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+			pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+		/* Upon resume, ignore the suspend key for a short while */
+		spitzkbd->suspend_jiffies = jiffies;
+		spitzkbd->suspended = 0;
+	}
+	return 0;
+}
+#else
+#define spitzkbd_suspend	NULL
+#define spitzkbd_resume		NULL
+#endif
+
+static int __init spitzkbd_probe(struct device *dev)
+{
+	int i;
+	struct spitzkbd *spitzkbd;
+
+	spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
+	if (!spitzkbd)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev,spitzkbd);
+	strcpy(spitzkbd->phys, "spitzkbd/input0");
+
+	spin_lock_init(&spitzkbd->lock);
+
+	/* Init Keyboard rescan timer */
+	init_timer(&spitzkbd->timer);
+	spitzkbd->timer.function = spitzkbd_timer_callback;
+	spitzkbd->timer.data = (unsigned long) spitzkbd;
+
+	/* Init Hinge Timer */
+	init_timer(&spitzkbd->htimer);
+	spitzkbd->htimer.function = spitzkbd_hinge_timer;
+	spitzkbd->htimer.data = (unsigned long) spitzkbd;
+
+	spitzkbd->suspend_jiffies=jiffies;
+
+	init_input_dev(&spitzkbd->input);
+	spitzkbd->input.private = spitzkbd;
+	spitzkbd->input.name = "Spitz Keyboard";
+	spitzkbd->input.dev = dev;
+	spitzkbd->input.phys = spitzkbd->phys;
+	spitzkbd->input.id.bustype = BUS_HOST;
+	spitzkbd->input.id.vendor = 0x0001;
+	spitzkbd->input.id.product = 0x0001;
+	spitzkbd->input.id.version = 0x0100;
+	spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+	spitzkbd->input.keycode = spitzkbd->keycode;
+	spitzkbd->input.keycodesize = sizeof(unsigned char);
+	spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+
+	memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
+	for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
+		set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
+	clear_bit(0, spitzkbd->input.keybit);
+	set_bit(SW_0, spitzkbd->input.swbit);
+	set_bit(SW_1, spitzkbd->input.swbit);
+
+	input_register_device(&spitzkbd->input);
+	mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+	/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+	for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
+		pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
+		if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
+						SA_INTERRUPT, "Spitzkbd Sense", spitzkbd))
+			printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
+		else
+			set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING);
+	}
+
+	/* Set Strobe lines as outputs - set high */
+	for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+	pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
+	pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
+	pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
+	pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
+
+	request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd);
+	request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd);
+	request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd);
+	request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd);
+
+	set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE);
+	set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE);
+	set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE);
+	set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE);
+
+	printk(KERN_INFO "input: Spitz Keyboard Registered\n");
+
+	return 0;
+}
+
+static int spitzkbd_remove(struct device *dev)
+{
+	int i;
+	struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+	for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
+		free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
+
+	free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
+	free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+	free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+	free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+
+	del_timer_sync(&spitzkbd->htimer);
+	del_timer_sync(&spitzkbd->timer);
+
+	input_unregister_device(&spitzkbd->input);
+
+	kfree(spitzkbd);
+
+	return 0;
+}
+
+static struct device_driver spitzkbd_driver = {
+	.name		= "spitz-keyboard",
+	.bus		= &platform_bus_type,
+	.probe		= spitzkbd_probe,
+	.remove		= spitzkbd_remove,
+	.suspend	= spitzkbd_suspend,
+	.resume		= spitzkbd_resume,
+};
+
+static int __devinit spitzkbd_init(void)
+{
+	return driver_register(&spitzkbd_driver);
+}
+
+static void __exit spitzkbd_exit(void)
+{
+	driver_unregister(&spitzkbd_driver);
+}
+
+module_init(spitzkbd_init);
+module_exit(spitzkbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Spitz Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0489af5..21d55ed 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -24,17 +24,17 @@
 	  module will be called h3600_ts_input.
 
 config TOUCHSCREEN_CORGI
-	tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+	tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
 	depends on PXA_SHARPSL
 	default y	
 	help
 	  Say Y here to enable the driver for the touchscreen on the 
-	  Sharp SL-C7xx series of PDAs.
+	  Sharp SL-C7xx and SL-Cxx00 series of PDAs.
 
 	  If unsure, say N.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ads7846_ts.
+	  module will be called corgi_ts.
 
 config TOUCHSCREEN_GUNZE
 	tristate "Gunze AHL-51S touchscreen"
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 5d19261..4c7fbe5 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -1,5 +1,5 @@
 /*
- *  Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ *  Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models
  *
  *  Copyright (c) 2004-2005 Richard Purdie
  *
@@ -19,7 +19,7 @@
 #include <linux/slab.h>
 #include <asm/irq.h>
 
-#include <asm/arch/corgi.h>
+#include <asm/arch/sharpsl.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
 
@@ -47,15 +47,20 @@
 	struct ts_event tc;
 	int pendown;
 	int power_mode;
+	int irq_gpio;
+	struct corgits_machinfo *machinfo;
 };
 
-#define STATUS_HSYNC		(GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
-
-#define SyncHS()	while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#ifdef CONFIG_PXA25x
 #define CCNT(a)		asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
 #define PMNC_GET(x)	asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
 #define PMNC_SET(x)	asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
-
+#endif
+#ifdef CONFIG_PXA27x
+#define CCNT(a)		asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
+#define PMNC_GET(x)	asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x))
+#define PMNC_SET(x)	asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x))
+#endif
 
 /* ADS7846 Touch Screen Controller bit definitions */
 #define ADSCTRL_PD0		(1u << 0)	/* PD0 */
@@ -66,12 +71,11 @@
 #define ADSCTRL_STS		(1u << 7)	/* Start Bit */
 
 /* External Functions */
-extern unsigned long w100fb_get_hsynclen(struct device *dev);
 extern unsigned int get_clk_frequency_khz(int info);
 
-static unsigned long calc_waittime(void)
+static unsigned long calc_waittime(struct corgi_ts *corgi_ts)
 {
-	unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev);
+	unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len();
 
 	if (hsync_len)
 		return get_clk_frequency_khz(0)*1000/hsync_len;
@@ -79,7 +83,8 @@
 		return 0;
 }
 
-static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend,
+		unsigned int address, unsigned long wait_time)
 {
 	unsigned long timer1 = 0, timer2, pmnc = 0;
 	int pos = 0;
@@ -90,7 +95,7 @@
 			PMNC_SET(0x01);
 
 		/* polling HSync */
-		SyncHS();
+		corgi_ts->machinfo->wait_hsync();
 		/* get CCNT */
 		CCNT(timer1);
 	}
@@ -109,7 +114,7 @@
 			CCNT(timer2);
 			if (timer2-timer1 > wait_time) {
 				/* too slow - timeout, try again */
-				SyncHS();
+				corgi_ts->machinfo->wait_hsync();
 				/* get OSCR */
 				CCNT(timer1);
 				/* Wait after HSync */
@@ -133,23 +138,23 @@
 	/* critical section */
 	local_irq_save(flags);
 	corgi_ssp_ads7846_lock();
-	wait_time=calc_waittime();
+	wait_time = calc_waittime(corgi_ts);
 
 	/* Y-axis */
-	sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+	sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time);
 
 	/* Y-axis */
-	sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+	sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time);
 
 	/* X-axis */
-	y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+	y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time);
 
 	/* Z1 */
-	x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+	x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time);
 
 	/* Z2 */
-	z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
-	z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+	z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time);
+	z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time);
 
 	/* Power-Down Enable */
 	corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -189,9 +194,9 @@
 
 static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
 {
-	if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+	if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
 		/* Disable Interrupt */
-		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+		set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
 		if (read_xydata(corgi_ts)) {
 			corgi_ts->pendown = 1;
 			new_data(corgi_ts, regs);
@@ -210,7 +215,7 @@
 		}
 
 		/* Enable Falling Edge */
-		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+		set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
 		corgi_ts->pendown = 0;
 	}
 }
@@ -254,7 +259,7 @@
 
 		corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
 		/* Enable Falling Edge */
-		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+		set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
 		corgi_ts->power_mode = PWR_MODE_ACTIVE;
 	}
 	return 0;
@@ -267,6 +272,7 @@
 static int __init corgits_probe(struct device *dev)
 {
 	struct corgi_ts *corgi_ts;
+	struct platform_device *pdev = to_platform_device(dev);
 
 	if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
 		return -ENOMEM;
@@ -275,6 +281,14 @@
 
 	memset(corgi_ts, 0, sizeof(struct corgi_ts));
 
+	corgi_ts->machinfo = dev->platform_data;
+	corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
+
+	if (corgi_ts->irq_gpio < 0) {
+		kfree(corgi_ts);
+		return -ENODEV;
+	}
+
 	init_input_dev(&corgi_ts->input);
 	corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
@@ -293,8 +307,7 @@
 	corgi_ts->input.id.product = 0x0002;
 	corgi_ts->input.id.version = 0x0100;
 
-	pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
-	pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+	pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
 
 	/* Initiaize ADS7846 Difference Reference mode */
 	corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -313,14 +326,14 @@
 	input_register_device(&corgi_ts->input);
 	corgi_ts->power_mode = PWR_MODE_ACTIVE;
 
-	if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+	if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
 		input_unregister_device(&corgi_ts->input);
 		kfree(corgi_ts);
 		return -EBUSY;
 	}
 
 	/* Enable Falling Edge */
-	set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+	set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
 
 	printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
 
@@ -331,8 +344,9 @@
 {
 	struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
 
-	free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+	free_irq(corgi_ts->irq_gpio, NULL);
 	del_timer_sync(&corgi_ts->timer);
+	corgi_ts->machinfo->put_hsync();
 	input_unregister_device(&corgi_ts->input);
 	kfree(corgi_ts);
 	return 0;
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 40b0df0..1ebed04 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -87,7 +87,7 @@
 			 */
 			for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
 				if(!request_region(io[b] + i * 0x400, 1, "sc test")) {
-					pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400);
+					pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
 					io[b] = 0;
 					break;
 				} else
@@ -181,7 +181,7 @@
 			for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) {
 				pr_debug("Checking RAM address 0x%x...\n", i);
 				if(request_region(i, SRAM_PAGESIZE, "sc test")) {
-					pr_debug("  check_region succeeded\n");
+					pr_debug("  request_region succeeded\n");
 					model = identify_board(i, io[b]);
 					release_region(i, SRAM_PAGESIZE);
 					if (model >= 0) {
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 8b4ad70..877c770 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -29,7 +29,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 013c835..5319a9c 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,7 +26,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 53d399b..022913d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -29,7 +29,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 202bfe6..6418f03 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -17,7 +17,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index c00245d..b2256d6 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -10,7 +10,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 3a464a0..6f03ce4 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>	/* __setup			*/
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
 #include <linux/isapnp.h>
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0732efd..71971e9 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -14,7 +14,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 248d67f..b03573c 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -25,7 +25,7 @@
 
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
-#include <linux/ioport.h>	/* check_region, request_region	*/
+#include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index d7da901..f304f3c 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -31,7 +31,7 @@
 
 #include <linux/module.h>	/* Modules                        */
 #include <linux/init.h>		/* Initdata                       */
-#include <linux/ioport.h>	/* check_region, request_region   */
+#include <linux/ioport.h>	/* request_region		  */
 #include <linux/proc_fs.h>	/* radio card status report	  */
 #include <asm/io.h>		/* outb, outb_p                   */
 #include <asm/uaccess.h>	/* copy to/from user              */
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 342f92d..4c6d6fb 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -28,7 +28,7 @@
 
 #include <linux/module.h>	/* Modules                        */
 #include <linux/init.h>		/* Initdata                       */
-#include <linux/ioport.h>	/* check_region, request_region   */
+#include <linux/ioport.h>	/* request_region		  */
 #include <linux/delay.h>	/* udelay, msleep                 */
 #include <asm/io.h>		/* outb, outb_p                   */
 #include <asm/uaccess.h>	/* copy to/from user              */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index c9106b1..4334744 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -221,9 +221,7 @@
 	int err;
 
 	/* Put the analog decoder in standby to keep it quiet */
-	if (core->tda9887_conf) {
-		cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
-	}
+	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
 	dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
 	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
@@ -402,6 +400,9 @@
 		dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
 	}
 
+	/* Put the analog decoder in standby to keep it quiet */
+	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
 	/* register everything */
 	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
 }
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index e11e55d..3cbca7c 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -93,7 +93,7 @@
 static inline void wbsd_unlock_config(struct wbsd_host* host)
 {
 	BUG_ON(host->config == 0);
-	
+
 	outb(host->unlock_code, host->config);
 	outb(host->unlock_code, host->config);
 }
@@ -101,14 +101,14 @@
 static inline void wbsd_lock_config(struct wbsd_host* host)
 {
 	BUG_ON(host->config == 0);
-	
+
 	outb(LOCK_CODE, host->config);
 }
 
 static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
 {
 	BUG_ON(host->config == 0);
-	
+
 	outb(reg, host->config);
 	outb(value, host->config + 1);
 }
@@ -116,7 +116,7 @@
 static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
 {
 	BUG_ON(host->config == 0);
-	
+
 	outb(reg, host->config);
 	return inb(host->config + 1);
 }
@@ -140,21 +140,21 @@
 static void wbsd_init_device(struct wbsd_host* host)
 {
 	u8 setup, ier;
-	
+
 	/*
 	 * Reset chip (SD/MMC part) and fifo.
 	 */
 	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
 	setup |= WBSD_FIFO_RESET | WBSD_SOFT_RESET;
 	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-	
+
 	/*
 	 * Set DAT3 to input
 	 */
 	setup &= ~WBSD_DAT3_H;
 	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
 	host->flags &= ~WBSD_FIGNORE_DETECT;
-	
+
 	/*
 	 * Read back default clock.
 	 */
@@ -164,12 +164,12 @@
 	 * Power down port.
 	 */
 	outb(WBSD_POWER_N, host->base + WBSD_CSR);
-	
+
 	/*
 	 * Set maximum timeout.
 	 */
 	wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
-	
+
 	/*
 	 * Test for card presence
 	 */
@@ -177,7 +177,7 @@
 		host->flags |= WBSD_FCARD_PRESENT;
 	else
 		host->flags &= ~WBSD_FCARD_PRESENT;
-	
+
 	/*
 	 * Enable interesting interrupts.
 	 */
@@ -200,9 +200,9 @@
 static void wbsd_reset(struct wbsd_host* host)
 {
 	u8 setup;
-	
+
 	printk(KERN_ERR DRIVER_NAME ": Resetting chip\n");
-	
+
 	/*
 	 * Soft reset of chip (SD/MMC part).
 	 */
@@ -214,9 +214,9 @@
 static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
 {
 	unsigned long dmaflags;
-	
+
 	DBGF("Ending request, cmd (%x)\n", mrq->cmd->opcode);
-	
+
 	if (host->dma >= 0)
 	{
 		/*
@@ -232,7 +232,7 @@
 		 */
 		wbsd_write_index(host, WBSD_IDX_DMA, 0);
 	}
-	
+
 	host->mrq = NULL;
 
 	/*
@@ -275,7 +275,7 @@
 	    host->offset = 0;
 	    host->remain = host->cur_sg->length;
 	  }
-	
+
 	return host->num_sg;
 }
 
@@ -297,12 +297,12 @@
 	struct scatterlist* sg;
 	char* dmabuf = host->dma_buffer;
 	char* sgbuf;
-	
+
 	size = host->size;
-	
+
 	sg = data->sg;
 	len = data->sg_len;
-	
+
 	/*
 	 * Just loop through all entries. Size might not
 	 * be the entire list though so make sure that
@@ -317,23 +317,23 @@
 			memcpy(dmabuf, sgbuf, sg[i].length);
 		kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
 		dmabuf += sg[i].length;
-		
+
 		if (size < sg[i].length)
 			size = 0;
 		else
 			size -= sg[i].length;
-	
+
 		if (size == 0)
 			break;
 	}
-	
+
 	/*
 	 * Check that we didn't get a request to transfer
 	 * more data than can fit into the SG list.
 	 */
-	
+
 	BUG_ON(size != 0);
-	
+
 	host->size -= size;
 }
 
@@ -343,12 +343,12 @@
 	struct scatterlist* sg;
 	char* dmabuf = host->dma_buffer;
 	char* sgbuf;
-	
+
 	size = host->size;
-	
+
 	sg = data->sg;
 	len = data->sg_len;
-	
+
 	/*
 	 * Just loop through all entries. Size might not
 	 * be the entire list though so make sure that
@@ -363,30 +363,30 @@
 			memcpy(sgbuf, dmabuf, sg[i].length);
 		kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
 		dmabuf += sg[i].length;
-		
+
 		if (size < sg[i].length)
 			size = 0;
 		else
 			size -= sg[i].length;
-		
+
 		if (size == 0)
 			break;
 	}
-	
+
 	/*
 	 * Check that we didn't get a request to transfer
 	 * more data than can fit into the SG list.
 	 */
-	
+
 	BUG_ON(size != 0);
-	
+
 	host->size -= size;
 }
 
 /*
  * Command handling
  */
- 
+
 static inline void wbsd_get_short_reply(struct wbsd_host* host,
 	struct mmc_command* cmd)
 {
@@ -398,7 +398,7 @@
 		cmd->error = MMC_ERR_INVALID;
 		return;
 	}
-	
+
 	cmd->resp[0] =
 		wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
 	cmd->resp[0] |=
@@ -415,7 +415,7 @@
 	struct mmc_command* cmd)
 {
 	int i;
-	
+
 	/*
 	 * Correct response type?
 	 */
@@ -424,7 +424,7 @@
 		cmd->error = MMC_ERR_INVALID;
 		return;
 	}
-	
+
 	for (i = 0;i < 4;i++)
 	{
 		cmd->resp[i] =
@@ -442,7 +442,7 @@
 {
 	int i;
 	u8 status, isr;
-	
+
 	DBGF("Sending cmd (%x)\n", cmd->opcode);
 
 	/*
@@ -451,16 +451,16 @@
 	 * transfer.
 	 */
 	host->isr = 0;
-	
+
 	/*
 	 * Send the command (CRC calculated by host).
 	 */
 	outb(cmd->opcode, host->base + WBSD_CMDR);
 	for (i = 3;i >= 0;i--)
 		outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
-	
+
 	cmd->error = MMC_ERR_NONE;
-	
+
 	/*
 	 * Wait for the request to complete.
 	 */
@@ -477,7 +477,7 @@
 		 * Read back status.
 		 */
 		isr = host->isr;
-		
+
 		/* Card removed? */
 		if (isr & WBSD_INT_CARD)
 			cmd->error = MMC_ERR_TIMEOUT;
@@ -509,13 +509,13 @@
 	struct mmc_data* data = host->mrq->cmd->data;
 	char* buffer;
 	int i, fsr, fifo;
-	
+
 	/*
 	 * Handle excessive data.
 	 */
 	if (data->bytes_xfered == host->size)
 		return;
-	
+
 	buffer = wbsd_kmap_sg(host) + host->offset;
 
 	/*
@@ -527,14 +527,14 @@
 		/*
 		 * The size field in the FSR is broken so we have to
 		 * do some guessing.
-		 */		
+		 */
 		if (fsr & WBSD_FIFO_FULL)
 			fifo = 16;
 		else if (fsr & WBSD_FIFO_FUTHRE)
 			fifo = 8;
 		else
 			fifo = 1;
-		
+
 		for (i = 0;i < fifo;i++)
 		{
 			*buffer = inb(host->base + WBSD_DFR);
@@ -543,23 +543,23 @@
 			host->remain--;
 
 			data->bytes_xfered++;
-			
+
 			/*
 			 * Transfer done?
 			 */
 			if (data->bytes_xfered == host->size)
 			{
-				wbsd_kunmap_sg(host);				
+				wbsd_kunmap_sg(host);
 				return;
 			}
-			
+
 			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0)
 			{
 				wbsd_kunmap_sg(host);
-				
+
 				/*
 				 * Get next entry. Check if last.
 				 */
@@ -572,17 +572,17 @@
 					 * into the scatter list.
 					 */
 					BUG_ON(1);
-					
+
 					host->size = data->bytes_xfered;
-					
+
 					return;
 				}
-				
+
 				buffer = wbsd_kmap_sg(host);
 			}
 		}
 	}
-	
+
 	wbsd_kunmap_sg(host);
 
 	/*
@@ -599,7 +599,7 @@
 	struct mmc_data* data = host->mrq->cmd->data;
 	char* buffer;
 	int i, fsr, fifo;
-	
+
 	/*
 	 * Check that we aren't being called after the
 	 * entire buffer has been transfered.
@@ -618,7 +618,7 @@
 		/*
 		 * The size field in the FSR is broken so we have to
 		 * do some guessing.
-		 */		
+		 */
 		if (fsr & WBSD_FIFO_EMPTY)
 			fifo = 0;
 		else if (fsr & WBSD_FIFO_EMTHRE)
@@ -632,9 +632,9 @@
 			buffer++;
 			host->offset++;
 			host->remain--;
-			
+
 			data->bytes_xfered++;
-			
+
 			/*
 			 * Transfer done?
 			 */
@@ -650,7 +650,7 @@
 			if (host->remain == 0)
 			{
 				wbsd_kunmap_sg(host);
-				
+
 				/*
 				 * Get next entry. Check if last.
 				 */
@@ -663,19 +663,19 @@
 					 * into the scatter list.
 					 */
 					BUG_ON(1);
-					
+
 					host->size = data->bytes_xfered;
-					
+
 					return;
 				}
-				
+
 				buffer = wbsd_kmap_sg(host);
 			}
 		}
 	}
-	
+
 	wbsd_kunmap_sg(host);
-	
+
 	/*
 	 * The controller stops sending interrupts for
 	 * 'FIFO empty' under certain conditions. So we
@@ -694,7 +694,7 @@
 		1 << data->blksz_bits, data->blocks, data->flags);
 	DBGF("tsac %d ms nsac %d clk\n",
 		data->timeout_ns / 1000000, data->timeout_clks);
-	
+
 	/*
 	 * Calculate size.
 	 */
@@ -708,12 +708,12 @@
 		wbsd_write_index(host, WBSD_IDX_TAAC, 127);
 	else
 		wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
-	
+
 	if (data->timeout_clks > 255)
 		wbsd_write_index(host, WBSD_IDX_NSAC, 255);
 	else
 		wbsd_write_index(host, WBSD_IDX_NSAC, data->timeout_clks);
-	
+
 	/*
 	 * Inform the chip of how large blocks will be
 	 * sent. It needs this to determine when to
@@ -732,7 +732,7 @@
 	else if (host->bus_width == MMC_BUS_WIDTH_4)
 	{
 		blksize = (1 << data->blksz_bits) + 2 * 4;
-	
+
 		wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0)
 			| WBSD_DATA_WIDTH);
 		wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
@@ -751,12 +751,12 @@
 	setup = wbsd_read_index(host, WBSD_IDX_SETUP);
 	setup |= WBSD_FIFO_RESET;
 	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-	
+
 	/*
 	 * DMA transfer?
 	 */
 	if (host->dma >= 0)
-	{	
+	{
 		/*
 		 * The buffer for DMA is only 64 kB.
 		 */
@@ -766,17 +766,17 @@
 			data->error = MMC_ERR_INVALID;
 			return;
 		}
-		
+
 		/*
 		 * Transfer data from the SG list to
 		 * the DMA buffer.
 		 */
 		if (data->flags & MMC_DATA_WRITE)
 			wbsd_sg_to_dma(host, data);
-		
+
 		/*
 		 * Initialise the ISA DMA controller.
-		 */	
+		 */
 		dmaflags = claim_dma_lock();
 		disable_dma(host->dma);
 		clear_dma_ff(host->dma);
@@ -802,17 +802,17 @@
 		 * output to a minimum.
 		 */
 		host->firsterr = 1;
-		
+
 		/*
 		 * Initialise the SG list.
 		 */
 		wbsd_init_sg(host, data);
-	
+
 		/*
 		 * Turn off DMA.
 		 */
 		wbsd_write_index(host, WBSD_IDX_DMA, 0);
-	
+
 		/*
 		 * Set up FIFO threshold levels (and fill
 		 * buffer if doing a write).
@@ -828,8 +828,8 @@
 				WBSD_FIFOEN_EMPTY | 8);
 			wbsd_fill_fifo(host);
 		}
-	}	
-		
+	}
+
 	data->error = MMC_ERR_NONE;
 }
 
@@ -838,7 +838,7 @@
 	unsigned long dmaflags;
 	int count;
 	u8 status;
-	
+
 	WARN_ON(host->mrq == NULL);
 
 	/*
@@ -855,7 +855,7 @@
 	{
 		status = wbsd_read_index(host, WBSD_IDX_STATUS);
 	} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
-	
+
 	/*
 	 * DMA transfer?
 	 */
@@ -865,7 +865,7 @@
 		 * Disable DMA on the host.
 		 */
 		wbsd_write_index(host, WBSD_IDX_DMA, 0);
-		
+
 		/*
 		 * Turn of ISA DMA controller.
 		 */
@@ -874,7 +874,7 @@
 		clear_dma_ff(host->dma);
 		count = get_dma_residue(host->dma);
 		release_dma_lock(dmaflags);
-		
+
 		/*
 		 * Any leftover data?
 		 */
@@ -882,7 +882,7 @@
 		{
 			printk(KERN_ERR DRIVER_NAME ": Incomplete DMA "
 				"transfer. %d bytes left.\n", count);
-			
+
 			data->error = MMC_ERR_FAILED;
 		}
 		else
@@ -893,13 +893,13 @@
 			 */
 			if (data->flags & MMC_DATA_READ)
 				wbsd_dma_to_sg(host, data);
-			
+
 			data->bytes_xfered = host->size;
 		}
 	}
-	
+
 	DBGF("Ending data transfer (%d bytes)\n", data->bytes_xfered);
-	
+
 	wbsd_request_end(host, host->mrq);
 }
 
@@ -924,7 +924,7 @@
 	cmd = mrq->cmd;
 
 	host->mrq = mrq;
-	
+
 	/*
 	 * If there is no card in the slot then
 	 * timeout immediatly.
@@ -941,18 +941,18 @@
 	if (cmd->data)
 	{
 		wbsd_prepare_data(host, cmd->data);
-		
+
 		if (cmd->data->error != MMC_ERR_NONE)
 			goto done;
 	}
-	
+
 	wbsd_send_command(host, cmd);
 
 	/*
 	 * If this is a data transfer the request
 	 * will be finished after the data has
 	 * transfered.
-	 */	
+	 */
 	if (cmd->data && (cmd->error == MMC_ERR_NONE))
 	{
 		/*
@@ -965,7 +965,7 @@
 
 		return;
 	}
-		
+
 done:
 	wbsd_request_end(host, mrq);
 
@@ -976,7 +976,7 @@
 {
 	struct wbsd_host* host = mmc_priv(mmc);
 	u8 clk, setup, pwr;
-	
+
 	DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
 	     ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
 	     ios->vdd, ios->bus_width);
@@ -989,7 +989,7 @@
 	 */
 	if (ios->power_mode == MMC_POWER_OFF)
 		wbsd_init_device(host);
-	
+
 	if (ios->clock >= 24000000)
 		clk = WBSD_CLK_24M;
 	else if (ios->clock >= 16000000)
@@ -1042,7 +1042,7 @@
 		mod_timer(&host->ignore_timer, jiffies + HZ/100);
 	}
 	wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-	
+
 	/*
 	 * Store bus width for later. Will be used when
 	 * setting up the data transfer.
@@ -1128,7 +1128,7 @@
 	WARN_ON(!host->mrq->cmd->data);
 	if (!host->mrq->cmd->data)
 		return NULL;
-	
+
 	return host->mrq->cmd->data;
 }
 
@@ -1136,72 +1136,67 @@
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	u8 csr;
-	
+	int delay = -1;
+
 	spin_lock(&host->lock);
-	
+
 	if (host->flags & WBSD_FIGNORE_DETECT)
 	{
 		spin_unlock(&host->lock);
 		return;
 	}
-	
+
 	csr = inb(host->base + WBSD_CSR);
 	WARN_ON(csr == 0xff);
-	
+
 	if (csr & WBSD_CARDPRESENT)
 	{
 		if (!(host->flags & WBSD_FCARD_PRESENT))
 		{
 			DBG("Card inserted\n");
 			host->flags |= WBSD_FCARD_PRESENT;
-			
-			spin_unlock(&host->lock);
 
-			/*
-			 * Delay card detection to allow electrical connections
-			 * to stabilise.
-			 */
-			mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+			delay = 500;
 		}
-		else
-			spin_unlock(&host->lock);
 	}
 	else if (host->flags & WBSD_FCARD_PRESENT)
 	{
 		DBG("Card removed\n");
 		host->flags &= ~WBSD_FCARD_PRESENT;
-		
+
 		if (host->mrq)
 		{
 			printk(KERN_ERR DRIVER_NAME
 				": Card removed during transfer!\n");
 			wbsd_reset(host);
-			
+
 			host->mrq->cmd->error = MMC_ERR_FAILED;
 			tasklet_schedule(&host->finish_tasklet);
 		}
-		
-		/*
-		 * Unlock first since we might get a call back.
-		 */
-		spin_unlock(&host->lock);
 
-		mmc_detect_change(host->mmc, 0);
+		delay = 0;
 	}
-	else
-		spin_unlock(&host->lock);
+
+	/*
+	 * Unlock first since we might get a call back.
+	 */
+
+	spin_unlock(&host->lock);
+
+	if (delay != -1)
+		mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
 }
 
 static void wbsd_tasklet_fifo(unsigned long param)
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	struct mmc_data* data;
-	
+
 	spin_lock(&host->lock);
-		
+
 	if (!host->mrq)
 		goto end;
-	
+
 	data = wbsd_get_data(host);
 	if (!data)
 		goto end;
@@ -1220,7 +1215,7 @@
 		tasklet_schedule(&host->finish_tasklet);
 	}
 
-end:	
+end:
 	spin_unlock(&host->lock);
 }
 
@@ -1228,23 +1223,23 @@
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	struct mmc_data* data;
-	
+
 	spin_lock(&host->lock);
-	
+
 	if (!host->mrq)
 		goto end;
-	
+
 	data = wbsd_get_data(host);
 	if (!data)
 		goto end;
-	
+
 	DBGF("CRC error\n");
 
 	data->error = MMC_ERR_BADCRC;
-	
+
 	tasklet_schedule(&host->finish_tasklet);
 
-end:		
+end:
 	spin_unlock(&host->lock);
 }
 
@@ -1252,23 +1247,23 @@
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	struct mmc_data* data;
-	
+
 	spin_lock(&host->lock);
-	
+
 	if (!host->mrq)
 		goto end;
-	
+
 	data = wbsd_get_data(host);
 	if (!data)
 		goto end;
-	
+
 	DBGF("Timeout\n");
 
 	data->error = MMC_ERR_TIMEOUT;
-	
+
 	tasklet_schedule(&host->finish_tasklet);
 
-end:	
+end:
 	spin_unlock(&host->lock);
 }
 
@@ -1276,20 +1271,20 @@
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	struct mmc_data* data;
-	
+
 	spin_lock(&host->lock);
-	
+
 	WARN_ON(!host->mrq);
 	if (!host->mrq)
 		goto end;
-	
+
 	data = wbsd_get_data(host);
 	if (!data)
 		goto end;
 
 	wbsd_finish_data(host, data);
-	
-end:	
+
+end:
 	spin_unlock(&host->lock);
 }
 
@@ -1297,7 +1292,7 @@
 {
 	struct wbsd_host* host = (struct wbsd_host*)param;
 	struct mmc_data* data;
-	
+
 	spin_lock(&host->lock);
 
 	if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
@@ -1306,15 +1301,15 @@
 		data = wbsd_get_data(host);
 		if (!data)
 			goto end;
-		
+
 		DBGF("CRC error\n");
 
 		data->error = MMC_ERR_BADCRC;
-	
+
 		tasklet_schedule(&host->finish_tasklet);
 	}
 
-end:	
+end:
 	spin_unlock(&host->lock);
 }
 
@@ -1326,7 +1321,7 @@
 {
 	struct wbsd_host* host = dev_id;
 	int isr;
-	
+
 	isr = inb(host->base + WBSD_ISR);
 
 	/*
@@ -1334,7 +1329,7 @@
 	 */
 	if (isr == 0xff || isr == 0x00)
 		return IRQ_NONE;
-	
+
 	host->isr |= isr;
 
 	/*
@@ -1352,7 +1347,7 @@
 		tasklet_hi_schedule(&host->block_tasklet);
 	if (isr & WBSD_INT_TC)
 		tasklet_schedule(&host->finish_tasklet);
-	
+
 	return IRQ_HANDLED;
 }
 
@@ -1370,14 +1365,14 @@
 {
 	struct mmc_host* mmc;
 	struct wbsd_host* host;
-	
+
 	/*
 	 * Allocate MMC structure.
 	 */
 	mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
 	if (!mmc)
 		return -ENOMEM;
-	
+
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 
@@ -1391,37 +1386,37 @@
 	mmc->f_max = 24000000;
 	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
 	mmc->caps = MMC_CAP_4_BIT_DATA;
-	
+
 	spin_lock_init(&host->lock);
-	
+
 	/*
 	 * Set up timers
 	 */
 	init_timer(&host->ignore_timer);
 	host->ignore_timer.data = (unsigned long)host;
 	host->ignore_timer.function = wbsd_reset_ignore;
-	
+
 	/*
 	 * Maximum number of segments. Worst case is one sector per segment
 	 * so this will be 64kB/512.
 	 */
 	mmc->max_hw_segs = 128;
 	mmc->max_phys_segs = 128;
-	
+
 	/*
 	 * Maximum number of sectors in one transfer. Also limited by 64kB
 	 * buffer.
 	 */
 	mmc->max_sectors = 128;
-	
+
 	/*
 	 * Maximum segment size. Could be one segment with the maximum number
 	 * of segments.
 	 */
 	mmc->max_seg_size = mmc->max_sectors * 512;
-	
+
 	dev_set_drvdata(dev, mmc);
-	
+
 	return 0;
 }
 
@@ -1429,18 +1424,18 @@
 {
 	struct mmc_host* mmc;
 	struct wbsd_host* host;
-	
+
 	mmc = dev_get_drvdata(dev);
 	if (!mmc)
 		return;
-	
+
 	host = mmc_priv(mmc);
 	BUG_ON(host == NULL);
-	
+
 	del_timer_sync(&host->ignore_timer);
-	
+
 	mmc_free_host(mmc);
-	
+
 	dev_set_drvdata(dev, NULL);
 }
 
@@ -1452,7 +1447,7 @@
 {
 	int i, j, k;
 	int id;
-	
+
 	/*
 	 * Iterate through all ports, all codes to
 	 * find hardware that is in our known list.
@@ -1461,32 +1456,32 @@
 	{
 		if (!request_region(config_ports[i], 2, DRIVER_NAME))
 			continue;
-			
+
 		for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
 		{
 			id = 0xFFFF;
-			
+
 			outb(unlock_codes[j], config_ports[i]);
 			outb(unlock_codes[j], config_ports[i]);
-			
+
 			outb(WBSD_CONF_ID_HI, config_ports[i]);
 			id = inb(config_ports[i] + 1) << 8;
 
 			outb(WBSD_CONF_ID_LO, config_ports[i]);
 			id |= inb(config_ports[i] + 1);
-			
+
 			for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
 			{
 				if (id == valid_ids[k])
-				{				
+				{
 					host->chip_id = id;
 					host->config = config_ports[i];
 					host->unlock_code = unlock_codes[i];
-				
+
 					return 0;
 				}
 			}
-			
+
 			if (id != 0xFFFF)
 			{
 				DBG("Unknown hardware (id %x) found at %x\n",
@@ -1495,10 +1490,10 @@
 
 			outb(LOCK_CODE, config_ports[i]);
 		}
-		
+
 		release_region(config_ports[i], 2);
 	}
-	
+
 	return -ENODEV;
 }
 
@@ -1510,12 +1505,12 @@
 {
 	if (io & 0x7)
 		return -EINVAL;
-	
+
 	if (!request_region(base, 8, DRIVER_NAME))
 		return -EIO;
-	
+
 	host->base = io;
-		
+
 	return 0;
 }
 
@@ -1523,12 +1518,12 @@
 {
 	if (host->base)
 		release_region(host->base, 8);
-	
+
 	host->base = 0;
 
 	if (host->config)
 		release_region(host->config, 2);
-	
+
 	host->config = 0;
 }
 
@@ -1540,10 +1535,10 @@
 {
 	if (dma < 0)
 		return;
-	
+
 	if (request_dma(dma, DRIVER_NAME))
 		goto err;
-	
+
 	/*
 	 * We need to allocate a special buffer in
 	 * order for ISA to be able to DMA to it.
@@ -1558,7 +1553,7 @@
 	 */
 	host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
 		WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
-			
+
 	/*
 	 * ISA DMA must be aligned on a 64k basis.
 	 */
@@ -1571,19 +1566,19 @@
 		goto kfree;
 
 	host->dma = dma;
-	
+
 	return;
-	
+
 kfree:
 	/*
 	 * If we've gotten here then there is some kind of alignment bug
 	 */
 	BUG_ON(1);
-	
+
 	dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
 		DMA_BIDIRECTIONAL);
 	host->dma_addr = (dma_addr_t)NULL;
-	
+
 	kfree(host->dma_buffer);
 	host->dma_buffer = NULL;
 
@@ -1604,7 +1599,7 @@
 		kfree(host->dma_buffer);
 	if (host->dma >= 0)
 		free_dma(host->dma);
-	
+
 	host->dma = -1;
 	host->dma_buffer = NULL;
 	host->dma_addr = (dma_addr_t)NULL;
@@ -1617,7 +1612,7 @@
 static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
 {
 	int ret;
-	
+
 	/*
 	 * Allocate interrupt.
 	 */
@@ -1625,7 +1620,7 @@
 	ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
 	if (ret)
 		return ret;
-	
+
 	host->irq = irq;
 
 	/*
@@ -1637,7 +1632,7 @@
 	tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
 	tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
 	tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
-	
+
 	return 0;
 }
 
@@ -1647,9 +1642,9 @@
 		return;
 
 	free_irq(host->irq, host);
-	
+
 	host->irq = 0;
-		
+
 	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->fifo_tasklet);
 	tasklet_kill(&host->crc_tasklet);
@@ -1666,7 +1661,7 @@
 	int base, int irq, int dma)
 {
 	int ret;
-	
+
 	/*
 	 * Allocate I/O ports.
 	 */
@@ -1685,7 +1680,7 @@
 	 * Allocate DMA.
 	 */
 	wbsd_request_dma(host, dma);
-	
+
 	return 0;
 }
 
@@ -1708,7 +1703,7 @@
 {
 	/*
 	 * Reset the chip.
-	 */	
+	 */
 	wbsd_write_config(host, WBSD_CONF_SWRST, 1);
 	wbsd_write_config(host, WBSD_CONF_SWRST, 0);
 
@@ -1716,23 +1711,23 @@
 	 * Select SD/MMC function.
 	 */
 	wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-	
+
 	/*
 	 * Set up card detection.
 	 */
 	wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
-	
+
 	/*
 	 * Configure chip
 	 */
 	wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
 	wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-	
+
 	wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
-	
+
 	if (host->dma >= 0)
 		wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
-	
+
 	/*
 	 * Enable and power up chip.
 	 */
@@ -1743,26 +1738,26 @@
 /*
  * Check that configured resources are correct.
  */
- 
+
 static int __devinit wbsd_chip_validate(struct wbsd_host* host)
 {
 	int base, irq, dma;
-	
+
 	/*
 	 * Select SD/MMC function.
 	 */
 	wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-	
+
 	/*
 	 * Read configuration.
 	 */
 	base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
 	base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
-	
+
 	irq = wbsd_read_config(host, WBSD_CONF_IRQ);
-	
+
 	dma = wbsd_read_config(host, WBSD_CONF_DRQ);
-	
+
 	/*
 	 * Validate against given configuration.
 	 */
@@ -1772,7 +1767,7 @@
 		return 0;
 	if ((dma != host->dma) && (host->dma != -1))
 		return 0;
-	
+
 	return 1;
 }
 
@@ -1788,14 +1783,14 @@
 	struct wbsd_host* host = NULL;
 	struct mmc_host* mmc = NULL;
 	int ret;
-	
+
 	ret = wbsd_alloc_mmc(dev);
 	if (ret)
 		return ret;
-	
+
 	mmc = dev_get_drvdata(dev);
 	host = mmc_priv(mmc);
-	
+
 	/*
 	 * Scan for hardware.
 	 */
@@ -1814,7 +1809,7 @@
 			return ret;
 		}
 	}
-	
+
 	/*
 	 * Request resources.
 	 */
@@ -1825,7 +1820,7 @@
 		wbsd_free_mmc(dev);
 		return ret;
 	}
-	
+
 	/*
 	 * See if chip needs to be configured.
 	 */
@@ -1842,7 +1837,7 @@
 	}
 	else
 		wbsd_chip_config(host);
-	
+
 	/*
 	 * Power Management stuff. No idea how this works.
 	 * Not tested.
@@ -1860,7 +1855,7 @@
 	 * Reset the chip into a known state.
 	 */
 	wbsd_init_device(host);
-	
+
 	mmc_add_host(mmc);
 
 	printk(KERN_INFO "%s: W83L51xD", mmc_hostname(mmc));
@@ -1882,12 +1877,12 @@
 {
 	struct mmc_host* mmc = dev_get_drvdata(dev);
 	struct wbsd_host* host;
-	
+
 	if (!mmc)
 		return;
 
 	host = mmc_priv(mmc);
-	
+
 	mmc_remove_host(mmc);
 
 	if (!pnp)
@@ -1900,9 +1895,9 @@
 		wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
 		wbsd_lock_config(host);
 	}
-	
+
 	wbsd_release_resources(host);
-	
+
 	wbsd_free_mmc(dev);
 }
 
@@ -1932,7 +1927,7 @@
 wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
 {
 	int io, irq, dma;
-	
+
 	/*
 	 * Get resources from PnP layer.
 	 */
@@ -1942,9 +1937,9 @@
 		dma = pnp_dma(pnpdev, 0);
 	else
 		dma = -1;
-	
+
 	DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
-	
+
 	return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
 }
 
@@ -1985,7 +1980,7 @@
 	.bus		= &platform_bus_type,
 	.probe		= wbsd_probe,
 	.remove		= wbsd_remove,
-	
+
 	.suspend	= wbsd_suspend,
 	.resume		= wbsd_resume,
 };
@@ -2008,7 +2003,7 @@
 static int __init wbsd_drv_init(void)
 {
 	int result;
-	
+
 	printk(KERN_INFO DRIVER_NAME
 		": Winbond W83L51xD SD/MMC card interface driver, "
 		DRIVER_VERSION "\n");
@@ -2023,8 +2018,8 @@
 			return result;
 	}
 
-#endif /* CONFIG_PNP */	
-	
+#endif /* CONFIG_PNP */
+
 	if (nopnp)
 	{
 		result = driver_register(&wbsd_driver);
@@ -2046,13 +2041,13 @@
 
 	if (!nopnp)
 		pnp_unregister_driver(&wbsd_pnp_driver);
-	
-#endif /* CONFIG_PNP */	
+
+#endif /* CONFIG_PNP */
 
 	if (nopnp)
 	{
 		platform_device_unregister(wbsd_device);
-	
+
 		driver_unregister(&wbsd_driver);
 	}
 
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index 9005b52..249baa7 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -139,51 +139,50 @@
 struct wbsd_host
 {
 	struct mmc_host*	mmc;		/* MMC structure */
-	
+
 	spinlock_t		lock;		/* Mutex */
 
 	int			flags;		/* Driver states */
 
 #define WBSD_FCARD_PRESENT	(1<<0)		/* Card is present */
 #define WBSD_FIGNORE_DETECT	(1<<1)		/* Ignore card detection */
-	
+
 	struct mmc_request*	mrq;		/* Current request */
-	
+
 	u8			isr;		/* Accumulated ISR */
-	
+
 	struct scatterlist*	cur_sg;		/* Current SG entry */
 	unsigned int		num_sg;		/* Number of entries left */
 	void*			mapped_sg;	/* vaddr of mapped sg */
-	
+
 	unsigned int		offset;		/* Offset into current entry */
 	unsigned int		remain;		/* Data left in curren entry */
 
 	int			size;		/* Total size of transfer */
-	
+
 	char*			dma_buffer;	/* ISA DMA buffer */
 	dma_addr_t		dma_addr;	/* Physical address for same */
 
 	int			firsterr;	/* See fifo functions */
-	
+
 	u8			clk;		/* Current clock speed */
 	unsigned char		bus_width;	/* Current bus width */
-	
+
 	int			config;		/* Config port */
 	u8			unlock_code;	/* Code to unlock config */
 
 	int			chip_id;	/* ID of controller */
-	
+
 	int			base;		/* I/O port base */
 	int			irq;		/* Interrupt */
 	int			dma;		/* DMA channel */
-	
+
 	struct tasklet_struct	card_tasklet;	/* Tasklet structures */
 	struct tasklet_struct	fifo_tasklet;
 	struct tasklet_struct	crc_tasklet;
 	struct tasklet_struct	timeout_tasklet;
 	struct tasklet_struct	finish_tasklet;
 	struct tasklet_struct	block_tasklet;
-	
-	struct timer_list	detect_timer;	/* Card detection timer */
+
 	struct timer_list	ignore_timer;	/* Ignore detection timer */
 };
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 811d92e..cc37213 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -25,9 +25,6 @@
 
 /****************************************************************************/
 
-
-/****************************************************************************/
-
 struct map_info uclinux_ram_map = {
 	.name = "RAM",
 };
@@ -60,14 +57,15 @@
 	struct mtd_info *mtd;
 	struct map_info *mapp;
 	extern char _ebss;
+	unsigned long addr = (unsigned long) &_ebss;
 
 	mapp = &uclinux_ram_map;
-	mapp->phys = (unsigned long) &_ebss;
-	mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
+	mapp->phys = addr;
+	mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
 	mapp->bankwidth = 4;
 
 	printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
-	       	(int) mapp->map_priv_2, (int) mapp->size);
+	       	(int) mapp->phys, (int) mapp->size);
 
 	mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
 
@@ -95,7 +93,6 @@
 	printk("uclinux[mtd]: set %s to be root filesystem\n",
 	     	uclinux_romfs[0].name);
 	ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
-	put_mtd_device(mtd);
 
 	return(0);
 }
@@ -109,7 +106,7 @@
 		map_destroy(uclinux_ram_mtdinfo);
 		uclinux_ram_mtdinfo = NULL;
 	}
-	if (uclinux_ram_map.map_priv_1) {
+	if (uclinux_ram_map.virt) {
 		iounmap((void *) uclinux_ram_map.virt);
 		uclinux_ram_map.virt = 0;
 	}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bb9232..54fff9c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1738,11 +1738,18 @@
 	  the Motorola 68360 processor.
 
 config FEC
-	bool "FEC ethernet controller (of ColdFire 5272)"
-	depends on M5272 || M5282
+	bool "FEC ethernet controller (of ColdFire CPUs)"
+	depends on M523x || M527x || M5272 || M528x
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
-	  controller on the Motorola ColdFire 5272 processor.
+	  controller on some Motorola ColdFire processors.
+
+config FEC2
+	bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+	depends on FEC
+	help
+	  Say Y here if you want to use the second built-in 10/100 Fast
+	  ethernet controller on some Motorola ColdFire processors.
 
 config NE_H8300
 	tristate "NE2000 compatible support for H8/300"
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 52c77cb..1f03027 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -160,7 +160,7 @@
 		return -ENODEV;
 	}
 	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
-		BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n",
+		BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
 		       ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
 		return -ENXIO;
 	}
@@ -242,7 +242,7 @@
 		BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
 		return -ENODEV;
 	}
-	/* Reserve the I/O region - guaranteed to work by check_region */
+	/* Reserve the I/O region */
 	if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
 		free_irq(dev->irq, dev);
 		return -EBUSY;
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 2c70084..85504fb9 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -8,7 +8,7 @@
  * describes connections using the internal parallel port I/O, which
  * is basically all of Port D.
  *
- * Right now, I am very watseful with the buffers.  I allocate memory
+ * Right now, I am very wasteful with the buffers.  I allocate memory
  * pages and then divide them into 2K frame buffers.  This way I know I
  * have buffers large enough to hold one frame within one buffer descriptor.
  * Once I get this working, I will use 64 or 128 byte CPM buffers, which
@@ -19,7 +19,10 @@
  * Copyright (c) 2000 Ericsson Radio Systems AB.
  *
  * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2005 Macq Electronique SA.
  */
 
 #include <linux/config.h>
@@ -46,7 +49,8 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+    defined(CONFIG_M5272) || defined(CONFIG_M528x)
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include "fec.h"
@@ -71,7 +75,7 @@
 #elif defined(CONFIG_M527x)
 	(MCF_MBAR + 0x1000),
 	(MCF_MBAR + 0x1800),
-#elif defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
 	(MCF_MBAR + 0x1000),
 #else
 	&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@
 #define	FEC_FLASHMAC	0xffe04000
 #elif defined(CONFIG_CANCam)
 #define	FEC_FLASHMAC	0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define	FEC_FLASHMAC	(0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC 	0xffc0406b
 #else
 #define	FEC_FLASHMAC	0
 #endif
 
-unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
-
 /* Forward declarations of some structures to support different PHYs
 */
 
@@ -158,7 +164,7 @@
  * size bits. Other FEC hardware does not, so we need to take that into
  * account when setting it.
  */
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
@@ -196,7 +202,7 @@
 	uint	phy_id_done;
 	uint	phy_status;
 	uint	phy_speed;
-	phy_info_t	*phy;
+	phy_info_t const	*phy;
 	struct work_struct phy_task;
 
 	uint	sequence_done;
@@ -209,7 +215,6 @@
 	int	link;
 	int	old_link;
 	int	full_duplex;
-	unsigned char mac_addr[ETH_ALEN];
 };
 
 static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@
 } mii_list_t;
 
 #define		NMII	20
-mii_list_t	mii_cmds[NMII];
-mii_list_t	*mii_free;
-mii_list_t	*mii_head;
-mii_list_t	*mii_tail;
+static mii_list_t	mii_cmds[NMII];
+static mii_list_t	*mii_free;
+static mii_list_t	*mii_head;
+static mii_list_t	*mii_tail;
 
 static int	mii_queue(struct net_device *dev, int request, 
 				void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@
 	}
 	}
 #endif
-	fec_restart(dev, 0);
+	fec_restart(dev, fep->full_duplex);
 	netif_wake_queue(dev);
 }
 
@@ -757,45 +762,52 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+	status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0004)
-		*s |= PHY_STAT_LINK;
+		status |= PHY_STAT_LINK;
 	if (mii_reg & 0x0010)
-		*s |= PHY_STAT_FAULT;
+		status |= PHY_STAT_FAULT;
 	if (mii_reg & 0x0020)
-		*s |= PHY_STAT_ANC;
+		status |= PHY_STAT_ANC;
+
+	*s = status;
 }
 
 static void mii_parse_cr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+	status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
 
 	if (mii_reg & 0x1000)
-		*s |= PHY_CONF_ANE;
+		status |= PHY_CONF_ANE;
 	if (mii_reg & 0x4000)
-		*s |= PHY_CONF_LOOP;
+		status |= PHY_CONF_LOOP;
+	*s = status;
 }
 
 static void mii_parse_anar(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_CONF_SPMASK);
+	status = *s & ~(PHY_CONF_SPMASK);
 
 	if (mii_reg & 0x0020)
-		*s |= PHY_CONF_10HDX;
+		status |= PHY_CONF_10HDX;
 	if (mii_reg & 0x0040)
-		*s |= PHY_CONF_10FDX;
+		status |= PHY_CONF_10FDX;
 	if (mii_reg & 0x0080)
-		*s |= PHY_CONF_100HDX;
+		status |= PHY_CONF_100HDX;
 	if (mii_reg & 0x00100)
-		*s |= PHY_CONF_100FDX;
+		status |= PHY_CONF_100FDX;
+	*s = status;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_STAT_SPMASK);
-
+	status = *s & ~(PHY_STAT_SPMASK);
 	if (mii_reg & 0x0800) {
 		if (mii_reg & 0x1000)
-			*s |= PHY_STAT_100FDX;
+			status |= PHY_STAT_100FDX;
 		else
-			*s |= PHY_STAT_100HDX;
+			status |= PHY_STAT_100HDX;
 	} else {
 		if (mii_reg & 0x1000)
-			*s |= PHY_STAT_10FDX;
+			status |= PHY_STAT_10FDX;
 		else
-			*s |= PHY_STAT_10HDX;
+			status |= PHY_STAT_10HDX;
 	}
+	*s = status;
 }
 
-static phy_info_t phy_info_lxt970 = {
-	0x07810000, 
-	"LXT970",
-
-	(const phy_cmd_t []) {  /* config */
+static phy_cmd_t const phy_cmd_lxt970_config[] = {
 		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
 		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* startup - enable interrupts */
+	};
+static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
 		{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) { /* ack_int */
+	};
+static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
 		/* read SR and ISR to acknowledge */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
 		{ mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@
 		/* find out the current status */
 		{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+	};
+static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
 		{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
 		{ mk_mii_end, }
-	},
+	};
+static phy_info_t const phy_info_lxt970 = {
+	.id = 0x07810000, 
+	.name = "LXT970",
+	.config = phy_cmd_lxt970_config,
+	.startup = phy_cmd_lxt970_startup,
+	.ack_int = phy_cmd_lxt970_ack_int,
+	.shutdown = phy_cmd_lxt970_shutdown
 };
 	
 /* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+	status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0400) {
 		fep->link = 1;
-		*s |= PHY_STAT_LINK;
+		status |= PHY_STAT_LINK;
 	} else {
 		fep->link = 0;
 	}
 	if (mii_reg & 0x0080)
-		*s |= PHY_STAT_ANC;
+		status |= PHY_STAT_ANC;
 	if (mii_reg & 0x4000) {
 		if (mii_reg & 0x0200)
-			*s |= PHY_STAT_100FDX;
+			status |= PHY_STAT_100FDX;
 		else
-			*s |= PHY_STAT_100HDX;
+			status |= PHY_STAT_100HDX;
 	} else {
 		if (mii_reg & 0x0200)
-			*s |= PHY_STAT_10FDX;
+			status |= PHY_STAT_10FDX;
 		else
-			*s |= PHY_STAT_10HDX;
+			status |= PHY_STAT_10HDX;
 	}
 	if (mii_reg & 0x0008)
-		*s |= PHY_STAT_FAULT;
-}
+		status |= PHY_STAT_FAULT;
 
-static phy_info_t phy_info_lxt971 = {
-	0x0001378e, 
-	"LXT971",
+	*s = status;
+}
 	
-	(const phy_cmd_t []) {  /* config */  
-		/* limit to 10MBit because my protorype board 
+static phy_cmd_t const phy_cmd_lxt971_config[] = {
+		/* limit to 10MBit because my prototype board 
 		 * doesn't work with 100. */
 		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
 		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
 		{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* startup - enable interrupts */
+	};
+static phy_cmd_t const phy_cmd_lxt971_startup[] = {  /* enable interrupts */
 		{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@
 		 * read here to get a valid value in ack_int */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr }, 
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) { /* ack_int */
+	};
+static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
+		/* acknowledge the int before reading status ! */
+		{ mk_mii_read(MII_LXT971_ISR), NULL },
 		/* find out the current status */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
 		{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
-		/* we only need to read ISR to acknowledge */
-		{ mk_mii_read(MII_LXT971_ISR), NULL },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+	};
+static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
 		{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
 		{ mk_mii_end, }
-	},
+	};
+static phy_info_t const phy_info_lxt971 = {
+	.id = 0x0001378e, 
+	.name = "LXT971",
+	.config = phy_cmd_lxt971_config,
+	.startup = phy_cmd_lxt971_startup,
+	.ack_int = phy_cmd_lxt971_ack_int,
+	.shutdown = phy_cmd_lxt971_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_STAT_SPMASK);
+	status = *s & ~(PHY_STAT_SPMASK);
 
 	switch((mii_reg >> 2) & 7) {
-	case 1: *s |= PHY_STAT_10HDX; break;
-	case 2: *s |= PHY_STAT_100HDX; break;
-	case 5: *s |= PHY_STAT_10FDX; break;
-	case 6: *s |= PHY_STAT_100FDX; break;
-	}
+	case 1: status |= PHY_STAT_10HDX; break;
+	case 2: status |= PHY_STAT_100HDX; break;
+	case 5: status |= PHY_STAT_10FDX; break;
+	case 6: status |= PHY_STAT_100FDX; break;
 }
 
-static phy_info_t phy_info_qs6612 = {
-	0x00181440, 
-	"QS6612",
-	
-	(const phy_cmd_t []) {  /* config */  
+	*s = status;
+}
+
+static phy_cmd_t const phy_cmd_qs6612_config[] = {
 		/* The PHY powers up isolated on the RPX, 
 		 * so send a command to allow operation.
 		 */
@@ -981,13 +1002,13 @@
 		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
 		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* startup - enable interrupts */
+	};
+static phy_cmd_t const phy_cmd_qs6612_startup[] = {  /* enable interrupts */
 		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) { /* ack_int */
+	};
+static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
 		/* we need to read ISR, SR and ANER to acknowledge */
 		{ mk_mii_read(MII_QS6612_ISR), NULL },
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@
 		/* read pcr to get info */
 		{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+	};
+static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
 		{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
 		{ mk_mii_end, }
-	},
+	};
+static phy_info_t const phy_info_qs6612 = {
+	.id = 0x00181440, 
+	.name = "QS6612",
+	.config = phy_cmd_qs6612_config,
+	.startup = phy_cmd_qs6612_startup,
+	.ack_int = phy_cmd_qs6612_ack_int,
+	.shutdown = phy_cmd_qs6612_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile uint *s = &(fep->phy_status);
+	uint status;
 
-	*s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+	status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0080)
-		*s |= PHY_STAT_ANC;
+		status |= PHY_STAT_ANC;
 	if (mii_reg & 0x0400)
-		*s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
+		status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
 	else
-		*s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+		status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+
+	*s = status;
 }
 
-static phy_info_t phy_info_am79c874 = {
-	0x00022561, 
-	"AM79C874",
-	
-	(const phy_cmd_t []) {  /* config */  
-		/* limit to 10MBit because my protorype board 
-		 * doesn't work with 100. */
+static phy_cmd_t const phy_cmd_am79c874_config[] = {
 		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
 		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
 		{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* startup - enable interrupts */
+	};
+static phy_cmd_t const phy_cmd_am79c874_startup[] = {  /* enable interrupts */
 		{ mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr }, 
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) { /* ack_int */
+	};
+static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
 		/* find out the current status */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
 		{ mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
 		/* we only need to read ISR to acknowledge */
 		{ mk_mii_read(MII_AM79C874_ICSR), NULL },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+	};
+static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
 		{ mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
 		{ mk_mii_end, }
-	},
+	};
+static phy_info_t const phy_info_am79c874 = {
+	.id = 0x00022561,
+	.name = "AM79C874",
+	.config = phy_cmd_am79c874_config,
+	.startup = phy_cmd_am79c874_startup,
+	.ack_int = phy_cmd_am79c874_ack_int,
+	.shutdown = phy_cmd_am79c874_shutdown
 };
 
+
 /* ------------------------------------------------------------------------- */
 /* Kendin KS8721BL phy                                                       */
 
@@ -1072,37 +1105,40 @@
 #define MII_KS8721BL_ICSR	22
 #define	MII_KS8721BL_PHYCR	31
 
-static phy_info_t phy_info_ks8721bl = {
-	0x00022161, 
-	"KS8721BL",
-	
-	(const phy_cmd_t []) {  /* config */  
+static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
 		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
 		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* startup */
+	};
+static phy_cmd_t const phy_cmd_ks8721bl_startup[] = {  /* enable interrupts */
 		{ mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
 		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr }, 
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) { /* ack_int */
+	};
+static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
 		/* find out the current status */
 		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
 		/* we only need to read ISR to acknowledge */
 		{ mk_mii_read(MII_KS8721BL_ICSR), NULL },
 		{ mk_mii_end, }
-	},
-	(const phy_cmd_t []) {  /* shutdown */
+	};
+static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
 		{ mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
 		{ mk_mii_end, }
-	},
+	};
+static phy_info_t const phy_info_ks8721bl = {
+	.id = 0x00022161, 
+	.name = "KS8721BL",
+	.config = phy_cmd_ks8721bl_config,
+	.startup = phy_cmd_ks8721bl_startup,
+	.ack_int = phy_cmd_ks8721bl_ack_int,
+	.shutdown = phy_cmd_ks8721bl_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
 
-static phy_info_t *phy_info[] = {
+static phy_info_t const * const phy_info[] = {
 	&phy_info_lxt970,
 	&phy_info_lxt971,
 	&phy_info_qs6612,
@@ -1129,16 +1165,23 @@
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
 	volatile unsigned long *icrp;
+	static const struct idesc {
+		char *name;
+		unsigned short irq;
+		irqreturn_t (*handler)(int, void *, struct pt_regs *);
+	} *idp, id[] = {
+		{ "fec(RX)", 86, fec_enet_interrupt },
+		{ "fec(TX)", 87, fec_enet_interrupt },
+		{ "fec(OTHER)", 88, fec_enet_interrupt },
+		{ "fec(MII)", 66, mii_link_interrupt },
+		{ NULL },
+	};
 
 	/* Setup interrupt handlers. */
-	if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0)
-		printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n");
-	if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0)
-		printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n");
-	if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
-		printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
-	if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
-		printk("FEC: Could not allocate MII IRQ(66)!\n");
+	for (idp = id; idp->name; idp++) {
+		if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
+			printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
+	}
 
 	/* Unmask interrupt at ColdFire 5272 SIM */
 	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile fec_t *fecp;
-	unsigned char *iap, tmpaddr[6];
-	int i;
+	unsigned char *iap, tmpaddr[ETH_ALEN];
 
 	fecp = fep->hwp;
 
-	if (fec_flashmac) {
+	if (FEC_FLASHMAC) {
 		/*
 		 * Get MAC address from FLASH.
 		 * If it is all 1's or 0's, use the default.
 		 */
-		iap = fec_flashmac;
+		iap = (unsigned char *)FEC_FLASHMAC;
 		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
 		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
 			iap = fec_mac_default;
@@ -1192,14 +1234,11 @@
 		iap = &tmpaddr[0];
 	}
 
-	for (i=0; i<ETH_ALEN; i++)
-		dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+	memcpy(dev->dev_addr, iap, ETH_ALEN);
 
 	/* Adjust MAC if using default MAC address */
-	if (iap == fec_mac_default) {
-		dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-			iap[ETH_ALEN-1] + fep->index;
-	}
+	if (iap == fec_mac_default)
+		 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@
 
 /* ------------------------------------------------------------------------- */
 
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 
 /*
- *	Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups.
+ *	Code specific to Coldfire 5230/5231/5232/5234/5235,
+ *	the 5270/5271/5274/5275 and 5280/5282 setups.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
 	struct fec_enet_private *fep;
 	int b;
+	static const struct idesc {
+		char *name;
+		unsigned short irq;
+	} *idp, id[] = {
+		{ "fec(TXF)", 23 },
+		{ "fec(TXB)", 24 },
+		{ "fec(TXFIFO)", 25 },
+		{ "fec(TXCR)", 26 },
+		{ "fec(RXF)", 27 },
+		{ "fec(RXB)", 28 },
+		{ "fec(MII)", 29 },
+		{ "fec(LC)", 30 },
+		{ "fec(HBERR)", 31 },
+		{ "fec(GRA)", 32 },
+		{ "fec(EBERR)", 33 },
+		{ "fec(BABT)", 34 },
+		{ "fec(BABR)", 35 },
+		{ NULL },
+	};
 
 	fep = netdev_priv(dev);
 	b = (fep->index) ? 128 : 64;
 
 	/* Setup interrupt handlers. */
-	if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0)
-		printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b);
-	if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0)
-		printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b);
-	if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
-		printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
-	if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
-		printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
-
-	if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
-		printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
-	if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
-		printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
-
-	if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
-		printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
-	if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
-		printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
-	if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
-		printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
-	if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
-		printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
-	if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
-		printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
-	if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
-		printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
-	if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
-		printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
+	for (idp = id; idp->name; idp++) {
+		if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
+			printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+	}
 
 	/* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
 	{
@@ -1300,11 +1335,13 @@
 #if defined(CONFIG_M528x)
 	/* Set up gpio outputs for MII lines */
 	{
-		volatile unsigned short *gpio_paspar;
+		volatile u16 *gpio_paspar;
+		volatile u8 *gpio_pehlpar;
   
-		gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR +
-			0x100056);
-		*gpio_paspar = 0x0f00;
+		gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
+		gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+		*gpio_paspar |= 0x0f00;
+		*gpio_pehlpar = 0xc0;
 	}
 #endif
 }
@@ -1331,17 +1368,16 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	volatile fec_t *fecp;
-	unsigned char *iap, tmpaddr[6];
-	int i;
+	unsigned char *iap, tmpaddr[ETH_ALEN];
 
 	fecp = fep->hwp;
 
-	if (fec_flashmac) {
+	if (FEC_FLASHMAC) {
 		/*
 		 * Get MAC address from FLASH.
 		 * If it is all 1's or 0's, use the default.
 		 */
-		iap = fec_flashmac;
+		iap = FEC_FLASHMAC;
 		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
 		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
 			iap = fec_mac_default;
@@ -1354,14 +1390,11 @@
 		iap = &tmpaddr[0];
 	}
 
-	for (i=0; i<ETH_ALEN; i++)
-		dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+	memcpy(dev->dev_addr, iap, ETH_ALEN);
 
 	/* Adjust MAC if using default MAC address */
-	if (iap == fec_mac_default) {
-		dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-			iap[ETH_ALEN-1] + fep->index;
-	}
+	if (iap == fec_mac_default)
+		dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@
 #else
 
 /*
- *	Code sepcific to the MPC860T setup.
+ *	Code specific to the MPC860T setup.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
@@ -1424,13 +1457,10 @@
 
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
-	unsigned char *iap, tmpaddr[6];
 	bd_t *bd;
-	int i;
 
-	iap = bd->bi_enetaddr;
 	bd = (bd_t *)__res;
+	memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
 
 #ifdef CONFIG_RPXCLASSIC
 	/* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@
 	 * the address bits above something that would have (up to
 	 * now) been allocated.
 	 */
-	for (i=0; i<6; i++)
-		tmpaddr[i] = *iap++;
-	tmpaddr[3] |= 0x80;
-	iap = tmpaddr;
+	dev->dev_adrd[3] |= 0x80;
 #endif
-
-	for (i=0; i<6; i++)
-		dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
 }
 
 static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@
 static void mii_display_config(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
+	uint status = fep->phy_status;
 
 	/*
 	** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@
 	fep->mii_phy_task_queued = 0;
 	printk("%s: config: auto-negotiation ", dev->name);
 
-	if (*s & PHY_CONF_ANE)
+	if (status & PHY_CONF_ANE)
 		printk("on");
 	else
 		printk("off");
 
-	if (*s & PHY_CONF_100FDX)
+	if (status & PHY_CONF_100FDX)
 		printk(", 100FDX");
-	if (*s & PHY_CONF_100HDX)
+	if (status & PHY_CONF_100HDX)
 		printk(", 100HDX");
-	if (*s & PHY_CONF_10FDX)
+	if (status & PHY_CONF_10FDX)
 		printk(", 10FDX");
-	if (*s & PHY_CONF_10HDX)
+	if (status & PHY_CONF_10HDX)
 		printk(", 10HDX");
-	if (!(*s & PHY_CONF_SPMASK))
+	if (!(status & PHY_CONF_SPMASK))
 		printk(", No speed/duplex selected?");
 
-	if (*s & PHY_CONF_LOOP)
+	if (status & PHY_CONF_LOOP)
 		printk(", loopback enabled");
 	
 	printk(".\n");
@@ -1639,7 +1663,7 @@
 	schedule_work(&fep->phy_task);
 }
 
-/* mii_queue_config is called in user context from fec_enet_open */
+/* mii_queue_config is called in interrupt context from fec_enet_mii */
 static void mii_queue_config(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@
 	schedule_work(&fep->phy_task);
 }
 
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
-			       { mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
-			       { mk_mii_end, } };
-
-
+phy_cmd_t const phy_cmd_relink[] = {
+	{ mk_mii_read(MII_REG_CR), mii_queue_relink },
+	{ mk_mii_end, }
+	};
+phy_cmd_t const phy_cmd_config[] = {
+	{ mk_mii_read(MII_REG_CR), mii_queue_config },
+	{ mk_mii_end, }
+	};
 
 /* Read remainder of PHY ID.
 */
@@ -1897,17 +1921,15 @@
 static void
 fec_set_mac_address(struct net_device *dev)
 {
-	struct fec_enet_private *fep;
 	volatile fec_t *fecp;
 
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
+	fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
 
 	/* Set station address. */
-	fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-		(fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-	fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-		(fep->mac_addr[4] << 24);
+	fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
+	fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
+		(dev->dev_addr[4] << 24);
 
 }
 
@@ -1943,7 +1965,7 @@
 	udelay(10);
 
 	/* Clear and enable interrupts */
-	fecp->fec_ievent = 0xffc0;
+	fecp->fec_ievent = 0xffc00000;
 	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
 		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
 	fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@
 	/* setup MII interface */
 	fec_set_mii(dev, fep);
 
-	printk("%s: FEC ENET Version 0.2, ", dev->name);
-	for (i=0; i<5; i++)
-		printk("%02x:", dev->dev_addr[i]);
-	printk("%02x\n", dev->dev_addr[5]);
-
 	/* Queue up command to detect the PHY and initialize the
 	 * remainder of the interface.
 	 */
@@ -2106,18 +2123,12 @@
 
 	/* Clear any outstanding interrupt.
 	*/
-	fecp->fec_ievent = 0xffc0;
+	fecp->fec_ievent = 0xffc00000;
 	fec_enable_phy_intr();
 
 	/* Set station address.
 	*/
-	fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-		(fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-	fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-		(fep->mac_addr[4] << 24);
-
-	for (i=0; i<ETH_ALEN; i++)
-		dev->dev_addr[i] = fep->mac_addr[i];
+	fec_set_mac_address(dev);
 
 	/* Reset all multicast.
 	*/
@@ -2215,7 +2226,7 @@
 
 	fecp->fec_x_cntrl = 0x01;	/* Graceful transmit stop */
 
-	while(!(fecp->fec_ievent & 0x10000000));
+	while(!(fecp->fec_ievent & FEC_ENET_GRA));
 
 	/* Whack a reset.  We should wait for this.
 	*/
@@ -2234,7 +2245,9 @@
 static int __init fec_enet_module_init(void)
 {
 	struct net_device *dev;
-	int i, err;
+	int i, j, err;
+
+	printk("FEC ENET Version 0.2\n");
 
 	for (i = 0; (i < FEC_MAX_PORTS); i++) {
 		dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@
 			free_netdev(dev);
 			return -EIO;
 		}
+
+		printk("%s: ethernet ", dev->name);
+		for (j = 0; (j < 5); j++)
+			printk("%02x:", dev->dev_addr[j]);
+		printk("%02x\n", dev->dev_addr[5]);
 	}
 	return 0;
 }
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index c6e4f97..045761b 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -1,8 +1,9 @@
 /****************************************************************************/
 
 /*
- *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5270,
-		   5271, 5272, 5274, 5275, 5280 and 5282.
+ *	fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5230,
+ *		   5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
+ *		   5280 and 5282.
  *
  *	(C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
  *	(C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
 #define	FEC_H
 /****************************************************************************/
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /*
  *	Just figures, Motorola would have to change the offsets for
  *	registers in the same peripheral device on different models
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d1fb1ba..bedd7f9 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -629,6 +629,7 @@
 	PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+	PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
 	PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
 	PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
 	PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 39ba640..80969f7 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -376,6 +376,7 @@
     socket_t i = iminor(inode);
     struct pcmcia_socket *s;
     user_info_t *user;
+    static int warning_printed = 0;
 
     ds_dbg(0, "ds_open(socket %d)\n", i);
 
@@ -407,6 +408,17 @@
     s->user = user;
     file->private_data = user;
 
+    if (!warning_printed) {
+	    printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
+			"usage.\n");
+	    printk(KERN_INFO "pcmcia: This interface will soon be removed from "
+			"the kernel; please expect breakage unless you upgrade "
+			"to new tools.\n");
+	    printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
+			"utils/kernel/pcmcia/pcmcia.html for details.\n");
+	    warning_printed = 1;
+    }
+
     if (s->pcmcia_state.present)
 	queue_event(user, CS_EVENT_CARD_INSERTION);
     return 0;
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index 87302fb..ccb20a6 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -295,8 +295,7 @@
 
 static void snooze(unsigned long snooze_time, unsigned minor)
 {
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(snooze_time + 1);
+	schedule_timeout_uninterruptible(snooze_time + 1);
 }
 
 static int wait_for(unsigned short set, unsigned short clr,
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index dbad7f3..24ed589 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -14,7 +14,7 @@
 #include <linux/major.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
-#include <linux/ioport.h>		/* request_region, check_region */
+#include <linux/ioport.h>		/* request_region */
 #include <asm/atomic.h>
 #include <asm/ebus.h>			/* EBus device					*/
 #include <asm/oplib.h>			/* OpenProm Library 			*/
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 739cad9..ceec306 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -81,8 +81,7 @@
 
 void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) 
 {
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(usecs_to_jiffies(usecs));
+	schedule_timeout_uninterruptible(usecs_to_jiffies(usecs));
 }
 
 void inline vfc_i2c_delay(struct vfc_dev *dev) 
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index bc6e462..a6ac616 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -59,6 +59,7 @@
                  Fix 'handled=1' ISR usage, remove bogus IRQ check.
                  Remove un-needed eh_abort handler.
                  Add support for embedded firmware error strings.
+   2.26.02.003 - Correctly handle single sgl's with use_sg=1.
 */
 
 #include <linux/module.h>
@@ -81,7 +82,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.002"
+#define TW_DRIVER_VERSION "2.26.02.003"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -1805,6 +1806,8 @@
 			if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {
 				command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
 				command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)
+					memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);
 			} else {
 				buffaddr = twa_map_scsi_single_data(tw_dev, request_id);
 				if (buffaddr == 0)
@@ -1823,6 +1826,12 @@
 
 		if (tw_dev->srb[request_id]->use_sg > 0) {
 			if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+				if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {
+					struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+					char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+					memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);
+					kunmap_atomic(buf - sg->offset, KM_IRQ0);
+				}
 				command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
 				command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
 			} else {
@@ -1888,11 +1897,20 @@
 /* This function completes an execute scsi operation */
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
 {
-	/* Copy the response if too small */
-	if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
-		memcpy(tw_dev->srb[request_id]->request_buffer,
-		       tw_dev->generic_buffer_virt[request_id],
-		       tw_dev->srb[request_id]->request_bufflen);
+	if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&
+	    (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||
+	     tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {
+		if (tw_dev->srb[request_id]->use_sg == 0) {
+			memcpy(tw_dev->srb[request_id]->request_buffer,
+			       tw_dev->generic_buffer_virt[request_id],
+			       tw_dev->srb[request_id]->request_bufflen);
+		}
+		if (tw_dev->srb[request_id]->use_sg == 1) {
+			struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
+			char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+			memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
+			kunmap_atomic(buf - sg->offset, KM_IRQ0);
+		}
 	}
 } /* End twa_scsiop_execute_scsi_complete() */
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 2d21265..20019b8 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -235,6 +235,13 @@
 	  each attached iSCSI device to sysfs, say Y.
 	  Otherwise, say N.
 
+config SCSI_SAS_ATTRS
+	tristate "SAS Transport Attributes"
+	depends on SCSI
+	help
+	  If you wish to export transport-specific information about
+	  each attached SAS device to sysfs, say Y.
+
 endmenu
 
 menu "SCSI low-level drivers"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 4b4fd94..1e4edbd 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -31,6 +31,7 @@
 obj-$(CONFIG_SCSI_SPI_ATTRS)	+= scsi_transport_spi.o
 obj-$(CONFIG_SCSI_FC_ATTRS) 	+= scsi_transport_fc.o
 obj-$(CONFIG_SCSI_ISCSI_ATTRS)	+= scsi_transport_iscsi.o
+obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
 
 obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 0e089a4..86eaf6d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -966,21 +966,21 @@
 lpfc_get_host_fabric_name (struct Scsi_Host *shost)
 {
 	struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];
-	u64 nodename;
+	u64 node_name;
 
 	spin_lock_irq(shost->host_lock);
 
 	if ((phba->fc_flag & FC_FABRIC) ||
 	    ((phba->fc_topology == TOPOLOGY_LOOP) &&
 	     (phba->fc_flag & FC_PUBLIC_LOOP)))
-		memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64));
+		node_name = wwn_to_u64(phba->fc_fabparam.nodeName.wwn);
 	else
 		/* fabric is local port if there is no F/FL_Port */
-		memcpy(&nodename, &phba->fc_nodename, sizeof(u64));
+		node_name = wwn_to_u64(phba->fc_nodename.wwn);
 
 	spin_unlock_irq(shost->host_lock);
 
-	fc_host_fabric_name(shost) = be64_to_cpu(nodename);
+	fc_host_fabric_name(shost) = node_name;
 }
 
 
@@ -1103,21 +1103,20 @@
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 	struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
-	uint64_t node_name = 0;
+	u64 node_name = 0;
 	struct lpfc_nodelist *ndlp = NULL;
 
 	spin_lock_irq(shost->host_lock);
 	/* Search the mapped list for this target ID */
 	list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
 		if (starget->id == ndlp->nlp_sid) {
-			memcpy(&node_name, &ndlp->nlp_nodename,
-						sizeof(struct lpfc_name));
+			node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);
 			break;
 		}
 	}
 	spin_unlock_irq(shost->host_lock);
 
-	fc_starget_node_name(starget) = be64_to_cpu(node_name);
+	fc_starget_node_name(starget) = node_name;
 }
 
 static void
@@ -1125,21 +1124,20 @@
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 	struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];
-	uint64_t port_name = 0;
+	u64 port_name = 0;
 	struct lpfc_nodelist *ndlp = NULL;
 
 	spin_lock_irq(shost->host_lock);
 	/* Search the mapped list for this target ID */
 	list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
 		if (starget->id == ndlp->nlp_sid) {
-			memcpy(&port_name, &ndlp->nlp_portname,
-						sizeof(struct lpfc_name));
+			port_name = wwn_to_u64(ndlp->nlp_portname.wwn);
 			break;
 		}
 	}
 	spin_unlock_irq(shost->host_lock);
 
-	fc_starget_port_name(starget) = be64_to_cpu(port_name);
+	fc_starget_port_name(starget) = port_name;
 }
 
 static void
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 0a8269d..4fb8eb0 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1017,13 +1017,10 @@
 	struct fc_rport *rport;
 	struct lpfc_rport_data *rdata;
 	struct fc_rport_identifiers rport_ids;
-	uint64_t wwn;
 
 	/* Remote port has reappeared. Re-register w/ FC transport */
-	memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t));
-	rport_ids.node_name = be64_to_cpu(wwn);
-	memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t));
-	rport_ids.port_name = be64_to_cpu(wwn);
+	rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);
+	rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.wwn);
 	rport_ids.port_id = ndlp->nlp_DID;
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
 	if (ndlp->nlp_type & NLP_FCP_TARGET)
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 21591cb..047a87c 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -262,12 +262,14 @@
 #define FF_FRAME_SIZE     2048
 
 struct lpfc_name {
+	union {
+		struct {
 #ifdef __BIG_ENDIAN_BITFIELD
-	uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
-	uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+			uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
+			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
 #else	/*  __LITTLE_ENDIAN_BITFIELD */
-	uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
-	uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
+			uint8_t IEEEextMsn:4;	/* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */
+			uint8_t nameType:4;	/* FC Word 0, bit 28:31 */
 #endif
 
 #define NAME_IEEE           0x1	/* IEEE name - nameType */
@@ -276,8 +278,11 @@
 #define NAME_IP_TYPE        0x4	/* IP address */
 #define NAME_CCITT_TYPE     0xC
 #define NAME_CCITT_GR_TYPE  0xE
-	uint8_t IEEEextLsb;	/* FC Word 0, bit 16:23, IEEE extended Lsb */
-	uint8_t IEEE[6];	/* FC IEEE address */
+			uint8_t IEEEextLsb;	/* FC Word 0, bit 16:23, IEEE extended Lsb */
+			uint8_t IEEE[6];	/* FC IEEE address */
+		};
+		uint8_t wwn[8];
+	};
 };
 
 struct csp {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 6f3cb59..454058f 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1333,7 +1333,6 @@
 	unsigned long bar0map_len, bar2map_len;
 	int error = -ENODEV, retval;
 	int i;
-	u64 wwname;
 
 	if (pci_enable_device(pdev))
 		goto out;
@@ -1524,10 +1523,8 @@
 	 * Must done after lpfc_sli_hba_setup()
 	 */
 
-	memcpy(&wwname, &phba->fc_nodename, sizeof(u64));
-	fc_host_node_name(host) = be64_to_cpu(wwname);
-	memcpy(&wwname, &phba->fc_portname, sizeof(u64));
-	fc_host_port_name(host) = be64_to_cpu(wwname);
+	fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.wwn);
+	fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.wwn);
 	fc_host_supported_classes(host) = FC_COS_CLASS3;
 
 	memset(fc_host_supported_fc4s(host), 0,
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index fe0fce7..fc25cd8 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -360,16 +360,16 @@
 	struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
 	scsi_qla_host_t *ha = to_qla_host(host);
 	fc_port_t *fcport;
-	uint64_t node_name = 0;
+	u64 node_name = 0;
 
 	list_for_each_entry(fcport, &ha->fcports, list) {
 		if (starget->id == fcport->os_target_id) {
-			node_name = *(uint64_t *)fcport->node_name;
+			node_name = wwn_to_u64(fcport->node_name);
 			break;
 		}
 	}
 
-	fc_starget_node_name(starget) = be64_to_cpu(node_name);
+	fc_starget_node_name(starget) = node_name;
 }
 
 static void
@@ -378,16 +378,16 @@
 	struct Scsi_Host *host = dev_to_shost(starget->dev.parent);
 	scsi_qla_host_t *ha = to_qla_host(host);
 	fc_port_t *fcport;
-	uint64_t port_name = 0;
+	u64 port_name = 0;
 
 	list_for_each_entry(fcport, &ha->fcports, list) {
 		if (starget->id == fcport->os_target_id) {
-			port_name = *(uint64_t *)fcport->port_name;
+			port_name = wwn_to_u64(fcport->port_name);
 			break;
 		}
 	}
 
-	fc_starget_port_name(starget) = be64_to_cpu(port_name);
+	fc_starget_port_name(starget) = port_name;
 }
 
 static void
@@ -460,9 +460,7 @@
 void
 qla2x00_init_host_attr(scsi_qla_host_t *ha)
 {
-	fc_host_node_name(ha->host) =
-	    be64_to_cpu(*(uint64_t *)ha->init_cb->node_name);
-	fc_host_port_name(ha->host) =
-	    be64_to_cpu(*(uint64_t *)ha->init_cb->port_name);
+	fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name);
+	fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name);
 	fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
 }
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index c619583..3e9b641 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2066,8 +2066,8 @@
 		return;
 	}
 
-	rport_ids.node_name = be64_to_cpu(*(uint64_t *)fcport->node_name);
-	rport_ids.port_name = be64_to_cpu(*(uint64_t *)fcport->port_name);
+	rport_ids.node_name = wwn_to_u64(fcport->node_name);
+	rport_ids.port_name = wwn_to_u64(fcport->port_name);
 	rport_ids.port_id = fcport->d_id.b.domain << 16 |
 	    fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
 	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 77f2d44..863bb64 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -97,6 +97,30 @@
 }
 
 static void scsi_run_queue(struct request_queue *q);
+static void scsi_release_buffers(struct scsi_cmnd *cmd);
+
+/*
+ * Function:	scsi_unprep_request()
+ *
+ * Purpose:	Remove all preparation done for a request, including its
+ *		associated scsi_cmnd, so that it can be requeued.
+ *
+ * Arguments:	req	- request to unprepare
+ *
+ * Lock status:	Assumed that no locks are held upon entry.
+ *
+ * Returns:	Nothing.
+ */
+static void scsi_unprep_request(struct request *req)
+{
+	struct scsi_cmnd *cmd = req->special;
+
+	req->flags &= ~REQ_DONTPREP;
+	req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+
+	scsi_release_buffers(cmd);
+	scsi_put_command(cmd);
+}
 
 /*
  * Function:    scsi_queue_insert()
@@ -116,12 +140,14 @@
  *              commands.
  * Notes:       This could be called either from an interrupt context or a
  *              normal process context.
+ * Notes:	Upon return, cmd is a stale pointer.
  */
 int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
 {
 	struct Scsi_Host *host = cmd->device->host;
 	struct scsi_device *device = cmd->device;
 	struct request_queue *q = device->request_queue;
+	struct request *req = cmd->request;
 	unsigned long flags;
 
 	SCSI_LOG_MLQUEUE(1,
@@ -162,8 +188,9 @@
 	 * function.  The SCSI request function detects the blocked condition
 	 * and plugs the queue appropriately.
          */
+	scsi_unprep_request(req);
 	spin_lock_irqsave(q->queue_lock, flags);
-	blk_requeue_request(q, cmd->request);
+	blk_requeue_request(q, req);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	scsi_run_queue(q);
@@ -339,7 +366,7 @@
 	int result;
 	
 	if (sshdr) {
-		sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+		sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
 		if (!sense)
 			return DRIVER_ERROR << 24;
 		memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
@@ -552,15 +579,16 @@
  *		I/O errors in the middle of the request, in which case
  *		we need to request the blocks that come after the bad
  *		sector.
+ * Notes:	Upon return, cmd is a stale pointer.
  */
 static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
 {
+	struct request *req = cmd->request;
 	unsigned long flags;
 
-	cmd->request->flags &= ~REQ_DONTPREP;
-
+	scsi_unprep_request(req);
 	spin_lock_irqsave(q->queue_lock, flags);
-	blk_requeue_request(q, cmd->request);
+	blk_requeue_request(q, req);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	scsi_run_queue(q);
@@ -595,13 +623,14 @@
  *
  * Lock status: Assumed that lock is not held upon entry.
  *
- * Returns:     cmd if requeue done or required, NULL otherwise
+ * Returns:     cmd if requeue required, NULL otherwise.
  *
  * Notes:       This is called for block device requests in order to
  *              mark some number of sectors as complete.
  * 
  *		We are guaranteeing that the request queue will be goosed
  *		at some point during this call.
+ * Notes:	If cmd was requeued, upon return it will be a stale pointer.
  */
 static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
 					  int bytes, int requeue)
@@ -624,14 +653,15 @@
 		if (!uptodate && blk_noretry_request(req))
 			end_that_request_chunk(req, 0, leftover);
 		else {
-			if (requeue)
+			if (requeue) {
 				/*
 				 * Bleah.  Leftovers again.  Stick the
 				 * leftovers in the front of the
 				 * queue, and goose the queue again.
 				 */
 				scsi_requeue_command(q, cmd);
-
+				cmd = NULL;
+			}
 			return cmd;
 		}
 	}
@@ -857,15 +887,13 @@
 		 * requeueing right here - we will requeue down below
 		 * when we handle the bad sectors.
 		 */
-		cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);
 
 		/*
-		 * If the command completed without error, then either finish off the
-		 * rest of the command, or start a new one.
+		 * If the command completed without error, then either
+		 * finish off the rest of the command, or start a new one.
 		 */
-		if (result == 0 || cmd == NULL ) {
+		if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)
 			return;
-		}
 	}
 	/*
 	 * Now, if we were good little boys and girls, Santa left us a request
@@ -880,7 +908,7 @@
 				 * and quietly refuse further access.
 				 */
 				cmd->device->changed = 1;
-				cmd = scsi_end_request(cmd, 0,
+				scsi_end_request(cmd, 0,
 						this_count, 1);
 				return;
 			} else {
@@ -914,7 +942,7 @@
 				scsi_requeue_command(q, cmd);
 				result = 0;
 			} else {
-				cmd = scsi_end_request(cmd, 0, this_count, 1);
+				scsi_end_request(cmd, 0, this_count, 1);
 				return;
 			}
 			break;
@@ -931,7 +959,7 @@
 				dev_printk(KERN_INFO,
 					   &cmd->device->sdev_gendev,
 					   "Device not ready.\n");
-			cmd = scsi_end_request(cmd, 0, this_count, 1);
+			scsi_end_request(cmd, 0, this_count, 1);
 			return;
 		case VOLUME_OVERFLOW:
 			if (!(req->flags & REQ_QUIET)) {
@@ -941,7 +969,7 @@
 				__scsi_print_command(cmd->data_cmnd);
 				scsi_print_sense("", cmd);
 			}
-			cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+			scsi_end_request(cmd, 0, block_bytes, 1);
 			return;
 		default:
 			break;
@@ -972,7 +1000,7 @@
 		block_bytes = req->hard_cur_sectors << 9;
 		if (!block_bytes)
 			block_bytes = req->data_len;
-		cmd = scsi_end_request(cmd, 0, block_bytes, 1);
+		scsi_end_request(cmd, 0, block_bytes, 1);
 	}
 }
 EXPORT_SYMBOL(scsi_io_completion);
@@ -1118,7 +1146,7 @@
 	if (unlikely(!scsi_device_online(sdev))) {
 		printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
 		       sdev->host->host_no, sdev->id, sdev->lun);
-		return BLKPREP_KILL;
+		goto kill;
 	}
 	if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
 		/* OK, we're not in a running state don't prep
@@ -1128,7 +1156,7 @@
 			 * at all allowed down */
 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
 			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
+			goto kill;
 		}
 		/* OK, we only allow special commands (i.e. not
 		 * user initiated ones */
@@ -1160,11 +1188,11 @@
 		if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
 			if(specials_only == SDEV_QUIESCE ||
 					specials_only == SDEV_BLOCK)
-				return BLKPREP_DEFER;
+				goto defer;
 			
 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
 			       sdev->host->host_no, sdev->id, sdev->lun);
-			return BLKPREP_KILL;
+			goto kill;
 		}
 			
 			
@@ -1182,7 +1210,7 @@
 		cmd->tag = req->tag;
 	} else {
 		blk_dump_rq_flags(req, "SCSI bad req");
-		return BLKPREP_KILL;
+		goto kill;
 	}
 	
 	/* note the overloading of req->special.  When the tag
@@ -1220,8 +1248,13 @@
 		 * required).
 		 */
 		ret = scsi_init_io(cmd);
-		if (ret)	/* BLKPREP_KILL return also releases the command */
-			return ret;
+		switch(ret) {
+		case BLKPREP_KILL:
+			/* BLKPREP_KILL return also releases the command */
+			goto kill;
+		case BLKPREP_DEFER:
+			goto defer;
+		}
 		
 		/*
 		 * Initialize the actual SCSI command for this request.
@@ -1231,7 +1264,7 @@
 			if (unlikely(!drv->init_command(cmd))) {
 				scsi_release_buffers(cmd);
 				scsi_put_command(cmd);
-				return BLKPREP_KILL;
+				goto kill;
 			}
 		} else {
 			memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
@@ -1262,6 +1295,9 @@
 	if (sdev->device_busy == 0)
 		blk_plug_device(q);
 	return BLKPREP_DEFER;
+ kill:
+	req->errors = DID_NO_CONNECT << 16;
+	return BLKPREP_KILL;
 }
 
 /*
@@ -1336,19 +1372,24 @@
 }
 
 /*
- * Kill requests for a dead device
+ * Kill a request for a dead device
  */
-static void scsi_kill_requests(request_queue_t *q)
+static void scsi_kill_request(struct request *req, request_queue_t *q)
 {
-	struct request *req;
+	struct scsi_cmnd *cmd = req->special;
 
-	while ((req = elv_next_request(q)) != NULL) {
-		blkdev_dequeue_request(req);
-		req->flags |= REQ_QUIET;
-		while (end_that_request_first(req, 0, req->nr_sectors))
-			;
-		end_that_request_last(req);
+	blkdev_dequeue_request(req);
+
+	if (unlikely(cmd == NULL)) {
+		printk(KERN_CRIT "impossible request in %s.\n",
+				 __FUNCTION__);
+		BUG();
 	}
+
+	scsi_init_cmd_errh(cmd);
+	cmd->result = DID_NO_CONNECT << 16;
+	atomic_inc(&cmd->device->iorequest_cnt);
+	__scsi_done(cmd);
 }
 
 /*
@@ -1371,7 +1412,8 @@
 
 	if (!sdev) {
 		printk("scsi: killing requests for dead queue\n");
-		scsi_kill_requests(q);
+		while ((req = elv_next_request(q)) != NULL)
+			scsi_kill_request(req, q);
 		return;
 	}
 
@@ -1398,11 +1440,7 @@
 		if (unlikely(!scsi_device_online(sdev))) {
 			printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",
 			       sdev->host->host_no, sdev->id, sdev->lun);
-			blkdev_dequeue_request(req);
-			req->flags |= REQ_QUIET;
-			while (end_that_request_first(req, 0, req->nr_sectors))
-				;
-			end_that_request_last(req);
+			scsi_kill_request(req, q);
 			continue;
 		}
 
@@ -1415,6 +1453,14 @@
 		sdev->device_busy++;
 
 		spin_unlock(q->queue_lock);
+		cmd = req->special;
+		if (unlikely(cmd == NULL)) {
+			printk(KERN_CRIT "impossible request in %s.\n"
+					 "please mail a stack trace to "
+					 "linux-scsi@vger.kernel.org",
+					 __FUNCTION__);
+			BUG();
+		}
 		spin_lock(shost->host_lock);
 
 		if (!scsi_host_queue_ready(q, shost, sdev))
@@ -1433,15 +1479,6 @@
 		 */
 		spin_unlock_irq(shost->host_lock);
 
-		cmd = req->special;
-		if (unlikely(cmd == NULL)) {
-			printk(KERN_CRIT "impossible request in %s.\n"
-					 "please mail a stack trace to "
-					 "linux-scsi@vger.kernel.org",
-					 __FUNCTION__);
-			BUG();
-		}
-
 		/*
 		 * Finally, initialize any error handling parameters, and set up
 		 * the timers for timeouts.
@@ -1477,6 +1514,7 @@
 	 * cases (host limits or settings) should run the queue at some
 	 * later time.
 	 */
+	scsi_unprep_request(req);
 	spin_lock_irq(q->queue_lock);
 	blk_requeue_request(q, req);
 	sdev->device_busy--;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index ee6de17..d05f778 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -124,6 +124,7 @@
 extern void scsi_sysfs_device_initialize(struct scsi_device *);
 extern int scsi_sysfs_target_initialize(struct scsi_device *);
 extern struct scsi_transport_template blank_transport_template;
+extern void __scsi_remove_device(struct scsi_device *);
 
 extern struct bus_type scsi_bus_type;
 
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 19c9a23..b86f170 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -870,8 +870,12 @@
  out_free_sdev:
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (sdevp) {
-			scsi_device_get(sdev);
-			*sdevp = sdev;
+			if (scsi_device_get(sdev) == 0) {
+				*sdevp = sdev;
+			} else {
+				__scsi_remove_device(sdev);
+				res = SCSI_SCAN_NO_RESPONSE;
+			}
 		}
 	} else {
 		if (sdev->host->hostt->slave_destroy)
@@ -1260,6 +1264,19 @@
 }
 EXPORT_SYMBOL(__scsi_add_device);
 
+int scsi_add_device(struct Scsi_Host *host, uint channel,
+		    uint target, uint lun)
+{
+	struct scsi_device *sdev = 
+		__scsi_add_device(host, channel, target, lun, NULL);
+	if (IS_ERR(sdev))
+		return PTR_ERR(sdev);
+
+	scsi_device_put(sdev);
+	return 0;
+}
+EXPORT_SYMBOL(scsi_add_device);
+
 void scsi_rescan_device(struct device *dev)
 {
 	struct scsi_driver *drv;
@@ -1276,27 +1293,8 @@
 }
 EXPORT_SYMBOL(scsi_rescan_device);
 
-/**
- * scsi_scan_target - scan a target id, possibly including all LUNs on the
- *     target.
- * @sdevsca:	Scsi_Device handle for scanning
- * @shost:	host to scan
- * @channel:	channel to scan
- * @id:		target id to scan
- *
- * Description:
- *     Scan the target id on @shost, @channel, and @id. Scan at least LUN
- *     0, and possibly all LUNs on the target id.
- *
- *     Use the pre-allocated @sdevscan as a handle for the scanning. This
- *     function sets sdevscan->host, sdevscan->id and sdevscan->lun; the
- *     scanning functions modify sdevscan->lun.
- *
- *     First try a REPORT LUN scan, if that does not scan the target, do a
- *     sequential scan of LUNs on the target id.
- **/
-void scsi_scan_target(struct device *parent, unsigned int channel,
-		      unsigned int id, unsigned int lun, int rescan)
+static void __scsi_scan_target(struct device *parent, unsigned int channel,
+		unsigned int id, unsigned int lun, int rescan)
 {
 	struct Scsi_Host *shost = dev_to_shost(parent);
 	int bflags = 0;
@@ -1310,9 +1308,7 @@
 		 */
 		return;
 
-
 	starget = scsi_alloc_target(parent, channel, id);
-
 	if (!starget)
 		return;
 
@@ -1358,6 +1354,33 @@
 
 	put_device(&starget->dev);
 }
+
+/**
+ * scsi_scan_target - scan a target id, possibly including all LUNs on the
+ *     target.
+ * @parent:	host to scan
+ * @channel:	channel to scan
+ * @id:		target id to scan
+ * @lun:	Specific LUN to scan or SCAN_WILD_CARD
+ * @rescan:	passed to LUN scanning routines
+ *
+ * Description:
+ *     Scan the target id on @parent, @channel, and @id. Scan at least LUN 0,
+ *     and possibly all LUNs on the target id.
+ *
+ *     First try a REPORT LUN scan, if that does not scan the target, do a
+ *     sequential scan of LUNs on the target id.
+ **/
+void scsi_scan_target(struct device *parent, unsigned int channel,
+		      unsigned int id, unsigned int lun, int rescan)
+{
+	struct Scsi_Host *shost = dev_to_shost(parent);
+
+	down(&shost->scan_mutex);
+	if (scsi_host_scan_allowed(shost))
+		__scsi_scan_target(parent, channel, id, lun, rescan);
+	up(&shost->scan_mutex);
+}
 EXPORT_SYMBOL(scsi_scan_target);
 
 static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
@@ -1383,10 +1406,12 @@
 				order_id = shost->max_id - id - 1;
 			else
 				order_id = id;
-			scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
+			__scsi_scan_target(&shost->shost_gendev, channel,
+					order_id, lun, rescan);
 		}
 	else
-		scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
+		__scsi_scan_target(&shost->shost_gendev, channel,
+				id, lun, rescan);
 }
 
 int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1484,12 +1509,15 @@
  */
 struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 {
-	struct scsi_device *sdev;
+	struct scsi_device *sdev = NULL;
 	struct scsi_target *starget;
 
+	down(&shost->scan_mutex);
+	if (!scsi_host_scan_allowed(shost))
+		goto out;
 	starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
 	if (!starget)
-		return NULL;
+		goto out;
 
 	sdev = scsi_alloc_sdev(starget, 0, NULL);
 	if (sdev) {
@@ -1497,6 +1525,8 @@
 		sdev->borken = 0;
 	}
 	put_device(&starget->dev);
+ out:
+	up(&shost->scan_mutex);
 	return sdev;
 }
 EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index dae59d1..b8052d5 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -653,7 +653,7 @@
 			error = attr_add(&sdev->sdev_gendev,
 					sdev->host->hostt->sdev_attrs[i]);
 			if (error) {
-				scsi_remove_device(sdev);
+				__scsi_remove_device(sdev);
 				goto out;
 			}
 		}
@@ -667,7 +667,7 @@
 							scsi_sysfs_sdev_attrs[i]);
 			error = device_create_file(&sdev->sdev_gendev, attr);
 			if (error) {
-				scsi_remove_device(sdev);
+				__scsi_remove_device(sdev);
 				goto out;
 			}
 		}
@@ -687,17 +687,10 @@
 	return error;
 }
 
-/**
- * scsi_remove_device - unregister a device from the scsi bus
- * @sdev:	scsi_device to unregister
- **/
-void scsi_remove_device(struct scsi_device *sdev)
+void __scsi_remove_device(struct scsi_device *sdev)
 {
-	struct Scsi_Host *shost = sdev->host;
-
-	down(&shost->scan_mutex);
 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-		goto out;
+		return;
 
 	class_device_unregister(&sdev->sdev_classdev);
 	device_del(&sdev->sdev_gendev);
@@ -706,8 +699,17 @@
 		sdev->host->hostt->slave_destroy(sdev);
 	transport_unregister_device(&sdev->sdev_gendev);
 	put_device(&sdev->sdev_gendev);
-out:
-	up(&shost->scan_mutex);
+}
+
+/**
+ * scsi_remove_device - unregister a device from the scsi bus
+ * @sdev:	scsi_device to unregister
+ **/
+void scsi_remove_device(struct scsi_device *sdev)
+{
+	down(&sdev->host->scan_mutex);
+	__scsi_remove_device(sdev);
+	up(&sdev->host->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
new file mode 100644
index 0000000..ff724bbe
--- /dev/null
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (C) 2005 Dell Inc.
+ *	Released under GPL v2.
+ *
+ * Serial Attached SCSI (SAS) transport class.
+ *
+ * The SAS transport class contains common code to deal with SAS HBAs,
+ * an aproximated representation of SAS topologies in the driver model,
+ * and various sysfs attributes to expose these topologies and managment
+ * interfaces to userspace.
+ *
+ * In addition to the basic SCSI core objects this transport class
+ * introduces two additional intermediate objects:  The SAS PHY
+ * as represented by struct sas_phy defines an "outgoing" PHY on
+ * a SAS HBA or Expander, and the SAS remote PHY represented by
+ * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
+ * end device.  Note that this is purely a software concept, the
+ * underlying hardware for a PHY and a remote PHY is the exactly
+ * the same.
+ *
+ * There is no concept of a SAS port in this code, users can see
+ * what PHYs form a wide port based on the port_identifier attribute,
+ * which is the same for all PHYs in a port.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_sas.h>
+
+
+#define SAS_HOST_ATTRS		0
+#define SAS_PORT_ATTRS		11
+#define SAS_RPORT_ATTRS		5
+
+struct sas_internal {
+	struct scsi_transport_template t;
+	struct sas_function_template *f;
+
+	struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+	struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+	struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+
+	struct transport_container phy_attr_cont;
+	struct transport_container rphy_attr_cont;
+
+	/*
+	 * The array of null terminated pointers to attributes
+	 * needed by scsi_sysfs.c
+	 */
+	struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+	struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+	struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+};
+#define to_sas_internal(tmpl)	container_of(tmpl, struct sas_internal, t)
+
+struct sas_host_attrs {
+	struct list_head rphy_list;
+	spinlock_t lock;
+	u32 next_target_id;
+};
+#define to_sas_host_attrs(host)	((struct sas_host_attrs *)(host)->shost_data)
+
+
+/*
+ * Hack to allow attributes of the same name in different objects.
+ */
+#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
+	struct class_device_attribute class_device_attr_##_prefix##_##_name = \
+	__ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * Pretty printing helpers
+ */
+
+#define sas_bitfield_name_match(title, table)			\
+static ssize_t							\
+get_sas_##title##_names(u32 table_key, char *buf)		\
+{								\
+	char *prefix = "";					\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+		if (table[i].value & table_key) {		\
+			len += sprintf(buf + len, "%s%s",	\
+				prefix, table[i].name);		\
+			prefix = ", ";				\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+#define sas_bitfield_name_search(title, table)			\
+static ssize_t							\
+get_sas_##title##_names(u32 table_key, char *buf)		\
+{								\
+	ssize_t len = 0;					\
+	int i;							\
+								\
+	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+		if (table[i].value == table_key) {		\
+			len += sprintf(buf + len, "%s",		\
+				table[i].name);			\
+			break;					\
+		}						\
+	}							\
+	len += sprintf(buf + len, "\n");			\
+	return len;						\
+}
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_device_type_names[] = {
+	{ SAS_PHY_UNUSED,		"unused" },
+	{ SAS_END_DEVICE,		"end device" },
+	{ SAS_EDGE_EXPANDER_DEVICE,	"edge expander" },
+	{ SAS_FANOUT_EXPANDER_DEVICE,	"fanout expander" },
+};
+sas_bitfield_name_search(device_type, sas_device_type_names)
+
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_protocol_names[] = {
+	{ SAS_PROTOCOL_SATA,		"sata" },
+	{ SAS_PROTOCOL_SMP,		"smp" },
+	{ SAS_PROTOCOL_STP,		"stp" },
+	{ SAS_PROTOCOL_SSP,		"ssp" },
+};
+sas_bitfield_name_match(protocol, sas_protocol_names)
+
+static struct {
+	u32		value;
+	char		*name;
+} sas_linkspeed_names[] = {
+	{ SAS_LINK_RATE_UNKNOWN,	"Unknown" },
+	{ SAS_PHY_DISABLED,		"Phy disabled" },
+	{ SAS_LINK_RATE_FAILED,		"Link Rate failed" },
+	{ SAS_SATA_SPINUP_HOLD,		"Spin-up hold" },
+	{ SAS_LINK_RATE_1_5_GBPS,	"1.5 Gbit" },
+	{ SAS_LINK_RATE_3_0_GBPS,	"3.0 Gbit" },
+};
+sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
+
+
+/*
+ * SAS host attributes
+ */
+
+static int sas_host_setup(struct transport_container *tc, struct device *dev,
+			  struct class_device *cdev)
+{
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+	INIT_LIST_HEAD(&sas_host->rphy_list);
+	spin_lock_init(&sas_host->lock);
+	sas_host->next_target_id = 0;
+	return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(sas_host_class,
+		"sas_host", sas_host_setup, NULL, NULL);
+
+static int sas_host_match(struct attribute_container *cont,
+			    struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct sas_internal *i;
+
+	if (!scsi_is_host_device(dev))
+		return 0;
+	shost = dev_to_shost(dev);
+
+	if (!shost->transportt)
+		return 0;
+	if (shost->transportt->host_attrs.ac.class !=
+			&sas_host_class.class)
+		return 0;
+
+	i = to_sas_internal(shost->transportt);
+	return &i->t.host_attrs.ac == cont;
+}
+
+static int do_sas_phy_delete(struct device *dev, void *data)
+{
+	if (scsi_is_sas_phy(dev))
+		sas_phy_delete(dev_to_phy(dev));
+	return 0;
+}
+
+/**
+ * sas_remove_host  --  tear down a Scsi_Host's SAS data structures
+ * @shost:	Scsi Host that is torn down
+ *
+ * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
+ * Must be called just before scsi_remove_host for SAS HBAs.
+ */
+void sas_remove_host(struct Scsi_Host *shost)
+{
+	device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete);
+}
+EXPORT_SYMBOL(sas_remove_host);
+
+
+/*
+ * SAS Port attributes
+ */
+
+#define sas_phy_show_simple(field, name, format_string, cast)		\
+static ssize_t								\
+show_sas_phy_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_phy *phy = transport_class_to_phy(cdev);		\
+									\
+	return snprintf(buf, 20, format_string, cast phy->field);	\
+}
+
+#define sas_phy_simple_attr(field, name, format_string, type)		\
+	sas_phy_show_simple(field, name, format_string, (type))	\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_protocol(field, name)				\
+static ssize_t								\
+show_sas_phy_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_phy *phy = transport_class_to_phy(cdev);		\
+									\
+	if (!phy->field)						\
+		return snprintf(buf, 20, "none\n");			\
+	return get_sas_protocol_names(phy->field, buf);		\
+}
+
+#define sas_phy_protocol_attr(field, name)				\
+	sas_phy_show_protocol(field, name)				\
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
+
+#define sas_phy_show_linkspeed(field)					\
+static ssize_t								\
+show_sas_phy_##field(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_phy *phy = transport_class_to_phy(cdev);		\
+									\
+	return get_sas_linkspeed_names(phy->field, buf);		\
+}
+
+#define sas_phy_linkspeed_attr(field)					\
+	sas_phy_show_linkspeed(field)					\
+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
+
+static ssize_t
+show_sas_device_type(struct class_device *cdev, char *buf)
+{
+	struct sas_phy *phy = transport_class_to_phy(cdev);
+
+	if (!phy->identify.device_type)
+		return snprintf(buf, 20, "none\n");
+	return get_sas_device_type_names(phy->identify.device_type, buf);
+}
+
+static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
+
+sas_phy_protocol_attr(identify.initiator_port_protocols,
+		initiator_port_protocols);
+sas_phy_protocol_attr(identify.target_port_protocols,
+		target_port_protocols);
+sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+		unsigned long long);
+sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
+sas_phy_linkspeed_attr(negotiated_linkrate);
+sas_phy_linkspeed_attr(minimum_linkrate_hw);
+sas_phy_linkspeed_attr(minimum_linkrate);
+sas_phy_linkspeed_attr(maximum_linkrate_hw);
+sas_phy_linkspeed_attr(maximum_linkrate);
+
+
+static DECLARE_TRANSPORT_CLASS(sas_phy_class,
+		"sas_phy", NULL, NULL, NULL);
+
+static int sas_phy_match(struct attribute_container *cont, struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct sas_internal *i;
+
+	if (!scsi_is_sas_phy(dev))
+		return 0;
+	shost = dev_to_shost(dev->parent);
+
+	if (!shost->transportt)
+		return 0;
+	if (shost->transportt->host_attrs.ac.class !=
+			&sas_host_class.class)
+		return 0;
+
+	i = to_sas_internal(shost->transportt);
+	return &i->phy_attr_cont.ac == cont;
+}
+
+static void sas_phy_release(struct device *dev)
+{
+	struct sas_phy *phy = dev_to_phy(dev);
+
+	put_device(dev->parent);
+	kfree(phy);
+}
+
+/**
+ * sas_phy_alloc  --  allocates and initialize a SAS PHY structure
+ * @parent:	Parent device
+ * @number:	Port number
+ *
+ * Allocates an SAS PHY structure.  It will be added in the device tree
+ * below the device specified by @parent, which has to be either a Scsi_Host
+ * or sas_rphy.
+ *
+ * Returns:
+ *	SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_phy *sas_phy_alloc(struct device *parent, int number)
+{
+	struct Scsi_Host *shost = dev_to_shost(parent);
+	struct sas_phy *phy;
+
+	phy = kmalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return NULL;
+	memset(phy, 0, sizeof(*phy));
+
+	get_device(parent);
+
+	phy->number = number;
+
+	device_initialize(&phy->dev);
+	phy->dev.parent = get_device(parent);
+	phy->dev.release = sas_phy_release;
+	sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
+
+	transport_setup_device(&phy->dev);
+
+	return phy;
+}
+EXPORT_SYMBOL(sas_phy_alloc);
+
+/**
+ * sas_phy_add  --  add a SAS PHY to the device hierachy
+ * @phy:	The PHY to be added
+ *
+ * Publishes a SAS PHY to the rest of the system.
+ */
+int sas_phy_add(struct sas_phy *phy)
+{
+	int error;
+
+	error = device_add(&phy->dev);
+	if (!error) {
+		transport_add_device(&phy->dev);
+		transport_configure_device(&phy->dev);
+	}
+
+	return error;
+}
+EXPORT_SYMBOL(sas_phy_add);
+
+/**
+ * sas_phy_free  --  free a SAS PHY
+ * @phy:	SAS PHY to free
+ *
+ * Frees the specified SAS PHY.
+ *
+ * Note:
+ *   This function must only be called on a PHY that has not
+ *   sucessfully been added using sas_phy_add().
+ */
+void sas_phy_free(struct sas_phy *phy)
+{
+	transport_destroy_device(&phy->dev);
+	put_device(phy->dev.parent);
+	put_device(phy->dev.parent);
+	put_device(phy->dev.parent);
+	kfree(phy);
+}
+EXPORT_SYMBOL(sas_phy_free);
+
+/**
+ * sas_phy_delete  --  remove SAS PHY
+ * @phy:	SAS PHY to remove
+ *
+ * Removes the specified SAS PHY.  If the SAS PHY has an
+ * associated remote PHY it is removed before.
+ */
+void
+sas_phy_delete(struct sas_phy *phy)
+{
+	struct device *dev = &phy->dev;
+
+	if (phy->rphy)
+		sas_rphy_delete(phy->rphy);
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(dev->parent);
+}
+EXPORT_SYMBOL(sas_phy_delete);
+
+/**
+ * scsi_is_sas_phy  --  check if a struct device represents a SAS PHY
+ * @dev:	device to check
+ *
+ * Returns:
+ *	%1 if the device represents a SAS PHY, %0 else
+ */
+int scsi_is_sas_phy(const struct device *dev)
+{
+	return dev->release == sas_phy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_phy);
+
+/*
+ * SAS remote PHY attributes.
+ */
+
+#define sas_rphy_show_simple(field, name, format_string, cast)		\
+static ssize_t								\
+show_sas_rphy_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_rphy *rphy = transport_class_to_rphy(cdev);	\
+									\
+	return snprintf(buf, 20, format_string, cast rphy->field);	\
+}
+
+#define sas_rphy_simple_attr(field, name, format_string, type)		\
+	sas_rphy_show_simple(field, name, format_string, (type))	\
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, 			\
+		show_sas_rphy_##name, NULL)
+
+#define sas_rphy_show_protocol(field, name)				\
+static ssize_t								\
+show_sas_rphy_##name(struct class_device *cdev, char *buf)		\
+{									\
+	struct sas_rphy *rphy = transport_class_to_rphy(cdev);	\
+									\
+	if (!rphy->field)					\
+		return snprintf(buf, 20, "none\n");			\
+	return get_sas_protocol_names(rphy->field, buf);	\
+}
+
+#define sas_rphy_protocol_attr(field, name)				\
+	sas_rphy_show_protocol(field, name)				\
+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO,			\
+		show_sas_rphy_##name, NULL)
+
+static ssize_t
+show_sas_rphy_device_type(struct class_device *cdev, char *buf)
+{
+	struct sas_rphy *rphy = transport_class_to_rphy(cdev);
+
+	if (!rphy->identify.device_type)
+		return snprintf(buf, 20, "none\n");
+	return get_sas_device_type_names(
+			rphy->identify.device_type, buf);
+}
+
+static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
+		show_sas_rphy_device_type, NULL);
+
+sas_rphy_protocol_attr(identify.initiator_port_protocols,
+		initiator_port_protocols);
+sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
+sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
+		unsigned long long);
+sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
+
+static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
+		"sas_rphy", NULL, NULL, NULL);
+
+static int sas_rphy_match(struct attribute_container *cont, struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct sas_internal *i;
+
+	if (!scsi_is_sas_rphy(dev))
+		return 0;
+	shost = dev_to_shost(dev->parent->parent);
+
+	if (!shost->transportt)
+		return 0;
+	if (shost->transportt->host_attrs.ac.class !=
+			&sas_host_class.class)
+		return 0;
+
+	i = to_sas_internal(shost->transportt);
+	return &i->rphy_attr_cont.ac == cont;
+}
+
+static void sas_rphy_release(struct device *dev)
+{
+	struct sas_rphy *rphy = dev_to_rphy(dev);
+
+	put_device(dev->parent);
+	kfree(rphy);
+}
+
+/**
+ * sas_rphy_alloc  --  allocates and initialize a SAS remote PHY structure
+ * @parent:		SAS PHY this remote PHY is conneted to
+ *
+ * Allocates an SAS remote PHY structure, connected to @parent.
+ *
+ * Returns:
+ *	SAS PHY allocated or %NULL if the allocation failed.
+ */
+struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent)
+{
+	struct Scsi_Host *shost = dev_to_shost(&parent->dev);
+	struct sas_rphy *rphy;
+
+	rphy = kmalloc(sizeof(*rphy), GFP_KERNEL);
+	if (!rphy) {
+		put_device(&parent->dev);
+		return NULL;
+	}
+	memset(rphy, 0, sizeof(*rphy));
+
+	device_initialize(&rphy->dev);
+	rphy->dev.parent = get_device(&parent->dev);
+	rphy->dev.release = sas_rphy_release;
+	sprintf(rphy->dev.bus_id, "rphy-%d:%d",
+		shost->host_no, parent->number);
+	transport_setup_device(&rphy->dev);
+
+	return rphy;
+}
+EXPORT_SYMBOL(sas_rphy_alloc);
+
+/**
+ * sas_rphy_add  --  add a SAS remote PHY to the device hierachy
+ * @rphy:	The remote PHY to be added
+ *
+ * Publishes a SAS remote PHY to the rest of the system.
+ */
+int sas_rphy_add(struct sas_rphy *rphy)
+{
+	struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+	struct sas_identify *identify = &rphy->identify;
+	int error;
+
+	if (parent->rphy)
+		return -ENXIO;
+	parent->rphy = rphy;
+
+	error = device_add(&rphy->dev);
+	if (error)
+		return error;
+	transport_add_device(&rphy->dev);
+	transport_configure_device(&rphy->dev);
+
+	spin_lock(&sas_host->lock);
+	list_add_tail(&rphy->list, &sas_host->rphy_list);
+	if (identify->device_type == SAS_END_DEVICE &&
+	    (identify->target_port_protocols &
+	     (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
+		rphy->scsi_target_id = sas_host->next_target_id++;
+	else
+		rphy->scsi_target_id = -1;
+	spin_unlock(&sas_host->lock);
+
+	if (rphy->scsi_target_id != -1) {
+		scsi_scan_target(&rphy->dev, parent->number,
+				rphy->scsi_target_id, ~0, 0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sas_rphy_add);
+
+/**
+ * sas_rphy_free  --  free a SAS remote PHY
+ * @rphy	SAS remote PHY to free
+ *
+ * Frees the specified SAS remote PHY.
+ *
+ * Note:
+ *   This function must only be called on a remote
+ *   PHY that has not sucessfully been added using
+ *   sas_rphy_add().
+ */
+void sas_rphy_free(struct sas_rphy *rphy)
+{
+	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+	spin_lock(&sas_host->lock);
+	list_del(&rphy->list);
+	spin_unlock(&sas_host->lock);
+
+	transport_destroy_device(&rphy->dev);
+	put_device(rphy->dev.parent);
+	put_device(rphy->dev.parent);
+	put_device(rphy->dev.parent);
+	kfree(rphy);
+}
+EXPORT_SYMBOL(sas_rphy_free);
+
+/**
+ * sas_rphy_delete  --  remove SAS remote PHY
+ * @rphy:	SAS remote PHY to remove
+ *
+ * Removes the specified SAS remote PHY.
+ */
+void
+sas_rphy_delete(struct sas_rphy *rphy)
+{
+	struct device *dev = &rphy->dev;
+	struct sas_phy *parent = dev_to_phy(dev->parent);
+	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
+	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+
+	transport_destroy_device(&rphy->dev);
+
+	scsi_remove_target(&rphy->dev);
+
+	spin_lock(&sas_host->lock);
+	list_del(&rphy->list);
+	spin_unlock(&sas_host->lock);
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(&parent->dev);
+}
+EXPORT_SYMBOL(sas_rphy_delete);
+
+/**
+ * scsi_is_sas_rphy  --  check if a struct device represents a SAS remote PHY
+ * @dev:	device to check
+ *
+ * Returns:
+ *	%1 if the device represents a SAS remote PHY, %0 else
+ */
+int scsi_is_sas_rphy(const struct device *dev)
+{
+	return dev->release == sas_rphy_release;
+}
+EXPORT_SYMBOL(scsi_is_sas_rphy);
+
+
+/*
+ * SCSI scan helper
+ */
+
+static struct device *sas_target_parent(struct Scsi_Host *shost,
+					int channel, uint id)
+{
+	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
+	struct sas_rphy *rphy;
+	struct device *dev = NULL;
+
+	spin_lock(&sas_host->lock);
+	list_for_each_entry(rphy, &sas_host->rphy_list, list) {
+		struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
+		if (parent->number == channel &&
+		    rphy->scsi_target_id == id)
+			dev = &rphy->dev;
+	}
+	spin_unlock(&sas_host->lock);
+
+	return dev;
+}
+
+
+/*
+ * Setup / Teardown code
+ */
+
+#define SETUP_RPORT_ATTRIBUTE(field)					\
+	i->private_rphy_attrs[count] = class_device_attr_##field;	\
+	i->private_rphy_attrs[count].attr.mode = S_IRUGO;		\
+	i->private_rphy_attrs[count].store = NULL;			\
+	i->rphy_attrs[count] = &i->private_rphy_attrs[count];	\
+	count++
+
+#define SETUP_PORT_ATTRIBUTE(field)					\
+	i->private_phy_attrs[count] = class_device_attr_##field;	\
+        i->private_phy_attrs[count].attr.mode = S_IRUGO;		\
+        i->private_phy_attrs[count].store = NULL;			\
+        i->phy_attrs[count] = &i->private_phy_attrs[count];		\
+	count++
+
+
+/**
+ * sas_attach_transport  --  instantiate SAS transport template
+ * @ft:		SAS transport class function template
+ */
+struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *ft)
+{
+	struct sas_internal *i;
+	int count;
+
+	i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL);
+	if (!i)
+		return NULL;
+	memset(i, 0, sizeof(struct sas_internal));
+
+	i->t.target_parent = sas_target_parent;
+
+	i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+	i->t.host_attrs.ac.class = &sas_host_class.class;
+	i->t.host_attrs.ac.match = sas_host_match;
+	transport_container_register(&i->t.host_attrs);
+	i->t.host_size = sizeof(struct sas_host_attrs);
+
+	i->phy_attr_cont.ac.class = &sas_phy_class.class;
+	i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
+	i->phy_attr_cont.ac.match = sas_phy_match;
+	transport_container_register(&i->phy_attr_cont);
+
+	i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
+	i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
+	i->rphy_attr_cont.ac.match = sas_rphy_match;
+	transport_container_register(&i->rphy_attr_cont);
+
+	i->f = ft;
+
+	count = 0;
+	i->host_attrs[count] = NULL;
+
+	count = 0;
+	SETUP_PORT_ATTRIBUTE(initiator_port_protocols);
+	SETUP_PORT_ATTRIBUTE(target_port_protocols);
+	SETUP_PORT_ATTRIBUTE(device_type);
+	SETUP_PORT_ATTRIBUTE(sas_address);
+	SETUP_PORT_ATTRIBUTE(phy_identifier);
+	SETUP_PORT_ATTRIBUTE(port_identifier);
+	SETUP_PORT_ATTRIBUTE(negotiated_linkrate);
+	SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);
+	SETUP_PORT_ATTRIBUTE(minimum_linkrate);
+	SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);
+	SETUP_PORT_ATTRIBUTE(maximum_linkrate);
+	i->phy_attrs[count] = NULL;
+
+	count = 0;
+	SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
+	SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
+	SETUP_RPORT_ATTRIBUTE(rphy_device_type);
+	SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
+	SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
+	i->rphy_attrs[count] = NULL;
+
+	return &i->t;
+}
+EXPORT_SYMBOL(sas_attach_transport);
+
+/**
+ * sas_release_transport  --  release SAS transport template instance
+ * @t:		transport template instance
+ */
+void sas_release_transport(struct scsi_transport_template *t)
+{
+	struct sas_internal *i = to_sas_internal(t);
+
+	transport_container_unregister(&i->t.host_attrs);
+	transport_container_unregister(&i->phy_attr_cont);
+	transport_container_unregister(&i->rphy_attr_cont);
+
+	kfree(i);
+}
+EXPORT_SYMBOL(sas_release_transport);
+
+static __init int sas_transport_init(void)
+{
+	int error;
+
+	error = transport_class_register(&sas_host_class);
+	if (error)
+		goto out;
+	error = transport_class_register(&sas_phy_class);
+	if (error)
+		goto out_unregister_transport;
+	error = transport_class_register(&sas_rphy_class);
+	if (error)
+		goto out_unregister_phy;
+
+	return 0;
+
+ out_unregister_phy:
+	transport_class_unregister(&sas_phy_class);
+ out_unregister_transport:
+	transport_class_unregister(&sas_host_class);
+ out:
+	return error;
+
+}
+
+static void __exit sas_transport_exit(void)
+{
+	transport_class_unregister(&sas_host_class);
+	transport_class_unregister(&sas_phy_class);
+	transport_class_unregister(&sas_rphy_class);
+}
+
+MODULE_AUTHOR("Christoph Hellwig");
+MODULE_DESCRIPTION("SAS Transphy Attributes");
+MODULE_LICENSE("GPL");
+
+module_init(sas_transport_init);
+module_exit(sas_transport_exit);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b1b69d7..9ea4765 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -61,7 +61,7 @@
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20050901";
+static char *sg_version_date = "20050908";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -1299,7 +1299,7 @@
 		sg_rb_correct4mmap(rsv_schp, 1);	/* do only once per fd lifetime */
 		sfp->mmap_called = 1;
 	}
-	vma->vm_flags |= (VM_RESERVED | VM_IO);
+	vma->vm_flags |= VM_RESERVED;
 	vma->vm_private_data = sfp;
 	vma->vm_ops = &sg_mmap_vm_ops;
 	return 0;
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 43b03c5..e2ebdca 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -63,8 +63,13 @@
 #endif
 
 #if defined(CONFIG_HW_FEITH)
-  #define	CONSOLE_BAUD_RATE	38400
-  #define	DEFAULT_CBAUD		B38400
+#define	CONSOLE_BAUD_RATE	38400
+#define	DEFAULT_CBAUD		B38400
+#endif
+
+#if defined(CONFIG_MOD5272)
+#define CONSOLE_BAUD_RATE 	115200
+#define DEFAULT_CBAUD		B115200
 #endif
 
 #ifndef CONSOLE_BAUD_RATE
@@ -90,7 +95,7 @@
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define	IRQBASE	(MCFINT_VECBASE+MCFINT_UART0)
 #else
 #define	IRQBASE	73
@@ -1510,7 +1515,7 @@
 	*portp = (*portp & ~0x000000ff) | 0x00000055;
 	portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
 	*portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 	volatile unsigned char *icrp, *uartp;
 	volatile unsigned long *imrp;
 
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 4382ee6..6bed871 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1683,7 +1683,7 @@
 #ifndef CONFIG_SERIAL_DEC_CONSOLE
 			/*
 			 * We're called early and memory managment isn't up, yet.
-			 * Thus check_region would fail.
+			 * Thus request_region would fail.
 			 */
 			if (!request_region((unsigned long)
 					 zs_channels[n_channels].control,
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index f8f2156..5085827 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -631,8 +631,10 @@
 	i = u->flags;
 	spin_unlock_irqrestore(&as->lock, flags);
 	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
+		if (notkilled)
+			schedule_timeout_interruptible(1);
+		else
+			schedule_timeout_uninterruptible(1);
 		spin_lock_irqsave(&as->lock, flags);
 		i = u->flags;
 		spin_unlock_irqrestore(&as->lock, flags);
@@ -1102,8 +1104,10 @@
 	i = u->flags;
 	spin_unlock_irqrestore(&as->lock, flags);
 	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
+		if (notkilled)
+			schedule_timeout_interruptible(1);
+		else
+			schedule_timeout_uninterruptible(1);
 		spin_lock_irqsave(&as->lock, flags);
 		i = u->flags;
 		spin_unlock_irqrestore(&as->lock, flags);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12ecdb0..1017a97 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1606,7 +1606,7 @@
 		return IRQ_NONE;
 
 	hcd->saw_irq = 1;
-	if (hcd->state != start && hcd->state == HC_STATE_HALT)
+	if (hcd->state == HC_STATE_HALT)
 		usb_hc_died (hcd);
 	return IRQ_HANDLED;
 }
@@ -1630,7 +1630,6 @@
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
 	if (hcd->rh_registered) {
 		hcd->poll_rh = 0;
-		del_timer(&hcd->rh_timer);
 
 		/* make khubd clean up old urbs and devices */
 		usb_set_device_state (hcd->self.root_hub,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 758c7f0..a12cab5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -435,6 +435,7 @@
 static void hub_power_on(struct usb_hub *hub)
 {
 	int port1;
+	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
 
 	/* if hub supports power switching, enable power on each port */
 	if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
@@ -444,8 +445,8 @@
 					USB_PORT_FEAT_POWER);
 	}
 
-	/* Wait for power to be enabled */
-	msleep(hub->descriptor->bPwrOn2PwrGood * 2);
+	/* Wait at least 100 msec for power to become stable */
+	msleep(max(pgood_delay, (unsigned) 100));
 }
 
 static void hub_quiesce(struct usb_hub *hub)
@@ -1460,7 +1461,7 @@
 					port1, status);
 		else {
 			status = hub_port_wait_reset(hub, port1, udev, delay);
-			if (status)
+			if (status && status != -ENOTCONN)
 				dev_dbg(hub->intfdev,
 						"port_wait_reset: err = %d\n",
 						status);
@@ -1469,8 +1470,8 @@
 		/* return on disconnect or reset */
 		switch (status) {
 		case 0:
-			/* TRSTRCY = 10 ms */
-			msleep(10);
+			/* TRSTRCY = 10 ms; plus some extra */
+			msleep(10 + 40);
 			/* FALL THROUGH */
 		case -ENOTCONN:
 		case -ENODEV:
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 0208153..5c40980 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -483,6 +483,7 @@
 		data->state = STATE_EP_DISABLED;
 		data->desc.bDescriptorType = 0;
 		data->hs_desc.bDescriptorType = 0;
+		usb_ep_disable(data->ep);
 	}
 	put_ep (data);
 	return 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 2507e89..b948ffd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -400,6 +400,23 @@
 				return -EIO;
 			}
 			break;
+		case PCI_VENDOR_ID_NVIDIA:
+			/* NVidia reports that certain chips don't handle
+			 * QH, ITD, or SITD addresses above 2GB.  (But TD,
+			 * data buffer, and periodic schedule are normal.)
+			 */
+			switch (pdev->device) {
+			case 0x003c:	/* MCP04 */
+			case 0x005b:	/* CK804 */
+			case 0x00d8:	/* CK8 */
+			case 0x00e8:	/* CK8S */
+				if (pci_set_consistent_dma_mask(pdev,
+							DMA_31BIT_MASK) < 0)
+					ehci_warn (ehci, "can't enable NVidia "
+						"workaround for >2GB RAM\n");
+				break;
+			}
+			break;
 		}
 
 		/* optional debug port, normally in the first BAR */
@@ -759,12 +776,16 @@
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep (100);
 
-	/* If any port is suspended, we know we can/must resume the HC. */
+	/* If any port is suspended (or owned by the companion),
+	 * we know we can/must resume the HC (and mustn't reset it).
+	 */
 	for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
 		u32	status;
 		port--;
 		status = readl (&ehci->regs->port_status [port]);
-		if (status & PORT_SUSPEND) {
+		if (!(status & PORT_POWER))
+			continue;
+		if (status & (PORT_SUSPEND | PORT_OWNER)) {
 			down (&hcd->self.root_hub->serialize);
 			retval = ehci_hub_resume (hcd);
 			up (&hcd->self.root_hub->serialize);
@@ -1126,8 +1147,7 @@
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
 idle_timeout:
 		spin_unlock_irqrestore (&ehci->lock, flags);
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (1);
+		schedule_timeout_uninterruptible(1);
 		goto rescan;
 	case QH_STATE_IDLE:		/* fully unlinked */
 		if (list_empty (&qh->qtd_list)) {
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 36cc1f2..18d3f22 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -54,7 +54,7 @@
 	/* suspend any active/unsuspended ports, maybe allow wakeup */
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
-		u32		t1 = readl (reg);
+		u32		t1 = readl (reg) & ~PORT_RWC_BITS;
 		u32		t2 = t1;
 
 		if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
@@ -115,7 +115,8 @@
 	i = HCS_N_PORTS (ehci->hcs_params);
 	while (i--) {
 		temp = readl (&ehci->regs->port_status [i]);
-		temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
+		temp &= ~(PORT_RWC_BITS
+			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
 		if (temp & PORT_SUSPEND) {
 			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
 			temp |= PORT_RESUME;
@@ -128,7 +129,7 @@
 		temp = readl (&ehci->regs->port_status [i]);
 		if ((temp & PORT_SUSPEND) == 0)
 			continue;
-		temp &= ~PORT_RESUME;
+		temp &= ~(PORT_RWC_BITS | PORT_RESUME);
 		writel (temp, &ehci->regs->port_status [i]);
 		ehci_vdbg (ehci, "resumed port %d\n", i + 1);
 	}
@@ -191,6 +192,7 @@
 
 		// what happens if HCS_N_CC(params) == 0 ?
 		port_status |= PORT_OWNER;
+		port_status &= ~PORT_RWC_BITS;
 		writel (port_status, &ehci->regs->port_status [index]);
 
 	} else
@@ -233,7 +235,8 @@
 		if (temp & PORT_OWNER) {
 			/* don't report this in GetPortStatus */
 			if (temp & PORT_CSC) {
-				temp &= ~PORT_CSC;
+				temp &= ~PORT_RWC_BITS;
+				temp |= PORT_CSC;
 				writel (temp, &ehci->regs->port_status [i]);
 			}
 			continue;
@@ -343,7 +346,7 @@
 				&ehci->regs->port_status [wIndex]);
 			break;
 		case USB_PORT_FEAT_C_ENABLE:
-			writel (temp | PORT_PEC,
+			writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
 				&ehci->regs->port_status [wIndex]);
 			break;
 		case USB_PORT_FEAT_SUSPEND:
@@ -353,7 +356,8 @@
 				if ((temp & PORT_PE) == 0)
 					goto error;
 				/* resume signaling for 20 msec */
-				writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
+				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+				writel (temp | PORT_RESUME,
 					&ehci->regs->port_status [wIndex]);
 				ehci->reset_done [wIndex] = jiffies
 						+ msecs_to_jiffies (20);
@@ -364,15 +368,15 @@
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (HCS_PPC (ehci->hcs_params))
-				writel (temp & ~PORT_POWER,
+				writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
 					&ehci->regs->port_status [wIndex]);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			writel (temp | PORT_CSC,
+			writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
 				&ehci->regs->port_status [wIndex]);
 			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
-			writel (temp | PORT_OCC,
+			writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
 				&ehci->regs->port_status [wIndex]);
 			break;
 		case USB_PORT_FEAT_C_RESET:
@@ -416,7 +420,7 @@
 
 			/* stop resume signaling */
 			temp = readl (&ehci->regs->port_status [wIndex]);
-			writel (temp & ~PORT_RESUME,
+			writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
 				&ehci->regs->port_status [wIndex]);
 			retval = handshake (
 					&ehci->regs->port_status [wIndex],
@@ -437,7 +441,7 @@
 			ehci->reset_done [wIndex] = 0;
 
 			/* force reset to complete */
-			writel (temp & ~PORT_RESET,
+			writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
 					&ehci->regs->port_status [wIndex]);
 			/* REVISIT:  some hardware needs 550+ usec to clear
 			 * this bit; seems too long to spin routinely...
@@ -500,6 +504,7 @@
 		if (temp & PORT_OWNER)
 			break;
 
+		temp &= ~PORT_RWC_BITS;
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
 			if ((temp & PORT_PE) == 0
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 20c9b55..f34a051 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -263,6 +263,7 @@
 #define PORT_PE		(1<<2)		/* port enable */
 #define PORT_CSC	(1<<1)		/* connect status change */
 #define PORT_CONNECT	(1<<0)		/* device connected */
+#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
 } __attribute__ ((packed));
 
 /* Appendix C, Debug port ... intended for use with special "debug devices"
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 447f488..7924c74 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -228,23 +228,22 @@
 	char **next,
 	unsigned *size)
 {
-	u32			temp, ndp, i;
+	u32			temp, i;
 
 	temp = roothub_a (controller);
 	if (temp == ~(u32)0)
 		return;
-	ndp = (temp & RH_A_NDP);
 
 	if (verbose) {
 		ohci_dbg_sw (controller, next, size,
-			"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+			"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
 			((temp & RH_A_POTPGT) >> 24) & 0xff,
 			(temp & RH_A_NOCP) ? " NOCP" : "",
 			(temp & RH_A_OCPM) ? " OCPM" : "",
 			(temp & RH_A_DT) ? " DT" : "",
 			(temp & RH_A_NPS) ? " NPS" : "",
 			(temp & RH_A_PSM) ? " PSM" : "",
-			ndp
+			(temp & RH_A_NDP), controller->num_ports
 			);
 		temp = roothub_b (controller);
 		ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@
 			);
 	}
 
-	for (i = 0; i < ndp; i++) {
+	for (i = 0; i < controller->num_ports; i++) {
 		temp = roothub_portstatus (controller, i);
 		dbg_port_sw (controller, i, temp, next, size);
 	}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 56b43f2..67c1aa5 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -382,8 +382,7 @@
 			goto sanitize;
 		}
 		spin_unlock_irqrestore (&ohci->lock, flags);
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (1);
+		schedule_timeout_uninterruptible(1);
 		goto rescan;
 	case ED_IDLE:		/* fully unlinked */
 		if (list_empty (&ed->td_list)) {
@@ -485,6 +484,10 @@
 	// flush the writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 
+	/* Read the number of ports unless overridden */
+	if (ohci->num_ports == 0)
+		ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
 	if (ohci->hcca)
 		return 0;
 
@@ -561,10 +564,8 @@
 	msleep(temp);
 	temp = roothub_a (ohci);
 	if (!(temp & RH_A_NPS)) {
-		unsigned ports = temp & RH_A_NDP; 
-
 		/* power down each port */
-		for (temp = 0; temp < ports; temp++)
+		for (temp = 0; temp < ohci->num_ports; temp++)
 			ohci_writel (ohci, RH_PS_LSDA,
 				&ohci->regs->roothub.portstatus [temp]);
 	}
@@ -720,6 +721,7 @@
 
 	if (ints & OHCI_INTR_RD) {
 		ohci_vdbg (ohci, "resume detect\n");
+		ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
 		if (hcd->state != HC_STATE_QUIESCING)
 			schedule_work(&ohci->rh_resume);
 	}
@@ -861,7 +863,7 @@
 		 * and that if we try to turn them back on the root hub
 		 * will respond to CSC processing.
 		 */
-		i = roothub_a (ohci) & RH_A_NDP;
+		i = ohci->num_ports;
 		while (i--)
 			ohci_writel (ohci, RH_PS_PSS,
 				&ohci->regs->roothub.portstatus [temp]);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 83ca454..ce7b28d 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -184,7 +184,7 @@
 	if (status != -EINPROGRESS)
 		return status;
 
-	temp = roothub_a (ohci) & RH_A_NDP;
+	temp = ohci->num_ports;
 	enables = 0;
 	while (temp--) {
 		u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@
 ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports, i, changed = 0, length = 1;
+	int		i, changed = 0, length = 1;
 	int		can_suspend = hcd->can_wakeup;
 	unsigned long	flags;
 
@@ -319,9 +319,10 @@
 		goto done;
 	}
 
-	ports = roothub_a (ohci) & RH_A_NDP; 
-	if (ports > MAX_ROOT_PORTS) {
-		ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+	/* undocumented erratum seen on at least rev D */
+	if ((ohci->flags & OHCI_QUIRK_AMD756)
+			&& (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+		ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
 			  ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
 		/* retry later; "should not happen" */
 		goto done;
@@ -332,13 +333,13 @@
 		buf [0] = changed = 1;
 	else
 		buf [0] = 0;
-	if (ports > 7) {
+	if (ohci->num_ports > 7) {
 		buf [1] = 0;
 		length++;
 	}
 
 	/* look at each port */
-	for (i = 0; i < ports; i++) {
+	for (i = 0; i < ohci->num_ports; i++) {
 		u32	status = roothub_portstatus (ohci, i);
 
 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@
 	struct usb_hub_descriptor	*desc
 ) {
 	u32		rh = roothub_a (ohci);
-	int		ports = rh & RH_A_NDP; 
 	u16		temp;
 
 	desc->bDescriptorType = 0x29;
 	desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
 	desc->bHubContrCurrent = 0;
 
-	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
+	desc->bNbrPorts = ohci->num_ports;
+	temp = 1 + (ohci->num_ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
 	temp = 0;
@@ -421,7 +421,7 @@
 	rh = roothub_b (ohci);
 	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
 	desc->bitmap [0] = rh & RH_B_DR;
-	if (ports > 7) {
+	if (ohci->num_ports > 7) {
 		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
 		desc->bitmap [2] = 0xff;
 	} else
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e5bc178..2fdb262 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -75,33 +75,6 @@
 	return 0;
 }
 
-/*
-  If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_set_port_power( int port )
-{
-	if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE)
-	     && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
-		UHCRHPS(port) |= 0x100;
-		return 0;
-	}
-	return -1;
-}
-
-/*
-  If you select PMM_PERPORT_MODE, you should set the port power
- */
-static int pxa27x_ohci_clear_port_power( int port )
-{
-	if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) 
-	     && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) {
-		UHCRHPS(port) |= 0x200;
-		return 0;
-	}
-	 
-	return -1;
-}
-
 extern int usb_disabled(void);
 
 /*-------------------------------------------------------------------------*/
@@ -130,11 +103,17 @@
 		   Polarity Low to active low. Supply power to USB ports. */
 		UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
 			~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+		pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
 	}
 
 	UHCHR &= ~UHCHR_SSE;
 
 	UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE);
+
+	/* Clear any OTG Pin Hold */
+	if (PSSR & PSSR_OTGPH)
+		PSSR |= PSSR_OTGPH;
 }
 
 static void pxa27x_stop_hc(struct platform_device *dev)
@@ -198,17 +177,7 @@
 	pxa27x_start_hc(dev);
 
 	/* Select Power Management Mode */
-	pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );
-
-	/* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
-	if (pxa27x_ohci_set_port_power(1) < 0)
-		printk(KERN_ERR "Setting port 1 power failed.\n");
-
-	if (pxa27x_ohci_clear_port_power(2) < 0)
-		printk(KERN_ERR "Setting port 2 power failed.\n");
-
-	if (pxa27x_ohci_clear_port_power(3) < 0)
-		printk(KERN_ERR "Setting port 3 power failed.\n");
+	pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
@@ -258,6 +227,9 @@
 
 	ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
 
+	/* The value of NDP in roothub_a is incorrect on this hardware */
+	ohci->num_ports = 3;
+
 	if ((ret = ohci_init(ohci)) < 0)
 		return ret;
 
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 71cdd22..8a9b9d9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -383,6 +383,7 @@
 	/*
 	 * driver state
 	 */
+	int			num_ports;
 	int			load [NUM_INTS];
 	u32 			hc_control;	/* copy of hc control reg */
 	unsigned long		next_statechange;	/* suspend/resume */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 0d5d254..0c02489 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -97,14 +97,9 @@
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
-static inline void restart_timer(struct uhci_hcd *uhci)
-{
-	mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100));
-}
-
-#include "uhci-hub.c"
 #include "uhci-debug.c"
 #include "uhci-q.c"
+#include "uhci-hub.c"
 
 /*
  * Make sure the controller is completely inactive, unable to
@@ -160,7 +155,6 @@
 {
 	reset_hc(uhci);
 	uhci->hc_inaccessible = 1;
-	del_timer(&uhci->stall_timer);
 }
 
 /*
@@ -287,8 +281,11 @@
 	/* Enable resume-detect interrupts if they work.
 	 * Then enter Global Suspend mode, still configured.
 	 */
-	int_enable = (resume_detect_interrupts_are_broken(uhci) ?
-			0 : USBINTR_RESUME);
+	uhci->working_RD = 1;
+	int_enable = USBINTR_RESUME;
+	if (resume_detect_interrupts_are_broken(uhci)) {
+		uhci->working_RD = int_enable = 0;
+	}
 	outw(int_enable, uhci->io_addr + USBINTR);
 	outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
 	mb();
@@ -315,7 +312,6 @@
 
 	uhci->rh_state = new_state;
 	uhci->is_stopped = UHCI_IS_STOPPED;
-	del_timer(&uhci->stall_timer);
 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
 	uhci_scan_schedule(uhci, NULL);
@@ -335,7 +331,6 @@
 	mb();
 	uhci->rh_state = UHCI_RH_RUNNING;
 	uhci_to_hcd(uhci)->poll_rh = 1;
-	restart_timer(uhci);
 }
 
 static void wakeup_rh(struct uhci_hcd *uhci)
@@ -374,20 +369,6 @@
 	mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
-static void stall_callback(unsigned long _uhci)
-{
-	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->lock, flags);
-	uhci_scan_schedule(uhci, NULL);
-	check_fsbr(uhci);
-
-	if (!uhci->is_stopped)
-		restart_timer(uhci);
-	spin_unlock_irqrestore(&uhci->lock, flags);
-}
-
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -418,8 +399,10 @@
 					"host controller halted, "
 					"very bad!\n");
 				hc_died(uhci);
-				spin_unlock_irqrestore(&uhci->lock, flags);
-				return IRQ_HANDLED;
+
+				/* Force a callback in case there are
+				 * pending unlinks */
+				mod_timer(&hcd->rh_timer, jiffies);
 			}
 			spin_unlock_irqrestore(&uhci->lock, flags);
 		}
@@ -427,10 +410,11 @@
 
 	if (status & USBSTS_RD)
 		usb_hcd_poll_rh_status(hcd);
-
-	spin_lock_irqsave(&uhci->lock, flags);
-	uhci_scan_schedule(uhci, regs);
-	spin_unlock_irqrestore(&uhci->lock, flags);
+	else {
+		spin_lock_irqsave(&uhci->lock, flags);
+		uhci_scan_schedule(uhci, regs);
+		spin_unlock_irqrestore(&uhci->lock, flags);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -595,10 +579,6 @@
 
 	init_waitqueue_head(&uhci->waitqh);
 
-	init_timer(&uhci->stall_timer);
-	uhci->stall_timer.function = stall_callback;
-	uhci->stall_timer.data = (unsigned long) uhci;
-
 	uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
 			&dma_handle, 0);
 	if (!uhci->fl) {
@@ -745,11 +725,11 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	spin_lock_irq(&uhci->lock);
-	reset_hc(uhci);
+	if (!uhci->hc_inaccessible)
+		reset_hc(uhci);
 	uhci_scan_schedule(uhci, NULL);
 	spin_unlock_irq(&uhci->lock);
 
-	del_timer_sync(&uhci->stall_timer);
 	release_uhci(uhci);
 }
 
@@ -811,13 +791,12 @@
 	 */
 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
 	uhci->hc_inaccessible = 1;
+	hcd->poll_rh = 0;
 
 	/* FIXME: Enable non-PME# remote wakeup? */
 
 done:
 	spin_unlock_irq(&uhci->lock);
-	if (rc == 0)
-		del_timer_sync(&hcd->rh_timer);
 	return rc;
 }
 
@@ -850,8 +829,11 @@
 
 	spin_unlock_irq(&uhci->lock);
 
-	if (hcd->poll_rh)
+	if (!uhci->working_RD) {
+		/* Suspended root hub needs to be polled */
+		hcd->poll_rh = 1;
 		usb_hcd_poll_rh_status(hcd);
+	}
 	return 0;
 }
 #endif
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index bf9c5f9..282f40b 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -345,9 +345,6 @@
 
 /*
  * This describes the full uhci information.
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs.
  */
 struct uhci_hcd {
 
@@ -360,8 +357,6 @@
 	struct dma_pool *qh_pool;
 	struct dma_pool *td_pool;
 
-	struct usb_bus *bus;
-
 	struct uhci_td *term_td;	/* Terminating TD, see UHCI bug */
 	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
@@ -380,6 +375,8 @@
 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
 	unsigned int need_rescan:1;		/* Redo the schedule scan */
 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
+	unsigned int working_RD:1;		/* Suspended root hub doesn't
+						   need to be polled */
 
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
@@ -405,9 +402,7 @@
 	/* List of URB's awaiting completion callback */
 	struct list_head complete_list;		/* P: uhci->lock */
 
-	int rh_numports;
-
-	struct timer_list stall_timer;
+	int rh_numports;			/* Number of root-hub ports */
 
 	wait_queue_head_t waitqh;		/* endpoint_disable waiters */
 };
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 4eace2b..a71e48a 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -145,15 +145,16 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
-	int status;
+	int status = 0;
 
 	spin_lock_irqsave(&uhci->lock, flags);
-	if (uhci->hc_inaccessible) {
-		status = 0;
-		goto done;
-	}
 
+	uhci_scan_schedule(uhci, NULL);
+	if (uhci->hc_inaccessible)
+		goto done;
+	check_fsbr(uhci);
 	uhci_check_ports(uhci);
+
 	status = get_hub_status_data(uhci, buf);
 
 	switch (uhci->rh_state) {
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index bbb36cd..ea0d168 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -33,7 +33,7 @@
 static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
 {
 	if (uhci->is_stopped)
-		mod_timer(&uhci->stall_timer, jiffies);
+		mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
 }
 
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 482c4be..1e53934 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -286,3 +286,23 @@
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called keyspan_remote.
+
+config USB_APPLETOUCH
+	tristate "Apple USB Touchpad support"
+	depends on USB && INPUT
+	---help---
+	  Say Y here if you want to use an Apple USB Touchpad.
+
+	  These are the touchpads that can be found on post-February 2005
+	  Apple Powerbooks (prior models have a Synaptics touchpad connected
+	  to the ADB bus).
+
+	  This driver provides a basic mouse driver but can be interfaced
+	  with the synaptics X11 driver to provide acceleration and
+	  scrolling in X11.
+
+	  For further information, see
+	  <file:Documentation/input/appletouch.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called appletouch.
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 43b2f99..5e03b93 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -41,3 +41,4 @@
 obj-$(CONFIG_USB_ACECAD)	+= acecad.o
 obj-$(CONFIG_USB_YEALINK)	+= yealink.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
+obj-$(CONFIG_USB_APPLETOUCH)	+= appletouch.o
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
new file mode 100644
index 0000000..e03c1c5
--- /dev/null
+++ b/drivers/usb/input/appletouch.c
@@ -0,0 +1,469 @@
+/*
+ * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
+ * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ *
+ * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/usb_input.h>
+
+/* Apple has powerbooks which have the keyboard with different Product IDs */
+#define APPLE_VENDOR_ID		0x05AC
+
+#define ATP_DEVICE(prod)					\
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |   		\
+		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
+		       USB_DEVICE_ID_MATCH_INT_PROTOCOL,	\
+	.idVendor = APPLE_VENDOR_ID,				\
+	.idProduct = (prod),					\
+	.bInterfaceClass = 0x03,				\
+	.bInterfaceProtocol = 0x02
+
+/* table of devices that work with this driver */
+static struct usb_device_id atp_table [] = {
+	{ ATP_DEVICE(0x020E) },
+	{ ATP_DEVICE(0x020F) },
+	{ ATP_DEVICE(0x030A) },
+	{ ATP_DEVICE(0x030B) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, atp_table);
+
+/* size of a USB urb transfer */
+#define ATP_DATASIZE	81
+
+/*
+ * number of sensors. Note that only 16 instead of 26 X (horizontal)
+ * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
+ * (vertical) sensors.
+ */
+#define ATP_XSENSORS	26
+#define ATP_YSENSORS	16
+
+/* amount of fuzz this touchpad generates */
+#define ATP_FUZZ	16
+
+/* maximum pressure this driver will report */
+#define ATP_PRESSURE	300
+/*
+ * multiplication factor for the X and Y coordinates.
+ * We try to keep the touchpad aspect ratio while still doing only simple
+ * arithmetics.
+ * The factors below give coordinates like:
+ * 	0 <= x <  960 on 12" and 15" Powerbooks
+ * 	0 <= x < 1600 on 17" Powerbooks
+ * 	0 <= y <  646
+ */
+#define ATP_XFACT	64
+#define ATP_YFACT	43
+
+/*
+ * Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
+ * ignored.
+ */
+#define ATP_THRESHOLD	 5
+
+/* Structure to hold all of our device specific stuff */
+struct atp {
+	struct usb_device *	udev;		/* usb device */
+	struct urb *		urb;		/* usb request block */
+	signed char *		data;		/* transferred data */
+	int			open;		/* non-zero if opened */
+	struct input_dev	input;		/* input dev */
+	int			valid;		/* are the sensors valid ? */
+	int			x_old;		/* last reported x/y, */
+	int			y_old;		/* used for smoothing */
+						/* current value of the sensors */
+	signed char		xy_cur[ATP_XSENSORS + ATP_YSENSORS];
+						/* last value of the sensors */
+	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
+						/* accumulated sensors */
+	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+};
+
+#define dbg_dump(msg, tab) \
+	if (debug > 1) {						\
+		int i;							\
+		printk("appletouch: %s %lld", msg, (long long)jiffies); \
+		for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)	\
+			printk(" %02x", tab[i]); 			\
+		printk("\n"); 						\
+	}
+
+#define dprintk(format, a...) 						\
+	do {								\
+		if (debug) printk(format, ##a);				\
+	} while (0)
+
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_LICENSE("GPL");
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
+			     int *z, int *fingers)
+{
+	int i;
+	/* values to calculate mean */
+	int pcum = 0, psum = 0;
+
+	*fingers = 0;
+
+	for (i = 0; i < nb_sensors; i++) {
+		if (xy_sensors[i] < ATP_THRESHOLD)
+			continue;
+		if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+			(*fingers)++;
+		pcum += xy_sensors[i] * i;
+		psum += xy_sensors[i];
+	}
+
+	if (psum > 0) {
+		*z = psum;
+		return pcum * fact / psum;
+	}
+
+	return 0;
+}
+
+static inline void atp_report_fingers(struct input_dev *input, int fingers)
+{
+	input_report_key(input, BTN_TOOL_FINGER, fingers == 1);
+	input_report_key(input, BTN_TOOL_DOUBLETAP, fingers == 2);
+	input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
+}
+
+static void atp_complete(struct urb* urb, struct pt_regs* regs)
+{
+	int x, y, x_z, y_z, x_f, y_f;
+	int retval, i;
+	struct atp *dev = urb->context;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* This urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	/* drop incomplete datasets */
+	if (dev->urb->actual_length != ATP_DATASIZE) {
+		dprintk("appletouch: incomplete data package.\n");
+		goto exit;
+	}
+
+	/* reorder the sensors values */
+	for (i = 0; i < 8; i++) {
+		/* X values */
+		dev->xy_cur[i     ] = dev->data[5 * i +  2];
+		dev->xy_cur[i +  8] = dev->data[5 * i +  4];
+		dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+		if (i < 2)
+			dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+		/* Y values */
+		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
+		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+	}
+
+	dbg_dump("sample", dev->xy_cur);
+
+	if (!dev->valid) {
+		/* first sample */
+		dev->valid = 1;
+		dev->x_old = dev->y_old = -1;
+		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+		/* 17" Powerbooks have 10 extra X sensors */
+		for (i = 16; i < ATP_XSENSORS; i++)
+			if (dev->xy_cur[i]) {
+				printk("appletouch: 17\" model detected.\n");
+				input_set_abs_params(&dev->input, ABS_X, 0,
+				     		     (ATP_XSENSORS - 1) *
+						     ATP_XFACT - 1,
+						     ATP_FUZZ, 0);
+				break;
+			}
+
+		goto exit;
+	}
+
+	for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+		/* accumulate the change */
+		signed char change = dev->xy_old[i] - dev->xy_cur[i];
+		dev->xy_acc[i] -= change;
+
+		/* prevent down drifting */
+		if (dev->xy_acc[i] < 0)
+			dev->xy_acc[i] = 0;
+	}
+
+	memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+
+	dbg_dump("accumulator", dev->xy_acc);
+
+	x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+			      ATP_XFACT, &x_z, &x_f);
+	y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+			      ATP_YFACT, &y_z, &y_f);
+
+	if (x && y) {
+		if (dev->x_old != -1) {
+			x = (dev->x_old * 3 + x) >> 2;
+			y = (dev->y_old * 3 + y) >> 2;
+			dev->x_old = x;
+			dev->y_old = y;
+
+			if (debug > 1)
+				printk("appletouch: X: %3d Y: %3d "
+				       "Xz: %3d Yz: %3d\n",
+				       x, y, x_z, y_z);
+
+			input_report_key(&dev->input, BTN_TOUCH, 1);
+			input_report_abs(&dev->input, ABS_X, x);
+			input_report_abs(&dev->input, ABS_Y, y);
+			input_report_abs(&dev->input, ABS_PRESSURE,
+					 min(ATP_PRESSURE, x_z + y_z));
+			atp_report_fingers(&dev->input, max(x_f, y_f));
+		}
+		dev->x_old = x;
+		dev->y_old = y;
+	}
+	else if (!x && !y) {
+
+		dev->x_old = dev->y_old = -1;
+		input_report_key(&dev->input, BTN_TOUCH, 0);
+		input_report_abs(&dev->input, ABS_PRESSURE, 0);
+		atp_report_fingers(&dev->input, 0);
+
+		/* reset the accumulator on release */
+		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+	}
+
+	input_report_key(&dev->input, BTN_LEFT, !!dev->data[80]);
+
+	input_sync(&dev->input);
+
+exit:
+	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+	if (retval) {
+		err("%s - usb_submit_urb failed with result %d",
+		    __FUNCTION__, retval);
+	}
+}
+
+static int atp_open(struct input_dev *input)
+{
+	struct atp *dev = input->private;
+
+	if (usb_submit_urb(dev->urb, GFP_ATOMIC))
+		return -EIO;
+
+	dev->open = 1;
+	return 0;
+}
+
+static void atp_close(struct input_dev *input)
+{
+	struct atp *dev = input->private;
+
+	usb_kill_urb(dev->urb);
+	dev->open = 0;
+}
+
+static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+	struct atp *dev = NULL;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int int_in_endpointAddr = 0;
+	int i, retval = -ENOMEM;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kmalloc(sizeof(struct atp), GFP_KERNEL);
+	if (dev == NULL) {
+		err("Out of memory");
+		goto err_kmalloc;
+	}
+	memset(dev, 0, sizeof(struct atp));
+
+	dev->udev = interface_to_usbdev(iface);
+
+	/* set up the endpoint information */
+	/* use only the first interrupt-in endpoint */
+	iface_desc = iface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+		if (!int_in_endpointAddr &&
+		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+					== USB_ENDPOINT_XFER_INT)) {
+			/* we found an interrupt in endpoint */
+			int_in_endpointAddr = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (!int_in_endpointAddr) {
+		retval = -EIO;
+		err("Could not find int-in endpoint");
+		goto err_endpoint;
+	}
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(iface, dev);
+
+	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->urb) {
+		retval = -ENOMEM;
+		goto err_usballoc;
+	}
+	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+				     &dev->urb->transfer_dma);
+	if (!dev->data) {
+		retval = -ENOMEM;
+		goto err_usbbufalloc;
+	}
+	usb_fill_int_urb(dev->urb, dev->udev,
+			 usb_rcvintpipe(dev->udev, int_in_endpointAddr),
+			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+
+	init_input_dev(&dev->input);
+	dev->input.name = "appletouch";
+	dev->input.dev = &iface->dev;
+	dev->input.private = dev;
+	dev->input.open = atp_open;
+	dev->input.close = atp_close;
+
+	usb_to_input_id(dev->udev, &dev->input.id);
+
+	set_bit(EV_ABS, dev->input.evbit);
+
+	/*
+	 * 12" and 15" Powerbooks only have 16 x sensors,
+	 * 17" models are detected later.
+	 */
+	input_set_abs_params(&dev->input, ABS_X, 0,
+			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+	input_set_abs_params(&dev->input, ABS_Y, 0,
+			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	input_set_abs_params(&dev->input, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
+
+	set_bit(EV_KEY, dev->input.evbit);
+	set_bit(BTN_TOUCH, dev->input.keybit);
+	set_bit(BTN_TOOL_FINGER, dev->input.keybit);
+	set_bit(BTN_TOOL_DOUBLETAP, dev->input.keybit);
+	set_bit(BTN_TOOL_TRIPLETAP, dev->input.keybit);
+	set_bit(BTN_LEFT, dev->input.keybit);
+
+	input_register_device(&dev->input);
+
+	printk(KERN_INFO "input: appletouch connected\n");
+
+	return 0;
+
+err_usbbufalloc:
+	usb_free_urb(dev->urb);
+err_usballoc:
+	usb_set_intfdata(iface, NULL);
+err_endpoint:
+	kfree(dev);
+err_kmalloc:
+	return retval;
+}
+
+static void atp_disconnect(struct usb_interface *iface)
+{
+	struct atp *dev = usb_get_intfdata(iface);
+
+	usb_set_intfdata(iface, NULL);
+	if (dev) {
+		usb_kill_urb(dev->urb);
+		input_unregister_device(&dev->input);
+		usb_free_urb(dev->urb);
+		usb_buffer_free(dev->udev, ATP_DATASIZE,
+				dev->data, dev->urb->transfer_dma);
+		kfree(dev);
+	}
+	printk(KERN_INFO "input: appletouch disconnected\n");
+}
+
+static int atp_suspend(struct usb_interface *iface, pm_message_t message)
+{
+	struct atp *dev = usb_get_intfdata(iface);
+	usb_kill_urb(dev->urb);
+	dev->valid = 0;
+	return 0;
+}
+
+static int atp_resume(struct usb_interface *iface)
+{
+	struct atp *dev = usb_get_intfdata(iface);
+	if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+		return -EIO;
+
+	return 0;
+}
+
+static struct usb_driver atp_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "appletouch",
+	.probe		= atp_probe,
+	.disconnect	= atp_disconnect,
+	.suspend	= atp_suspend,
+	.resume		= atp_resume,
+	.id_table	= atp_table,
+};
+
+static int __init atp_init(void)
+{
+	return usb_register(&atp_driver);
+}
+
+static void __exit atp_exit(void)
+{
+	usb_deregister(&atp_driver);
+}
+
+module_init(atp_init);
+module_exit(atp_exit);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index e108e0a..a99865c 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1446,7 +1446,6 @@
 
 #define USB_VENDOR_ID_APPLE		0x05ac
 #define USB_DEVICE_ID_APPLE_POWERMOUSE	0x0304
-#define USB_DEVICE_ID_APPLE_BLUETOOTH	0x1000
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1465,7 +1464,6 @@
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_BLUETOOTH, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
index 3957e14..7603cbe 100644
--- a/drivers/usb/misc/sisusbvga/Kconfig
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -4,11 +4,43 @@
 	depends on USB && USB_EHCI_HCD
         ---help---
 	  Say Y here if you intend to attach a USB2VGA dongle based on a
-	  Net2280 and a SiS315 chip. 
-	  
-	  Note that this device requires a USB 2.0 host controller. It will not 
+	  Net2280 and a SiS315 chip.
+
+	  Note that this device requires a USB 2.0 host controller. It will not
 	  work with USB 1.x controllers.
 
-	  To compile this driver as a module, choose M here: the module will be
-	  called sisusb.  If unsure, say N.
+	  To compile this driver as a module, choose M here; the module will be
+	  called sisusbvga. If unsure, say N.
+
+config USB_SISUSBVGA_CON
+	bool "Text console and mode switching support" if USB_SISUSBVGA
+	depends on VT
+	select FONT_8x16
+	---help---
+	  Say Y here if you want a VGA text console via the USB dongle or
+	  want to support userland applications that utilize the driver's
+	  display mode switching capabilities.
+
+	  Note that this console supports VGA/EGA text mode only.
+
+	  By default, the console part of the driver will not kick in when
+	  the driver is initialized. If you want the driver to take over
+	  one or more of the consoles, you need to specify the number of
+	  the first and last consoles (starting at 1) as driver parameters.
+
+	  For example, if the driver is compiled as a module:
+
+	     modprobe sisusbvga first=1 last=5
+
+	  If you use hotplug, add this to your modutils config files with
+	  the "options" keyword, such as eg.
+
+	     options sisusbvga first=1 last=5
+
+	  If the driver is compiled into the kernel image, the parameters
+	  must be given in the kernel command like, such as
+
+	     sisusbvga.first=1 sisusbvga.last=5
+
+
 
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 76f1643..7f934cf 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -2,5 +2,7 @@
 # Makefile for the sisusb driver (if driver is inside kernel tree).
 #
 
-obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
+
+sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index d63ce6c..39db315 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -1,6 +1,8 @@
 /*
  * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
  *
+ * Main part
+ *
  * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, this code is licensed under the
@@ -48,16 +50,60 @@
 #include <linux/kref.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
 
 #include "sisusb.h"
 
+#ifdef INCL_SISUSB_CON
+#include <linux/font.h>
+#endif
+
 #define SISUSB_DONTSYNC
 
 /* Forward declarations / clean-up routines */
 
+#ifdef INCL_SISUSB_CON
+int	sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+int	sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+int	sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
+int	sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
+int	sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,	u8 myand, u8 myor);
+int	sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
+int	sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
+
+int	sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+int	sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+int	sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+int	sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+int	sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+			u32 dest, int length, size_t *bytes_written);
+
+int	sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int  SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern int  SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern void sisusb_init_concode(void);
+extern int  sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+
+extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+
+extern int  sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+		u8 *arg, int cmapsz, int ch512, int dorecalc,
+		struct vc_data *c, int fh, int uplock);
+
+static int sisusb_first_vc = 0;
+static int sisusb_last_vc = 0;
+module_param_named(first, sisusb_first_vc, int, 0);
+module_param_named(last, sisusb_last_vc, int, 0);
+MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)");
+MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES)");
+#endif
+
 static struct usb_driver sisusb_driver;
 
-static DECLARE_MUTEX(disconnect_sem);
+DECLARE_MUTEX(disconnect_sem);
 
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -639,7 +685,10 @@
 
 /* The following routines assume being used to transfer byte, word,
  * long etc.
- * This means that they assume "data" in machine endianness format.
+ * This means that
+ *   - the write routines expect "data" in machine endianness format.
+ *     The data will be converted to leXX in sisusb_xxx_packet.
+ *   - the read routines can expect read data in machine-endianess.
  */
 
 static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
@@ -839,7 +888,7 @@
 				if (get_user(swap16, (u16 __user *)userbuffer))
 					return -EFAULT;
 			} else
-				swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+				swap16 = *((u16 *)kernbuffer);
 
 			ret = sisusb_write_memio_word(sisusb,
 							SISUSB_TYPE_MEM,
@@ -855,14 +904,25 @@
 			if (userbuffer) {
 				if (copy_from_user(&buf, userbuffer, 3))
 					return -EFAULT;
-
+#ifdef __BIG_ENDIAN
 				swap32 = (buf[0] << 16) |
 					 (buf[1] <<  8) |
 					 buf[2];
+#else
+				swap32 = (buf[2] << 16) |
+					 (buf[1] <<  8) |
+					 buf[0];
+#endif
 			} else
+#ifdef __BIG_ENDIAN
 				swap32 = (kernbuffer[0] << 16) |
 					 (kernbuffer[1] <<  8) |
 					 kernbuffer[2];
+#else
+				swap32 = (kernbuffer[2] << 16) |
+					 (kernbuffer[1] <<  8) |
+					 kernbuffer[0];
+#endif
 
 			ret = sisusb_write_memio_24bit(sisusb,
 							SISUSB_TYPE_MEM,
@@ -879,10 +939,7 @@
 				if (get_user(swap32, (u32 __user *)userbuffer))
 					return -EFAULT;
 			} else
-				swap32 = (kernbuffer[0] << 24) |
-					 (kernbuffer[1] << 16) |
-					 (kernbuffer[2] <<  8) |
-					 kernbuffer[3];
+				swap32 = *((u32 *)kernbuffer);
 
 			ret = sisusb_write_memio_long(sisusb,
 							SISUSB_TYPE_MEM,
@@ -1005,6 +1062,10 @@
 	return ret ? -EIO : 0;
 }
 
+/* Remember: Read data in packet is in machine-endianess! So for
+ * byte, word, 24bit, long no endian correction is necessary.
+ */
+
 static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
 							u32 addr, u8 *data)
 {
@@ -1191,8 +1252,7 @@
 						(u16 __user *)userbuffer))
 						return -EFAULT;
 				} else {
-					kernbuffer[0] = swap16 >> 8;
-					kernbuffer[1] = swap16 & 0xff;
+					*((u16 *)kernbuffer) = swap16;
 				}
 			}
 			return ret;
@@ -1202,9 +1262,15 @@
 								addr, &swap32);
 			if (!ret) {
 				(*bytes_read) += 3;
+#ifdef __BIG_ENDIAN
 				buf[0] = (swap32 >> 16) & 0xff;
 				buf[1] = (swap32 >> 8) & 0xff;
 				buf[2] = swap32 & 0xff;
+#else
+				buf[2] = (swap32 >> 16) & 0xff;
+				buf[1] = (swap32 >> 8) & 0xff;
+				buf[0] = swap32 & 0xff;
+#endif
 				if (userbuffer) {
 					if (copy_to_user(userbuffer, &buf[0], 3))
 						return -EFAULT;
@@ -1228,10 +1294,7 @@
 
 					userbuffer += 4;
 				} else {
-					kernbuffer[0] = (swap32 >> 24) & 0xff;
-					kernbuffer[1] = (swap32 >> 16) & 0xff;
-					kernbuffer[2] = (swap32 >> 8) & 0xff;
-					kernbuffer[3] = swap32 & 0xff;
+					*((u32 *)kernbuffer) = swap32;
 					kernbuffer += 4;
 				}
 				addr += 4;
@@ -1289,7 +1352,24 @@
 
 /* High level: Gfx (indexed) register access */
 
-static int
+#ifdef INCL_SISUSB_CON
+int
+sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data)
+{
+	return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+
+int
+sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data)
+{
+	return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);
+}
+#endif
+
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
 {
 	int ret;
@@ -1298,7 +1378,10 @@
 	return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
 {
 	int ret;
@@ -1307,7 +1390,10 @@
 	return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
 							u8 myand, u8 myor)
 {
@@ -1336,18 +1422,89 @@
 	return ret;
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
 {
 	return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
 }
 
-static int
+#ifndef INCL_SISUSB_CON
+static
+#endif
+int
 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
 {
 	return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
 }
 
+/* Write/read video ram */
+
+#ifdef INCL_SISUSB_CON
+int
+sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data)
+{
+	return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data)
+{
+	return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
+{
+	return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data)
+{
+	return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
+}
+
+int
+sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+			u32 dest, int length, size_t *bytes_written)
+{
+	return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));
+}
+
+#ifdef SISUSBENDIANTEST
+int
+sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest,
+			u32 src, int length, size_t *bytes_written)
+{
+	return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));
+}
+#endif
+#endif
+
+#ifdef SISUSBENDIANTEST
+static void
+sisusb_testreadwrite(struct sisusb_usb_data *sisusb)
+{
+    static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+    char destbuffer[10];
+    size_t dummy;
+    int i,j;
+
+    sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy);
+
+    for(i = 1; i <= 7; i++) {
+        printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i);
+	sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy);
+	for(j = 0; j < i; j++) {
+	     printk(KERN_DEBUG "sisusb: rwtest read[%d] = %x\n", j, destbuffer[j]);
+	}
+    }
+}
+#endif
+
 /* access pci config registers (reg numbers 0, 4, 8, etc) */
 
 static int
@@ -2270,6 +2427,129 @@
 	return ret;
 }
 
+
+#ifdef INCL_SISUSB_CON
+
+/* Set up default text mode:
+   - Set text mode (0x03)
+   - Upload default font
+   - Upload user font (if available)
+*/
+
+int
+sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
+{
+	int ret = 0, slot = sisusb->font_slot, i;
+	struct font_desc *myfont;
+	u8 *tempbuf;
+	u16 *tempbufb;
+	size_t written;
+	static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+	static char bootlogo[] = "(o_ //\\ V_/_";
+
+	/* sisusb->lock is down */
+
+	if (!sisusb->SiS_Pr)
+		return 1;
+
+	sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+	sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+	/* Set mode 0x03 */
+	SiSUSBSetMode(sisusb->SiS_Pr, 0x03);
+
+	if (!(myfont = find_font("VGA8x16")))
+		return 1;
+
+	if (!(tempbuf = vmalloc(8192)))
+		return 1;
+
+	for (i = 0; i < 256; i++)
+		memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16);
+
+	/* Upload default font */
+	ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0);
+
+	vfree(tempbuf);
+
+	/* Upload user font (and reset current slot) */
+	if (sisusb->font_backup) {
+		ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup,
+				8192, sisusb->font_backup_512, 1, NULL,
+				sisusb->font_backup_height, 0);
+		if (slot != 2)
+			sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1,
+					NULL, 16, 0);
+	}
+
+	if (init && !sisusb->scrbuf) {
+
+		if ((tempbuf = vmalloc(8192))) {
+
+			i = 4096;
+			tempbufb = (u16 *)tempbuf;
+			while (i--)
+				*(tempbufb++) = 0x0720;
+
+			i = 0;
+			tempbufb = (u16 *)tempbuf;
+			while (bootlogo[i]) {
+				*(tempbufb++) = 0x0700 | bootlogo[i++];
+				if (!(i % 4))
+					tempbufb += 76;
+			}
+
+			i = 0;
+			tempbufb = (u16 *)tempbuf + 6;
+			while (bootstring[i])
+				*(tempbufb++) = 0x0700 | bootstring[i++];
+
+			ret |= sisusb_copy_memory(sisusb, tempbuf,
+				sisusb->vrambase, 8192, &written);
+
+			vfree(tempbuf);
+
+		}
+
+	} else if (sisusb->scrbuf) {
+
+		ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf,
+				sisusb->vrambase, sisusb->scrbuf_size, &written);
+
+	}
+
+	if (sisusb->sisusb_cursor_size_from >= 0 &&
+	    sisusb->sisusb_cursor_size_to >= 0) {
+		sisusb_setidxreg(sisusb, SISCR, 0x0a,
+				sisusb->sisusb_cursor_size_from);
+		sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0,
+				sisusb->sisusb_cursor_size_to);
+	} else {
+		sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d);
+		sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e);
+		sisusb->sisusb_cursor_size_to = -1;
+	}
+
+	slot = sisusb->sisusb_cursor_loc;
+	if(slot < 0) slot = 0;
+
+	sisusb->sisusb_cursor_loc = -1;
+	sisusb->bad_cursor_pos = 1;
+
+	sisusb_set_cursor(sisusb, slot);
+
+	sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+	sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+
+	sisusb->textmodedestroyed = 0;
+
+	/* sisusb->lock is down */
+
+	return ret;
+}
+
+#endif
+
 /* fops */
 
 static int
@@ -2329,7 +2609,7 @@
 		}
 	}
 
-	/* increment usage count for the device */
+	/* Increment usage count for our sisusb */
 	kref_get(&sisusb->kref);
 
 	sisusb->isopen = 1;
@@ -2340,12 +2620,10 @@
 
 	up(&disconnect_sem);
 
-	printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
-
 	return 0;
 }
 
-static void
+void
 sisusb_delete(struct kref *kref)
 {
 	struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
@@ -2359,6 +2637,9 @@
 	sisusb->sisusb_dev = NULL;
 	sisusb_free_buffers(sisusb);
 	sisusb_free_urbs(sisusb);
+#ifdef INCL_SISUSB_CON
+	kfree(sisusb->SiS_Pr);
+#endif
 	kfree(sisusb);
 }
 
@@ -2395,8 +2676,6 @@
 
 	up(&disconnect_sem);
 
-	printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
-
 	return 0;
 }
 
@@ -2733,6 +3012,12 @@
 	int 	retval, port, length;
 	u32	address;
 
+	/* All our commands require the device
+	 * to be initialized.
+	 */
+	if (!sisusb->devinit)
+		return -ENODEV;
+
 	port = y->data3 -
 		SISUSB_PCI_PSEUDO_IOPORTBASE +
 		SISUSB_PCI_IOPORTBASE;
@@ -2774,6 +3059,10 @@
 			break;
 
 		case SUCMD_CLRSCR:
+			/* Gfx core must be initialized */
+			if (!sisusb->gfxinit)
+				return -ENODEV;
+
 			length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
 			address = y->data3 -
 				SISUSB_PCI_PSEUDO_MEMBASE +
@@ -2781,11 +3070,61 @@
 			retval = sisusb_clear_vram(sisusb, address, length);
 			break;
 
+		case SUCMD_HANDLETEXTMODE:
+			retval = 0;
+#ifdef INCL_SISUSB_CON
+			/* Gfx core must be initialized, SiS_Pr must exist */
+			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+				return -ENODEV;
+
+			switch (y->data0) {
+			case 0:
+				retval = sisusb_reset_text_mode(sisusb, 0);
+				break;
+			case 1:
+				sisusb->textmodedestroyed = 1;
+				break;
+			}
+#endif
+			break;
+
+#ifdef INCL_SISUSB_CON
+		case SUCMD_SETMODE:
+			/* Gfx core must be initialized, SiS_Pr must exist */
+			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+				return -ENODEV;
+
+			retval = 0;
+
+			sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+			sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+			if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3))
+				retval = -EINVAL;
+
+			break;
+
+		case SUCMD_SETVESAMODE:
+			/* Gfx core must be initialized, SiS_Pr must exist */
+			if (!sisusb->gfxinit || !sisusb->SiS_Pr)
+				return -ENODEV;
+
+			retval = 0;
+
+			sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30;
+			sisusb->SiS_Pr->sisusb = (void *)sisusb;
+
+			if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3))
+				retval = -EINVAL;
+
+			break;
+#endif
+
 		default:
 			retval = -EINVAL;
 	}
 
-	if(retval > 0)
+	if (retval > 0)
 		retval = -EIO;
 
 	return retval;
@@ -2835,6 +3174,11 @@
 			x.sisusb_vramsize   = sisusb->vramsize;
 			x.sisusb_minor	    = sisusb->minor;
 			x.sisusb_fbdevactive= 0;
+#ifdef INCL_SISUSB_CON
+			x.sisusb_conactive  = sisusb->haveconsole ? 1 : 0;
+#else
+			x.sisusb_conactive  = 0;
+#endif
 
 			if (copy_to_user((void __user *)arg, &x, sizeof(x)))
 				retval = -EFAULT;
@@ -2895,9 +3239,13 @@
 };
 
 static struct usb_class_driver usb_sisusb_class = {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
 	.name =		"usb/sisusbvga%d",
-	.fops =		&usb_sisusb_fops,
 	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+#else
+	.name =		"sisusbvga%d",
+#endif
+	.fops =		&usb_sisusb_fops,
 	.minor_base =	SISUSB_MINOR
 };
 
@@ -2994,12 +3342,25 @@
 	printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
 					sisusb->minor, sisusb->numobufs);
 
+#ifdef INCL_SISUSB_CON
+	/* Allocate our SiS_Pr */
+	if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) {
+		printk(KERN_ERR
+			"sisusbvga[%d]: Failed to allocate SiS_Pr\n",
+			sisusb->minor);
+	}
+#endif
+
 	/* Do remaining init stuff */
 
 	init_waitqueue_head(&sisusb->wait_q);
 
 	usb_set_intfdata(intf, sisusb);
 
+	usb_get_dev(sisusb->sisusb_dev);
+
+	sisusb->present = 1;
+
 #ifdef SISUSB_OLD_CONFIG_COMPAT
 	{
 	int ret;
@@ -3014,14 +3375,19 @@
 			sisusb->minor);
 	else
 		sisusb->ioctl32registered = 1;
-
 	}
 #endif
 
-	sisusb->present = 1;
-
 	if (dev->speed == USB_SPEED_HIGH) {
-		if (sisusb_init_gfxdevice(sisusb, 1))
+		int initscreen = 1;
+#ifdef INCL_SISUSB_CON
+		if (sisusb_first_vc > 0 &&
+		    sisusb_last_vc > 0 &&
+		    sisusb_first_vc <= sisusb_last_vc &&
+		    sisusb_last_vc <= MAX_NR_CONSOLES)
+			initscreen = 0;
+#endif
+		if (sisusb_init_gfxdevice(sisusb, initscreen))
 			printk(KERN_ERR
 				"sisusbvga[%d]: Failed to early "
 				"initialize device\n",
@@ -3035,6 +3401,16 @@
 
 	sisusb->ready = 1;
 
+#ifdef SISUSBENDIANTEST
+	printk(KERN_DEBUG "sisusb: *** RWTEST ***\n");
+	sisusb_testreadwrite(sisusb);
+	printk(KERN_DEBUG "sisusb: *** RWTEST END ***\n");
+#endif
+
+#ifdef INCL_SISUSB_CON
+	sisusb_console_init(sisusb, sisusb_first_vc, sisusb_last_vc);
+#endif
+
 	return 0;
 
 error_4:
@@ -3053,13 +3429,20 @@
 	struct sisusb_usb_data *sisusb;
 	int minor;
 
-	down(&disconnect_sem);
-
 	/* This should *not* happen */
-	if (!(sisusb = usb_get_intfdata(intf))) {
-		up(&disconnect_sem);
+	if (!(sisusb = usb_get_intfdata(intf)))
 		return;
-	}
+
+#ifdef INCL_SISUSB_CON
+	sisusb_console_exit(sisusb);
+#endif
+
+	/* The above code doesn't need the disconnect
+	 * semaphore to be down; its meaning is to
+	 * protect all other routines from the disconnect
+	 * case, not the other way round.
+	 */
+	down(&disconnect_sem);
 
 	down(&sisusb->lock);
 
@@ -3123,11 +3506,17 @@
 {
 	int retval;
 
+#ifdef INCL_SISUSB_CON
+	sisusb_init_concode();
+#endif
+
 	if (!(retval = usb_register(&sisusb_driver))) {
+
 		printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
 			SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
 		printk(KERN_INFO
 			"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+
 	}
 
 	return retval;
@@ -3142,6 +3531,6 @@
 module_exit(usb_sisusb_exit);
 
 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
-MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_DESCRIPTION("sisusbvga - Driver for Net2280/SiS315-based USB2VGA dongles");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index 1306d00..401ff21 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -46,15 +46,36 @@
 #endif
 #endif
 
+/* For older kernels, support for text consoles is by default
+ * off. To ensable text console support, change the following:
+ */
+#if 0
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+#define CONFIG_USB_SISUSBVGA_CON
+#endif
+#endif
+
 /* Version Information */
 
 #define SISUSB_VERSION		0
 #define SISUSB_REVISION 	0
-#define SISUSB_PATCHLEVEL	7
+#define SISUSB_PATCHLEVEL	8
+
+/* Include console and mode switching code? */
+
+#ifdef CONFIG_USB_SISUSBVGA_CON
+#define INCL_SISUSB_CON		1
+#endif
+
+#ifdef INCL_SISUSB_CON
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include "sisusb_struct.h"
+#endif
 
 /* USB related */
 
-#define SISUSB_MINOR	133		/* FIXME */
+#define SISUSB_MINOR		133	/* official */
 
 /* Size of the sisusb input/output buffers */
 #define SISUSB_IBUF_SIZE  0x01000
@@ -131,6 +152,26 @@
 	unsigned char gfxinit;		/* graphics core initialized? */
 	unsigned short chipid, chipvendor;
 	unsigned short chiprevision;
+#ifdef INCL_SISUSB_CON
+	struct SiS_Private *SiS_Pr;
+	unsigned long scrbuf;
+	unsigned int scrbuf_size;
+	int haveconsole, con_first, con_last;
+	int havethisconsole[MAX_NR_CONSOLES];
+	int textmodedestroyed;
+	unsigned int sisusb_num_columns; /* real number, not vt's idea */
+	int cur_start_addr, con_rolled_over;
+	int sisusb_cursor_loc, bad_cursor_pos;
+	int sisusb_cursor_size_from;
+	int sisusb_cursor_size_to;
+	int current_font_height, current_font_512;
+	int font_backup_size, font_backup_height, font_backup_512;
+	char *font_backup;
+	int font_slot;
+	struct vc_data *sisusb_display_fg;
+	int is_gfx;
+	int con_blanked;
+#endif
 };
 
 #define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
@@ -249,7 +290,9 @@
 
 	__u32   sisusb_fbdevactive;	/* != 0 if framebuffer device active */
 
-	__u8	sisusb_reserved[32];	/* for future use */
+	__u32   sisusb_conactive;	/* != 0 if console driver active */
+
+	__u8	sisusb_reserved[28];	/* for future use */
 };
 
 struct sisusb_command {
@@ -261,18 +304,24 @@
 	__u32  data4;		/* for future use */
 };
 
-#define SUCMD_GET      0x01	/* for all: data0 = index, data3 = port */
-#define SUCMD_SET      0x02	/* data1 = value */
-#define SUCMD_SETOR    0x03	/* data1 = or */
-#define SUCMD_SETAND   0x04	/* data1 = and */
-#define SUCMD_SETANDOR 0x05	/* data1 = and, data2 = or */
-#define SUCMD_SETMASK  0x06	/* data1 = data, data2 = mask */
+#define SUCMD_GET	0x01	/* for all: data0 = index, data3 = port */
+#define SUCMD_SET	0x02	/* data1 = value */
+#define SUCMD_SETOR	0x03	/* data1 = or */
+#define SUCMD_SETAND	0x04	/* data1 = and */
+#define SUCMD_SETANDOR	0x05	/* data1 = and, data2 = or */
+#define SUCMD_SETMASK	0x06	/* data1 = data, data2 = mask */
 
-#define SUCMD_CLRSCR   0x07	/* data0:1:2 = length, data3 = address */
+#define SUCMD_CLRSCR	0x07	/* data0:1:2 = length, data3 = address */
+
+#define SUCMD_HANDLETEXTMODE 0x08 /* Reset/destroy text mode */
+
+#define SUCMD_SETMODE	0x09	/* Set a display mode (data3 = SiS mode) */
+#define SUCMD_SETVESAMODE 0x0a	/* Set a display mode (data3 = VESA mode) */
 
 #define SISUSB_COMMAND		_IOWR(0xF3,0x3D,struct sisusb_command)
-#define SISUSB_GET_CONFIG_SIZE 	_IOR(0xF3,0x3E,__u32)
-#define SISUSB_GET_CONFIG  	_IOR(0xF3,0x3F,struct sisusb_info)
+#define SISUSB_GET_CONFIG_SIZE	_IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG	_IOR(0xF3,0x3F,struct sisusb_info)
+
 
 #endif /* SISUSB_H */
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
new file mode 100644
index 0000000..2458446
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -0,0 +1,1658 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * VGA text mode console part
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ * Portions based on vgacon.c which are
+ *	Created 28 Sep 1997 by Geert Uytterhoeven
+ *      Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ *      based on code Copyright (C) 1991, 1992  Linus Torvalds
+ *			    1995  Jay Estabrook
+ *
+ * A note on using in_atomic() in here: We can't handle console
+ * calls from non-schedulable context due to our USB-dependend
+ * nature. For now, this driver just ignores any calls if it
+ * detects this state.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/smp_lock.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
+extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
+extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
+extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
+extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
+
+extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
+extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
+extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+			u32 dest, int length, size_t *bytes_written);
+
+extern void sisusb_delete(struct kref *kref);
+extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+
+extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+
+#define sisusbcon_writew(val, addr)	(*(addr) = (val))
+#define sisusbcon_readw(addr)		(*(addr))
+#define sisusbcon_memmovew(d, s, c)	memmove(d, s, c)
+#define sisusbcon_memcpyw(d, s, c)	memcpy(d, s, c)
+
+/* vc_data -> sisusb conversion table */
+static struct sisusb_usb_data *mysisusbs[MAX_NR_CONSOLES];
+
+/* Forward declaration */
+static const struct consw sisusb_con;
+
+extern struct semaphore disconnect_sem;
+
+static inline void
+sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
+{
+	count /= 2;
+	while (count--)
+		sisusbcon_writew(c, s++);
+}
+
+static inline void
+sisusb_initialize(struct sisusb_usb_data *sisusb)
+{
+	/* Reset cursor and start address */
+	if (sisusb_setidxreg(sisusb, SISCR, 0x0c, 0x00))
+		return;
+	if (sisusb_setidxreg(sisusb, SISCR, 0x0d, 0x00))
+		return;
+	if (sisusb_setidxreg(sisusb, SISCR, 0x0e, 0x00))
+		return;
+	sisusb_setidxreg(sisusb, SISCR, 0x0f, 0x00);
+}
+
+static inline void
+sisusbcon_set_start_address(struct sisusb_usb_data *sisusb, struct vc_data *c)
+{
+	sisusb->cur_start_addr = (c->vc_visible_origin - sisusb->scrbuf) / 2;
+
+	sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8));
+	sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff));
+}
+
+void
+sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location)
+{
+	if (sisusb->sisusb_cursor_loc == location)
+		return;
+
+	sisusb->sisusb_cursor_loc = location;
+
+	/* Hardware bug: Text cursor appears twice or not at all
+	 * at some positions. Work around it with the cursor skew
+	 * bits.
+	 */
+
+	if ((location & 0x0007) == 0x0007) {
+		sisusb->bad_cursor_pos = 1;
+		location--;
+		if (sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0x1f, 0x20))
+			return;
+	} else if (sisusb->bad_cursor_pos) {
+		if (sisusb_setidxregand(sisusb, SISCR, 0x0b, 0x1f))
+			return;
+		sisusb->bad_cursor_pos = 0;
+	}
+
+	if (sisusb_setidxreg(sisusb, SISCR, 0x0e, (location >> 8)))
+		return;
+	sisusb_setidxreg(sisusb, SISCR, 0x0f, (location & 0xff));
+}
+
+static inline struct sisusb_usb_data *
+sisusb_get_sisusb(unsigned short console)
+{
+	return mysisusbs[console];
+}
+
+static inline int
+sisusb_sisusb_valid(struct sisusb_usb_data *sisusb)
+{
+	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev)
+		return 0;
+
+	return 1;
+}
+
+static struct sisusb_usb_data *
+sisusb_get_sisusb_lock_and_check(unsigned short console)
+{
+	struct sisusb_usb_data *sisusb;
+
+	/* We can't handle console calls in non-schedulable
+	 * context due to our locks and the USB transport.
+	 * So we simply ignore them. This should only affect
+	 * some calls to printk.
+	 */
+	if (in_atomic())
+		return NULL;
+
+	if (!(sisusb = sisusb_get_sisusb(console)))
+		return NULL;
+
+	down(&sisusb->lock);
+
+	if (!sisusb_sisusb_valid(sisusb) ||
+	    !sisusb->havethisconsole[console]) {
+		up(&sisusb->lock);
+		return NULL;
+	}
+
+	return sisusb;
+}
+
+static int
+sisusb_is_inactive(struct vc_data *c, struct sisusb_usb_data *sisusb)
+{
+	if (sisusb->is_gfx ||
+	    sisusb->textmodedestroyed ||
+	    c->vc_mode != KD_TEXT)
+		return 1;
+
+	return 0;
+}
+
+/* con_startup console interface routine */
+static const char *
+sisusbcon_startup(void)
+{
+	return "SISUSBCON";
+}
+
+/* con_init console interface routine */
+static void
+sisusbcon_init(struct vc_data *c, int init)
+{
+	struct sisusb_usb_data *sisusb;
+	int cols, rows;
+
+	/* This is called by take_over_console(),
+	 * ie by us/under our control. It is
+	 * only called after text mode and fonts
+	 * are set up/restored.
+	 */
+
+	down(&disconnect_sem);
+
+	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+		up(&disconnect_sem);
+		return;
+	}
+
+	down(&sisusb->lock);
+
+	if (!sisusb_sisusb_valid(sisusb)) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return;
+	}
+
+	c->vc_can_do_color = 1;
+
+	c->vc_complement_mask = 0x7700;
+
+	c->vc_hi_font_mask = sisusb->current_font_512 ? 0x0800 : 0;
+
+	sisusb->haveconsole = 1;
+
+	sisusb->havethisconsole[c->vc_num] = 1;
+
+	/* We only support 640x400 */
+	c->vc_scan_lines = 400;
+
+	c->vc_font.height = sisusb->current_font_height;
+
+	/* We only support width = 8 */
+	cols = 80;
+	rows = c->vc_scan_lines / c->vc_font.height;
+
+	/* Increment usage count for our sisusb.
+	 * Doing so saves us from upping/downing
+	 * the disconnect semaphore; we can't
+	 * lose our sisusb until this is undone
+	 * in con_deinit. For all other console
+	 * interface functions, it suffices to
+	 * use sisusb->lock and do a quick check
+	 * of sisusb for device disconnection.
+	 */
+	kref_get(&sisusb->kref);
+
+	if (!*c->vc_uni_pagedir_loc)
+		con_set_default_unimap(c);
+
+	up(&sisusb->lock);
+
+	up(&disconnect_sem);
+
+	if (init) {
+		c->vc_cols = cols;
+		c->vc_rows = rows;
+	} else
+		vc_resize(c, cols, rows);
+}
+
+/* con_deinit console interface routine */
+static void
+sisusbcon_deinit(struct vc_data *c)
+{
+	struct sisusb_usb_data *sisusb;
+	int i;
+
+	/* This is called by take_over_console()
+	 * and others, ie not under our control.
+	 */
+
+	down(&disconnect_sem);
+
+	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
+		up(&disconnect_sem);
+		return;
+	}
+
+	down(&sisusb->lock);
+
+	/* Clear ourselves in mysisusbs */
+	mysisusbs[c->vc_num] = NULL;
+
+	sisusb->havethisconsole[c->vc_num] = 0;
+
+	/* Free our font buffer if all consoles are gone */
+	if (sisusb->font_backup) {
+		for(i = 0; i < MAX_NR_CONSOLES; i++) {
+			if (sisusb->havethisconsole[c->vc_num])
+				break;
+		}
+		if (i == MAX_NR_CONSOLES) {
+			vfree(sisusb->font_backup);
+			sisusb->font_backup = NULL;
+		}
+	}
+
+	up(&sisusb->lock);
+
+	/* decrement the usage count on our sisusb */
+	kref_put(&sisusb->kref, sisusb_delete);
+
+	up(&disconnect_sem);
+}
+
+/* interface routine */
+static u8
+sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+			    u8 blink, u8 underline, u8 reverse)
+{
+	u8 attr = color;
+
+	if (underline)
+		attr = (attr & 0xf0) | c->vc_ulcolor;
+	else if (intensity == 0)
+		attr = (attr & 0xf0) | c->vc_halfcolor;
+
+	if (reverse)
+		attr = ((attr) & 0x88) |
+		       ((((attr) >> 4) |
+		       ((attr) << 4)) & 0x77);
+
+	if (blink)
+		attr ^= 0x80;
+
+	if (intensity == 2)
+		attr ^= 0x08;
+
+	return attr;
+}
+
+/* Interface routine */
+static void
+sisusbcon_invert_region(struct vc_data *vc, u16 *p, int count)
+{
+	/* Invert a region. This is called with a pointer
+	 * to the console's internal screen buffer. So we
+	 * simply do the inversion there and rely on
+	 * a call to putc(s) to update the real screen.
+	 */
+
+	while (count--) {
+		u16 a = sisusbcon_readw(p);
+
+		a = ((a) & 0x88ff)        |
+		    (((a) & 0x7000) >> 4) |
+		    (((a) & 0x0700) << 4);
+
+		sisusbcon_writew(a, p++);
+	}
+}
+
+#define SISUSB_VADDR(x,y) \
+	((u16 *)c->vc_origin + \
+	(y) * sisusb->sisusb_num_columns + \
+	(x))
+
+#define SISUSB_HADDR(x,y) \
+	((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
+	(y) * sisusb->sisusb_num_columns + \
+	(x))
+
+/* Interface routine */
+static void
+sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
+{
+	struct sisusb_usb_data *sisusb;
+	ssize_t written;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	/* Don't need to put the character into buffer ourselves,
+	 * because the vt does this BEFORE calling us.
+	 */
+#if 0
+	sisusbcon_writew(ch, SISUSB_VADDR(x, y));
+#endif
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+
+	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+				(u32)SISUSB_HADDR(x, y), 2, &written);
+
+	up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
+		         int count, int y, int x)
+{
+	struct sisusb_usb_data *sisusb;
+	ssize_t written;
+	u16 *dest;
+	int i;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	/* Need to put the characters into the buffer ourselves,
+	 * because the vt does this AFTER calling us.
+	 */
+
+	dest = SISUSB_VADDR(x, y);
+
+	for (i = count; i > 0; i--)
+		sisusbcon_writew(sisusbcon_readw(s++), dest++);
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
+				(u32)SISUSB_HADDR(x, y), count * 2, &written);
+
+	up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
+{
+	struct sisusb_usb_data *sisusb;
+	u16 eattr = c->vc_video_erase_char;
+	ssize_t written;
+	int i, length, cols;
+	u16 *dest;
+
+	if (width <= 0 || height <= 0)
+		return;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	/* Need to clear buffer ourselves, because the vt does
+	 * this AFTER calling us.
+	 */
+
+	dest = SISUSB_VADDR(x, y);
+
+	cols = sisusb->sisusb_num_columns;
+
+	if (width > cols)
+		width = cols;
+
+	if (x == 0 && width >= c->vc_cols) {
+
+		sisusbcon_memsetw(dest, eattr, height * cols * 2);
+
+	} else {
+
+		for (i = height; i > 0; i--, dest += cols)
+			sisusbcon_memsetw(dest, eattr, width * 2);
+
+	}
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+	length = ((height * cols) - x - (cols - width - x)) * 2;
+
+
+	sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
+				(u32)SISUSB_HADDR(x, y), length, &written);
+
+	up(&sisusb->lock);
+}
+
+/* Interface routine */
+static void
+sisusbcon_bmove(struct vc_data *c, int sy, int sx,
+			 int dy, int dx, int height, int width)
+{
+	struct sisusb_usb_data *sisusb;
+	ssize_t written;
+	int cols, length;
+#if 0
+	u16 *src, *dest;
+	int i;
+#endif
+
+	if (width <= 0 || height <= 0)
+		return;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	cols = sisusb->sisusb_num_columns;
+
+	/* Don't need to move data outselves, because
+	 * vt does this BEFORE calling us.
+	 * This is only used by vt's insert/deletechar.
+	 */
+#if 0
+	if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
+
+		sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
+					height * width * 2);
+
+	} else if (dy < sy || (dy == sy && dx < sx)) {
+
+		src  = SISUSB_VADDR(sx, sy);
+		dest = SISUSB_VADDR(dx, dy);
+
+		for (i = height; i > 0; i--) {
+			sisusbcon_memmovew(dest, src, width * 2);
+			src  += cols;
+			dest += cols;
+		}
+
+	} else {
+
+		src  = SISUSB_VADDR(sx, sy + height - 1);
+		dest = SISUSB_VADDR(dx, dy + height - 1);
+
+		for (i = height; i > 0; i--) {
+			sisusbcon_memmovew(dest, src, width * 2);
+			src  -= cols;
+			dest -= cols;
+		}
+
+	}
+#endif
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+	length = ((height * cols) - dx - (cols - width - dx)) * 2;
+
+
+	sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
+				(u32)SISUSB_HADDR(dx, dy), length, &written);
+
+	up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_switch(struct vc_data *c)
+{
+	struct sisusb_usb_data *sisusb;
+	ssize_t written;
+	int length;
+
+	/* Returnvalue 0 means we have fully restored screen,
+	 *	and vt doesn't need to call do_update_region().
+	 * Returnvalue != 0 naturally means the opposite.
+	 */
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return 0;
+
+	/* sisusb->lock is down */
+
+	/* Don't write to screen if in gfx mode */
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	/* That really should not happen. It would mean we are
+	 * being called while the vc is using its private buffer
+	 * as origin.
+	 */
+	if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
+		up(&sisusb->lock);
+		printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
+		return 0;
+	}
+
+	/* Check that we don't copy too much */
+	length = min((int)c->vc_screenbuf_size,
+			(int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+	/* Restore the screen contents */
+	sisusbcon_memcpyw((u16 *)c->vc_origin, (u16 *)c->vc_screenbuf,
+								length);
+
+	sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
+				(u32)SISUSB_HADDR(0, 0),
+				length, &written);
+
+	up(&sisusb->lock);
+
+	return 0;
+}
+
+/* interface routine */
+static void
+sisusbcon_save_screen(struct vc_data *c)
+{
+	struct sisusb_usb_data *sisusb;
+	int length;
+
+	/* Save the current screen contents to vc's private
+	 * buffer.
+	 */
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+	/* Check that we don't copy too much */
+	length = min((int)c->vc_screenbuf_size,
+			(int)(sisusb->scrbuf + sisusb->scrbuf_size - c->vc_origin));
+
+	/* Save the screen contents to vc's private buffer */
+	sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
+								length);
+
+	up(&sisusb->lock);
+}
+
+/* interface routine */
+static int
+sisusbcon_set_palette(struct vc_data *c, unsigned char *table)
+{
+	struct sisusb_usb_data *sisusb;
+	int i, j;
+
+	/* Return value not used by vt */
+
+	if (!CON_IS_VISIBLE(c))
+		return -EINVAL;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return -EINVAL;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return -EINVAL;
+	}
+
+	for (i = j = 0; i < 16; i++) {
+		if (sisusb_setreg(sisusb, SISCOLIDX, table[i]))
+			break;
+		if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+			break;
+		if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+			break;
+		if (sisusb_setreg(sisusb, SISCOLDATA, c->vc_palette[j++] >> 2))
+			break;
+	}
+
+	up(&sisusb->lock);
+
+	return 0;
+}
+
+/* interface routine */
+static int
+sisusbcon_blank(struct vc_data *c, int blank, int mode_switch)
+{
+	struct sisusb_usb_data *sisusb;
+	u8 sr1, cr17, pmreg, cr63;
+	ssize_t written;
+	int ret = 0;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return 0;
+
+	/* sisusb->lock is down */
+
+	if (mode_switch)
+		sisusb->is_gfx = blank ? 1 : 0;
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	switch (blank) {
+
+	case 1:		/* Normal blanking: Clear screen */
+	case -1:
+		sisusbcon_memsetw((u16 *)c->vc_origin,
+				c->vc_video_erase_char,
+				c->vc_screenbuf_size);
+		sisusb_copy_memory(sisusb,
+				(unsigned char *)c->vc_origin,
+				(u32)(sisusb->vrambase +
+					(c->vc_origin - sisusb->scrbuf)),
+				c->vc_screenbuf_size, &written);
+		sisusb->con_blanked = 1;
+		ret = 1;
+		break;
+
+	default:	/* VESA blanking */
+		switch (blank) {
+		case 0: /* Unblank */
+			sr1   = 0x00;
+			cr17  = 0x80;
+			pmreg = 0x00;
+			cr63  = 0x00;
+			ret = 1;
+			sisusb->con_blanked = 0;
+			break;
+		case VESA_VSYNC_SUSPEND + 1:
+			sr1   = 0x20;
+			cr17  = 0x80;
+			pmreg = 0x80;
+			cr63  = 0x40;
+			break;
+		case VESA_HSYNC_SUSPEND + 1:
+			sr1   = 0x20;
+			cr17  = 0x80;
+			pmreg = 0x40;
+			cr63  = 0x40;
+			break;
+		case VESA_POWERDOWN + 1:
+			sr1   = 0x20;
+			cr17  = 0x00;
+			pmreg = 0xc0;
+			cr63  = 0x40;
+			break;
+		default:
+			up(&sisusb->lock);
+			return -EINVAL;
+		}
+
+		sisusb_setidxregandor(sisusb, SISSR, 0x01, ~0x20, sr1);
+		sisusb_setidxregandor(sisusb, SISCR, 0x17, 0x7f, cr17);
+		sisusb_setidxregandor(sisusb, SISSR, 0x1f, 0x3f, pmreg);
+		sisusb_setidxregandor(sisusb, SISCR, 0x63, 0xbf, cr63);
+
+	}
+
+	up(&sisusb->lock);
+
+	return ret;
+}
+
+/* interface routine */
+static int
+sisusbcon_scrolldelta(struct vc_data *c, int lines)
+{
+	struct sisusb_usb_data *sisusb;
+	int margin = c->vc_size_row * 4;
+	int ul, we, p, st;
+
+	/* The return value does not seem to be used */
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return 0;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	if (!lines)		/* Turn scrollback off */
+		c->vc_visible_origin = c->vc_origin;
+	else {
+
+		if (sisusb->con_rolled_over >
+				(c->vc_scr_end - sisusb->scrbuf) + margin) {
+
+			ul = c->vc_scr_end - sisusb->scrbuf;
+			we = sisusb->con_rolled_over + c->vc_size_row;
+
+		} else {
+
+			ul = 0;
+			we = sisusb->scrbuf_size;
+
+		}
+
+		p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we +
+				lines * c->vc_size_row;
+
+		st = (c->vc_origin - sisusb->scrbuf - ul + we) % we;
+
+		if (st < 2 * margin)
+			margin = 0;
+
+		if (p < margin)
+			p = 0;
+
+		if (p > st - margin)
+			p = st;
+
+		c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we;
+	}
+
+	sisusbcon_set_start_address(sisusb, c);
+
+	up(&sisusb->lock);
+
+	return 1;
+}
+
+/* Interface routine */
+static void
+sisusbcon_cursor(struct vc_data *c, int mode)
+{
+	struct sisusb_usb_data *sisusb;
+	int from, to, baseline;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return;
+	}
+
+	if (c->vc_origin != c->vc_visible_origin) {
+		c->vc_visible_origin = c->vc_origin;
+		sisusbcon_set_start_address(sisusb, c);
+	}
+
+	if (mode == CM_ERASE) {
+		sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
+		sisusb->sisusb_cursor_size_to = -1;
+		up(&sisusb->lock);
+		return;
+	}
+
+	sisusb_set_cursor(sisusb, (c->vc_pos - sisusb->scrbuf) / 2);
+
+	baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
+
+	switch (c->vc_cursor_type & 0x0f) {
+		case CUR_BLOCK:		from = 1;
+					to   = c->vc_font.height;
+					break;
+		case CUR_TWO_THIRDS:	from = c->vc_font.height / 3;
+					to   = baseline;
+					break;
+		case CUR_LOWER_HALF:	from = c->vc_font.height / 2;
+					to   = baseline;
+					break;
+		case CUR_LOWER_THIRD:	from = (c->vc_font.height * 2) / 3;
+					to   = baseline;
+					break;
+		case CUR_NONE:		from = 31;
+					to = 30;
+					break;
+		default:
+		case CUR_UNDERLINE:	from = baseline - 1;
+					to   = baseline;
+					break;
+	}
+
+	if (sisusb->sisusb_cursor_size_from != from ||
+	    sisusb->sisusb_cursor_size_to != to) {
+
+		sisusb_setidxreg(sisusb, SISCR, 0x0a, from);
+		sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, to);
+
+		sisusb->sisusb_cursor_size_from = from;
+		sisusb->sisusb_cursor_size_to   = to;
+	}
+
+	up(&sisusb->lock);
+}
+
+static int
+sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
+					int t, int b, int dir, int lines)
+{
+	int cols = sisusb->sisusb_num_columns;
+	int length = ((b - t) * cols) * 2;
+	u16 eattr = c->vc_video_erase_char;
+	ssize_t written;
+
+	/* sisusb->lock is down */
+
+	/* Scroll an area which does not match the
+	 * visible screen's dimensions. This needs
+	 * to be done separately, as it does not
+	 * use hardware panning.
+	 */
+
+	switch (dir) {
+
+		case SM_UP:
+			sisusbcon_memmovew(SISUSB_VADDR(0, t),
+					   SISUSB_VADDR(0, t + lines),
+					   (b - t - lines) * cols * 2);
+			sisusbcon_memsetw(SISUSB_VADDR(0, b - lines), eattr,
+					  lines * cols * 2);
+			break;
+
+		case SM_DOWN:
+			sisusbcon_memmovew(SISUSB_VADDR(0, t + lines),
+					   SISUSB_VADDR(0, t),
+					   (b - t - lines) * cols * 2);
+			sisusbcon_memsetw(SISUSB_VADDR(0, t), eattr,
+					  lines * cols * 2);
+			break;
+	}
+
+	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
+				(u32)SISUSB_HADDR(0, t), length, &written);
+
+	up(&sisusb->lock);
+
+	return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+	struct sisusb_usb_data *sisusb;
+	u16 eattr = c->vc_video_erase_char;
+	ssize_t written;
+	int copyall = 0;
+	unsigned long oldorigin;
+	unsigned int delta = lines * c->vc_size_row;
+	u32 originoffset;
+
+	/* Returning != 0 means we have done the scrolling successfully.
+	 * Returning 0 makes vt do the scrolling on its own.
+	 * Note that con_scroll is only called if the console is
+	 * visible. In that case, the origin should be our buffer,
+	 * not the vt's private one.
+	 */
+
+	if (!lines)
+		return 1;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return 0;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb)) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	/* Special case */
+	if (t || b != c->vc_rows)
+		return sisusbcon_scroll_area(c, sisusb, t, b, dir, lines);
+
+	if (c->vc_origin != c->vc_visible_origin) {
+		c->vc_visible_origin = c->vc_origin;
+		sisusbcon_set_start_address(sisusb, c);
+	}
+
+	/* limit amount to maximum realistic size */
+	if (lines > c->vc_rows)
+		lines = c->vc_rows;
+
+	oldorigin = c->vc_origin;
+
+	switch (dir) {
+
+	case SM_UP:
+
+		if (c->vc_scr_end + delta >=
+				sisusb->scrbuf + sisusb->scrbuf_size) {
+			sisusbcon_memcpyw((u16 *)sisusb->scrbuf,
+					  (u16 *)(oldorigin + delta),
+					  c->vc_screenbuf_size - delta);
+			c->vc_origin = sisusb->scrbuf;
+			sisusb->con_rolled_over = oldorigin - sisusb->scrbuf;
+			copyall = 1;
+		} else
+			c->vc_origin += delta;
+
+		sisusbcon_memsetw(
+			(u16 *)(c->vc_origin + c->vc_screenbuf_size - delta),
+					eattr, delta);
+
+		break;
+
+	case SM_DOWN:
+
+		if (oldorigin - delta < sisusb->scrbuf) {
+			sisusbcon_memmovew((u16 *)(sisusb->scrbuf +
+							sisusb->scrbuf_size -
+							c->vc_screenbuf_size +
+							delta),
+					   (u16 *)oldorigin,
+					   c->vc_screenbuf_size - delta);
+			c->vc_origin = sisusb->scrbuf +
+					sisusb->scrbuf_size -
+					c->vc_screenbuf_size;
+			sisusb->con_rolled_over = 0;
+			copyall = 1;
+		} else
+			c->vc_origin -= delta;
+
+		c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+
+		scr_memsetw((u16 *)(c->vc_origin), eattr, delta);
+
+		break;
+	}
+
+	originoffset = (u32)(c->vc_origin - sisusb->scrbuf);
+
+	if (copyall)
+		sisusb_copy_memory(sisusb,
+			(char *)c->vc_origin,
+			(u32)(sisusb->vrambase + originoffset),
+			c->vc_screenbuf_size, &written);
+	else if (dir == SM_UP)
+		sisusb_copy_memory(sisusb,
+			(char *)c->vc_origin + c->vc_screenbuf_size - delta,
+			(u32)sisusb->vrambase + originoffset +
+					c->vc_screenbuf_size - delta,
+			delta, &written);
+	else
+		sisusb_copy_memory(sisusb,
+			(char *)c->vc_origin,
+			(u32)(sisusb->vrambase + originoffset),
+			delta, &written);
+
+	c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
+	c->vc_visible_origin = c->vc_origin;
+
+	sisusbcon_set_start_address(sisusb, c);
+
+	c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
+
+	up(&sisusb->lock);
+
+	return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_set_origin(struct vc_data *c)
+{
+	struct sisusb_usb_data *sisusb;
+
+	/* Returning != 0 means we were successful.
+	 * Returning 0 will vt make to use its own
+	 *	screenbuffer as the origin.
+	 */
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return 0;
+
+	/* sisusb->lock is down */
+
+	if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;
+
+	sisusbcon_set_start_address(sisusb, c);
+
+	sisusb->con_rolled_over = 0;
+
+	up(&sisusb->lock);
+
+	return 1;
+}
+
+/* Interface routine */
+static int
+sisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows)
+{
+	struct sisusb_usb_data *sisusb;
+	int fh;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return -ENODEV;
+
+	fh = sisusb->current_font_height;
+
+	up(&sisusb->lock);
+
+	/* We are quite unflexible as regards resizing. The vt code
+	 * handles sizes where the line length isn't equal the pitch
+	 * quite badly. As regards the rows, our panning tricks only
+	 * work well if the number of rows equals the visible number
+	 * of rows.
+	 */
+
+	if (newcols != 80 || c->vc_scan_lines / fh != newrows)
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+			u8 *arg, int cmapsz, int ch512, int dorecalc,
+			struct vc_data *c, int fh, int uplock)
+{
+	int font_select = 0x00, i, err = 0;
+	u32 offset = 0;
+	u8 dummy;
+
+	/* sisusb->lock is down */
+
+	/*
+	 * The default font is kept in slot 0.
+	 * A user font is loaded in slot 2 (256 ch)
+	 * or 2+3 (512 ch).
+	 */
+
+	if ((slot != 0 && slot != 2) || !fh) {
+		if (uplock)
+			up(&sisusb->lock);
+		return -EINVAL;
+	}
+
+	if (set)
+		sisusb->font_slot = slot;
+
+	/* Default font is always 256 */
+	if (slot == 0)
+		ch512 = 0;
+	else
+		offset = 4 * cmapsz;
+
+	font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);
+
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */
+
+	if (err)
+		goto font_op_error;
+
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */
+
+	if (err)
+		goto font_op_error;
+
+	if (arg) {
+		if (set)
+			for (i = 0; i < cmapsz; i++) {
+				err |= sisusb_writeb(sisusb,
+					sisusb->vrambase + offset + i,
+					arg[i]);
+				if (err)
+					break;
+			}
+		else
+			for (i = 0; i < cmapsz; i++) {
+				err |= sisusb_readb(sisusb,
+					sisusb->vrambase + offset + i,
+					&arg[i]);
+				if (err)
+					break;
+			}
+
+		/*
+		 * In 512-character mode, the character map is not contiguous if
+		 * we want to remain EGA compatible -- which we do
+		 */
+
+		if (ch512) {
+			if (set)
+				for (i = 0; i < cmapsz; i++) {
+					err |= sisusb_writeb(sisusb,
+						sisusb->vrambase + offset +
+							(2 * cmapsz) + i,
+						arg[cmapsz + i]);
+					if (err)
+						break;
+				}
+			else
+				for (i = 0; i < cmapsz; i++) {
+					err |= sisusb_readb(sisusb,
+						sisusb->vrambase + offset +
+							(2 * cmapsz) + i,
+						&arg[cmapsz + i]);
+					if (err)
+						break;
+				}
+		}
+	}
+
+	if (err)
+		goto font_op_error;
+
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */
+	if (set)
+		sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);
+	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */
+
+	if (err)
+		goto font_op_error;
+
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */
+	err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */
+
+	if (err)
+		goto font_op_error;
+
+	if ((set) && (ch512 != sisusb->current_font_512)) {
+
+		/* Font is shared among all our consoles.
+		 * And so is the hi_font_mask.
+		 */
+		for (i = 0; i < MAX_NR_CONSOLES; i++) {
+			struct vc_data *c = vc_cons[i].d;
+			if (c && c->vc_sw == &sisusb_con)
+				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+		}
+
+		sisusb->current_font_512 = ch512;
+
+		/* color plane enable register:
+			256-char: enable intensity bit
+			512-char: disable intensity bit */
+		sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+		sisusb_setreg(sisusb, SISAR, 0x12);
+		sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);
+
+		sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+		sisusb_setreg(sisusb, SISAR, 0x20);
+		sisusb_getreg(sisusb, SISINPSTAT, &dummy);
+	}
+
+	if (dorecalc) {
+
+		/*
+		 * Adjust the screen to fit a font of a certain height
+		 */
+
+		unsigned char ovr, vde, fsr;
+		int rows = 0, maxscan = 0;
+
+		if (c) {
+
+			/* Number of video rows */
+			rows = c->vc_scan_lines / fh;
+			/* Scan lines to actually display-1 */
+			maxscan = rows * fh - 1;
+
+			/*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
+				rows, maxscan, fh, c->vc_scan_lines);*/
+
+			sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);
+			vde = maxscan & 0xff;
+			ovr = (ovr & 0xbd) |
+			      ((maxscan & 0x100) >> 7) |
+			      ((maxscan & 0x200) >> 3);
+			sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);
+			sisusb_setidxreg(sisusb, SISCR, 0x12, vde);
+
+		}
+
+		sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);
+		fsr = (fsr & 0xe0) | (fh - 1);
+		sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);
+		sisusb->current_font_height = fh;
+
+		sisusb->sisusb_cursor_size_from = -1;
+		sisusb->sisusb_cursor_size_to   = -1;
+
+	}
+
+	if (uplock)
+		up(&sisusb->lock);
+
+	if (dorecalc && c) {
+		int i, rows = c->vc_scan_lines / fh;
+
+		/* Now adjust our consoles' size */
+
+		for (i = 0; i < MAX_NR_CONSOLES; i++) {
+			struct vc_data *vc = vc_cons[i].d;
+
+			if (vc && vc->vc_sw == &sisusb_con) {
+				if (CON_IS_VISIBLE(vc)) {
+					vc->vc_sw->con_cursor(vc, CM_DRAW);
+				}
+				vc->vc_font.height = fh;
+				vc_resize(vc, 0, rows);
+			}
+		}
+	}
+
+	return 0;
+
+font_op_error:
+	if (uplock)
+		up(&sisusb->lock);
+
+	return -EIO;
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_set(struct vc_data *c, struct console_font *font,
+							unsigned flags)
+{
+	struct sisusb_usb_data *sisusb;
+	unsigned charcount = font->charcount;
+
+	if (font->width != 8 || (charcount != 256 && charcount != 512))
+		return -EINVAL;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return -ENODEV;
+
+	/* sisusb->lock is down */
+
+	/* Save the user-provided font into a buffer. This
+	 * is used for restoring text mode after quitting
+	 * from X and for the con_getfont routine.
+	 */
+	if (sisusb->font_backup) {
+		if (sisusb->font_backup_size < charcount) {
+			vfree(sisusb->font_backup);
+			sisusb->font_backup = NULL;
+		}
+	}
+
+	if (!sisusb->font_backup)
+		sisusb->font_backup = vmalloc(charcount * 32);
+
+	if (sisusb->font_backup) {
+		memcpy(sisusb->font_backup, font->data, charcount * 32);
+		sisusb->font_backup_size = charcount;
+		sisusb->font_backup_height = font->height;
+		sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;
+	}
+
+	/* do_font_op ups sisusb->lock */
+
+	return sisusbcon_do_font_op(sisusb, 1, 2, font->data,
+			8192, (charcount == 512),
+			(!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,
+			c, font->height, 1);
+}
+
+/* Interface routine */
+static int
+sisusbcon_font_get(struct vc_data *c, struct console_font *font)
+{
+	struct sisusb_usb_data *sisusb;
+
+	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))
+		return -ENODEV;
+
+	/* sisusb->lock is down */
+
+	font->width = 8;
+	font->height = c->vc_font.height;
+	font->charcount = 256;
+
+	if (!font->data) {
+		up(&sisusb->lock);
+		return 0;
+	}
+
+	if (!sisusb->font_backup) {
+		up(&sisusb->lock);
+		return -ENODEV;
+	}
+
+	/* Copy 256 chars only, like vgacon */
+	memcpy(font->data, sisusb->font_backup, 256 * 32);
+
+	up(&sisusb->lock);
+
+	return 0;
+}
+
+/*
+ *  The console `switch' structure for the sisusb console
+ */
+
+static const struct consw sisusb_con = {
+	.owner =		THIS_MODULE,
+	.con_startup =		sisusbcon_startup,
+	.con_init =		sisusbcon_init,
+	.con_deinit =		sisusbcon_deinit,
+	.con_clear =		sisusbcon_clear,
+	.con_putc =		sisusbcon_putc,
+	.con_putcs =		sisusbcon_putcs,
+	.con_cursor =		sisusbcon_cursor,
+	.con_scroll =		sisusbcon_scroll,
+	.con_bmove =		sisusbcon_bmove,
+	.con_switch =		sisusbcon_switch,
+	.con_blank =		sisusbcon_blank,
+	.con_font_set =		sisusbcon_font_set,
+	.con_font_get =		sisusbcon_font_get,
+	.con_set_palette =	sisusbcon_set_palette,
+	.con_scrolldelta =	sisusbcon_scrolldelta,
+	.con_build_attr =	sisusbcon_build_attr,
+	.con_invert_region =	sisusbcon_invert_region,
+	.con_set_origin =	sisusbcon_set_origin,
+	.con_save_screen =	sisusbcon_save_screen,
+	.con_resize =		sisusbcon_resize,
+};
+
+/* Our very own dummy console driver */
+
+static const char *sisusbdummycon_startup(void)
+{
+    return "SISUSBVGADUMMY";
+}
+
+static void sisusbdummycon_init(struct vc_data *vc, int init)
+{
+    vc->vc_can_do_color = 1;
+    if (init) {
+	vc->vc_cols = 80;
+	vc->vc_rows = 25;
+    } else
+	vc_resize(vc, 80, 25);
+}
+
+static int sisusbdummycon_dummy(void)
+{
+    return 0;
+}
+
+#define SISUSBCONDUMMY	(void *)sisusbdummycon_dummy
+
+const struct consw sisusb_dummy_con = {
+	.owner =		THIS_MODULE,
+	.con_startup =		sisusbdummycon_startup,
+	.con_init =		sisusbdummycon_init,
+	.con_deinit =		SISUSBCONDUMMY,
+	.con_clear =		SISUSBCONDUMMY,
+	.con_putc =		SISUSBCONDUMMY,
+	.con_putcs =		SISUSBCONDUMMY,
+	.con_cursor =		SISUSBCONDUMMY,
+	.con_scroll =		SISUSBCONDUMMY,
+	.con_bmove =		SISUSBCONDUMMY,
+	.con_switch =		SISUSBCONDUMMY,
+	.con_blank =		SISUSBCONDUMMY,
+	.con_font_set =		SISUSBCONDUMMY,
+	.con_font_get =		SISUSBCONDUMMY,
+	.con_font_default =	SISUSBCONDUMMY,
+	.con_font_copy =	SISUSBCONDUMMY,
+	.con_set_palette =	SISUSBCONDUMMY,
+	.con_scrolldelta =	SISUSBCONDUMMY,
+};
+
+int
+sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
+{
+	int i, ret, minor = sisusb->minor;
+
+	down(&disconnect_sem);
+
+	down(&sisusb->lock);
+
+	/* Erm.. that should not happen */
+	if (sisusb->haveconsole || !sisusb->SiS_Pr) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return 1;
+	}
+
+	sisusb->con_first = first;
+	sisusb->con_last  = last;
+
+	if (first > last ||
+	    first > MAX_NR_CONSOLES ||
+	    last > MAX_NR_CONSOLES) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return 1;
+	}
+
+	/* If gfxcore not initialized or no consoles given, quit graciously */
+	if (!sisusb->gfxinit || first < 1 || last < 1) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return 0;
+	}
+
+	sisusb->sisusb_cursor_loc       = -1;
+	sisusb->sisusb_cursor_size_from = -1;
+	sisusb->sisusb_cursor_size_to   = -1;
+
+	/* Set up text mode (and upload  default font) */
+	if (sisusb_reset_text_mode(sisusb, 1)) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		printk(KERN_ERR
+			"sisusbvga[%d]: Failed to set up text mode\n",
+			minor);
+		return 1;
+	}
+
+	/* Initialize some gfx registers */
+	sisusb_initialize(sisusb);
+
+	for (i = first - 1; i <= last - 1; i++) {
+		/* Save sisusb for our interface routines */
+		mysisusbs[i] = sisusb;
+	}
+
+	/* Initial console setup */
+	sisusb->sisusb_num_columns = 80;
+
+	/* Use a 32K buffer (matches b8000-bffff area) */
+	sisusb->scrbuf_size = 32 * 1024;
+
+	/* Allocate screen buffer */
+	if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		printk(KERN_ERR
+			"sisusbvga[%d]: Failed to allocate screen buffer\n",
+			minor);
+		return 1;
+	}
+
+	up(&sisusb->lock);
+	up(&disconnect_sem);
+
+	/* Now grab the desired console(s) */
+	ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
+
+	if (!ret)
+		sisusb->haveconsole = 1;
+	else {
+		for (i = first - 1; i <= last - 1; i++)
+			mysisusbs[i] = NULL;
+	}
+
+	return ret;
+}
+
+void
+sisusb_console_exit(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	/* This is called if the device is disconnected
+	 * and while disconnect and lock semaphores
+	 * are up. This should be save because we
+	 * can't lose our sisusb any other way but by
+	 * disconnection (and hence, the disconnect
+	 * sema is for protecting all other access
+	 * functions from disconnection, not the
+	 * other way round).
+	 */
+
+	/* Now what do we do in case of disconnection:
+	 * One alternative would be to simply call
+	 * give_up_console(). Nah, not a good idea.
+	 * give_up_console() is obviously buggy as it
+	 * only discards the consw pointer from the
+	 * driver_map, but doesn't adapt vc->vc_sw
+	 * of the affected consoles. Hence, the next
+	 * call to any of the console functions will
+	 * eventually take a trip to oops county.
+	 * Also, give_up_console for some reason
+	 * doesn't decrement our module refcount.
+	 * Instead, we switch our consoles to a private
+	 * dummy console. This, of course, keeps our
+	 * refcount up as well, but it works perfectly.
+	 */
+
+	if (sisusb->haveconsole) {
+		for (i = 0; i < MAX_NR_CONSOLES; i++)
+			if (sisusb->havethisconsole[i])
+				take_over_console(&sisusb_dummy_con, i, i, 0);
+				/* At this point, con_deinit for all our
+				 * consoles is executed by take_over_console().
+				 */
+		sisusb->haveconsole = 0;
+	}
+
+	vfree((void *)sisusb->scrbuf);
+	sisusb->scrbuf = 0;
+
+	vfree(sisusb->font_backup);
+	sisusb->font_backup = NULL;
+}
+
+void __init sisusb_init_concode(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		mysisusbs[i] = NULL;
+}
+
+#endif /* INCL_CON */
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
new file mode 100644
index 0000000..f28bc24
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -0,0 +1,1047 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Display mode initializing code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+
+#include "sisusb.h"
+
+#ifdef INCL_SISUSB_CON
+
+#include "sisusb_init.h"
+
+/*********************************************/
+/*         POINTER INITIALIZATION            */
+/*********************************************/
+
+static void
+SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
+{
+	SiS_Pr->SiS_ModeResInfo   = SiSUSB_ModeResInfo;
+	SiS_Pr->SiS_StandTable    = SiSUSB_StandTable;
+
+	SiS_Pr->SiS_SModeIDTable  = SiSUSB_SModeIDTable;
+	SiS_Pr->SiS_EModeIDTable  = SiSUSB_EModeIDTable;
+	SiS_Pr->SiS_RefIndex      = SiSUSB_RefIndex;
+	SiS_Pr->SiS_CRT1Table     = SiSUSB_CRT1Table;
+
+	SiS_Pr->SiS_VCLKData      = SiSUSB_VCLKData;
+}
+
+/*********************************************/
+/*            HELPER: Get ModeID             */
+/*********************************************/
+
+unsigned short
+SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
+{
+	unsigned short ModeIndex = 0;
+
+	switch (HDisplay)
+	{
+		case 320:
+			if (VDisplay == 200)
+				ModeIndex = ModeIndex_320x200[Depth];
+			else if (VDisplay == 240)
+				ModeIndex = ModeIndex_320x240[Depth];
+			break;
+		case 400:
+			if (VDisplay == 300)
+				ModeIndex = ModeIndex_400x300[Depth];
+			break;
+		case 512:
+			if (VDisplay == 384)
+				ModeIndex = ModeIndex_512x384[Depth];
+			break;
+		case 640:
+			if (VDisplay == 480)
+				ModeIndex = ModeIndex_640x480[Depth];
+			else if (VDisplay == 400)
+				ModeIndex = ModeIndex_640x400[Depth];
+			break;
+		case 720:
+			if (VDisplay == 480)
+				ModeIndex = ModeIndex_720x480[Depth];
+			else if (VDisplay == 576)
+				ModeIndex = ModeIndex_720x576[Depth];
+			break;
+		case 768:
+			if (VDisplay == 576)
+				ModeIndex = ModeIndex_768x576[Depth];
+			break;
+		case 800:
+			if (VDisplay == 600)
+				ModeIndex = ModeIndex_800x600[Depth];
+			else if (VDisplay == 480)
+				ModeIndex = ModeIndex_800x480[Depth];
+			break;
+		case 848:
+			if (VDisplay == 480)
+				ModeIndex = ModeIndex_848x480[Depth];
+			break;
+		case 856:
+			if (VDisplay == 480)
+				ModeIndex = ModeIndex_856x480[Depth];
+			break;
+		case 960:
+			if (VDisplay == 540)
+				ModeIndex = ModeIndex_960x540[Depth];
+			else if (VDisplay == 600)
+				ModeIndex = ModeIndex_960x600[Depth];
+			break;
+		case 1024:
+			if (VDisplay == 576)
+				ModeIndex = ModeIndex_1024x576[Depth];
+			else if (VDisplay == 768)
+				ModeIndex = ModeIndex_1024x768[Depth];
+			break;
+		case 1152:
+			if (VDisplay == 864)
+				ModeIndex = ModeIndex_1152x864[Depth];
+			break;
+		case 1280:
+			switch (VDisplay) {
+				case 720:
+					ModeIndex = ModeIndex_1280x720[Depth];
+					break;
+				case 768:
+					ModeIndex = ModeIndex_1280x768[Depth];
+					break;
+				case 1024:
+					ModeIndex = ModeIndex_1280x1024[Depth];
+					break;
+			}
+	}
+
+	return ModeIndex;
+}
+
+/*********************************************/
+/*          HELPER: SetReg, GetReg           */
+/*********************************************/
+
+static void
+SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+			unsigned short index, unsigned short data)
+{
+	sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
+}
+
+static void
+SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
+						unsigned short data)
+{
+	sisusb_setreg(SiS_Pr->sisusb, port, data);
+}
+
+static unsigned char
+SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
+						unsigned short index)
+{
+	u8 data;
+
+	sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
+
+	return data;
+}
+
+static unsigned char
+SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
+{
+	u8 data;
+
+	sisusb_getreg(SiS_Pr->sisusb, port, &data);
+
+	return data;
+}
+
+static void
+SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
+			unsigned short index, unsigned short DataAND,
+						unsigned short DataOR)
+{
+	sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
+}
+
+static void
+SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
+			unsigned short index, unsigned short DataAND)
+{
+	sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
+}
+
+static void
+SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
+			unsigned short index, unsigned short DataOR)
+{
+	sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
+}
+
+/*********************************************/
+/*      HELPER: DisplayOn, DisplayOff        */
+/*********************************************/
+
+static void
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
+{
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
+}
+
+/*********************************************/
+/*        HELPER: Init Port Addresses        */
+/*********************************************/
+
+void
+SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
+{
+	SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
+	SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
+	SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
+	SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
+	SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
+	SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
+	SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
+	SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+	SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+	SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+	SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+	SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
+	SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
+	SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
+	SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+}
+
+/*********************************************/
+/*             HELPER: GetSysFlags           */
+/*********************************************/
+
+static void
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
+{
+	SiS_Pr->SiS_MyCR63 = 0x63;
+}
+
+/*********************************************/
+/*         HELPER: Init PCI & Engines        */
+/*********************************************/
+
+static void
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
+{
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
+	/*  - Enable 2D (0x40)
+	 *  - Enable 3D (0x02)
+	 *  - Enable 3D vertex command fetch (0x10)
+	 *  - Enable 3D command parser (0x08)
+	 *  - Enable 3D G/L transformation engine (0x80)
+	 */
+	SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
+}
+
+/*********************************************/
+/*        HELPER: SET SEGMENT REGISTERS      */
+/*********************************************/
+
+static void
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+	unsigned short temp;
+
+	value &= 0x00ff;
+	temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
+	temp |= (value >> 4);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+	temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
+	temp |= (value & 0x0f);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+	unsigned short temp;
+
+	value &= 0x00ff;
+	temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
+	temp |= (value & 0xf0);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
+	temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
+	temp |= (value << 4);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
+}
+
+static void
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+	SiS_SetSegRegLower(SiS_Pr, value);
+	SiS_SetSegRegUpper(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
+{
+	SiS_SetSegmentReg(SiS_Pr, 0);
+}
+
+static void
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
+{
+	unsigned short temp = value >> 8;
+
+	temp &= 0x07;
+	temp |= (temp << 4);
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
+	SiS_SetSegmentReg(SiS_Pr, value);
+}
+
+static void
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
+{
+	SiS_SetSegmentRegOver(SiS_Pr, 0);
+}
+
+static void
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
+{
+	SiS_ResetSegmentReg(SiS_Pr);
+	SiS_ResetSegmentRegOver(SiS_Pr);
+}
+
+/*********************************************/
+/*           HELPER: SearchModeID            */
+/*********************************************/
+
+static int
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+						unsigned short *ModeIdIndex)
+{
+	if ((*ModeNo) <= 0x13) {
+
+		if ((*ModeNo) != 0x03)
+			return 0;
+
+		(*ModeIdIndex) = 0;
+
+	} else {
+
+		for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
+
+			if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
+				break;
+
+			if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+				return 0;
+		}
+
+	}
+
+	return 1;
+}
+
+/*********************************************/
+/*            HELPER: ENABLE CRT1            */
+/*********************************************/
+
+static void
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
+{
+	/* Enable CRT1 gating */
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
+}
+
+/*********************************************/
+/*           HELPER: GetColorDepth           */
+/*********************************************/
+
+static unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex)
+{
+	static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
+	unsigned short modeflag;
+	short index;
+
+	if (ModeNo <= 0x13) {
+		modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	} else {
+		modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	}
+
+	index = (modeflag & ModeTypeMask) - ModeEGA;
+	if (index < 0) index = 0;
+	return ColorDepth[index];
+}
+
+/*********************************************/
+/*             HELPER: GetOffset             */
+/*********************************************/
+
+static unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+		unsigned short ModeIdIndex, unsigned short rrti)
+{
+	unsigned short xres, temp, colordepth, infoflag;
+
+	infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+	xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
+
+	colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+	temp = xres / 16;
+
+	if (infoflag & InterlaceMode)
+		temp <<= 1;
+
+	temp *= colordepth;
+
+	if (xres % 16)
+		temp += (colordepth >> 1);
+
+	return temp;
+}
+
+/*********************************************/
+/*                   SEQ                     */
+/*********************************************/
+
+static void
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+	unsigned char SRdata;
+	int i;
+
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
+
+	SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
+
+	for(i = 2; i <= 4; i++) {
+		SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
+	}
+}
+
+/*********************************************/
+/*                  MISC                     */
+/*********************************************/
+
+static void
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+	unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
+
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
+}
+
+/*********************************************/
+/*                  CRTC                     */
+/*********************************************/
+
+static void
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+	unsigned char CRTCdata;
+	unsigned short i;
+
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
+
+	for(i = 0; i <= 0x18; i++) {
+		CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
+	}
+}
+
+/*********************************************/
+/*                   ATT                     */
+/*********************************************/
+
+static void
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+	unsigned char ARdata;
+	unsigned short i;
+
+	for(i = 0; i <= 0x13; i++) {
+		ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
+		SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+		SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
+		SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
+	}
+	SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
+
+	SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
+	SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
+}
+
+/*********************************************/
+/*                   GRC                     */
+/*********************************************/
+
+static void
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
+{
+	unsigned char GRdata;
+	unsigned short i;
+
+	for(i = 0; i <= 0x08; i++) {
+		GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
+	}
+
+	if (SiS_Pr->SiS_ModeType > ModeVGA) {
+		/* 256 color disable */
+		SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
+	}
+}
+
+/*********************************************/
+/*          CLEAR EXTENDED REGISTERS         */
+/*********************************************/
+
+static void
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+	int i;
+
+	for(i = 0x0A; i <= 0x0E; i++) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
+	}
+
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
+}
+
+/*********************************************/
+/*              Get rate index               */
+/*********************************************/
+
+static unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+					unsigned short ModeIdIndex)
+{
+	unsigned short rrti, i, index, temp;
+
+	if (ModeNo <= 0x13)
+		return 0xFFFF;
+
+	index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
+	if (index > 0) index--;
+
+	rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+	ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
+
+	i = 0;
+	do {
+		if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
+			break;
+
+		temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
+		if (temp < SiS_Pr->SiS_ModeType)
+			break;
+
+		i++;
+		index--;
+	} while(index != 0xFFFF);
+
+	i--;
+
+	return (rrti + i);
+}
+
+/*********************************************/
+/*                  SYNC                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
+{
+	unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
+	sync &= 0xC0;
+	sync |= 0x2f;
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
+}
+
+/*********************************************/
+/*                  CRTC/2                   */
+/*********************************************/
+
+static void
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex, unsigned short rrti)
+{
+	unsigned char  index;
+	unsigned short temp, i, j, modeflag;
+
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+	index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
+
+	for(i = 0,j = 0; i <= 7; i++, j++) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+				SiS_Pr->SiS_CRT1Table[index].CR[i]);
+	}
+	for(j = 0x10; i <= 10; i++, j++) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+				SiS_Pr->SiS_CRT1Table[index].CR[i]);
+	}
+	for(j = 0x15; i <= 12; i++, j++) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
+				SiS_Pr->SiS_CRT1Table[index].CR[i]);
+	}
+	for(j = 0x0A; i <= 15; i++, j++) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
+				SiS_Pr->SiS_CRT1Table[index].CR[i]);
+	}
+
+	temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+	SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
+
+	temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+	if (modeflag & DoubleScanMode)  temp |= 0x80;
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
+
+	if (SiS_Pr->SiS_ModeType > ModeVGA)
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
+}
+
+/*********************************************/
+/*               OFFSET & PITCH              */
+/*********************************************/
+/*  (partly overruled by SetPitch() in XF86) */
+/*********************************************/
+
+static void
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex, unsigned short rrti)
+{
+	unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+	unsigned short infoflag =  SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+	unsigned short temp;
+
+	temp = (du >> 8) & 0x0f;
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
+
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
+
+	if (infoflag & InterlaceMode) du >>= 1;
+
+	du <<= 5;
+	temp = (du >> 8) & 0xff;
+	if (du & 0xff) temp++;
+	temp++;
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
+}
+
+/*********************************************/
+/*                  VCLK                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+						unsigned short rrti)
+{
+	unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+	unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+	unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+	SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
+	SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
+	SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
+}
+
+/*********************************************/
+/*                  FIFO                     */
+/*********************************************/
+
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+							unsigned short mi)
+{
+	unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+	/* disable auto-threshold */
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
+
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
+
+	if (ModeNo <= 0x13)
+		return;
+
+	if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
+		SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
+	}
+}
+
+/*********************************************/
+/*              MODE REGISTERS               */
+/*********************************************/
+
+static void
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+							unsigned short rrti)
+{
+	unsigned short data = 0, VCLK = 0, index = 0;
+
+	if (ModeNo > 0x13) {
+		index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
+		VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+	}
+
+	if (VCLK >= 166) data |= 0x0c;
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
+
+	if (VCLK >= 166)
+		SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
+
+	/* DAC speed */
+	data = 0x03;
+	if (VCLK >= 260)
+		data = 0x00;
+	else if (VCLK >= 160)
+		data = 0x01;
+	else if (VCLK >= 135)
+		data = 0x02;
+
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+			unsigned short ModeIdIndex, unsigned short rrti)
+{
+	unsigned short data, infoflag = 0, modeflag;
+
+	if (ModeNo <= 0x13)
+		modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else {
+		modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
+	}
+
+	/* Disable DPMS */
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
+
+	data = 0;
+	if (ModeNo > 0x13) {
+		if (SiS_Pr->SiS_ModeType > ModeEGA) {
+			data |= 0x02;
+			data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+		}
+		if (infoflag & InterlaceMode) data |= 0x20;
+	}
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
+
+	data = 0;
+	if (infoflag & InterlaceMode) {
+		/* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+		unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
+			((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
+		unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
+			((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
+		data = hrs - (hto >> 1) + 3;
+	}
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
+
+	if (modeflag & HalfDCLK)
+		SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
+
+	data = 0;
+	if (modeflag & LineCompareOff)
+		data = 0x08;
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
+
+	if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
+		SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
+
+	SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
+
+	data = 0x60;
+	if (SiS_Pr->SiS_ModeType != ModeText) {
+		data ^= 0x60;
+		if (SiS_Pr->SiS_ModeType != ModeEGA)
+			data ^= 0xA0;
+	}
+	SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
+
+	SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
+
+	if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
+	else
+		SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
+}
+
+/*********************************************/
+/*                 LOAD DAC                  */
+/*********************************************/
+
+static void
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
+		unsigned short shiftflag, unsigned short dl, unsigned short ah,
+		unsigned short al, unsigned short dh)
+{
+	unsigned short d1, d2, d3;
+
+	switch (dl) {
+		case  0:
+			d1 = dh; d2 = ah; d3 = al;
+			break;
+		case  1:
+			d1 = ah; d2 = al; d3 = dh;
+			break;
+		default:
+			d1 = al; d2 = dh; d3 = ah;
+	}
+	SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
+	SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
+	SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
+}
+
+static void
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
+{
+	unsigned short data, data2, time, i, j, k, m, n, o;
+	unsigned short si, di, bx, sf;
+	unsigned long DACAddr, DACData;
+	const unsigned char *table = NULL;
+
+	if (ModeNo < 0x13)
+		data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
+	else
+		data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
+
+	data &= DACInfoFlag;
+
+	j = time = 64;
+	if (data == 0x00)
+		table = SiS_MDA_DAC;
+	else if (data == 0x08)
+		table = SiS_CGA_DAC;
+	else if (data == 0x10)
+		table = SiS_EGA_DAC;
+	else {
+		j = 16;
+		time = 256;
+		table = SiS_VGA_DAC;
+	}
+
+	DACAddr = SiS_Pr->SiS_P3c8;
+	DACData = SiS_Pr->SiS_P3c9;
+	sf = 0;
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+	SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
+
+	for(i = 0; i < j; i++) {
+		data = table[i];
+		for(k = 0; k < 3; k++) {
+			data2 = 0;
+			if (data & 0x01) data2 += 0x2A;
+			if (data & 0x02) data2 += 0x15;
+			SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
+			data >>= 2;
+		}
+	}
+
+	if (time == 256) {
+		for(i = 16; i < 32; i++) {
+			data = table[i] << sf;
+			for(k = 0; k < 3; k++)
+				SiS_SetRegByte(SiS_Pr, DACData, data);
+		}
+		si = 32;
+		for(m = 0; m < 9; m++) {
+			di = si;
+			bx = si + 4;
+			for(n = 0; n < 3; n++) {
+				for(o = 0; o < 5; o++) {
+					SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+						table[di], table[bx], table[si]);
+					si++;
+				}
+				si -= 2;
+				for(o = 0; o < 3; o++) {
+					SiS_WriteDAC(SiS_Pr, DACData, sf, n,
+						table[di], table[si], table[bx]);
+					si--;
+				}
+			}
+		si += 5;
+		}
+	}
+}
+
+/*********************************************/
+/*         SET CRT1 REGISTER GROUP           */
+/*********************************************/
+
+static void
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+					unsigned short ModeIdIndex)
+{
+	unsigned short StandTableIndex, rrti;
+
+	SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+	if (ModeNo <= 0x13)
+		StandTableIndex = 0;
+	else
+		StandTableIndex = 1;
+
+	SiS_ResetSegmentRegisters(SiS_Pr);
+	SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+	SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+	SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+	SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+	SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+	SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+
+	rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+	if (rrti != 0xFFFF) {
+		SiS_SetCRT1Sync(SiS_Pr, rrti);
+		SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+		SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+		SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
+	}
+
+	SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
+
+	SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
+
+	SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
+
+	SiS_DisplayOn(SiS_Pr);
+}
+
+/*********************************************/
+/*                 SiSSetMode()              */
+/*********************************************/
+
+int
+SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
+{
+	unsigned short ModeIdIndex;
+	unsigned long  BaseAddr = SiS_Pr->IOAddress;
+
+	SiSUSB_InitPtr(SiS_Pr);
+	SiSUSBRegInit(SiS_Pr, BaseAddr);
+	SiS_GetSysFlags(SiS_Pr);
+
+	if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
+		return 0;
+
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
+
+	SiSInitPCIetc(SiS_Pr);
+
+	ModeNo &= 0x7f;
+
+	SiS_Pr->SiS_ModeType =
+		SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
+
+	SiS_Pr->SiS_SetFlag = LowModeTests;
+
+	/* Set mode on CRT1 */
+	SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
+
+	SiS_HandleCRT1(SiS_Pr);
+
+	SiS_DisplayOn(SiS_Pr);
+	SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
+
+	/* Store mode number */
+	SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
+
+	return 1;
+}
+
+int
+SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
+{
+	unsigned short ModeNo = 0;
+	int i;
+
+	SiSUSB_InitPtr(SiS_Pr);
+
+	if (VModeNo == 0x03) {
+
+		ModeNo = 0x03;
+
+	} else {
+
+		i = 0;
+		do {
+
+			if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
+				ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
+				break;
+			}
+
+		} while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
+
+	}
+
+	if (!ModeNo)
+		return 0;
+
+	return SiSUSBSetMode(SiS_Pr, ModeNo);
+}
+
+#endif /* INCL_SISUSB_CON */
+
+
+
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
new file mode 100644
index 0000000..5b11577
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -0,0 +1,830 @@
+/* $XFree86$ */
+/* $XdotOrg$ */
+/*
+ * Data and prototypes for init.c
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * 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 named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_INIT_H_
+#define _SISUSB_INIT_H_
+
+/* SiS_ModeType */
+#define ModeText		0x00
+#define ModeCGA			0x01
+#define ModeEGA			0x02
+#define ModeVGA			0x03
+#define Mode15Bpp		0x04
+#define Mode16Bpp		0x05
+#define Mode24Bpp		0x06
+#define Mode32Bpp		0x07
+
+#define ModeTypeMask		0x07
+#define IsTextMode		0x07
+
+#define DACInfoFlag		0x0018
+#define MemoryInfoFlag		0x01E0
+#define MemorySizeShift		5
+
+/* modeflag */
+#define Charx8Dot		0x0200
+#define LineCompareOff		0x0400
+#define CRT2Mode		0x0800
+#define HalfDCLK		0x1000
+#define NoSupportSimuTV		0x2000
+#define NoSupportLCDScale	0x4000 /* SiS bridge: No scaling possible (no matter what panel) */
+#define DoubleScanMode		0x8000
+
+/* Infoflag */
+#define SupportTV		0x0008
+#define SupportTV1024		0x0800
+#define SupportCHTV 		0x0800
+#define Support64048060Hz	0x0800  /* Special for 640x480 LCD */
+#define SupportHiVision		0x0010
+#define SupportYPbPr750p	0x1000
+#define SupportLCD		0x0020
+#define SupportRAMDAC2		0x0040	/* All           (<= 100Mhz) */
+#define SupportRAMDAC2_135	0x0100  /* All except DH (<= 135Mhz) */
+#define SupportRAMDAC2_162	0x0200  /* B, C          (<= 162Mhz) */
+#define SupportRAMDAC2_202	0x0400  /* C             (<= 202Mhz) */
+#define InterlaceMode		0x0080
+#define SyncPP			0x0000
+#define SyncPN			0x4000
+#define SyncNP			0x8000
+#define SyncNN			0xc000
+
+/* SetFlag */
+#define ProgrammingCRT2		0x0001
+#define LowModeTests		0x0002
+#define LCDVESATiming		0x0008
+#define EnableLVDSDDA		0x0010
+#define SetDispDevSwitchFlag	0x0020
+#define CheckWinDos		0x0040
+#define SetDOSMode		0x0080
+
+/* Index in ModeResInfo table */
+#define SIS_RI_320x200		0
+#define SIS_RI_320x240		1
+#define SIS_RI_320x400		2
+#define SIS_RI_400x300		3
+#define SIS_RI_512x384		4
+#define SIS_RI_640x400		5
+#define SIS_RI_640x480		6
+#define SIS_RI_800x600		7
+#define SIS_RI_1024x768		8
+#define SIS_RI_1280x1024	9
+#define SIS_RI_1600x1200	10
+#define SIS_RI_1920x1440	11
+#define SIS_RI_2048x1536	12
+#define SIS_RI_720x480		13
+#define SIS_RI_720x576		14
+#define SIS_RI_1280x960		15
+#define SIS_RI_800x480		16
+#define SIS_RI_1024x576		17
+#define SIS_RI_1280x720		18
+#define SIS_RI_856x480		19
+#define SIS_RI_1280x768		20
+#define SIS_RI_1400x1050	21
+#define SIS_RI_1152x864		22  /* Up to here SiS conforming */
+#define SIS_RI_848x480		23
+#define SIS_RI_1360x768		24
+#define SIS_RI_1024x600		25
+#define SIS_RI_1152x768		26
+#define SIS_RI_768x576		27
+#define SIS_RI_1360x1024	28
+#define SIS_RI_1680x1050	29
+#define SIS_RI_1280x800		30
+#define SIS_RI_1920x1080	31
+#define SIS_RI_960x540		32
+#define SIS_RI_960x600		33
+
+#define SIS_VIDEO_CAPTURE	0x00 - 0x30
+#define SIS_VIDEO_PLAYBACK	0x02 - 0x30
+#define SIS_CRT2_PORT_04	0x04 - 0x30
+
+/* Mode numbers */
+static const unsigned short ModeIndex_320x200[]   = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[]   = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_400x300[]   = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[]   = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[]   = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[]   = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[]   = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[]   = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[]   = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[]   = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[]   = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[]   = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[]   = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[]   = {0x1d, 0x1e, 0x00, 0x1f};
+static const unsigned short ModeIndex_960x600[]   = {0x20, 0x21, 0x00, 0x22};
+static const unsigned short ModeIndex_1024x768[]  = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[]  = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1152x864[]  = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_1280x720[]  = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x768[]  = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x1024[] = {0x3a, 0x4d, 0x00, 0x65};
+
+static const unsigned char SiS_MDA_DAC[] =
+{
+	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+        0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
+};
+
+static const unsigned char SiS_CGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_EGA_DAC[] =
+{
+        0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
+        0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
+        0x08,0x18,0x0C,0x1C,0x09,0x19,0x0D,0x1D,
+        0x28,0x38,0x2C,0x3C,0x29,0x39,0x2D,0x3D,
+        0x02,0x12,0x06,0x16,0x03,0x13,0x07,0x17,
+        0x22,0x32,0x26,0x36,0x23,0x33,0x27,0x37,
+        0x0A,0x1A,0x0E,0x1E,0x0B,0x1B,0x0F,0x1F,
+        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
+};
+
+static const unsigned char SiS_VGA_DAC[] =
+{
+	0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
+	0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
+	0x00,0x05,0x08,0x0B,0x0E,0x11,0x14,0x18,
+	0x1C,0x20,0x24,0x28,0x2D,0x32,0x38,0x3F,
+	0x00,0x10,0x1F,0x2F,0x3F,0x1F,0x27,0x2F,
+	0x37,0x3F,0x2D,0x31,0x36,0x3A,0x3F,0x00,
+	0x07,0x0E,0x15,0x1C,0x0E,0x11,0x15,0x18,
+	0x1C,0x14,0x16,0x18,0x1A,0x1C,0x00,0x04,
+	0x08,0x0C,0x10,0x08,0x0A,0x0C,0x0E,0x10,
+	0x0B,0x0C,0x0D,0x0F,0x10
+};
+
+static const struct SiS_St SiSUSB_SModeIDTable[] =
+{
+	{0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiSUSB_StResInfo[] =
+{
+	{ 640,400},
+	{ 640,350},
+	{ 720,400},
+	{ 720,350},
+	{ 640,480}
+};
+
+static const struct SiS_ModeResInfo SiSUSB_ModeResInfo[] =
+{
+	{  320, 200, 8, 8},   /* 0x00 */
+	{  320, 240, 8, 8},   /* 0x01 */
+	{  320, 400, 8, 8},   /* 0x02 */
+	{  400, 300, 8, 8},   /* 0x03 */
+	{  512, 384, 8, 8},   /* 0x04 */
+	{  640, 400, 8,16},   /* 0x05 */
+	{  640, 480, 8,16},   /* 0x06 */
+	{  800, 600, 8,16},   /* 0x07 */
+	{ 1024, 768, 8,16},   /* 0x08 */
+	{ 1280,1024, 8,16},   /* 0x09 */
+	{ 1600,1200, 8,16},   /* 0x0a */
+	{ 1920,1440, 8,16},   /* 0x0b */
+	{ 2048,1536, 8,16},   /* 0x0c */
+	{  720, 480, 8,16},   /* 0x0d */
+	{  720, 576, 8,16},   /* 0x0e */
+	{ 1280, 960, 8,16},   /* 0x0f */
+	{  800, 480, 8,16},   /* 0x10 */
+	{ 1024, 576, 8,16},   /* 0x11 */
+	{ 1280, 720, 8,16},   /* 0x12 */
+	{  856, 480, 8,16},   /* 0x13 */
+	{ 1280, 768, 8,16},   /* 0x14 */
+	{ 1400,1050, 8,16},   /* 0x15 */
+	{ 1152, 864, 8,16},   /* 0x16 */
+	{  848, 480, 8,16},   /* 0x17 */
+	{ 1360, 768, 8,16},   /* 0x18 */
+	{ 1024, 600, 8,16},   /* 0x19 */
+	{ 1152, 768, 8,16},   /* 0x1a */
+	{  768, 576, 8,16},   /* 0x1b */
+	{ 1360,1024, 8,16},   /* 0x1c */
+	{ 1680,1050, 8,16},   /* 0x1d */
+	{ 1280, 800, 8,16},   /* 0x1e */
+	{ 1920,1080, 8,16},   /* 0x1f */
+	{  960, 540, 8,16},   /* 0x20 */
+	{  960, 600, 8,16}    /* 0x21 */
+};
+
+static const struct SiS_StandTable SiSUSB_StandTable[] =
+{
+	/* MD_3_400 - mode 0x03 - 400 */
+	{
+		0x50,0x18,0x10,0x1000,
+		{ 0x00,0x03,0x00,0x02 },
+		0x67,
+		{ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+		  0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+		  0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+		  0xff },
+		{ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+		  0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+		  0x0c,0x00,0x0f,0x08 },
+		{ 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00, 0xff }
+	},
+	/* Generic for VGA and higher */
+	{
+		0x00,0x00,0x00,0x0000,
+		{ 0x01,0x0f,0x00,0x0e },
+		0x23,
+		{ 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+		  0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		  0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+		  0xff },
+		{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		  0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+		  0x01,0x00,0x00,0x00 },
+		{ 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, 0xff }
+	}
+};
+
+static const struct SiS_Ext SiSUSB_EModeIDTable[] =
+{
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+	{0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+	{0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x8 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x16 */
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x8  */
+	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x16 */
+	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x8  */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x1d, 4}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x16 */
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x2f, 8}, /* 1280x1024x32 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x32 */
+	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x21,-1}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x24, 5}, /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x1e,-1}, /* 800x480x16 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x27, 6}, /* 1280x768x32 */
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1}, /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x28,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1}, /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x2a,-1},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x1a, 0}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x1b, 2}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x1c, 3}, /* 400x300x32 */
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1}, /* 768x576 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1},
+	{0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x2c,-1},
+	{0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1}, /* 960x540 */
+	{0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1},
+	{0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x2d,-1},
+	{0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1}, /* 960x600 */
+	{0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1},
+	{0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x2e,-1},
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1}, /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x33,-1},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
+};
+
+static const struct SiS_Ext2 SiSUSB_RefIndex[] =
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x0 */
+	{0x0067,0x0e,0x04,0x05,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x1 */
+	{0x0067,0x0f,0x08,0x48,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x2 */
+	{0x0067,0x10,0x07,0x8b,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x3 */
+	{0x0047,0x11,0x0a,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x4 */
+	{0x0047,0x12,0x0d,0x00,0x05,0x30, 800, 600, 0x40, 0x00, 0x00}, /* 0x5 */
+	{0x0047,0x13,0x13,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x6 */
+	{0x0107,0x14,0x1c,0x00,0x05,0x30, 800, 600, 0x20, 0x00, 0x00}, /* 0x7 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x8 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0x9 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xa */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xb */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xc */
+	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xd */
+	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xe */
+	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00}, /* 0xf */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e}, /* 0x10 */
+	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00}, /* 0x11 */
+	{0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00}, /* 0x12 (6f was 03) */
+	{0x0087,0x15,0x06,0x00,0x06,0x38,1024, 768, 0x30, 0x00, 0x00}, /* 0x13 */
+	{0xc877,0x16,0x0b,0x06,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x14 */
+	{0xc067,0x17,0x0f,0x49,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x15 */
+	{0x0067,0x18,0x11,0x00,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x16 */
+	{0x0047,0x19,0x16,0x8c,0x06,0x38,1024, 768, 0x20, 0x00, 0x00}, /* 0x17 */
+	{0x0107,0x1a,0x1b,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x18 */
+	{0x0107,0x1b,0x1f,0x00,0x06,0x38,1024, 768, 0x10, 0x00, 0x00}, /* 0x19 */
+	{0x407f,0x00,0x00,0x00,0x00,0x41, 320, 200, 0x30, 0x56, 0x4e}, /* 0x1a */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00}, /* 0x1b */
+	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00}, /* 0x1c */
+	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00}, /* 0x1d */
+	{0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1e */
+	{0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x1f */
+	{0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00}, /* 0x20 */
+	{0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x21 */
+	{0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x22 */
+	{0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00}, /* 0x23 */
+	{0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x24 */
+	{0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x25 */
+	{0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00}, /* 0x26 */
+	{0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00}, /* 0x27 */
+	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x28 38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00}, /* 0x29 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2a 856x480-38Hzi  */
+	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00}, /* 0x2b 856x480-60Hz   */
+	{0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00}, /* 0x2c 768x576-56Hz   */
+	{0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00}, /* 0x2d 960x540 60Hz */
+	{0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00}, /* 0x2e 960x600 60Hz */
+	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00}, /* 0x2f */
+	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x30 */
+	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x31 */
+	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00}, /* 0x32 */
+	{0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x33 1152x864-60Hz  */
+	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x34 1152x864-75Hz  */
+	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00}, /* 0x35 1152x864-85Hz  */
+	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiSUSB_CRT1Table[] =
+{
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
+   0x00}}, /* 0x0 */
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}, /* 0x1 */
+ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+   0x01}}, /* 0x2 */
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+   0x01}}, /* 0x3 */
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+   0x00}}, /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}}, /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,
+   0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
+   0x00}}, /* 0x6 */
+ {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
+   0x00}}, /* 0x7 */
+ {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+   0x00}}, /* 0x8 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
+   0x61}}, /* 0x9 */
+ {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
+   0x61}}, /* 0xa */
+ {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,
+   0x61}}, /* 0xb */
+ {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,
+   0x00}}, /* 0xc */
+ {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
+   0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
+   0x01}}, /* 0xd */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
+   0x01}}, /* 0xe */
+ {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
+   0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
+   0x01}}, /* 0xf */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
+   0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
+   0x01}}, /* 0x10 */
+ {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
+   0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
+   0x01}}, /* 0x11 */
+ {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
+   0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
+   0x61}}, /* 0x12 */
+ {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
+   0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
+   0x61}}, /* 0x13 */
+ {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
+   0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
+   0x61}}, /* 0x14 */
+ {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
+   0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
+   0x00}}, /* 0x15 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}}, /* 0x16 */
+ {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}}, /* 0x17 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
+   0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
+   0x01}}, /* 0x18 */
+ {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
+   0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
+   0x01}}, /* 0x19 */
+ {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
+   0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
+   0x62}}, /* 0x1a */
+ {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
+   0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
+   0x62}}, /* 0x1b */
+ {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
+   0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
+   0x00}}, /* 0x1c */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}}, /* 0x1d */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
+   0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
+   0x01}}, /* 0x1e */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
+   0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
+   0x01}}, /* 0x1f */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x20 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x21 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x22 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x23 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x24 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x25 */
+ {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
+   0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
+   0x00}}, /* 0x26 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x27 */
+ {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
+   0x63}}, /* 0x28 */
+ {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
+   0x63}}, /* 0x29 */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2a */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2b */
+ {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
+   0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
+   0x00}}, /* 0x2c */
+ {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
+   0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
+   0x44}}, /* 0x2d */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
+   0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
+   0x44}}, /* 0x2e */
+ {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
+   0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
+   0x44}}, /* 0x2f */
+ {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
+   0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
+   0x44}}, /* 0x30 */
+ {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
+   0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
+   0x00}}, /* 0x31 */
+ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
+   0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+   0x01}}, /* 0x32 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+   0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
+   0x01}}, /* 0x33 */
+ {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
+   0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
+   0x01}}, /* 0x34 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
+   0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
+   0x01}}, /* 0x35 */
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+   0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+   0x01}}, /* 0x36 */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,
+   0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+   0x01}}, /* 0x37 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x38 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
+   0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
+   0x01}}, /* 0x39 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+   0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+   0x01}}, /* 0x3a */
+ {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,
+   0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
+   0x01}}, /* 0x3b */
+ {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+   0x00}}, /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}}, /* 0x3d */
+ {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
+   0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
+   0x00}}, /* 0x3e */
+ {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
+   0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
+   0x00}}, /* 0x3f */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+   0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+   0x01}},  /* 0x40 */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+   0x01}},  /* 0x41 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,
+   0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
+   0x01}},  /* 0x42 */
+ {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
+   0x00}},  /* 0x43 */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef,
+   0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+   0x01}},  /* 0x44 */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15,
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x45 */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E,
+   0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+   0x00}},  /* 0x46 */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15,
+   0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+   0x00}},  /* 0x47 */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E,
+   0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+   0x00}},  /* 0x48 */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd,
+   0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+   0x01}},  /* 0x49 */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff,
+   0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+   0x01}},  /* 0x4a */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10,
+   0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
+   0x00}},  /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff,
+   0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+   0x01}},  /* 0x4c */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},
+ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff,
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10,
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}},  /* 0x50 */
+ {{0x0e,0xef,0xef,0x92,0xfe,0x03,0x30,0xf0,
+   0x1e,0x83,0x1b,0x1c,0x31,0x00,0x01,0x00,
+   0x61}},  /* 0x51 */
+ {{0x85,0x77,0x77,0x89,0x7d,0x01,0x31,0xf0,
+   0x1e,0x84,0x1b,0x1c,0x32,0x00,0x00,0x02,
+   0x41}},  /* 0x52 */
+ {{0x87,0x77,0x77,0x8b,0x81,0x0b,0x68,0xf0,
+   0x5a,0x80,0x57,0x57,0x69,0x00,0x00,0x02,
+   0x01}},  /* 0x53 */
+ {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,
+   0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
+   0x41}}   /* 0x54 */
+};
+
+static struct SiS_VCLKData SiSUSB_VCLKData[] =
+{
+	{ 0x1b,0xe1, 25}, /* 0x00 */
+	{ 0x4e,0xe4, 28}, /* 0x01 */
+	{ 0x57,0xe4, 31}, /* 0x02 */
+	{ 0xc3,0xc8, 36}, /* 0x03 */
+	{ 0x42,0xe2, 40}, /* 0x04 */
+	{ 0xfe,0xcd, 43}, /* 0x05 */
+	{ 0x5d,0xc4, 44}, /* 0x06 */
+	{ 0x52,0xe2, 49}, /* 0x07 */
+	{ 0x53,0xe2, 50}, /* 0x08 */
+	{ 0x74,0x67, 52}, /* 0x09 */
+	{ 0x6d,0x66, 56}, /* 0x0a */
+	{ 0x5a,0x64, 65}, /* 0x0b */
+	{ 0x46,0x44, 67}, /* 0x0c */
+	{ 0xb1,0x46, 68}, /* 0x0d */
+	{ 0xd3,0x4a, 72}, /* 0x0e */
+	{ 0x29,0x61, 75}, /* 0x0f */
+	{ 0x6e,0x46, 76}, /* 0x10 */
+	{ 0x2b,0x61, 78}, /* 0x11 */
+	{ 0x31,0x42, 79}, /* 0x12 */
+	{ 0xab,0x44, 83}, /* 0x13 */
+	{ 0x46,0x25, 84}, /* 0x14 */
+	{ 0x78,0x29, 86}, /* 0x15 */
+	{ 0x62,0x44, 94}, /* 0x16 */
+	{ 0x2b,0x41,104}, /* 0x17 */
+	{ 0x3a,0x23,105}, /* 0x18 */
+	{ 0x70,0x44,108}, /* 0x19 */
+	{ 0x3c,0x23,109}, /* 0x1a */
+	{ 0x5e,0x43,113}, /* 0x1b */
+	{ 0xbc,0x44,116}, /* 0x1c */
+	{ 0xe0,0x46,132}, /* 0x1d */
+	{ 0x54,0x42,135}, /* 0x1e */
+	{ 0xea,0x2a,139}, /* 0x1f */
+	{ 0x41,0x22,157}, /* 0x20 */
+	{ 0x70,0x24,162}, /* 0x21 */
+	{ 0x30,0x21,175}, /* 0x22 */
+	{ 0x4e,0x22,189}, /* 0x23 */
+	{ 0xde,0x26,194}, /* 0x24 */
+	{ 0x62,0x06,202}, /* 0x25 */
+	{ 0x3f,0x03,229}, /* 0x26 */
+	{ 0xb8,0x06,234}, /* 0x27 */
+	{ 0x34,0x02,253}, /* 0x28 */
+	{ 0x58,0x04,255}, /* 0x29 */
+	{ 0x24,0x01,265}, /* 0x2a */
+	{ 0x9b,0x02,267}, /* 0x2b */
+	{ 0x70,0x05,270}, /* 0x2c */
+	{ 0x25,0x01,272}, /* 0x2d */
+	{ 0x9c,0x02,277}, /* 0x2e */
+	{ 0x27,0x01,286}, /* 0x2f */
+	{ 0x3c,0x02,291}, /* 0x30 */
+	{ 0xef,0x0a,292}, /* 0x31 */
+	{ 0xf6,0x0a,310}, /* 0x32 */
+	{ 0x95,0x01,315}, /* 0x33 */
+	{ 0xf0,0x09,324}, /* 0x34 */
+	{ 0xfe,0x0a,331}, /* 0x35 */
+	{ 0xf3,0x09,332}, /* 0x36 */
+	{ 0xea,0x08,340}, /* 0x37 */
+	{ 0xe8,0x07,376}, /* 0x38 */
+	{ 0xde,0x06,389}, /* 0x39 */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
+	{ 0x31,0xc2, 39}, /* 0x40 */
+	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
+	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
+	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x44 */
+	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
+	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
+	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
+	{ 0xce,0x3c, 39}, /* 0x49 */
+	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
+	{ 0x34,0x61, 95}, /* 0x4b */
+	{ 0x78,0x27,108}, /* 0x4c - was 102 */
+	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
+	{ 0x41,0x4e, 21}, /* 0x4e */
+	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
+	{ 0x19,0x42, 42}, /* 0x50 */
+	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
+	{ 0x25,0x42, 61}, /* 0x52 */
+	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
+	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
+	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
+	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
+	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
+	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
+	{ 0x52,0x27, 75}, /* 0x69 1920x1080i 60Hz interlaced */
+	{ 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
+	{ 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
+	{ 0x45,0x25, 83}, /* 0x6c 1280x800 */
+	{ 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+	{ 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+	{ 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+	{ 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+	{ 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
+};
+
+void		SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
+unsigned short	SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
+int		SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+int		SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
+
+extern int	sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
+extern int	sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
+extern int	sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port,
+					u8 index, u8 data);
+extern int	sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port,
+					u8 index, u8 *data);
+extern int	sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port,
+					u8 idx,	u8 myand, u8 myor);
+extern int	sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port,
+					u8 index, u8 myor);
+extern int	sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
+					u8 idx, u8 myand);
+
+#endif
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
new file mode 100644
index 0000000..94edd47
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -0,0 +1,169 @@
+/*
+ * General structure definitions for universal mode switching modules
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, the following license terms
+ * apply:
+ *
+ * * 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 named License,
+ * * or any later version.
+ * *
+ * * This program is distributed in the hope that it will be useful,
+ * * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * * GNU General Public License for more details.
+ * *
+ * * You should have received a copy of the GNU General Public License
+ * * along with this program; if not, write to the Free Software
+ * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_STRUCT_H_
+#define _SISUSB_STRUCT_H_
+
+struct SiS_St {
+	unsigned char	St_ModeID;
+	unsigned short	St_ModeFlag;
+	unsigned char	St_StTableIndex;
+	unsigned char	St_CRT2CRTC;
+	unsigned char	St_ResInfo;
+	unsigned char	VB_StTVFlickerIndex;
+	unsigned char	VB_StTVEdgeIndex;
+	unsigned char	VB_StTVYFilterIndex;
+	unsigned char	St_PDC;
+};
+
+struct SiS_StandTable
+{
+	unsigned char	CRT_COLS;
+	unsigned char	ROWS;
+	unsigned char	CHAR_HEIGHT;
+	unsigned short	CRT_LEN;
+	unsigned char	SR[4];
+	unsigned char	MISC;
+	unsigned char	CRTC[0x19];
+	unsigned char	ATTR[0x14];
+	unsigned char	GRC[9];
+};
+
+struct SiS_StResInfo_S {
+	unsigned short	HTotal;
+	unsigned short	VTotal;
+};
+
+struct SiS_Ext
+{
+	unsigned char	Ext_ModeID;
+	unsigned short	Ext_ModeFlag;
+	unsigned short	Ext_VESAID;
+	unsigned char	Ext_RESINFO;
+	unsigned char	VB_ExtTVFlickerIndex;
+	unsigned char	VB_ExtTVEdgeIndex;
+	unsigned char	VB_ExtTVYFilterIndex;
+	unsigned char	VB_ExtTVYFilterIndexROM661;
+	unsigned char	REFindex;
+	char		ROMMODEIDX661;
+};
+
+struct SiS_Ext2
+{
+	unsigned short	Ext_InfoFlag;
+	unsigned char	Ext_CRT1CRTC;
+	unsigned char	Ext_CRTVCLK;
+	unsigned char	Ext_CRT2CRTC;
+	unsigned char	Ext_CRT2CRTC_NS;
+	unsigned char	ModeID;
+	unsigned short	XRes;
+	unsigned short	YRes;
+	unsigned char	Ext_PDC;
+	unsigned char	Ext_FakeCRT2CRTC;
+	unsigned char	Ext_FakeCRT2Clk;
+};
+
+struct SiS_CRT1Table
+{
+	unsigned char	CR[17];
+};
+
+struct SiS_VCLKData
+{
+	unsigned char	SR2B,SR2C;
+	unsigned short	CLOCK;
+};
+
+struct SiS_ModeResInfo
+{
+	unsigned short	HTotal;
+	unsigned short	VTotal;
+	unsigned char	XChar;
+	unsigned char	YChar;
+};
+
+struct SiS_Private
+{
+	void *sisusb;
+
+	unsigned long IOAddress;
+
+	unsigned long SiS_P3c4;
+	unsigned long SiS_P3d4;
+	unsigned long SiS_P3c0;
+	unsigned long SiS_P3ce;
+	unsigned long SiS_P3c2;
+	unsigned long SiS_P3ca;
+	unsigned long SiS_P3c6;
+	unsigned long SiS_P3c7;
+	unsigned long SiS_P3c8;
+	unsigned long SiS_P3c9;
+	unsigned long SiS_P3cb;
+	unsigned long SiS_P3cc;
+	unsigned long SiS_P3cd;
+	unsigned long SiS_P3da;
+	unsigned long SiS_Part1Port;
+
+	unsigned char	SiS_MyCR63;
+	unsigned short	SiS_CRT1Mode;
+	unsigned short	SiS_ModeType;
+	unsigned short	SiS_SetFlag;
+
+	const struct SiS_StandTable	*SiS_StandTable;
+	const struct SiS_St		*SiS_SModeIDTable;
+	const struct SiS_Ext		*SiS_EModeIDTable;
+	const struct SiS_Ext2		*SiS_RefIndex;
+	const struct SiS_CRT1Table	*SiS_CRT1Table;
+	struct SiS_VCLKData		*SiS_VCLKData;
+	const struct SiS_ModeResInfo	*SiS_ModeResInfo;
+};
+
+#endif
+
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index faa7443..03fb70e 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -3,8 +3,8 @@
 /*
  *	uss720.c  --  USS720 USB Parport Cable.
  *
- *	Copyright (C) 1999
- *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *	Copyright (C) 1999, 2005
+ *	    Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
@@ -23,99 +23,236 @@
  *  Based on parport_pc.c
  *
  *  History:
- *   0.1  04.08.99  Created
- *   0.2  07.08.99  Some fixes mainly suggested by Tim Waugh
- *		    Interrupt handling currently disabled because
- *		    usb_request_irq crashes somewhere within ohci.c
- *		    for no apparent reason (that is for me, anyway)
- *		    ECP currently untested
- *   0.3  10.08.99  fixing merge errors
- *   0.4  13.08.99  Added Vendor/Product ID of Brad Hard's cable
- *   0.5  20.09.99  usb_control_msg wrapper used
- *        Nov01.00  usb_device_table support by Adam J. Richter
- *        08.04.01  Identify version on module load.  gb
+ *   0.1  04.08.1999  Created
+ *   0.2  07.08.1999  Some fixes mainly suggested by Tim Waugh
+ *		      Interrupt handling currently disabled because
+ *		      usb_request_irq crashes somewhere within ohci.c
+ *		      for no apparent reason (that is for me, anyway)
+ *		      ECP currently untested
+ *   0.3  10.08.1999  fixing merge errors
+ *   0.4  13.08.1999  Added Vendor/Product ID of Brad Hard's cable
+ *   0.5  20.09.1999  usb_control_msg wrapper used
+ *        Nov01.2000  usb_device_table support by Adam J. Richter
+ *        08.04.2001  Identify version on module load.  gb
+ *   0.6  02.09.2005  Fix "scheduling in interrupt" problem by making save/restore
+ *                    context asynchronous
  *
  */
 
 /*****************************************************************************/
 
+#define DEBUG
+
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <linux/parport.h>
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
 
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.5"
-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_VERSION "v0.6"
+#define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
 #define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
 
 /* --------------------------------------------------------------------- */
 
 struct parport_uss720_private {
 	struct usb_device *usbdev;
-	void *irqhandle;
-	unsigned int irqpipe;
-	unsigned char reg[7];  /* USB registers */
+	struct parport *pp;
+	struct kref ref_count;
+	__u8 reg[7];  /* USB registers */
+	struct list_head asynclist;
+	spinlock_t asynclock;
+};
+
+struct uss720_async_request {
+	struct parport_uss720_private *priv;
+	struct kref ref_count;
+	struct list_head asynclist;
+	struct completion compl;
+	struct urb *urb;
+	struct usb_ctrlrequest dr;
+	__u8 reg[7];
 };
 
 /* --------------------------------------------------------------------- */
 
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+static void destroy_priv(struct kref *kref)
 {
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
+	struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
+
+	usb_put_dev(priv->usbdev);
+	kfree(priv);
+	dbg("destroying priv datastructure");
+}
+
+static void destroy_async(struct kref *kref)
+{
+	struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
+	struct parport_uss720_private *priv = rq->priv;
+	unsigned long flags;
+
+	if (likely(rq->urb))
+		usb_free_urb(rq->urb);
+	spin_lock_irqsave(&priv->asynclock, flags);
+	list_del_init(&rq->asynclist);
+	spin_unlock_irqrestore(&priv->asynclock, flags);
+	kfree(rq);
+	kref_put(&priv->ref_count, destroy_priv);
+}
+
+/* --------------------------------------------------------------------- */
+
+static void async_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+	struct uss720_async_request *rq;
+	struct parport *pp;
+	struct parport_uss720_private *priv;
+
+	rq = urb->context;
+	priv = rq->priv;
+	pp = priv->pp;
+	if (urb->status) {
+		err("async_complete: urb error %d", urb->status);
+	} else if (rq->dr.bRequest == 3) {
+		memcpy(priv->reg, rq->reg, sizeof(priv->reg));
+#if 0
+		dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x",
+		    (unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2],
+		    (unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5],
+		    (unsigned int)priv->reg[6]);
+#endif
+		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
+		if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
+			parport_generic_irq(0, pp, NULL);
+	}
+	complete(&rq->compl);
+	kref_put(&rq->ref_count, destroy_async);
+}
+
+static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
+							 __u8 request, __u8 requesttype, __u16 value, __u16 index,
+							 unsigned int mem_flags)
+{
+	struct usb_device *usbdev;
+	struct uss720_async_request *rq;
+	unsigned long flags;
+	int ret;
+
+	if (!priv)
+		return NULL;
+	usbdev = priv->usbdev;
+	if (!usbdev)
+		return NULL;
+	rq = kmalloc(sizeof(struct uss720_async_request), mem_flags);
+	if (!rq) {
+		err("submit_async_request out of memory");
+		return NULL;
+	}
+	kref_init(&rq->ref_count);
+	INIT_LIST_HEAD(&rq->asynclist);
+	init_completion(&rq->compl);
+	kref_get(&priv->ref_count);
+	rq->priv = priv;
+	rq->urb = usb_alloc_urb(0, mem_flags);
+	if (!rq->urb) {
+		kref_put(&rq->ref_count, destroy_async);
+		err("submit_async_request out of memory");
+		return NULL;
+	}
+	rq->dr.bRequestType = requesttype;
+	rq->dr.bRequest = request;
+	rq->dr.wValue = cpu_to_le16(value);
+	rq->dr.wIndex = cpu_to_le16(index);
+	rq->dr.wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
+	usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
+			     (unsigned char *)&rq->dr,
+			     (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
+	/* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
+	spin_lock_irqsave(&priv->asynclock, flags);
+	list_add_tail(&rq->asynclist, &priv->asynclist);
+	spin_unlock_irqrestore(&priv->asynclock, flags);
+	ret = usb_submit_urb(rq->urb, mem_flags);
+	if (!ret) {
+		kref_get(&rq->ref_count);
+		return rq;
+	}
+	kref_put(&rq->ref_count, destroy_async);
+	err("submit_async_request submit_urb failed with %d", ret);
+	return NULL;
+}
+
+static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
+{
+	struct uss720_async_request *rq;
+	unsigned long flags;
+	unsigned int ret = 0;
+
+	spin_lock_irqsave(&priv->asynclock, flags);
+	list_for_each_entry(rq, &priv->asynclist, asynclist) {
+		usb_unlink_urb(rq->urb);
+		ret++;
+	}
+	spin_unlock_irqrestore(&priv->asynclock, flags);
+	return ret;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, unsigned int mem_flags)
+{
+	struct parport_uss720_private *priv;
+	struct uss720_async_request *rq;
 	static const unsigned char regindex[9] = {
 		4, 0, 1, 5, 5, 0, 2, 3, 6
 	};
 	int ret;
 
-	if (!usbdev)
-		return -1;
-	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
-	if (ret != 7) {
-		printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
-		       (unsigned int)reg, ret);
-		ret = -1;
-	} else {
-#if 0
-		printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
-		       (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
-		       (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
-		       (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
-#endif
-		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
-		if (priv->reg[2] & priv->reg[1] & 0x10)
-			parport_generic_irq(0, pp, NULL);
-		ret = 0;
+	if (!pp)
+		return -EIO;
+	priv = pp->private_data;
+	rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
+	if (!rq) {
+		err("get_1284_register(%u) failed", (unsigned int)reg);
+		return -EIO;
 	}
-	if (val)
+	if (!val) {
+		kref_put(&rq->ref_count, destroy_async);
+		return 0;
+	}
+	if (wait_for_completion_timeout(&rq->compl, HZ)) {
+		ret = rq->urb->status;
 		*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
-	return ret;
+		if (ret)
+			warn("get_1284_register: usb error %d", ret);
+		kref_put(&rq->ref_count, destroy_async);
+		return ret;
+	}
+	warn("get_1284_register timeout");
+	kill_all_async_requests_priv(priv);
+	return -EIO;
 }
 
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, unsigned int mem_flags)
 {
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int ret;
+	struct parport_uss720_private *priv;
+	struct uss720_async_request *rq;
 
-	if (!usbdev)
-		return -1;
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
-	if (ret) {
-		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
-		       (unsigned int)reg, (unsigned int)val, ret);
-	} else {
-#if 0
-		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 
-		       (unsigned int)reg, (unsigned int)val);
-#endif
+	if (!pp)
+		return -EIO;
+	priv = pp->private_data;
+	rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
+	if (!rq) {
+		err("set_1284_register(%u,%u) failed", (unsigned int)reg, (unsigned int)val);
+		return -EIO;
 	}
-	return ret;
+	kref_put(&rq->ref_count, destroy_async);
+	return 0;
 }
 
 /* --------------------------------------------------------------------- */
@@ -132,8 +269,9 @@
 {
 	struct parport_uss720_private *priv = pp->private_data;
 	int mode;
+	__u8 reg;
 
-	if (get_1284_register(pp, 6, NULL))
+	if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
 		return -EIO;
 	/* Bits <7:5> contain the mode. */
 	mode = (priv->reg[2] >> 5) & 0x7;
@@ -153,7 +291,7 @@
 		case ECR_ECP: /* ECP Parallel Port mode */
 			/* Poll slowly. */
 			for (;;) {
-				if (get_1284_register(pp, 6, NULL))
+				if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
 					return -EIO;
 				if (priv->reg[2] & 0x01)
 					break;
@@ -167,7 +305,9 @@
 		}
 	}
 	/* Set the mode. */
-	if (set_1284_register(pp, 6, m << 5))
+	if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
+		return -EIO;
+	if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
 		return -EIO;
 	return 0;
 }
@@ -179,7 +319,7 @@
 {
 	unsigned char stat;
 
-	if (get_1284_register(pp, 1, &stat))
+	if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
 		return 1;
 	return stat & 1;
 }
@@ -205,14 +345,14 @@
 
 static void parport_uss720_write_data(struct parport *pp, unsigned char d)
 {
-	set_1284_register(pp, 0, d);
+	set_1284_register(pp, 0, d, GFP_KERNEL);
 }
 
 static unsigned char parport_uss720_read_data(struct parport *pp)
 {
 	unsigned char ret;
 
-	if (get_1284_register(pp, 0, &ret))
+	if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
 		return 0;
 	return ret;
 }
@@ -222,7 +362,7 @@
 	struct parport_uss720_private *priv = pp->private_data;	
 
 	d = (d & 0xf) | (priv->reg[1] & 0xf0);
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return;
 	priv->reg[1] = d;
 }
@@ -241,7 +381,7 @@
 	mask &= 0x0f;
 	val &= 0x0f;
 	d = (priv->reg[1] & (~mask)) ^ val;
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return 0;
 	priv->reg[1] = d;
 	return d & 0xf;
@@ -251,7 +391,7 @@
 {
 	unsigned char ret;
 
-	if (get_1284_register(pp, 1, &ret))
+	if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
 		return 0;
 	return ret & 0xf8;
 }
@@ -262,7 +402,7 @@
 	unsigned char d;
 
 	d = priv->reg[1] & ~0x10;
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return;
 	priv->reg[1] = d;
 }
@@ -273,7 +413,7 @@
 	unsigned char d;
 
 	d = priv->reg[1] | 0x10;
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return;
 	priv->reg[1] = d;
 }
@@ -284,7 +424,7 @@
 	unsigned char d;
 
 	d = priv->reg[1] & ~0x20;
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return;
 	priv->reg[1] = d;
 }
@@ -295,7 +435,7 @@
 	unsigned char d;
 
 	d = priv->reg[1] | 0x20;
-	if (set_1284_register(pp, 2, d))
+	if (set_1284_register(pp, 2, d, GFP_KERNEL))
 		return;
 	priv->reg[1] = d;
 }
@@ -310,17 +450,23 @@
 {
 	struct parport_uss720_private *priv = pp->private_data;	
 
-	if (get_1284_register(pp, 2, NULL))
+#if 0
+	if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
 		return;
+#endif
 	s->u.pc.ctr = priv->reg[1];
 	s->u.pc.ecr = priv->reg[2];
 }
 
 static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
 {
-	set_1284_register(pp, 2, s->u.pc.ctr);
-	set_1284_register(pp, 6, s->u.pc.ecr);
-	get_1284_register(pp, 2, NULL);
+	struct parport_uss720_private *priv = pp->private_data;
+
+	set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
+	set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
+	get_1284_register(pp, 2, NULL, GFP_ATOMIC);
+	priv->reg[1] = s->u.pc.ctr;
+	priv->reg[2] = s->u.pc.ecr;
 }
 
 static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
@@ -331,7 +477,7 @@
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; got < length; got++) {
-		if (get_1284_register(pp, 4, (char *)buf))
+		if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
 			break;
 		buf++;
 		if (priv->reg[0] & 0x01) {
@@ -352,10 +498,10 @@
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; written < length; written++) {
-		if (set_1284_register(pp, 4, (char *)buf))
+		if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
 			break;
 		((char*)buf)++;
-		if (get_1284_register(pp, 1, NULL))
+		if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
 			break;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
@@ -390,7 +536,7 @@
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; got < length; got++) {
-		if (get_1284_register(pp, 3, (char *)buf))
+		if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
 			break;
 		buf++;
 		if (priv->reg[0] & 0x01) {
@@ -410,10 +556,10 @@
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; written < length; written++) {
-		if (set_1284_register(pp, 3, *(char *)buf))
+		if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
 			break;
 		buf++;
-		if (get_1284_register(pp, 1, NULL))
+		if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
 			break;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
@@ -467,7 +613,7 @@
 	if (change_mode(pp, ECR_ECP))
 		return 0;
 	for (; written < len; written++) {
-		if (set_1284_register(pp, 5, *(char *)buffer))
+		if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
 			break;
 		buffer++;
 	}
@@ -536,93 +682,91 @@
 static int uss720_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
-	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
 	struct usb_host_interface *interface;
 	struct usb_host_endpoint *endpoint;
 	struct parport_uss720_private *priv;
 	struct parport *pp;
+	unsigned char reg;
 	int i;
 
-	printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
-	       le16_to_cpu(usbdev->descriptor.idVendor),
-	       le16_to_cpu(usbdev->descriptor.idProduct));
+	dbg("probe: vendor id 0x%x, device id 0x%x\n",
+	    le16_to_cpu(usbdev->descriptor.idVendor),
+	    le16_to_cpu(usbdev->descriptor.idProduct));
 
 	/* our known interfaces have 3 alternate settings */
-	if (intf->num_altsetting != 3)
+	if (intf->num_altsetting != 3) {
+		usb_put_dev(usbdev);
 		return -ENODEV;
-
+	}
 	i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
-	printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+	dbg("set inteface result %d", i);
 
 	interface = intf->cur_altsetting;
 
 	/*
 	 * Allocate parport interface 
 	 */
-	printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
-
-	if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+	if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+		usb_put_dev(usbdev);
 		return -ENOMEM;
+	}
+	priv->pp = NULL;
+	priv->usbdev = usbdev;
+	kref_init(&priv->ref_count);
+	spin_lock_init(&priv->asynclock);
+	INIT_LIST_HEAD(&priv->asynclist);
 	if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
-		printk(KERN_WARNING "usb-uss720: could not register parport\n");
+		warn("could not register parport");
 		goto probe_abort;
 	}
 
+	priv->pp = pp;
 	pp->private_data = priv;
-	priv->usbdev = usbdev;
 	pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
 
 	/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
-	set_1284_register(pp, 7, 0x00);
-	set_1284_register(pp, 6, 0x30);  /* PS/2 mode */
-	set_1284_register(pp, 2, 0x0c);
+	set_1284_register(pp, 7, 0x00, GFP_KERNEL);
+	set_1284_register(pp, 6, 0x30, GFP_KERNEL);  /* PS/2 mode */
+	set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
 	/* debugging */
-	get_1284_register(pp, 0, NULL);
-	printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
-	       priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+	get_1284_register(pp, 0, &reg, GFP_KERNEL);
+	dbg("reg: %02x %02x %02x %02x %02x %02x %02x",
+	    priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
 
 	endpoint = &interface->endpoint[2];
-	printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
-#if 0
-	priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
-	i = usb_request_irq(usbdev, priv->irqpipe,
-				  uss720_irq, endpoint->bInterval,
-				  pp, &priv->irqhandle);
-	if (i) {
-		printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
-		goto probe_abort_port;
-	}
-#endif
+	dbg("epaddr %d interval %d", endpoint->desc.bEndpointAddress, endpoint->desc.bInterval);
 	parport_announce_port(pp);
 
-	usb_set_intfdata (intf, pp);
+	usb_set_intfdata(intf, pp);
 	return 0;
 
-#if 0
-probe_abort_port:
-	parport_put_port(pp);
-#endif
 probe_abort:
-	kfree(priv);
+	kill_all_async_requests_priv(priv);
+	kref_put(&priv->ref_count, destroy_priv);
 	return -ENODEV;
 }
 
 static void uss720_disconnect(struct usb_interface *intf)
 {
-	struct parport *pp = usb_get_intfdata (intf);
+	struct parport *pp = usb_get_intfdata(intf);
 	struct parport_uss720_private *priv;
+	struct usb_device *usbdev;
 
-	usb_set_intfdata (intf, NULL);
+	dbg("disconnect");
+	usb_set_intfdata(intf, NULL);
 	if (pp) {
 		priv = pp->private_data;
-		parport_remove_port(pp);
-#if 0
-		usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
+		usbdev = priv->usbdev;
 		priv->usbdev = NULL;
+		priv->pp = NULL;
+		dbg("parport_remove_port");
+		parport_remove_port(pp);
 		parport_put_port(pp);
-		kfree(priv);
+		kill_all_async_requests_priv(priv);
+		kref_put(&priv->ref_count, destroy_priv);
 	}
+	dbg("disconnect done");
 }
 
 /* table of cables that work through this driver */
@@ -647,8 +791,8 @@
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static int __init uss720_init(void)
@@ -659,6 +803,9 @@
 		goto out;
 
 	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info("NOTE: this is a special purpose driver to allow nonstandard");
+	info("protocols (eg. bitbang) over USS720 usb to parallel cables");
+	info("If you just want to connect to a printer, use usblp instead");
 out:
 	return retval;
 }
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 417464d..17d0190 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -79,7 +79,7 @@
 		return '-';
 
 	if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
-		return 'D';
+		return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
 	if (urb->setup_packet == NULL)
 		return 'Z';	/* '0' would be not as pretty. */
 
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 4ace996..97c78c2 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -32,7 +32,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.04"
+#define DRIVER_VERSION "v0.05"
 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
 
 /*
@@ -54,8 +54,11 @@
 static int debug;
 
 static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
 	{ USB_DEVICE(0x10C4, 0xEA60) },	/* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0x80CA) },	/* Degree Controls Inc */
+	{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
+	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
 	{ USB_DEVICE(0x10AB, 0x10C5) },	/* Siemens MC60 Cable */
 	{ } /* Terminating Entry */
 };
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 05c44ae..9ee1aaf 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -610,8 +610,7 @@
 		timeout = max((HZ*2560)/bps,HZ/10);
 	else
 		timeout = 2*HZ;
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(timeout);
+	schedule_timeout_interruptible(timeout);
 
 	dbg("%s - stopping urbs", __FUNCTION__);
 	usb_kill_urb (port->interrupt_in_urb);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0a6e8b4..4e434cb 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -914,7 +914,7 @@
 	unsigned interfaces;
 
 	/* Assume it is not the original SIO device for now. */
-	priv->baud_base = 48000000 / 16;
+	priv->baud_base = 48000000 / 2;
 	priv->write_offset = 0;
 
 	version = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 4614741..3cf245b 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -95,6 +95,7 @@
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
 	{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
 	{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
+	{ USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) },
 	{ }					/* Terminating entry */
 };
 
@@ -652,8 +653,7 @@
 		timeout = max((HZ*2560)/bps,HZ/10);
 	else
 		timeout = 2*HZ;
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(timeout);
+	schedule_timeout_interruptible(timeout);
 
 	/* shutdown our urbs */
 	dbg("%s - shutting down urbs", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index b734c40..7be9644 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -58,3 +58,7 @@
 
 #define SYNTECH_VENDOR_ID	0x0745
 #define SYNTECH_PRODUCT_ID	0x0001
+
+/* Nokia CA-42 Cable */
+#define NOKIA_CA42_VENDOR_ID	0x078b
+#define NOKIA_CA42_PRODUCT_ID	0x1234
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d34dc9f..4837524 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -227,42 +227,42 @@
  ***********************************************************************/
 
 /* Command timeout and abort */
-/* This is always called with scsi_lock(host) held */
 static int command_abort(struct scsi_cmnd *srb)
 {
 	struct us_data *us = host_to_us(srb->device->host);
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
+	/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+	 * bits are protected by the host lock. */
+	scsi_lock(us_to_host(us));
+
 	/* Is this command still active? */
 	if (us->srb != srb) {
+		scsi_unlock(us_to_host(us));
 		US_DEBUGP ("-- nothing to abort\n");
 		return FAILED;
 	}
 
 	/* Set the TIMED_OUT bit.  Also set the ABORTING bit, but only if
 	 * a device reset isn't already in progress (to avoid interfering
-	 * with the reset).  To prevent races with auto-reset, we must
-	 * stop any ongoing USB transfers while still holding the host
-	 * lock. */
+	 * with the reset).  Note that we must retain the host lock while
+	 * calling usb_stor_stop_transport(); otherwise it might interfere
+	 * with an auto-reset that begins as soon as we release the lock. */
 	set_bit(US_FLIDX_TIMED_OUT, &us->flags);
 	if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
 		set_bit(US_FLIDX_ABORTING, &us->flags);
 		usb_stor_stop_transport(us);
 	}
+	scsi_unlock(us_to_host(us));
 
 	/* Wait for the aborted command to finish */
 	wait_for_completion(&us->notify);
-
-	/* Reacquire the lock and allow USB transfers to resume */
-	clear_bit(US_FLIDX_ABORTING, &us->flags);
-	clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
 	return SUCCESS;
 }
 
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
-/* This is always called with scsi_lock(host) held */
 static int device_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = host_to_us(srb->device->host);
@@ -279,7 +279,6 @@
 }
 
 /* Simulate a SCSI bus reset by resetting the device's USB port. */
-/* This is always called with scsi_lock(host) held */
 static int bus_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = host_to_us(srb->device->host);
@@ -291,7 +290,6 @@
 	result = usb_stor_port_reset(us);
 	up(&(us->dev_semaphore));
 
-	/* lock the host for the return */
 	return result < 0 ? FAILED : SUCCESS;
 }
 
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index ad0cfd7..b79dad1 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -86,6 +86,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
+ * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
+ * for USB floppies that need the SINGLE_LUN enforcement.
+ */
+UNUSUAL_DEV(  0x0409, 0x0040, 0x0000, 0x9999,
+		"NEC",
+		"NEC USB UF000x",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
+
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
  * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
  * always fails and confuses drive.
@@ -96,6 +106,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
+UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
+		"SMSC",
+		"FDC GOLD-2.30",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN ),
+
 #ifdef CONFIG_USB_STORAGE_DPCM
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
@@ -103,6 +120,24 @@
  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
 #endif
 
+/*
+ * Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
+ * The key does not actually break, but it returns zero sense which
+ * makes our SCSI stack to print confusing messages.
+ */
+UNUSUAL_DEV(  0x0457, 0x0150, 0x0100, 0x0100,
+		"USBest Technology",	/* sold by Transcend */
+		"USB Mass Storage Device",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+
+/* Patch submitted by Daniel Drake <dsd@gentoo.org>
+ * Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
+UNUSUAL_DEV(  0x0451, 0x5416, 0x0100, 0x0100,
+		"Neuros Audio",
+		"USB 2.0 HD 2.5",
+		US_SC_DEVICE, US_PR_BULK, NULL,
+		US_FL_NEED_OVERRIDE ),
+
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index cb4c770..f9a9bfa 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -392,11 +392,16 @@
 		/* If an abort request was received we need to signal that
 		 * the abort has finished.  The proper test for this is
 		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
-		 * a timeout/abort request might be received after all the
-		 * USB processing was complete. */
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags))
+		 * the timeout might have occurred after the command had
+		 * already completed with a different result code. */
+		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
 			complete(&(us->notify));
 
+			/* Allow USB transfers to resume */
+			clear_bit(US_FLIDX_ABORTING, &us->flags);
+			clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+		}
+
 		/* finished working on this command */
 		us->srb = NULL;
 		scsi_unlock(host);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 615874e..31ee13e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -753,7 +753,8 @@
 
 config FB_I810_I2C
 	bool "Enable DDC Support"
-	depends on FB_I810 && I2C && FB_I810_GTF
+	depends on FB_I810 && FB_I810_GTF
+	select I2C
 	select I2C_ALGOBIT
 	help
 
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 353cb3f..a328176 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -43,18 +43,10 @@
 			intensity &= CORGI_LIMIT_MASK;
 	}
 
-	/* Skip 0x20 as it will blank the display */
-	if (intensity >= 0x20)
-		intensity++;
-
 	spin_lock_irqsave(&bl_lock, flags);
-	/* Bits 0-4 are accessed via the SSP interface */
-	corgi_ssp_blduty_set(intensity & 0x1f);
-	/* Bit 5 is via SCOOP */
-	if (intensity & 0x0020)
-		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
-	else
-		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+
+	corgibl_mach_set_intensity(intensity);
+
 	spin_unlock_irqrestore(&bl_lock, flags);
 }
 
@@ -113,8 +105,8 @@
 
 static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
 {
-	if (intensity > CORGI_MAX_INTENSITY)
-		intensity = CORGI_MAX_INTENSITY;
+	if (intensity > corgibl_data.max_brightness)
+		intensity = corgibl_data.max_brightness;
 	corgibl_send_intensity(intensity);
 	current_intensity=intensity;
 	return 0;
@@ -141,7 +133,6 @@
 	.owner		= THIS_MODULE,
 	.get_power      = corgibl_get_power,
 	.set_power      = corgibl_set_power,
-	.max_brightness = CORGI_MAX_INTENSITY,
 	.get_brightness = corgibl_get_intensity,
 	.set_brightness = corgibl_set_intensity,
 };
@@ -150,12 +141,18 @@
 
 static int __init corgibl_probe(struct device *dev)
 {
+	struct corgibl_machinfo *machinfo = dev->platform_data;
+
+	corgibl_data.max_brightness = machinfo->max_intensity;
+	corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+
 	corgi_backlight_device = backlight_device_register ("corgi-bl",
 		NULL, &corgibl_data);
 	if (IS_ERR (corgi_backlight_device))
 		return PTR_ERR (corgi_backlight_device);
 
 	corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
+	corgibl_limit_intensity(0);
 
 	printk("Corgi Backlight Driver Initialized.\n");
 	return 0;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5fe182d..eb83a78 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -137,7 +137,7 @@
 
 config FONT_8x16
 	bool "VGA 8x16 font" if FONTS
-	depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
+	depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y || USB_SISUSBVGA_CON
 	default y if !SPARC32 && !SPARC64 && !FONTS
 	help
 	  This is the "high resolution" font for the VGA frame buffer (the one
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index b562f6b..42c7b8d 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -33,6 +33,10 @@
 
 obj-$(CONFIG_FB_STI)              += sticore.o font.o
 
+ifeq ($(CONFIG_USB_SISUSBVGA_CON),y)
+obj-$(CONFIG_USB_SISUSBVGA)           += font.o
+endif
+
 # Targets that kbuild needs to know about
 targets := promcon_tbl.c
 
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2e93224..0fc8bb4 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -767,7 +767,7 @@
 	const char *display_desc = "frame buffer device";
 	struct display *p = &fb_display[fg_console];
 	struct vc_data *vc = vc_cons[fg_console].d;
-	struct font_desc *font = NULL;
+	const struct font_desc *font = NULL;
 	struct module *owner;
 	struct fb_info *info = NULL;
 	struct fbcon_ops *ops;
@@ -841,7 +841,7 @@
 						info->var.yres);
 		vc->vc_font.width = font->width;
 		vc->vc_font.height = font->height;
-		vc->vc_font.data = p->fontdata = font->data;
+		vc->vc_font.data = (void *)(p->fontdata = font->data);
 		vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */
 	}
 
@@ -941,7 +941,7 @@
 	   fb, copy the font from that console */
 	t = &fb_display[svc->vc_num];
 	if (!vc->vc_font.data) {
-		vc->vc_font.data = p->fontdata = t->fontdata;
+		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
 		vc->vc_font.width = (*default_mode)->vc_font.width;
 		vc->vc_font.height = (*default_mode)->vc_font.height;
 		p->userfont = t->userfont;
@@ -1188,7 +1188,7 @@
 		return;
 	t = &fb_display[svc->vc_num];
 	if (!vc->vc_font.data) {
-		vc->vc_font.data = p->fontdata = t->fontdata;
+		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
 		vc->vc_font.width = (*default_mode)->vc_font.width;
 		vc->vc_font.height = (*default_mode)->vc_font.height;
 		p->userfont = t->userfont;
@@ -1687,6 +1687,8 @@
 	case SM_DOWN:
 		if (count > vc->vc_rows)	/* Maximum realistic size */
 			count = vc->vc_rows;
+		if (logo_shown >= 0)
+			goto redraw_down;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
 			ops->bmove(vc, info, t, 0, t + count, 0,
@@ -2148,7 +2150,7 @@
 }
 
 static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
-			     u8 * data, int userfont)
+			     const u8 * data, int userfont)
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
@@ -2166,7 +2168,7 @@
 		cnt = FNTCHARCNT(data);
 	else
 		cnt = 256;
-	vc->vc_font.data = p->fontdata = data;
+	vc->vc_font.data = (void *)(p->fontdata = data);
 	if ((p->userfont = userfont))
 		REFCOUNT(data)++;
 	vc->vc_font.width = w;
@@ -2323,7 +2325,7 @@
 		    tmp->vc_font.width == w &&
 		    !memcmp(fb_display[i].fontdata, new_data, size)) {
 			kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
-			new_data = fb_display[i].fontdata;
+			new_data = (u8 *)fb_display[i].fontdata;
 			break;
 		}
 	}
@@ -2333,7 +2335,7 @@
 static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-	struct font_desc *f;
+	const struct font_desc *f;
 
 	if (!name)
 		f = get_default_font(info->var.xres, info->var.yres);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 08befaf..0738cd6 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -30,7 +30,7 @@
     /* Filled in by the frame buffer device */
     u_short inverse;                /* != 0 text black on white as default */
     /* Filled in by the low-level console driver */
-    u_char *fontdata;
+    const u_char *fontdata;
     int userfont;                   /* != 0 if fontdata kmalloc()ed */
     u_short scrollmode;             /* Scroll Method */
     short yscroll;                  /* Hardware scrolling */
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index ff0af96..e6aa0ea 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -7,7 +7,7 @@
 
 #define FONTDATAMAX 9216
 
-static unsigned char fontdata_10x18[FONTDATAMAX] = {
+static const unsigned char fontdata_10x18[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, 0x00, /* 0000000000 */
@@ -5132,7 +5132,7 @@
 };
 
 
-struct font_desc font_10x18 = {
+const struct font_desc font_10x18 = {
 	FONT10x18_IDX,
 	"10x18",
 	10,
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index c52f129..89976cd 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -8,7 +8,7 @@
 
 #define FONTDATAMAX (11*256)
 
-static unsigned char fontdata_6x11[FONTDATAMAX] = {
+static const unsigned char fontdata_6x11[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, /* 00000000 */
@@ -3341,7 +3341,7 @@
 };
 
 
-struct font_desc font_vga_6x11 = {
+const struct font_desc font_vga_6x11 = {
 	VGA6x11_IDX,
 	"ProFont6x11",
 	6,
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index 1fa7fcf..bbf1166 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -7,7 +7,7 @@
 
 #define FONTDATAMAX 3584
 
-static unsigned char fontdata_7x14[FONTDATAMAX] = {
+static const unsigned char fontdata_7x14[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, /* 0000000 */
@@ -4108,7 +4108,7 @@
 };
 
 
-struct font_desc font_7x14 = {
+const struct font_desc font_7x14 = {
 	FONT7x14_IDX,
 	"7x14",
 	7,
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index e6f8dba..74fe86f 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -8,7 +8,7 @@
 
 #define FONTDATAMAX 4096
 
-static unsigned char fontdata_8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_8x16[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, /* 00000000 */
@@ -4621,7 +4621,7 @@
 };
 
 
-struct font_desc font_vga_8x16 = {
+const struct font_desc font_vga_8x16 = {
 	VGA8x16_IDX,
 	"VGA8x16",
 	8,
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 57fbe26..26199f8 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -8,7 +8,7 @@
 
 #define FONTDATAMAX 2048
 
-static unsigned char fontdata_8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_8x8[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, /* 00000000 */
@@ -2573,7 +2573,7 @@
 };
 
 
-struct font_desc font_vga_8x8 = {
+const struct font_desc font_vga_8x8 = {
 	VGA8x8_IDX,
 	"VGA8x8",
 	8,
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index d565505..2d2e396 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -3,7 +3,7 @@
 #include <linux/config.h>
 #include <linux/font.h>
 
-static unsigned char acorndata_8x8[] = {
+static const unsigned char acorndata_8x8[] = {
 /* 00 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
 /* 01 */  0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
 /* 02 */  0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -262,7 +262,7 @@
 /* FF */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-struct font_desc font_acorn_8x8 = {
+const struct font_desc font_acorn_8x8 = {
 	ACORN8x8_IDX,
 	"Acorn8x8",
 	8,
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 593b955..d818234 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -43,7 +43,7 @@
 
 #define FONTDATAMAX 1536
 
-static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
+static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
 
 	/*{*/
 	  	/*   Char 0: ' '  */
@@ -2147,7 +2147,7 @@
 	/*}*/
 };
 
-struct font_desc font_mini_4x6 = {
+const struct font_desc font_mini_4x6 = {
 	MINI4x6_IDX,
 	"MINI4x6",
 	4,
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index 5fa95f1..e646c88 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -13,7 +13,7 @@
 
 #define FONTDATAMAX 2048
 
-static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
 
    /* 0 0x00 '^@' */
    0x00, /* 00000000 */
@@ -2577,7 +2577,7 @@
 
 };
 
-struct font_desc font_pearl_8x8 = {
+const struct font_desc font_pearl_8x8 = {
 	PEARL8x8_IDX,
 	"PEARL8x8",
 	8,
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index c7bd967..ab5eb93 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -2,7 +2,7 @@
 
 #define FONTDATAMAX 11264
 
-static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
+static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
 	0x00, 0x00, /* 000000000000 */
@@ -6151,7 +6151,7 @@
 };
 
 
-struct font_desc font_sun_12x22 = {
+const struct font_desc font_sun_12x22 = {
 	SUN12x22_IDX,
 	"SUN12x22",
 	12,
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 2af3ab3..41f910f 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -2,7 +2,7 @@
 
 #define FONTDATAMAX 4096
 
-static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
 /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
 /* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00,
@@ -261,7 +261,7 @@
 /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 };
 
-struct font_desc font_sun_8x16 = {
+const struct font_desc font_sun_8x16 = {
 	SUN8x16_IDX,
 	"SUN8x16",
 	8,
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index e79b297..4fd07d9 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -23,7 +23,7 @@
 
 #define NO_FONTS
 
-static struct font_desc *fonts[] = {
+static const struct font_desc *fonts[] = {
 #ifdef CONFIG_FONT_8x8
 #undef NO_FONTS
     &font_vga_8x8,
@@ -84,7 +84,7 @@
  *
  */
 
-struct font_desc *find_font(char *name)
+const struct font_desc *find_font(const char *name)
 {
    unsigned int i;
 
@@ -108,10 +108,10 @@
  *
  */
 
-struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres)
 {
     int i, c, cc;
-    struct font_desc *f, *g;
+    const struct font_desc *f, *g;
 
     g = NULL;
     cc = -10000;
@@ -138,7 +138,6 @@
     return g;
 }
 
-EXPORT_SYMBOL(fonts);
 EXPORT_SYMBOL(find_font);
 EXPORT_SYMBOL(get_default_font);
 
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 7018fff..0dbc9dd 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -95,18 +95,18 @@
 static char *mode_option __devinitdata = NULL;
 static int vram       __devinitdata = 4;
 static int bpp        __devinitdata = 8;
-static int mtrr       __devinitdata = 0;
-static int accel      __devinitdata = 0;
-static int hsync1     __devinitdata = 0;
-static int hsync2     __devinitdata = 0;
-static int vsync1     __devinitdata = 0;
-static int vsync2     __devinitdata = 0;
-static int xres       __devinitdata = 640;
-static int yres       __devinitdata = 480;
-static int vyres      __devinitdata = 0;
-static int sync       __devinitdata = 0;
-static int ext_vga    __devinitdata = 0;
-static int dcolor     __devinitdata = 0;
+static int mtrr       __devinitdata;
+static int accel      __devinitdata;
+static int hsync1     __devinitdata;
+static int hsync2     __devinitdata;
+static int vsync1     __devinitdata;
+static int vsync2     __devinitdata;
+static int xres       __devinitdata;
+static int yres       __devinitdata;
+static int vyres      __devinitdata;
+static int sync       __devinitdata;
+static int extvga     __devinitdata;
+static int dcolor     __devinitdata;
 
 /*------------------------------------------------------------*/
 
@@ -950,7 +950,7 @@
 			     struct fb_info *info)
 {
 	struct i810fb_par *par = (struct i810fb_par *) info->par;
-	int line_length, vidmem, mode_valid = 0;
+	int line_length, vidmem, mode_valid = 0, retval = 0;
 	u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
 	/*
 	 *  Memory limit
@@ -1026,10 +1026,11 @@
 			printk("i810fb: invalid video mode%s\n",
 			       default_sync ? "" : ". Specifying "
 			       "vsyncN/hsyncN parameters may help");
+			retval = -EINVAL;
 		}
 	}
 
-	return 0;
+	return retval;
 }	
 
 /**
@@ -1724,12 +1725,21 @@
 	if (bpp < 8)
 		bpp = 8;
 	
-	if (!vyres) 
-		vyres = (vram << 20)/(xres*bpp >> 3);
-
 	par->i810fb_ops = i810fb_ops;
-	info->var.xres = xres;
-	info->var.yres = yres;
+
+	if (xres)
+		info->var.xres = xres;
+	else
+		info->var.xres = 640;
+
+	if (yres)
+		info->var.yres = yres;
+	else
+		info->var.yres = 480;
+
+	if (!vyres) 
+		vyres = (vram << 20)/(info->var.xres*bpp >> 3);
+
 	info->var.yres_virtual = vyres;
 	info->var.bits_per_pixel = bpp;
 
@@ -1756,7 +1766,7 @@
 	i810_init_cursor(par);
 
 	/* mvo: enable external vga-connector (for laptops) */
-	if (ext_vga) {
+	if (extvga) {
 		i810_writel(HVSYNC, mmio, 0);
 		i810_writel(PWR_CLKC, mmio, 3);
 	}
@@ -1830,7 +1840,7 @@
 {
 	struct fb_videomode mode;
 	struct fb_var_screeninfo var;
-	struct fb_monspecs *specs = NULL;
+	struct fb_monspecs *specs = &info->monspecs;
 	int found = 0;
 #ifdef CONFIG_FB_I810_I2C
 	int i;
@@ -1853,16 +1863,24 @@
 	if (!err)
 		printk("i810fb_init_pci: DDC probe successful\n");
 
-	fb_edid_to_monspecs(par->edid, &info->monspecs);
+	fb_edid_to_monspecs(par->edid, specs);
 
-	if (info->monspecs.modedb == NULL)
+	if (specs->modedb == NULL)
 		printk("i810fb_init_pci: Unable to get Mode Database\n");
 
-	specs = &info->monspecs;
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		if (specs->misc & FB_MISC_1ST_DETAIL) {
+		if (xres && yres) {
+			struct fb_videomode *m;
+
+			if ((m = fb_find_best_mode(&var, &info->modelist))) {
+				mode = *m;
+				found  = 1;
+			}
+		}
+
+		if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
 			for (i = 0; i < specs->modedb_len; i++) {
 				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
 					mode = specs->modedb[i];
@@ -1903,8 +1921,8 @@
 			mtrr = 1;
 		else if (!strncmp(this_opt, "accel", 5))
 			accel = 1;
-		else if (!strncmp(this_opt, "ext_vga", 7))
-			ext_vga = 1;
+		else if (!strncmp(this_opt, "extvga", 6))
+			extvga = 1;
 		else if (!strncmp(this_opt, "sync", 4))
 			sync = 1;
 		else if (!strncmp(this_opt, "vram:", 5))
@@ -2133,8 +2151,8 @@
 MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
 module_param(mtrr, bool, 0);
 MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
 module_param(sync, bool, 0);
 MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
 		 " (default = 0)");
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 98e00d8..e02da41 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1285,7 +1285,7 @@
 	vaddr_t vm;
 	unsigned int offs;
 	unsigned int offs2;
-	unsigned char store;
+	unsigned char store, orig;
 	unsigned char bytes[32];
 	unsigned char* tmp;
 
@@ -1298,7 +1298,8 @@
 	if (maxSize > 0x2000000) maxSize = 0x2000000;
 
 	mga_outb(M_EXTVGA_INDEX, 0x03);
-	mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+	orig = mga_inb(M_EXTVGA_DATA);
+	mga_outb(M_EXTVGA_DATA, orig | 0x80);
 
 	store = mga_readb(vm, 0x1234);
 	tmp = bytes;
@@ -1323,7 +1324,7 @@
 	mga_writeb(vm, 0x1234, store);
 
 	mga_outb(M_EXTVGA_INDEX, 0x03);
-	mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+	mga_outb(M_EXTVGA_DATA, orig);
 
 	*realSize = offs - 0x100000;
 #ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1858,6 +1859,8 @@
 							to yres_virtual * xres_virtual < 2^32 */
 	}
 	matroxfb_init_fix(PMINFO2);
+	ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+	matroxfb_update_fix(PMINFO2);
 	/* Normalize values (namely yres_virtual) */
 	matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
 	/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
@@ -2010,11 +2013,11 @@
 	}
 	/* not match... */
 	if (!b->vendor)
-		return -1;
+		return -ENODEV;
 	if (dev > 0) {
 		/* not requested one... */
 		dev--;
-		return -1;
+		return -ENODEV;
 	}
 	pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
 	if (pci_enable_device(pdev)) {
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index e0dad94..2e11b60 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -67,6 +67,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
+#include <linux/ctype.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
@@ -2594,7 +2595,7 @@
 {
 	char *next;
 
-	if (!(CHAR_IS_NUM(options[0]))) {
+	if (!(isdigit(options[0]))) {
 		(*bn) = 0;
 		return (options);
 	}
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
index b7c24b3..279e0e0 100644
--- a/drivers/w1/w1_ds2433.c
+++ b/drivers/w1/w1_ds2433.c
@@ -15,6 +15,10 @@
 #include <linux/delay.h>
 #ifdef CONFIG_W1_F23_CRC
 #include <linux/crc16.h>
+
+#define CRC16_INIT		0
+#define CRC16_VALID		0xb001
+
 #endif
 
 #include "w1.h"
@@ -214,7 +218,7 @@
 #ifdef CONFIG_W1_F23_CRC
 	/* can only write full blocks in cached mode */
 	if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
-		dev_err(&sl->dev, "invalid offset/count off=%d cnt=%d\n",
+		dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
 			(int)off, count);
 		return -EINVAL;
 	}
diff --git a/fs/namei.c b/fs/namei.c
index 21d85f1..043d587 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1048,7 +1048,7 @@
 out:
 	if (unlikely(current->audit_context
 		     && nd && nd->dentry && nd->dentry->d_inode))
-		audit_inode(name, nd->dentry->d_inode);
+		audit_inode(name, nd->dentry->d_inode, flags);
 	return retval;
 }
 
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e08edc1..361b400 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -162,7 +162,7 @@
 
 
 static inline int
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
 {
 	int status;
 	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -238,8 +238,10 @@
 	 */
 	status = nfsd4_process_open2(rqstp, current_fh, open);
 out:
-	if (open->op_stateowner)
+	if (open->op_stateowner) {
 		nfs4_get_stateowner(open->op_stateowner);
+		*replay_owner = open->op_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 }
@@ -809,8 +811,7 @@
 			op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
 			break;
 		case OP_CLOSE:
-			op->status = nfsd4_close(rqstp, current_fh, &op->u.close);
-			replay_owner = op->u.close.cl_stateowner;
+			op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
 			break;
 		case OP_COMMIT:
 			op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
@@ -831,15 +832,13 @@
 			op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
 			break;
 		case OP_LOCK:
-			op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock);
-			replay_owner = op->u.lock.lk_stateowner;
+			op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
 			break;
 		case OP_LOCKT:
 			op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
 			break;
 		case OP_LOCKU:
-			op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku);
-			replay_owner = op->u.locku.lu_stateowner;
+			op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
 			break;
 		case OP_LOOKUP:
 			op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
@@ -853,16 +852,13 @@
 				op->status = nfs_ok;
 			break;
 		case OP_OPEN:
-			op->status = nfsd4_open(rqstp, current_fh, &op->u.open);
-			replay_owner = op->u.open.op_stateowner;
+			op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
 			break;
 		case OP_OPEN_CONFIRM:
-			op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm);
-			replay_owner = op->u.open_confirm.oc_stateowner;
+			op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
 			break;
 		case OP_OPEN_DOWNGRADE:
-			op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade);
-			replay_owner = op->u.open_downgrade.od_stateowner;
+			op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
 			break;
 		case OP_PUTFH:
 			op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index b83f8fb..6bbefd0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -624,7 +624,7 @@
 	cb->cb_ident = se->se_callback_ident;
 	return;
 out_err:
-	printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
+	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
 		"will not receive delegations\n",
 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
 
@@ -678,13 +678,12 @@
 	int 			status;
 	char                    dname[HEXDIR_LEN];
 	
-	status = nfserr_inval;
 	if (!check_name(clname))
-		goto out;
+		return nfserr_inval;
 
 	status = nfs4_make_rec_clidname(dname, &clname);
 	if (status)
-		goto out;
+		return status;
 
 	/* 
 	 * XXX The Duplicate Request Cache (DRC) has been checked (??)
@@ -2014,7 +2013,7 @@
 {
 	if (stateid->si_boot == boot_time)
 		return 0;
-	printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
+	dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
 		stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
 		stateid->si_generation);
 	return 1;
@@ -2275,7 +2274,7 @@
 
 check_replay:
 	if (seqid == sop->so_seqid - 1) {
-		printk("NFSD: preprocess_seqid_op: retransmission?\n");
+		dprintk("NFSD: preprocess_seqid_op: retransmission?\n");
 		/* indicate replay to calling function */
 		return NFSERR_REPLAY_ME;
 	}
@@ -2286,7 +2285,7 @@
 }
 
 int
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
 {
 	int status;
 	struct nfs4_stateowner *sop;
@@ -2320,8 +2319,10 @@
 
 	nfsd4_create_clid_dir(sop->so_client);
 out:
-	if (oc->oc_stateowner)
+	if (oc->oc_stateowner) {
 		nfs4_get_stateowner(oc->oc_stateowner);
+		*replay_owner = oc->oc_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 }
@@ -2352,7 +2353,7 @@
 }
 
 int
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
+nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
 {
 	int status;
 	struct nfs4_stateid *stp;
@@ -2394,8 +2395,10 @@
 	memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
 	status = nfs_ok;
 out:
-	if (od->od_stateowner)
+	if (od->od_stateowner) {
 		nfs4_get_stateowner(od->od_stateowner);
+		*replay_owner = od->od_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 }
@@ -2404,7 +2407,7 @@
  * nfs4_unlock_state() called after encode
  */
 int
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
+nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
 {
 	int status;
 	struct nfs4_stateid *stp;
@@ -2430,8 +2433,10 @@
 	/* release_state_owner() calls nfsd_close() if needed */
 	release_state_owner(stp, OPEN_STATE);
 out:
-	if (close->cl_stateowner)
+	if (close->cl_stateowner) {
 		nfs4_get_stateowner(close->cl_stateowner);
+		*replay_owner = close->cl_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 }
@@ -2500,8 +2505,7 @@
 			    (local->st_stateid.si_fileid == f_id))
 				return local;
 		}
-	} else
-		printk("NFSD: find_stateid: ERROR: no state flag\n");
+	}
 	return NULL;
 }
 
@@ -2624,7 +2628,9 @@
 	sop->so_is_open_owner = 0;
 	sop->so_id = current_ownerid++;
 	sop->so_client = clp;
-	sop->so_seqid = lock->lk_new_lock_seqid;
+	/* It is the openowner seqid that will be incremented in encode in the
+	 * case of new lockowners; so increment the lock seqid manually: */
+	sop->so_seqid = lock->lk_new_lock_seqid + 1;
 	sop->so_confirmed = 1;
 	rp = &sop->so_replay;
 	rp->rp_status = NFSERR_SERVERFAULT;
@@ -2676,9 +2682,10 @@
  *  LOCK operation 
  */
 int
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
+nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateowner *open_sop = NULL;
+	struct nfs4_stateowner *lock_sop = NULL;
 	struct nfs4_stateid *lock_stp;
 	struct file *filp;
 	struct file_lock file_lock;
@@ -2705,19 +2712,19 @@
 		struct nfs4_file *fp;
 		
 		status = nfserr_stale_clientid;
-		if (STALE_CLIENTID(&lock->lk_new_clientid)) {
-			printk("NFSD: nfsd4_lock: clientid is stale!\n");
+		if (STALE_CLIENTID(&lock->lk_new_clientid))
 			goto out;
-		}
 
 		/* validate and update open stateid and open seqid */
 		status = nfs4_preprocess_seqid_op(current_fh, 
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
-		                        &open_sop, &open_stp, lock);
+		                        &lock->lk_stateowner, &open_stp,
+					lock);
 		if (status)
 			goto out;
+		open_sop = lock->lk_stateowner;
 		/* create lockowner and lock stateid */
 		fp = open_stp->st_file;
 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
@@ -2727,16 +2734,15 @@
 		 * the same file, or should they just be allowed (and
 		 * create new stateids)? */
 		status = nfserr_resource;
-		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
+		lock_sop = alloc_init_lock_stateowner(strhashval,
+				open_sop->so_client, open_stp, lock);
+		if (lock_sop == NULL)
 			goto out;
-		if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, 
-						fp, open_stp)) == NULL) {
-			release_stateowner(lock->lk_stateowner);
-			lock->lk_stateowner = NULL;
+		lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
+		if (lock_stp == NULL) {
+			release_stateowner(lock_sop);
 			goto out;
 		}
-		/* bump the open seqid used to create the lock */
-		open_sop->so_seqid++;
 	} else {
 		/* lock (lock owner + lock stateid) already exists */
 		status = nfs4_preprocess_seqid_op(current_fh,
@@ -2746,12 +2752,13 @@
 				       &lock->lk_stateowner, &lock_stp, lock);
 		if (status)
 			goto out;
+		lock_sop = lock->lk_stateowner;
 	}
 	/* lock->lk_stateowner 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))) {
-		printk("NFSD: nfsd4_lock: permission denied!\n");
+		dprintk("NFSD: nfsd4_lock: permission denied!\n");
 		goto out;
 	}
 
@@ -2776,7 +2783,7 @@
 			status = nfserr_inval;
 		goto out;
 	}
-	file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
+	file_lock.fl_owner = (fl_owner_t)lock_sop;
 	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX;
@@ -2832,14 +2839,13 @@
 		 * An error encountered after instantiation of the new
 		 * stateid has forced us to destroy it.
 		 */
-		if (!seqid_mutating_err(status))
-			open_sop->so_seqid--;
-
 		release_state_owner(lock_stp, LOCK_STATE);
 	}
 out:
-	if (lock->lk_stateowner)
+	if (lock->lk_stateowner) {
 		nfs4_get_stateowner(lock->lk_stateowner);
+		*replay_owner = lock->lk_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 }
@@ -2866,13 +2872,11 @@
 	nfs4_lock_state();
 
 	status = nfserr_stale_clientid;
-	if (STALE_CLIENTID(&lockt->lt_clientid)) {
-		printk("NFSD: nfsd4_lockt: clientid is stale!\n");
+	if (STALE_CLIENTID(&lockt->lt_clientid))
 		goto out;
-	}
 
 	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
-		printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
+		dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
 		if (status == nfserr_symlink)
 			status = nfserr_inval;
 		goto out;
@@ -2930,7 +2934,7 @@
 }
 
 int
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
+nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateid *stp;
 	struct file *filp = NULL;
@@ -2976,7 +2980,7 @@
 	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
 		file_lock.fl_ops->fl_release_private(&file_lock);
 	if (status) {
-		printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
+		dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
 		goto out_nfserr;
 	}
 	/*
@@ -2986,8 +2990,10 @@
 	memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
 
 out:
-	if (locku->lu_stateowner)
+	if (locku->lu_stateowner) {
 		nfs4_get_stateowner(locku->lu_stateowner);
+		*replay_owner = locku->lu_stateowner;
+	}
 	nfs4_unlock_state();
 	return status;
 
@@ -3036,10 +3042,8 @@
 	/* XXX check for lease expiration */
 
 	status = nfserr_stale_clientid;
-	if (STALE_CLIENTID(clid)) {
-		printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n");
+	if (STALE_CLIENTID(clid))
 		return status;
-	}
 
 	nfs4_lock_state();
 
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index e4fd613..49eafbd 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -34,9 +34,6 @@
 	  journals with two different restart pages.  We sanity check both and
 	  either use the only sane one or the more recent one of the two in the
 	  case that both are valid.
-	- Modify fs/ntfs/malloc.h::ntfs_malloc_nofs() to do the kmalloc() based
-	  allocations with __GFP_HIGHMEM, analogous to how the vmalloc() based
-	  allocations are done.
 	- Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
 	  ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
 	  hence cannot fail.
@@ -90,7 +87,11 @@
 	  in the first buffer head instead of a driver global spin lock to
 	  improve scalability.
 	- Minor fix to error handling and error message display in
-	  fs/ntfs/aops.c::ntfs_prepare_nonresident_write(). 
+	  fs/ntfs/aops.c::ntfs_prepare_nonresident_write().
+	- Change the mount options {u,f,d}mask to always parse the number as
+	  an octal number to conform to how chmod(1) works, too.  Thanks to
+	  Giuseppe Bilotta and Horst von Brand for pointing out the errors of
+	  my ways.
 
 2.1.23 - Implement extension of resident files and make writing safe as well as
 	 many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
index 9994e01..3288bcc 100644
--- a/fs/ntfs/malloc.h
+++ b/fs/ntfs/malloc.h
@@ -45,7 +45,7 @@
 	if (likely(size <= PAGE_SIZE)) {
 		BUG_ON(!size);
 		/* kmalloc() has per-CPU caches so is faster for now. */
-		return kmalloc(PAGE_SIZE, gfp_mask);
+		return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM);
 		/* return (void *)__get_free_page(gfp_mask); */
 	}
 	if (likely(size >> PAGE_SHIFT < num_physpages))
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index b2b3929..453d0d5 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -126,6 +126,14 @@
 		if (*v)							\
 			goto needs_val;					\
 	}
+#define NTFS_GETOPT_OCTAL(option, variable)				\
+	if (!strcmp(p, option)) {					\
+		if (!v || !*v)						\
+			goto needs_arg;					\
+		variable = simple_strtoul(ov = v, &v, 8);		\
+		if (*v)							\
+			goto needs_val;					\
+	}
 #define NTFS_GETOPT_BOOL(option, variable)				\
 	if (!strcmp(p, option)) {					\
 		BOOL val;						\
@@ -157,9 +165,9 @@
 			*v++ = 0;
 		NTFS_GETOPT("uid", uid)
 		else NTFS_GETOPT("gid", gid)
-		else NTFS_GETOPT("umask", fmask = dmask)
-		else NTFS_GETOPT("fmask", fmask)
-		else NTFS_GETOPT("dmask", dmask)
+		else NTFS_GETOPT_OCTAL("umask", fmask = dmask)
+		else NTFS_GETOPT_OCTAL("fmask", fmask)
+		else NTFS_GETOPT_OCTAL("dmask", dmask)
 		else NTFS_GETOPT("mft_zone_multiplier", mft_zone_multiplier)
 		else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE)
 		else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files)
diff --git a/fs/open.c b/fs/open.c
index 2fac58c..f0d90cf 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -738,52 +738,15 @@
 	return error;
 }
 
-/*
- * Note that while the flag value (low two bits) for sys_open means:
- *	00 - read-only
- *	01 - write-only
- *	10 - read-write
- *	11 - special
- * it is changed into
- *	00 - no permissions needed
- *	01 - read-permission
- *	10 - write-permission
- *	11 - read-write
- * 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 *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
+					int flags, struct file *f)
 {
-	int namei_flags, error;
-	struct nameidata nd;
-
-	namei_flags = flags;
-	if ((namei_flags+1) & O_ACCMODE)
-		namei_flags++;
-	if (namei_flags & O_TRUNC)
-		namei_flags |= 2;
-
-	error = open_namei(filename, namei_flags, mode, &nd);
-	if (!error)
-		return dentry_open(nd.dentry, nd.mnt, flags);
-
-	return ERR_PTR(error);
-}
-
-EXPORT_SYMBOL(filp_open);
-
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-{
-	struct file * f;
 	struct inode *inode;
 	int error;
 
-	error = -ENFILE;
-	f = get_empty_filp();
-	if (!f)
-		goto cleanup_dentry;
 	f->f_flags = flags;
-	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
+	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
+				FMODE_PREAD | FMODE_PWRITE;
 	inode = dentry->d_inode;
 	if (f->f_mode & FMODE_WRITE) {
 		error = get_write_access(inode);
@@ -828,12 +791,63 @@
 	f->f_vfsmnt = NULL;
 cleanup_file:
 	put_filp(f);
-cleanup_dentry:
 	dput(dentry);
 	mntput(mnt);
 	return ERR_PTR(error);
 }
 
+/*
+ * Note that while the flag value (low two bits) for sys_open means:
+ *	00 - read-only
+ *	01 - write-only
+ *	10 - read-write
+ *	11 - special
+ * it is changed into
+ *	00 - no permissions needed
+ *	01 - read-permission
+ *	10 - write-permission
+ *	11 - read-write
+ * 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)
+{
+	int namei_flags, error;
+	struct nameidata nd;
+	struct file *f;
+
+	namei_flags = flags;
+	if ((namei_flags+1) & O_ACCMODE)
+		namei_flags++;
+	if (namei_flags & O_TRUNC)
+		namei_flags |= 2;
+
+	error = -ENFILE;
+	f = get_empty_filp();
+	if (f == NULL)
+		return ERR_PTR(error);
+
+	error = open_namei(filename, namei_flags, mode, &nd);
+	if (!error)
+		return __dentry_open(nd.dentry, nd.mnt, flags, f);
+
+	put_filp(f);
+	return ERR_PTR(error);
+}
+EXPORT_SYMBOL(filp_open);
+
+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+{
+	int error;
+	struct file *f;
+
+	error = -ENFILE;
+	f = get_empty_filp();
+	if (f == NULL)
+		return ERR_PTR(error);
+
+	return __dentry_open(dentry, mnt, flags, f);
+}
 EXPORT_SYMBOL(dentry_open);
 
 /*
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index c9f178f..c20babd 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -667,7 +667,7 @@
 	if (th->t_trans_id) {
 		int err;
 		// update any changes we made to blk count
-		reiserfs_update_sd(th, inode);
+		mark_inode_dirty(inode);
 		err =
 		    journal_end(th, inode->i_sb,
 				JOURNAL_PER_BALANCE_CNT * 3 + 1 +
@@ -855,17 +855,18 @@
 
 		if (th->t_trans_id) {
 			reiserfs_write_lock(inode->i_sb);
-			reiserfs_update_sd(th, inode);	// And update on-disk metadata
+			// this sets the proper flags for O_SYNC to trigger a commit
+			mark_inode_dirty(inode);
 			reiserfs_write_unlock(inode->i_sb);
 		} else
-			inode->i_sb->s_op->dirty_inode(inode);
+			mark_inode_dirty(inode);
 
 		sd_update = 1;
 	}
 	if (th->t_trans_id) {
 		reiserfs_write_lock(inode->i_sb);
 		if (!sd_update)
-			reiserfs_update_sd(th, inode);
+			mark_inode_dirty(inode);
 		status = journal_end(th, th->t_super, th->t_blocks_allocated);
 		if (status)
 			retval = status;
@@ -1320,7 +1321,7 @@
 				return err;
 			}
 			reiserfs_update_inode_transaction(inode);
-			reiserfs_update_sd(&th, inode);
+			mark_inode_dirty(inode);
 			err = journal_end(&th, inode->i_sb, 1);
 			if (err) {
 				reiserfs_write_unlock(inode->i_sb);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1a8a1bf..d76ee6c 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2639,6 +2639,12 @@
 		}
 		reiserfs_update_inode_transaction(inode);
 		inode->i_size = pos;
+		/*
+		 * this will just nest into our transaction.  It's important
+		 * to use mark_inode_dirty so the inode gets pushed around on the
+		 * dirty lists, and so that O_SYNC works as expected
+		 */
+		mark_inode_dirty(inode);
 		reiserfs_update_sd(&myth, inode);
 		update_sd = 1;
 		ret = journal_end(&myth, inode->i_sb, 1);
@@ -2649,21 +2655,13 @@
 	if (th) {
 		reiserfs_write_lock(inode->i_sb);
 		if (!update_sd)
-			reiserfs_update_sd(th, inode);
+			mark_inode_dirty(inode);
 		ret = reiserfs_end_persistent_transaction(th);
 		reiserfs_write_unlock(inode->i_sb);
 		if (ret)
 			goto out;
 	}
 
-	/* we test for O_SYNC here so we can commit the transaction
-	 ** for any packed tails the file might have had
-	 */
-	if (f && (f->f_flags & O_SYNC)) {
-		reiserfs_write_lock(inode->i_sb);
-		ret = reiserfs_commit_for_inode(inode);
-		reiserfs_write_unlock(inode->i_sb);
-	}
       out:
 	return ret;
 
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 22b53e3..8393bf3 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -339,13 +339,6 @@
 #define kern_addr_valid(addr)	(1)
 #endif
 
-#define io_remap_page_range(vma, start, busaddr, size, prot)	\
-({								\
-	void *va = (void __force *)ioremap(busaddr, size);	\
-	unsigned long pfn = virt_to_phys(va) >> PAGE_SHIFT;	\
-	remap_pfn_range(vma, start, pfn, size, prot);		\
-})
-
 #define io_remap_pfn_range(vma, start, pfn, size, prot)	\
 		remap_pfn_range(vma, start, pfn, size, prot)
 
diff --git a/include/asm-arm/arch-pxa/akita.h b/include/asm-arm/arch-pxa/akita.h
new file mode 100644
index 0000000..4a1fbcf
--- /dev/null
+++ b/include/asm-arm/arch-pxa/akita.h
@@ -0,0 +1,30 @@
+/*
+ * Hardware specific definitions for SL-C1000 (Akita)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/* Akita IO Expander GPIOs */
+
+#define AKITA_IOEXP_RESERVED_7      (1 << 7)
+#define AKITA_IOEXP_IR_ON           (1 << 6)
+#define AKITA_IOEXP_AKIN_PULLUP     (1 << 5)
+#define AKITA_IOEXP_BACKLIGHT_CONT  (1 << 4)
+#define AKITA_IOEXP_BACKLIGHT_ON    (1 << 3)
+#define AKITA_IOEXP_MIC_BIAS        (1 << 2)
+#define AKITA_IOEXP_RESERVED_1      (1 << 1)
+#define AKITA_IOEXP_RESERVED_0      (1 << 0)
+
+/* Direction Bitfield  0=output  1=input */
+#define AKITA_IOEXP_IO_DIR	0
+/* Default Values */
+#define AKITA_IOEXP_IO_OUT	(AKITA_IOEXP_IR_ON | AKITA_IOEXP_AKIN_PULLUP)
+
+void akita_set_ioexp(struct device *dev, unsigned char bitmask);
+void akita_reset_ioexp(struct device *dev, unsigned char bitmask);
+
diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
index 4b7aa0b..e554caa 100644
--- a/include/asm-arm/arch-pxa/corgi.h
+++ b/include/asm-arm/arch-pxa/corgi.h
@@ -106,17 +106,5 @@
 extern struct platform_device corgissp_device;
 extern struct platform_device corgifb_device;
 
-/*
- * External Functions
- */
-extern unsigned long corgi_ssp_ads7846_putget(unsigned long);
-extern unsigned long corgi_ssp_ads7846_get(void);
-extern void corgi_ssp_ads7846_put(unsigned long data);
-extern void corgi_ssp_ads7846_lock(void);
-extern void corgi_ssp_ads7846_unlock(void);
-extern void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
-extern void corgi_ssp_blduty_set(int duty);
-extern int corgi_ssp_max1111_get(unsigned long data);
-
 #endif /* __ASM_ARCH_CORGI_H  */
 
diff --git a/include/asm-arm/arch-pxa/sharpsl.h b/include/asm-arm/arch-pxa/sharpsl.h
new file mode 100644
index 0000000..311f2bb
--- /dev/null
+++ b/include/asm-arm/arch-pxa/sharpsl.h
@@ -0,0 +1,32 @@
+/*
+ * SharpSL SSP Driver
+ */
+
+unsigned long corgi_ssp_ads7846_putget(unsigned long);
+unsigned long corgi_ssp_ads7846_get(void);
+void corgi_ssp_ads7846_put(unsigned long data);
+void corgi_ssp_ads7846_lock(void);
+void corgi_ssp_ads7846_unlock(void);
+void corgi_ssp_lcdtg_send (unsigned char adrs, unsigned char data);
+void corgi_ssp_blduty_set(int duty);
+int corgi_ssp_max1111_get(unsigned long data);
+
+/*
+ * SharpSL Touchscreen Driver
+ */
+
+struct corgits_machinfo {
+	unsigned long (*get_hsync_len)(void);
+	void (*put_hsync)(void);
+	void (*wait_hsync)(void);
+};
+
+/*
+ * SharpSL Backlight
+ */
+
+struct corgibl_machinfo {
+	int max_intensity;
+	void (*set_bl_intensity)(int intensity);
+};
+
diff --git a/include/asm-arm/arch-pxa/spitz.h b/include/asm-arm/arch-pxa/spitz.h
new file mode 100644
index 0000000..62e1fe4
--- /dev/null
+++ b/include/asm-arm/arch-pxa/spitz.h
@@ -0,0 +1,158 @@
+/*
+ * Hardware specific definitions for SL-Cx000 series of PDAs
+ *
+ * Copyright (c) 2005 Alexander Wykes
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on Sharp's 2.4 kernel patches
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_SPITZ_H
+#define __ASM_ARCH_SPITZ_H  1
+#endif
+
+/* Spitz/Akita GPIOs */
+
+#define SPITZ_GPIO_KEY_INT         (0) /* Key Interrupt */
+#define SPITZ_GPIO_RESET           (1)
+#define SPITZ_GPIO_nSD_DETECT      (9)
+#define SPITZ_GPIO_TP_INT          (11) /* Touch Panel interrupt */
+#define SPITZ_GPIO_AK_INT          (13) /* Remote Control */
+#define SPITZ_GPIO_ADS7846_CS      (14)
+#define SPITZ_GPIO_SYNC            (16)
+#define SPITZ_GPIO_MAX1111_CS      (20)
+#define SPITZ_GPIO_FATAL_BAT       (21)
+#define SPITZ_GPIO_HSYNC           (22)
+#define SPITZ_GPIO_nSD_CLK         (32)
+#define SPITZ_GPIO_USB_DEVICE      (35)
+#define SPITZ_GPIO_USB_HOST        (37)
+#define SPITZ_GPIO_USB_CONNECT     (41)
+#define SPITZ_GPIO_LCDCON_CS       (53)
+#define SPITZ_GPIO_nPCE            (54)
+#define SPITZ_GPIO_nSD_WP          (81)
+#define SPITZ_GPIO_ON_RESET        (89)
+#define SPITZ_GPIO_BAT_COVER       (90)
+#define SPITZ_GPIO_CF_CD           (94)
+#define SPITZ_GPIO_ON_KEY          (95)
+#define SPITZ_GPIO_SWA             (97)
+#define SPITZ_GPIO_SWB             (96)
+#define SPITZ_GPIO_CHRG_FULL       (101)
+#define SPITZ_GPIO_CO              (101)
+#define SPITZ_GPIO_CF_IRQ          (105)
+#define SPITZ_GPIO_AC_IN           (115)
+#define SPITZ_GPIO_HP_IN           (116)
+
+/* Spitz Only GPIOs */
+
+#define SPITZ_GPIO_CF2_IRQ         (106) /* CF slot1 Ready */
+#define SPITZ_GPIO_CF2_CD          (93)
+
+
+/* Spitz/Akita Keyboard Definitions */
+
+#define SPITZ_KEY_STROBE_NUM         (11)
+#define SPITZ_KEY_SENSE_NUM          (7)
+#define SPITZ_GPIO_G0_STROBE_BIT     0x0f800000
+#define SPITZ_GPIO_G1_STROBE_BIT     0x00100000
+#define SPITZ_GPIO_G2_STROBE_BIT     0x01000000
+#define SPITZ_GPIO_G3_STROBE_BIT     0x00041880
+#define SPITZ_GPIO_G0_SENSE_BIT      0x00021000
+#define SPITZ_GPIO_G1_SENSE_BIT      0x000000d4
+#define SPITZ_GPIO_G2_SENSE_BIT      0x08000000
+#define SPITZ_GPIO_G3_SENSE_BIT      0x00000000
+
+#define SPITZ_GPIO_KEY_STROBE0       88
+#define SPITZ_GPIO_KEY_STROBE1       23
+#define SPITZ_GPIO_KEY_STROBE2       24
+#define SPITZ_GPIO_KEY_STROBE3       25
+#define SPITZ_GPIO_KEY_STROBE4       26
+#define SPITZ_GPIO_KEY_STROBE5       27
+#define SPITZ_GPIO_KEY_STROBE6       52
+#define SPITZ_GPIO_KEY_STROBE7       103
+#define SPITZ_GPIO_KEY_STROBE8       107
+#define SPITZ_GPIO_KEY_STROBE9       108
+#define SPITZ_GPIO_KEY_STROBE10      114
+
+#define SPITZ_GPIO_KEY_SENSE0        12
+#define SPITZ_GPIO_KEY_SENSE1        17
+#define SPITZ_GPIO_KEY_SENSE2        91
+#define SPITZ_GPIO_KEY_SENSE3        34
+#define SPITZ_GPIO_KEY_SENSE4        36
+#define SPITZ_GPIO_KEY_SENSE5        38
+#define SPITZ_GPIO_KEY_SENSE6        39
+
+
+/* Spitz Scoop Device (No. 1) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP_LED_GREEN     SCOOP_GPCR_PA11  /* Keep */
+#define SPITZ_SCP_JK_B          SCOOP_GPCR_PA12  /* Keep */
+#define SPITZ_SCP_CHRG_ON       SCOOP_GPCR_PA13  /* Keep */
+#define SPITZ_SCP_MUTE_L        SCOOP_GPCR_PA14  /* Low */
+#define SPITZ_SCP_MUTE_R        SCOOP_GPCR_PA15  /* Low */
+#define SPITZ_SCP_CF_POWER      SCOOP_GPCR_PA16  /* Keep */
+#define SPITZ_SCP_LED_ORANGE    SCOOP_GPCR_PA17  /* Keep */
+#define SPITZ_SCP_JK_A          SCOOP_GPCR_PA18  /* Low */
+#define SPITZ_SCP_ADC_TEMP_ON   SCOOP_GPCR_PA19  /* Low */
+
+#define SPITZ_SCP_IO_DIR      (SPITZ_SCP_LED_GREEN | SPITZ_SCP_JK_B | SPITZ_SCP_CHRG_ON | \
+                               SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_LED_ORANGE | \
+                               SPITZ_SCP_CF_POWER | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_IO_OUT      (SPITZ_SCP_CHRG_ON | SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R)
+#define SPITZ_SCP_SUS_CLR     (SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON)
+#define SPITZ_SCP_SUS_SET     0
+
+/* Spitz Scoop Device (No. 2) GPIOs */
+/* Suspend States in comments */
+#define SPITZ_SCP2_IR_ON           SCOOP_GPCR_PA11  /* High */
+#define SPITZ_SCP2_AKIN_PULLUP     SCOOP_GPCR_PA12  /* Keep */
+#define SPITZ_SCP2_RESERVED_1      SCOOP_GPCR_PA13  /* High */
+#define SPITZ_SCP2_RESERVED_2      SCOOP_GPCR_PA14  /* Low */
+#define SPITZ_SCP2_RESERVED_3      SCOOP_GPCR_PA15  /* Low */
+#define SPITZ_SCP2_RESERVED_4      SCOOP_GPCR_PA16  /* Low */
+#define SPITZ_SCP2_BACKLIGHT_CONT  SCOOP_GPCR_PA17  /* Low */
+#define SPITZ_SCP2_BACKLIGHT_ON    SCOOP_GPCR_PA18  /* Low */
+#define SPITZ_SCP2_MIC_BIAS        SCOOP_GPCR_PA19  /* Low */
+
+#define SPITZ_SCP2_IO_DIR (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1 | \
+                           SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+                           SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+
+#define SPITZ_SCP2_IO_OUT   (SPITZ_SCP2_IR_ON | SPITZ_SCP2_AKIN_PULLUP | SPITZ_SCP2_RESERVED_1)
+#define SPITZ_SCP2_SUS_CLR  (SPITZ_SCP2_RESERVED_2 | SPITZ_SCP2_RESERVED_3 | SPITZ_SCP2_RESERVED_4 | \
+                             SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS)
+#define SPITZ_SCP2_SUS_SET  (SPITZ_SCP2_IR_ON | SPITZ_SCP2_RESERVED_1)
+
+
+/* Spitz IRQ Definitions */
+
+#define SPITZ_IRQ_GPIO_KEY_INT        IRQ_GPIO(SPITZ_GPIO_KEY_INT)
+#define SPITZ_IRQ_GPIO_AC_IN          IRQ_GPIO(SPITZ_GPIO_AC_IN)
+#define SPITZ_IRQ_GPIO_AK_INT         IRQ_GPIO(SPITZ_GPIO_AK_INT)
+#define SPITZ_IRQ_GPIO_HP_IN          IRQ_GPIO(SPITZ_GPIO_HP_IN)
+#define SPITZ_IRQ_GPIO_TP_INT         IRQ_GPIO(SPITZ_GPIO_TP_INT)
+#define SPITZ_IRQ_GPIO_SYNC           IRQ_GPIO(SPITZ_GPIO_SYNC)
+#define SPITZ_IRQ_GPIO_ON_KEY         IRQ_GPIO(SPITZ_GPIO_ON_KEY)
+#define SPITZ_IRQ_GPIO_SWA            IRQ_GPIO(SPITZ_GPIO_SWA)
+#define SPITZ_IRQ_GPIO_SWB            IRQ_GPIO(SPITZ_GPIO_SWB)
+#define SPITZ_IRQ_GPIO_BAT_COVER      IRQ_GPIO(SPITZ_GPIO_BAT_COVER)
+#define SPITZ_IRQ_GPIO_FATAL_BAT      IRQ_GPIO(SPITZ_GPIO_FATAL_BAT)
+#define SPITZ_IRQ_GPIO_CO             IRQ_GPIO(SPITZ_GPIO_CO)
+#define SPITZ_IRQ_GPIO_CF_IRQ         IRQ_GPIO(SPITZ_GPIO_CF_IRQ)
+#define SPITZ_IRQ_GPIO_CF_CD          IRQ_GPIO(SPITZ_GPIO_CF_CD)
+#define SPITZ_IRQ_GPIO_CF2_IRQ        IRQ_GPIO(SPITZ_GPIO_CF2_IRQ)
+#define SPITZ_IRQ_GPIO_nSD_INT        IRQ_GPIO(SPITZ_GPIO_nSD_INT)
+#define SPITZ_IRQ_GPIO_nSD_DETECT     IRQ_GPIO(SPITZ_GPIO_nSD_DETECT)
+
+/*
+ * Shared data structures
+ */
+extern struct platform_device spitzscoop_device;
+extern struct platform_device spitzscoop2_device;
+extern struct platform_device spitzssp_device;
+extern struct sharpsl_charger_machinfo spitz_pm_machinfo;
+
+extern void spitz_lcd_power(int on);
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 478c49b..366bafb 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -445,12 +445,9 @@
 #define HAVE_ARCH_UNMAPPED_AREA
 
 /*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
  * into virtual address `from'
  */
-#define io_remap_page_range(vma,from,phys,size,prot) \
-		remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
 		remap_pfn_range(vma, from, pfn, size, prot)
 
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index 4a0a00d..f602cf5 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -294,12 +294,9 @@
 #include <asm-generic/pgtable.h>
 
 /*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
  * into virtual address `from'
  */
-#define io_remap_page_range(vma,from,phys,size,prot) \
-		remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma,from,pfn,size,prot) \
 		remap_pfn_range(vma, from, pfn, size, prot)
 
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index d0a9c2f..473fb4b 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -500,9 +500,6 @@
 #define PageSkip(page)		(0)
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index faff403..7d02983 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -23,7 +23,11 @@
  * and page free order so much..
  */
 #ifdef CONFIG_SMP
-  #define FREE_PTE_NR	506
+  #ifdef ARCH_FREE_PTR_NR
+    #define FREE_PTR_NR   ARCH_FREE_PTR_NR
+  #else
+    #define FREE_PTE_NR	506
+  #endif
   #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
 #else
   #define FREE_PTE_NR	1
diff --git a/include/asm-h8300/pgtable.h b/include/asm-h8300/pgtable.h
index 69076eb..f6e296f 100644
--- a/include/asm-h8300/pgtable.h
+++ b/include/asm-h8300/pgtable.h
@@ -52,8 +52,6 @@
  * No page table caches to initialise
  */
 #define pgtable_cache_init()   do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 6a1b188..8c454aa 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -130,6 +130,8 @@
 #define NMI_LOCAL_APIC	2
 #define NMI_INVALID	3
 
+extern int disable_timer_pin_1;
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
diff --git a/include/asm-i386/numa.h b/include/asm-i386/numa.h
new file mode 100644
index 0000000..96fcb15
--- /dev/null
+++ b/include/asm-i386/numa.h
@@ -0,0 +1,3 @@
+
+int pxm_to_nid(int pxm);
+
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 47bc1ff..d101ac4 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -431,9 +431,6 @@
 #define kern_addr_valid(addr)	(1)
 #endif /* CONFIG_FLATMEM */
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 2461b73..0ec27c9 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -60,7 +60,7 @@
 	return first_cpu(mask);
 }
 
-#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_node(bus) ((long) (bus)->sysdata)
 #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
 
 /* sched_domains SD_NODE_INIT for NUMAQ machines */
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index a7cb377..fbaf90a 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -332,7 +332,7 @@
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(arg1))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -342,7 +342,7 @@
 long __res; \
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
-	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
+	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -353,7 +353,7 @@
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
 	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-		  "d" ((long)(arg3))); \
+		  "d" ((long)(arg3)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -364,7 +364,7 @@
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
 	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-	  "d" ((long)(arg3)),"S" ((long)(arg4))); \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
 __syscall_return(type,__res); \
 } 
 
@@ -376,7 +376,7 @@
 __asm__ volatile ("int $0x80" \
 	: "=a" (__res) \
 	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -389,7 +389,7 @@
 	: "=a" (__res) \
 	: "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
 	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
-	  "0" ((long)(arg6))); \
+	  "0" ((long)(arg6)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 2e34c06..3339c7b 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -443,10 +443,6 @@
 #define pte_to_pgoff(pte)		((pte_val(pte) << 1) >> 3)
 #define pgoff_to_pte(off)		((pte_t) { ((off) << 2) | _PAGE_FILE })
 
-/* XXX is this right? */
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index da805e9..388e5ee 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -378,9 +378,6 @@
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)	\
-	remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 0c87fc8..add129e 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -141,9 +141,6 @@
 
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index f95e32b..c42f88a 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -259,7 +259,7 @@
 #define find_first_bit(addr, size) \
         find_next_bit((addr), (size), 0)
 
-static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (const void * addr, int size, int offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index aa7a2ff..026bbc9 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -2,23 +2,23 @@
 #define _M68KNOMMU_CACHEFLUSH_H
 
 /*
- * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
+ * (C) Copyright 2000-2004, Greg Ungerer <gerg@snapgear.com>
  */
 #include <linux/mm.h>
 
 #define flush_cache_all()			__flush_cache_all()
 #define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
-#define flush_dcache_range(start,len)		do { } while (0)
+#define flush_cache_range(vma, start, end)	__flush_cache_all()
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_dcache_range(start,len)		__flush_cache_all()
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 #define flush_icache_range(start,len)		__flush_cache_all()
 #define flush_icache_page(vma,pg)		do { } while (0)
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-#define flush_cache_vmap(start, end)		flush_cache_all()
-#define flush_cache_vunmap(start, end)		flush_cache_all()
+#define flush_cache_vmap(start, end)		do { } while (0)
+#define flush_cache_vunmap(start, end)		do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 	memcpy(dst, src, len)
@@ -50,22 +50,23 @@
 		"movec	%%d0,%%CACR\n\t"
 		: : : "d0", "a0" );
 #endif /* CONFIG_M5407 */
+#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+	__asm__ __volatile__ (
+        	"movel	#0x81400100, %%d0\n\t"
+        	"movec	%%d0, %%CACR\n\t"
+		"nop\n\t"
+		: : : "d0" );
+#endif /* CONFIG_M527x || CONFIG_M528x */
 #ifdef CONFIG_M5272
 	__asm__ __volatile__ (
         	"movel	#0x01000000, %%d0\n\t"
         	"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
-        	"movel	#0x80000100, %%d0\n\t"
-        	"movec	%%d0, %%CACR\n\t"
-		"nop\n\t"
 		: : : "d0" );
 #endif /* CONFIG_M5272 */
-#if 0 /* CONFIG_M5249 */
+#if CONFIG_M5249
 	__asm__ __volatile__ (
-        	"movel	#0x01000000, %%d0\n\t"
-        	"movec	%%d0, %%CACR\n\t"
-		"nop\n\t"
-        	"movel	#0xa0000200, %%d0\n\t"
+        	"movel	#0xa1000200, %%d0\n\t"
         	"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
 		: : : "d0" );
diff --git a/include/asm-m68knommu/checksum.h b/include/asm-m68knommu/checksum.h
index 92cf102..294ec75 100644
--- a/include/asm-m68knommu/checksum.h
+++ b/include/asm-m68knommu/checksum.h
@@ -25,7 +25,8 @@
  * better 64-bit) boundary
  */
 
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+	int len, int sum);
 
 
 /*
@@ -35,8 +36,8 @@
  * better 64-bit) boundary
  */
 
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
-						int len, int sum, int *csum_err);
+extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+	unsigned char *dst, int len, int sum, int *csum_err);
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
 	csum_partial_copy((src), (dst), (len), (sum))
diff --git a/include/asm-m68knommu/m527xsim.h b/include/asm-m68knommu/m527xsim.h
index d280d01..e7878d0 100644
--- a/include/asm-m68knommu/m527xsim.h
+++ b/include/asm-m68knommu/m527xsim.h
@@ -37,13 +37,14 @@
 /*
  *	SDRAM configuration registers.
  */
-#ifdef CONFIG_M5271EVB
+#ifdef CONFIG_M5271
 #define	MCFSIM_DCR		0x40		/* SDRAM control */
 #define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
 #define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
 #define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
 #define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
-#else
+#endif
+#ifdef CONFIG_M5275
 #define	MCFSIM_DMR		0x40		/* SDRAM mode */
 #define	MCFSIM_DCR		0x44		/* SDRAM control */
 #define	MCFSIM_DCFG1		0x48		/* SDRAM configuration 1 */
@@ -54,5 +55,21 @@
 #define	MCFSIM_DMR1		0x5c		/* SDRAM address mask 1 */
 #endif
 
+/*
+ *	GPIO pins setups to enable the UARTs.
+ */
+#ifdef CONFIG_M5271
+#define MCF_GPIO_PAR_UART	0x100048	/* PAR UART address */
+#define UART0_ENABLE_MASK	0x000f
+#define UART1_ENABLE_MASK	0x0ff0
+#define UART2_ENABLE_MASK	0x3000
+#endif
+#ifdef CONFIG_M5275
+#define MCF_GPIO_PAR_UART	0x10007c	/* PAR UART address */
+#define UART0_ENABLE_MASK	0x000f
+#define UART1_ENABLE_MASK	0x00f0
+#define UART2_ENABLE_MASK	0x3f00 
+#endif
+
 /****************************************************************************/
 #endif	/* m527xsim_h */
diff --git a/include/asm-m68knommu/m528xsim.h b/include/asm-m68knommu/m528xsim.h
index 371993a..610774a 100644
--- a/include/asm-m68knommu/m528xsim.h
+++ b/include/asm-m68knommu/m528xsim.h
@@ -41,5 +41,117 @@
 #define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
 #define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
 
+/*
+ *	Derek Cheung - 6 Feb 2005
+ *		add I2C and QSPI register definition using Freescale's MCF5282
+ */
+/* set Port AS pin for I2C or UART */
+#define MCF5282_GPIO_PASPAR     (volatile u16 *) (MCF_IPSBAR + 0x00100056)
+
+/* Interrupt Mask Register Register Low */ 
+#define MCF5282_INTC0_IMRL      (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
+/* Interrupt Control Register 7 */
+#define MCF5282_INTC0_ICR17     (volatile u8 *) (MCF_IPSBAR + 0x0C51)
+
+
+
+/*********************************************************************
+*
+* Inter-IC (I2C) Module
+*
+*********************************************************************/
+/* Read/Write access macros for general use */
+#define MCF5282_I2C_I2ADR       (volatile u8 *) (MCF_IPSBAR + 0x0300) // Address 
+#define MCF5282_I2C_I2FDR       (volatile u8 *) (MCF_IPSBAR + 0x0304) // Freq Divider
+#define MCF5282_I2C_I2CR        (volatile u8 *) (MCF_IPSBAR + 0x0308) // Control
+#define MCF5282_I2C_I2SR        (volatile u8 *) (MCF_IPSBAR + 0x030C) // Status
+#define MCF5282_I2C_I2DR        (volatile u8 *) (MCF_IPSBAR + 0x0310) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF5282_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
+
+#define MCF5282_I2C_I2FDR_IC(x)                         (((x)&0x3F))
+
+#define MCF5282_I2C_I2CR_IEN    (0x80)	// I2C enable
+#define MCF5282_I2C_I2CR_IIEN   (0x40)  // interrupt enable
+#define MCF5282_I2C_I2CR_MSTA   (0x20)  // master/slave mode
+#define MCF5282_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
+#define MCF5282_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
+#define MCF5282_I2C_I2CR_RSTA   (0x04)  // repeat start
+
+#define MCF5282_I2C_I2SR_ICF    (0x80)  // data transfer bit
+#define MCF5282_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
+#define MCF5282_I2C_I2SR_IBB    (0x20)  // I2C bus busy
+#define MCF5282_I2C_I2SR_IAL    (0x10)  // aribitration lost
+#define MCF5282_I2C_I2SR_SRW    (0x04)  // slave read/write
+#define MCF5282_I2C_I2SR_IIF    (0x02)  // I2C interrupt
+#define MCF5282_I2C_I2SR_RXAK   (0x01)  // received acknowledge
+
+
+
+/*********************************************************************
+*
+* Queued Serial Peripheral Interface (QSPI) Module
+*
+*********************************************************************/
+/* Derek - 21 Feb 2005 */
+/* change to the format used in I2C */
+/* Read/Write access macros for general use */
+#define MCF5282_QSPI_QMR        MCF_IPSBAR + 0x0340
+#define MCF5282_QSPI_QDLYR      MCF_IPSBAR + 0x0344
+#define MCF5282_QSPI_QWR        MCF_IPSBAR + 0x0348
+#define MCF5282_QSPI_QIR        MCF_IPSBAR + 0x034C
+#define MCF5282_QSPI_QAR        MCF_IPSBAR + 0x0350
+#define MCF5282_QSPI_QDR        MCF_IPSBAR + 0x0354
+#define MCF5282_QSPI_QCR        MCF_IPSBAR + 0x0354
+
+/* Bit level definitions and macros */
+#define MCF5282_QSPI_QMR_MSTR                           (0x8000)
+#define MCF5282_QSPI_QMR_DOHIE                          (0x4000)
+#define MCF5282_QSPI_QMR_BITS_16                        (0x0000)
+#define MCF5282_QSPI_QMR_BITS_8                         (0x2000)
+#define MCF5282_QSPI_QMR_BITS_9                         (0x2400)
+#define MCF5282_QSPI_QMR_BITS_10                        (0x2800)
+#define MCF5282_QSPI_QMR_BITS_11                        (0x2C00)
+#define MCF5282_QSPI_QMR_BITS_12                        (0x3000)
+#define MCF5282_QSPI_QMR_BITS_13                        (0x3400)
+#define MCF5282_QSPI_QMR_BITS_14                        (0x3800)
+#define MCF5282_QSPI_QMR_BITS_15                        (0x3C00)
+#define MCF5282_QSPI_QMR_CPOL                           (0x0200)
+#define MCF5282_QSPI_QMR_CPHA                           (0x0100)
+#define MCF5282_QSPI_QMR_BAUD(x)                        (((x)&0x00FF))
+
+#define MCF5282_QSPI_QDLYR_SPE                          (0x80)
+#define MCF5282_QSPI_QDLYR_QCD(x)                       (((x)&0x007F)<<8)
+#define MCF5282_QSPI_QDLYR_DTL(x)                       (((x)&0x00FF))
+
+#define MCF5282_QSPI_QWR_HALT                           (0x8000)
+#define MCF5282_QSPI_QWR_WREN                           (0x4000)
+#define MCF5282_QSPI_QWR_WRTO                           (0x2000)
+#define MCF5282_QSPI_QWR_CSIV                           (0x1000)
+#define MCF5282_QSPI_QWR_ENDQP(x)                       (((x)&0x000F)<<8)
+#define MCF5282_QSPI_QWR_CPTQP(x)                       (((x)&0x000F)<<4)
+#define MCF5282_QSPI_QWR_NEWQP(x)                       (((x)&0x000F))
+
+#define MCF5282_QSPI_QIR_WCEFB                          (0x8000)
+#define MCF5282_QSPI_QIR_ABRTB                          (0x4000)
+#define MCF5282_QSPI_QIR_ABRTL                          (0x1000)
+#define MCF5282_QSPI_QIR_WCEFE                          (0x0800)
+#define MCF5282_QSPI_QIR_ABRTE                          (0x0400)
+#define MCF5282_QSPI_QIR_SPIFE                          (0x0100)
+#define MCF5282_QSPI_QIR_WCEF                           (0x0008)
+#define MCF5282_QSPI_QIR_ABRT                           (0x0004)
+#define MCF5282_QSPI_QIR_SPIF                           (0x0001)
+
+#define MCF5282_QSPI_QAR_ADDR(x)                        (((x)&0x003F))
+
+#define MCF5282_QSPI_QDR_COMMAND(x)                     (((x)&0xFF00))
+#define MCF5282_QSPI_QCR_DATA(x)                        (((x)&0x00FF)<<8)
+#define MCF5282_QSPI_QCR_CONT                           (0x8000)
+#define MCF5282_QSPI_QCR_BITSE                          (0x4000)
+#define MCF5282_QSPI_QCR_DT                             (0x2000)
+#define MCF5282_QSPI_QCR_DSCK                           (0x1000)
+#define MCF5282_QSPI_QCR_CS                             (((x)&0x000F)<<8)
+
 /****************************************************************************/
 #endif	/* m528xsim_h */
diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
index bdd8c53..b17cd92 100644
--- a/include/asm-m68knommu/mcfcache.h
+++ b/include/asm-m68knommu/mcfcache.h
@@ -33,7 +33,7 @@
 .endm
 #endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
 
-#if defined(CONFIG_M527x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
 /*
  *	New version 2 cores have a configurable split cache arrangement.
  *	For now I am just enabling instruction cache - but ultimately I
@@ -51,23 +51,20 @@
 	movec	%d0,%CACR		/* enable cache */
 	nop
 .endm
-#endif /* CONFIG_M527x */
+#endif /* CONFIG_M523x || CONFIG_M527x */
 
 #if defined(CONFIG_M528x)
-/*
- *	Cache is totally broken on early 5282 silicon. So far now we
- *	disable its cache all together.
- */
 .macro CACHE_ENABLE
-	movel	#0x01000000,%d0
-	movec	%d0,%CACR		/* invalidate cache */
 	nop
-	movel	#0x0000c000,%d0		/* set SDRAM cached only */
-	movec	%d0,%ACR0
-	movel	#0x00000000,%d0		/* no other regions cached */
-	movec	%d0,%ACR1
-	movel	#0x00000000,%d0		/* configure cache */
-	movec	%d0,%CACR		/* enable cache */
+	movel	#0x01000000, %d0
+	movec	%d0, %CACR		/* Invalidate cache */
+	nop
+	movel	#0x0000c020, %d0	/* Set SDRAM cached only */
+	movec	%d0, %ACR0
+	movel	#0xff00c000, %d0	/* Cache Flash also */
+	movec	%d0, %ACR1
+	movel	#0x80000200, %d0	/* Setup cache mask */
+	movec	%d0, %CACR		/* Enable cache */
 	nop
 .endm
 #endif /* CONFIG_M528x */
diff --git a/include/asm-m68knommu/mcfdma.h b/include/asm-m68knommu/mcfdma.h
index 350c609..b93f8ba 100644
--- a/include/asm-m68knommu/mcfdma.h
+++ b/include/asm-m68knommu/mcfdma.h
@@ -21,7 +21,7 @@
 #define	MCFDMA_BASE1		0x240		/* Base address of DMA 1 */
 #elif defined(CONFIG_M5272)
 #define	MCFDMA_BASE0		0x0e0		/* Base address of DMA 0 */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /* These are relative to the IPSBAR, not MBAR */
 #define	MCFDMA_BASE0		0x100		/* Base address of DMA 0 */
 #define	MCFDMA_BASE1		0x140		/* Base address of DMA 1 */
diff --git a/include/asm-m68knommu/pgtable.h b/include/asm-m68knommu/pgtable.h
index e2a69ff..0089305 100644
--- a/include/asm-m68knommu/pgtable.h
+++ b/include/asm-m68knommu/pgtable.h
@@ -56,8 +56,6 @@
  * No page table caches to initialise.
  */
 #define pgtable_cache_init()	do { } while (0)
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h
index 230b8d5..12309b1 100644
--- a/include/asm-m68knommu/scatterlist.h
+++ b/include/asm-m68knommu/scatterlist.h
@@ -1,6 +1,8 @@
 #ifndef _M68KNOMMU_SCATTERLIST_H
 #define _M68KNOMMU_SCATTERLIST_H
 
+#include <linux/mm.h>
+
 struct scatterlist {
 	struct page	*page;
 	unsigned int	offset;
@@ -8,6 +10,10 @@
 	unsigned int	length;
 };
 
+#define sg_address(sg) (page_address((sg)->page) + (sg)->offset
+#define sg_dma_address(sg)      ((sg)->dma_address)
+#define sg_dma_len(sg)          ((sg)->length)
+
 #define ISA_DMA_THRESHOLD	(0xffffffff)
 
 #endif /* !(_M68KNOMMU_SCATTERLIST_H) */
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index c341b66..53cbbad 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -57,9 +57,18 @@
         : "cc", "%d0", "memory")
 #define local_irq_disable() __asm__ __volatile__ (		\
 	"move %/sr,%%d0\n\t"					\
-	"ori.l  #0x0700,%%d0\n\t"				\
+	"ori.l #0x0700,%%d0\n\t"				\
 	"move %%d0,%/sr\n"					\
-	: /* no inputs */					\
+	: /* no outputs */					\
+	:							\
+	: "cc", "%d0", "memory")
+/* For spinlocks etc */
+#define local_irq_save(x) __asm__ __volatile__ (		\
+	"movew %%sr,%0\n\t"					\
+	"movew #0x0700,%%d0\n\t"				\
+	"or.l  %0,%%d0\n\t"					\
+	"movew %%d0,%/sr"					\
+	: "=d" (x)						\
 	:							\
 	: "cc", "%d0", "memory")
 #else
@@ -75,7 +84,9 @@
 #define local_irq_restore(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
 
 /* For spinlocks etc */
+#ifndef local_irq_save
 #define local_irq_save(x) do { local_save_flags(x); local_irq_disable(); } while (0)
+#endif
 
 #define	irqs_disabled()			\
 ({					\
@@ -234,9 +245,9 @@
 #ifdef CONFIG_COLDFIRE
 #if defined(CONFIG_M5272) && defined(CONFIG_NETtel)
 /*
- *	Need to account for broken early mask of 5272 silicon. So don't
- *	jump through the original start address. Jump strait into the
- *	known start of the FLASH code.
+ * Need to account for broken early mask of 5272 silicon. So don't
+ * jump through the original start address. Jump strait into the
+ * known start of the FLASH code.
  */
 #define HARD_RESET_NOW() ({		\
         asm("				\
@@ -244,7 +255,9 @@
         jmp 0xf0000400;			\
         ");				\
 })
-#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
+#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+      defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
+      defined(CONFIG_CLEOPATRA)
 #define HARD_RESET_NOW() ({		\
         asm("				\
 	movew #0x2700, %sr;		\
@@ -257,6 +270,26 @@
         jmp (%a0);			\
         ");				\
 })
+#elif defined(CONFIG_M5272)
+/*
+ * Retrieve the boot address in flash using CSBR0 and CSOR0
+ * find the reset vector at flash_address + 4 (e.g. 0x400)
+ * remap it in the flash's current location (e.g. 0xf0000400)
+ * and jump there.
+ */ 
+#define HARD_RESET_NOW() ({		\
+	asm("				\
+	movew #0x2700, %%sr;		\
+	move.l	%0+0x40,%%d0;		\
+	and.l	%0+0x44,%%d0;		\
+	andi.l	#0xfffff000,%%d0;	\
+	mov.l	%%d0,%%a0;		\
+	or.l	4(%%a0),%%d0;		\
+	mov.l	%%d0,%%a0;		\
+	jmp (%%a0);"			\
+	: /* No output */		\
+	: "o" (*(char *)MCF_MBAR) );	\
+})
 #elif defined(CONFIG_M528x)
 /*
  * The MCF528x has a bit (SOFTRST) in memory (Reset Control Register RCR),
@@ -270,6 +303,15 @@
 	while(1)				\
 	*reset |= (0x01 << 7);\
 })
+#elif defined(CONFIG_M523x)
+#define HARD_RESET_NOW() ({		\
+	asm("				\
+	movew #0x2700, %sr;		\
+	movel #0x01000000, %sp;		\
+	moveal #0x40110000, %a0;	\
+	moveb #0x80, (%a0);		\
+	");				\
+})
 #else
 #define HARD_RESET_NOW() ({		\
         asm("				\
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index dbe13da..cbd1672 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -358,16 +358,6 @@
 extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
 
-static inline int io_remap_page_range(struct vm_area_struct *vma,
-		unsigned long vaddr,
-		unsigned long paddr,
-		unsigned long size,
-		pgprot_t prot)
-{
-	phys_t phys_addr_high = fixup_bigphys_addr(paddr, size);
-	return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
-}
-
 static inline int io_remap_pfn_range(struct vm_area_struct *vma,
 		unsigned long vaddr,
 		unsigned long pfn,
@@ -378,8 +368,6 @@
 	return remap_pfn_range(vma, vaddr, pfn, size, prot);
 }
 #else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index f001bb0..820c6e7 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -498,9 +498,6 @@
 
 #endif /* !__ASSEMBLY__ */
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-powerpc/siginfo.h b/include/asm-powerpc/siginfo.h
index 538ea8e..12f1bce 100644
--- a/include/asm-powerpc/siginfo.h
+++ b/include/asm-powerpc/siginfo.h
@@ -15,4 +15,12 @@
 
 #include <asm-generic/siginfo.h>
 
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRANCH	(__SI_FAULT|3)	/* process taken branch trap */
+#define TRAP_HWBKPT	(__SI_FAULT|4)	/* hardware breakpoint or watchpoint */
+#undef NSIGTRAP
+#define NSIGTRAP	4
+
 #endif	/* _ASM_POWERPC_SIGINFO_H */
diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
index 835930d..75c2ffa 100644
--- a/include/asm-ppc/mv64x60.h
+++ b/include/asm-ppc/mv64x60.h
@@ -119,6 +119,14 @@
 
 #define	MV64x60_64BIT_WIN_COUNT			24
 
+/* Watchdog Platform Device, Driver Data */
+#define	MV64x60_WDT_NAME			"wdt"
+
+struct mv64x60_wdt_pdata {
+	int	timeout;	/* watchdog expiry in seconds, default 10 */
+	int	bus_clk;	/* bus clock in MHz, default 133 */
+};
+
 /*
  * Define a structure that's used to pass in config information to the
  * core routines.
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 92f30b2..eee601b 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -812,15 +812,6 @@
 #ifdef CONFIG_PHYS_64BIT
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
 			unsigned long paddr, unsigned long size, pgprot_t prot);
-static inline int io_remap_page_range(struct vm_area_struct *vma,
-					unsigned long vaddr,
-					unsigned long paddr,
-					unsigned long size,
-					pgprot_t prot)
-{
-	phys_addr_t paddr64 = fixup_bigphys_addr(paddr, size);
-	return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
-}
 
 static inline int io_remap_pfn_range(struct vm_area_struct *vma,
 					unsigned long vaddr,
@@ -832,8 +823,6 @@
 	return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
 }
 #else
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 #endif
diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
index 9d4e4ea..7043c16 100644
--- a/include/asm-ppc/ptrace.h
+++ b/include/asm-ppc/ptrace.h
@@ -142,4 +142,11 @@
 #define PTRACE_GETEVRREGS	20
 #define PTRACE_SETEVRREGS	21
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG	25
+#define PTRACE_SET_DEBUGREG	26
+
 #endif
diff --git a/include/asm-ppc/segment.h b/include/asm-ppc/segment.h
deleted file mode 100644
index 0f2f742..0000000
--- a/include/asm-ppc/segment.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm/uaccess.h>
diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
index 4f668a4..ab7c3cf 100644
--- a/include/asm-ppc64/hvcall.h
+++ b/include/asm-ppc64/hvcall.h
@@ -56,6 +56,11 @@
 #define H_PP1			(1UL<<(63-62))
 #define H_PP2			(1UL<<(63-63))
 
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR	(1UL<<(63-61))
+#define H_DABRX_KERNEL		(1UL<<(63-62))
+#define H_DABRX_USER		(1UL<<(63-63))
+
 /* pSeries hypervisor opcodes */
 #define H_REMOVE		0x04
 #define H_ENTER			0x08
@@ -101,6 +106,7 @@
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA             0x110
+#define H_SET_XDABR		0x134
 #define H_STUFF_TCE		0x138
 #define H_PUT_TCE_INDIRECT	0x13C
 #define H_VTERM_PARTNER_INFO	0x150
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 9a1ef44..8027160 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -88,6 +88,7 @@
 
 	/* PCI stuff */
 	void		(*pcibios_fixup)(void);
+	int		(*pci_probe_mode)(struct pci_bus *);
 
 	void		(*restart)(char *cmd);
 	void		(*power_off)(void);
@@ -173,10 +174,6 @@
 void ppc64_boot_msg(unsigned int src, const char *msg);
 /* Print a termination message (print only -- does not stop the kernel) */
 void ppc64_terminate_msg(unsigned int src, const char *msg);
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg);
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg);
 
 static inline void log_error(char *buf, unsigned int err_type, int fatal)
 {
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index 6b4a5b1..d899138 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -119,5 +119,10 @@
 	return PCI_DN(busdn)->phb;
 }
 
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE		-1	/* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL	0	/* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE	1	/* Instantiate from device tree */
+
 #endif
 #endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h
index f4a5fb7..72dd244 100644
--- a/include/asm-ppc64/plpar_wrappers.h
+++ b/include/asm-ppc64/plpar_wrappers.h
@@ -107,5 +107,14 @@
 				  lbuf[1]);
 }
 
+static inline long plpar_set_xdabr(unsigned long address, unsigned long flags)
+{
+	return plpar_hcall_norets(H_SET_XDABR, address, flags);
+}
+
+static inline long plpar_set_dabr(unsigned long val)
+{
+	return plpar_hcall_norets(H_SET_DABR, val);
+}
 
 #endif /* _PPC64_PLPAR_WRAPPERS_H */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index 8bd7aa9..4146189 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -433,6 +433,7 @@
 	unsigned long	start_tb;	/* Start purr when proc switched in */
 	unsigned long	accum_tb;	/* Total accumilated purr for process */
 	unsigned long	vdso_base;	/* base of the vDSO library */
+	unsigned long	dabr;		/* Data address breakpoint register */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
 	vector128	vr[32] __attribute((aligned(16)));
diff --git a/include/asm-ppc64/ptrace-common.h b/include/asm-ppc64/ptrace-common.h
index af03547..b1babb7 100644
--- a/include/asm-ppc64/ptrace-common.h
+++ b/include/asm-ppc64/ptrace-common.h
@@ -11,6 +11,10 @@
 
 #ifndef _PPC64_PTRACE_COMMON_H
 #define _PPC64_PTRACE_COMMON_H
+
+#include <linux/config.h>
+#include <asm/system.h>
+
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
@@ -69,4 +73,92 @@
 	clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
 }
 
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the
+ * same structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long __user *data,
+			     struct task_struct *task)
+{
+	unsigned long regsize;
+
+	/* copy AltiVec registers VR[0] .. VR[31] */
+	regsize = 32 * sizeof(vector128);
+	if (copy_to_user(data, task->thread.vr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
+
+	/* copy VSCR */
+	regsize = 1 * sizeof(vector128);
+	if (copy_to_user(data, &task->thread.vscr, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
+
+	/* copy VRSAVE */
+	if (put_user(task->thread.vrsave, (u32 __user *)data))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task,
+			     unsigned long __user *data)
+{
+	unsigned long regsize;
+
+	/* copy AltiVec registers VR[0] .. VR[31] */
+	regsize = 32 * sizeof(vector128);
+	if (copy_from_user(task->thread.vr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
+
+	/* copy VSCR */
+	regsize = 1 * sizeof(vector128);
+	if (copy_from_user(&task->thread.vscr, data, regsize))
+		return -EFAULT;
+	data += (regsize / sizeof(unsigned long));
+
+	/* copy VRSAVE */
+	if (get_user(task->thread.vrsave, (u32 __user *)data))
+		return -EFAULT;
+
+	return 0;
+}
+#endif
+
+static inline int ptrace_set_debugreg(struct task_struct *task,
+				      unsigned long addr, unsigned long data)
+{
+	/* We only support one DABR and no IABRS at the moment */
+	if (addr > 0)
+		return -EINVAL;
+
+	/* The bottom 3 bits are flags */
+	if ((data & ~0x7UL) >= TASK_SIZE)
+		return -EIO;
+
+	/* Ensure translation is on */
+	if (data && !(data & DABR_TRANSLATION))
+		return -EIO;
+
+	task->thread.dabr = data;
+	return 0;
+}
+
 #endif /* _PPC64_PTRACE_COMMON_H */
diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h
index c96aad2..3a55377 100644
--- a/include/asm-ppc64/ptrace.h
+++ b/include/asm-ppc64/ptrace.h
@@ -25,56 +25,49 @@
  */
 
 #ifndef __ASSEMBLY__
-#define PPC_REG unsigned long
+
 struct pt_regs {
-	PPC_REG gpr[32];
-	PPC_REG nip;
-	PPC_REG msr;
-	PPC_REG orig_gpr3;	/* Used for restarting system calls */
-	PPC_REG ctr;
-	PPC_REG link;
-	PPC_REG xer;
-	PPC_REG ccr;
-	PPC_REG softe;		/* Soft enabled/disabled */
-	PPC_REG trap;		/* Reason for being here */
-	PPC_REG dar;		/* Fault registers */
-	PPC_REG dsisr;
-	PPC_REG result; 	/* Result of a system call */
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long orig_gpr3; /* Used for restarting system calls */
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long softe;	/* Soft enabled/disabled */
+	unsigned long trap;	/* Reason for being here */
+	unsigned long dar;	/* Fault registers */
+	unsigned long dsisr;
+	unsigned long result;	/* Result of a system call */
 };
 
-#define PPC_REG_32 unsigned int
 struct pt_regs32 {
-	PPC_REG_32 gpr[32];
-	PPC_REG_32 nip;
-	PPC_REG_32 msr;
-	PPC_REG_32 orig_gpr3;	/* Used for restarting system calls */
-	PPC_REG_32 ctr;
-	PPC_REG_32 link;
-	PPC_REG_32 xer;
-	PPC_REG_32 ccr;
-	PPC_REG_32 mq;		/* 601 only (not used at present) */
-				/* Used on APUS to hold IPL value. */
-	PPC_REG_32 trap;		/* Reason for being here */
-	PPC_REG_32 dar;		/* Fault registers */
-	PPC_REG_32 dsisr;
-	PPC_REG_32 result; 	/* Result of a system call */
+	unsigned int gpr[32];
+	unsigned int nip;
+	unsigned int msr;
+	unsigned int orig_gpr3;	/* Used for restarting system calls */
+	unsigned int ctr;
+	unsigned int link;
+	unsigned int xer;
+	unsigned int ccr;
+	unsigned int mq;	/* 601 only (not used at present) */
+	unsigned int trap;	/* Reason for being here */
+	unsigned int dar;	/* Fault registers */
+	unsigned int dsisr;
+	unsigned int result;	/* Result of a system call */
 };
 
+#ifdef __KERNEL__
+
 #define instruction_pointer(regs) ((regs)->nip)
+
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
 
-#endif /* __ASSEMBLY__ */
-
-#define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
-
-/* Size of dummy stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE	128
-#define __SIGNAL_FRAMESIZE32	64
-
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
@@ -89,6 +82,16 @@
 #define TRAP(regs)		((regs)->trap & ~0xF)
 #define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1)
 
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
+
+/* Size of dummy stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE	128
+#define __SIGNAL_FRAMESIZE32	64
+
 /*
  * Offsets used by 'ptrace' system call interface.
  */
@@ -135,17 +138,21 @@
 #define PT_XER	37
 #define PT_CCR	38
 #define PT_SOFTE 39
+#define PT_TRAP	40
+#define PT_DAR	41
+#define PT_DSISR 42
 #define PT_RESULT 43
 
 #define PT_FPR0	48
 
-/* Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will have
- * visibility to the asm-ppc/ptrace.h header instead of this one.
+/*
+ * Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will
+ * have visibility to the asm-ppc/ptrace.h header instead of this one.
  */
-#define PT_FPSCR (PT_FPR0 + 32)	  /* each FP reg occupies 1 slot in 64-bit space */
+#define PT_FPSCR (PT_FPR0 + 32)	/* each FP reg occupies 1 slot in 64-bit space */
 
 #ifdef __KERNEL__
-#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)	  /* each FP reg occupies 2 32-bit userspace slots */
+#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)	/* each FP reg occupies 2 32-bit userspace slots */
 #endif
 
 #define PT_VR0 82	/* each Vector reg occupies 2 slots in 64-bit */
@@ -173,17 +180,34 @@
 #define PTRACE_GETVRREGS	18
 #define PTRACE_SETVRREGS	19
 
-/* Additional PTRACE requests implemented on PowerPC. */
-#define PPC_PTRACE_GETREGS	      0x99  /* Get GPRs 0 - 31 */
-#define PPC_PTRACE_SETREGS	      0x98  /* Set GPRs 0 - 31 */
-#define PPC_PTRACE_GETFPREGS	    0x97  /* Get FPRs 0 - 31 */
-#define PPC_PTRACE_SETFPREGS	    0x96  /* Set FPRs 0 - 31 */
-#define PPC_PTRACE_PEEKTEXT_3264  0x95  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKDATA_3264  0x94  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKETEXT_3264  0x93  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEDATA_3264  0x92  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKUSR_3264   0x91  /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEUSR_3264   0x90  /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */
+/*
+ * While we dont have 64bit book E processors, we need to reserve the
+ * relevant ptrace calls for 32bit compatibility.
+ */
+#if 0
+#define PTRACE_GETEVRREGS       20
+#define PTRACE_SETEVRREGS       21
+#endif
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG	25
+#define PTRACE_SET_DEBUGREG	26
+
+/* Additional PTRACE requests implemented on PowerPC. */
+#define PPC_PTRACE_GETREGS	0x99	/* Get GPRs 0 - 31 */
+#define PPC_PTRACE_SETREGS	0x98	/* Set GPRs 0 - 31 */
+#define PPC_PTRACE_GETFPREGS	0x97	/* Get FPRs 0 - 31 */
+#define PPC_PTRACE_SETFPREGS	0x96	/* Set FPRs 0 - 31 */
+
+/* Calls to trace a 64bit program from a 32bit program */
+#define PPC_PTRACE_PEEKTEXT_3264 0x95
+#define PPC_PTRACE_PEEKDATA_3264 0x94
+#define PPC_PTRACE_POKETEXT_3264 0x93
+#define PPC_PTRACE_POKEDATA_3264 0x92
+#define PPC_PTRACE_PEEKUSR_3264  0x91
+#define PPC_PTRACE_POKEUSR_3264  0x90
 
 #endif /* _PPC64_PTRACE_H */
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
index c039642..375015c 100644
--- a/include/asm-ppc64/system.h
+++ b/include/asm-ppc64/system.h
@@ -101,6 +101,9 @@
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
+extern int set_dabr(unsigned long dabr);
+extern void _exception(int signr, struct pt_regs *regs, int code,
+		       unsigned long addr);
 extern int fix_alignment(struct pt_regs *regs);
 extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
 			   int sig);
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index ecb9095..0f4bcaa 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -277,9 +277,6 @@
 
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 78ac6be..51db430 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -482,9 +482,6 @@
 #define PageSkip(page)		(0)
 #define kern_addr_valid(addr)	(1)
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 16ec82e..6c5d5ca 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -109,9 +109,10 @@
 #define NMI_LOCAL_APIC	2
 #define NMI_INVALID	3
 
+extern int disable_timer_pin_1;
+
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#define esr_disable 0
 extern unsigned boot_cpu_id;
 
 #endif /* __ASM_APIC_H */
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 9388062..fb1c99a 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -113,6 +113,7 @@
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
 #define MAX_IO_APICS 128
+#define MAX_LOCAL_APIC 256
 
 /*
  * All x86-64 systems are xAPIC compatible.
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index eed7856..80ac1fe 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -9,10 +9,8 @@
  */
 struct bug_frame {
 	unsigned char ud2[2];
-	unsigned char mov;
-	/* should use 32bit offset instead, but the assembler doesn't 
-	   like it */
-	char *filename;
+	unsigned char push;
+	signed int filename;
 	unsigned char ret;
 	unsigned short line;
 } __attribute__((packed));
@@ -25,8 +23,8 @@
    The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
 #define BUG() 								\
 	asm volatile(							\
-	"ud2 ; .byte 0xa3 ; .quad %c1 ; .byte 0xc2 ; .short %c0" :: 	\
-		     "i"(__LINE__), "i" (__stringify(__FILE__)))
+	"ud2 ; pushq $%c1 ; ret $%c0" :: 				\
+		     "i"(__LINE__), "i" (__FILE__))
 void out_of_line_bug(void);
 #else
 static inline void out_of_line_bug(void) { }
diff --git a/include/asm-x86_64/calling.h b/include/asm-x86_64/calling.h
index 0bc1265..fc2c5a6 100644
--- a/include/asm-x86_64/calling.h
+++ b/include/asm-x86_64/calling.h
@@ -65,27 +65,36 @@
 	.if \skipr11
 	.else
 	movq (%rsp),%r11
+	CFI_RESTORE r11
 	.endif
 	.if \skipr8910
 	.else
 	movq 1*8(%rsp),%r10
+	CFI_RESTORE r10
 	movq 2*8(%rsp),%r9
+	CFI_RESTORE r9
 	movq 3*8(%rsp),%r8
+	CFI_RESTORE r8
 	.endif
 	.if \skiprax
 	.else
 	movq 4*8(%rsp),%rax
+	CFI_RESTORE rax
 	.endif
 	.if \skiprcx
 	.else
 	movq 5*8(%rsp),%rcx
+	CFI_RESTORE rcx
 	.endif
 	.if \skiprdx
 	.else
 	movq 6*8(%rsp),%rdx
+	CFI_RESTORE rdx
 	.endif
 	movq 7*8(%rsp),%rsi
+	CFI_RESTORE rsi
 	movq 8*8(%rsp),%rdi
+	CFI_RESTORE rdi
 	.if ARG_SKIP+\addskip > 0
 	addq $ARG_SKIP+\addskip,%rsp
 	CFI_ADJUST_CFA_OFFSET	-(ARG_SKIP+\addskip)
@@ -124,11 +133,17 @@
 
 	.macro RESTORE_REST
 	movq (%rsp),%r15
+	CFI_RESTORE r15
 	movq 1*8(%rsp),%r14
+	CFI_RESTORE r14
 	movq 2*8(%rsp),%r13
+	CFI_RESTORE r13
 	movq 3*8(%rsp),%r12
+	CFI_RESTORE r12
 	movq 4*8(%rsp),%rbp
+	CFI_RESTORE rbp
 	movq 5*8(%rsp),%rbx
+	CFI_RESTORE rbx
 	addq $REST_SKIP,%rsp
 	CFI_ADJUST_CFA_OFFSET	-(REST_SKIP)
 	.endm
@@ -146,11 +161,3 @@
 	.macro icebp
 	.byte 0xf1
 	.endm
-
-#ifdef CONFIG_FRAME_POINTER
-#define ENTER enter
-#define LEAVE leave
-#else
-#define ENTER
-#define LEAVE
-#endif
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index c89b58b..594e610 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -191,7 +191,7 @@
 /*
  * load one particular LDT into the current CPU
  */
-extern inline void load_LDT_nolock (mm_context_t *pc, int cpu)
+static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
 {
 	int count = pc->size;
 
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index a416dc3..e784fdc 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -85,6 +85,11 @@
 	flush_write_buffers();
 }
 
+#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir)       \
+        dma_sync_single_for_cpu(dev, dma_handle, size, dir)
+#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir)    \
+        dma_sync_single_for_device(dev, dma_handle, size, dir)
+
 static inline void dma_sync_sg_for_cpu(struct device *hwdev,
 				       struct scatterlist *sg,
 				       int nelems, int direction)
diff --git a/include/asm-x86_64/dwarf2.h b/include/asm-x86_64/dwarf2.h
index afd4212..582757f 100644
--- a/include/asm-x86_64/dwarf2.h
+++ b/include/asm-x86_64/dwarf2.h
@@ -24,6 +24,10 @@
 #define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
 #define CFI_OFFSET .cfi_offset
 #define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
 
 #else
 
@@ -36,6 +40,10 @@
 #define CFI_ADJUST_CFA_OFFSET	#
 #define CFI_OFFSET	#
 #define CFI_REL_OFFSET	#
+#define CFI_REGISTER	#
+#define CFI_RESTORE	#
+#define CFI_REMEMBER_STATE	#
+#define CFI_RESTORE_STATE	#
 
 #endif
 
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index cf8b16c..a582cfc 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -76,7 +76,7 @@
  * directly without translation, we catch the bug with a NULL-deference
  * kernel oops. Illegal ranges of incoming indices are caught too.
  */
-extern inline unsigned long fix_to_virt(const unsigned int idx)
+static inline unsigned long fix_to_virt(const unsigned int idx)
 {
 	/*
 	 * this branch gets completely eliminated after inlining,
diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
index 27c381f..8661b47 100644
--- a/include/asm-x86_64/hardirq.h
+++ b/include/asm-x86_64/hardirq.h
@@ -9,11 +9,12 @@
 
 #define __ARCH_IRQ_STAT 1
 
-/* Generate a lvalue for a pda member. Should fix softirq.c instead to use
-   special access macros. This would generate better code. */ 
-#define __IRQ_STAT(cpu,member) (read_pda(me)->member)
+#define local_softirq_pending() read_pda(__softirq_pending)
 
-#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#define __ARCH_SET_SOFTIRQ_PENDING 1
+
+#define set_softirq_pending(x) write_pda(__softirq_pending, (x))
+#define or_softirq_pending(x)  or_pda(__softirq_pending, (x))
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 2b5cb28..dc97668 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -26,6 +26,7 @@
 struct hw_interrupt_type;
 #endif
 
+#define NMI_VECTOR		0x02
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
@@ -50,14 +51,15 @@
  */
 #define SPURIOUS_APIC_VECTOR	0xff
 #define ERROR_APIC_VECTOR	0xfe
-#define INVALIDATE_TLB_VECTOR	0xfd
-#define RESCHEDULE_VECTOR	0xfc
-#define TASK_MIGRATION_VECTOR	0xfb
-#define CALL_FUNCTION_VECTOR	0xfa
-#define KDB_VECTOR	0xf9
+#define RESCHEDULE_VECTOR	0xfd
+#define CALL_FUNCTION_VECTOR	0xfc
+#define KDB_VECTOR		0xfb	/* reserved for KDB */
+#define THERMAL_APIC_VECTOR	0xfa
+/* 0xf9 free */
+#define INVALIDATE_TLB_VECTOR_END	0xf8
+#define INVALIDATE_TLB_VECTOR_START	0xf0	/* f0-f8 used for TLB flush */
 
-#define THERMAL_APIC_VECTOR	0xf0
-
+#define NUM_INVALIDATE_TLB_VECTORS	8
 
 /*
  * Local APIC timer IRQ vector is on a different priority level,
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 37fc3f1..52ff269 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -48,7 +48,7 @@
  * Talk about misusing macros..
  */
 #define __OUT1(s,x) \
-extern inline void out##s(unsigned x value, unsigned short port) {
+static inline void out##s(unsigned x value, unsigned short port) {
 
 #define __OUT2(s,s1,s2) \
 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
@@ -58,7 +58,7 @@
 __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
 
 #define __IN1(s) \
-extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
 
 #define __IN2(s,s1,s2) \
 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
@@ -68,12 +68,12 @@
 __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
 
 #define __INS(s) \
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; ins" #s \
 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
 #define __OUTS(s) \
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; outs" #s \
 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
@@ -110,12 +110,12 @@
  * Change virtual addresses to physical addresses and vv.
  * These are pretty trivial
  */
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
 {
 	return __pa(address);
 }
 
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
 {
 	return __va(address);
 }
@@ -130,7 +130,7 @@
 
 extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
diff --git a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h
index 5e166b9..022e9d3 100644
--- a/include/asm-x86_64/ipi.h
+++ b/include/asm-x86_64/ipi.h
@@ -31,9 +31,20 @@
 
 static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
 {
-	unsigned int icr =  APIC_DM_FIXED | shortcut | vector | dest;
-	if (vector == KDB_VECTOR)
-		icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
+	unsigned int icr = shortcut | dest;
+
+	switch (vector) {
+	default:
+		icr |= APIC_DM_FIXED | vector;
+		break;
+	case NMI_VECTOR:
+		/*
+		 * Setup KDB IPI to be delivered as an NMI
+		 */
+	case KDB_VECTOR:
+		icr |= APIC_DM_NMI;
+		break;
+	}
 	return icr;
 }
 
@@ -66,7 +77,7 @@
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
-	apic_write_around(APIC_ICR, cfg);
+	apic_write(APIC_ICR, cfg);
 }
 
 
@@ -92,7 +103,7 @@
 		 * prepare target chip field
 		 */
 		cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
-		apic_write_around(APIC_ICR2, cfg);
+		apic_write(APIC_ICR2, cfg);
 
 		/*
 		 * program the ICR
@@ -102,7 +113,7 @@
 		/*
 		 * Send the IPI. The write to APIC_ICR fires this off.
 		 */
-		apic_write_around(APIC_ICR, cfg);
+		apic_write(APIC_ICR, cfg);
 	}
 	local_irq_restore(flags);
 }
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index b903419..f604e84 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -46,7 +46,7 @@
 extern void __die(const char *,struct pt_regs *,long);
 extern void show_registers(struct pt_regs *regs);
 extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
 
 #endif
diff --git a/include/asm-x86_64/local.h b/include/asm-x86_64/local.h
index c954f15..3e72c41 100644
--- a/include/asm-x86_64/local.h
+++ b/include/asm-x86_64/local.h
@@ -29,7 +29,7 @@
 		:"m" (v->counter));
 }
 
-static __inline__ void local_add(unsigned long i, local_t *v)
+static __inline__ void local_add(unsigned int i, local_t *v)
 {
 	__asm__ __volatile__(
 		"addl %1,%0"
@@ -37,7 +37,7 @@
 		:"ir" (i), "m" (v->counter));
 }
 
-static __inline__ void local_sub(unsigned long i, local_t *v)
+static __inline__ void local_sub(unsigned int i, local_t *v)
 {
 	__asm__ __volatile__(
 		"subl %1,%0"
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 7684137..b40c661 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -12,7 +12,7 @@
 
 #include <asm/smp.h>
 
-#define NODEMAPSIZE 0xff
+#define NODEMAPSIZE 0xfff
 
 /* Simple perfect hash to map physical addresses to node numbers */
 extern int memnode_shift; 
@@ -54,7 +54,7 @@
 
 #define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \
 			({ u8 nid__ = pfn_to_nid(pfn); \
-			   nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
+			   nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); }))
 #endif
 
 #define local_mapnr(kvaddr) \
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index ba15279..4d727f3 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -29,22 +29,37 @@
 #define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32) 
 
 /* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__;						\
-	asm volatile("2: wrmsr ; xorl %0,%0\n"						\
-		     "1:\n\t"								\
-		     ".section .fixup,\"ax\"\n\t"					\
-		     "3:  movl %4,%0 ; jmp 1b\n\t"					\
-		     ".previous\n\t"							\
- 		     ".section __ex_table,\"a\"\n"					\
-		     "   .align 8\n\t"							\
-		     "   .quad 	2b,3b\n\t"						\
-		     ".previous"							\
-		     : "=a" (ret__)							\
-		     : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
+#define wrmsr_safe(msr,a,b) ({ int ret__;			\
+	asm volatile("2: wrmsr ; xorl %0,%0\n"			\
+		     "1:\n\t"					\
+		     ".section .fixup,\"ax\"\n\t"		\
+		     "3:  movl %4,%0 ; jmp 1b\n\t"		\
+		     ".previous\n\t"				\
+ 		     ".section __ex_table,\"a\"\n"		\
+		     "   .align 8\n\t"				\
+		     "   .quad 	2b,3b\n\t"			\
+		     ".previous"				\
+		     : "=a" (ret__)				\
+		     : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
 	ret__; })
 
 #define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
 
+#define rdmsr_safe(msr,a,b) \
+	({ int ret__;						\
+	  asm volatile ("1:       rdmsr\n"			\
+                      "2:\n"					\
+                      ".section .fixup,\"ax\"\n"		\
+                      "3:       movl %4,%0\n"			\
+                      " jmp 2b\n"				\
+                      ".previous\n"				\
+                      ".section __ex_table,\"a\"\n"		\
+                      " .align 8\n"				\
+                      " .quad 1b,3b\n"				\
+                      ".previous":"=&bDS" (ret__), "=a"(a), "=d"(b)\
+                      :"c"(msr), "i"(-EIO), "0"(0));		\
+	  ret__; })		
+
 #define rdtsc(low,high) \
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
 
@@ -64,7 +79,7 @@
 			  : "=a" (low), "=d" (high) \
 			  : "c" (counter))
 
-extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
 			 unsigned int *ecx, unsigned int *edx)
 {
 	__asm__("cpuid"
@@ -90,7 +105,7 @@
 /*
  * CPUID functions returning a single datum
  */
-extern inline unsigned int cpuid_eax(unsigned int op)
+static inline unsigned int cpuid_eax(unsigned int op)
 {
 	unsigned int eax;
 
@@ -100,7 +115,7 @@
 		: "bx", "cx", "dx");
 	return eax;
 }
-extern inline unsigned int cpuid_ebx(unsigned int op)
+static inline unsigned int cpuid_ebx(unsigned int op)
 {
 	unsigned int eax, ebx;
 
@@ -110,7 +125,7 @@
 		: "cx", "dx" );
 	return ebx;
 }
-extern inline unsigned int cpuid_ecx(unsigned int op)
+static inline unsigned int cpuid_ecx(unsigned int op)
 {
 	unsigned int eax, ecx;
 
@@ -120,7 +135,7 @@
 		: "bx", "dx" );
 	return ecx;
 }
-extern inline unsigned int cpuid_edx(unsigned int op)
+static inline unsigned int cpuid_edx(unsigned int op)
 {
 	unsigned int eax, edx;
 
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index 5c363a1..bcf55c3 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -9,6 +9,7 @@
 };
 
 extern int compute_hash_shift(struct node *nodes, int numnodes);
+extern int pxm_to_node(int nid);
 
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
@@ -16,6 +17,8 @@
 extern void numa_init_array(void);
 extern int numa_off;
 
+extern unsigned char apicid_to_node[256];
+
 #define NUMA_NO_NODE 0xff
 
 #endif
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 135ffaa..e5ab4d2 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -32,6 +32,8 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+extern unsigned long end_pfn;
+
 void clear_page(void *);
 void copy_page(void *, void *);
 
@@ -111,7 +113,7 @@
 #ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
-#define pfn_valid(pfn)		((pfn) < max_mapnr)
+#define pfn_valid(pfn)		((pfn) < end_pfn)
 #endif
 
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index eeb3088..5a82a67 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -50,10 +50,10 @@
  * address space.  The networking and block device layers use
  * this boolean for bounce buffer decisions
  *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
+ * On x86-64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an hard or soft IOMMU is available.
  */
-#define PCI_DMA_BUS_IS_PHYS	(no_iommu ? 1 : 0)
+#define PCI_DMA_BUS_IS_PHYS 0
 
 /*
  * x86-64 always supports DAC, but sometimes it is useful to force
diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h
index 36b766c..bbf89aa 100644
--- a/include/asm-x86_64/pda.h
+++ b/include/asm-x86_64/pda.h
@@ -10,10 +10,8 @@
 struct x8664_pda {
 	struct task_struct *pcurrent;	/* Current process */
 	unsigned long data_offset;	/* Per cpu data offset from linker address */
-	struct x8664_pda *me;	    /* Pointer to itself */  
 	unsigned long kernelstack;  /* top of kernel stack for current */ 
 	unsigned long oldrsp; 	    /* user rsp for system call */
-	unsigned long irqrsp;	    /* Old rsp for interrupts. */ 
         int irqcount;		    /* Irq nesting counter. Starts with -1 */  	
 	int cpunumber;		    /* Logical CPU number */
 	char *irqstackptr;	/* top of irqstack */
@@ -22,7 +20,7 @@
 	struct mm_struct *active_mm;
 	int mmu_state;     
 	unsigned apic_timer_irqs;
-} ____cacheline_aligned;
+} ____cacheline_aligned_in_smp;
 
 
 #define IRQSTACK_ORDER 2
@@ -42,13 +40,14 @@
 #define pda_offset(field) offsetof(struct x8664_pda, field)
 
 #define pda_to_op(op,field,val) do { \
+	typedef typeof_field(struct x8664_pda, field) T__; \
        switch (sizeof_field(struct x8664_pda, field)) { 		\
 case 2: \
-asm volatile(op "w %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 4: \
-asm volatile(op "l %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 8: \
-asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
        default: __bad_pda_field(); 					\
        } \
        } while (0)
@@ -58,7 +57,7 @@
  * Unfortunately removing them causes all hell to break lose currently.
  */
 #define pda_from_op(op,field) ({ \
-       typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \
+       typeof_field(struct x8664_pda, field) ret__; \
        switch (sizeof_field(struct x8664_pda, field)) { 		\
 case 2: \
 asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
@@ -75,6 +74,7 @@
 #define write_pda(field,val) pda_to_op("mov",field,val)
 #define add_pda(field,val) pda_to_op("add",field,val)
 #define sub_pda(field,val) pda_to_op("sub",field,val)
+#define or_pda(field,val) pda_to_op("or",field,val)
 
 #endif
 
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
index deadd14..08cad24 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -18,12 +18,12 @@
 	set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
 }
 
-extern __inline__ pmd_t *get_pmd(void)
+static inline pmd_t *get_pmd(void)
 {
 	return (pmd_t *)get_zeroed_page(GFP_KERNEL);
 }
 
-extern __inline__ void pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
 {
 	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
 	free_page((unsigned long)pmd);
@@ -86,13 +86,13 @@
 /* Should really implement gc for free page table pages. This could be
    done with a reference count in struct page. */
 
-extern __inline__ void pte_free_kernel(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
 {
 	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
 	free_page((unsigned long)pte); 
 }
 
-extern inline void pte_free(struct page *pte)
+static inline void pte_free(struct page *pte)
 {
 	__free_page(pte);
 } 
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 5e0f2fd..2cb4835 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -85,7 +85,7 @@
 	pud_val(*dst) = pud_val(val);
 }
 
-extern inline void pud_clear (pud_t *pud)
+static inline void pud_clear (pud_t *pud)
 {
 	set_pud(pud, __pud(0));
 }
@@ -95,7 +95,7 @@
 	pgd_val(*dst) = pgd_val(val); 
 } 
 
-extern inline void pgd_clear (pgd_t * pgd)
+static inline void pgd_clear (pgd_t * pgd)
 {
 	set_pgd(pgd, __pgd(0));
 }
@@ -375,7 +375,7 @@
 }
  
 /* Change flags of a PTE */
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
 	pte_val(pte) &= _PAGE_CHG_MASK;
 	pte_val(pte) |= pgprot_val(newprot);
@@ -421,9 +421,6 @@
 
 extern int kern_addr_valid(unsigned long addr); 
 
-#define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
-		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
-
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index a832199..03837d3 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -254,7 +254,13 @@
 	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
 
-#define INIT_THREAD  {}
+#define INIT_THREAD  { \
+	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+#define INIT_TSS  { \
+	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
@@ -375,13 +381,13 @@
 #define ASM_NOP_MAX 8
 
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-extern inline void rep_nop(void)
+static inline void rep_nop(void)
 {
 	__asm__ __volatile__("rep;nop": : :"memory");
 }
 
 /* Stop speculative execution */
-extern inline void sync_core(void)
+static inline void sync_core(void)
 { 
 	int tmp;
 	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index f757419..dbb37b0 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -74,9 +74,6 @@
 
 extern void swap_low_mappings(void);
 
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
 extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
@@ -93,8 +90,6 @@
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
 
-extern unsigned long max_mapnr;
-extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
 
 extern int exception_trace;
diff --git a/include/asm-x86_64/signal.h b/include/asm-x86_64/signal.h
index fe9b96d..f8d5579 100644
--- a/include/asm-x86_64/signal.h
+++ b/include/asm-x86_64/signal.h
@@ -143,23 +143,23 @@
 #undef __HAVE_ARCH_SIG_BITOPS
 #if 0
 
-extern __inline__ void sigaddset(sigset_t *set, int _sig)
+static inline void sigaddset(sigset_t *set, int _sig)
 {
 	__asm__("btsq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ void sigdelset(sigset_t *set, int _sig)
+static inline void sigdelset(sigset_t *set, int _sig)
 {
 	__asm__("btrq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ int __const_sigismember(sigset_t *set, int _sig)
+static inline int __const_sigismember(sigset_t *set, int _sig)
 {
 	unsigned long sig = _sig - 1;
 	return 1 & (set->sig[sig / _NSIG_BPW] >> (sig & ~(_NSIG_BPW-1)));
 }
 
-extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
+static inline int __gen_sigismember(sigset_t *set, int _sig)
 {
 	int ret;
 	__asm__("btq %2,%1\n\tsbbq %0,%0"
@@ -172,7 +172,7 @@
 	 __const_sigismember((set),(sig)) :	\
 	 __gen_sigismember((set),(sig)))
 
-extern __inline__ int sigfindinword(unsigned long word)
+static inline int sigfindinword(unsigned long word)
 {
 	__asm__("bsfq %1,%0" : "=r"(word) : "rm"(word) : "cc");
 	return word;
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index de8b57b..24e3261 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -72,7 +72,7 @@
 
 #define raw_smp_processor_id() read_pda(cpunumber)
 
-extern __inline int hard_smp_processor_id(void)
+static inline int hard_smp_processor_id(void)
 {
 	/* we don't want to mark this access volatile - bad code generation */
 	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 8606e17..85348e0 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -188,7 +188,7 @@
 
 #define __xg(x) ((volatile long *)(x))
 
-extern inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
 {
 	*ptr = val;
 }
@@ -253,19 +253,19 @@
 	case 2:
 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
 				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
 				     : "memory");
 		return prev;
 	case 4:
 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
 				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
 				     : "memory");
 		return prev;
 	case 8:
 		__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
 				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
 				     : "memory");
 		return prev;
 	}
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 24ecf6a..f971f45 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -6,7 +6,6 @@
 #ifndef _ASMx8664_TIMEX_H
 #define _ASMx8664_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/8253pit.h>
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h
index 505b0cf..4a9c20e 100644
--- a/include/asm-x86_64/tlbflush.h
+++ b/include/asm-x86_64/tlbflush.h
@@ -109,6 +109,10 @@
 #define TLBSTATE_OK	1
 #define TLBSTATE_LAZY	2
 
+/* Roughly an IPI every 20MB with 4k pages for freeing page table
+   ranges. Cost is about 42k of memory for each CPU. */
+#define ARCH_FREE_PTE_NR 5350	
+
 #endif
 
 #define flush_tlb_kernel_range(start, end) flush_tlb_all()
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index c1bc3fa..1c603cd 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -13,7 +13,6 @@
 extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
-extern unsigned char pci_bus_to_node[];
 extern cpumask_t     node_to_cpumask[];
 
 #ifdef CONFIG_ACPI_NUMA
@@ -26,7 +25,7 @@
 #define parent_node(node)		(node)
 #define node_to_first_cpu(node) 	(__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)		(node_to_cpumask[node])
-#define pcibus_to_node(bus)		pci_bus_to_node[(bus)->number]
+#define pcibus_to_node(bus)		((long)(bus->sysdata))	
 #define pcibus_to_cpumask(bus)		node_to_cpumask(pcibus_to_node(bus));
 
 /* sched_domains SD_NODE_INIT for x86_64 machines */
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index 2872da2..438a3f5 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -29,7 +29,6 @@
 
 struct vxtime_data {
 	long hpet_address;	/* HPET base address */
-	unsigned long hz;	/* HPET clocks / sec */
 	int last;
 	unsigned long last_tsc;
 	long quot;
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 883ebc2..987e3b8 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -441,11 +441,11 @@
 			      unsigned long address, pte_t pte);
 
 /*
- * remap a physical address `phys' of size `size' with page protection `prot'
+ * remap a physical page `pfn' of size `size' with page protection `prot'
  * into virtual address `from'
  */
-#define io_remap_page_range(vma,from,phys,size,prot) \
-                remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+                remap_pfn_range(vma, from, pfn, size, prot)
 
 
 /* No page table caches to init */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 68aba0c..b2a2509 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -51,7 +51,8 @@
 #define AUDIT_WATCH_LIST	1009	/* List all file/dir watches */
 #define AUDIT_SIGNAL_INFO	1010	/* Get info about sender of signal to auditd */
 
-#define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages uninteresting to kernel */
+#define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages mostly uninteresting to kernel */
+#define AUDIT_USER_AVC		1107	/* We filter this differently */
 #define AUDIT_LAST_USER_MSG	1199
  
 #define AUDIT_DAEMON_START      1200    /* Daemon startup record */
@@ -75,10 +76,15 @@
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
-#define AUDIT_PER_TASK 0x01	/* Apply rule at task creation (not syscall) */
-#define AUDIT_AT_ENTRY 0x02	/* Apply rule at syscall entry */
-#define AUDIT_AT_EXIT  0x04	/* Apply rule at syscall exit */
-#define AUDIT_PREPEND  0x10	/* Prepend to front of list */
+#define AUDIT_FILTER_USER	0x00	/* Apply rule to user-generated messages */
+#define AUDIT_FILTER_TASK	0x01	/* Apply rule at task creation (not syscall) */
+#define AUDIT_FILTER_ENTRY	0x02	/* Apply rule at syscall entry */
+#define AUDIT_FILTER_WATCH	0x03	/* Apply rule to file system watches */
+#define AUDIT_FILTER_EXIT	0x04	/* Apply rule at syscall exit */
+
+#define AUDIT_NR_FILTERS	5
+
+#define AUDIT_FILTER_PREPEND	0x10	/* Prepend to front of list */
 
 /* Rule actions */
 #define AUDIT_NEVER    0	/* Do not build context if rule matches */
@@ -199,6 +205,7 @@
 struct audit_buffer;
 struct audit_context;
 struct inode;
+struct netlink_skb_parms;
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
@@ -215,7 +222,7 @@
 extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
 extern void audit_getname(const char *name);
 extern void audit_putname(const char *name);
-extern void audit_inode(const char *name, const struct inode *inode);
+extern void audit_inode(const char *name, const struct inode *inode, unsigned flags);
 
 				/* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
@@ -230,6 +237,7 @@
 extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
 extern void audit_signal_info(int sig, struct task_struct *t);
+extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -237,7 +245,7 @@
 #define audit_syscall_exit(t,f,r) do { ; } while (0)
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
-#define audit_inode(n,i) do { ; } while (0)
+#define audit_inode(n,i,f) do { ; } while (0)
 #define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
@@ -246,16 +254,17 @@
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
 #define audit_signal_info(s,t) do { ; } while (0)
+#define audit_filter_user(cb,t) ({ 1; })
 #endif
 
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
 				/* Public API */
-extern void		    audit_log(struct audit_context *ctx, int type,
-				      const char *fmt, ...)
-			    __attribute__((format(printf,3,4)));
+extern void		    audit_log(struct audit_context *ctx, int gfp_mask,
+				      int type, const char *fmt, ...)
+				      __attribute__((format(printf,4,5)));
 
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, int type);
 extern void		    audit_log_format(struct audit_buffer *ab,
 					     const char *fmt, ...)
 			    __attribute__((format(printf,2,3)));
@@ -274,9 +283,10 @@
 					     int done, int multi,
 					     void *payload, int size);
 extern void		    audit_log_lost(const char *message);
+extern struct semaphore audit_netlink_sem;
 #else
-#define audit_log(c,t,f,...) do { ; } while (0)
-#define audit_log_start(c,t) ({ NULL; })
+#define audit_log(c,g,t,f,...) do { ; } while (0)
+#define audit_log_start(c,g,t) ({ NULL; })
 #define audit_log_vformat(b,f,a) do { ; } while (0)
 #define audit_log_format(b,f,...) do { ; } while (0)
 #define audit_log_end(b) do { ; } while (0)
diff --git a/include/linux/crc16.h b/include/linux/crc16.h
index bdedf82..9443c08 100644
--- a/include/linux/crc16.h
+++ b/include/linux/crc16.h
@@ -1,22 +1,11 @@
 /*
  *	crc16.h - CRC-16 routine
  *
- * Implements the standard CRC-16, as used with 1-wire devices:
+ * Implements the standard CRC-16:
  *   Width 16
  *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
  *   Init  0
  *
- * For 1-wire devices, the CRC is stored inverted, LSB-first
- *
- * Example buffer with the CRC attached:
- *   31 32 33 34 35 36 37 38 39 C2 44
- *
- * The CRC over a buffer with the CRC attached is 0xB001.
- * So, if (crc16(0, buf, size) == 0xB001) then the buffer is valid.
- *
- * Refer to "Application Note 937: Book of iButton Standards" for details.
- * http://www.maxim-ic.com/appnotes.cfm/appnote_number/937
- *
  * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
  *
  * This source code is licensed under the GNU General Public License,
@@ -28,9 +17,6 @@
 
 #include <linux/types.h>
 
-#define CRC16_INIT		0
-#define CRC16_VALID		0xb001
-
 extern u16 const crc16_table[256];
 
 extern u16 crc16(u16 crc, const u8 *buffer, size_t len);
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index c30175e..a415f1d 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -70,7 +70,7 @@
 
 static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
 static inline char * dmi_get_system_info(int field) { return NULL; }
-static struct dmi_device * dmi_find_device(int type, const char *name,
+static inline struct dmi_device * dmi_find_device(int type, const char *name,
 	struct dmi_device *from) { return NULL; }
 
 #endif
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 82e39cd..c698055 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -619,7 +619,7 @@
 	__u32 height;               /* height of each tile in scanlines */
 	__u32 depth;                /* color depth of each tile */
 	__u32 length;               /* number of tiles in the map */
-	__u8  *data;                /* actual tile map: a bitmap array, packed
+	const __u8 *data;           /* actual tile map: a bitmap array, packed
 				       to the nearest byte */
 };
 
diff --git a/include/linux/font.h b/include/linux/font.h
index 8fc80a7..53b129f 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -15,9 +15,9 @@
 
 struct font_desc {
     int idx;
-    char *name;
+    const char *name;
     int width, height;
-    void *data;
+    const void *data;
     int pref;
 };
 
@@ -32,7 +32,7 @@
 #define ACORN8x8_IDX	8
 #define	MINI4x6_IDX	9
 
-extern struct font_desc	font_vga_8x8,
+extern const struct font_desc	font_vga_8x8,
 			font_vga_8x16,
 			font_pearl_8x8,
 			font_vga_6x11,
@@ -45,11 +45,11 @@
 
 /* Find a font with a specific name */
 
-extern struct font_desc *find_font(char *name);
+extern const struct font_desc *find_font(const char *name);
 
 /* Get the default font for a specific screen size */
 
-extern struct font_desc *get_default_font(int xres, int yres);
+extern const struct font_desc *get_default_font(int xres, int yres);
 
 /* Max. length for the name of a predefined font */
 #define MAX_FONT_NAME	32
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index d99e7ae..0a90205 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -57,6 +57,11 @@
 extern void enable_irq(unsigned int irq);
 #endif
 
+#ifndef __ARCH_SET_SOFTIRQ_PENDING
+#define set_softirq_pending(x) (local_softirq_pending() = (x))
+#define or_softirq_pending(x)  (local_softirq_pending() |= (x))
+#endif
+
 /*
  * Temporary defines for UP kernels, until all code gets fixed.
  */
@@ -123,7 +128,7 @@
 asmlinkage void do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
 extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 extern void FASTCALL(raise_softirq(unsigned int nr));
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 687ba8c..4367ce4 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -307,8 +307,8 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
-extern void BUILD_BUG(void);
-#define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
+/* Force a compilation error if condition is false */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
 
 #ifdef CONFIG_SYSCTL
 extern int randomize_va_space;
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 4d24d65..8903688 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -438,17 +438,22 @@
 extern int nfsd4_process_open2(struct svc_rqst *rqstp, 
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern int nfsd4_open_confirm(struct svc_rqst *rqstp, 
-		struct svc_fh *current_fh, struct nfsd4_open_confirm *oc);
+		struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
+		struct nfs4_stateowner **);
 extern  int nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
-		struct nfsd4_close *close);
+		struct nfsd4_close *close,
+		struct nfs4_stateowner **replay_owner);
 extern int nfsd4_open_downgrade(struct svc_rqst *rqstp, 
-		struct svc_fh *current_fh, struct nfsd4_open_downgrade *od);
+		struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
+		struct nfs4_stateowner **replay_owner);
 extern int nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
-		struct nfsd4_lock *lock);
+		struct nfsd4_lock *lock,
+		struct nfs4_stateowner **replay_owner);
 extern int nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
 		struct nfsd4_lockt *lockt);
 extern int nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, 
-		struct nfsd4_locku *locku);
+		struct nfsd4_locku *locku,
+		struct nfs4_stateowner **replay_owner);
 extern int
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
 		struct nfsd4_release_lockowner *rlockowner);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ee0ab7a..f6c1a14 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -447,6 +447,10 @@
 #define PCI_DEVICE_ID_CIRRUS_7542	0x1200
 #define PCI_DEVICE_ID_CIRRUS_7543	0x1202
 #define PCI_DEVICE_ID_CIRRUS_7541	0x1204
+#define PCI_DEVICE_ID_CIRRUS_4610	0x6001
+#define PCI_DEVICE_ID_CIRRUS_4612	0x6003
+#define PCI_DEVICE_ID_CIRRUS_4615	0x6004
+#define PCI_DEVICE_ID_CIRRUS_4281	0x6005
 
 #define PCI_VENDOR_ID_IBM		0x1014
 #define PCI_DEVICE_ID_IBM_FIRE_CORAL	0x000a
@@ -682,7 +686,9 @@
 #define PCI_DEVICE_ID_SI_6326		0x6326
 #define PCI_DEVICE_ID_SI_7001		0x7001
 #define PCI_DEVICE_ID_SI_7012		0x7012
+#define PCI_DEVICE_ID_SI_7013		0x7013
 #define PCI_DEVICE_ID_SI_7016		0x7016
+#define PCI_DEVICE_ID_SI_7018		0x7018
 
 #define PCI_VENDOR_ID_HP		0x103c
 #define PCI_DEVICE_ID_HP_VISUALIZE_EG	0x1005
@@ -713,10 +719,12 @@
 #define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
 #define PCI_DEVICE_ID_HP_DIVA_RMP3	0x1301
+#define PCI_DEVICE_ID_HP_CISS		0x3210
 #define PCI_DEVICE_ID_HP_CISSA		0x3220
 #define PCI_DEVICE_ID_HP_CISSB		0x3222
-#define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
 #define PCI_DEVICE_ID_HP_CISSC		0x3230
+#define PCI_DEVICE_ID_HP_CISSD		0x3238
+#define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
@@ -991,6 +999,7 @@
 #define PCI_DEVICE_ID_BROOKTREE_849A	0x0351
 #define PCI_DEVICE_ID_BROOKTREE_878_1	0x036e
 #define PCI_DEVICE_ID_BROOKTREE_878	0x0878
+#define PCI_DEVICE_ID_BROOKTREE_879	0x0879
 #define PCI_DEVICE_ID_BROOKTREE_8474	0x8474
 
 #define PCI_VENDOR_ID_SIERRA		0x10a8
@@ -1109,6 +1118,9 @@
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV       0x0005
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS   0x0083
+#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
+#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
+#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
 
 #define PCI_VENDOR_ID_ASP		0x10cd
 #define PCI_DEVICE_ID_ASP_ABP940	0x1200
@@ -1155,10 +1167,13 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS	0x0064
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_NVENET_2		0x0066
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM		0x0069
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS	0x0084
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
 #define PCI_DEVICE_ID_NVIDIA_NVENET_4		0x0086
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM	0x0089
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO		0x008a
 #define PCI_DEVICE_ID_NVIDIA_NVENET_5		0x008c
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
@@ -1173,6 +1188,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS	0x00d4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE	0x00d5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_3		0x00d6
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM		0x00d9
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
 #define PCI_DEVICE_ID_NVIDIA_NVENET_7		0x00df
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S		0x00e1
@@ -1180,6 +1196,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS	0x00e4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE	0x00e5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_6		0x00e6
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO		0x00ea
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2	0x00ee
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
@@ -1230,6 +1247,7 @@
 #define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO		0x01b1
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS	0x01b4
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
+#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM		0x01c1
 #define PCI_DEVICE_ID_NVIDIA_NVENET_1		0x01c3
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2		0x01e0
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
@@ -1334,6 +1352,13 @@
 #define PCI_DEVICE_ID_REALTEK_8169	0x8169
 
 #define PCI_VENDOR_ID_XILINX		0x10ee
+#define PCI_DEVICE_ID_RME_DIGI96	0x3fc0
+#define PCI_DEVICE_ID_RME_DIGI96_8	0x3fc1
+#define PCI_DEVICE_ID_RME_DIGI96_8_PRO	0x3fc2
+#define PCI_DEVICE_IDRME__DIGI96_8_PAD_OR_PST 0x3fc3
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL	0x3fc4
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
 #define PCI_DEVICE_ID_TURBOPAM		0x4020
 
 #define PCI_VENDOR_ID_TRUEVISION	0x10fa
@@ -1809,6 +1834,14 @@
 #define PCI_DEVICE_ID_ESS_ESS1968	0x1968
 #define PCI_DEVICE_ID_ESS_AUDIOPCI	0x1969
 #define PCI_DEVICE_ID_ESS_ESS1978	0x1978
+#define PCI_DEVICE_ID_ESS_ALLEGRO_1	0x1988
+#define PCI_DEVICE_ID_ESS_ALLEGRO	0x1989
+#define PCI_DEVICE_ID_ESS_CANYON3D_2LE	0x1990
+#define PCI_DEVICE_ID_ESS_CANYON3D_2	0x1992
+#define PCI_DEVICE_ID_ESS_MAESTRO3	0x1998
+#define PCI_DEVICE_ID_ESS_MAESTRO3_1	0x1999
+#define PCI_DEVICE_ID_ESS_MAESTRO3_HW	0x199a
+#define PCI_DEVICE_ID_ESS_MAESTRO3_2	0x199b
 
 #define PCI_VENDOR_ID_SATSAGEM		0x1267
 #define PCI_DEVICE_ID_SATSAGEM_NICCY	0x1016
@@ -1968,6 +2001,9 @@
 #define PCI_DEVICE_ID_LMC_SSI		0x0005
 #define PCI_DEVICE_ID_LMC_T1		0x0006
 
+#define PCI_VENDOR_ID_MARIAN		0x1382
+#define PCI_DEVICE_ID_MARIAN_PRODIF_PLUS 0x2048
+
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
 #define PCI_DEVICE_ID_NETGEAR_GA622	0x622a
@@ -2056,6 +2092,10 @@
 #define PCI_VENDOR_ID_TIMEDIA		0x1409
 #define PCI_DEVICE_ID_TIMEDIA_1889	0x7168
 
+#define PCI_VENDOR_ID_ICE		0x1412
+#define PCI_DEVICE_ID_ICE_1712		0x1712
+#define PCI_DEVICE_ID_VT1724		0x1724
+
 #define PCI_VENDOR_ID_OXSEMI		0x1415
 #define PCI_DEVICE_ID_OXSEMI_12PCI840	0x8403
 #define PCI_DEVICE_ID_OXSEMI_16PCI954	0x9501
@@ -2536,6 +2576,7 @@
 #define PCI_DEVICE_ID_INTEL_82443BX_1	0x7191
 #define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
+#define PCI_DEVICE_ID_INTEL_440MX_6	0x7196
 #define PCI_DEVICE_ID_INTEL_82443MX_0	0x7198
 #define PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
 #define PCI_DEVICE_ID_INTEL_82443MX_2	0x719a
@@ -2642,6 +2683,11 @@
 #define PCI_VENDOR_ID_TTTECH		0x0357
 #define PCI_DEVICE_ID_TTTECH_MC322	0x000A
 
+#define PCI_VENDOR_ID_XILINX_RME	0xea60
+#define PCI_DEVICE_ID_RME_DIGI32	0x9896
+#define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
+#define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
+
 #define PCI_VENDOR_ID_ARK		0xedd8
 #define PCI_DEVICE_ID_ARK_STING		0xa091
 #define PCI_DEVICE_ID_ARK_STINGARK	0xa099
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 4b32bce..2c177e4 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -166,6 +166,9 @@
 /*
  * 32 buffers of 2048 bytes
  */
+#if (PAGE_SIZE % CD_FRAMESIZE) != 0
+#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
+#endif
 #define PACKET_MAX_SIZE		32
 #define PAGES_PER_PACKET	(PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE)
 #define PACKET_MAX_SECTORS	(PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ed3bb19..49e617f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -121,6 +121,17 @@
 #define set_task_state(tsk, state_value)		\
 	set_mb((tsk)->state, (state_value))
 
+/*
+ * set_current_state() includes a barrier so that the write of current->state
+ * is correctly serialised wrt the caller's subsequent test of whether to
+ * actually sleep:
+ *
+ *	set_current_state(TASK_UNINTERRUPTIBLE);
+ *	if (do_i_need_to_sleep())
+ *		schedule();
+ *
+ * If the caller does not need such serialisation then use __set_current_state()
+ */
 #define __set_current_state(state_value)			\
 	do { current->state = (state_value); } while (0)
 #define set_current_state(state_value)		\
@@ -785,7 +796,6 @@
 	short il_next;
 #endif
 #ifdef CONFIG_CPUSETS
-	short cpuset_sem_nest_depth;
 	struct cpuset *cpuset;
 	nodemask_t mems_allowed;
 	int cpuset_mems_generation;
diff --git a/include/linux/security.h b/include/linux/security.h
index 55b02e1..0e43460 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1907,6 +1907,11 @@
 extern int unregister_security	(struct security_operations *ops);
 extern int mod_reg_security	(const char *name, struct security_operations *ops);
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
+extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
+					     struct dentry *parent, void *data,
+					     struct file_operations *fops);
+extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
+extern void securityfs_remove(struct dentry *dentry);
 
 
 #else /* CONFIG_SECURITY */
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index fb57c22..9facf73 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -32,7 +32,6 @@
 #define _LINUX_USBDEVICE_FS_H
 
 #include <linux/types.h>
-#include <linux/compat.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -125,6 +124,7 @@
 };
 
 #ifdef CONFIG_COMPAT
+#include <linux/compat.h>
 struct usbdevfs_urb32 {
 	unsigned char type;
 	unsigned char endpoint;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index f623a33..89a0557 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -60,12 +60,17 @@
 	 (field) == V4L2_FIELD_SEQ_BT)
 
 enum v4l2_buf_type {
-	V4L2_BUF_TYPE_VIDEO_CAPTURE  = 1,
-	V4L2_BUF_TYPE_VIDEO_OUTPUT   = 2,
-	V4L2_BUF_TYPE_VIDEO_OVERLAY  = 3,
-	V4L2_BUF_TYPE_VBI_CAPTURE    = 4,
-	V4L2_BUF_TYPE_VBI_OUTPUT     = 5,
-	V4L2_BUF_TYPE_PRIVATE        = 0x80,
+	V4L2_BUF_TYPE_VIDEO_CAPTURE      = 1,
+	V4L2_BUF_TYPE_VIDEO_OUTPUT       = 2,
+	V4L2_BUF_TYPE_VIDEO_OVERLAY      = 3,
+	V4L2_BUF_TYPE_VBI_CAPTURE        = 4,
+	V4L2_BUF_TYPE_VBI_OUTPUT         = 5,
+#if 1
+	/* Experimental Sliced VBI */
+	V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6,
+	V4L2_BUF_TYPE_SLICED_VBI_OUTPUT  = 7,
+#endif
+	V4L2_BUF_TYPE_PRIVATE            = 0x80,
 };
 
 enum v4l2_ctrl_type {
@@ -149,20 +154,24 @@
 };
 
 /* Values for 'capabilities' field */
-#define V4L2_CAP_VIDEO_CAPTURE	0x00000001  /* Is a video capture device */
-#define V4L2_CAP_VIDEO_OUTPUT	0x00000002  /* Is a video output device */
-#define V4L2_CAP_VIDEO_OVERLAY	0x00000004  /* Can do video overlay */
-#define V4L2_CAP_VBI_CAPTURE	0x00000010  /* Is a VBI capture device */
-#define V4L2_CAP_VBI_OUTPUT	0x00000020  /* Is a VBI output device */
-#define V4L2_CAP_RDS_CAPTURE	0x00000100  /* RDS data capture */
+#define V4L2_CAP_VIDEO_CAPTURE	        0x00000001  /* Is a video capture device */
+#define V4L2_CAP_VIDEO_OUTPUT	        0x00000002  /* Is a video output device */
+#define V4L2_CAP_VIDEO_OVERLAY	        0x00000004  /* Can do video overlay */
+#define V4L2_CAP_VBI_CAPTURE	        0x00000010  /* Is a raw VBI capture device */
+#define V4L2_CAP_VBI_OUTPUT	        0x00000020  /* Is a raw VBI output device */
+#if 1
+#define V4L2_CAP_SLICED_VBI_CAPTURE	0x00000040  /* Is a sliced VBI capture device */
+#define V4L2_CAP_SLICED_VBI_OUTPUT	0x00000080  /* Is a sliced VBI output device */
+#endif
+#define V4L2_CAP_RDS_CAPTURE	        0x00000100  /* RDS data capture */
 
-#define V4L2_CAP_TUNER		0x00010000  /* has a tuner */
-#define V4L2_CAP_AUDIO		0x00020000  /* has audio support */
-#define V4L2_CAP_RADIO		0x00040000  /* is a radio device */
+#define V4L2_CAP_TUNER		        0x00010000  /* has a tuner */
+#define V4L2_CAP_AUDIO		        0x00020000  /* has audio support */
+#define V4L2_CAP_RADIO		        0x00040000  /* is a radio device */
 
-#define V4L2_CAP_READWRITE      0x01000000  /* read/write systemcalls */
-#define V4L2_CAP_ASYNCIO        0x02000000  /* async I/O */
-#define V4L2_CAP_STREAMING      0x04000000  /* streaming I/O ioctls */
+#define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
+#define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
+#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */
 
 /*
  *	V I D E O   I M A G E   F O R M A T
@@ -809,6 +818,8 @@
  *	Data services API by Michael Schimek
  */
 
+/* Raw VBI */
+
 struct v4l2_vbi_format
 {
 	__u32	sampling_rate;		/* in 1 Hz */
@@ -825,6 +836,54 @@
 #define V4L2_VBI_UNSYNC		(1<< 0)
 #define V4L2_VBI_INTERLACED	(1<< 1)
 
+#if 1
+/* Sliced VBI
+ *
+ *    This implements is a proposal V4L2 API to allow SLICED VBI
+ * required for some hardware encoders. It should change without
+ * notice in the definitive implementation.
+ */
+
+struct v4l2_sliced_vbi_format
+{
+        __u16   service_set;
+        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+                                 (equals frame lines 313-336 for 625 line video
+                                  standards, 263-286 for 525 line standards) */
+        __u16   service_lines[2][24];
+        __u32   io_size;
+        __u32   reserved[2];            /* must be zero */
+};
+
+#define V4L2_SLICED_TELETEXT_B          (0x0001)
+#define V4L2_SLICED_VPS                 (0x0400)
+#define V4L2_SLICED_CAPTION_525         (0x1000)
+#define V4L2_SLICED_WSS_625             (0x4000)
+
+#define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
+#define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
+
+struct v4l2_sliced_vbi_cap
+{
+        __u16   service_set;
+        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
+           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
+                                 (equals frame lines 313-336 for 625 line video
+                                  standards, 263-286 for 525 line standards) */
+        __u16   service_lines[2][24];
+        __u32   reserved[4];    /* must be 0 */
+};
+
+struct v4l2_sliced_vbi_data
+{
+        __u32   id;
+        __u32   field;          /* 0: first field, 1: second field */
+        __u32   line;           /* 1-23 */
+        __u32   reserved;       /* must be 0 */
+        __u8    data[48];
+};
+#endif
 
 /*
  *	A G G R E G A T E   S T R U C T U R E S
@@ -837,10 +896,13 @@
 	enum v4l2_buf_type type;
 	union
 	{
-		struct v4l2_pix_format	pix;  // V4L2_BUF_TYPE_VIDEO_CAPTURE
-		struct v4l2_window	win;  // V4L2_BUF_TYPE_VIDEO_OVERLAY
-		struct v4l2_vbi_format	vbi;  // V4L2_BUF_TYPE_VBI_CAPTURE
-		__u8	raw_data[200];        // user-defined
+		struct v4l2_pix_format	        pix;     // V4L2_BUF_TYPE_VIDEO_CAPTURE
+		struct v4l2_window	        win;     // V4L2_BUF_TYPE_VIDEO_OVERLAY
+		struct v4l2_vbi_format	        vbi;     // V4L2_BUF_TYPE_VBI_CAPTURE
+#if 1
+		struct v4l2_sliced_vbi_format	sliced;  // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
+#endif
+		__u8	raw_data[200];                   // user-defined
 	} fmt;
 };
 
@@ -916,6 +978,9 @@
 #define VIDIOC_ENUMAUDOUT	_IOWR ('V', 66, struct v4l2_audioout)
 #define VIDIOC_G_PRIORITY       _IOR  ('V', 67, enum v4l2_priority)
 #define VIDIOC_S_PRIORITY       _IOW  ('V', 68, enum v4l2_priority)
+#if 1
+#define VIDIOC_G_SLICED_VBI_CAP _IOR  ('V', 69, struct v4l2_sliced_vbi_cap)
+#endif
 
 /* for compatibility, will go away some day */
 #define VIDIOC_OVERLAY_OLD     	_IOWR ('V', 14, int)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 371e7d3..fa2d12b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -463,6 +463,17 @@
 	__s8     rssi;
 } __attribute__ ((packed));
 
+#define HCI_EV_EXTENDED_INQUIRY_RESULT	0x2F
+struct extended_inquiry_info {
+	bdaddr_t bdaddr;
+	__u8     pscan_rep_mode;
+	__u8     pscan_period_mode;
+	__u8     dev_class[3];
+	__u16    clock_offset;
+	__s8     rssi;
+	__u8     data[240];
+} __attribute__ ((packed));
+
 #define HCI_EV_CONN_COMPLETE 	0x03
 struct hci_ev_conn_complete {
 	__u8     status;
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index da63722..c0e4c67 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -178,8 +178,8 @@
 
 extern struct scsi_device *__scsi_add_device(struct Scsi_Host *,
 		uint, uint, uint, void *hostdata);
-#define scsi_add_device(host, channel, target, lun) \
-	__scsi_add_device(host, channel, target, lun, NULL)
+extern int scsi_add_device(struct Scsi_Host *host, uint channel,
+			   uint target, uint lun);
 extern void scsi_remove_device(struct scsi_device *);
 extern int scsi_device_cancel(struct scsi_device *, int);
 
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 70ad163..115db05 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -439,4 +439,12 @@
 void fc_remote_port_unblock(struct fc_rport *rport);
 int scsi_is_fc_rport(const struct device *);
 
+static inline u64 wwn_to_u64(u8 *wwn)
+{
+	return (u64)wwn[0] << 56 | (u64)wwn[1] << 48 |
+	    (u64)wwn[2] << 40 | (u64)wwn[3] << 32 |
+	    (u64)wwn[4] << 24 | (u64)wwn[5] << 16 |
+	    (u64)wwn[6] <<  8 | (u64)wwn[7];
+}
+
 #endif /* SCSI_TRANSPORT_FC_H */
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
new file mode 100644
index 0000000..bc4aeb6
--- /dev/null
+++ b/include/scsi/scsi_transport_sas.h
@@ -0,0 +1,100 @@
+#ifndef SCSI_TRANSPORT_SAS_H
+#define SCSI_TRANSPORT_SAS_H
+
+#include <linux/transport_class.h>
+#include <linux/types.h>
+
+struct scsi_transport_template;
+struct sas_rphy;
+
+
+enum sas_device_type {
+	SAS_PHY_UNUSED,
+	SAS_END_DEVICE,
+	SAS_EDGE_EXPANDER_DEVICE,
+	SAS_FANOUT_EXPANDER_DEVICE,
+};
+
+enum sas_protocol {
+	SAS_PROTOCOL_SATA		= 0x01,
+	SAS_PROTOCOL_SMP		= 0x02,
+	SAS_PROTOCOL_STP		= 0x04,
+	SAS_PROTOCOL_SSP		= 0x08,
+};
+
+enum sas_linkrate {
+	SAS_LINK_RATE_UNKNOWN,
+	SAS_PHY_DISABLED,
+	SAS_LINK_RATE_FAILED,
+	SAS_SATA_SPINUP_HOLD,
+	SAS_SATA_PORT_SELECTOR,
+	SAS_LINK_RATE_1_5_GBPS,
+	SAS_LINK_RATE_3_0_GBPS,
+	SAS_LINK_VIRTUAL,
+};
+
+struct sas_identify {
+	enum sas_device_type	device_type;
+	enum sas_protocol	initiator_port_protocols;
+	enum sas_protocol	target_port_protocols;
+	u64			sas_address;
+	u8			phy_identifier;
+};
+
+/* The functions by which the transport class and the driver communicate */
+struct sas_function_template {
+};
+
+struct sas_phy {
+	struct device		dev;
+	int			number;
+	struct sas_identify	identify;
+	enum sas_linkrate	negotiated_linkrate;
+	enum sas_linkrate	minimum_linkrate_hw;
+	enum sas_linkrate	minimum_linkrate;
+	enum sas_linkrate	maximum_linkrate_hw;
+	enum sas_linkrate	maximum_linkrate;
+	u8			port_identifier;
+	struct sas_rphy		*rphy;
+};
+
+#define dev_to_phy(d) \
+	container_of((d), struct sas_phy, dev)
+#define transport_class_to_phy(cdev) \
+	dev_to_phy((cdev)->dev)
+#define phy_to_shost(phy) \
+	dev_to_shost((phy)->dev.parent)
+
+struct sas_rphy {
+	struct device		dev;
+	struct sas_identify	identify;
+	struct list_head	list;
+	u32			scsi_target_id;
+};
+
+#define dev_to_rphy(d) \
+	container_of((d), struct sas_rphy, dev)
+#define transport_class_to_rphy(cdev) \
+	dev_to_rphy((cdev)->dev)
+#define rphy_to_shost(rphy) \
+	dev_to_shost((rphy)->dev.parent)
+
+extern void sas_remove_host(struct Scsi_Host *);
+
+extern struct sas_phy *sas_phy_alloc(struct device *, int);
+extern void sas_phy_free(struct sas_phy *);
+extern int sas_phy_add(struct sas_phy *);
+extern void sas_phy_delete(struct sas_phy *);
+extern int scsi_is_sas_phy(const struct device *);
+
+extern struct sas_rphy *sas_rphy_alloc(struct sas_phy *);
+void sas_rphy_free(struct sas_rphy *);
+extern int sas_rphy_add(struct sas_rphy *);
+extern void sas_rphy_delete(struct sas_rphy *);
+extern int scsi_is_sas_rphy(const struct device *);
+
+extern struct scsi_transport_template *
+sas_attach_transport(struct sas_function_template *);
+extern void sas_release_transport(struct scsi_transport_template *);
+
+#endif /* SCSI_TRANSPORT_SAS_H */
diff --git a/include/sound/core.h b/include/sound/core.h
index 3dc41fd..26160ad 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -168,6 +168,9 @@
 	wait_queue_head_t shutdown_sleep;
 	struct work_struct free_workq;	/* for free in workqueue */
 	struct device *dev;
+#ifdef CONFIG_SND_GENERIC_DRIVER
+	struct snd_generic_device *generic_dev;
+#endif
 
 #ifdef CONFIG_PM
 	int (*pm_suspend)(snd_card_t *card, pm_message_t state);
@@ -176,9 +179,6 @@
 	unsigned int power_state;	/* power state */
 	struct semaphore power_lock;	/* power lock */
 	wait_queue_head_t power_sleep;
-#ifdef CONFIG_SND_GENERIC_PM
-	struct snd_generic_device *pm_dev;	/* for ISA */
-#endif
 #endif
 
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -348,6 +348,8 @@
 #ifndef snd_card_set_dev
 #define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
 #endif
+/* register a generic device (for ISA, etc) */
+int snd_card_set_generic_dev(snd_card_t *card);
 
 /* device.c */
 
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 9b94510..b0c0e19 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -29,19 +29,6 @@
 #include "ac97_codec.h"
 #include "cs46xx_dsp_spos.h"
 
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS            0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4610
-#define PCI_DEVICE_ID_CIRRUS_4610       0x6001
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4612
-#define PCI_DEVICE_ID_CIRRUS_4612       0x6003
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4615
-#define PCI_DEVICE_ID_CIRRUS_4615       0x6004
-#endif
-
 /*
  *  Direct registers
  */
@@ -1715,7 +1702,6 @@
 	void (*active_ctrl)(cs46xx_t *, int);
   	void (*mixer_init)(cs46xx_t *);
 
-	struct pci_dev *acpi_dev;
 	int acpi_port;
 	snd_kcontrol_t *eapd_switch; /* for amplifier hack */
 	int accept_valid;	/* accept mmap valid (for OSS) */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 4e3993d..67bf3f1 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -35,13 +35,6 @@
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
-#ifndef PCI_VENDOR_ID_CREATIVE
-#define PCI_VENDOR_ID_CREATIVE		0x1102
-#endif
-#ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
-#define PCI_DEVICE_ID_CREATIVE_EMU10K1	0x0002
-#endif
-
 /* ------------------- DEFINES -------------------- */
 
 #define EMUPAGESIZE     4096
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index d6361dab..2b23a59 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -903,13 +903,16 @@
 int snd_pcm_format_linear(snd_pcm_format_t format);
 int snd_pcm_format_little_endian(snd_pcm_format_t format);
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
-/*
+#if 0 /* just for DocBook */
+/**
  * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
  * @format: the format to check
  *
  * Returns 1 if the given PCM format is CPU-endian, 0 if
  * opposite, or a negative error code if endian not specified.
  */
+int snd_pcm_format_cpu_endian(snd_pcm_format_t format);
+#endif /* DocBook */
 #ifdef SNDRV_LITTLE_ENDIAN
 #define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format)
 #else
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 5187285..0b67c9d 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -32,7 +32,8 @@
 		     block:1,
 		     nonblock:1,
 		     partialfrag:1,
-		     nosilence:1;
+		     nosilence:1,
+		     buggyptr:1;
 	unsigned int periods;
 	unsigned int period_size;
 	snd_pcm_oss_setup_t *next;
diff --git a/include/sound/trident.h b/include/sound/trident.h
index f5254ec..a408d39 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -33,23 +33,6 @@
 //#include "ainstr_gf1.h"
 #include "ainstr_simple.h"
 
-#ifndef PCI_VENDOR_ID_TRIDENT
-#define PCI_VENDOR_ID_TRIDENT		0x1023
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX	0x2000
-#endif
-#ifndef PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 
-#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX	0x2001
-#endif
-
-#ifndef PCI_VENDOR_ID_SI
-#define PCI_VENDOR_ID_SI		0x1039
-#endif
-#ifndef PCI_DEVICE_ID_SI_7018
-#define PCI_DEVICE_ID_SI_7018		0x7018
-#endif
-
 #define TRIDENT_DEVICE_ID_DX		((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_DX)
 #define TRIDENT_DEVICE_ID_NX		((PCI_VENDOR_ID_TRIDENT<<16)|PCI_DEVICE_ID_TRIDENT_4DWAVE_NX)
 #define TRIDENT_DEVICE_ID_SI7018	((PCI_VENDOR_ID_SI<<16)|PCI_DEVICE_ID_SI_7018)
diff --git a/include/sound/version.h b/include/sound/version.h
index 8d19bfa..ee32af2 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
 #define CONFIG_SND_VERSION "1.0.10rc1"
-#define CONFIG_SND_DATE " (Tue Aug 30 05:31:08 2005 UTC)"
+#define CONFIG_SND_DATE " (Mon Sep 12 08:13:09 2005 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index 9a3c1e6..c3bccbfd 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -28,28 +28,6 @@
 #include "timer.h"
 #include <linux/gameport.h>
 
-#ifndef PCI_VENDOR_ID_YAMAHA
-#define PCI_VENDOR_ID_YAMAHA            0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724
-#define PCI_DEVICE_ID_YAMAHA_724	0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_724F
-#define PCI_DEVICE_ID_YAMAHA_724F	0x000d
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740
-#define PCI_DEVICE_ID_YAMAHA_740	0x000a
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_740C
-#define PCI_DEVICE_ID_YAMAHA_740C	0x000c
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_744
-#define PCI_DEVICE_ID_YAMAHA_744	0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YAMAHA_754
-#define PCI_DEVICE_ID_YAMAHA_754	0x0012
-#endif
-
 /*
  *  Direct registers
  */
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 8d3cef5..6f4ea80 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1142,9 +1142,6 @@
 /* do we want accelerated console  */
 #define PM3FB_USE_ACCEL 1
 
-/* useful ? */
-#define CHAR_IS_NUM(a)  ((((a) >= '0') && ((a) <= '9')) ? 1 : 0)
-
 /* for driver debugging ONLY */
 /* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
 /* define PM3FB_MASTER_DEBUG 1 */
diff --git a/include/video/w100fb.h b/include/video/w100fb.h
index e6da2d7..677d403 100644
--- a/include/video/w100fb.h
+++ b/include/video/w100fb.h
@@ -19,6 +19,7 @@
 
 unsigned long w100fb_gpio_read(int port);
 void w100fb_gpio_write(int port, unsigned long value);
+unsigned long w100fb_get_hsynclen(struct device *dev);
 
 /* LCD Specific Routines and Config */
 struct w100_tg_info {
diff --git a/init/initramfs.c b/init/initramfs.c
index 02c5ce6..0c5d9a3 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -466,6 +466,14 @@
 extern char __initramfs_start[], __initramfs_end[];
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
+
+static void __init free_initrd(void)
+{
+	free_initrd_mem(initrd_start, initrd_end);
+	initrd_start = 0;
+	initrd_end = 0;
+}
+
 #endif
 
 void __init populate_rootfs(void)
@@ -484,7 +492,7 @@
 			printk(" it is\n");
 			unpack_to_rootfs((char *)initrd_start,
 				initrd_end - initrd_start, 0);
-			free_initrd_mem(initrd_start, initrd_end);
+			free_initrd();
 			return;
 		}
 		printk("it isn't (%s); looks like an initrd\n", err);
@@ -493,7 +501,7 @@
 			sys_write(fd, (char *)initrd_start,
 					initrd_end - initrd_start);
 			sys_close(fd);
-			free_initrd_mem(initrd_start, initrd_end);
+			free_initrd();
 		}
 	}
 #endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 7f06997..83096b6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -79,6 +79,8 @@
 
 /* Number of outstanding audit_buffers allowed. */
 static int	audit_backlog_limit = 64;
+static int	audit_backlog_wait_time = 60 * HZ;
+static int	audit_backlog_wait_overflow = 0;
 
 /* The identity of the user shutting down the audit system. */
 uid_t		audit_sig_uid = -1;
@@ -106,18 +108,12 @@
 static struct sk_buff_head audit_skb_queue;
 static struct task_struct *kauditd_task;
 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
-
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
+static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
 
 /* The netlink socket is only to be read by 1 CPU, which lets us assume
  * that list additions and deletions never happen simultaneously in
  * auditsc.c */
-static DECLARE_MUTEX(audit_netlink_sem);
+DECLARE_MUTEX(audit_netlink_sem);
 
 /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
  * audit records.  Since printk uses a 1024 byte buffer, this buffer
@@ -137,6 +133,7 @@
 	struct list_head     list;
 	struct sk_buff       *skb;	/* formatted skb ready to send */
 	struct audit_context *ctx;	/* NULL or associated context */
+	int		     gfp_mask;
 };
 
 static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
@@ -145,11 +142,6 @@
 	nlh->nlmsg_pid = pid;
 }
 
-struct audit_entry {
-	struct list_head  list;
-	struct audit_rule rule;
-};
-
 static void audit_panic(const char *message)
 {
 	switch (audit_failure)
@@ -233,7 +225,7 @@
 {
 	int old		 = audit_rate_limit;
 	audit_rate_limit = limit;
-	audit_log(NULL, AUDIT_CONFIG_CHANGE, 
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 
 			"audit_rate_limit=%d old=%d by auid=%u",
 			audit_rate_limit, old, loginuid);
 	return old;
@@ -243,7 +235,7 @@
 {
 	int old		 = audit_backlog_limit;
 	audit_backlog_limit = limit;
-	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 			"audit_backlog_limit=%d old=%d by auid=%u",
 			audit_backlog_limit, old, loginuid);
 	return old;
@@ -255,7 +247,7 @@
 	if (state != 0 && state != 1)
 		return -EINVAL;
 	audit_enabled = state;
-	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 			"audit_enabled=%d old=%d by auid=%u",
 			audit_enabled, old, loginuid);
 	return old;
@@ -269,7 +261,7 @@
 	    && state != AUDIT_FAIL_PANIC)
 		return -EINVAL;
 	audit_failure = state;
-	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 			"audit_failure=%d old=%d by auid=%u",
 			audit_failure, old, loginuid);
 	return old;
@@ -281,6 +273,7 @@
 
 	while (1) {
 		skb = skb_dequeue(&audit_skb_queue);
+		wake_up(&audit_backlog_wait);
 		if (skb) {
 			if (audit_pid) {
 				int err = netlink_unicast(audit_sock, skb, audit_pid, 0);
@@ -290,7 +283,7 @@
 					audit_pid = 0;
 				}
 			} else {
-				printk(KERN_ERR "%s\n", skb->data + NLMSG_SPACE(0));
+				printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
 				kfree_skb(skb);
 			}
 		} else {
@@ -423,7 +416,7 @@
 		if (status_get->mask & AUDIT_STATUS_PID) {
 			int old   = audit_pid;
 			audit_pid = status_get->pid;
-			audit_log(NULL, AUDIT_CONFIG_CHANGE,
+			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
 				"audit_pid=%d old=%d by auid=%u",
 				  audit_pid, old, loginuid);
 		}
@@ -435,15 +428,21 @@
 		break;
 	case AUDIT_USER:
 	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
-		ab = audit_log_start(NULL, msg_type);
-		if (!ab)
-			break;	/* audit_panic has been called */
-		audit_log_format(ab,
-				 "user pid=%d uid=%u auid=%u"
-				 " msg='%.1024s'",
-				 pid, uid, loginuid, (char *)data);
-		audit_set_pid(ab, pid);
-		audit_log_end(ab);
+		if (!audit_enabled && msg_type != AUDIT_USER_AVC)
+			return 0;
+
+		err = audit_filter_user(&NETLINK_CB(skb), msg_type);
+		if (err == 1) {
+			err = 0;
+			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+			if (ab) {
+				audit_log_format(ab,
+						 "user pid=%d uid=%u auid=%u msg='%.1024s'",
+						 pid, uid, loginuid, (char *)data);
+				audit_set_pid(ab, pid);
+				audit_log_end(ab);
+			}
+		}
 		break;
 	case AUDIT_ADD:
 	case AUDIT_DEL:
@@ -523,7 +522,7 @@
 	skb_queue_head_init(&audit_skb_queue);
 	audit_initialized = 1;
 	audit_enabled = audit_default;
-	audit_log(NULL, AUDIT_KERNEL, "initialized");
+	audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
 	return 0;
 }
 __initcall(audit_init);
@@ -561,7 +560,7 @@
 }
 
 static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
-						int gfp_mask, int type)
+						unsigned int __nocast gfp_mask, int type)
 {
 	unsigned long flags;
 	struct audit_buffer *ab = NULL;
@@ -587,6 +586,7 @@
 		goto err;
 
 	ab->ctx = ctx;
+	ab->gfp_mask = gfp_mask;
 	nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
 	nlh->nlmsg_type = type;
 	nlh->nlmsg_flags = 0;
@@ -606,26 +606,27 @@
  * (timestamp,serial) tuple is unique for each syscall and is live from
  * syscall entry to syscall exit.
  *
- * Atomic values are only guaranteed to be 24-bit, so we count down.
- *
  * NOTE: Another possibility is to store the formatted records off the
  * audit context (for those records that have a context), and emit them
  * all at syscall exit.  However, this could delay the reporting of
  * significant errors until syscall exit (or never, if the system
  * halts). */
+
 unsigned int audit_serial(void)
 {
-	static atomic_t serial = ATOMIC_INIT(0xffffff);
-	unsigned int a, b;
+	static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
+	static unsigned int serial = 0;
 
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&serial_lock, flags);
 	do {
-		a = atomic_read(&serial);
-		if (atomic_dec_and_test(&serial))
-			atomic_set(&serial, 0xffffff);
-		b = atomic_read(&serial);
-	} while (b != a - 1);
+		ret = ++serial;
+	} while (unlikely(!ret));
+	spin_unlock_irqrestore(&serial_lock, flags);
 
-	return 0xffffff - b;
+	return ret;
 }
 
 static inline void audit_get_stamp(struct audit_context *ctx, 
@@ -645,17 +646,43 @@
  * syscall, then the syscall is marked as auditable and an audit record
  * will be written at syscall exit.  If there is no associated task, tsk
  * should be NULL. */
-struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
+
+struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
+				     int type)
 {
 	struct audit_buffer	*ab	= NULL;
 	struct timespec		t;
 	unsigned int		serial;
+	int reserve;
+	unsigned long timeout_start = jiffies;
 
 	if (!audit_initialized)
 		return NULL;
 
-	if (audit_backlog_limit
-	    && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) {
+	if (gfp_mask & __GFP_WAIT)
+		reserve = 0;
+	else
+		reserve = 5; /* Allow atomic callers to go up to five 
+				entries over the normal backlog limit */
+
+	while (audit_backlog_limit
+	       && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
+		if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time
+		    && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {
+
+			/* Wait for auditd to drain the queue a little */
+			DECLARE_WAITQUEUE(wait, current);
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&audit_backlog_wait, &wait);
+
+			if (audit_backlog_limit &&
+			    skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
+				schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);
+
+			__set_current_state(TASK_RUNNING);
+			remove_wait_queue(&audit_backlog_wait, &wait);
+			continue;
+		}
 		if (audit_rate_check())
 			printk(KERN_WARNING
 			       "audit: audit_backlog=%d > "
@@ -663,10 +690,12 @@
 			       skb_queue_len(&audit_skb_queue),
 			       audit_backlog_limit);
 		audit_log_lost("backlog limit exceeded");
+		audit_backlog_wait_time = audit_backlog_wait_overflow;
+		wake_up(&audit_backlog_wait);
 		return NULL;
 	}
 
-	ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
+	ab = audit_buffer_alloc(ctx, gfp_mask, type);
 	if (!ab) {
 		audit_log_lost("out of memory in audit_log_start");
 		return NULL;
@@ -690,7 +719,7 @@
 {
 	struct sk_buff *skb = ab->skb;
 	int ret = pskb_expand_head(skb, skb_headroom(skb), extra,
-				   GFP_ATOMIC);
+				   ab->gfp_mask);
 	if (ret < 0) {
 		audit_log_lost("out of memory in audit_expand");
 		return 0;
@@ -809,7 +838,7 @@
 		audit_log_format(ab, " %s", prefix);
 
 	/* We will allow 11 spaces for ' (deleted)' to be appended */
-	path = kmalloc(PATH_MAX+11, GFP_KERNEL);
+	path = kmalloc(PATH_MAX+11, ab->gfp_mask);
 	if (!path) {
 		audit_log_format(ab, "<no memory>");
 		return;
@@ -841,7 +870,7 @@
 			ab->skb = NULL;
 			wake_up_interruptible(&kauditd_wait);
 		} else {
-			printk("%s\n", ab->skb->data + NLMSG_SPACE(0));
+			printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0));
 		}
 	}
 	audit_buffer_free(ab);
@@ -850,12 +879,13 @@
 /* Log an audit record.  This is a convenience function that calls
  * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
  * called in any context. */
-void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
+void audit_log(struct audit_context *ctx, int gfp_mask, int type, 
+	       const char *fmt, ...)
 {
 	struct audit_buffer *ab;
 	va_list args;
 
-	ab = audit_log_start(ctx, type);
+	ab = audit_log_start(ctx, gfp_mask, type);
 	if (ab) {
 		va_start(args, fmt);
 		audit_log_vformat(ab, fmt, args);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e75f84e..88696f6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -39,6 +39,9 @@
 #include <linux/audit.h>
 #include <linux/personality.h>
 #include <linux/time.h>
+#include <linux/kthread.h>
+#include <linux/netlink.h>
+#include <linux/compiler.h>
 #include <asm/unistd.h>
 
 /* 0 = no checking
@@ -95,6 +98,7 @@
 	uid_t		uid;
 	gid_t		gid;
 	dev_t		rdev;
+	unsigned	flags;
 };
 
 struct audit_aux_data {
@@ -167,9 +171,16 @@
 /* There are three lists of rules -- one to search at task creation
  * time, one to search at syscall entry time, and another to search at
  * syscall exit time. */
-static LIST_HEAD(audit_tsklist);
-static LIST_HEAD(audit_entlist);
-static LIST_HEAD(audit_extlist);
+static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
+	LIST_HEAD_INIT(audit_filter_list[0]),
+	LIST_HEAD_INIT(audit_filter_list[1]),
+	LIST_HEAD_INIT(audit_filter_list[2]),
+	LIST_HEAD_INIT(audit_filter_list[3]),
+	LIST_HEAD_INIT(audit_filter_list[4]),
+#if AUDIT_NR_FILTERS != 5
+#error Fix audit_filter_list initialiser
+#endif
+};
 
 struct audit_entry {
 	struct list_head  list;
@@ -179,9 +190,36 @@
 
 extern int audit_pid;
 
+/* Copy rule from user-space to kernel-space.  Called from 
+ * audit_add_rule during AUDIT_ADD. */
+static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+{
+	int i;
+
+	if (s->action != AUDIT_NEVER
+	    && s->action != AUDIT_POSSIBLE
+	    && s->action != AUDIT_ALWAYS)
+		return -1;
+	if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
+		return -1;
+	if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
+		return -1;
+
+	d->flags	= s->flags;
+	d->action	= s->action;
+	d->field_count	= s->field_count;
+	for (i = 0; i < d->field_count; i++) {
+		d->fields[i] = s->fields[i];
+		d->values[i] = s->values[i];
+	}
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
+	return 0;
+}
+
 /* Check to see if two rules are identical.  It is called from
+ * audit_add_rule during AUDIT_ADD and 
  * audit_del_rule during AUDIT_DEL. */
-static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
+static inline int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
 {
 	int i;
 
@@ -210,19 +248,37 @@
 /* Note that audit_add_rule and audit_del_rule are called via
  * audit_receive() in audit.c, and are protected by
  * audit_netlink_sem. */
-static inline int audit_add_rule(struct audit_entry *entry,
-				 struct list_head *list)
+static inline int audit_add_rule(struct audit_rule *rule,
+				  struct list_head *list)
 {
-	if (entry->rule.flags & AUDIT_PREPEND) {
-		entry->rule.flags &= ~AUDIT_PREPEND;
+	struct audit_entry  *entry;
+
+	/* Do not use the _rcu iterator here, since this is the only
+	 * addition routine. */
+	list_for_each_entry(entry, list, list) {
+		if (!audit_compare_rule(rule, &entry->rule)) {
+			return -EEXIST;
+		}
+	}
+
+	if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
+		return -ENOMEM;
+	if (audit_copy_rule(&entry->rule, rule)) {
+		kfree(entry);
+		return -EINVAL;
+	}
+
+	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+		entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
 		list_add_rcu(&entry->list, list);
 	} else {
 		list_add_tail_rcu(&entry->list, list);
 	}
+
 	return 0;
 }
 
-static void audit_free_rule(struct rcu_head *head)
+static inline void audit_free_rule(struct rcu_head *head)
 {
 	struct audit_entry *e = container_of(head, struct audit_entry, rcu);
 	kfree(e);
@@ -245,82 +301,82 @@
 			return 0;
 		}
 	}
-	return -EFAULT;		/* No matching rule */
+	return -ENOENT;		/* No matching rule */
 }
 
-/* Copy rule from user-space to kernel-space.  Called during
- * AUDIT_ADD. */
-static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
+static int audit_list_rules(void *_dest)
 {
+	int pid, seq;
+	int *dest = _dest;
+	struct audit_entry *entry;
 	int i;
 
-	if (s->action != AUDIT_NEVER
-	    && s->action != AUDIT_POSSIBLE
-	    && s->action != AUDIT_ALWAYS)
-		return -1;
-	if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
-		return -1;
+	pid = dest[0];
+	seq = dest[1];
+	kfree(dest);
 
-	d->flags	= s->flags;
-	d->action	= s->action;
-	d->field_count	= s->field_count;
-	for (i = 0; i < d->field_count; i++) {
-		d->fields[i] = s->fields[i];
-		d->values[i] = s->values[i];
+	down(&audit_netlink_sem);
+
+	/* The *_rcu iterators not needed here because we are
+	   always called with audit_netlink_sem held. */
+	for (i=0; i<AUDIT_NR_FILTERS; i++) {
+		list_for_each_entry(entry, &audit_filter_list[i], list)
+			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+					 &entry->rule, sizeof(entry->rule));
 	}
-	for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
+	audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+	
+	up(&audit_netlink_sem);
 	return 0;
 }
 
 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
 							uid_t loginuid)
 {
-	u32		   flags;
-	struct audit_entry *entry;
+	struct task_struct *tsk;
+	int *dest;
 	int		   err = 0;
+	unsigned listnr;
 
 	switch (type) {
 	case AUDIT_LIST:
-		/* The *_rcu iterators not needed here because we are
-		   always called with audit_netlink_sem held. */
-		list_for_each_entry(entry, &audit_tsklist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
-		list_for_each_entry(entry, &audit_entlist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
-		list_for_each_entry(entry, &audit_extlist, list)
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
-					 &entry->rule, sizeof(entry->rule));
-		audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+		/* We can't just spew out the rules here because we might fill
+		 * the available socket buffer space and deadlock waiting for
+		 * auditctl to read from it... which isn't ever going to
+		 * happen if we're actually running in the context of auditctl
+		 * trying to _send_ the stuff */
+		 
+		dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
+		if (!dest)
+			return -ENOMEM;
+		dest[0] = pid;
+		dest[1] = seq;
+
+		tsk = kthread_run(audit_list_rules, dest, "audit_list_rules");
+		if (IS_ERR(tsk)) {
+			kfree(dest);
+			err = PTR_ERR(tsk);
+		}
 		break;
 	case AUDIT_ADD:
-		if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
-			return -ENOMEM;
-		if (audit_copy_rule(&entry->rule, data)) {
-			kfree(entry);
+		listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
+		if (listnr >= AUDIT_NR_FILTERS)
 			return -EINVAL;
-		}
-		flags = entry->rule.flags;
-		if (!err && (flags & AUDIT_PER_TASK))
-			err = audit_add_rule(entry, &audit_tsklist);
-		if (!err && (flags & AUDIT_AT_ENTRY))
-			err = audit_add_rule(entry, &audit_entlist);
-		if (!err && (flags & AUDIT_AT_EXIT))
-			err = audit_add_rule(entry, &audit_extlist);
-		audit_log(NULL, AUDIT_CONFIG_CHANGE, 
-				"auid=%u added an audit rule\n", loginuid);
+
+		err = audit_add_rule(data, &audit_filter_list[listnr]);
+		if (!err)
+			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+				  "auid=%u added an audit rule\n", loginuid);
 		break;
 	case AUDIT_DEL:
-		flags =((struct audit_rule *)data)->flags;
-		if (!err && (flags & AUDIT_PER_TASK))
-			err = audit_del_rule(data, &audit_tsklist);
-		if (!err && (flags & AUDIT_AT_ENTRY))
-			err = audit_del_rule(data, &audit_entlist);
-		if (!err && (flags & AUDIT_AT_EXIT))
-			err = audit_del_rule(data, &audit_extlist);
-		audit_log(NULL, AUDIT_CONFIG_CHANGE,
-				"auid=%u removed an audit rule\n", loginuid);
+		listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
+		if (listnr >= AUDIT_NR_FILTERS)
+			return -EINVAL;
+
+		err = audit_del_rule(data, &audit_filter_list[listnr]);
+		if (!err)
+			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+				  "auid=%u removed an audit rule\n", loginuid);
 		break;
 	default:
 		return -EINVAL;
@@ -384,8 +440,12 @@
 				result = (ctx->return_code == value);
 			break;
 		case AUDIT_SUCCESS:
-			if (ctx && ctx->return_valid)
-				result = (ctx->return_valid == AUDITSC_SUCCESS);
+			if (ctx && ctx->return_valid) {
+				if (value)
+					result = (ctx->return_valid == AUDITSC_SUCCESS);
+				else
+					result = (ctx->return_valid == AUDITSC_FAILURE);
+			}
 			break;
 		case AUDIT_DEVMAJOR:
 			if (ctx) {
@@ -454,7 +514,7 @@
 	enum audit_state   state;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(e, &audit_tsklist, list) {
+	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
 		if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
 			rcu_read_unlock();
 			return state;
@@ -474,22 +534,86 @@
 					     struct list_head *list)
 {
 	struct audit_entry *e;
-	enum audit_state   state;
-	int		   word = AUDIT_WORD(ctx->major);
-	int		   bit  = AUDIT_BIT(ctx->major);
+	enum audit_state state;
+
+	if (audit_pid && tsk->tgid == audit_pid)
+		return AUDIT_DISABLED;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(e, list, list) {
-		if ((e->rule.mask[word] & bit) == bit
- 		    && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
-			rcu_read_unlock();
-			return state;
-		}
+	if (!list_empty(list)) {
+		    int word = AUDIT_WORD(ctx->major);
+		    int bit  = AUDIT_BIT(ctx->major);
+
+		    list_for_each_entry_rcu(e, list, list) {
+			    if ((e->rule.mask[word] & bit) == bit
+				&& audit_filter_rules(tsk, &e->rule, ctx, &state)) {
+				    rcu_read_unlock();
+				    return state;
+			    }
+		    }
 	}
 	rcu_read_unlock();
 	return AUDIT_BUILD_CONTEXT;
 }
 
+static int audit_filter_user_rules(struct netlink_skb_parms *cb,
+			      struct audit_rule *rule,
+			      enum audit_state *state)
+{
+	int i;
+
+	for (i = 0; i < rule->field_count; i++) {
+		u32 field  = rule->fields[i] & ~AUDIT_NEGATE;
+		u32 value  = rule->values[i];
+		int result = 0;
+
+		switch (field) {
+		case AUDIT_PID:
+			result = (cb->creds.pid == value);
+			break;
+		case AUDIT_UID:
+			result = (cb->creds.uid == value);
+			break;
+		case AUDIT_GID:
+			result = (cb->creds.gid == value);
+			break;
+		case AUDIT_LOGINUID:
+			result = (cb->loginuid == value);
+			break;
+		}
+
+		if (rule->fields[i] & AUDIT_NEGATE)
+			result = !result;
+		if (!result)
+			return 0;
+	}
+	switch (rule->action) {
+	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
+	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
+	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
+	}
+	return 1;
+}
+
+int audit_filter_user(struct netlink_skb_parms *cb, int type)
+{
+	struct audit_entry *e;
+	enum audit_state   state;
+	int ret = 1;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
+		if (audit_filter_user_rules(cb, &e->rule, &state)) {
+			if (state == AUDIT_DISABLED)
+				ret = 0;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return ret; /* Audit by default */
+}
+
 /* This should be called with task_lock() held. */
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 						      int return_valid,
@@ -504,7 +628,7 @@
 
 	if (context->in_syscall && !context->auditable) {
 		enum audit_state state;
-		state = audit_filter_syscall(tsk, context, &audit_extlist);
+		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
 		if (state == AUDIT_RECORD_CONTEXT)
 			context->auditable = 1;
 	}
@@ -679,13 +803,13 @@
 	up_read(&mm->mmap_sem);
 }
 
-static void audit_log_exit(struct audit_context *context)
+static void audit_log_exit(struct audit_context *context, unsigned int gfp_mask)
 {
 	int i;
 	struct audit_buffer *ab;
 	struct audit_aux_data *aux;
 
-	ab = audit_log_start(context, AUDIT_SYSCALL);
+	ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
 	if (!ab)
 		return;		/* audit_panic has been called */
 	audit_log_format(ab, "arch=%x syscall=%d",
@@ -717,7 +841,7 @@
 
 	for (aux = context->aux; aux; aux = aux->next) {
 
-		ab = audit_log_start(context, aux->type);
+		ab = audit_log_start(context, GFP_KERNEL, aux->type);
 		if (!ab)
 			continue; /* audit_panic has been called */
 
@@ -754,14 +878,14 @@
 	}
 
 	if (context->pwd && context->pwdmnt) {
-		ab = audit_log_start(context, AUDIT_CWD);
+		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
 		if (ab) {
 			audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
 			audit_log_end(ab);
 		}
 	}
 	for (i = 0; i < context->name_count; i++) {
-		ab = audit_log_start(context, AUDIT_PATH);
+		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
 		if (!ab)
 			continue; /* audit_panic has been called */
 
@@ -770,6 +894,8 @@
 			audit_log_format(ab, " name=");
 			audit_log_untrustedstring(ab, context->names[i].name);
 		}
+		audit_log_format(ab, " flags=%x\n", context->names[i].flags);
+			 
 		if (context->names[i].ino != (unsigned long)-1)
 			audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
 					     " ouid=%u ogid=%u rdev=%02x:%02x",
@@ -799,9 +925,11 @@
 		return;
 
 	/* Check for system calls that do not go through the exit
-	 * function (e.g., exit_group), then free context block. */
-	if (context->in_syscall && context->auditable && context->pid != audit_pid)
-		audit_log_exit(context);
+	 * function (e.g., exit_group), then free context block. 
+	 * We use GFP_ATOMIC here because we might be doing this 
+	 * in the context of the idle thread */
+	if (context->in_syscall && context->auditable)
+		audit_log_exit(context, GFP_ATOMIC);
 
 	audit_free_context(context);
 }
@@ -876,11 +1004,11 @@
 
 	state = context->state;
 	if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
-		state = audit_filter_syscall(tsk, context, &audit_entlist);
+		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
 	if (likely(state == AUDIT_DISABLED))
 		return;
 
-	context->serial     = audit_serial();
+	context->serial     = 0;
 	context->ctime      = CURRENT_TIME;
 	context->in_syscall = 1;
 	context->auditable  = !!(state == AUDIT_RECORD_CONTEXT);
@@ -903,10 +1031,10 @@
 	/* Not having a context here is ok, since the parent may have
 	 * called __put_task_struct. */
 	if (likely(!context))
-		return;
+		goto out;
 
-	if (context->in_syscall && context->auditable && context->pid != audit_pid)
-		audit_log_exit(context);
+	if (context->in_syscall && context->auditable)
+		audit_log_exit(context, GFP_KERNEL);
 
 	context->in_syscall = 0;
 	context->auditable  = 0;
@@ -919,9 +1047,9 @@
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
-		audit_zero_context(context, context->state);
 		tsk->audit_context = context;
 	}
+ out:
 	put_task_struct(tsk);
 }
 
@@ -996,7 +1124,7 @@
 
 /* Store the inode and device from a lookup.  Called from
  * fs/namei.c:path_lookup(). */
-void audit_inode(const char *name, const struct inode *inode)
+void audit_inode(const char *name, const struct inode *inode, unsigned flags)
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
@@ -1022,17 +1150,20 @@
 		++context->ino_count;
 #endif
 	}
-	context->names[idx].ino  = inode->i_ino;
-	context->names[idx].dev	 = inode->i_sb->s_dev;
-	context->names[idx].mode = inode->i_mode;
-	context->names[idx].uid  = inode->i_uid;
-	context->names[idx].gid  = inode->i_gid;
-	context->names[idx].rdev = inode->i_rdev;
+	context->names[idx].flags = flags;
+	context->names[idx].ino   = inode->i_ino;
+	context->names[idx].dev	  = inode->i_sb->s_dev;
+	context->names[idx].mode  = inode->i_mode;
+	context->names[idx].uid   = inode->i_uid;
+	context->names[idx].gid   = inode->i_gid;
+	context->names[idx].rdev  = inode->i_rdev;
 }
 
 void auditsc_get_stamp(struct audit_context *ctx,
 		       struct timespec *t, unsigned int *serial)
 {
+	if (!ctx->serial)
+		ctx->serial = audit_serial();
 	t->tv_sec  = ctx->ctime.tv_sec;
 	t->tv_nsec = ctx->ctime.tv_nsec;
 	*serial    = ctx->serial;
@@ -1044,7 +1175,7 @@
 	if (task->audit_context) {
 		struct audit_buffer *ab;
 
-		ab = audit_log_start(NULL, AUDIT_LOGIN);
+		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
 		if (ab) {
 			audit_log_format(ab, "login pid=%d uid=%u "
 				"old auid=%u new auid=%u",
@@ -1153,7 +1284,7 @@
 	extern pid_t audit_sig_pid;
 	extern uid_t audit_sig_uid;
 
-	if (unlikely(audit_pid && t->pid == audit_pid)) {
+	if (unlikely(audit_pid && t->tgid == audit_pid)) {
 		if (sig == SIGTERM || sig == SIGHUP) {
 			struct audit_context *ctx = current->audit_context;
 			audit_sig_pid = current->pid;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 407b5f0..79866bc 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -180,6 +180,8 @@
  */
 
 static DECLARE_MUTEX(cpuset_sem);
+static struct task_struct *cpuset_sem_owner;
+static int cpuset_sem_depth;
 
 /*
  * The global cpuset semaphore cpuset_sem can be needed by the
@@ -200,16 +202,19 @@
 
 static inline void cpuset_down(struct semaphore *psem)
 {
-	if (current->cpuset_sem_nest_depth == 0)
+	if (cpuset_sem_owner != current) {
 		down(psem);
-	current->cpuset_sem_nest_depth++;
+		cpuset_sem_owner = current;
+	}
+	cpuset_sem_depth++;
 }
 
 static inline void cpuset_up(struct semaphore *psem)
 {
-	current->cpuset_sem_nest_depth--;
-	if (current->cpuset_sem_nest_depth == 0)
+	if (--cpuset_sem_depth == 0) {
+		cpuset_sem_owner = NULL;
 		up(psem);
+	}
 }
 
 /*
diff --git a/kernel/module.c b/kernel/module.c
index 4b39d37..ff5c500 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/moduleloader.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/elf.h>
@@ -498,7 +499,7 @@
 {
 	int ret = (flags & O_TRUNC);
 	if (ret)
-		tainted |= TAINT_FORCED_MODULE;
+		add_taint(TAINT_FORCED_MODULE);
 	return ret;
 }
 #else
@@ -897,7 +898,7 @@
 	if (!(tainted & TAINT_FORCED_MODULE)) {
 		printk("%s: no version for \"%s\" found: kernel tainted.\n",
 		       mod->name, symname);
-		tainted |= TAINT_FORCED_MODULE;
+		add_taint(TAINT_FORCED_MODULE);
 	}
 	return 1;
 }
@@ -1352,7 +1353,7 @@
 	if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
 		printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
 		       mod->name, license);
-		tainted |= TAINT_PROPRIETARY_MODULE;
+		add_taint(TAINT_PROPRIETARY_MODULE);
 	}
 }
 
@@ -1610,7 +1611,7 @@
 	modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
 	/* This is allowed: modprobe --force will invalidate it. */
 	if (!modmagic) {
-		tainted |= TAINT_FORCED_MODULE;
+		add_taint(TAINT_FORCED_MODULE);
 		printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
 		       mod->name);
 	} else if (!same_magic(modmagic, vermagic)) {
@@ -1739,7 +1740,7 @@
 	    (mod->num_gpl_syms && !gplcrcindex)) {
 		printk(KERN_WARNING "%s: No versions for exported symbols."
 		       " Tainting kernel.\n", mod->name);
-		tainted |= TAINT_FORCED_MODULE;
+		add_taint(TAINT_FORCED_MODULE);
 	}
 #endif
 
diff --git a/kernel/sched.c b/kernel/sched.c
index e9ff04a..1f31a52 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -294,6 +294,10 @@
 
 static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
 {
+#ifdef CONFIG_DEBUG_SPINLOCK
+	/* this is a valid case when another task releases the spinlock */
+	rq->lock.owner = current;
+#endif
 	spin_unlock_irq(&rq->lock);
 }
 
@@ -1529,10 +1533,6 @@
 	 *		Manfred Spraul <manfred@colorfullife.com>
 	 */
 	prev_task_flags = prev->flags;
-#ifdef CONFIG_DEBUG_SPINLOCK
-	/* this is a valid case when another task releases the spinlock */
-	rq->lock.owner = current;
-#endif
 	finish_arch_switch(prev);
 	finish_lock_switch(rq, prev);
 	if (mm)
@@ -3577,32 +3577,6 @@
 }
 
 /**
- * curr_task - return the current task for a given cpu.
- * @cpu: the processor in question.
- */
-task_t *curr_task(int cpu)
-{
-	return cpu_curr(cpu);
-}
-
-/**
- * set_curr_task - set the current task for a given cpu.
- * @cpu: the processor in question.
- * @p: the task pointer to set.
- *
- * Description: This function must only be used when non-maskable interrupts
- * are serviced on a separate stack.  It allows the architecture to switch the
- * notion of the current task on a cpu in a non-blocking manner.  This function
- * must be called with interrupts disabled, the caller must save the original
- * value of the current task (see curr_task() above) and restore that value
- * before reenabling interrupts.
- */
-void set_curr_task(int cpu, task_t *p)
-{
-	cpu_curr(cpu) = p;
-}
-
-/**
  * find_process_by_pid - find a process with a matching PID value.
  * @pid: the pid in question.
  */
@@ -5628,3 +5602,47 @@
 }
 
 #endif /* CONFIG_MAGIC_SYSRQ */
+
+#ifdef CONFIG_IA64
+/*
+ * These functions are only useful for the IA64 MCA handling.
+ *
+ * They can only be called when the whole system has been
+ * stopped - every CPU needs to be quiescent, and no scheduling
+ * activity can take place. Using them for anything else would
+ * be a serious bug, and as a result, they aren't even visible
+ * under any other configuration.
+ */
+
+/**
+ * curr_task - return the current task for a given cpu.
+ * @cpu: the processor in question.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+task_t *curr_task(int cpu)
+{
+	return cpu_curr(cpu);
+}
+
+/**
+ * set_curr_task - set the current task for a given cpu.
+ * @cpu: the processor in question.
+ * @p: the task pointer to set.
+ *
+ * Description: This function must only be used when non-maskable interrupts
+ * are serviced on a separate stack.  It allows the architecture to switch the
+ * notion of the current task on a cpu in a non-blocking manner.  This function
+ * must be called with all CPU's synchronized, and interrupts disabled, the
+ * and caller must save the original value of the current task (see
+ * curr_task() above) and restore that value before reenabling interrupts and
+ * re-starting the system.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+void set_curr_task(int cpu, task_t *p)
+{
+	cpu_curr(cpu) = p;
+}
+
+#endif
diff --git a/kernel/softirq.c b/kernel/softirq.c
index b4ab6af..f766b2f 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -84,7 +84,7 @@
 	cpu = smp_processor_id();
 restart:
 	/* Reset the pending bitmask before enabling irqs */
-	local_softirq_pending() = 0;
+	set_softirq_pending(0);
 
 	local_irq_enable();
 
diff --git a/kernel/timer.c b/kernel/timer.c
index f4152fc..3ba10fa 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1151,19 +1151,22 @@
  out:
 	return timeout < 0 ? 0 : timeout;
 }
-
 EXPORT_SYMBOL(schedule_timeout);
 
+/*
+ * We can use __set_current_state() here because schedule_timeout() calls
+ * schedule() unconditionally.
+ */
 signed long __sched schedule_timeout_interruptible(signed long timeout)
 {
-       set_current_state(TASK_INTERRUPTIBLE);
+       __set_current_state(TASK_INTERRUPTIBLE);
        return schedule_timeout(timeout);
 }
 EXPORT_SYMBOL(schedule_timeout_interruptible);
 
 signed long __sched schedule_timeout_uninterruptible(signed long timeout)
 {
-       set_current_state(TASK_UNINTERRUPTIBLE);
+       __set_current_state(TASK_UNINTERRUPTIBLE);
        return schedule_timeout(timeout);
 }
 EXPORT_SYMBOL(schedule_timeout_uninterruptible);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 3754c9a..016e89a 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -170,11 +170,11 @@
 
 config FRAME_POINTER
 	bool "Compile the kernel with frame pointers"
-	depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+	depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
 	default y if DEBUG_INFO && UML
 	help
 	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but it will give very useful debugging information.
-	  If you don't debug the kernel, you can say N, but we may not be able
-	  to solve problems without frame pointers.
+	  and slower, but it might give very useful debugging information
+	  on some architectures or you use external debuggers.
+	  If you don't debug the kernel, you can say N.
 
diff --git a/mm/bootmem.c b/mm/bootmem.c
index c1330cc..8ec4e4c 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -61,9 +61,17 @@
 {
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long mapsize = ((end - start)+7)/8;
+	static struct pglist_data *pgdat_last;
 
-	pgdat->pgdat_next = pgdat_list;
-	pgdat_list = pgdat;
+	pgdat->pgdat_next = NULL;
+	/* Add new nodes last so that bootmem always starts
+	   searching in the first nodes, not the last ones */
+	if (pgdat_last)
+		pgdat_last->pgdat_next = pgdat;
+	else {
+		pgdat_list = pgdat; 	
+		pgdat_last = pgdat;
+	}
 
 	mapsize = ALIGN(mapsize, sizeof(long));
 	bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index afa06e1..9033f08 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -333,8 +333,13 @@
 		if (prev && prev->vm_end < vma->vm_start)
 			return ERR_PTR(-EFAULT);
 		if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
+			unsigned long endvma = vma->vm_end;
+			if (endvma > end)
+				endvma = end;
+			if (vma->vm_start > start)
+				start = vma->vm_start;
 			err = check_pgd_range(vma->vm_mm,
-					   vma->vm_start, vma->vm_end, nodes);
+					   start, endvma, nodes);
 			if (err) {
 				first = ERR_PTR(err);
 				break;
diff --git a/mm/nommu.c b/mm/nommu.c
index fd4e8df..064d704 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -57,6 +57,11 @@
 struct vm_operations_struct generic_file_vm_ops = {
 };
 
+EXPORT_SYMBOL(vmalloc);
+EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_32);
+
 /*
  * Handle all mappings that got truncated by a "truncate()"
  * system call.
@@ -142,6 +147,8 @@
 	return(i);
 }
 
+EXPORT_SYMBOL(get_user_pages);
+
 DEFINE_RWLOCK(vmlist_lock);
 struct vm_struct *vmlist;
 
@@ -852,7 +859,7 @@
  error_getting_vma:
 	up_write(&nommu_vma_sem);
 	kfree(vml);
-	printk("Allocation of vml for %lu byte allocation from process %d failed\n",
+	printk("Allocation of vma for %lu byte allocation from process %d failed\n",
 	       len, current->pid);
 	show_free_areas();
 	return -ENOMEM;
@@ -909,7 +916,7 @@
 
 	for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
 		if ((*parent)->vma->vm_start == addr &&
-		    (*parent)->vma->vm_end == end)
+		    ((len == 0) || ((*parent)->vma->vm_end == end)))
 			goto found;
 
 	printk("munmap of non-mmaped memory by process %d (%s): %p\n",
@@ -1054,7 +1061,8 @@
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
 		unsigned long to, unsigned long size, pgprot_t prot)
 {
-	return -EPERM;
+	vma->vm_start = vma->vm_pgoff << PAGE_SHIFT;
+	return 0;
 }
 
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -1073,9 +1081,10 @@
 
 void update_mem_hiwater(struct task_struct *tsk)
 {
-	unsigned long rss = get_mm_counter(tsk->mm, rss);
+	unsigned long rss;
 
 	if (likely(tsk->mm)) {
+		rss = get_mm_counter(tsk->mm, rss);
 		if (tsk->mm->hiwater_rss < rss)
 			tsk->mm->hiwater_rss = rss;
 		if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c5823c3..ae29033 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -22,6 +22,7 @@
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/suspend.h>
 #include <linux/pagevec.h>
@@ -117,7 +118,7 @@
 	set_page_count(page, 0);
 	reset_page_mapcount(page);
 	page->mapping = NULL;
-	tainted |= TAINT_BAD_PAGE;
+	add_taint(TAINT_BAD_PAGE);
 }
 
 #ifndef CONFIG_HUGETLB_PAGE
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a740778..0ea71e8 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1258,9 +1258,9 @@
 		pgdat->kswapd_max_order = order;
 	if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
 		return;
-	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+	if (!waitqueue_active(&pgdat->kswapd_wait))
 		return;
-	wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
+	wake_up_interruptible(&pgdat->kswapd_wait);
 }
 
 #ifdef CONFIG_PM
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d6da093..b61b4e8 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -558,6 +558,35 @@
 	hci_dev_unlock(hdev);
 }
 
+/* Extended Inquiry Result */
+static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct inquiry_data data;
+	struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1);
+	int num_rsp = *((__u8 *) skb->data);
+
+	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+
+	if (!num_rsp)
+		return;
+
+	hci_dev_lock(hdev);
+
+	for (; num_rsp; num_rsp--) {
+		bacpy(&data.bdaddr, &info->bdaddr);
+		data.pscan_rep_mode     = info->pscan_rep_mode;
+		data.pscan_period_mode  = info->pscan_period_mode;
+		data.pscan_mode         = 0x00;
+		memcpy(data.dev_class, info->dev_class, 3);
+		data.clock_offset       = info->clock_offset;
+		data.rssi               = info->rssi;
+		info++;
+		hci_inquiry_cache_update(hdev, &data);
+	}
+
+	hci_dev_unlock(hdev);
+}
+
 /* Connect Request */
 static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
@@ -940,6 +969,10 @@
 		hci_inquiry_result_with_rssi_evt(hdev, skb);
 		break;
 
+	case HCI_EV_EXTENDED_INQUIRY_RESULT:
+		hci_extended_inquiry_result_evt(hdev, skb);
+		break;
+
 	case HCI_EV_CONN_REQUEST:
 		hci_conn_request_evt(hdev, skb);
 		break;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 90e19eb..f49e7e9 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -363,6 +363,11 @@
 		goto done;
 	}
 
+	if (sk->sk_type != SOCK_STREAM) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	write_lock_bh(&rfcomm_sk_list.lock);
 
 	if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) {
@@ -393,14 +398,18 @@
 	if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc))
 		return -EINVAL;
 
-	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
-		return -EBADFD;
-
-	if (sk->sk_type != SOCK_STREAM)
-		return -EINVAL;
-
 	lock_sock(sk);
 
+	if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	if (sk->sk_type != SOCK_STREAM) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	sk->sk_state = BT_CONNECT;
 	bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr);
 	rfcomm_pi(sk)->channel = sa->rc_channel;
@@ -410,6 +419,7 @@
 		err = bt_sock_wait_state(sk, BT_CONNECTED,
 				sock_sndtimeo(sk, flags & O_NONBLOCK));
 
+done:
 	release_sock(sk);
 	return err;
 }
@@ -428,6 +438,11 @@
 		goto done;
 	}
 
+	if (sk->sk_type != SOCK_STREAM) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	if (!rfcomm_pi(sk)->channel) {
 		bdaddr_t *src = &bt_sk(sk)->src;
 		u8 channel;
@@ -472,6 +487,11 @@
 		goto done;
 	}
 
+	if (sk->sk_type != SOCK_STREAM) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
 	BT_DBG("sk %p timeo %ld", sk, timeo);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 1b79ec3..d77d6b3 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -29,9 +29,9 @@
 static DEFINE_SPINLOCK(ip_ftp_lock);
 
 #define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
 static int ports_c;
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
 
 static int loose;
 module_param(loose, int, 0600);
@@ -450,7 +450,7 @@
 }
 
 static struct ip_conntrack_helper ftp[MAX_PORTS];
-static char ftp_names[MAX_PORTS][10];
+static char ftp_names[MAX_PORTS][sizeof("ftp-65535")];
 
 /* Not __exit: called from init() */
 static void fini(void)
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index d7a8a98..1545741 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -34,7 +34,7 @@
 #include <linux/moduleparam.h>
 
 #define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
 static int ports_c;
 static int max_dcc_channels = 8;
 static unsigned int dcc_timeout = 300;
@@ -52,7 +52,7 @@
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
 MODULE_LICENSE("GPL");
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 module_param(max_dcc_channels, int, 0400);
 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
@@ -240,7 +240,7 @@
 }
 
 static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
-static char irc_names[MAX_PORTS][10];
+static char irc_names[MAX_PORTS][sizeof("irc-65535")];
 
 static void fini(void);
 
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index bb72466..71ef19d 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -23,7 +23,6 @@
 #include <linux/inetdevice.h>
 #include <linux/in.h>
 #include <linux/ip.h>
-#include <linux/udp.h>
 #include <net/route.h>
 
 #include <linux/netfilter.h>
@@ -31,6 +30,8 @@
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 
+#define NMBD_PORT	137
+
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
 MODULE_LICENSE("GPL");
@@ -44,7 +45,6 @@
 {
 	struct ip_conntrack_expect *exp;
 	struct iphdr *iph = (*pskb)->nh.iph;
-	struct udphdr _uh, *uh;
 	struct rtable *rt = (struct rtable *)(*pskb)->dst;
 	struct in_device *in_dev;
 	u_int32_t mask = 0;
@@ -72,20 +72,15 @@
 	if (mask == 0)
 		goto out;
 
-	uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh);
-	BUG_ON(uh == NULL);
-
 	exp = ip_conntrack_expect_alloc(ct);
 	if (exp == NULL)
 		goto out;
-	memset(&exp->tuple, 0, sizeof(exp->tuple));
-	exp->tuple.src.ip         = iph->daddr & mask;
-	exp->tuple.dst.ip         = iph->saddr;
-	exp->tuple.dst.u.udp.port = uh->source;
-	exp->tuple.dst.protonum   = IPPROTO_UDP;
 
-	memset(&exp->mask, 0, sizeof(exp->mask));
+	exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+	exp->tuple.src.u.udp.port = ntohs(NMBD_PORT);
+
 	exp->mask.src.ip          = mask;
+	exp->mask.src.u.udp.port  = 0xFFFF;
 	exp->mask.dst.ip          = 0xFFFFFFFF;
 	exp->mask.dst.u.udp.port  = 0xFFFF;
 	exp->mask.dst.protonum    = 0xFF;
@@ -107,7 +102,7 @@
 		.src = {
 			.u = {
 				.udp = {
-					.port	= __constant_htons(137),
+					.port	= __constant_htons(NMBD_PORT),
 				}
 			}
 		},
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index d2b5905..a78736b 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -26,9 +26,9 @@
 MODULE_LICENSE("GPL");
 
 #define MAX_PORTS 8
-static int ports[MAX_PORTS];
+static short ports[MAX_PORTS];
 static int ports_c;
-module_param_array(ports, int, &ports_c, 0400);
+module_param_array(ports, short, &ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -100,7 +100,7 @@
 }
 
 static struct ip_conntrack_helper tftp[MAX_PORTS];
-static char tftp_names[MAX_PORTS][10];
+static char tftp_names[MAX_PORTS][sizeof("tftp-65535")];
 
 static void fini(void)
 {
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 2f3e181..275a174 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -90,6 +90,12 @@
 	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
 	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
+	/* Source address is 0.0.0.0 - locally generated packet that is
+	 * probably not supposed to be masqueraded.
+	 */
+	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
+		return NF_ACCEPT;
+
 	mr = targinfo;
 	rt = (struct rtable *)(*pskb)->dst;
 	newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index d2e1344..715cb61 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -88,14 +88,18 @@
 		newdst = htonl(0x7F000001);
 	else {
 		struct in_device *indev;
+		struct in_ifaddr *ifa;
 
-		/* Device might not have an associated in_device. */
-		indev = (struct in_device *)(*pskb)->dev->ip_ptr;
-		if (indev == NULL || indev->ifa_list == NULL)
+		newdst = 0;
+		
+		rcu_read_lock();
+		indev = __in_dev_get((*pskb)->dev);
+		if (indev && (ifa = indev->ifa_list))
+			newdst = ifa->ifa_local;
+		rcu_read_unlock();
+
+		if (!newdst)
 			return NF_DROP;
-
-		/* Grab first address on interface. */
-		newdst = indev->ifa_list->ifa_local;
 	}
 
 	/* Transfer from original range. */
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 51885b5..30ec3ef 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -512,15 +512,14 @@
 static void
 svc_udp_data_ready(struct sock *sk, int count)
 {
-	struct svc_sock	*svsk = (struct svc_sock *)(sk->sk_user_data);
+	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
 
-	if (!svsk)
-		goto out;
-	dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
-		svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
-	set_bit(SK_DATA, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
- out:
+	if (svsk) {
+		dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
+			svsk, sk, count, test_bit(SK_BUSY, &svsk->sk_flags));
+		set_bit(SK_DATA, &svsk->sk_flags);
+		svc_sock_enqueue(svsk);
+	}
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
 		wake_up_interruptible(sk->sk_sleep);
 }
@@ -540,7 +539,7 @@
 	}
 
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) {
-		printk(KERN_WARNING "RPC svc_write_space: some sleeping on %p\n",
+		dprintk("RPC svc_write_space: someone sleeping on %p\n",
 		       svsk);
 		wake_up_interruptible(sk->sk_sleep);
 	}
@@ -692,31 +691,29 @@
 static void
 svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
 {
-	struct svc_sock	*svsk;
+	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
 
 	dprintk("svc: socket %p TCP (listen) state change %d\n",
-			sk, sk->sk_state);
+		sk, sk->sk_state);
 
-	if  (sk->sk_state != TCP_LISTEN) {
-		/*
-		 * This callback may called twice when a new connection
-		 * is established as a child socket inherits everything
-		 * from a parent LISTEN socket.
-		 * 1) data_ready method of the parent socket will be called
-		 *    when one of child sockets become ESTABLISHED.
-		 * 2) data_ready method of the child socket may be called
-		 *    when it receives data before the socket is accepted.
-		 * In case of 2, we should ignore it silently.
-		 */
-		goto out;
+	/*
+	 * This callback may called twice when a new connection
+	 * is established as a child socket inherits everything
+	 * from a parent LISTEN socket.
+	 * 1) data_ready method of the parent socket will be called
+	 *    when one of child sockets become ESTABLISHED.
+	 * 2) data_ready method of the child socket may be called
+	 *    when it receives data before the socket is accepted.
+	 * In case of 2, we should ignore it silently.
+	 */
+	if (sk->sk_state == TCP_LISTEN) {
+		if (svsk) {
+			set_bit(SK_CONN, &svsk->sk_flags);
+			svc_sock_enqueue(svsk);
+		} else
+			printk("svc: socket %p: no user data\n", sk);
 	}
-	if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
-		printk("svc: socket %p: no user data\n", sk);
-		goto out;
-	}
-	set_bit(SK_CONN, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
- out:
+
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
 		wake_up_interruptible_all(sk->sk_sleep);
 }
@@ -727,18 +724,17 @@
 static void
 svc_tcp_state_change(struct sock *sk)
 {
-	struct svc_sock	*svsk;
+	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
 
 	dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
-			sk, sk->sk_state, sk->sk_user_data);
+		sk, sk->sk_state, sk->sk_user_data);
 
-	if (!(svsk = (struct svc_sock *) sk->sk_user_data)) {
+	if (!svsk)
 		printk("svc: socket %p: no user data\n", sk);
-		goto out;
+	else {
+		set_bit(SK_CLOSE, &svsk->sk_flags);
+		svc_sock_enqueue(svsk);
 	}
-	set_bit(SK_CLOSE, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
- out:
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
 		wake_up_interruptible_all(sk->sk_sleep);
 }
@@ -746,15 +742,14 @@
 static void
 svc_tcp_data_ready(struct sock *sk, int count)
 {
-	struct svc_sock *	svsk;
+	struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
 
 	dprintk("svc: socket %p TCP data ready (svsk %p)\n",
-			sk, sk->sk_user_data);
-	if (!(svsk = (struct svc_sock *)(sk->sk_user_data)))
-		goto out;
-	set_bit(SK_DATA, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
- out:
+		sk, sk->sk_user_data);
+	if (svsk) {
+		set_bit(SK_DATA, &svsk->sk_flags);
+		svc_sock_enqueue(svsk);
+	}
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
 		wake_up_interruptible(sk->sk_sleep);
 }
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 09ffca5..3bed09e 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -370,6 +370,12 @@
 			/* Ignore register directives. */
 			if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
 				break;
+ 			if (symname[0] == '.') {
+ 				char *munged = strdup(symname);
+ 				munged[0] = '_';
+ 				munged[1] = toupper(munged[1]);
+ 				symname = munged;
+ 			}
 		}
 #endif
 		
diff --git a/security/Kconfig b/security/Kconfig
index dcf04a0..64d3f1e 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -35,6 +35,7 @@
 
 config SECURITY
 	bool "Enable different security models"
+	depends on SYSFS
 	help
 	  This allows you to choose different security modules to be
 	  configured into your kernel.
diff --git a/security/Makefile b/security/Makefile
index 197cc2f..8cbbf2f 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -11,7 +11,7 @@
 endif
 
 # Object file lists
-obj-$(CONFIG_SECURITY)			+= security.o dummy.o
+obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
diff --git a/security/inode.c b/security/inode.c
new file mode 100644
index 0000000..a596450
--- /dev/null
+++ b/security/inode.c
@@ -0,0 +1,347 @@
+/*
+ *  inode.c - securityfs
+ *
+ *  Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License version
+ *	2 as published by the Free Software Foundation.
+ *
+ *  Based on fs/debugfs/inode.c which had the following copyright notice:
+ *    Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *    Copyright (C) 2004 IBM Inc.
+ */
+
+/* #define DEBUG */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+
+#define SECURITYFS_MAGIC	0x73636673
+
+static struct vfsmount *mount;
+static int mount_count;
+
+/*
+ * TODO:
+ *   I think I can get rid of these default_file_ops, but not quite sure...
+ */
+static ssize_t default_read_file(struct file *file, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t default_write_file(struct file *file, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+	if (inode->u.generic_ip)
+		file->private_data = inode->u.generic_ip;
+
+	return 0;
+}
+
+static struct file_operations default_file_ops = {
+	.read =		default_read_file,
+	.write =	default_write_file,
+	.open =		default_open,
+};
+
+static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = 0;
+		inode->i_gid = 0;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &default_file_ops;
+			break;
+		case S_IFDIR:
+			inode->i_op = &simple_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+
+			/* directory inodes start off with i_nlink == 2 (for "." entry) */
+			inode->i_nlink++;
+			break;
+		}
+	}
+	return inode;
+}
+
+/* SMP-safe */
+static int mknod(struct inode *dir, struct dentry *dentry,
+			 int mode, dev_t dev)
+{
+	struct inode *inode;
+	int error = -EPERM;
+
+	if (dentry->d_inode)
+		return -EEXIST;
+
+	inode = get_inode(dir->i_sb, mode, dev);
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int res;
+
+	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
+	res = mknod(dir, dentry, mode, 0);
+	if (!res)
+		dir->i_nlink++;
+	return res;
+}
+
+static int create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	mode = (mode & S_IALLUGO) | S_IFREG;
+	return mknod(dir, dentry, mode, 0);
+}
+
+static inline int positive(struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int fill_super(struct super_block *sb, void *data, int silent)
+{
+	static struct tree_descr files[] = {{""}};
+
+	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
+}
+
+static struct super_block *get_sb(struct file_system_type *fs_type,
+				        int flags, const char *dev_name,
+					void *data)
+{
+	return get_sb_single(fs_type, flags, data, fill_super);
+}
+
+static struct file_system_type fs_type = {
+	.owner =	THIS_MODULE,
+	.name =		"securityfs",
+	.get_sb =	get_sb,
+	.kill_sb =	kill_litter_super,
+};
+
+static int create_by_name(const char *name, mode_t mode,
+			  struct dentry *parent,
+			  struct dentry **dentry)
+{
+	int error = 0;
+
+	*dentry = NULL;
+
+	/* If the parent is not specified, we create it in the root.
+	 * We need the root dentry to do this, which is in the super
+	 * block. A pointer to that is in the struct vfsmount that we
+	 * have around.
+	 */
+	if (!parent ) {
+		if (mount && mount->mnt_sb) {
+			parent = mount->mnt_sb->s_root;
+		}
+	}
+	if (!parent) {
+		pr_debug("securityfs: Ah! can not find a parent!\n");
+		return -EFAULT;
+	}
+
+	down(&parent->d_inode->i_sem);
+	*dentry = lookup_one_len(name, parent, strlen(name));
+	if (!IS_ERR(dentry)) {
+		if ((mode & S_IFMT) == S_IFDIR)
+			error = mkdir(parent->d_inode, *dentry, mode);
+		else
+			error = create(parent->d_inode, *dentry, mode);
+	} else
+		error = PTR_ERR(dentry);
+	up(&parent->d_inode->i_sem);
+
+	return error;
+}
+
+/**
+ * securityfs_create_file - create a file in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the file to create.
+ * @mode: the permission that the file should have
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          file will be created in the root of the securityfs filesystem.
+ * @data: a pointer to something that the caller will want to get to later
+ *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        the open() call.
+ * @fops: a pointer to a struct file_operations that should be used for
+ *        this file.
+ *
+ * This is the basic "create a file" function for securityfs.  It allows for a
+ * wide range of flexibility in createing a file, or a directory (if you
+ * want to create a directory, the securityfs_create_dir() function is
+ * recommended to be used instead.)
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned.  It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_file(const char *name, mode_t mode,
+				   struct dentry *parent, void *data,
+				   struct file_operations *fops)
+{
+	struct dentry *dentry = NULL;
+	int error;
+
+	pr_debug("securityfs: creating file '%s'\n",name);
+
+	error = simple_pin_fs("securityfs", &mount, &mount_count);
+	if (error) {
+		dentry = ERR_PTR(error);
+		goto exit;
+	}
+
+	error = create_by_name(name, mode, parent, &dentry);
+	if (error) {
+		dentry = ERR_PTR(error);
+		simple_release_fs(&mount, &mount_count);
+		goto exit;
+	}
+
+	if (dentry->d_inode) {
+		if (fops)
+			dentry->d_inode->i_fop = fops;
+		if (data)
+			dentry->d_inode->u.generic_ip = data;
+	}
+exit:
+	return dentry;
+}
+EXPORT_SYMBOL_GPL(securityfs_create_file);
+
+/**
+ * securityfs_create_dir - create a directory in the securityfs filesystem
+ *
+ * @name: a pointer to a string containing the name of the directory to
+ *        create.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory will be created in the root of the securityfs filesystem.
+ *
+ * This function creates a directory in securityfs with the given name.
+ *
+ * This function will return a pointer to a dentry if it succeeds.  This
+ * pointer must be passed to the securityfs_remove() function when the file is
+ * to be removed (no automatic cleanup happens if your module is unloaded,
+ * you are responsible here.)  If an error occurs, NULL will be returned.
+ *
+ * If securityfs is not enabled in the kernel, the value -ENODEV will be
+ * returned.  It is not wise to check for this value, but rather, check for
+ * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
+ * code.
+ */
+struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
+{
+	return securityfs_create_file(name,
+				      S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+				      parent, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(securityfs_create_dir);
+
+/**
+ * securityfs_remove - removes a file or directory from the securityfs filesystem
+ *
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ *          removed.
+ *
+ * This function removes a file or directory in securityfs that was previously
+ * created with a call to another securityfs function (like
+ * securityfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void securityfs_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+
+	if (!dentry)
+		return;
+
+	parent = dentry->d_parent;
+	if (!parent || !parent->d_inode)
+		return;
+
+	down(&parent->d_inode->i_sem);
+	if (positive(dentry)) {
+		if (dentry->d_inode) {
+			if (S_ISDIR(dentry->d_inode->i_mode))
+				simple_rmdir(parent->d_inode, dentry);
+			else
+				simple_unlink(parent->d_inode, dentry);
+			dput(dentry);
+		}
+	}
+	up(&parent->d_inode->i_sem);
+	simple_release_fs(&mount, &mount_count);
+}
+EXPORT_SYMBOL_GPL(securityfs_remove);
+
+static decl_subsys(security, NULL, NULL);
+
+static int __init securityfs_init(void)
+{
+	int retval;
+
+	kset_set_kset_s(&security_subsys, kernel_subsys);
+	retval = subsystem_register(&security_subsys);
+	if (retval)
+		return retval;
+
+	retval = register_filesystem(&fs_type);
+	if (retval)
+		subsystem_unregister(&security_subsys);
+	return retval;
+}
+
+static void __exit securityfs_exit(void)
+{
+	simple_release_fs(&mount, &mount_count);
+	unregister_filesystem(&fs_type);
+	subsystem_unregister(&security_subsys);
+}
+
+core_initcall(securityfs_init);
+module_exit(securityfs_exit);
+MODULE_LICENSE("GPL");
+
diff --git a/security/seclvl.c b/security/seclvl.c
index 96b1f21..dc4e17b 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -119,69 +119,6 @@
 	} while (0)
 
 /**
- * kobject stuff
- */
-
-struct subsystem seclvl_subsys;
-
-struct seclvl_obj {
-	char *name;
-	struct list_head slot_list;
-	struct kobject kobj;
-};
-
-/**
- * There is a seclvl_attribute struct for each file in sysfs.
- *
- * In our case, we have one of these structs for "passwd" and another
- * for "seclvl".
- */
-struct seclvl_attribute {
-	struct attribute attr;
-	ssize_t(*show) (struct seclvl_obj *, char *);
-	ssize_t(*store) (struct seclvl_obj *, const char *, size_t);
-};
-
-/**
- * When this function is called, one of the files in sysfs is being
- * written to.  attribute->store is a function pointer to whatever the
- * struct seclvl_attribute store function pointer points to.  It is
- * unique for "passwd" and "seclvl".
- */
-static ssize_t
-seclvl_attr_store(struct kobject *kobj,
-		  struct attribute *attr, const char *buf, size_t len)
-{
-	struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
-	struct seclvl_attribute *attribute =
-	    container_of(attr, struct seclvl_attribute, attr);
-	return attribute->store ? attribute->store(obj, buf, len) : -EIO;
-}
-
-static ssize_t
-seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
-	struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
-	struct seclvl_attribute *attribute =
-	    container_of(attr, struct seclvl_attribute, attr);
-	return attribute->show ? attribute->show(obj, buf) : -EIO;
-}
-
-/**
- * Callback function pointers for show and store
- */
-static struct sysfs_ops seclvlfs_sysfs_ops = {
-	.show = seclvl_attr_show,
-	.store = seclvl_attr_store,
-};
-
-static struct kobj_type seclvl_ktype = {
-	.sysfs_ops = &seclvlfs_sysfs_ops
-};
-
-decl_subsys(seclvl, &seclvl_ktype, NULL);
-
-/**
  * The actual security level.  Ranges between -1 and 2 inclusive.
  */
 static int seclvl;
@@ -213,97 +150,44 @@
 }
 
 /**
- * Called whenever the user reads the sysfs handle to this kernel
- * object
- */
-static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff)
-{
-	return snprintf(buff, PAGE_SIZE, "%d\n", seclvl);
-}
-
-/**
  * security level advancement rules:
  *   Valid levels are -1 through 2, inclusive.
  *   From -1, stuck.  [ in case compiled into kernel ]
  *   From 0 or above, can only increment.
  */
-static int do_seclvl_advance(int newlvl)
+static void do_seclvl_advance(void *data, u64 val)
 {
-	if (newlvl <= seclvl) {
-		seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
-			      "[%d]\n", newlvl);
-		return -EINVAL;
-	}
+	int ret;
+	int newlvl = (int)val;
+
+	ret = seclvl_sanity(newlvl);
+	if (ret)
+		return;
+
 	if (newlvl > 2) {
 		seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
 			      "[%d]\n", newlvl);
-		return -EINVAL;
+		return;
 	}
 	if (seclvl == -1) {
 		seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
 			      "seclvl [%d]\n", seclvl);
-		return -EPERM;
+		return;
 	}
-	seclvl = newlvl;
-	return 0;
+	seclvl = newlvl;  /* would it be more "correct" to set *data? */
+	return;
 }
 
-/**
- * Called whenever the user writes to the sysfs handle to this kernel
- * object (seclvl/seclvl).  It expects a single-digit number.
- */
-static ssize_t
-seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)
+static u64 seclvl_int_get(void *data)
 {
-	unsigned long val;
-	if (count > 2 || (count == 2 && buff[1] != '\n')) {
-		seclvl_printk(1, KERN_WARNING, "Invalid value passed to "
-			      "seclvl: [%s]\n", buff);
-		return -EINVAL;
-	}
-	val = buff[0] - 48;
-	if (seclvl_sanity(val)) {
-		seclvl_printk(1, KERN_WARNING, "Illegal secure level "
-			      "requested: [%d]\n", (int)val);
-		return -EPERM;
-	}
-	if (do_seclvl_advance(val)) {
-		seclvl_printk(0, KERN_ERR, "Failure advancing security level "
-			      "to %lu\n", val);
-	}
-	return count;
+	return *(int *)data;
 }
 
-/* Generate sysfs_attr_seclvl */
-static struct seclvl_attribute sysfs_attr_seclvl =
-__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,
-       seclvl_write_file);
+DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");
 
 static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
 
 /**
- * Called whenever the user reads the sysfs passwd handle.
- */
-static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff)
-{
-	/* So just how good *is* your password? :-) */
-	char tmp[3];
-	int i = 0;
-	buff[0] = '\0';
-	if (hideHash) {
-		/* Security through obscurity */
-		return 0;
-	}
-	while (i < SHA1_DIGEST_SIZE) {
-		snprintf(tmp, 3, "%02x", hashedPassword[i]);
-		strncat(buff, tmp, 2);
-		i++;
-	}
-	strcat(buff, "\n");
-	return ((SHA1_DIGEST_SIZE * 2) + 1);
-}
-
-/**
  * Converts a block of plaintext of into its SHA1 hashed value.
  *
  * It would be nice if crypto had a wrapper to do this for us linear
@@ -347,12 +231,15 @@
  * object.  It hashes the password and compares the hashed results.
  */
 static ssize_t
-seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
+passwd_write_file(struct file * file, const char __user * buf,
+				size_t count, loff_t *ppos)
 {
 	int i;
 	unsigned char tmp[SHA1_DIGEST_SIZE];
+	char *page;
 	int rc;
 	int len;
+
 	if (!*passwd && !*sha1_passwd) {
 		seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
 			      "seclvl module, but neither a plain text "
@@ -363,13 +250,26 @@
 			      "maintainer about this event.\n");
 		return -EINVAL;
 	}
-	len = strlen(buff);
+
+	if (count < 0 || count >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		return -EINVAL;
+	}
+	page = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	len = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+	
+	len = strlen(page);
 	/* ``echo "secret" > seclvl/passwd'' includes a newline */
-	if (buff[len - 1] == '\n') {
+	if (page[len - 1] == '\n') {
 		len--;
 	}
 	/* Hash the password, then compare the hashed values */
-	if ((rc = plaintext_to_sha1(tmp, buff, len))) {
+	if ((rc = plaintext_to_sha1(tmp, page, len))) {
 		seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
 			      "[%d]\n", rc);
 		return rc;
@@ -382,13 +282,16 @@
 	seclvl_printk(0, KERN_INFO,
 		      "Password accepted; seclvl reduced to 0.\n");
 	seclvl = 0;
-	return count;
+	len = count;
+
+out:
+	free_page((unsigned long)page);
+	return len;
 }
 
-/* Generate sysfs_attr_passwd */
-static struct seclvl_attribute sysfs_attr_passwd =
-__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd,
-       seclvl_write_passwd);
+static struct file_operations passwd_file_ops = {
+	.write = passwd_write_file,
+};
 
 /**
  * Explicitely disallow ptrace'ing the init process.
@@ -647,22 +550,34 @@
 }
 
 /**
- * Sysfs registrations
+ * securityfs registrations
  */
-static int doSysfsRegistrations(void)
+struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
+
+static int seclvlfs_register(void)
 {
-	int rc = 0;
-	if ((rc = subsystem_register(&seclvl_subsys))) {
-		seclvl_printk(0, KERN_WARNING,
-			      "Error [%d] registering seclvl subsystem\n", rc);
-		return rc;
-	}
-	sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
+	dir_ino = securityfs_create_dir("seclvl", NULL);
+	if (!dir_ino)
+		return -EFAULT;
+
+	seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
+				dir_ino, &seclvl, &seclvl_file_ops);
+	if (!seclvl_ino)
+		goto out_deldir;
 	if (*passwd || *sha1_passwd) {
-		sysfs_create_file(&seclvl_subsys.kset.kobj,
-				  &sysfs_attr_passwd.attr);
+		passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
+				dir_ino, NULL, &passwd_file_ops);
+		if (!passwd_ino)
+			goto out_delf;
 	}
 	return 0;
+
+out_deldir:
+	securityfs_remove(dir_ino);
+out_delf:
+	securityfs_remove(seclvl_ino);
+
+	return -EFAULT;
 }
 
 /**
@@ -677,8 +592,6 @@
 		rc = -EINVAL;
 		goto exit;
 	}
-	sysfs_attr_seclvl.attr.owner = THIS_MODULE;
-	sysfs_attr_passwd.attr.owner = THIS_MODULE;
 	if (initlvl < -1 || initlvl > 2) {
 		seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
 			      "[%d].\n", initlvl);
@@ -706,7 +619,7 @@
 		}		/* if primary module registered */
 		secondary = 1;
 	}			/* if we registered ourselves with the security framework */
-	if ((rc = doSysfsRegistrations())) {
+	if ((rc = seclvlfs_register())) {
 		seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
 		goto exit;
 	}
@@ -724,12 +637,11 @@
  */
 static void __exit seclvl_exit(void)
 {
-	sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
+	securityfs_remove(seclvl_ino);
 	if (*passwd || *sha1_passwd) {
-		sysfs_remove_file(&seclvl_subsys.kset.kobj,
-				  &sysfs_attr_passwd.attr);
+		securityfs_remove(passwd_ino);
 	}
-	subsystem_unregister(&seclvl_subsys);
+	securityfs_remove(dir_ino);
 	if (secondary == 1) {
 		mod_unreg_security(MY_NAME, &seclvl_ops);
 	} else if (unregister_security(&seclvl_ops)) {
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index cf6020f..12e4fb7 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -242,7 +242,7 @@
 	avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
 					     0, SLAB_PANIC, NULL, NULL);
 
-	audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
+	audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n");
 }
 
 int avc_get_hash_stats(char *page)
@@ -550,7 +550,7 @@
 			return;
 	}
 
-	ab = audit_log_start(current->audit_context, AUDIT_AVC);
+	ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
 	if (!ab)
 		return;		/* audit_panic has been called */
 	audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f40c822..6e4937f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3389,7 +3389,7 @@
 	err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
 	if (err) {
 		if (err == -EINVAL) {
-			audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+			audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
 				  "SELinux:  unrecognized netlink message"
 				  " type=%hu for sclass=%hu\n",
 				  nlh->nlmsg_type, isec->sclass);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 92b89dc..aecdded 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -381,7 +381,7 @@
 		goto out;
 	if (context_struct_to_string(tcontext, &t, &tlen) < 0)
 		goto out;
-	audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
 	          "security_validate_transition:  denied for"
 	          " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
 	          o, n, t, policydb.p_class_val_to_name[tclass-1]);
@@ -787,7 +787,7 @@
 		goto out;
 	if (context_struct_to_string(newcontext, &n, &nlen) < 0)
 		goto out;
-	audit_log(current->audit_context, AUDIT_SELINUX_ERR,
+	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
 		  "security_compute_sid:  invalid context %s"
 		  " for scontext=%s"
 		  " tcontext=%s"
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 2e4a5e0..0864a7c 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -7,6 +7,7 @@
 	tristate "SA11xx UDA1341TS driver (iPaq H3600)"
 	depends on ARCH_SA1100 && SND && L3
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here if you have a Compaq iPaq H3x00 handheld computer
 	  and want to use its Philips UDA 1341 audio chip.
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 9887703..34195b74 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -900,6 +900,8 @@
 	if (ret)
 		goto out;
 
+	snd_card_set_dev(aaci->card, &dev->dev);
+
 	ret = snd_card_register(aaci->card);
 	if (ret == 0) {
 		dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 174bc03..6ee9122 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -21,7 +21,7 @@
  *                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.23 2005/09/09 13:22:34 tiwai Exp $ */
 
 /***************************************************************************************************
 *
@@ -918,7 +918,7 @@
 	if (card == NULL)
 		return -ENOMEM;
 
-	sa11xx_uda1341 = kcalloc(1, sizeof(*sa11xx_uda1341), GFP_KERNEL);
+	sa11xx_uda1341 = kzalloc(sizeof(*sa11xx_uda1341), GFP_KERNEL);
 	if (sa11xx_uda1341 == NULL)
 		return -ENOMEM;	
 	spin_lock_init(&chip->s[0].dma_lock);
@@ -946,6 +946,9 @@
 	strcpy(card->shortname, "H3600 UDA1341TS");
 	sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS");
         
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto nodev;
+
 	if ((err = snd_card_register(card)) == 0) {
 		printk( KERN_INFO "iPAQ audio support initialized\n" );
 		return 0;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index d1e800b..48cf45c 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -99,6 +99,18 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-rtctimer.
 
+config SND_SEQ_RTCTIMER_DEFAULT
+	bool "Use RTC as default sequencer timer"
+	depends on SND_RTCTIMER && SND_SEQUENCER
+	default y
+	help
+	  Say Y here to use the RTC timer as the default sequencer
+	  timer.  This is strongly recommended because it ensures
+	  precise MIDI timing even when the system timer runs at less
+	  than 1000 Hz.
+
+	  If in doubt, say Y.
+
 config SND_VERBOSE_PRINTK
 	bool "Verbose printk"
 	depends on SND
@@ -128,6 +140,6 @@
 	  Say Y here to enable extra-verbose log messages printed when
 	  detecting devices.
 
-config SND_GENERIC_PM
+config SND_GENERIC_DRIVER
 	bool
 	depends on SND
diff --git a/sound/core/control.c b/sound/core/control.c
index 227f3cf..736edf3 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -69,7 +69,7 @@
 		err = -EFAULT;
 		goto __error2;
 	}
-	ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
+	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
 	if (ctl == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -162,7 +162,7 @@
 				goto _found;
 			}
 		}
-		ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
+		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (ev) {
 			ev->id = *id;
 			ev->mask = mask;
@@ -195,7 +195,7 @@
 	
 	snd_runtime_check(control != NULL, return NULL);
 	snd_runtime_check(control->count > 0, return NULL);
-	kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
+	kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
 	if (kctl == NULL)
 		return NULL;
 	*kctl = *control;
@@ -521,7 +521,7 @@
 {
 	snd_ctl_card_info_t *info;
 
-	info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (! info)
 		return -ENOMEM;
 	down_read(&snd_ioctl_rwsem);
@@ -929,7 +929,7 @@
 		return -EINVAL;
 	}
 	private_size *= info->count;
-	ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL);
+	ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
 	if (ue == NULL)
 		return -ENOMEM;
 	ue->info = *info;
@@ -1185,7 +1185,7 @@
 {
 	snd_kctl_ioctl_t *pn;
 
-	pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+	pn = kzalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
 	if (pn == NULL)
 		return -ENOMEM;
 	pn->fioctl = fcn;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 7fdabea..207c7de 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -92,7 +92,7 @@
 	struct sndrv_ctl_elem_info *data;
 	int err;
 
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (! data)
 		return -ENOMEM;
 
@@ -271,7 +271,7 @@
 	struct sndrv_ctl_elem_value *data;
 	int err, type, count;
 
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
 
@@ -291,7 +291,7 @@
 	struct sndrv_ctl_elem_value *data;
 	int err, type, count;
 
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
 
@@ -313,7 +313,7 @@
 	struct sndrv_ctl_elem_info *data;
 	int err;
 
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (! data)
 		return -ENOMEM;
 
diff --git a/sound/core/device.c b/sound/core/device.c
index ca00ad7..1f509f5 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -49,7 +49,7 @@
 	snd_assert(card != NULL, return -ENXIO);
 	snd_assert(device_data != NULL, return -ENXIO);
 	snd_assert(ops != NULL, return -ENXIO);
-	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	dev->card = card;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 997dd41..9383f12 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -359,7 +359,7 @@
 	snd_assert(rhwdep != NULL, return -EINVAL);
 	*rhwdep = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
+	hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
 	if (hwdep == NULL)
 		return -ENOMEM;
 	hwdep->card = card;
diff --git a/sound/core/info.c b/sound/core/info.c
index 7f8bdf7..37024d6 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -295,7 +295,7 @@
 		    	goto __error;
 		}
 	}
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (data == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -304,7 +304,7 @@
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
 		if (mode == O_RDONLY || mode == O_RDWR) {
-			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
 				kfree(data);
 				err = -ENOMEM;
@@ -323,7 +323,7 @@
 			data->rbuffer = buffer;
 		}
 		if (mode == O_WRONLY || mode == O_RDWR) {
-			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
+			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
 				if (mode == O_RDWR) {
 					vfree(data->rbuffer->buffer);
@@ -752,7 +752,7 @@
 static snd_info_entry_t *snd_info_create_entry(const char *name)
 {
 	snd_info_entry_t *entry;
-	entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (entry == NULL)
 		return NULL;
 	entry->name = kstrdup(name, GFP_KERNEL);
diff --git a/sound/core/init.c b/sound/core/init.c
index d72f58f..a570201 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -72,7 +72,7 @@
 
 	if (extra_size < 0)
 		extra_size = 0;
-	card = kcalloc(1, sizeof(*card) + extra_size, GFP_KERNEL);
+	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
 	if (card == NULL)
 		return NULL;
 	if (xid) {
@@ -226,8 +226,10 @@
 	return 0;	
 }
 
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
-static void snd_generic_device_unregister(struct snd_generic_device *dev);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+static void snd_generic_device_unregister(snd_card_t *card);
+#else
+#define snd_generic_device_unregister(x) /*NOP*/
 #endif
 
 /**
@@ -253,14 +255,7 @@
 
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
-#ifdef CONFIG_SND_GENERIC_PM
-	if (card->pm_dev) {
-		snd_generic_device_unregister(card->pm_dev);
-		card->pm_dev = NULL;
-	}
 #endif
-#endif
-
 	/* wait, until all devices are ready for the free operation */
 	wait_event(card->shutdown_sleep, card->files == NULL);
 
@@ -288,6 +283,7 @@
 		snd_printk(KERN_WARNING "unable to free card info\n");
 		/* Not fatal error */
 	}
+	snd_generic_device_unregister(card);
 	while (card->s_f_ops) {
 		s_f_ops = card->s_f_ops;
 		card->s_f_ops = s_f_ops->next;
@@ -665,6 +661,96 @@
 	return 0;
 }
 
+#ifdef CONFIG_SND_GENERIC_DRIVER
+/*
+ * generic device without a proper bus using platform_device
+ * (e.g. ISA)
+ */
+struct snd_generic_device {
+	struct platform_device pdev;
+	snd_card_t *card;
+};
+
+#define get_snd_generic_card(dev)	container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
+
+#define SND_GENERIC_NAME	"snd_generic"
+
+#ifdef CONFIG_PM
+static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
+static int snd_generic_resume(struct device *dev, u32 level);
+#endif
+
+/* initialized in sound.c */
+struct device_driver snd_generic_driver = {
+	.name		= SND_GENERIC_NAME,
+	.bus		= &platform_bus_type,
+#ifdef CONFIG_PM
+	.suspend	= snd_generic_suspend,
+	.resume		= snd_generic_resume,
+#endif
+};
+
+void snd_generic_device_release(struct device *dev)
+{
+}
+
+static int snd_generic_device_register(snd_card_t *card)
+{
+	struct snd_generic_device *dev;
+	int err;
+
+	if (card->generic_dev)
+		return 0; /* already registered */
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (! dev) {
+		snd_printk(KERN_ERR "can't allocate generic_device\n");
+		return -ENOMEM;
+	}
+
+	dev->pdev.name = SND_GENERIC_NAME;
+	dev->pdev.id = card->number;
+	dev->pdev.dev.release = snd_generic_device_release;
+	dev->card = card;
+	if ((err = platform_device_register(&dev->pdev)) < 0) {
+		kfree(dev);
+		return err;
+	}
+	card->generic_dev = dev;
+	return 0;
+}
+
+static void snd_generic_device_unregister(snd_card_t *card)
+{
+	struct snd_generic_device *dev = card->generic_dev;
+	if (dev) {
+		platform_device_unregister(&dev->pdev);
+		kfree(dev);
+		card->generic_dev = NULL;
+	}
+}
+
+/**
+ * snd_card_set_generic_dev - assign the generic device to the card
+ * @card: soundcard structure
+ *
+ * Assigns a generic device to the card.  This function is provided as the
+ * last resort, for devices without any proper bus.  Thus this won't override
+ * the device already assigned to the card.
+ * 
+ * Returns zero if successful, or a negative error code.
+ */
+int snd_card_set_generic_dev(snd_card_t *card)
+{
+	int err;
+	if ((err = snd_generic_device_register(card)) < 0)
+		return err;
+	if (! card->dev)
+		snd_card_set_dev(card, &card->generic_dev->pdev.dev);
+	return 0;
+}
+#endif /* CONFIG_SND_GENERIC_DRIVER */
+
 #ifdef CONFIG_PM
 /**
  *  snd_power_wait - wait until the power-state is changed.
@@ -730,75 +816,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_SND_GENERIC_PM
-/*
- * use platform_device for generic power-management without a proper bus
- * (e.g. ISA)
- */
-struct snd_generic_device {
-	struct platform_device pdev;
-	snd_card_t *card;
-};
-
-#define get_snd_generic_card(dev)	container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
-
-#define SND_GENERIC_NAME	"snd_generic_pm"
-
-static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level);
-static int snd_generic_resume(struct device *dev, u32 level);
-
-static struct device_driver snd_generic_driver = {
-	.name		= SND_GENERIC_NAME,
-	.bus		= &platform_bus_type,
-	.suspend	= snd_generic_suspend,
-	.resume		= snd_generic_resume,
-};
-
-static int generic_driver_registered;
-
-static void generic_driver_unregister(void)
-{
-	if (generic_driver_registered) {
-		generic_driver_registered--;
-		if (! generic_driver_registered)
-			driver_unregister(&snd_generic_driver);
-	}
-}
-
-static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
-{
-	struct snd_generic_device *dev;
-
-	if (! generic_driver_registered) {
-		if (driver_register(&snd_generic_driver) < 0)
-			return NULL;
-	}
-	generic_driver_registered++;
-
-	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
-	if (! dev) {
-		generic_driver_unregister();
-		return NULL;
-	}
-
-	dev->pdev.name = SND_GENERIC_NAME;
-	dev->pdev.id = card->number;
-	dev->card = card;
-	if (platform_device_register(&dev->pdev) < 0) {
-		kfree(dev);
-		generic_driver_unregister();
-		return NULL;
-	}
-	return dev;
-}
-
-static void snd_generic_device_unregister(struct snd_generic_device *dev)
-{
-	platform_device_unregister(&dev->pdev);
-	kfree(dev);
-	generic_driver_unregister();
-}
-
+#ifdef CONFIG_SND_GENERIC_DRIVER
 /* suspend/resume callbacks for snd_generic platform device */
 static int snd_generic_suspend(struct device *dev, pm_message_t state, u32 level)
 {
@@ -846,13 +864,12 @@
 				 int (*resume)(snd_card_t *),
 				 void *private_data)
 {
-	card->pm_dev = snd_generic_device_register(card);
-	if (! card->pm_dev)
-		return -ENOMEM;
-	snd_card_set_pm_callback(card, suspend, resume, private_data);
-	return 0;
+	int err;
+	if ((err = snd_generic_device_register(card)) < 0)
+		return err;
+	return snd_card_set_pm_callback(card, suspend, resume, private_data);
 }
-#endif /* CONFIG_SND_GENERIC_PM */
+#endif /* CONFIG_SND_GENERIC_DRIVER */
 
 #ifdef CONFIG_PCI
 int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 39a54a4..91124dd 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -590,7 +590,7 @@
 
 		alloced = 0;
 		pci = NULL;
-		while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+		while ((pci = pci_get_device(vendor, device, pci)) != NULL) {
 			if (mask > 0 && mask < 0xffffffff) {
 				if (pci_set_dma_mask(pci, mask) < 0 ||
 				    pci_set_consistent_dma_mask(pci, mask) < 0) {
@@ -604,6 +604,7 @@
 				if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 							size, &dmab) < 0) {
 					printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+					pci_dev_put(pci);
 					return (int)count;
 				}
 				snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 291b476..8fa888f 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -249,7 +249,7 @@
 int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count)
 {
 #if defined(__i386__) || defined(CONFIG_SPARC32)
-	return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
+	return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0;
 #else
 	char buf[256];
 	while (count) {
@@ -280,7 +280,7 @@
 int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count)
 {
 #if defined(__i386__) || defined(CONFIG_SPARC32)
-	return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
+	return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0;
 #else
 	char buf[256];
 	while (count) {
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 98fc076..69e1059 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -53,7 +53,7 @@
 	err = snd_card_file_add(card, file);
 	if (err < 0)
 		return err;
-	fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
+	fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
 	if (fmixer == NULL) {
 		snd_card_file_remove(card, file);
 		return -ENOMEM;
@@ -517,8 +517,8 @@
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -551,8 +551,8 @@
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -612,8 +612,8 @@
 	down_read(&card->controls_rwsem);
 	if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
 		return;
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -649,8 +649,8 @@
 		up_read(&fmixer->card->controls_rwsem);
 		return;
 	}
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -768,8 +768,8 @@
 	snd_ctl_elem_value_t *uctl;
 	int err, idx;
 	
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
@@ -813,8 +813,8 @@
 	int err;
 	unsigned int idx;
 
-	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index a13bd7b..842c28b 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -850,7 +850,9 @@
 					return xfer > 0 ? xfer : -EAGAIN;
 			}
 		} else {
-			tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
+			tmp = snd_pcm_oss_write2(substream,
+						 (const char __force *)buf,
+						 runtime->oss.period_bytes, 0);
 			if (tmp <= 0)
 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 			runtime->oss.bytes += tmp;
@@ -926,7 +928,8 @@
 			xfer += tmp;
 			runtime->oss.buffer_used -= tmp;
 		} else {
-			tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0);
+			tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
+						runtime->oss.period_bytes, 0);
 			if (tmp <= 0)
 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 			runtime->oss.bytes += tmp;
@@ -1540,7 +1543,11 @@
 	} else {
 		delay = snd_pcm_oss_bytes(substream, delay);
 		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+			snd_pcm_oss_setup_t *setup = substream->oss.setup;
+			if (setup && setup->buggyptr)
+				info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
+			else
+				info.blocks = (delay + fixup) / runtime->oss.period_bytes;
 			info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
 		} else {
 			delay += fixup;
@@ -1733,7 +1740,7 @@
 	snd_assert(rpcm_oss_file != NULL, return -EINVAL);
 	*rpcm_oss_file = NULL;
 
-	pcm_oss_file = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL);
+	pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
 	if (pcm_oss_file == NULL)
 		return -ENOMEM;
 
@@ -2347,6 +2354,8 @@
 				template.partialfrag = 1;
 			} else if (!strcmp(str, "no-silence")) {
 				template.nosilence = 1;
+			} else if (!strcmp(str, "buggy-ptr")) {
+				template.buggyptr = 1;
 			}
 		} while (*str);
 		if (setup == NULL) {
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6430410..fc23373 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -171,7 +171,7 @@
 	
 	snd_assert(plug != NULL, return -ENXIO);
 	snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
-	plugin = kcalloc(1, sizeof(*plugin) + extra, GFP_KERNEL);
+	plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
 	if (plugin == NULL)
 		return -ENOMEM;
 	plugin->name = name;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9f4c920..1be470e 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -597,7 +597,7 @@
 	}
 	prev = NULL;
 	for (idx = 0, prev = NULL; idx < substream_count; idx++) {
-		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+		substream = kzalloc(sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->pcm = pcm;
@@ -657,7 +657,7 @@
 	snd_assert(rpcm != NULL, return -EINVAL);
 	*rpcm = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
+	pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
 	if (pcm == NULL)
 		return -ENOMEM;
 	pcm->card = card;
@@ -795,7 +795,7 @@
 	if (substream == NULL)
 		return -EAGAIN;
 
-	runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
 	if (runtime == NULL)
 		return -ENOMEM;
 
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0082914..0503980 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -524,6 +524,9 @@
 
 /**
  * snd_interval_div - refine the interval value with division
+ * @a: dividend
+ * @b: divisor
+ * @c: quotient
  *
  * c = a / b
  *
@@ -555,7 +558,11 @@
 
 /**
  * snd_interval_muldivk - refine the interval value
- *
+ * @a: dividend 1
+ * @b: dividend 2
+ * @k: divisor (as integer)
+ * @c: result
+  *
  * c = a * b / k
  *
  * Returns non-zero if the value is changed, zero if not changed.
@@ -582,6 +589,10 @@
 
 /**
  * snd_interval_mulkdiv - refine the interval value
+ * @a: dividend 1
+ * @k: dividend 2 (as integer)
+ * @b: divisor
+ * @c: result
  *
  * c = a * k / b
  *
@@ -618,6 +629,11 @@
 
 /**
  * snd_interval_ratnum - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratnum_t 
+ * @rats: ratnum_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
  *
  * Returns non-zero if the value is changed, zero if not changed.
  */
@@ -715,6 +731,11 @@
 
 /**
  * snd_interval_ratden - refine the interval value
+ * @i: interval to refine
+ * @rats_count: number of ratden_t
+ * @rats: ratden_t array
+ * @nump: pointer to store the resultant numerator
+ * @denp: pointer to store the resultant denominator
  *
  * Returns non-zero if the value is changed, zero if not changed.
  */
@@ -936,6 +957,11 @@
 
 /**
  * snd_pcm_hw_constraint_mask
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
  */
 int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
 			       u_int32_t mask)
@@ -951,6 +977,11 @@
 
 /**
  * snd_pcm_hw_constraint_mask64
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the mask
+ * @mask: the 64bit bitmap mask
+ *
+ * Apply the constraint of the given bitmap mask to a mask parameter.
  */
 int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
 				 u_int64_t mask)
@@ -967,6 +998,10 @@
 
 /**
  * snd_pcm_hw_constraint_integer
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the integer constraint
+ *
+ * Apply the constraint of integer to an interval parameter.
  */
 int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var)
 {
@@ -976,6 +1011,12 @@
 
 /**
  * snd_pcm_hw_constraint_minmax
+ * @runtime: PCM runtime instance
+ * @var: hw_params variable to apply the range
+ * @min: the minimal value
+ * @max: the maximal value
+ * 
+ * Apply the min/max range constraint to an interval parameter.
  */
 int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
 				 unsigned int min, unsigned int max)
@@ -999,6 +1040,12 @@
 
 /**
  * snd_pcm_hw_constraint_list
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the list constraint
+ * @l: list
+ * 
+ * Apply the list of constraints to an interval parameter.
  */
 int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
 			       unsigned int cond,
@@ -1027,6 +1074,10 @@
 
 /**
  * snd_pcm_hw_constraint_ratnums
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratnums constraint
+ * @r: ratnums_t constriants
  */
 int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime, 
 				  unsigned int cond,
@@ -1054,6 +1105,10 @@
 
 /**
  * snd_pcm_hw_constraint_ratdens
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the ratdens constraint
+ * @r: ratdens_t constriants
  */
 int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime, 
 				  unsigned int cond,
@@ -1079,6 +1134,10 @@
 
 /**
  * snd_pcm_hw_constraint_msbits
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @width: sample bits width
+ * @msbits: msbits width
  */
 int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime, 
 				 unsigned int cond,
@@ -1101,6 +1160,10 @@
 
 /**
  * snd_pcm_hw_constraint_step
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the step constraint
+ * @step: step size
  */
 int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
 			       unsigned int cond,
@@ -1126,6 +1189,9 @@
 
 /**
  * snd_pcm_hw_constraint_pow2
+ * @runtime: PCM runtime instance
+ * @cond: condition bits
+ * @var: hw_params variable to apply the power-of-2 constraint
  */
 int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
 			       unsigned int cond,
@@ -1162,7 +1228,7 @@
 }
 
 #if 0
-/**
+/*
  * snd_pcm_hw_param_any
  */
 int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
@@ -1185,7 +1251,7 @@
 }
 
 #if 0
-/**
+/*
  * snd_pcm_hw_params_any
  *
  * Fill PARAMS with full configuration space boundaries
@@ -1199,6 +1265,9 @@
 
 /**
  * snd_pcm_hw_param_value
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Return the value for field PAR if it's fixed in configuration space 
  *  defined by PARAMS. Return -EINVAL otherwise
@@ -1228,6 +1297,9 @@
 
 /**
  * snd_pcm_hw_param_value_min
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Return the minimum value for field PAR.
  */
@@ -1251,6 +1323,9 @@
 
 /**
  * snd_pcm_hw_param_value_max
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Return the maximum value for field PAR.
  */
@@ -1302,7 +1377,7 @@
 }
 	
 #if 0
-/**
+/*
  * snd_pcm_hw_param_setinteger
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
@@ -1347,6 +1422,10 @@
 
 /**
  * snd_pcm_hw_param_first
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
  * values > minimum. Reduce configuration space accordingly.
@@ -1388,6 +1467,10 @@
 
 /**
  * snd_pcm_hw_param_last
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
  * values < maximum. Reduce configuration space accordingly.
@@ -1439,6 +1522,11 @@
 
 /**
  * snd_pcm_hw_param_min
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: minimal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
  * values < VAL. Reduce configuration space accordingly.
@@ -1494,6 +1582,11 @@
 
 /**
  * snd_pcm_hw_param_max
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: maximal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
  *  values >= VAL + 1. Reduce configuration space accordingly.
@@ -1565,6 +1658,11 @@
 
 /**
  * snd_pcm_hw_param_set
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS remove from PAR all 
  * values != VAL. Reduce configuration space accordingly.
@@ -1599,6 +1697,10 @@
 
 /**
  * snd_pcm_hw_param_mask
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: mask to apply
  *
  * Inside configuration space defined by PARAMS remove from PAR all values
  * not contained in MASK. Reduce configuration space accordingly.
@@ -1671,6 +1773,11 @@
 
 /**
  * snd_pcm_hw_param_near
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @best: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
  *
  * Inside configuration space defined by PARAMS set PAR to the available value
  * nearest to VAL. Reduce configuration space accordingly.
@@ -1747,6 +1854,8 @@
 
 /**
  * snd_pcm_hw_param_choose
+ * @pcm: PCM instance
+ * @params: the hw_params instance
  *
  * Choose one configuration from configuration space defined by PARAMS
  * The configuration chosen is that obtained fixing in this order:
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 9a174fb..b3f5344 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -244,7 +244,7 @@
 
 /**
  * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
- * @substream: the pcm substream instance
+ * @pcm: the pcm instance
  * @type: DMA type (SNDRV_DMA_TYPE_*)
  * @data: DMA type dependant data
  * @size: the requested pre-allocation size in bytes
@@ -321,7 +321,7 @@
 	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
 		dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
 	} else {
-		dmab = kcalloc(1, sizeof(*dmab), GFP_KERNEL);
+		dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
 		if (! dmab)
 			return -ENOMEM;
 		dmab->dev = substream->dma_buffer.dev;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 03c1715..67abeba 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -859,6 +859,7 @@
 
 /**
  * snd_pcm_start
+ * @substream: the PCM substream instance
  *
  * Start all linked streams.
  */
@@ -908,6 +909,8 @@
 
 /**
  * snd_pcm_stop
+ * @substream: the PCM substream instance
+ * @state: PCM state after stopping the stream
  *
  * Try to stop all running streams in the substream group.
  * The state of each stream is changed to the given value after that unconditionally.
@@ -919,6 +922,7 @@
 
 /**
  * snd_pcm_drain_done
+ * @substream: the PCM substream
  *
  * Stop the DMA only when the given stream is playback.
  * The state is changed to SETUP.
@@ -1040,6 +1044,7 @@
 
 /**
  * snd_pcm_suspend
+ * @substream: the PCM substream
  *
  * Trigger SUSPEND to all linked streams.
  * After this call, all streams are changed to SUSPENDED state.
@@ -1057,6 +1062,7 @@
 
 /**
  * snd_pcm_suspend_all
+ * @pcm: the PCM instance
  *
  * Trigger SUSPEND to all substreams in the given pcm.
  * After this call, all streams are changed to SUSPENDED state.
@@ -1272,6 +1278,9 @@
 
 /**
  * snd_pcm_prepare
+ * @substream: the PCM substream instance
+ *
+ * Prepare the PCM substream to be triggerable.
  */
 int snd_pcm_prepare(snd_pcm_substream_t *substream)
 {
@@ -1992,7 +2001,7 @@
 	snd_assert(rpcm_file != NULL, return -EINVAL);
 	*rpcm_file = NULL;
 
-	pcm_file = kcalloc(1, sizeof(*pcm_file), GFP_KERNEL);
+	pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
 	if (pcm_file == NULL) {
 		return -ENOMEM;
 	}
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index edba411..7c20eaf 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -101,7 +101,7 @@
 {
 	snd_rawmidi_runtime_t *runtime;
 
-	if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL)
+	if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	spin_lock_init(&runtime->lock);
 	init_waitqueue_head(&runtime->sleep);
@@ -984,7 +984,9 @@
 			spin_lock_irq(&runtime->lock);
 		}
 		spin_unlock_irq(&runtime->lock);
-		count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
+		count1 = snd_rawmidi_kernel_read1(substream,
+						  (unsigned char __force *)buf,
+						  count, 0);
 		if (count1 < 0)
 			return result > 0 ? result : count1;
 		result += count1;
@@ -1107,7 +1109,7 @@
 /**
  * snd_rawmidi_transmit - copy from the buffer to the device
  * @substream: the rawmidi substream
- * @buf: the buffer pointer
+ * @buffer: the buffer pointer
  * @count: the data size to transfer
  * 
  * Copies data from the buffer to the device and advances the pointer.
@@ -1213,7 +1215,9 @@
 			spin_lock_irq(&runtime->lock);
 		}
 		spin_unlock_irq(&runtime->lock);
-		count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
+		count1 = snd_rawmidi_kernel_write1(substream,
+						   (unsigned char __force *)buf,
+						   count, 0);
 		if (count1 < 0)
 			return result > 0 ? result : count1;
 		result += count1;
@@ -1370,7 +1374,7 @@
 
 	INIT_LIST_HEAD(&stream->substreams);
 	for (idx = 0; idx < count; idx++) {
-		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
+		substream = kzalloc(sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->stream = direction;
@@ -1413,7 +1417,7 @@
 	snd_assert(rrawmidi != NULL, return -EINVAL);
 	*rrawmidi = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	rmidi = kcalloc(1, sizeof(*rmidi), GFP_KERNEL);
+	rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
 	if (rmidi == NULL)
 		return -ENOMEM;
 	rmidi->card = card;
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 32e91c6..207c2c5 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -61,7 +61,7 @@
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = kcalloc(1, sizeof(*wp), gfp_mask);
+	wp = kzalloc(sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 2622b86..b3cee09 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -92,7 +92,7 @@
 		points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
 		if (points_size > *len)
 			return -EINVAL;
-		rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
+		rp = kzalloc(sizeof(*rp) + points_size, gfp_mask);
 		if (rp == NULL)
 			return -ENOMEM;
 		rp->nattack = le16_to_cpu(rx.nattack);
@@ -139,7 +139,7 @@
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = kcalloc(1, sizeof(*wp), gfp_mask);
+	wp = kzalloc(sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -273,7 +273,7 @@
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -EINVAL;
 		}
-		lp = kcalloc(1, sizeof(*lp), gfp_mask);
+		lp = kzalloc(sizeof(*lp), gfp_mask);
 		if (lp == NULL) {
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -ENOMEM;
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index bac4b4f..1ab1cf8 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -193,7 +193,7 @@
 	int i, rc;
 	seq_oss_devinfo_t *dp;
 
-	if ((dp = kcalloc(1, sizeof(*dp), GFP_KERNEL)) == NULL) {
+	if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc device info\n");
 		return -ENOMEM;
 	}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 9aece6c..f0e95c8 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -76,8 +76,8 @@
 	snd_seq_client_info_t *clinfo;
 	snd_seq_port_info_t *pinfo;
 
-	clinfo = kcalloc(1, sizeof(*clinfo), GFP_KERNEL);
-	pinfo = kcalloc(1, sizeof(*pinfo), GFP_KERNEL);
+	clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
+	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
 	if (! clinfo || ! pinfo) {
 		kfree(clinfo);
 		kfree(pinfo);
@@ -172,7 +172,7 @@
 	/*
 	 * allocate midi info record
 	 */
-	if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
+	if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc midi info\n");
 		return -ENOMEM;
 	}
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 0a6f2a6..55571e1 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -46,7 +46,7 @@
 {
 	seq_oss_readq_t *q;
 
-	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
+	if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc read queue\n");
 		return NULL;
 	}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 1a7736c..8257fce 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -103,7 +103,7 @@
 	snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
 	unsigned long flags;
 
-	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
+	if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc synth info\n");
 		return -ENOMEM;
 	}
@@ -499,7 +499,7 @@
 
 	sysex = dp->synths[dev].sysex;
 	if (sysex == NULL) {
-		sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
+		sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
 		if (sysex == NULL)
 			return -ENOMEM;
 		dp->synths[dev].sysex = sysex;
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index 42ca949..64d594b 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -46,7 +46,7 @@
 {
 	seq_oss_timer_t *rec;
 
-	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
 	if (rec == NULL)
 		return NULL;
 
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 87f85f7..b203780 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -38,7 +38,7 @@
 	seq_oss_writeq_t *q;
 	snd_seq_client_pool_t pool;
 
-	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
+	if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
 		return NULL;
 	q->dp = dp;
 	q->maxlen = maxlen;
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 7449d2a..24644150 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -43,7 +43,13 @@
 int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
 int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
 int seq_default_timer_card = -1;
-int seq_default_timer_device = SNDRV_TIMER_GLOBAL_SYSTEM;
+int seq_default_timer_device =
+#ifdef CONFIG_SND_SEQ_RTCTIMER_DEFAULT
+	SNDRV_TIMER_GLOBAL_RTC
+#else
+	SNDRV_TIMER_GLOBAL_SYSTEM
+#endif
+	;
 int seq_default_timer_subdevice = 0;
 int seq_default_timer_resolution = 0;	/* Hz */
 
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index d8f76af..a886db9 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -203,7 +203,7 @@
 	client_t *client;
 
 	/* init client data */
-	client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
 	if (client == NULL)
 		return NULL;
 	client->pool = snd_seq_pool_new(poolsize);
@@ -413,7 +413,9 @@
 			}
 			count -= sizeof(snd_seq_event_t);
 			buf += sizeof(snd_seq_event_t);
-			err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t));
+			err = snd_seq_expand_var_event(&cell->event, count,
+						       (char __force *)buf, 0,
+						       sizeof(snd_seq_event_t));
 			if (err < 0)
 				break;
 			result += err;
@@ -1009,7 +1011,8 @@
 			}
 			/* set user space pointer */
 			event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;
-			event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);
+			event.data.ext.ptr = (char __force *)buf
+						+ sizeof(snd_seq_event_t);
 			len += extlen; /* increment data length */
 		} else {
 #ifdef CONFIG_COMPAT
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4d80f39..252b527 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -200,7 +200,7 @@
 	if (ops == NULL)
 		return -ENOMEM;
 
-	dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
 	if (dev == NULL) {
 		unlock_driver(ops);
 		return -ENOMEM;
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ea945a5..5dd0e6a 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -153,7 +153,7 @@
 	snd_seq_port_callback_t pcb;
 	snd_seq_dummy_port_t *rec;
 
-	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL)
+	if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	rec->client = my_client;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 3b7647c..4767cfd 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -33,7 +33,7 @@
 {
 	fifo_t *f;
 
-	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("malloc failed for snd_seq_fifo_new() \n");
 		return NULL;
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 5b40ea2..019d43a 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -53,7 +53,7 @@
 {
 	snd_seq_kinstr_t *instr;
 	
-	instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+	instr = kzalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
 	if (instr == NULL)
 		return NULL;
 	instr->add_len = add_len;
@@ -77,7 +77,7 @@
 {
 	snd_seq_kinstr_list_t *list;
 
-	list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+	list = kzalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
 	if (list == NULL)
 		return NULL;
 	spin_lock_init(&list->lock);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 03acb2d..d4d7d32 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -452,7 +452,7 @@
 	pool_t *pool;
 
 	/* create pool block */
-	pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
+	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
 	if (pool == NULL) {
 		snd_printd("seq: malloc failed for pool\n");
 		return NULL;
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 4374829..b4674ae 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -322,7 +322,7 @@
 	client = synths[card->number];
 	if (client == NULL) {
 		newclient = 1;
-		client = kcalloc(1, sizeof(*client), GFP_KERNEL);
+		client = kzalloc(sizeof(*client), GFP_KERNEL);
 		if (client == NULL) {
 			up(&register_mutex);
 			kfree(info);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 603b637..2dc1aec 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -118,7 +118,7 @@
 	snd_midi_event_t *dev;
 
 	*rdev = NULL;
-	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	if (bufsize > 0) {
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index b976951..57ec31d 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -141,7 +141,7 @@
 	}
 
 	/* create a new port */
-	new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
+	new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
 	if (! new_port) {
 		snd_printd("malloc failed for registering client port\n");
 		return NULL;	/* failure, out of memory */
@@ -488,7 +488,7 @@
 	unsigned long flags;
 	int exclusive;
 
-	subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
+	subs = kzalloc(sizeof(*subs), GFP_KERNEL);
 	if (! subs)
 		return -ENOMEM;
 
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index a519732e..cd641bc 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -59,7 +59,7 @@
 {
 	prioq_t *f;
 
-	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
 		return NULL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 98de2e7..5f5c3cb 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -111,7 +111,7 @@
 {
 	queue_t *q;
 
-	q = kcalloc(1, sizeof(*q), GFP_KERNEL);
+	q = kzalloc(sizeof(*q), GFP_KERNEL);
 	if (q == NULL) {
 		snd_printd("malloc failed for snd_seq_queue_new()\n");
 		return NULL;
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index e8f0a66..0d9eff8 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -126,8 +126,8 @@
 	snd_seq_client_info_t *inf;
 	snd_seq_port_info_t *port;
 
-	inf = kcalloc(1, sizeof(*inf), GFP_KERNEL);
-	port = kcalloc(1, sizeof(*port), GFP_KERNEL);
+	inf = kzalloc(sizeof(*inf), GFP_KERNEL);
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
 	if (! inf || ! port) {
 		kfree(inf);
 		kfree(port);
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index a7f76fc..b57a3c0 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -60,7 +60,7 @@
 {
 	seq_timer_t *tmr;
 	
-	tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
+	tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
 	if (tmr == NULL) {
 		snd_printd("malloc failed for snd_seq_timer_new() \n");
 		return NULL;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index a66484b5..e4f512a 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -205,7 +205,7 @@
 	snd_virmidi_t *vmidi;
 	unsigned long flags;
 
-	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+	vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
@@ -233,7 +233,7 @@
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 	snd_virmidi_t *vmidi;
 
-	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
+	vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
@@ -508,7 +508,7 @@
 				   &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, rmidi->id);
-	rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
+	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
 	if (rdev == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 3271e92..9e76bdd 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -328,6 +328,10 @@
  *  INIT PART
  */
 
+#ifdef CONFIG_SND_GENERIC_DRIVER
+extern struct device_driver snd_generic_driver;
+#endif
+
 static int __init alsa_sound_init(void)
 {
 	short controlnum;
@@ -354,6 +358,9 @@
 		return -ENOMEM;
 	}
 	snd_info_minor_register();
+#ifdef CONFIG_SND_GENERIC_DRIVER
+	driver_register(&snd_generic_driver);
+#endif
 	for (controlnum = 0; controlnum < cards_limit; controlnum++)
 		devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
 #ifndef MODULE
@@ -369,6 +376,9 @@
 	for (controlnum = 0; controlnum < cards_limit; controlnum++)
 		devfs_remove("snd/controlC%d", controlnum);
 
+#ifdef CONFIG_SND_GENERIC_DRIVER
+	driver_unregister(&snd_generic_driver);
+#endif
 	snd_info_minor_unregister();
 	snd_info_done();
 	snd_memory_done();
@@ -416,10 +426,13 @@
 EXPORT_SYMBOL(snd_component_add);
 EXPORT_SYMBOL(snd_card_file_add);
 EXPORT_SYMBOL(snd_card_file_remove);
+#ifdef CONFIG_SND_GENERIC_DRIVER
+EXPORT_SYMBOL(snd_card_set_generic_dev);
+#endif
 #ifdef CONFIG_PM
 EXPORT_SYMBOL(snd_power_wait);
 EXPORT_SYMBOL(snd_card_set_pm_callback);
-#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+#ifdef CONFIG_SND_GENERIC_DRIVER
 EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
 #endif
 #ifdef CONFIG_PCI
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 4104f6e..22b1046 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -98,7 +98,7 @@
 static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer)
 {
 	snd_timer_instance_t *timeri;
-	timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
+	timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
 	if (timeri == NULL)
 		return NULL;
 	timeri->owner = kstrdup(owner, GFP_KERNEL);
@@ -764,7 +764,7 @@
 	snd_assert(tid != NULL, return -EINVAL);
 	snd_assert(rtimer != NULL, return -EINVAL);
 	*rtimer = NULL;
-	timer = kcalloc(1, sizeof(*timer), GFP_KERNEL);
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
 	if (timer == NULL)
 		return -ENOMEM;
 	timer->tmr_class = tid->dev_class;
@@ -1017,7 +1017,7 @@
 		return err;
 	strcpy(timer->name, "system timer");
 	timer->hw = snd_timer_system;
-	priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL) {
 		snd_timer_free(timer);
 		return -ENOMEM;
@@ -1202,7 +1202,7 @@
 {
 	snd_timer_user_t *tu;
 	
-	tu = kcalloc(1, sizeof(*tu), GFP_KERNEL);
+	tu = kzalloc(sizeof(*tu), GFP_KERNEL);
 	if (tu == NULL)
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
@@ -1513,7 +1513,7 @@
 	t = tu->timeri->timer;
 	snd_assert(t != NULL, return -ENXIO);
 
-	info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (! info)
 		return -ENOMEM;
 	info->card = t->card ? t->card->number : -1;
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 3b2bee1..efcb4eb 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -29,6 +29,7 @@
 	tristate "Dummy (/dev/null) soundcard"
 	depends on SND
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include the dummy driver.  This driver does
 	  nothing, but emulates various mixer controls and PCM devices.
@@ -44,6 +45,7 @@
 	depends on SND_SEQUENCER
 	select SND_TIMER
 	select SND_RAWMIDI
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include the virtual MIDI driver.  This driver
 	  allows to connect applications using raw MIDI devices to
@@ -59,6 +61,7 @@
 	depends on SND
 	select SND_TIMER
 	select SND_RAWMIDI
+	select SND_GENERIC_DRIVER
 	help
 	  To use a MOTU MidiTimePiece AV multiport MIDI adapter
 	  connected to the parallel port, say Y here and make sure that
@@ -72,6 +75,7 @@
 	depends on SND
 	select SND_TIMER
 	select SND_RAWMIDI
+	select SND_GENERIC_DRIVER
 	help
 	  To include support for MIDI serial port interfaces, say Y here
 	  and read <file:Documentation/sound/alsa/serial-u16550.txt>.
@@ -88,6 +92,7 @@
 	tristate "Generic MPU-401 UART driver"
 	depends on SND
 	select SND_MPU401_UART
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for MIDI ports compatible with
 	  the Roland MPU-401 interface in UART mode.
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a61640c..64ef7f6 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -337,7 +337,7 @@
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+	dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
 	init_timer(&dpcm->timer);
@@ -368,7 +368,7 @@
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
+	dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
 	init_timer(&dpcm->timer);
@@ -600,6 +600,10 @@
 	strcpy(card->driver, "Dummy");
 	strcpy(card->shortname, "Dummy");
 	sprintf(card->longname, "Dummy %i", dev + 1);
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto __nodev;
+
 	if ((err = snd_card_register(card)) == 0) {
 		snd_dummy_cards[dev] = card;
 		return 0;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index cb36ecb..54e2ff9 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -77,20 +77,26 @@
 		strcat(card->longname, "polled");
 	}
 
-	if (snd_mpu401_uart_new(card, 0,
-				MPU401_HW_MPU401,
-				port[dev], 0,
-				irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
+	if ((err = snd_mpu401_uart_new(card, 0,
+				       MPU401_HW_MPU401,
+				       port[dev], 0,
+				       irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL)) < 0) {
 		printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
-		snd_card_free(card);
-		return -ENODEV;
+		goto _err;
 	}
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	*rcard = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __devinit snd_mpu401_probe(int dev)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 0f83c52..fe3f921 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -463,7 +463,7 @@
 		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
 		return err;
-	mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
+	mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
 	if (mpu == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 1280a57..3a25c89 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -688,7 +688,7 @@
 
 static mtpav_t *new_mtpav(void)
 {
-	mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
+	mtpav_t *ncrd = kzalloc(sizeof(*ncrd), GFP_KERNEL);
 	if (ncrd != NULL) {
 		spin_lock_init(&ncrd->spinlock);
 
@@ -757,6 +757,9 @@
 	if (err < 0)
 		goto __error;
 
+	if ((err = snd_card_set_generic_dev(mtp_card->card)) < 0)
+		goto __error;
+
 	err = snd_card_register(mtp_card->card);	// don't snd_card_register until AFTER all cards reources done!
 
 	//printk("snd_card_register returned %d\n", err);
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index c313e52..1f84d78 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -354,7 +354,7 @@
 	int err;
 
 	*ropl3 = NULL;
-	opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
+	opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
 	if (opl3 == NULL)
 		return -ENOMEM;
 
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 33da334..21a2b40 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -241,7 +241,7 @@
 		}
 
 		size = sizeof(*put) + sizeof(fm_xinstrument_t);
-		put = kcalloc(1, size, GFP_KERNEL);
+		put = kzalloc(size, GFP_KERNEL);
 		if (put == NULL)
 			return -ENOMEM;
 		/* build header */
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 8261464..380c2c7 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -204,7 +204,7 @@
 	if (ropl4)
 		*ropl4 = NULL;
 
-	opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
+	opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL);
 	if (!opl4)
 		return -ENOMEM;
 
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 986df35..416172e 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -779,7 +779,7 @@
 	int err;
 
 
-	if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
+	if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	uart->adaptor = adaptor;
 	uart->card = card;
@@ -928,15 +928,11 @@
 					base[dev],
 					adaptor[dev],
 					droponfull[dev],
-					&uart)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+					&uart)) < 0)
+		goto _err;
 
-	if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0)
+		goto _err;
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
 		card->shortname,
@@ -949,12 +945,18 @@
 		adaptor_names[uart->adaptor],
 		uart->drop_on_full);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_serial_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init alsa_card_serial_init(void)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 5937711..af12185 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -116,6 +116,10 @@
 	strcpy(card->driver, "VirMIDI");
 	strcpy(card->shortname, "VirMIDI");
 	sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto __nodev;
+
 	if ((err = snd_card_register(card)) == 0) {
 		snd_virmidi_cards[dev] = card;
 		return 0;
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index c6fa5af..4697b1d 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -782,7 +782,7 @@
 
 	snd_assert(card && hw && ops, return NULL);
 
-	chip = kcalloc(1, sizeof(*chip) + extra_size, GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "vx_core: no memory\n");
 		return NULL;
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index d4becf4..c2312d9 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -473,7 +473,7 @@
 		return err;
 
 	/* initialize the pipe record */
-	pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
+	pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
 	if (! pipe) {
 		/* release the pipe */
 		vx_init_rmh(&rmh, CMD_FREE_PIPE);
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index a3fda85..a21f7d5 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -200,7 +200,7 @@
 
 	if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
 		return err;
-	chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 	      	snd_i2c_device_free(device);
 		return -ENOMEM;
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index e8fa7e1..e4e505b 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -81,7 +81,7 @@
 	};
 
 	*ri2c = NULL;
-	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
 	init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@
 
 	*rdevice = NULL;
 	snd_assert(bus != NULL, return -EINVAL);
-	device = kcalloc(1, sizeof(*device), GFP_KERNEL);
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
 	if (device == NULL)
 		return -ENOMEM;
 	device->addr = addr;
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index e13122f..103a7dc 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -17,7 +17,7 @@
  * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.15 2005/01/03 12:05:20 tiwai Exp $ */
+/* $Id: uda1341.c,v 1.16 2005/09/09 13:22:34 tiwai Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -670,7 +670,7 @@
 
 	snd_assert(card != NULL, return -EINVAL);
 
-	uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
+	uda1341 = kzalloc(sizeof(*uda1341), GFP_KERNEL);
 	if (uda1341 == NULL)
 		return -ENOMEM;
          
@@ -707,7 +707,7 @@
 {
 	struct uda1341 *uda;
 
-	uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
+	uda = kzalloc(sizeof(*uda), 0, GFP_KERNEL);
 	if (!uda)
 		return -ENOMEM;
 
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 5adde30..af5eadc 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -92,7 +92,7 @@
 		.dev_free =     snd_ak4114_dev_free,
 	};
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->lock);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 0419c43..d51b51d 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -83,7 +83,7 @@
 		.dev_free =     snd_ak4117_dev_free,
 	};
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->lock);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 2da8d7f..fd65da6 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -281,7 +281,7 @@
 	u8 default_treble, default_bass;
 	unsigned char bytes[7];
 
-	tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
+	tea = kzalloc(sizeof(*tea), GFP_KERNEL);
 	if (tea == NULL)
 		return -ENOMEM;
 	if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 5c39483..5d6c300 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -6,12 +6,12 @@
 config SND_AD1848_LIB
         tristate
         select SND_PCM
-	select SND_GENERIC_PM
+	select SND_GENERIC_DRIVER
 
 config SND_CS4231_LIB
         tristate
         select SND_PCM
-	select SND_GENERIC_PM
+	select SND_GENERIC_DRIVER
 
 config SND_AD1816A
 	tristate "Analog Devices SoundPort AD1816A"
@@ -97,6 +97,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for ESS AudioDrive ES688 or
 	  ES1688 chips.
@@ -110,7 +111,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
-	select SND_GENERIC_PM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for ESS AudioDrive ES18xx chips.
 
@@ -126,6 +127,7 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	select SND_GUS_SYNTH
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Gravis UltraSound Classic
 	  soundcards.
@@ -140,6 +142,7 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	select SND_GUS_SYNTH
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Gravis UltraSound Extreme
 	  soundcards.
@@ -153,6 +156,7 @@
 	select SND_RAWMIDI
 	select SND_CS4231_LIB
 	select SND_GUS_SYNTH
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Gravis UltraSound MAX
 	  soundcards.
@@ -166,7 +170,7 @@
 	select SND_RAWMIDI
 	select SND_CS4231_LIB
 	select SND_GUS_SYNTH
-	select ISAPNP
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for AMD InterWave based
 	  soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -181,7 +185,7 @@
 	select SND_RAWMIDI
 	select SND_CS4231_LIB
 	select SND_GUS_SYNTH
-	select ISAPNP
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for AMD InterWave based
 	  soundcards with a TEA6330T bass and treble regulator
@@ -224,6 +228,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for soundcards based on Opti
 	  82C93x chips.
@@ -237,6 +242,7 @@
 	select SND_OPL3_LIB
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Creative Sound Blaster 1.0/
 	  2.0/Pro (8-bit) or 100% compatible soundcards.
@@ -250,6 +256,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Sound Blaster 16 soundcards
 	  (including the Plug and Play version).
@@ -263,6 +270,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for Sound Blaster AWE soundcards
 	  (including the Plug and Play version).
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index ae86036..27a9dcf 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -591,7 +591,7 @@
 
 	*rchip = NULL;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 8c39934..3ebcc48 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -91,35 +91,36 @@
 				     irq[dev],
 				     dma1[dev],
 				     thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
-				     &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     &chip)) < 0)
+		goto _err;
 
-	if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_ad1848_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0)
+		goto _err;
+
+	if ((err = snd_ad1848_mixer(chip)) < 0)
+		goto _err;
+
 	strcpy(card->driver, "AD1848");
 	strcpy(card->shortname, pcm->name);
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
 		pcm->name, chip->port, irq[dev], dma1[dev]);
 
-	if (thinkpad[dev]) {
+	if (thinkpad[dev])
 		strcat(card->longname, " [Thinkpad]");
-	}
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_ad1848_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init alsa_card_ad1848_init(void)
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index bc642dc..303861c 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -890,7 +890,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 1fce8b9..5252206 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -438,33 +438,37 @@
 /*
  */
 
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev)		isapnp[dev]
+#else
+#define is_isapnp_selected(dev)		0
+#endif
+
+#define PFX	"cmi8330: "
+
 static int __devinit snd_cmi8330_probe(int dev,
 				       struct pnp_card_link *pcard,
 				       const struct pnp_card_device_id *pid)
 {
 	snd_card_t *card;
 	struct snd_cmi8330 *acard;
-	unsigned long flags;
 	int i, err;
 
-#ifdef CONFIG_PNP
-	if (!isapnp[dev]) {
-#endif
+	if (! is_isapnp_selected(dev)) {
 		if (wssport[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify wssport\n");
+			snd_printk(KERN_ERR PFX "specify wssport\n");
 			return -EINVAL;
 		}
 		if (sbport[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify sbport\n");
+			snd_printk(KERN_ERR PFX "specify sbport\n");
 			return -EINVAL;
 		}
-#ifdef CONFIG_PNP
 	}
-#endif
+
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
 			    sizeof(struct snd_cmi8330));
 	if (card == NULL) {
-		snd_printk("could not get a new card\n");
+		snd_printk(KERN_ERR PFX "could not get a new card\n");
 		return -ENOMEM;
 	}
 	acard = (struct snd_cmi8330 *)card->private_data;
@@ -473,9 +477,8 @@
 #ifdef CONFIG_PNP
 	if (isapnp[dev]) {
 		if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) {
-			snd_printk("PnP detection failed\n");
-			snd_card_free(card);
-			return err;
+			snd_printk(KERN_ERR PFX "PnP detection failed\n");
+			goto _err;
 		}
 		snd_card_set_dev(card, &pcard->card->dev);
 	}
@@ -487,14 +490,13 @@
 				     wssdma[dev],
 				     AD1848_HW_DETECT,
 				     &acard->wss)) < 0) {
-		snd_printk("(AD1848) device busy??\n");
-		snd_card_free(card);
-		return err;
+		snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
+		goto _err;
 	}
 	if (acard->wss->hardware != AD1848_HW_CMI8330) {
-		snd_printk("(AD1848) not found during probe\n");
-		snd_card_free(card);
-		return -ENODEV;
+		snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
+		err = -ENODEV;
+		goto _err;
 	}
 
 	if ((err = snd_sbdsp_create(card, sbport[dev],
@@ -503,32 +505,26 @@
 				    sbdma8[dev],
 				    sbdma16[dev],
 				    SB_HW_AUTO, &acard->sb)) < 0) {
-		snd_printk("(SB16) device busy??\n");
-		snd_card_free(card);
-		return err;
+		snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
+		goto _err;
 	}
 	if (acard->sb->hardware != SB_HW_16) {
-		snd_printk("(SB16) not found during probe\n");
-		snd_card_free(card);
-		return -ENODEV;
+		snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
+		goto _err;
 	}
 
-	spin_lock_irqsave(&acard->wss->reg_lock, flags);
 	snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
 	for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
 		snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
-	spin_unlock_irqrestore(&acard->wss->reg_lock, flags);
 
 	if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
-		snd_printk("failed to create mixers\n");
-		snd_card_free(card);
-		return err;
+		snd_printk(KERN_ERR PFX "failed to create mixers\n");
+		goto _err;
 	}
 
 	if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
-		snd_printk("failed to create pcms\n");
-		snd_card_free(card);
-		return err;
+		snd_printk(KERN_ERR PFX "failed to create pcms\n");
+		goto _err;
 	}
 
 	strcpy(card->driver, "CMI8330/C3D");
@@ -539,16 +535,21 @@
 		wssirq[dev],
 		wssdma[dev]);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 
 	if (pcard)
 		pnp_set_card_drvdata(pcard, card);
 	else
 		snd_cmi8330_legacy[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 #ifdef CONFIG_PNP
@@ -594,10 +595,8 @@
 	for (dev = 0; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		if (snd_cmi8330_probe(dev, NULL, NULL) >= 0)
 			cards++;
 	}
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 7640837..9be5416 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -76,15 +76,15 @@
 	int err;
 
 	if (port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk("specify port\n");
+		snd_printk(KERN_ERR "specify port\n");
 		return -EINVAL;
 	}
 	if (irq[dev] == SNDRV_AUTO_IRQ) {
-		snd_printk("specify irq\n");
+		snd_printk(KERN_ERR "specify irq\n");
 		return -EINVAL;
 	}
 	if (dma1[dev] == SNDRV_AUTO_DMA) {
-		snd_printk("specify dma1\n");
+		snd_printk(KERN_ERR "specify dma1\n");
 		return -EINVAL;
 	}
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -96,15 +96,11 @@
 				     dma1[dev],
 				     dma2[dev],
 				     CS4231_HW_DETECT,
-				     0, &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     0, &chip)) < 0)
+		goto _err;
 
-	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+		goto _err;
 
 	strcpy(card->driver, "CS4231");
 	strcpy(card->shortname, pcm->name);
@@ -113,14 +109,10 @@
 	if (dma2[dev] >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
 
-	if ((err = snd_cs4231_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_cs4231_mixer(chip)) < 0)
+		goto _err;
+	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+		goto _err;
 
 	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
 		if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
@@ -130,14 +122,20 @@
 					mpu_irq[dev],
 					mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
 					NULL) < 0)
-			printk(KERN_ERR "cs4231: MPU401 not detected\n");
+			printk(KERN_WARNING "cs4231: MPU401 not detected\n");
 	}
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 	snd_cs4231_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init alsa_card_cs4231_init(void)
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 3199941..3231825 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -1480,7 +1480,7 @@
 	cs4231_t *chip;
 
 	*rchip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->hardware = hardware;
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 39f4eff..d28315d 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -387,6 +387,12 @@
 	}
 }
 
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev)		isapnp[dev]
+#else
+#define is_isapnp_selected(dev)		0
+#endif
+
 static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
 					   const struct pnp_card_device_id *pid)
 {
@@ -397,20 +403,16 @@
 	opl3_t *opl3;
 	int err;
 
-#ifdef CONFIG_PNP
-	if (!isapnp[dev]) {
-#endif
+	if (! is_isapnp_selected(dev)) {
 		if (port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify port\n");
+			snd_printk(KERN_ERR "specify port\n");
 			return -EINVAL;
 		}
 		if (cport[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify cport\n");
+			snd_printk(KERN_ERR "specify cport\n");
 			return -EINVAL;
 		}
-#ifdef CONFIG_PNP
 	}
-#endif
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
 			    sizeof(struct snd_card_cs4236));
 	if (card == NULL)
@@ -421,8 +423,7 @@
 	if (isapnp[dev]) {
 		if ((err = snd_card_cs4236_pnp(dev, acard, pcard, pid))<0) {
 			printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n");
-			snd_card_free(card);
-			return -ENXIO;
+			goto _err;
 		}
 		snd_card_set_dev(card, &pcard->card->dev);
 	}
@@ -430,8 +431,8 @@
 	if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT)
 		if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) {
 			printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]);
-			snd_card_free(card);
-			return -ENOMEM;
+			err = -EBUSY;
+			goto _err;
 		}
 
 #ifdef CS4232
@@ -443,18 +444,14 @@
 				     dma2[dev],
 				     CS4231_HW_DETECT,
 				     0,
-				     &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     &chip)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_mixer(chip)) < 0)
+		goto _err;
 
 #else /* CS4236 */
 	if ((err = snd_cs4236_create(card,
@@ -465,18 +462,14 @@
 				     dma2[dev],
 				     CS4231_HW_DETECT,
 				     0,
-				     &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4236_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     &chip)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4236_mixer(chip)) < 0)
+		goto _err;
 #endif
 	strcpy(card->driver, pcm->name);
 	strcpy(card->shortname, pcm->name);
@@ -488,21 +481,17 @@
 	if (dma2[dev] >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
 
-	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
+		goto _err;
 
 	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
 		if (snd_opl3_create(card,
 				    fm_port[dev], fm_port[dev] + 2,
 				    OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
-			printk(KERN_ERR IDENT ": OPL3 not detected\n");
+			printk(KERN_WARNING IDENT ": OPL3 not detected\n");
 		} else {
-			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
-				snd_card_free(card);
-				return err;
-			}
+			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+				goto _err;
 		}
 	}
 
@@ -513,17 +502,23 @@
 					mpu_port[dev], 0,
 					mpu_irq[dev],
 					mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0)
-			printk(KERN_ERR IDENT ": MPU401 not detected\n");
+			printk(KERN_WARNING IDENT ": MPU401 not detected\n");
 	}
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 	if (pcard)
 		pnp_set_card_drvdata(pcard, card);
 	else
 		snd_cs4236_legacy[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 #ifdef CONFIG_PNP
@@ -569,10 +564,8 @@
 	for (dev = 0; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		if (snd_card_cs423x_probe(dev, NULL, NULL) >= 0)
 			cards++;
 	}
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index c5eaec0..26a7d33 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -70,6 +70,7 @@
 
 static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"es1688: "
 
 static int __init snd_audiodrive_probe(int dev)
 {
@@ -89,47 +90,41 @@
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xmpu_irq = mpu_irq[dev];
 	xdma = dma8[dev];
 	if (xdma == SNDRV_AUTO_DMA) {
 		if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 
 	if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
 				     xirq, xmpu_irq, xdma,
-				     ES1688_HW_AUTO, &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_es1688_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     ES1688_HW_AUTO, &chip)) < 0)
+		goto _err;
+
+	if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0)
+		goto _err;
+
+	if ((err = snd_es1688_mixer(chip)) < 0)
+		goto _err;
 
 	strcpy(card->driver, "ES1688");
 	strcpy(card->shortname, pcm->name);
 	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma);
 
 	if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
-		printk(KERN_ERR "es1688: opl3 not detected at 0x%lx\n", chip->port);
+		printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port);
 	} else {
-		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+			goto _err;
 	}
 
 	if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) {
@@ -137,18 +132,22 @@
 					       chip->mpu_port, 0,
 					       xmpu_irq,
 					       SA_INTERRUPT,
-					       NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+					       NULL)) < 0)
+			goto _err;
 	}
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_audiodrive_cards[dev] = card;
 	return 0;
 
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 17f68d0..aac8987 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -649,7 +649,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1d832b2..d0ea19f 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1686,7 +1686,7 @@
 	int err;
 
 	*rchip = NULL;
-        chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1988,6 +1988,12 @@
 }
 #endif /* CONFIG_PNP */
 
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev)		isapnp[dev]
+#else
+#define is_isapnp_selected(dev)		0
+#endif
+
 static int __devinit snd_audiodrive_probe(int dev, struct pnp_card_link *pcard,
 					  const struct pnp_card_device_id *pid)
 {
@@ -1996,7 +2002,6 @@
 	int xirq, xdma1, xdma2;
 	snd_card_t *card;
 	struct snd_audiodrive *acard;
-	snd_rawmidi_t *rmidi = NULL;
 	es18xx_t *chip;
 	opl3_t *opl3;
 	int err;
@@ -2019,25 +2024,25 @@
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma1 = dma1[dev];
         if (xdma1 == SNDRV_AUTO_DMA) {
                 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-                        snd_card_free(card);
-                        snd_printk("unable to find a free DMA1\n");
-                        return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+			err = -EBUSY;
+			goto _err;
                 }
         }
 	xdma2 = dma2[dev];
         if (xdma2 == SNDRV_AUTO_DMA) {
                 if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-                        snd_card_free(card);
-                        snd_printk("unable to find a free DMA2\n");
-                        return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+			err = -EBUSY;
+			goto _err;
                 }
         }
 
@@ -2046,10 +2051,8 @@
 					 mpu_port[dev],
 					 fm_port[dev],
 					 xirq, xdma1, xdma2,
-					 &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+					 &chip)) < 0)
+		goto _err;
 
 	sprintf(card->driver, "ES%x", chip->version);
 	sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
@@ -2064,23 +2067,18 @@
 			chip->port,
 			xirq, xdma1);
 
-	if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_es18xx_mixer(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+		goto _err;
+
+	if ((err = snd_es18xx_mixer(chip)) < 0)
+		goto _err;
 
 	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
 		if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
-			snd_printk(KERN_ERR PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
+			snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
 		} else {
-			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
-				snd_card_free(card);
-				return err;
-			}
+			if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+				goto _err;
 		}
 	}
 
@@ -2088,25 +2086,28 @@
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
 					       chip->mpu_port, 0,
 					       xirq, 0,
-					       &rmidi)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
-		chip->rmidi = rmidi;
+					       &chip->rmidi)) < 0)
+			goto _err;
 	}
 
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
 	/* Power Management */
 	snd_card_set_isa_pm_callback(card, snd_es18xx_suspend, snd_es18xx_resume, chip);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	if (pcard)
 		pnp_set_card_drvdata(pcard, card);
 	else
 		snd_audiodrive_legacy[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
@@ -2117,10 +2118,8 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		port[dev] = xport;
 		res = snd_audiodrive_probe(dev, NULL, NULL);
 		if (res < 0)
@@ -2177,10 +2176,8 @@
 	for (dev = 0; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		if (snd_audiodrive_probe(dev, NULL, NULL) >= 0)
 			cards++;
 	}
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index a636d9c..8f2872f 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -157,7 +157,7 @@
 	};
 
 	*rgus = NULL;
-	gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
+	gus = kzalloc(sizeof(*gus), GFP_KERNEL);
 	if (gus == NULL)
 		return -ENOMEM;
 	gus->gf1.irq = -1;
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 886763f..7f96ac2 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -98,7 +98,7 @@
 
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
-			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+			priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->gus = gus;
@@ -115,7 +115,7 @@
 	}
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.rom_present & (1 << idx)) {
-			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
+			priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->rom = 1;
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index b75066a..beb0136 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -666,7 +666,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
+	pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL);
 	if (pcmp == NULL)
 		return -ENOMEM;
 	pcmp->gus = gus;
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index a99fa50..39cef38 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -72,40 +72,24 @@
 
 static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"gusclassic: "
 
 static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
 {
-	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
+	unsigned char d;
 
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
-			snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+		snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
+	}
 	udelay(160);
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);	/* release reset */
 	udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
-			snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+		snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
-
+	}
 	return 0;
 }
 
@@ -137,25 +121,25 @@
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma1 = dma1[dev];
 	if (xdma1 == SNDRV_AUTO_DMA) {
 		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA1\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma2 = dma2[dev];
 	if (xdma2 == SNDRV_AUTO_DMA) {
 		if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA2\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 
@@ -164,47 +148,48 @@
 				  port[dev],
 				  xirq, xdma1, xdma2,
 			          0, channels[dev], pcm_channels[dev],
-			          0, &gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_gusclassic_detect(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+			          0, &gus)) < 0)
+		goto _err;
+
+	if ((err = snd_gusclassic_detect(gus)) < 0)
+		goto _err;
+
 	snd_gusclassic_init(dev, gus);
-	if ((err = snd_gus_initialize(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_gus_initialize(gus)) < 0)
+		goto _err;
+
 	if (gus->max_flag || gus->ess_flag) {
-		snd_printdd("GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
-		snd_card_free(card);
-		return -ENODEV;
+		snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
+		err = -ENODEV;
+		goto _err;
 	}
-	if ((err = snd_gf1_new_mixer(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_gf1_new_mixer(gus)) < 0)
+		goto _err;
+
+	if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0)
+		goto _err;
+
 	if (!gus->ace_flag) {
-		if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+			goto _err;
 	}
 	sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
 	if (dma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_gusclassic_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index bc6fecb..d2e7cb1 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -87,6 +87,7 @@
 
 static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"gusextreme: "
 
 static int __init snd_gusextreme_detect(int dev,
 					snd_card_t * card,
@@ -94,6 +95,7 @@
 					es1688_t *es1688)
 {
 	unsigned long flags;
+	unsigned char d;
 
 	/*
 	 * This is main stuff - enable access to GF1 chip...
@@ -123,36 +125,17 @@
 	udelay(100);
 
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
-			snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
-			return -EIO;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+		snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
 		return -EIO;
-#endif
+	}
 	udelay(160);
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);	/* release reset */
 	udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
-			snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
-			return -EIO;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+		snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 		return -EIO;
-#endif
-
+	}
 	return 0;
 }
 
@@ -205,7 +188,7 @@
 	xgf1_irq = gf1_irq[dev];
 	if (xgf1_irq == SNDRV_AUTO_IRQ) {
 		if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
-			snd_printk("unable to find a free IRQ for GF1\n");
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n");
 			err = -EBUSY;
 			goto out;
 		}
@@ -213,7 +196,7 @@
 	xess_irq = irq[dev];
 	if (xess_irq == SNDRV_AUTO_IRQ) {
 		if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
-			snd_printk("unable to find a free IRQ for ES1688\n");
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n");
 			err = -EBUSY;
 			goto out;
 		}
@@ -226,7 +209,7 @@
 	xgf1_dma = dma1[dev];
 	if (xgf1_dma == SNDRV_AUTO_DMA) {
 		if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
-			snd_printk("unable to find a free DMA for GF1\n");
+			snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n");
 			err = -EBUSY;
 			goto out;
 		}
@@ -234,7 +217,7 @@
 	xess_dma = dma8[dev];
 	if (xess_dma == SNDRV_AUTO_DMA) {
 		if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
-			snd_printk("unable to find a free DMA for ES1688\n");
+			snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n");
 			err = -EBUSY;
 			goto out;
 		}
@@ -264,7 +247,7 @@
 		goto out;
 
 	if (!gus->ess_flag) {
-		snd_printdd("GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
+		snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
 		err = -ENODEV;
 		goto out;
 	}
@@ -287,7 +270,7 @@
 
 	if (snd_opl3_create(card, es1688->port, es1688->port + 2,
 			    OPL3_HW_OPL3, 0, &opl3) < 0) {
-		printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
+		printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
 	} else {
 		if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0)
 			goto out;
@@ -303,6 +286,10 @@
 
 	sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i",
 		es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma);
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto out;
+
 	if ((err = snd_card_register(card)) < 0)
 		goto out;
 
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 400ff34..0bb44b5 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -82,39 +82,25 @@
 
 static snd_card_t *snd_gusmax_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"gusmax: "
 
 static int __init snd_gusmax_detect(snd_gus_card_t * gus)
 {
-	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
+	unsigned char d;
 
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
-			snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+		snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
+	}
 	udelay(160);
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);	/* release reset */
 	udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		unsigned char d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
-			snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+		snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
+	}
+
 	return 0;
 }
 
@@ -239,25 +225,25 @@
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma1 = dma1[dev];
 	if (xdma1 == SNDRV_AUTO_DMA) {
 		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA1\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma2 = dma2[dev];
 	if (xdma2 == SNDRV_AUTO_DMA) {
 		if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA2\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 
@@ -266,31 +252,28 @@
 				  -xirq, xdma1, xdma2,
 				  0, channels[dev],
 				  pcm_channels[dev],
-				  0, &gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_gusmax_detect(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				  0, &gus)) < 0)
+		goto _err;
+
+	if ((err = snd_gusmax_detect(gus)) < 0)
+		goto _err;
+
 	maxcard->gus_status_reg = gus->gf1.reg_irqstat;
 	maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
 	snd_gusmax_init(dev, card, gus);
-	if ((err = snd_gus_initialize(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_gus_initialize(gus)) < 0)
+		goto _err;
+
 	if (!gus->max_flag) {
-		printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
-		snd_card_free(card);
-		return -ENODEV;
+		snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
+		err = -ENODEV;
+		goto _err;
 	}
 
 	if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) {
-		snd_card_free(card);
-		printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", xirq);
-		return -EBUSY;
+		snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+		err = -EBUSY;
+		goto _err;
 	}
 	maxcard->irq = xirq;
 	
@@ -301,50 +284,46 @@
 				     CS4231_HWSHARE_IRQ |
 				     CS4231_HWSHARE_DMA1 |
 				     CS4231_HWSHARE_DMA2,
-				     &cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_mixer(cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if (pcm_channels[dev] > 0) {
-		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
-	}
-	if ((err = snd_gusmax_mixer(cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     &cs4231)) < 0)
+		goto _err;
 
-	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
+	if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_mixer(cs4231)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+		goto _err;
+
+	if (pcm_channels[dev] > 0) {
+		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+			goto _err;
 	}
+	if ((err = snd_gusmax_mixer(cs4231)) < 0)
+		goto _err;
+
+	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+		goto _err;
 
 	sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
 	if (xdma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 		
 	maxcard->gus = gus;
 	maxcard->cs4231 = cs4231;
 	snd_gusmax_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init snd_gusmax_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 46e867d..358cba9 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -73,6 +73,12 @@
 static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
 
+#ifdef SNDRV_STB
+#define PFX "interwave-stb: "
+#else
+#define PFX "interwave: "
+#endif
+
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
 module_param_array(id, charp, NULL, 0444);
@@ -249,38 +255,20 @@
 {
 	unsigned long flags;
 	unsigned char rev1, rev2;
+	int d;
 
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);	/* reset GF1 */
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		int d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
-			snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) {
+		snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
+	}
 	udelay(160);
 	snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);	/* release reset */
 	udelay(160);
-#ifdef CONFIG_SND_DEBUG_DETECT
-	{
-		int d;
-
-		if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
-			snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
-			return -ENODEV;
-		}
-	}
-#else
-	if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1)
+	if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) {
+		snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 		return -ENODEV;
-#endif
-
+	}
 	spin_lock_irqsave(&gus->reg_lock, flags);
 	rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER);
 	snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1);
@@ -686,35 +674,33 @@
 	card->private_free = snd_interwave_free;
 #ifdef CONFIG_PNP
 	if (isapnp[dev]) {
-		if (snd_interwave_pnp(dev, iwcard, pcard, pid)) {
-			snd_card_free(card);
-			return -ENODEV;
-		}
+		if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0)
+			goto _err;
 		snd_card_set_dev(card, &pcard->card->dev);
 	}
 #endif
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma1 = dma1[dev];
 	if (xdma1 == SNDRV_AUTO_DMA) {
 		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA1\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma2 = dma2[dev];
 	if (xdma2 == SNDRV_AUTO_DMA) {
 		if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA2\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 
@@ -722,32 +708,28 @@
 				  port[dev],
 				  -xirq, xdma1, xdma2,
 				  0, 32,
-				  pcm_channels[dev], effect[dev], &gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				  pcm_channels[dev], effect[dev], &gus)) < 0)
+		goto _err;
+
 	if ((err = snd_interwave_detect(iwcard, gus, dev
 #ifdef SNDRV_STB
             , &i2c_bus
 #endif
-	    )) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	    )) < 0)
+		goto _err;
+
 	iwcard->gus_status_reg = gus->gf1.reg_irqstat;
 	iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
 
 	snd_interwave_init(dev, gus);
 	snd_interwave_detect_memory(gus);
-	if ((err = snd_gus_initialize(gus)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_gus_initialize(gus)) < 0)
+		goto _err;
 
 	if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
-		snd_card_free(card);
-		snd_printk("unable to grab IRQ %d\n", xirq);
-		return -EBUSY;
+		snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
+		err = -EBUSY;
+		goto _err;
 	}
 	iwcard->irq = xirq;
 
@@ -758,34 +740,28 @@
 				     CS4231_HWSHARE_IRQ |
 				     CS4231_HWSHARE_DMA1 |
 				     CS4231_HWSHARE_DMA2,
-				     &cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     &cs4231)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)
+		goto _err;
+
 	sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
 	strcat(pcm->name, " (codec)");
-	if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_cs4231_mixer(cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)
+		goto _err;
+
+	if ((err = snd_cs4231_mixer(cs4231)) < 0)
+		goto _err;
+
 	if (pcm_channels[dev] > 0) {
-		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+			goto _err;
 	}
-	if ((err = snd_interwave_mixer(cs4231)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_interwave_mixer(cs4231)) < 0)
+		goto _err;
+
 #ifdef SNDRV_STB
 	{
 		snd_ctl_elem_id_t id1, id2;
@@ -795,28 +771,20 @@
 		strcpy(id1.name, "Master Playback Switch");
 		strcpy(id2.name, id1.name);
 		id2.index = 1;
-		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+			goto _err;
 		strcpy(id1.name, "Master Playback Volume");
 		strcpy(id2.name, id1.name);
-		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
-		if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+			goto _err;
+		if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0)
+			goto _err;
 	}
 #endif
 
 	gus->uart_enable = midi[dev];
-	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+		goto _err;
 
 #ifndef SNDRV_STB
 	str = "AMD InterWave";
@@ -835,10 +803,11 @@
 	if (xdma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 	
 	iwcard->cs4231 = cs4231;
 	iwcard->gus = gus;
@@ -847,6 +816,10 @@
 	else
 		snd_interwave_legacy[dev++] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __devinit snd_interwave_probe_legacy_port(unsigned long xport)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 75bd6ec..e2d2bab 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -143,6 +143,8 @@
 
 static snd_card_t *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"opl3sa2: "
+
 #ifdef CONFIG_PNP
 
 static struct pnp_device_id snd_opl3sa2_pnpbiosids[] = {
@@ -231,7 +233,7 @@
 	card = chip->card;
 	port = chip->port;
 	if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) {
-		snd_printk(KERN_ERR "opl3sa2: can't grab port 0x%lx\n", port);
+		snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port);
 		return -EBUSY;
 	}
 	// snd_printk("REG 0A = 0x%x\n", snd_opl3sa2_read(chip, 0x0a));
@@ -668,6 +670,12 @@
 	return snd_opl3sa2_free(chip);
 }
 
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev)		isapnp[dev]
+#else
+#define is_isapnp_selected(dev)		0
+#endif
+
 static int __devinit snd_opl3sa2_probe(int dev,
 				       struct pnp_dev *pdev,
 				       struct pnp_card_link *pcard,
@@ -683,34 +691,31 @@
 	};
 	int err;
 
-#ifdef CONFIG_PNP
-	if (!isapnp[dev]) {
-#endif
+	if (! is_isapnp_selected(dev)) {
 		if (port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify port\n");
+			snd_printk(KERN_ERR PFX "specify port\n");
 			return -EINVAL;
 		}
 		if (wss_port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify wss_port\n");
+			snd_printk(KERN_ERR PFX "specify wss_port\n");
 			return -EINVAL;
 		}
 		if (fm_port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify fm_port\n");
+			snd_printk(KERN_ERR PFX "specify fm_port\n");
 			return -EINVAL;
 		}
 		if (midi_port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk("specify midi_port\n");
+			snd_printk(KERN_ERR PFX "specify midi_port\n");
 			return -EINVAL;
 		}
-#ifdef CONFIG_PNP
 	}
-#endif
+
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
 	strcpy(card->driver, "OPL3SA2");
 	strcpy(card->shortname, "Yamaha OPL3-SA2");
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -742,7 +747,7 @@
 	if ((err = snd_opl3sa2_detect(chip)) < 0)
 		goto __error;
 	if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) {
-		snd_printk(KERN_ERR "opl3sa2: can't grab IRQ %d\n", xirq);
+		snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
 		err = -ENODEV;
 		goto __error;
 	}
@@ -795,6 +800,9 @@
 	if (dma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
 
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto __error;
+
 	if ((err = snd_card_register(card)) < 0)
 		goto __error;
 
@@ -852,8 +860,10 @@
         int res;
 
         for ( ; dev < SNDRV_CARDS; dev++) {
-                if (!enable[dev] || !isapnp[dev])
-                        continue;
+		if (!enable[dev])
+			continue;
+		if (is_isapnp_selected(dev))
+			continue;
                 res = snd_opl3sa2_probe(dev, NULL, card, id);
                 if (res < 0)
                         return res;
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 411a702..73573cb 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -1038,8 +1038,7 @@
 
 	chip->c_dma_size = size;
 	snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
-		OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO,
-		(unsigned char)~(OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO));
+		OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);
 
 	snd_dma_program(chip->dma2, runtime->dma_addr, size,
 		DMA_MODE_READ | DMA_AUTOINIT);
@@ -1274,7 +1273,7 @@
 	opti93x_t *codec;
 
 	*rcodec = NULL;
-	codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 	codec->irq = -1;
@@ -1895,8 +1894,8 @@
 	}
 }
 
-static int __devinit snd_card_opti9xx_probe(struct pnp_card_link *pcard,
-					    const struct pnp_card_device_id *pid)
+static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
+				  const struct pnp_card_device_id *pid)
 {
 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 	static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
@@ -1966,6 +1965,10 @@
 			snd_card_free(card);
 			return error;
 		}
+		if ((error = snd_card_set_generic_dev(card)) < 0) {
+			snd_card_free(card);
+			return error;
+		}
 #ifdef CONFIG_PNP
 	}
 #endif	/* CONFIG_PNP */
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 028af40..5375705 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1097,7 +1097,7 @@
 	if (seq_ports <= 0)
 		return 0;
 
-	hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
+	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
 	if (hw == NULL)
 		return -ENOMEM;
 	spin_lock_init(&hw->reg_lock);
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index db5eb8b..0209790 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -233,7 +233,7 @@
 	emu8k_pcm_t *rec;
 	snd_pcm_runtime_t *runtime = subs->runtime;
 
-	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
 	if (! rec)
 		return -ENOMEM;
 
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 60e2c53..7888783 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -351,6 +351,12 @@
 	}
 }
 
+#ifdef CONFIG_PNP
+#define is_isapnp_selected(dev)		isapnp[dev]
+#else
+#define is_isapnp_selected(dev)		0
+#endif
+
 static int __init snd_sb16_probe(int dev,
 				 struct pnp_card_link *pcard,
 				 const struct pnp_card_device_id *pid)
@@ -378,10 +384,8 @@
 	card->private_free = snd_sb16_free;
 #ifdef CONFIG_PNP
 	if (isapnp[dev]) {
-		if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid))) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid)))
+			goto _err;
 		snd_card_set_dev(card, &pcard->card->dev);
 	}
 #endif
@@ -389,41 +393,37 @@
 	xirq = irq[dev];
 	xdma8 = dma8[dev];
 	xdma16 = dma16[dev];
-#ifdef CONFIG_PNP
-	if (!isapnp[dev]) {
-#endif
-	if (xirq == SNDRV_AUTO_IRQ) {
-		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-			return -EBUSY;
+	if (! is_isapnp_selected(dev)) {
+		if (xirq == SNDRV_AUTO_IRQ) {
+			if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+				snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+				err = -EBUSY;
+				goto _err;
+			}
 		}
-	}
-	if (xdma8 == SNDRV_AUTO_DMA) {
-		if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
-			snd_card_free(card);
-			snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
-			return -EBUSY;
+		if (xdma8 == SNDRV_AUTO_DMA) {
+			if ((xdma8 = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
+				snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
+				err = -EBUSY;
+				goto _err;
+			}
 		}
-	}
-	if (xdma16 == SNDRV_AUTO_DMA) {
-		if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
-			snd_card_free(card);
-			snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
-			return -EBUSY;
+		if (xdma16 == SNDRV_AUTO_DMA) {
+			if ((xdma16 = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
+				snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
+				err = -EBUSY;
+				goto _err;
+			}
 		}
-	}
-	/* non-PnP FM port address is hardwired with base port address */
-	fm_port[dev] = port[dev];
-	/* block the 0x388 port to avoid PnP conflicts */
-	acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
+		/* non-PnP FM port address is hardwired with base port address */
+		fm_port[dev] = port[dev];
+		/* block the 0x388 port to avoid PnP conflicts */
+		acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
 #ifdef SNDRV_SBAWE_EMU8000
-	/* non-PnP AWE port address is hardwired with base port address */
-	awe_port[dev] = port[dev] + 0x400;
+		/* non-PnP AWE port address is hardwired with base port address */
+		awe_port[dev] = port[dev] + 0x400;
 #endif
-#ifdef CONFIG_PNP
 	}
-#endif
 
 	if ((err = snd_sbdsp_create(card,
 				    port[dev],
@@ -432,28 +432,20 @@
 				    xdma8,
 				    xdma16,
 				    SB_HW_AUTO,
-				    &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				    &chip)) < 0)
+		goto _err;
+
 	if (chip->hardware != SB_HW_16) {
-		snd_card_free(card);
-		snd_printdd("SB 16 chip was not detected at 0x%lx\n", port[dev]);
-		return -ENODEV;
+		snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]);
+		err = -ENODEV;
+		goto _err;
 	}
 	chip->mpu_port = mpu_port[dev];
-#ifdef CONFIG_PNP
-	if (!isapnp[dev] && (err = snd_sb16dsp_configure(chip)) < 0) {
-#else
-	if ((err = snd_sb16dsp_configure(chip)) < 0) {
-#endif
-		snd_card_free(card);
-		return -ENXIO;
-	}
-	if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return -ENXIO;
-	}
+	if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
+		goto _err;
+
+	if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0)
+		goto _err;
 
 	strcpy(card->driver,
 #ifdef SNDRV_SBAWE_EMU8000
@@ -474,10 +466,8 @@
 	if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
 					       chip->mpu_port, 0,
-					       xirq, 0, &chip->rmidi)) < 0) {
-			snd_card_free(card);
-			return -ENXIO;
-		}
+					       xirq, 0, &chip->rmidi)) < 0)
+			goto _err;
 		chip->rmidi_callback = snd_mpu401_uart_interrupt;
 	}
 
@@ -499,17 +489,13 @@
 #else
 			int seqdev = 1;
 #endif
-			if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) {
-				snd_card_free(card);
-				return -ENXIO;
-			}
+			if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0)
+				goto _err;
 		}
 	}
 
-	if ((err = snd_sbmixer_new(chip)) < 0) {
-		snd_card_free(card);
-		return -ENXIO;
-	}
+	if ((err = snd_sbmixer_new(chip)) < 0)
+		goto _err;
 
 #ifdef CONFIG_SND_SB16_CSP
 	/* CSP chip on SB16ASP/AWE32 */
@@ -525,11 +511,11 @@
 #endif
 #ifdef SNDRV_SBAWE_EMU8000
 	if (awe_port[dev] > 0) {
-		if (snd_emu8000_new(card, 1, awe_port[dev],
-				    seq_ports[dev], NULL) < 0) {
+		if ((err = snd_emu8000_new(card, 1, awe_port[dev],
+					   seq_ports[dev], NULL)) < 0) {
 			snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]);
-			snd_card_free(card);
-			return -ENXIO;
+
+			goto _err;
 		}
 	}
 #endif
@@ -541,15 +527,21 @@
 		(mic_agc[dev] ? 0x00 : 0x01));
 	spin_unlock_irqrestore(&chip->mixer_lock, flags);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	if (pcard)
 		pnp_set_card_drvdata(pcard, card);
 	else
 		snd_sb16_legacy[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init snd_sb16_probe_legacy_port(unsigned long xport)
@@ -560,10 +552,8 @@
 	for ( ; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		port[dev] = xport;
 		res = snd_sb16_probe(dev, NULL, NULL);
 		if (res < 0)
@@ -621,10 +611,8 @@
 	for (dev = 0; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
 			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[dev])
+		if (is_isapnp_selected(dev))
 			continue;
-#endif
 		if (!snd_sb16_probe(dev, NULL, NULL)) {
 			cards++;
 			continue;
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index d64790b..7192d4c 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -122,7 +122,7 @@
 	if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
 		return err;
 
-	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+	if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_device_free(chip->card, hw);
 		return -ENOMEM;
 	}
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index e2cbc42..c41ac25 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -107,54 +107,47 @@
 				    dma8[dev],
 				    -1,
 				    SB_HW_AUTO,
-				    &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				    &chip)) < 0)
+		goto _err;
+
 	if (chip->hardware >= SB_HW_16) {
-		snd_card_free(card);
 		if (chip->hardware == SB_HW_ALS100)
-			snd_printdd("ALS100 chip detected at 0x%lx, try snd-als100 module\n",
+			snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n",
 				    port[dev]);
 		else
-			snd_printdd("SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
-				    port[dev]);
-		return -ENODEV;
+			snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n",
+				   port[dev]);
+		err = -ENODEV;
+		goto _err;
 	}
 
-	if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
-	if ((err = snd_sbmixer_new(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0)
+		goto _err;
+
+	if ((err = snd_sbmixer_new(chip)) < 0)
+		goto _err;
+
 	if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) {
 		if ((err = snd_opl3_create(card, chip->port + 8, 0,
 					   OPL3_HW_AUTO, 1,
 					   &opl3)) < 0) {
-			snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx\n", chip->port + 8);
+			snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8);
 		}
 	} else {
 		if ((err = snd_opl3_create(card, chip->port, chip->port + 2,
 					   OPL3_HW_AUTO, 1,
 					   &opl3)) < 0) {
-			snd_printk(KERN_ERR "sb8: no OPL device at 0x%lx-0x%lx\n",
+			snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n",
 				   chip->port, chip->port + 2);
 		}
 	}
 	if (err >= 0) {
-		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
-			snd_card_free(card);
-			return err;
-		}
+		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
+			goto _err;
 	}
 
-	if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0)
+		goto _err;
 
 	strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
 	strcpy(card->shortname, chip->name);
@@ -162,12 +155,19 @@
 		chip->name,
 		chip->port,
 		irq[dev], dma8[dev]);
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_sb8_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport)
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 5b6bde2..f0f205a 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -221,7 +221,7 @@
 
 	snd_assert(r_chip != NULL, return -EINVAL);
 	*r_chip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 17f585b..52f2294 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -67,6 +67,8 @@
 
 static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
+#define PFX	"sgalaxy: "
+
 /*
 
  */
@@ -135,7 +137,7 @@
 	}
 
 #if 0
-	snd_printdd("sgalaxy - setting up IRQ/DMA for WSS\n");
+	snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
 #endif
 
         /* initialize IRQ for WSS codec */
@@ -160,7 +162,7 @@
 static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
 {
 #if 0
-	snd_printdd("sgalaxy - switching to WSS mode\n");
+	snd_printdd(PFX "switching to WSS mode\n");
 #endif
 
 	/* switch to WSS mode */
@@ -223,11 +225,11 @@
 	ad1848_t *chip;
 
 	if (sbport[dev] == SNDRV_AUTO_PORT) {
-		snd_printk("specify SB port\n");
+		snd_printk(KERN_ERR PFX "specify SB port\n");
 		return -EINVAL;
 	}
 	if (wssport[dev] == SNDRV_AUTO_PORT) {
-		snd_printk("specify WSS port\n");
+		snd_printk(KERN_ERR PFX "specify WSS port\n");
 		return -EINVAL;
 	}
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -237,46 +239,39 @@
 	xirq = irq[dev];
 	if (xirq == SNDRV_AUTO_IRQ) {
 		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free IRQ\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 	xdma1 = dma1[dev];
         if (xdma1 == SNDRV_AUTO_DMA) {
 		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_card_free(card);
-			snd_printk("unable to find a free DMA\n");
-			return -EBUSY;
+			snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
+			err = -EBUSY;
+			goto _err;
 		}
 	}
 
-	if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
+		goto _err;
 
 	if ((err = snd_ad1848_create(card, wssport[dev] + 4,
 				     xirq, xdma1,
-				     AD1848_HW_DETECT, &chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+				     AD1848_HW_DETECT, &chip)) < 0)
+		goto _err;
 
 	if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
-		snd_printdd("sgalaxy - error creating new ad1848 PCM device\n");
-		snd_card_free(card);
-		return err;
+		snd_printdd(PFX "error creating new ad1848 PCM device\n");
+		goto _err;
 	}
 	if ((err = snd_ad1848_mixer(chip)) < 0) {
-		snd_printdd("sgalaxy - error creating new ad1848 mixer\n");
-		snd_card_free(card);
-		return err;
+		snd_printdd(PFX "error creating new ad1848 mixer\n");
+		goto _err;
 	}
-	if (snd_sgalaxy_mixer(chip) < 0) {
-		snd_printdd("sgalaxy - the mixer rewrite failed\n");
-		snd_card_free(card);
-		return err;
+	if ((err = snd_sgalaxy_mixer(chip)) < 0) {
+		snd_printdd(PFX "the mixer rewrite failed\n");
+		goto _err;
 	}
 
 	strcpy(card->driver, "Sound Galaxy");
@@ -284,12 +279,18 @@
 	sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
 		wssport[dev], xirq, xdma1);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
+
 	snd_sgalaxy_cards[dev] = card;
 	return 0;
+
+ _err:
+	snd_card_free(card);
+	return err;
 }
 
 static int __init alsa_card_sgalaxy_init(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 3959ed6..9f6b58c 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1262,11 +1262,6 @@
 	 */
 	sscape_write(sscape, GA_INTENA_REG, 0x80);
 
-	if ((err = snd_card_register(card)) < 0) {
-		printk(KERN_ERR "sscape: Failed to register sound card\n");
-		goto _release_card;
-	}
-
 	/*
 	 * Initialize mixer
 	 */
@@ -1396,6 +1391,13 @@
 			if (ret < 0)
 				return ret;
 			snd_card_set_dev(card, &pcard->card->dev);
+
+			if ((ret = snd_card_register(card)) < 0) {
+				printk(KERN_ERR "sscape: Failed to register sound card\n");
+				snd_card_free(card);
+				return ret;
+			}
+
 			pnp_set_card_drvdata(pcard, card);
 			++sscape_cards;
 			++idx;
@@ -1460,6 +1462,16 @@
 		if (ret < 0)
 			return ret;
 
+		if ((ret = snd_card_set_generic_dev(card)) < 0) {
+			snd_card_free(card);
+			return ret;
+		}
+		if ((ret = snd_card_register(card)) < 0) {
+			printk(KERN_ERR "sscape: Failed to register sound card\n");
+			snd_card_free(card);
+			return ret;
+		}
+
 		sscape_card[sscape_cards] = card;
 		params++;
 		sscape_cards++;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 79b0220..0a572e0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -622,6 +622,11 @@
 		 ics2115_port[dev],
 		 ics2115_irq[dev]);
 
+	if ((err = snd_card_set_generic_dev(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
index 531f8ba..2433b77 100644
--- a/sound/mips/Kconfig
+++ b/sound/mips/Kconfig
@@ -8,6 +8,7 @@
 	depends on (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SND
 	select SND_PCM
 	select SND_AC97_CODEC
+	select SND_GENERIC_DRIVER
 	help
 	  ALSA Sound driver for the Au1x00's AC97 port.
 
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index c20522b..3f9684f 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -667,6 +667,11 @@
 	strcpy(au1000->card->shortname, "Au1000-AC97");
 	sprintf(au1000->card->longname, "AMD Au1000--AC97 ALSA Driver");
 
+	if ((err = snd_card_set_generic_dev(au1000->card)) < 0) {
+		snd_card_free(au1000->card);
+		return err;
+	}
+
 	if ((err = snd_card_register(au1000->card)) < 0) {
 		snd_card_free(au1000->card);
 		return err;
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index d7a8f9f..f560dd8 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -880,6 +880,8 @@
                 goto free_and_ret;
         }
 
+	snd_card_set_dev(card, &padev->dev);
+
 	*rchip = h;
 
 	return 0;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1e458919..a5d593c 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -316,6 +316,18 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-ymfpci.
 
+config SND_AD1889
+	tristate "Analog Devices AD1889"
+	depends on SND
+	select SND_AC97_CODEC
+	help
+	  Say Y here to include support for the integrated AC97 sound
+	  device found in particular on the Hewlett-Packard [BCJ]-xxx0
+	  class PA-RISC workstations, using the AD1819 codec.
+
+	  To compile this as a module, choose M here: the module
+	  will be called snd-ad1889.
+
 config SND_ALS4000
 	tristate "Avance Logic ALS4000"
 	depends on SND && ISA_DMA_API
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index b40575c..42fabfc 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -3,6 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
+snd-ad1889-objs := ad1889.o
 snd-als4000-objs := als4000.o
 snd-atiixp-objs := atiixp.o
 snd-atiixp-modem-objs := atiixp_modem.o
@@ -25,6 +26,7 @@
 snd-via82xx-modem-objs := via82xx_modem.o
 
 # Toplevel Module Dependency
+obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
 obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
 obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
 obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 5501f44..e64cb07 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -112,6 +112,7 @@
 { 0x414c4723, 0xffffffff, "ALC650F",		NULL,	NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650,	NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655,	NULL },
+{ 0x414c4781, 0xffffffff, "ALC658D",		NULL,	NULL }, /* already patched */
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
 { 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
 { 0x414c4730, 0xffffffff, "ALC101",		NULL,		NULL },
@@ -1796,7 +1797,7 @@
 
 	snd_assert(card != NULL, return -EINVAL);
 	snd_assert(rbus != NULL, return -EINVAL);
-	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
 	bus->card = card;
@@ -1905,7 +1906,7 @@
 	}
 
 	card = bus->card;
-	ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
+	ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL);
 	if (ac97 == NULL)
 		return -ENOMEM;
 	ac97->private_data = template->private_data;
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index dadf387..6d73514 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -52,6 +52,7 @@
 #define AC97_ID_ALC650F		0x414c4723
 #define AC97_ID_ALC655		0x414c4760
 #define AC97_ID_ALC658		0x414c4780
+#define AC97_ID_ALC658D		0x414c4781
 #define AC97_ID_ALC850		0x414c4790
 #define AC97_ID_YMF753		0x594d4803
 #define AC97_ID_VT1616		0x49434551
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index b584172..045ddc7 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -2134,7 +2134,13 @@
 {
 	unsigned int val;
 
-	ac97->spec.dev_flags = (ac97->id == 0x414c4780); /* ALC658 */
+	if (ac97->id == AC97_ID_ALC658) {
+		ac97->spec.dev_flags = 1; /* ALC658 */
+		if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
+			ac97->id = AC97_ID_ALC658D;
+			ac97->spec.dev_flags = 2;
+		}
+	}
 
 	ac97->build_ops = &patch_alc655_ops;
 
@@ -2143,10 +2149,15 @@
 
 	/* adjust default values */
 	val = snd_ac97_read(ac97, 0x7a); /* misc control */
-	if (ac97->id == 0x414c4780) /* ALC658 */
+	if (ac97->spec.dev_flags) /* ALC658 */
 		val &= ~(1 << 1); /* Pin 47 is spdif input pin */
-	else /* ALC655 */
-		val |= (1 << 1); /* Pin 47 is spdif input pin */
+	else { /* ALC655 */
+		if (ac97->subsystem_vendor == 0x1462 &&
+		    ac97->subsystem_device == 0x0131) /* MSI S270 laptop */
+			val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
+		else
+			val |= (1 << 1); /* Pin 47 is spdif input pin */
+	}
 	val &= ~(1 << 12); /* vref enable */
 	snd_ac97_write_cache(ac97, 0x7a, val);
 	/* set default: spdif-in enabled,
@@ -2159,6 +2170,11 @@
 	/* full DAC volume */
 	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
 	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+
+	/* update undocumented bit... */
+	if (ac97->id == AC97_ID_ALC658D)
+		snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
+
 	return 0;
 }
 
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index f9ce0fd..4032c57 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -357,7 +357,7 @@
 	snd_assert(rak4531 != NULL, return -EINVAL);
 	*rak4531 = NULL;
 	snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
-	ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
+	ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
 	if (ak4531 == NULL)
 		return -ENOMEM;
 	*ak4531 = *_ak4531;
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
new file mode 100644
index 0000000..d7d99a2
--- /dev/null
+++ b/sound/pci/ad1889.c
@@ -0,0 +1,1090 @@
+/* Analog Devices 1889 audio driver
+ *
+ * This is a driver for the AD1889 PCI audio chipset found
+ * on the HP PA-RISC [BCJ]-xxx0 workstations.
+ *
+ * Copyright (C) 2004-2005, Kyle McMartin <kyle@parisc-linux.org>
+ * Copyright (C) 2005, Thibaut Varene <varenet@parisc-linux.org>
+ *   Based on the OSS AD1889 driver by Randolph Chung <tausq@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ *	Do we need to take care of CCS register?
+ *	Maybe we could use finer grained locking (separate locks for pb/cap)?
+ * Wishlist:
+ *	Control Interface (mixer) support
+ *	Better AC97 support (VSR...)?
+ *	PM support
+ *	MIDI support
+ *	Game Port support
+ *	SG DMA support (this will need *alot* of work)
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include <asm/io.h>
+
+#include "ad1889.h"
+#include "ac97/ac97_id.h"
+
+#define	AD1889_DRVVER	"$Revision: 1.3 $"
+
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>");
+MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1889}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable AD1889 soundcard.");
+
+static char *ac97_quirk[SNDRV_CARDS];
+module_param_array(ac97_quirk, charp, NULL, 0444);
+MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+
+#define DEVNAME "ad1889"
+#define PFX	DEVNAME ": "
+
+/* let's use the global sound debug interfaces */
+#define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg)
+
+/* keep track of some hw registers */
+struct ad1889_register_state {
+	u16 reg;	/* reg setup */
+	u32 addr;	/* dma base address */
+	unsigned long size;	/* DMA buffer size */
+};
+
+struct snd_ad1889 {
+	snd_card_t *card;
+	struct pci_dev *pci;
+
+	int irq;
+	unsigned long bar;
+	void __iomem *iobase;
+
+	ac97_t *ac97;
+	ac97_bus_t *ac97_bus;
+	snd_pcm_t *pcm;
+	snd_info_entry_t *proc;
+
+	snd_pcm_substream_t *psubs;
+	snd_pcm_substream_t *csubs;
+
+	/* playback register state */
+	struct ad1889_register_state wave;
+	struct ad1889_register_state ramc;
+
+	spinlock_t lock;
+};
+
+static inline u16
+ad1889_readw(struct snd_ad1889 *chip, unsigned reg)
+{
+	return readw(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val)
+{
+	writew(val, chip->iobase + reg);
+}
+
+static inline u32
+ad1889_readl(struct snd_ad1889 *chip, unsigned reg)
+{
+	return readl(chip->iobase + reg);
+}
+
+static inline void
+ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val)
+{
+	writel(val, chip->iobase + reg);
+}
+
+static inline void
+ad1889_unmute(struct snd_ad1889 *chip)
+{
+	u16 st;
+	st = ad1889_readw(chip, AD_DS_WADA) & 
+		~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM);
+	ad1889_writew(chip, AD_DS_WADA, st);
+	ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_mute(struct snd_ad1889 *chip)
+{
+	u16 st;
+	st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM;
+	ad1889_writew(chip, AD_DS_WADA, st);
+	ad1889_readw(chip, AD_DS_WADA);
+}
+
+static inline void
+ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+	ad1889_writel(chip, AD_DMA_ADCBA, address);
+	ad1889_writel(chip, AD_DMA_ADCCA, address);
+}
+
+static inline void
+ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+	ad1889_writel(chip, AD_DMA_ADCBC, count);
+	ad1889_writel(chip, AD_DMA_ADCCC, count);
+}
+
+static inline void
+ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+	ad1889_writel(chip, AD_DMA_ADCIB, count);
+	ad1889_writel(chip, AD_DMA_ADCIC, count);
+}
+
+static inline void
+ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address)
+{
+	ad1889_writel(chip, AD_DMA_WAVBA, address);
+	ad1889_writel(chip, AD_DMA_WAVCA, address);
+}
+
+static inline void
+ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count)
+{
+	ad1889_writel(chip, AD_DMA_WAVBC, count);
+	ad1889_writel(chip, AD_DMA_WAVCC, count);
+}
+
+static inline void
+ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count)
+{
+	ad1889_writel(chip, AD_DMA_WAVIB, count);
+	ad1889_writel(chip, AD_DMA_WAVIC, count);
+}
+
+static void
+ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel)
+{
+	u16 reg;
+	
+	if (channel & AD_CHAN_WAV) {
+		/* Disable wave channel */
+		reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN;
+		ad1889_writew(chip, AD_DS_WSMC, reg);
+		chip->wave.reg = reg;
+		
+		/* disable IRQs */
+		reg = ad1889_readw(chip, AD_DMA_WAV);
+		reg &= AD_DMA_IM_DIS;
+		reg &= ~AD_DMA_LOOP;
+		ad1889_writew(chip, AD_DMA_WAV, reg);
+
+		/* clear IRQ and address counters and pointers */
+		ad1889_load_wave_buffer_address(chip, 0x0);
+		ad1889_load_wave_buffer_count(chip, 0x0);
+		ad1889_load_wave_interrupt_count(chip, 0x0);
+
+		/* flush */
+		ad1889_readw(chip, AD_DMA_WAV);
+	}
+	
+	if (channel & AD_CHAN_ADC) {
+		/* Disable ADC channel */
+		reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN;
+		ad1889_writew(chip, AD_DS_RAMC, reg);
+		chip->ramc.reg = reg;
+
+		reg = ad1889_readw(chip, AD_DMA_ADC);
+		reg &= AD_DMA_IM_DIS;
+		reg &= ~AD_DMA_LOOP;
+		ad1889_writew(chip, AD_DMA_ADC, reg);
+	
+		ad1889_load_adc_buffer_address(chip, 0x0);
+		ad1889_load_adc_buffer_count(chip, 0x0);
+		ad1889_load_adc_interrupt_count(chip, 0x0);
+
+		/* flush */
+		ad1889_readw(chip, AD_DMA_ADC);
+	}
+}
+
+static inline u16
+snd_ad1889_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+	struct snd_ad1889 *chip = ac97->private_data;
+	return ad1889_readw(chip, AD_AC97_BASE + reg);
+}
+
+static inline void
+snd_ad1889_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+	struct snd_ad1889 *chip = ac97->private_data;
+	ad1889_writew(chip, AD_AC97_BASE + reg, val);
+}
+
+static int
+snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
+{
+	int retry = 400; /* average needs 352 msec */
+	
+	while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY) 
+			&& --retry)
+		mdelay(1);
+	if (!retry) {
+		snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n",
+		       __FUNCTION__);
+		return -EIO;
+	}
+	ad1889_debug("[%s] ready after %d ms\n", __FUNCTION__, 400 - retry);
+
+	return 0;
+}
+
+static int 
+snd_ad1889_hw_params(snd_pcm_substream_t *substream,
+			snd_pcm_hw_params_t *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, 
+					params_buffer_bytes(hw_params));
+}
+
+static int
+snd_ad1889_hw_free(snd_pcm_substream_t *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static snd_pcm_hardware_t snd_ad1889_playback_hw = {
+	.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+	.rate_min = 8000,	/* docs say 7000, but we're lazy */
+	.rate_max = 48000,
+	.channels_min = 1,
+	.channels_max = 2,
+	.buffer_bytes_max = BUFFER_BYTES_MAX,
+	.period_bytes_min = PERIOD_BYTES_MIN,
+	.period_bytes_max = PERIOD_BYTES_MAX,
+	.periods_min = PERIODS_MIN,
+	.periods_max = PERIODS_MAX,
+	/*.fifo_size = 0,*/
+};
+
+static snd_pcm_hardware_t snd_ad1889_capture_hw = {
+	.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_48000,
+	.rate_min = 48000,	/* docs say we could to VSR, but we're lazy */
+	.rate_max = 48000,
+	.channels_min = 1,
+	.channels_max = 2,
+	.buffer_bytes_max = BUFFER_BYTES_MAX,
+	.period_bytes_min = PERIOD_BYTES_MIN,
+	.period_bytes_max = PERIOD_BYTES_MAX,
+	.periods_min = PERIODS_MIN,
+	.periods_max = PERIODS_MAX,
+	/*.fifo_size = 0,*/
+};
+
+static int
+snd_ad1889_playback_open(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
+
+	chip->psubs = ss;
+	rt->hw = snd_ad1889_playback_hw;
+
+	return 0;
+}
+
+static int
+snd_ad1889_capture_open(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
+
+	chip->csubs = ss;
+	rt->hw = snd_ad1889_capture_hw;
+
+	return 0;
+}
+
+static int
+snd_ad1889_playback_close(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	chip->psubs = NULL;
+	return 0;
+}
+
+static int
+snd_ad1889_capture_close(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	chip->csubs = NULL;
+	return 0;
+}
+
+static int
+snd_ad1889_playback_prepare(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
+	unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+	unsigned int count = snd_pcm_lib_period_bytes(ss);
+	u16 reg;
+
+	ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+	reg = ad1889_readw(chip, AD_DS_WSMC);
+	
+	/* Mask out 16-bit / Stereo */
+	reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST);
+
+	if (snd_pcm_format_width(rt->format) == 16)
+		reg |= AD_DS_WSMC_WA16;
+
+	if (rt->channels > 1)
+		reg |= AD_DS_WSMC_WAST;
+
+	/* let's make sure we don't clobber ourselves */
+	spin_lock_irq(&chip->lock);
+	
+	chip->wave.size = size;
+	chip->wave.reg = reg;
+	chip->wave.addr = rt->dma_addr;
+
+	ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg);
+	
+	/* Set sample rates on the codec */
+	ad1889_writew(chip, AD_DS_WAS, rt->rate);
+
+	/* Set up DMA */
+	ad1889_load_wave_buffer_address(chip, chip->wave.addr);
+	ad1889_load_wave_buffer_count(chip, size);
+	ad1889_load_wave_interrupt_count(chip, count);
+
+	/* writes flush */
+	ad1889_readw(chip, AD_DS_WSMC);
+	
+	spin_unlock_irq(&chip->lock);
+	
+	ad1889_debug("prepare playback: addr = 0x%x, count = %u, "
+			"size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr,
+			count, size, reg, rt->rate);
+	return 0;
+}
+
+static int
+snd_ad1889_capture_prepare(snd_pcm_substream_t *ss)
+{
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
+	unsigned int size = snd_pcm_lib_buffer_bytes(ss);
+	unsigned int count = snd_pcm_lib_period_bytes(ss);
+	u16 reg;
+
+	ad1889_channel_reset(chip, AD_CHAN_ADC);
+	
+	reg = ad1889_readw(chip, AD_DS_RAMC);
+
+	/* Mask out 16-bit / Stereo */
+	reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);
+
+	if (snd_pcm_format_width(rt->format) == 16)
+		reg |= AD_DS_RAMC_AD16;
+
+	if (rt->channels > 1)
+		reg |= AD_DS_RAMC_ADST;
+
+	/* let's make sure we don't clobber ourselves */
+	spin_lock_irq(&chip->lock);
+	
+	chip->ramc.size = size;
+	chip->ramc.reg = reg;
+	chip->ramc.addr = rt->dma_addr;
+
+	ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);
+
+	/* Set up DMA */
+	ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
+	ad1889_load_adc_buffer_count(chip, size);
+	ad1889_load_adc_interrupt_count(chip, count);
+
+	/* writes flush */
+	ad1889_readw(chip, AD_DS_RAMC);
+	
+	spin_unlock_irq(&chip->lock);
+	
+	ad1889_debug("prepare capture: addr = 0x%x, count = %u, "
+			"size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr,
+			count, size, reg, rt->rate);
+	return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+   Must be as fast as possible and not sleep.
+   DMA should be *triggered* by this call.
+   The WSMC "WAEN" bit triggers DMA Wave On/Off */
+static int
+snd_ad1889_playback_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+	u16 wsmc;
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+	
+	wsmc = ad1889_readw(chip, AD_DS_WSMC);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* enable DMA loop & interrupts */
+		ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT);
+		wsmc |= AD_DS_WSMC_WAEN;
+		/* 1 to clear CHSS bit */
+		ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS);
+		ad1889_unmute(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		ad1889_mute(chip);
+		wsmc &= ~AD_DS_WSMC_WAEN;
+		break;
+	default:
+		snd_BUG();
+		return -EINVAL;
+	}
+	
+	chip->wave.reg = wsmc;
+	ad1889_writew(chip, AD_DS_WSMC, wsmc);	
+	ad1889_readw(chip, AD_DS_WSMC);	/* flush */
+
+	/* reset the chip when STOP - will disable IRQs */
+	if (cmd == SNDRV_PCM_TRIGGER_STOP)
+		ad1889_channel_reset(chip, AD_CHAN_WAV);
+
+	return 0;
+}
+
+/* this is called in atomic context with IRQ disabled.
+   Must be as fast as possible and not sleep.
+   DMA should be *triggered* by this call.
+   The RAMC "ADEN" bit triggers DMA ADC On/Off */
+static int
+snd_ad1889_capture_trigger(snd_pcm_substream_t *ss, int cmd)
+{
+	u16 ramc;
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+	ramc = ad1889_readw(chip, AD_DS_RAMC);
+	
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* enable DMA loop & interrupts */
+		ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT);
+		ramc |= AD_DS_RAMC_ADEN;
+		/* 1 to clear CHSS bit */
+		ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		ramc &= ~AD_DS_RAMC_ADEN;
+		break;
+	default:
+		return -EINVAL;
+	}
+	
+	chip->ramc.reg = ramc;
+	ad1889_writew(chip, AD_DS_RAMC, ramc);	
+	ad1889_readw(chip, AD_DS_RAMC);	/* flush */
+	
+	/* reset the chip when STOP - will disable IRQs */
+	if (cmd == SNDRV_PCM_TRIGGER_STOP)
+		ad1889_channel_reset(chip, AD_CHAN_ADC);
+		
+	return 0;
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_playback_pointer(snd_pcm_substream_t *ss)
+{
+	size_t ptr = 0;
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+	if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN)))
+		return 0;
+
+	ptr = ad1889_readl(chip, AD_DMA_WAVCA);
+	ptr -= chip->wave.addr;
+	
+	snd_assert((ptr >= 0) && (ptr < chip->wave.size), return 0);
+	
+	return bytes_to_frames(ss->runtime, ptr);
+}
+
+/* Called in atomic context with IRQ disabled */
+static snd_pcm_uframes_t
+snd_ad1889_capture_pointer(snd_pcm_substream_t *ss)
+{
+	size_t ptr = 0;
+	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
+
+	if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN)))
+		return 0;
+
+	ptr = ad1889_readl(chip, AD_DMA_ADCCA);
+	ptr -= chip->ramc.addr;
+
+	snd_assert((ptr >= 0) && (ptr < chip->ramc.size), return 0);
+	
+	return bytes_to_frames(ss->runtime, ptr);
+}
+
+static snd_pcm_ops_t snd_ad1889_playback_ops = {
+	.open = snd_ad1889_playback_open,
+	.close = snd_ad1889_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_ad1889_hw_params,
+	.hw_free = snd_ad1889_hw_free,
+	.prepare = snd_ad1889_playback_prepare,
+	.trigger = snd_ad1889_playback_trigger,
+	.pointer = snd_ad1889_playback_pointer, 
+};
+
+static snd_pcm_ops_t snd_ad1889_capture_ops = {
+	.open = snd_ad1889_capture_open,
+	.close = snd_ad1889_capture_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_ad1889_hw_params,
+	.hw_free = snd_ad1889_hw_free,
+	.prepare = snd_ad1889_capture_prepare,
+	.trigger = snd_ad1889_capture_trigger,
+	.pointer = snd_ad1889_capture_pointer, 
+};
+
+static irqreturn_t
+snd_ad1889_interrupt(int irq, 
+		     void *dev_id, 
+		     struct pt_regs *regs)
+{
+	unsigned long st;
+	struct snd_ad1889 *chip = dev_id;
+
+	st = ad1889_readl(chip, AD_DMA_DISR);
+
+	/* clear ISR */
+	ad1889_writel(chip, AD_DMA_DISR, st);
+
+	st &= AD_INTR_MASK;
+
+	if (unlikely(!st))
+		return IRQ_NONE;
+
+	if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI))
+		ad1889_debug("Unexpected master or target abort interrupt!\n");
+
+	if ((st & AD_DMA_DISR_WAVI) && chip->psubs)
+		snd_pcm_period_elapsed(chip->psubs);
+	if ((st & AD_DMA_DISR_ADCI) && chip->csubs)
+		snd_pcm_period_elapsed(chip->csubs);
+
+	return IRQ_HANDLED;
+}
+
+static void 
+snd_ad1889_pcm_free(snd_pcm_t *pcm)
+{
+	struct snd_ad1889 *chip = pcm->private_data;
+	chip->pcm = NULL;
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int __devinit
+snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, snd_pcm_t **rpcm)
+{
+	int err;
+	snd_pcm_t *pcm;
+
+	if (rpcm)
+		*rpcm = NULL;
+
+	err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm);
+	if (err < 0)
+		return err;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+			&snd_ad1889_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_ad1889_capture_ops);
+
+	pcm->private_data = chip;
+	pcm->private_free = snd_ad1889_pcm_free;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, chip->card->shortname);
+	
+	chip->pcm = pcm;
+	chip->psubs = NULL;
+	chip->csubs = NULL;
+
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+						snd_dma_pci_data(chip->pci),
+						BUFFER_BYTES_MAX / 2,
+						BUFFER_BYTES_MAX);
+
+	if (err < 0) {
+		snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
+		return err;
+	}
+	
+	if (rpcm)
+		*rpcm = pcm;
+	
+	return 0;
+}
+
+static void
+snd_ad1889_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	struct snd_ad1889 *chip = entry->private_data;
+	u16 reg;
+	int tmp;
+
+	reg = ad1889_readw(chip, AD_DS_WSMC);
+	snd_iprintf(buffer, "Wave output: %s\n",
+			(reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled");
+	snd_iprintf(buffer, "Wave Channels: %s\n",
+			(reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+	snd_iprintf(buffer, "Wave Quality: %d-bit linear\n",
+			(reg & AD_DS_WSMC_WA16) ? 16 : 8);
+	
+	/* WARQ is at offset 12 */
+	tmp = (reg & AD_DS_WSMC_WARQ) ?
+			(((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4;
+	tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+	
+	snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
+			(reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+				
+	
+	snd_iprintf(buffer, "Synthesis output: %s\n",
+			reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled");
+	
+	/* SYRQ is at offset 4 */
+	tmp = (reg & AD_DS_WSMC_SYRQ) ?
+			(((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4;
+	tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
+	
+	snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
+			(reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+
+	reg = ad1889_readw(chip, AD_DS_RAMC);
+	snd_iprintf(buffer, "ADC input: %s\n",
+			(reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled");
+	snd_iprintf(buffer, "ADC Channels: %s\n",
+			(reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+	snd_iprintf(buffer, "ADC Quality: %d-bit linear\n",
+			(reg & AD_DS_RAMC_AD16) ? 16 : 8);
+	
+	/* ACRQ is at offset 4 */
+	tmp = (reg & AD_DS_RAMC_ACRQ) ?
+			(((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4;
+	tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+	
+	snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
+			(reg & AD_DS_RAMC_ADST) ? "stereo" : "mono");
+	
+	snd_iprintf(buffer, "Resampler input: %s\n",
+			reg & AD_DS_RAMC_REEN ? "enabled" : "disabled");
+			
+	/* RERQ is at offset 12 */
+	tmp = (reg & AD_DS_RAMC_RERQ) ?
+			(((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4;
+	tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
+	
+	snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
+			(reg & AD_DS_WSMC_WAST) ? "stereo" : "mono");
+				
+	
+	/* doc says LSB represents -1.5dB, but the max value (-94.5dB)
+	suggests that LSB is -3dB, which is more coherent with the logarithmic
+	nature of the dB scale */
+	reg = ad1889_readw(chip, AD_DS_WADA);
+	snd_iprintf(buffer, "Left: %s, -%d dB\n",
+			(reg & AD_DS_WADA_LWAM) ? "mute" : "unmute",
+			((reg & AD_DS_WADA_LWAA) >> 8) * 3);
+	reg = ad1889_readw(chip, AD_DS_WADA);
+	snd_iprintf(buffer, "Right: %s, -%d dB\n",
+			(reg & AD_DS_WADA_RWAM) ? "mute" : "unmute",
+			((reg & AD_DS_WADA_RWAA) >> 8) * 3);
+	
+	reg = ad1889_readw(chip, AD_DS_WAS);
+	snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg);
+	reg = ad1889_readw(chip, AD_DS_RES);
+	snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg);
+}
+
+static void __devinit
+snd_ad1889_proc_init(struct snd_ad1889 *chip)
+{
+	snd_info_entry_t *entry;
+
+	if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
+		snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read);
+}
+
+static struct ac97_quirk ac97_quirks[] = {
+	{
+		.subvendor = 0x11d4,	/* AD */
+		.subdevice = 0x1889,	/* AD1889 */
+		.codec_id = AC97_ID_AD1819,
+		.name = "AD1889",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{ } /* terminator */
+};
+
+static void __devinit
+snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
+{
+	u16 reg;
+
+	reg = ad1889_readw(chip, AD_AC97_ACIC);
+	reg |= AD_AC97_ACIC_ACRD;		/* Reset Disable */
+	ad1889_writew(chip, AD_AC97_ACIC, reg);
+	ad1889_readw(chip, AD_AC97_ACIC);	/* flush posted write */
+	udelay(10);
+	/* Interface Enable */
+	reg |= AD_AC97_ACIC_ACIE;
+	ad1889_writew(chip, AD_AC97_ACIC, reg);
+	
+	snd_ad1889_ac97_ready(chip);
+
+	/* Audio Stream Output | Variable Sample Rate Mode */
+	reg = ad1889_readw(chip, AD_AC97_ACIC);
+	reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM;
+	ad1889_writew(chip, AD_AC97_ACIC, reg);
+	ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */
+
+}
+
+static void
+snd_ad1889_ac97_bus_free(ac97_bus_t *bus)
+{
+	struct snd_ad1889 *chip = bus->private_data;
+	chip->ac97_bus = NULL;
+}
+
+static void
+snd_ad1889_ac97_free(ac97_t *ac97)
+{
+	struct snd_ad1889 *chip = ac97->private_data;
+	chip->ac97 = NULL;
+}
+
+static int __devinit
+snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
+{
+	int err;
+	ac97_template_t ac97;
+	static ac97_bus_ops_t ops = {
+		.write = snd_ad1889_ac97_write,
+		.read = snd_ad1889_ac97_read,
+	};
+
+	/* doing that here, it works. */
+	snd_ad1889_ac97_xinit(chip);
+
+	err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus);
+	if (err < 0)
+		return err;
+	
+	chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free;
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.private_data = chip;
+	ac97.private_free = snd_ad1889_ac97_free;
+	ac97.pci = chip->pci;
+
+	err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97);
+	if (err < 0)
+		return err;
+		
+	snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);
+	
+	return 0;
+}
+
+static int
+snd_ad1889_free(struct snd_ad1889 *chip)
+{
+	if (chip->irq < 0)
+		goto skip_hw;
+
+	spin_lock_irq(&chip->lock);
+
+	ad1889_mute(chip);
+
+	/* Turn off interrupt on count and zero DMA registers */
+	ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC);
+
+	/* clear DISR. If we don't, we'd better jump off the Eiffel Tower */
+	ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI);
+	ad1889_readl(chip, AD_DMA_DISR);	/* flush, dammit! */
+
+	spin_unlock_irq(&chip->lock);
+
+	synchronize_irq(chip->irq);
+	
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void*)chip);
+
+skip_hw:
+	if (chip->iobase)
+		iounmap(chip->iobase);
+
+	pci_release_regions(chip->pci);
+	pci_disable_device(chip->pci);
+
+	kfree(chip);
+	return 0;
+}
+
+static inline int
+snd_ad1889_dev_free(snd_device_t *device) 
+{
+	struct snd_ad1889 *chip = device->device_data;
+	return snd_ad1889_free(chip);
+}
+
+static int __devinit
+snd_ad1889_init(struct snd_ad1889 *chip) 
+{
+	ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
+	ad1889_readw(chip, AD_DS_CCS);	/* flush posted write */
+
+	mdelay(10);
+
+	/* enable Master and Target abort interrupts */
+	ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);
+
+	return 0;
+}
+
+static int __devinit
+snd_ad1889_create(snd_card_t *card,
+		  struct pci_dev *pci,
+		  struct snd_ad1889 **rchip)
+{
+	int err;
+
+	struct snd_ad1889 *chip;
+	static snd_device_ops_t ops = {
+		.dev_free = snd_ad1889_dev_free,
+	};
+
+	*rchip = NULL;
+
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+	
+	/* check PCI availability (32bit DMA) */
+	if (pci_set_dma_mask(pci, 0xffffffff) < 0 ||
+	    pci_set_consistent_dma_mask(pci, 0xffffffff) < 0) {
+		printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n");
+		pci_disable_device(pci);
+		return -ENXIO;
+	}
+
+	/* allocate chip specific data with zero-filled memory */
+	if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	chip->card = card;
+	card->private_data = chip;
+	chip->pci = pci;
+	chip->irq = -1;
+
+	/* (1) PCI resource allocation */
+	if ((err = pci_request_regions(pci, card->driver)) < 0)
+		goto free_and_ret;
+
+	chip->bar = pci_resource_start(pci, 0);
+	chip->iobase = ioremap_nocache(chip->bar, pci_resource_len(pci, 0));
+	if (chip->iobase == NULL) {
+		printk(KERN_ERR PFX "unable to reserve region.\n");
+		err = -EBUSY;
+		goto free_and_ret;
+	}
+	
+	pci_set_master(pci);
+
+	spin_lock_init(&chip->lock);	/* only now can we call ad1889_free */
+
+	if (request_irq(pci->irq, snd_ad1889_interrupt,
+			SA_INTERRUPT|SA_SHIRQ, card->driver, (void*)chip)) {
+		printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq);
+		snd_ad1889_free(chip);
+		return -EBUSY;
+	}
+
+	chip->irq = pci->irq;
+	synchronize_irq(chip->irq);
+
+	/* (2) initialization of the chip hardware */
+	if ((err = snd_ad1889_init(chip)) < 0) {
+		snd_ad1889_free(chip);
+		return err;
+	}
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+		snd_ad1889_free(chip);
+		return err;
+	}
+
+	snd_card_set_dev(card, &pci->dev);
+
+	*rchip = chip;
+
+	return 0;
+
+free_and_ret:
+	if (chip)
+		kfree(chip);
+	pci_disable_device(pci);
+
+	return err;
+}
+
+static int __devinit
+snd_ad1889_probe(struct pci_dev *pci,
+		 const struct pci_device_id *pci_id)
+{
+	int err;
+	static int devno;
+	snd_card_t *card;
+	struct snd_ad1889 *chip;
+
+	/* (1) */
+	if (devno >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[devno]) {
+		devno++;
+		return -ENOENT;
+	}
+
+	/* (2) */
+	card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0);
+	/* XXX REVISIT: we can probably allocate chip in this call */
+	if (card == NULL)
+		return -ENOMEM;
+
+	strcpy(card->driver, "AD1889");
+	strcpy(card->shortname, "Analog Devices AD1889");
+
+	/* (3) */
+	err = snd_ad1889_create(card, pci, &chip);
+	if (err < 0)
+		goto free_and_ret;
+
+	/* (4) */
+	sprintf(card->longname, "%s at 0x%lx irq %i",
+		card->shortname, chip->bar, chip->irq);
+
+	/* (5) */
+	/* register AC97 mixer */
+	err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]);
+	if (err < 0)
+		goto free_and_ret;
+	
+	err = snd_ad1889_pcm_init(chip, 0, NULL);
+	if (err < 0)
+		goto free_and_ret;
+
+	/* register proc interface */
+	snd_ad1889_proc_init(chip);
+
+	/* (6) */
+	err = snd_card_register(card);
+	if (err < 0)
+		goto free_and_ret;
+
+	/* (7) */
+	pci_set_drvdata(pci, card);
+
+	devno++;
+	return 0;
+
+free_and_ret:
+	snd_card_free(card);
+	return err;
+}
+
+static void __devexit
+snd_ad1889_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_device_id snd_ad1889_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
+	{ 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_ad1889_ids);
+
+static struct pci_driver ad1889_pci = {
+	.name = "AD1889 Audio",
+	.owner = THIS_MODULE,
+	.id_table = snd_ad1889_ids,
+	.probe = snd_ad1889_probe,
+	.remove = __devexit_p(snd_ad1889_remove),
+};
+
+static int __init
+alsa_ad1889_init(void)
+{
+	return pci_register_driver(&ad1889_pci);
+}
+
+static void __exit
+alsa_ad1889_fini(void)
+{
+	pci_unregister_driver(&ad1889_pci);
+}
+
+module_init(alsa_ad1889_init);
+module_exit(alsa_ad1889_fini);
diff --git a/sound/pci/ad1889.h b/sound/pci/ad1889.h
new file mode 100644
index 0000000..5e6dad5
--- /dev/null
+++ b/sound/pci/ad1889.h
@@ -0,0 +1,189 @@
+/* Analog Devices 1889 audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __AD1889_H__
+#define __AD1889_H__
+
+#define AD_DS_WSMC	0x00 /* wave/synthesis channel mixer control */
+#define  AD_DS_WSMC_SYEN 0x0004 /* synthesis channel enable */
+#define  AD_DS_WSMC_SYRQ 0x0030 /* synth. fifo request point */
+#define  AD_DS_WSMC_WA16 0x0100 /* wave channel 16bit select */
+#define  AD_DS_WSMC_WAST 0x0200 /* wave channel stereo select */
+#define  AD_DS_WSMC_WAEN 0x0400 /* wave channel enable */
+#define  AD_DS_WSMC_WARQ 0x3000 /* wave fifo request point */
+
+#define AD_DS_RAMC	0x02 /* resampler/ADC channel mixer control */
+#define  AD_DS_RAMC_AD16 0x0001 /* ADC channel 16bit select */
+#define  AD_DS_RAMC_ADST 0x0002 /* ADC channel stereo select */
+#define  AD_DS_RAMC_ADEN 0x0004 /* ADC channel enable */
+#define  AD_DS_RAMC_ACRQ 0x0030 /* ADC fifo request point */
+#define  AD_DS_RAMC_REEN 0x0400 /* resampler channel enable */
+#define  AD_DS_RAMC_RERQ 0x3000 /* res. fifo request point */
+
+#define AD_DS_WADA	0x04 /* wave channel mix attenuation */
+#define  AD_DS_WADA_RWAM 0x0080 /* right wave mute */
+#define  AD_DS_WADA_RWAA 0x001f /* right wave attenuation */
+#define  AD_DS_WADA_LWAM 0x8000 /* left wave mute */
+#define  AD_DS_WADA_LWAA 0x3e00 /* left wave attenuation */
+
+#define AD_DS_SYDA	0x06 /* synthesis channel mix attenuation */
+#define  AD_DS_SYDA_RSYM 0x0080 /* right synthesis mute */
+#define  AD_DS_SYDA_RSYA 0x001f /* right synthesis attenuation */
+#define  AD_DS_SYDA_LSYM 0x8000 /* left synthesis mute */
+#define  AD_DS_SYDA_LSYA 0x3e00 /* left synthesis attenuation */
+
+#define AD_DS_WAS	0x08 /* wave channel sample rate */
+#define  AD_DS_WAS_WAS   0xffff /* sample rate mask */
+
+#define AD_DS_RES	0x0a /* resampler channel sample rate */
+#define  AD_DS_RES_RES   0xffff /* sample rate mask */
+
+#define AD_DS_CCS	0x0c /* chip control/status */
+#define  AD_DS_CCS_ADO   0x0001 /* ADC channel overflow */
+#define  AD_DS_CCS_REO   0x0002 /* resampler channel overflow */
+#define  AD_DS_CCS_SYU   0x0004 /* synthesis channel underflow */
+#define  AD_DS_CCS_WAU   0x0008 /* wave channel underflow */
+/* bits 4 -> 7, 9, 11 -> 14 reserved */
+#define  AD_DS_CCS_XTD   0x0100 /* xtd delay control (4096 clock cycles) */
+#define  AD_DS_CCS_PDALL 0x0400 /* power */
+#define  AD_DS_CCS_CLKEN 0x8000 /* clock */
+
+#define AD_DMA_RESBA	0x40 /* RES base address */
+#define AD_DMA_RESCA	0x44 /* RES current address */
+#define AD_DMA_RESBC	0x48 /* RES base count */
+#define AD_DMA_RESCC	0x4c /* RES current count */
+
+#define AD_DMA_ADCBA	0x50 /* ADC base address */
+#define AD_DMA_ADCCA	0x54 /* ADC current address */
+#define AD_DMA_ADCBC	0x58 /* ADC base count */
+#define AD_DMA_ADCCC	0x5c /* ADC current count */
+
+#define AD_DMA_SYNBA	0x60 /* synth base address */
+#define AD_DMA_SYNCA	0x64 /* synth current address */
+#define AD_DMA_SYNBC	0x68 /* synth base count */
+#define AD_DMA_SYNCC	0x6c /* synth current count */
+
+#define AD_DMA_WAVBA	0x70 /* wave base address */
+#define AD_DMA_WAVCA	0x74 /* wave current address */
+#define AD_DMA_WAVBC	0x78 /* wave base count */
+#define AD_DMA_WAVCC	0x7c /* wave current count */
+
+#define AD_DMA_RESIC	0x80 /* RES dma interrupt current byte count */
+#define AD_DMA_RESIB	0x84 /* RES dma interrupt base byte count */
+
+#define AD_DMA_ADCIC	0x88 /* ADC dma interrupt current byte count */
+#define AD_DMA_ADCIB	0x8c /* ADC dma interrupt base byte count */
+
+#define AD_DMA_SYNIC	0x90 /* synth dma interrupt current byte count */
+#define AD_DMA_SYNIB	0x94 /* synth dma interrupt base byte count */
+
+#define AD_DMA_WAVIC	0x98 /* wave dma interrupt current byte count */
+#define AD_DMA_WAVIB	0x9c /* wave dma interrupt base byte count */
+
+#define  AD_DMA_ICC	0xffffff /* current byte count mask */
+#define  AD_DMA_IBC	0xffffff /* base byte count mask */
+/* bits 24 -> 31 reserved */
+
+/* 4 bytes pad */
+#define AD_DMA_ADC	0xa8	/* ADC      dma control and status */
+#define AD_DMA_SYNTH	0xb0	/* Synth    dma control and status */
+#define AD_DMA_WAV	0xb8	/* wave     dma control and status */
+#define AD_DMA_RES	0xa0	/* Resample dma control and status */
+
+#define  AD_DMA_SGDE	0x0001 /* SGD mode enable */
+#define  AD_DMA_LOOP	0x0002 /* loop enable */
+#define  AD_DMA_IM	0x000c /* interrupt mode mask */
+#define  AD_DMA_IM_DIS	(~AD_DMA_IM)	/* disable */
+#define  AD_DMA_IM_CNT	0x0004 /* interrupt on count */
+#define  AD_DMA_IM_SGD	0x0008 /* interrupt on SGD flag */
+#define  AD_DMA_IM_EOL	0x000c /* interrupt on End of Linked List */
+#define  AD_DMA_SGDS	0x0030 /* SGD status */
+#define  AD_DMA_SFLG	0x0040 /* SGD flag */
+#define  AD_DMA_EOL	0x0080 /* SGD end of list */
+/* bits 8 -> 15 reserved */
+
+#define AD_DMA_DISR	0xc0 /* dma interrupt status */
+#define  AD_DMA_DISR_RESI 0x000001 /* resampler channel interrupt */
+#define  AD_DMA_DISR_ADCI 0x000002 /* ADC channel interrupt */
+#define  AD_DMA_DISR_SYNI 0x000004 /* synthesis channel interrupt */
+#define  AD_DMA_DISR_WAVI 0x000008 /* wave channel interrupt */
+/* bits 4, 5 reserved */
+#define  AD_DMA_DISR_SEPS 0x000040 /* serial eeprom status */
+/* bits 7 -> 13 reserved */
+#define  AD_DMA_DISR_PMAI 0x004000 /* pci master abort interrupt */
+#define  AD_DMA_DISR_PTAI 0x008000 /* pci target abort interrupt */
+#define  AD_DMA_DISR_PTAE 0x010000 /* pci target abort interrupt enable */
+#define  AD_DMA_DISR_PMAE 0x020000 /* pci master abort interrupt enable */
+/* bits 19 -> 31 reserved */
+
+/* interrupt mask */
+#define  AD_INTR_MASK     (AD_DMA_DISR_RESI|AD_DMA_DISR_ADCI| \
+                           AD_DMA_DISR_WAVI|AD_DMA_DISR_SYNI| \
+                           AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)
+
+#define AD_DMA_CHSS	0xc4 /* dma channel stop status */
+#define  AD_DMA_CHSS_RESS 0x000001 /* resampler channel stopped */
+#define  AD_DMA_CHSS_ADCS 0x000002 /* ADC channel stopped */
+#define  AD_DMA_CHSS_SYNS 0x000004 /* synthesis channel stopped */
+#define  AD_DMA_CHSS_WAVS 0x000008 /* wave channel stopped */
+
+#define AD_GPIO_IPC	0xc8	/* gpio port control */
+#define AD_GPIO_OP	0xca	/* gpio output port status */
+#define AD_GPIO_IP	0xcc	/* gpio  input port status */
+
+#define AD_AC97_BASE	0x100	/* ac97 base register */
+
+#define AD_AC97_RESET   0x100   /* reset */
+
+#define AD_AC97_PWR_CTL	0x126	/* == AC97_POWERDOWN */
+#define  AD_AC97_PWR_ADC 0x0001 /* ADC ready status */
+#define  AD_AC97_PWR_DAC 0x0002 /* DAC ready status */
+#define  AD_AC97_PWR_PR0 0x0100 /* PR0 (ADC) powerdown */
+#define  AD_AC97_PWR_PR1 0x0200 /* PR1 (DAC) powerdown */
+
+#define AD_MISC_CTL     0x176 /* misc control */
+#define  AD_MISC_CTL_DACZ   0x8000 /* set for zero fill, unset for repeat */
+#define  AD_MISC_CTL_ARSR   0x0001 /* set for SR1, unset for SR0 */
+#define  AD_MISC_CTL_ALSR   0x0100
+#define  AD_MISC_CTL_DLSR   0x0400
+#define  AD_MISC_CTL_DRSR   0x0004
+
+#define AD_AC97_SR0     0x178 /* sample rate 0, 0xbb80 == 48K */
+#define  AD_AC97_SR0_48K 0xbb80 /* 48KHz */
+#define AD_AC97_SR1     0x17a /* sample rate 1 */
+
+#define AD_AC97_ACIC	0x180 /* ac97 codec interface control */
+#define  AD_AC97_ACIC_ACIE  0x0001 /* analog codec interface enable */
+#define  AD_AC97_ACIC_ACRD  0x0002 /* analog codec reset disable */
+#define  AD_AC97_ACIC_ASOE  0x0004 /* audio stream output enable */
+#define  AD_AC97_ACIC_VSRM  0x0008 /* variable sample rate mode */
+#define  AD_AC97_ACIC_FSDH  0x0100 /* force SDATA_OUT high */
+#define  AD_AC97_ACIC_FSYH  0x0200 /* force sync high */
+#define  AD_AC97_ACIC_ACRDY 0x8000 /* analog codec ready status */
+/* bits 10 -> 14 reserved */
+
+
+#define AD_DS_MEMSIZE	512
+#define AD_OPL_MEMSIZE	16
+#define AD_MIDI_MEMSIZE	16
+
+#define AD_WAV_STATE	0
+#define AD_ADC_STATE	1
+#define AD_MAX_STATES	2
+
+#define AD_CHAN_WAV	0x0001
+#define AD_CHAN_ADC	0x0002
+#define AD_CHAN_RES	0x0004
+#define AD_CHAN_SYN	0x0008
+
+
+/* The chip would support 4 GB buffers and 16 MB periods,
+ * but let's not overdo it ... */
+#define BUFFER_BYTES_MAX	(256 * 1024)
+#define PERIOD_BYTES_MIN	32
+#define PERIOD_BYTES_MAX	(BUFFER_BYTES_MAX / 2)
+#define PERIODS_MIN		2
+#define PERIODS_MAX		(BUFFER_BYTES_MAX / PERIOD_BYTES_MIN)
+
+#endif /* __AD1889_H__ */
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 4943299..d683f77 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -78,15 +78,7 @@
  *  Constants definition
  */
 
-#ifndef PCI_VENDOR_ID_ALI
-#define PCI_VENDOR_ID_ALI	0x10b9
-#endif
-
-#ifndef PCI_DEVICE_ID_ALI_5451
-#define PCI_DEVICE_ID_ALI_5451	0x5451
-#endif
-
-#define DEVICE_ID_ALI5451	((PCI_VENDOR_ID_ALI<<16)|PCI_DEVICE_ID_ALI_5451)
+#define DEVICE_ID_ALI5451	((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451)
 
 
 #define ALI_CHANNELS		32
@@ -326,13 +318,12 @@
 static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
 {
 	unsigned int dwVal;
-	struct pci_dev *pci_dev = NULL;
+	struct pci_dev *pci_dev;
 	int i,j;
 
-
-        pci_dev = pci_find_device(vendor, deviceid, pci_dev);
-        if (pci_dev == NULL)
-                return ;
+	pci_dev = pci_get_device(vendor, deviceid, NULL);
+	if (pci_dev == NULL)
+		return ;
 
 	printk("\nM%x PCI CFG\n", deviceid);
 	printk("    ");
@@ -349,6 +340,7 @@
 		}
 		printk("\n");
 	}
+	pci_dev_put(pci_dev);
  }
 static void ali_read_ac97regs(ali_t *codec, int secondary)
 {
@@ -2116,6 +2108,8 @@
 #ifdef CONFIG_PM
 	kfree(codec->image);
 #endif
+	pci_dev_put(codec->pci_m1533);
+	pci_dev_put(codec->pci_m7101);
 	kfree(codec);
 	return 0;
 }
@@ -2305,7 +2299,7 @@
 	codec->chregs.data.ainten = 0x00;
 
 	/* M1533: southbridge */
-       	pci_dev = pci_find_device(0x10b9, 0x1533, NULL);
+	pci_dev = pci_get_device(0x10b9, 0x1533, NULL);
 	codec->pci_m1533 = pci_dev;
 	if (! codec->pci_m1533) {
 		snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n");
@@ -2313,7 +2307,7 @@
 		return -ENODEV;
 	}
 	/* M7101: power management */
-       	pci_dev = pci_find_device(0x10b9, 0x7101, NULL);
+	pci_dev = pci_get_device(0x10b9, 0x7101, NULL);
 	codec->pci_m7101 = pci_dev;
 	if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
 		snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
@@ -2417,6 +2411,7 @@
 
 static struct pci_driver driver = {
 	.name = "ALI 5451",
+	.owner = THIS_MODULE,
 	.id_table = snd_ali_ids,
 	.probe = snd_ali_probe,
 	.remove = __devexit_p(snd_ali_remove),
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index ca28b22..196ec1c 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -770,6 +770,7 @@
 
 static struct pci_driver driver = {
 	.name = "ALS4000",
+	.owner = THIS_MODULE,
 	.id_table = snd_als4000_ids,
 	.probe = snd_card_als4000_probe,
 	.remove = __devexit_p(snd_card_als4000_remove),
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 188df08..241eacf 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1453,6 +1453,7 @@
 			atiixp_dma_t *dma = &chip->dmas[i];
 			if (dma->substream && dma->suspended) {
 				dma->ops->enable_dma(chip, 1);
+				dma->substream->ops->prepare(dma->substream);
 				writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN,
 				       chip->remap_addr + dma->ops->llp_offset);
 				writel(dma->saved_curptr, chip->remap_addr + dma->ops->dt_cur);
@@ -1530,7 +1531,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1644,6 +1645,7 @@
 
 static struct pci_driver driver = {
 	.name = "ATI IXP AC97 controller",
+	.owner = THIS_MODULE,
 	.id_table = snd_atiixp_ids,
 	.probe = snd_atiixp_probe,
 	.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 8d20029..8a59598 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1208,7 +1208,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1318,6 +1318,7 @@
 
 static struct pci_driver driver = {
 	.name = "ATI IXP MC97 controller",
+	.owner = THIS_MODULE,
 	.id_table = snd_atiixp_ids,
 	.probe = snd_atiixp_probe,
 	.remove = __devexit_p(snd_atiixp_remove),
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index f6236c6..04b695d 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -79,19 +79,21 @@
 
 static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
 {
-	struct pci_dev *via;
+	struct pci_dev *via = NULL;
 
 	/* autodetect if workarounds are required */
 	if (fix == 255) {
 		/* VIA KT133 */
-		via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL);
+		via = pci_get_device(PCI_VENDOR_ID_VIA,
+			PCI_DEVICE_ID_VIA_8365_1, NULL);
 		/* VIA Apollo */
 		if (via == NULL) {
-			via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL);
-		}
-		/* AMD Irongate */
-		if (via == NULL) {
-			via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
+			via = pci_get_device(PCI_VENDOR_ID_VIA,
+				PCI_DEVICE_ID_VIA_82C598_1, NULL);
+			/* AMD Irongate */
+			if (via == NULL)
+				via = pci_get_device(PCI_VENDOR_ID_AMD,
+					PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
 		}
 		if (via) {
 			printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n");
@@ -101,13 +103,17 @@
 	} else {
 		if (fix & 0x1)
 			vortex_fix_latency(vortex);
-		if ((fix & 0x2) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8365_1, NULL)))
+		if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+				PCI_DEVICE_ID_VIA_8365_1, NULL)))
 			vortex_fix_agp_bridge(via);
-		if ((fix & 0x4) && (via = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_1, NULL)))
+		if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+				PCI_DEVICE_ID_VIA_82C598_1, NULL)))
 			vortex_fix_agp_bridge(via);
-		if ((fix & 0x8) && (via = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
+		if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD,
+				PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
 			vortex_fix_agp_bridge(via);
 	}
+	pci_dev_put(via);
 }
 
 // component-destructor
@@ -150,7 +156,7 @@
 	}
 	pci_set_dma_mask(pci, VORTEX_DMA_MASK);
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -367,6 +373,7 @@
 // pci_driver definition
 static struct pci_driver driver = {
 	.name = CARD_NAME_SHORT,
+	.owner = THIS_MODULE,
 	.id_table = snd_vortex_ids,
 	.probe = snd_vortex_probe,
 	.remove = __devexit_p(snd_vortex_remove),
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 72bba7b..d5261bd 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1345,7 +1345,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1511,6 +1511,7 @@
 
 static struct pci_driver driver = {
 	.name = "AZF3328",
+	.owner = THIS_MODULE,
 	.id_table = snd_azf3328_ids,
 	.probe = snd_azf3328_probe,
 	.remove = __devexit_p(snd_azf3328_remove),
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index c5557ea..2236c95 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -59,16 +59,6 @@
 MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards");
 
 
-#ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_878
-#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
-#endif
-#ifndef PCI_DEVICE_ID_BROOKTREE_879
-#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
-#endif
-
 /* register offsets */
 #define REG_INT_STAT		0x100	/* interrupt status */
 #define REG_INT_MASK		0x104	/* interrupt mask */
@@ -720,7 +710,7 @@
 	if (err < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (!chip) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -911,6 +901,7 @@
 
 static struct pci_driver driver = {
 	.name = "Bt87x",
+	.owner = THIS_MODULE,
 	.id_table = snd_bt87x_ids,
 	.probe = snd_bt87x_probe,
 	.remove = __devexit_p(snd_bt87x_remove),
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 7e27bfc..ba07960 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -352,7 +352,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 
 	if (epcm == NULL)
 		return -ENOMEM;
@@ -419,7 +419,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL) {
                 snd_printk("open_capture_channel: failed epcm alloc\n");
 		return -ENOMEM;
@@ -1144,7 +1144,7 @@
 		return -ENXIO;
 	}
   
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1390,6 +1390,7 @@
 // pci_driver definition
 static struct pci_driver driver = {
 	.name = "CA0106",
+	.owner = THIS_MODULE,
 	.id_table = snd_ca0106_ids,
 	.probe = snd_ca0106_probe,
 	.remove = __devexit_p(snd_ca0106_remove),
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index b6b8882..c10e4a5 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -482,7 +482,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Front Volume",
+        .name =         "Analog Front Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_front,
         .put =          snd_ca0106_volume_put_analog_front
@@ -490,7 +490,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Center/LFE Volume",
+        .name =         "Analog Center/LFE Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_center_lfe,
         .put =          snd_ca0106_volume_put_analog_center_lfe
@@ -498,7 +498,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Side Volume",
+        .name =         "Analog Side Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_unknown,
         .put =          snd_ca0106_volume_put_analog_unknown
@@ -506,7 +506,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Rear Volume",
+        .name =         "Analog Rear Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_rear,
         .put =          snd_ca0106_volume_put_analog_rear
@@ -514,7 +514,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "SPDIF Front Volume",
+        .name =         "SPDIF Front Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_spdif_front,
         .put =          snd_ca0106_volume_put_spdif_front
@@ -522,7 +522,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "SPDIF Center/LFE Volume",
+        .name =         "SPDIF Center/LFE Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_spdif_center_lfe,
         .put =          snd_ca0106_volume_put_spdif_center_lfe
@@ -530,7 +530,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "SPDIF Unknown Volume",
+        .name =         "SPDIF Unknown Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_spdif_unknown,
         .put =          snd_ca0106_volume_put_spdif_unknown
@@ -538,7 +538,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "SPDIF Rear Volume",
+        .name =         "SPDIF Rear Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_spdif_rear,
         .put =          snd_ca0106_volume_put_spdif_rear
@@ -547,7 +547,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_feedback =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "CAPTURE feedback into PLAYBACK",
+        .name =         "CAPTURE feedback Playback Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_feedback,
         .put =          snd_ca0106_volume_put_feedback
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index b098b51..1eb3315 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -79,13 +79,6 @@
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
 #endif
 
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738	0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B	0x0112
-#endif
-
 /*
  * CM8x38 registers definition
  */
@@ -348,25 +341,6 @@
 
 
 /*
- * pci ids
- */
-#ifndef PCI_VENDOR_ID_CMEDIA
-#define PCI_VENDOR_ID_CMEDIA         0x13F6
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A
-#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B
-#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738
-#define PCI_DEVICE_ID_CMEDIA_CM8738  0x0111
-#endif
-#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B
-#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
-#endif
-
-/*
  * channels for playback / capture
  */
 #define CM_CH_PLAY	0
@@ -2801,7 +2775,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	cm = kcalloc(1, sizeof(*cm), GFP_KERNEL);
+	cm = kzalloc(sizeof(*cm), GFP_KERNEL);
 	if (cm == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -3063,6 +3037,7 @@
 
 static struct pci_driver driver = {
 	.name = "C-Media PCI",
+	.owner = THIS_MODULE,
 	.id_table = snd_cmipci_ids,
 	.probe = snd_cmipci_probe,
 	.remove = __devexit_p(snd_cmipci_remove),
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index c7a370d..dc87e01 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -57,17 +57,6 @@
 MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
 
 /*
- *
- */
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS            0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CIRRUS_4281
-#define PCI_DEVICE_ID_CIRRUS_4281	0x6005
-#endif
-
-/*
  *  Direct registers
  */
 
@@ -1394,7 +1383,7 @@
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2119,6 +2108,7 @@
 
 static struct pci_driver driver = {
 	.name = "CS4281",
+	.owner = THIS_MODULE,
 	.id_table = snd_cs4281_ids,
 	.probe = snd_cs4281_probe,
 	.remove = __devexit_p(snd_cs4281_remove),
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index b9fff4e..32b4f84 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -163,6 +163,7 @@
 
 static struct pci_driver driver = {
 	.name = "Sound Fusion CS46xx",
+	.owner = THIS_MODULE,
 	.id_table = snd_cs46xx_ids,
 	.probe = snd_card_cs46xx_probe,
 	.remove = __devexit_p(snd_card_cs46xx_remove),
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 4b05215..6e3855b 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1304,7 +1304,7 @@
 	cs46xx_pcm_t * cpcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
+	cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
 	if (cpcm == NULL)
 		return -ENOMEM;
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
@@ -3525,17 +3525,6 @@
 
 
 /*
- * piix4 pci ids
- */
-#ifndef PCI_VENDOR_ID_INTEL
-#define PCI_VENDOR_ID_INTEL 0x8086
-#endif /* PCI_VENDOR_ID_INTEL */
-
-#ifndef PCI_DEVICE_ID_INTEL_82371AB_3
-#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
-#endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */
-
-/*
  *	Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
  *	whenever we need to beat on the chip.
  *
@@ -3548,7 +3537,7 @@
 {
 	u16 control, nval;
 	
-	if (chip->acpi_dev == NULL)
+	if (!chip->acpi_port)
 		return;
 
 	chip->amplifier += change;
@@ -3571,15 +3560,20 @@
  */
 static void clkrun_init(cs46xx_t *chip)
 {
+	struct pci_dev *pdev;
 	u8 pp;
 
-	chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-	if (chip->acpi_dev == NULL)
+	chip->acpi_port = 0;
+	
+	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+		PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
+	if (pdev == NULL)
 		return;		/* Not a thinkpad thats for sure */
 
 	/* Find the control port */		
-	pci_read_config_byte(chip->acpi_dev, 0x41, &pp);
+	pci_read_config_byte(pdev, 0x41, &pp);
 	chip->acpi_port = pp << 8;
+	pci_dev_put(pdev);
 }
 
 
@@ -3780,7 +3774,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index fc377c4..b0e00f0 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -223,6 +223,7 @@
 
 static struct pci_driver driver = {
 	.name = "EMU10K1_Audigy",
+	.owner = THIS_MODULE,
 	.id_table = snd_emu10k1_ids,
 	.probe = snd_card_emu10k1_probe,
 	.remove = __devexit_p(snd_card_emu10k1_remove),
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index e69d5b7..e87e842 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -754,12 +754,11 @@
 	 .emu10k1_chip = 1,
 	 .ac97_chip = 1,
 	 .sblive51 = 1} ,
-	/* Tested by alsa bugtrack user "hus" 12th Sept 2005 */
+	/* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
 	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
-	 .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", 
+	 .driver = "EMU10K1", .name = "SBLive! Platinum 5.1 [SB0060]", 
 	 .id = "Live",
 	 .emu10k1_chip = 1,
-	 .ac97_chip = 1,
 	 .sblive51 = 1} ,
 	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
 	 .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", 
@@ -865,7 +864,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+	emu = kzalloc(sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 52c7826..ad15755 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -395,7 +395,7 @@
 	if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
                 return err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = chip;
@@ -571,7 +571,7 @@
 	if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
                 return err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 
@@ -920,7 +920,7 @@
 		return -ENXIO;
 	}
   
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1615,6 +1615,7 @@
 // pci_driver definition
 static struct pci_driver driver = {
 	.name = "EMU10K1X",
+	.owner = THIS_MODULE,
 	.id_table = snd_emu10k1x_ids,
 	.probe = snd_emu10k1x_probe,
 	.remove = __devexit_p(snd_emu10k1x_remove),
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 637c555..646b5d9 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -470,7 +470,7 @@
 {
 	u_int32_t *code;
 	snd_assert(*ptr < 512, return);
-	code = (u_int32_t *)icode->code + (*ptr) * 2;
+	code = (u_int32_t __force *)icode->code + (*ptr) * 2;
 	set_bit(*ptr, icode->code_valid);
 	code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
 	code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
@@ -485,7 +485,7 @@
 {
 	u_int32_t *code;
 	snd_assert(*ptr < 1024, return);
-	code = (u_int32_t *)icode->code + (*ptr) * 2;
+	code = (u_int32_t __force *)icode->code + (*ptr) * 2;
 	set_bit(*ptr, icode->code_valid);
 	code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
 	code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
@@ -1036,13 +1036,13 @@
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
+	if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
 	    (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
 	    (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
 		err = -ENOMEM;
 		goto __err;
 	}
-	gpr_map = (u32 *)icode->gpr_map;
+	gpr_map = (u32 __force *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 512;
 	icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1431,7 +1431,7 @@
  __err:
 	kfree(controls);
 	if (icode != NULL) {
-		kfree((void *)icode->gpr_map);
+		kfree((void __force *)icode->gpr_map);
 		kfree(icode);
 	}
 	return err;
@@ -1503,15 +1503,15 @@
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
+	if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
             (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
-	    (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
+	    (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
 		err = -ENOMEM;
 		goto __err;
 	}
-	gpr_map = (u32 *)icode->gpr_map;
+	gpr_map = (u32 __force *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 256;
 	icode->tram_addr_map = icode->tram_data_map + 160;
@@ -2032,7 +2032,7 @@
 	kfree(ipcm);
 	kfree(controls);
 	if (icode != NULL) {
-		kfree((void *)icode->gpr_map);
+		kfree((void __force *)icode->gpr_map);
 		kfree(icode);
 	}
 	return err;
@@ -2217,7 +2217,7 @@
 		kfree(ipcm);
 		return res;
 	case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
-		ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
+		ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
 		if (ipcm == NULL)
 			return -ENOMEM;
 		if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 9c35f6d..66ba27a 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1016,7 +1016,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int i;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -1049,7 +1049,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int i, err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -1094,7 +1094,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	emu10k1_pcm_t *epcm;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -1130,7 +1130,7 @@
 	emu10k1_pcm_t *epcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -1170,7 +1170,7 @@
 	int nefx = emu->audigy ? 64 : 32;
 	int idx;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index a169133..d59c7f3 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -178,7 +178,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
         //snd_printk("epcm kcalloc: %p\n", epcm);
 
 	if (epcm == NULL)
@@ -214,7 +214,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
 	//snd_printk("epcm kcalloc: %p\n", epcm);
 
 	if (epcm == NULL)
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index f06b95f..bef9a59 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -100,13 +100,6 @@
 #endif
 #endif /* SUPPORT_JOYSTICK */
 
-#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
-#define PCI_DEVICE_ID_ENSONIQ_CT5880    0x5880
-#endif
-#ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
-#define PCI_DEVICE_ID_ENSONIQ_ES1371	0x1371
-#endif
-
 /* ES1371 chip ID */
 /* This is a little confusing because all ES1371 compatible chips have the
    same DEVICE_ID, the only thing differentiating them is the REV_ID field.
@@ -1950,7 +1943,7 @@
 	*rensoniq = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
+	ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL);
 	if (ensoniq == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2394,6 +2387,7 @@
 
 static struct pci_driver driver = {
 	.name = DRIVER_NAME,
+	.owner = THIS_MODULE,
 	.id_table = snd_audiopci_ids,
 	.probe = snd_audiopci_probe,
 	.remove = __devexit_p(snd_audiopci_remove),
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index b492777..17fa80c 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -76,13 +76,6 @@
 #define SUPPORT_JOYSTICK 1
 #endif
 
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS		0x125d
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ES1938
-#define PCI_DEVICE_ID_ESS_ES1938	0x1969
-#endif
-
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
@@ -1501,7 +1494,7 @@
                 return -ENXIO;
         }
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1753,6 +1746,7 @@
 
 static struct pci_driver driver = {
 	.name = "ESS ES1938 (Solo-1)",
+	.owner = THIS_MODULE,
 	.id_table = snd_es1938_ids,
 	.probe = snd_es1938_probe,
 	.remove = __devexit_p(snd_es1938_remove),
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 9d7a287..ecdcada 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -160,25 +160,6 @@
 #endif
 
 
-/* PCI Dev ID's */
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS	0x125D
-#endif
-
-#define PCI_VENDOR_ID_ESS_OLD	0x1285	/* Platform Tech, the people the ESS
-					   was bought form */
-
-#ifndef PCI_DEVICE_ID_ESS_M2E
-#define PCI_DEVICE_ID_ESS_M2E	0x1978
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M2
-#define PCI_DEVICE_ID_ESS_M2	0x1968
-#endif
-#ifndef PCI_DEVICE_ID_ESS_M1
-#define PCI_DEVICE_ID_ESS_M1	0x0100
-#endif
-
 #define NR_APUS			64
 #define NR_APU_REGS		16
 
@@ -1596,7 +1577,7 @@
 	if (apu1 < 0)
 		return apu1;
 
-	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+	es = kzalloc(sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		return -ENOMEM;
@@ -1641,7 +1622,7 @@
 		return apu2;
 	}
 	
-	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
+	es = kzalloc(sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		snd_es1968_free_apu_pair(chip, apu2);
@@ -2588,7 +2569,7 @@
 		return -ENXIO;
 	}
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2782,6 +2763,7 @@
 
 static struct pci_driver driver = {
 	.name = "ES1968 (ESS Maestro)",
+	.owner = THIS_MODULE,
 	.id_table = snd_es1968_ids,
 	.probe = snd_es1968_probe,
 	.remove = __devexit_p(snd_es1968_remove),
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 36b2f62..e5cfa2a 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1263,7 +1263,7 @@
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1462,6 +1462,7 @@
 
 static struct pci_driver driver = {
 	.name = "FM801",
+	.owner = THIS_MODULE,
 	.id_table = snd_fm801_ids,
 	.probe = snd_card_fm801_probe,
 	.remove = __devexit_p(snd_card_fm801_remove),
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 20f7762..3815403 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -288,7 +288,7 @@
 {
 	struct hda_bus_unsolicited *unsol;
 
-	unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL);
+	unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
 	if (! unsol) {
 		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
 		return -ENOMEM;
@@ -358,7 +358,7 @@
 	if (busp)
 		*busp = NULL;
 
-	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL) {
 		snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
 		return -ENOMEM;
@@ -493,7 +493,7 @@
 		return -EBUSY;
 	}
 
-	codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
 	if (codec == NULL) {
 		snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
 		return -ENOMEM;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 63a29a8..bb53bcf 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -505,6 +505,7 @@
 struct hda_pcm {
 	char *name;
 	struct hda_pcm_stream stream[2];
+	unsigned int is_modem;	/* modem codec? */
 };
 
 /* codec information */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 1229227..5b829a1 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -98,7 +98,7 @@
 	struct hda_gnode *node;
 	int nconns;
 
-	node = kcalloc(1, sizeof(*node), GFP_KERNEL);
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
 	if (node == NULL)
 		return -ENOMEM;
 	node->nid = nid;
@@ -886,7 +886,7 @@
 		return -ENODEV;
 	}
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL) {
 		printk(KERN_ERR "hda_generic: can't allocate spec\n");
 		return -ENOMEM;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 15107df..9590ece 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -62,7 +62,7 @@
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
 
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
@@ -164,7 +164,9 @@
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE	(1024*1024*1024)
 /* max number of PCM devics per card */
-#define AZX_MAX_PCMS		8
+#define AZX_MAX_AUDIO_PCMS	6
+#define AZX_MAX_MODEM_PCMS	2
+#define AZX_MAX_PCMS		(AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE	0x01
@@ -211,9 +213,10 @@
 
 /* position fix mode */
 enum {
-	POS_FIX_FIFO,
+	POS_FIX_AUTO,
 	POS_FIX_NONE,
-	POS_FIX_POSBUF
+	POS_FIX_POSBUF,
+	POS_FIX_FIFO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -243,6 +246,7 @@
 	unsigned int fragsize;		/* size of each period in bytes */
 	unsigned int frags;		/* number for period in the play buffer */
 	unsigned int fifo_size;		/* FIFO size */
+	unsigned int last_pos;		/* last updated period position */
 
 	void __iomem *sd_addr;		/* stream descriptor pointer */
 
@@ -256,6 +260,7 @@
 
 	unsigned int opened: 1;
 	unsigned int running: 1;
+	unsigned int period_updating: 1;
 };
 
 /* CORB/RIRB */
@@ -724,11 +729,9 @@
 	/* initialize the codec command I/O */
 	azx_init_cmd_io(chip);
 
-	if (chip->position_fix == POS_FIX_POSBUF) {
-		/* program the position buffer */
-		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
-		azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
-	}
+	/* program the position buffer */
+	azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+	azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
 
 	/* For ATI SB450 azalia HD audio, we need to enable snoop */
 	if (chip->driver_type == AZX_DRIVER_ATI) {
@@ -763,9 +766,11 @@
 		if (status & azx_dev->sd_int_sta_mask) {
 			azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
 			if (azx_dev->substream && azx_dev->running) {
+				azx_dev->period_updating = 1;
 				spin_unlock(&chip->reg_lock);
 				snd_pcm_period_elapsed(azx_dev->substream);
 				spin_lock(&chip->reg_lock);
+				azx_dev->period_updating = 0;
 			}
 		}
 	}
@@ -866,11 +871,9 @@
 	/* upper BDL address */
 	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
 
-	if (chip->position_fix == POS_FIX_POSBUF) {
-		/* enable the position buffer */
-		if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
-			azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
-	}
+	/* enable the position buffer */
+	if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
 
 	/* set the interrupt enable bits in the descriptor control register */
 	azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1078,6 +1081,7 @@
 		azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
 	else
 		azx_dev->fifo_size = 0;
+	azx_dev->last_pos = 0;
 
 	return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
 				  azx_dev->format_val, substream);
@@ -1133,6 +1137,26 @@
 		pos = azx_sd_readl(azx_dev, SD_LPIB);
 		if (chip->position_fix == POS_FIX_FIFO)
 			pos += azx_dev->fifo_size;
+		else if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_updating) {
+			/* check the validity of DMA position */
+			unsigned int diff = 0;
+			azx_dev->last_pos += azx_dev->fragsize;
+			if (azx_dev->last_pos > pos)
+				diff = azx_dev->last_pos - pos;
+			if (azx_dev->last_pos >= azx_dev->bufsize) {
+				if (pos < azx_dev->fragsize)
+					diff = 0;
+				azx_dev->last_pos = 0;
+			}
+			if (diff > 0 && diff <= azx_dev->fifo_size)
+				pos += azx_dev->fifo_size;
+			else {
+				snd_printdd(KERN_INFO "hda_intel: DMA position fix %d, switching to posbuf\n", diff);
+				chip->position_fix = POS_FIX_POSBUF;
+				pos = *azx_dev->posbuf;
+			}
+			azx_dev->period_updating = 0;
+		}
 	}
 	if (pos >= azx_dev->bufsize)
 		pos = 0;
@@ -1203,12 +1227,33 @@
 	if ((err = snd_hda_build_pcms(chip->bus)) < 0)
 		return err;
 
+	/* create audio PCMs */
 	pcm_dev = 0;
 	list_for_each(p, &chip->bus->codec_list) {
 		codec = list_entry(p, struct hda_codec, list);
 		for (c = 0; c < codec->num_pcms; c++) {
+			if (codec->pcm_info[c].is_modem)
+				continue; /* create later */
+			if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
+				snd_printk(KERN_ERR SFX "Too many audio PCMs\n");
+				return -EINVAL;
+			}
+			err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+			if (err < 0)
+				return err;
+			pcm_dev++;
+		}
+	}
+
+	/* create modem PCMs */
+	pcm_dev = AZX_MAX_AUDIO_PCMS;
+	list_for_each(p, &chip->bus->codec_list) {
+		codec = list_entry(p, struct hda_codec, list);
+		for (c = 0; c < codec->num_pcms; c++) {
+			if (! codec->pcm_info[c].is_modem)
+				continue; /* already created */
 			if (pcm_dev >= AZX_MAX_PCMS) {
-				snd_printk(KERN_ERR SFX "Too many PCMs\n");
+				snd_printk(KERN_ERR SFX "Too many modem PCMs\n");
 				return -EINVAL;
 			}
 			err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
@@ -1244,8 +1289,7 @@
 		azx_dev_t *azx_dev = &chip->azx_dev[i];
 		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
 		azx_dev->bdl_addr = chip->bdl.addr + off;
-		if (chip->position_fix == POS_FIX_POSBUF)
-			azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+		azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
 		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
 		/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1358,7 +1402,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	
 	if (NULL == chip) {
 		snd_printk(KERN_ERR SFX "cannot allocate chip\n");
@@ -1437,13 +1481,11 @@
 		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
 		goto errout;
 	}
-	if (chip->position_fix == POS_FIX_POSBUF) {
-		/* allocate memory for the position buffer */
-		if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
-					       chip->num_streams * 8, &chip->posbuf)) < 0) {
-			snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
-			goto errout;
-		}
+	/* allocate memory for the position buffer */
+	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				       chip->num_streams * 8, &chip->posbuf)) < 0) {
+		snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+		goto errout;
 	}
 	/* allocate CORB/RIRB */
 	if ((err = azx_alloc_cmd_io(chip)) < 0)
@@ -1561,6 +1603,7 @@
 /* pci_driver definition */
 static struct pci_driver driver = {
 	.name = "HDA Intel",
+	.owner = THIS_MODULE,
 	.id_table = azx_ids,
 	.probe = azx_probe,
 	.remove = __devexit_p(azx_remove),
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index de1217b..08f6a6e 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -207,6 +207,8 @@
 	snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
 	snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+	if (! codec->afg)
+		return;
 	snd_iprintf(buffer, "Default PCM: ");
 	print_pcm_caps(buffer, codec, codec->afg);
 	snd_iprintf(buffer, "Default Amp-In caps: ");
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index bceb83a..da6874d 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -465,7 +465,7 @@
 {
 	struct ad198x_spec *spec;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -623,7 +623,7 @@
 {
 	struct ad198x_spec *spec;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -764,7 +764,7 @@
 {
 	struct ad198x_spec *spec;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 07fb4f5..523c362 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -667,7 +667,7 @@
 {
 	struct cmi_spec *spec;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eeb900a..849b5b5 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1526,6 +1526,7 @@
 	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
 	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
 	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 
+	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
 
 	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
 	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
@@ -1581,6 +1582,7 @@
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
@@ -2093,7 +2095,7 @@
 	int board_config;
 	int i, err;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -2365,7 +2367,7 @@
 	struct alc_spec *spec;
 	int board_config;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -2615,7 +2617,7 @@
 {
 	struct alc_spec *spec;
 
-	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index b0270d1..d014b7b 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -214,6 +214,7 @@
 	info->name = "Si3054 Modem";
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
 	info->stream[SNDRV_PCM_STREAM_CAPTURE]  = si3054_pcm;
+	info->is_modem = 1;
 	return 0;
 }
 
@@ -282,7 +283,7 @@
 
 static int patch_si3054(struct hda_codec *codec)
 {
-	struct si3054_spec *spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	struct si3054_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 	codec->spec = spec;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9d503da..33a8ada 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -919,7 +919,7 @@
 	struct sigmatel_spec *spec;
 	int err;
 
-	spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
@@ -957,7 +957,7 @@
 	struct sigmatel_spec *spec;
 	int err;
 
-	spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	spec  = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 4405d96..2e0a316 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1796,7 +1796,7 @@
 	}
 
 	/* to remeber the register values of CS8415 */
-	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ice->akm)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index b97f50d..a6d9801 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -100,12 +100,6 @@
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE		0x1412
-#endif
-#ifndef PCI_DEVICE_ID_ICE_1712
-#define PCI_DEVICE_ID_ICE_1712		0x1712
-#endif
 
 static struct pci_device_id snd_ice1712_ids[] = {
 	{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },   /* ICE1712 */
@@ -2535,7 +2529,7 @@
 		return -ENXIO;
 	}
 
-	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+	ice = kzalloc(sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2741,6 +2735,7 @@
 
 static struct pci_driver driver = {
 	.name = "ICE1712",
+	.owner = THIS_MODULE,
 	.id_table = snd_ice1712_ids,
 	.probe = snd_ice1712_probe,
 	.remove = __devexit_p(snd_ice1712_remove),
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index c7af5e5..c3ce8f9 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -83,12 +83,6 @@
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
-#ifndef PCI_VENDOR_ID_ICE
-#define PCI_VENDOR_ID_ICE		0x1412
-#endif
-#ifndef PCI_DEVICE_ID_VT1724
-#define PCI_DEVICE_ID_VT1724		0x1724
-#endif
 
 /* Both VT1720 and VT1724 have the same PCI IDs */
 static struct pci_device_id snd_vt1724_ids[] = {
@@ -2130,7 +2124,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
+	ice = kzalloc(sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2321,6 +2315,7 @@
 
 static struct pci_driver driver = {
 	.name = "ICE1724",
+	.owner = THIS_MODULE,
 	.id_table = snd_vt1724_ids,
 	.probe = snd_vt1724_probe,
 	.remove = __devexit_p(snd_vt1724_remove),
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 3fb297b..2437876 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -182,7 +182,7 @@
 		ice->num_total_dacs = 2;
 		ice->num_total_adcs = 2;
 
-		ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+		ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
 		if (! ak)
 			return -ENOMEM;
 		ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index 5bf734b..dcf1e8c 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -122,7 +122,7 @@
 	}
 
 	// Initialize analog chips
-	ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ak)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
@@ -386,7 +386,7 @@
 	ice->num_total_adcs = 2;
 
 	// Initialize analog chips
-	ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
 	if (!ak)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 25f827d..a5f852b 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -781,7 +781,7 @@
 	ice->num_total_adcs = 2;
 
 	/* to remeber the register values */
-	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ice->akm)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 7b54841..1a96198 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -69,6 +69,7 @@
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
 static char *ac97_quirk[SNDRV_CARDS];
+static int buggy_semaphore[SNDRV_CARDS];
 static int buggy_irq[SNDRV_CARDS];
 static int xbox[SNDRV_CARDS];
 
@@ -86,6 +87,8 @@
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
 module_param_array(ac97_quirk, charp, NULL, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
+module_param_array(buggy_semaphore, bool, NULL, 0444);
+MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores.");
 module_param_array(buggy_irq, bool, NULL, 0444);
 MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
 module_param_array(xbox, bool, NULL, 0444);
@@ -94,62 +97,6 @@
 /*
  *  Direct registers
  */
-
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801       0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901       0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA
-#define PCI_DEVICE_ID_INTEL_82801BA     0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX       0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3	0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4	0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5	0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
-#define PCI_DEVICE_ID_INTEL_ICH6_18	0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
-#define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB2_14
-#define PCI_DEVICE_ID_INTEL_ESB2_14	0x2698
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012		0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO	0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO	0x008a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO	0x00ea
-#endif
-
 enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
 #define ICHREG(x) ICH_REG_##x
@@ -423,6 +370,7 @@
 	unsigned fix_nocache: 1; 	/* workaround for 440MX */
 	unsigned buggy_irq: 1;		/* workaround for buggy mobos */
 	unsigned xbox: 1;		/* workaround for Xbox AC'97 detection */
+	unsigned buggy_semaphore: 1;	/* workaround for buggy codec semaphore */
 
 	int spdif_idx;	/* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
 	unsigned int sdm_saved;	/* SDM reg value */
@@ -577,6 +525,9 @@
 	if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0)
 		return -EIO;
 
+	if (chip->buggy_semaphore)
+		return 0; /* just ignore ... */
+
 	/* Anyone holding a semaphore for 1 msec should be shot... */
 	time = 100;
       	do {
@@ -1759,6 +1710,12 @@
 		.type = AC97_TUNE_ALC_JACK
 	},
 	{
+		.subvendor = 0x1014,
+		.subdevice = 0x0267,
+		.name = "IBM NetVista A30p",	/* AD1981B */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.subvendor = 0x1028,
 		.subdevice = 0x00d8,
 		.name = "Dell Precision 530",	/* AD1885 */
@@ -2599,6 +2556,7 @@
 static int __devinit snd_intel8x0_create(snd_card_t * card,
 					 struct pci_dev *pci,
 					 unsigned long device_type,
+					 int buggy_sem,
 					 intel8x0_t ** r_intel8x0)
 {
 	intel8x0_t *chip;
@@ -2646,7 +2604,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2656,6 +2614,7 @@
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
+	chip->buggy_semaphore = buggy_sem;
 
 	if (pci->vendor == PCI_VENDOR_ID_INTEL &&
 	    pci->device == PCI_DEVICE_ID_INTEL_440MX)
@@ -2795,19 +2754,19 @@
 	unsigned int id;
 	const char *s;
 } shortnames[] __devinitdata = {
-	{ PCI_DEVICE_ID_INTEL_82801, "Intel 82801AA-ICH" },
-	{ PCI_DEVICE_ID_INTEL_82901, "Intel 82901AB-ICH0" },
-	{ PCI_DEVICE_ID_INTEL_82801BA, "Intel 82801BA-ICH2" },
+	{ PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
+	{ PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
+	{ PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
 	{ PCI_DEVICE_ID_INTEL_440MX, "Intel 440MX" },
-	{ PCI_DEVICE_ID_INTEL_ICH3, "Intel 82801CA-ICH3" },
-	{ PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
-	{ PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
+	{ PCI_DEVICE_ID_INTEL_82801CA_5, "Intel 82801CA-ICH3" },
+	{ PCI_DEVICE_ID_INTEL_82801DB_5, "Intel 82801DB-ICH4" },
+	{ PCI_DEVICE_ID_INTEL_82801EB_5, "Intel ICH5" },
 	{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
 	{ PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
 	{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
 	{ PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" },
 	{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, "NVidia nForce" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
 	{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
@@ -2860,7 +2819,8 @@
 		}
 	}
 
-	if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip)) < 0) {
+	if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
+				       buggy_semaphore[dev], &chip)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -2904,6 +2864,7 @@
 
 static struct pci_driver driver = {
 	.name = "Intel ICH",
+	.owner = THIS_MODULE,
 	.id_table = snd_intel8x0_ids,
 	.probe = snd_intel8x0_probe,
 	.remove = __devexit_p(snd_intel8x0_remove),
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index bb758c7..9e2060d 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -73,51 +73,6 @@
 /*
  *  Direct registers
  */
-
-#ifndef PCI_DEVICE_ID_INTEL_82801_6
-#define PCI_DEVICE_ID_INTEL_82801_6     0x2416
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901_6
-#define PCI_DEVICE_ID_INTEL_82901_6     0x2426
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA_6
-#define PCI_DEVICE_ID_INTEL_82801BA_6   0x2446
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX_6
-#define PCI_DEVICE_ID_INTEL_440MX_6     0x7196
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3_6
-#define PCI_DEVICE_ID_INTEL_ICH3_6	0x2486
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4_6
-#define PCI_DEVICE_ID_INTEL_ICH4_6	0x24c6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5_6
-#define PCI_DEVICE_ID_INTEL_ICH5_6	0x24d6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_6
-#define PCI_DEVICE_ID_INTEL_ICH6_6	0x266d
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_6
-#define PCI_DEVICE_ID_INTEL_ICH7_6	0x27dd
-#endif
-#ifndef PCI_DEVICE_ID_SI_7013
-#define PCI_DEVICE_ID_SI_7013		0x7013
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP_MODEM	0x01c1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM	0x0069
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
-#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM	0x00d9
-#endif
-
-
 enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
 #define ICHREG(x) ICH_REG_##x
@@ -1158,7 +1113,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1283,18 +1238,18 @@
 	unsigned int id;
 	const char *s;
 } shortnames[] __devinitdata = {
-	{ PCI_DEVICE_ID_INTEL_82801_6, "Intel 82801AA-ICH" },
-	{ PCI_DEVICE_ID_INTEL_82901_6, "Intel 82901AB-ICH0" },
+	{ PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },
+	{ PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },
 	{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },
 	{ PCI_DEVICE_ID_INTEL_440MX_6, "Intel 440MX" },
-	{ PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" },
-	{ PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
-	{ PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
-	{ PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" },
-	{ PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" },
+	{ PCI_DEVICE_ID_INTEL_82801CA_6, "Intel 82801CA-ICH3" },
+	{ PCI_DEVICE_ID_INTEL_82801DB_6, "Intel 82801DB-ICH4" },
+	{ PCI_DEVICE_ID_INTEL_82801EB_6, "Intel ICH5" },
+	{ PCI_DEVICE_ID_INTEL_ICH6_17, "Intel ICH6" },
+	{ PCI_DEVICE_ID_INTEL_ICH7_19, "Intel ICH7" },
 	{ 0x7446, "AMD AMD768" },
 	{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP1_MODEM, "NVidia nForce" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
@@ -1371,6 +1326,7 @@
 
 static struct pci_driver driver = {
 	.name = "Intel ICH Modem",
+	.owner = THIS_MODULE,
 	.id_table = snd_intel8x0m_ids,
 	.probe = snd_intel8x0m_probe,
 	.remove = __devexit_p(snd_intel8x0m_remove),
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index d2aa9c8..09f9cbe 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2220,7 +2220,7 @@
         if ((err = pci_enable_device(pci)) < 0)
                 return err;
 
-        korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL);
+        korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL);
         if (korg1212 == NULL) {
 		pci_disable_device(pci);
                 return -ENOMEM;
@@ -2534,6 +2534,7 @@
 
 static struct pci_driver driver = {
 	.name = "korg1212",
+	.owner = THIS_MODULE,
 	.id_table = snd_korg1212_ids,
 	.probe = snd_korg1212_probe,
 	.remove = __devexit_p(snd_korg1212_remove),
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 39b5e7d..2693b6f 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -872,35 +872,6 @@
 /*
  * pci ids
  */
-
-#ifndef PCI_VENDOR_ID_ESS
-#define PCI_VENDOR_ID_ESS         0x125D
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO_1
-#define PCI_DEVICE_ID_ESS_ALLEGRO_1	0x1988
-#endif
-#ifndef PCI_DEVICE_ID_ESS_ALLEGRO
-#define PCI_DEVICE_ID_ESS_ALLEGRO	0x1989
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2LE
-#define PCI_DEVICE_ID_ESS_CANYON3D_2LE	0x1990
-#endif
-#ifndef PCI_DEVICE_ID_ESS_CANYON3D_2
-#define PCI_DEVICE_ID_ESS_CANYON3D_2	0x1992
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3
-#define PCI_DEVICE_ID_ESS_MAESTRO3	0x1998
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_1
-#define PCI_DEVICE_ID_ESS_MAESTRO3_1	0x1999
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_HW
-#define PCI_DEVICE_ID_ESS_MAESTRO3_HW	0x199a
-#endif
-#ifndef PCI_DEVICE_ID_ESS_MAESTRO3_2
-#define PCI_DEVICE_ID_ESS_MAESTRO3_2	0x199b
-#endif
-
 static struct pci_device_id snd_m3_ids[] = {
 	{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
 	 PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
@@ -2689,7 +2660,7 @@
 		return -ENXIO;
 	}
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -2890,6 +2861,7 @@
 
 static struct pci_driver driver = {
 	.name = "Maestro3",
+	.owner = THIS_MODULE,
 	.id_table = snd_m3_ids,
 	.probe = snd_m3_probe,
 	.remove = __devexit_p(snd_m3_remove),
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 6c868d9..1a62c7f 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1004,7 +1004,7 @@
 		.dev_free = snd_mixart_chip_dev_free,
 	};
 
-	mgr->chip[idx] = chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "cannot allocate chip\n");
 		return -ENOMEM;
@@ -1292,7 +1292,7 @@
 
 	/*
 	 */
-	mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL);
+	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
 	if (! mgr) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1424,6 +1424,7 @@
 
 static struct pci_driver driver = {
 	.name = "Digigram miXart",
+	.owner = THIS_MODULE,
 	.id_table = snd_mixart_ids,
 	.probe = snd_mixart_probe,
 	.remove = __devexit_p(snd_mixart_remove),
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 2bbeb10..5c55a3b 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -259,21 +259,6 @@
 /*
  * PCI ids
  */
-
-#ifndef PCI_VENDOR_ID_NEOMAGIC
-#define PCI_VENDOR_ID_NEOMEGIC 0x10c8
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
-#endif
-#ifndef PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO
-#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-#endif
-
-
 static struct pci_device_id snd_nm256_ids[] = {
 	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -840,7 +825,7 @@
 	runtime->hw = *hw_ptr;
 	runtime->hw.buffer_bytes_max = s->bufsize;
 	runtime->hw.period_bytes_max = s->bufsize / 2;
-	runtime->dma_area = (void*) s->bufptr;
+	runtime->dma_area = (void __force *) s->bufptr;
 	runtime->dma_addr = s->bufptr_addr;
 	runtime->dma_bytes = s->bufsize;
 	runtime->private_data = s;
@@ -1404,7 +1389,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1683,6 +1668,7 @@
 
 static struct pci_driver driver = {
 	.name = "NeoMagic 256",
+	.owner = THIS_MODULE,
 	.id_table = snd_nm256_ids,
 	.probe = snd_nm256_probe,
 	.remove = __devexit_p(snd_nm256_remove),
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 456be39..3daeecb 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -192,20 +192,6 @@
 #define RME32_PRO_REVISION_WITH_8414 150
 
 
-/* PCI vendor/device ID's */
-#ifndef PCI_VENDOR_ID_XILINX_RME
-# define PCI_VENDOR_ID_XILINX_RME 0xea60
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32
-# define PCI_DEVICE_ID_DIGI32 0x9896
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_PRO
-# define PCI_DEVICE_ID_DIGI32_PRO 0x9897
-#endif
-#ifndef PCI_DEVICE_ID_DIGI32_8
-# define PCI_DEVICE_ID_DIGI32_8 0x9898
-#endif
-
 typedef struct snd_rme32 {
 	spinlock_t lock;
 	int irq;
@@ -692,7 +678,8 @@
 		if (err < 0)
 			return err;
 	} else {
-		runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+		runtime->dma_area = (void __force *)(rme32->iobase +
+						     RME32_IO_DATA_BUFFER);
 		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
 		runtime->dma_bytes = RME32_BUFFER_SIZE;
 	}
@@ -746,7 +733,8 @@
 		if (err < 0)
 			return err;
 	} else {
-		runtime->dma_area = (void *)rme32->iobase + RME32_IO_DATA_BUFFER;
+		runtime->dma_area = (void __force *)rme32->iobase +
+					RME32_IO_DATA_BUFFER;
 		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
 		runtime->dma_bytes = RME32_BUFFER_SIZE;
 	}
@@ -2024,6 +2012,7 @@
 
 static struct pci_driver driver = {
 	.name =		"RME Digi32",
+	.owner =	THIS_MODULE,
 	.id_table =	snd_rme32_ids,
 	.probe =	snd_rme32_probe,
 	.remove =	__devexit_p(snd_rme32_remove),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 9645e90..9983b66 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -200,25 +200,6 @@
 #define RME96_AD1852_VOL_BITS 14
 #define RME96_AD1855_VOL_BITS 10
 
-/*
- * PCI vendor/device ids, could in the future be defined in <linux/pci.h>,
- * therefore #ifndef is used.
- */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX 0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96
-#define PCI_DEVICE_ID_DIGI96 0x3fc0
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8
-#define PCI_DEVICE_ID_DIGI96_8 0x3fc1
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PRO
-#define PCI_DEVICE_ID_DIGI96_8_PRO 0x3fc2
-#endif
-#ifndef PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST
-#define PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST 0x3fc3
-#endif
 
 typedef struct snd_rme96 {
 	spinlock_t    lock;
@@ -985,7 +966,8 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, rate, dummy;
 
-	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+	runtime->dma_area = (void __force *)(rme96->iobase +
+					     RME96_IO_PLAY_BUFFER);
 	runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
 	runtime->dma_bytes = RME96_BUFFER_SIZE;
 
@@ -1037,7 +1019,8 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, isadat, rate;
 	
-	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+	runtime->dma_area = (void __force *)(rme96->iobase +
+					     RME96_IO_REC_BUFFER);
 	runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
 	runtime->dma_bytes = RME96_BUFFER_SIZE;
 
@@ -2430,6 +2413,7 @@
 
 static struct pci_driver driver = {
 	.name = "RME Digi96",
+	.owner = THIS_MODULE,
 	.id_table = snd_rme96_ids,
 	.probe = snd_rme96_probe,
 	.remove = __devexit_p(snd_rme96_remove),
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 6694866..52525eb 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -370,13 +370,6 @@
 #define UNITY_GAIN                       32768
 #define MINUS_INFINITY_GAIN              0
 
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX		0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-
 /* the size of a substream (1 mono data stream) */
 
 #define HDSP_CHANNEL_BUFFER_SAMPLES  (16*1024)
@@ -4899,6 +4892,7 @@
 	}
 	
 	if (!(hdsp->state & HDSP_InitializationComplete)) {
+		strcpy(card->shortname, "Hammerfall DSP");
 		sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, 
 			hdsp->port, hdsp->irq);
 	    
@@ -5222,6 +5216,7 @@
 
 static struct pci_driver driver = {
 	.name =     "RME Hammerfall DSP",
+	.owner =    THIS_MODULE,
 	.id_table = snd_hdsp_ids,
 	.probe =    snd_hdsp_probe,
 	.remove = __devexit_p(snd_hdsp_remove),
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 5d786d1..fc3f328 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -301,18 +301,6 @@
 #define UNITY_GAIN          32768	/* = 65536/2 */
 #define MINUS_INFINITY_GAIN 0
 
-/* PCI info */
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX		0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-#endif
-
-
 /* Number of channels for different Speed Modes */
 #define MADI_SS_CHANNELS       64
 #define MADI_DS_CHANNELS       32
@@ -3652,6 +3640,7 @@
 
 static struct pci_driver driver = {
 	.name = "RME Hammerfall DSP MADI",
+	.owner = THIS_MODULE,
 	.id_table = snd_hdspm_ids,
 	.probe = snd_hdspm_probe,
 	.remove = __devexit_p(snd_hdspm_remove),
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 8ee4d6f..b600f45 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -120,13 +120,6 @@
 
 #define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos))
 
-#ifndef PCI_VENDOR_ID_XILINX
-#define PCI_VENDOR_ID_XILINX		0x10ee
-#endif
-#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL
-#define PCI_DEVICE_ID_XILINX_HAMMERFALL	0x3fc4
-#endif
-
 /* amount of io space we remap for register access. i'm not sure we
    even need this much, but 1K is nice round number :)
 */
@@ -2661,6 +2654,7 @@
 
 static struct pci_driver driver = {
 	.name	  = "RME Digi9652 (Hammerfall)",
+	.owner	  = THIS_MODULE,
 	.id_table = snd_rme9652_ids,
 	.probe	  = snd_rme9652_probe,
 	.remove	  = __devexit_p(snd_rme9652_remove),
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 60ecb2b..1f6c2bf 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -50,13 +50,6 @@
 #define SUPPORT_JOYSTICK 1
 #endif
 
-#ifndef PCI_VENDOR_ID_S3
-#define PCI_VENDOR_ID_S3             0x5333
-#endif
-#ifndef PCI_DEVICE_ID_S3_SONICVIBES
-#define PCI_DEVICE_ID_S3_SONICVIBES  0xca00
-#endif
-
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
@@ -1257,7 +1250,7 @@
                 return -ENXIO;
         }
 
-	sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL);
+	sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);
 	if (sonic == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
@@ -1515,6 +1508,7 @@
 
 static struct pci_driver driver = {
 	.name = "S3 SonicVibes",
+	.owner = THIS_MODULE,
 	.id_table = snd_sonic_ids,
 	.probe = snd_sonic_probe,
 	.remove = __devexit_p(snd_sonic_remove),
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 940d531..a8ca8e1 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -177,6 +177,7 @@
 
 static struct pci_driver driver = {
 	.name = "Trident4DWaveAudio",
+	.owner = THIS_MODULE,
 	.id_table = snd_trident_ids,
 	.probe = snd_trident_probe,
 	.remove = __devexit_p(snd_trident_remove),
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index f30d9d9..777da9a 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2960,7 +2960,7 @@
 		.read = snd_trident_codec_read,
 	};
 
-	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
+	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
 	if (!uctl)
 		return -ENOMEM;
 
@@ -3546,7 +3546,7 @@
 		return -ENXIO;
 	}
 	
-	trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
+	trident = kzalloc(sizeof(*trident), GFP_KERNEL);
 	if (trident == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 56c6e52..6db7de6 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -104,14 +104,6 @@
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
 
 
-/* pci ids */
-#ifndef PCI_DEVICE_ID_VIA_82C686_5
-#define PCI_DEVICE_ID_VIA_82C686_5	0x3058
-#endif
-#ifndef PCI_DEVICE_ID_VIA_8233_5
-#define PCI_DEVICE_ID_VIA_8233_5	0x3059
-#endif
-
 /* revision numbers for via686 */
 #define VIA_REV_686_A		0x10
 #define VIA_REV_686_B		0x11
@@ -1935,11 +1927,12 @@
 		 * DXS channels don't work properly with VRA if MC97 is disabled.
 		 */
 		struct pci_dev *pci;
-		pci = pci_find_device(0x1106, 0x3068, NULL); /* MC97 */
+		pci = pci_get_device(0x1106, 0x3068, NULL); /* MC97 */
 		if (pci) {
 			unsigned char data;
 			pci_read_config_byte(pci, 0x44, &data);
 			pci_write_config_byte(pci, 0x44, data | 0x40);
+			pci_dev_put(pci);
 		}
 	}
 
@@ -2065,7 +2058,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+	if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
 	}
@@ -2350,6 +2343,7 @@
 
 static struct pci_driver driver = {
 	.name = "VIA 82xx Audio",
+	.owner = THIS_MODULE,
 	.id_table = snd_via82xx_ids,
 	.probe = snd_via82xx_probe,
 	.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 5872d43..7eac6f6 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1083,7 +1083,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL) {
+	if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
 	}
@@ -1207,6 +1207,7 @@
 
 static struct pci_driver driver = {
 	.name = "VIA 82xx Modem",
+	.owner = THIS_MODULE,
 	.id_table = snd_via82xx_modem_ids,
 	.probe = snd_via82xx_probe,
 	.remove = __devexit_p(snd_via82xx_remove),
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index dca6bd2..2a7ad9d 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -252,6 +252,7 @@
 
 static struct pci_driver driver = {
 	.name = "Digigram VX222",
+	.owner = THIS_MODULE,
 	.id_table = snd_vx222_ids,
 	.probe = snd_vx222_probe,
 	.remove = __devexit_p(snd_vx222_remove),
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 5b5b624..2e69abe 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -352,6 +352,7 @@
 
 static struct pci_driver driver = {
 	.name = "Yamaha DS-XG PCI",
+	.owner = THIS_MODULE,
 	.id_table = snd_ymfpci_ids,
 	.probe = snd_card_ymfpci_probe,
 	.remove = __devexit_p(snd_card_ymfpci_remove),
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 0548364..27fa523 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -839,7 +839,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+	ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -957,7 +957,7 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
+	ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -2270,7 +2270,7 @@
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		pci_disable_device(pci);
 		return -ENOMEM;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index a2132e3..0208c54 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -151,7 +151,7 @@
 {
 	pdacf_t *chip;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return NULL;
 	chip->card = card;
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 75213bf..206b933 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -13,11 +13,24 @@
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
 	depends on SND && I2C && INPUT && PPC_PMAC
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for the integrated sound device.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-powermac.
 
-endmenu
+config SND_POWERMAC_AUTO_DRC
+	bool "Toggle DRC automatically at headphone/line plug-in"
+	depends on SND_POWERMAC
+	default y
+	help
+	  Say Y here to enable the automatic toggle of DRC (dynamic
+	  range compression) on Tumbler/Snapper.
+	  If this feature is enabled, DRC is turned off when the
+	  headphone/line jack is plugged, and turned on when unplugged.
 
+	  Note that you can turn on/off DRC manually even without this
+	  option.
+
+endmenu
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index c89e82e..e35b48d 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -988,6 +988,7 @@
 		case 0x33:
 		case 0x29:
 		case 0x24:
+		case 0x5c:
 			chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 			chip->model = PMAC_SNAPPER;
 			chip->can_byte_swap = 0; /* FIXME: check this */
@@ -1159,7 +1160,7 @@
 	snd_runtime_check(chip_return, return -EINVAL);
 	*chip_return = NULL;
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->card = card;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 231f643..a6d8cbf 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -131,6 +131,9 @@
 	if (enable_beep)
 		snd_pmac_attach_beep(chip);
 
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto __error;
+
 	if ((err = snd_card_register(card)) < 0)
 		goto __error;
 
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index b94437c..65384af 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -948,7 +948,6 @@
 			msleep(10);
 		check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
 			   chip->speaker_sw_ctl);
-		mix->drc_enable = 0;
 	} else {
 		/* unmute speaker, mute others */
 		check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
@@ -960,20 +959,21 @@
 		if (mix->line_mute.addr != 0)
 			check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
 				   chip->lineout_sw_ctl);
-		mix->drc_enable = 1;
 	}
-	if (mix->auto_mute_notify) {
+	if (mix->auto_mute_notify)
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->hp_detect_ctl->id);
+
+#ifdef CONFIG_SND_POWERMAC_AUTO_DRC
+	mix->drc_enable = ! (headphone || lineout);
+	if (mix->auto_mute_notify)
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 			       &chip->drc_sw_ctl->id);
-	}
-
-	/* first set the DRC so the speaker do not explode -ReneR */
 	if (chip->model == PMAC_TUMBLER)
 		tumbler_set_drc(mix);
 	else
 		snapper_set_drc(mix);
+#endif
 
 	/* reset the master volume so the correct amplification is applied */
 	tumbler_set_master_volume(mix);
@@ -1370,6 +1370,17 @@
 	if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
 		return err;
 
+	/* set initial DRC range to 60% */
+	if (chip->model == PMAC_TUMBLER)
+		mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;
+	else
+		mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;
+	mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */
+	if (chip->model == PMAC_TUMBLER)
+		tumbler_set_drc(mix);
+	else
+		snapper_set_drc(mix);
+
 #ifdef CONFIG_PM
 	chip->suspend = tumbler_suspend;
 	chip->resume = tumbler_resume;
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
index 25a8a55..09ab138 100644
--- a/sound/sparc/Kconfig
+++ b/sound/sparc/Kconfig
@@ -7,6 +7,7 @@
 	tristate "Sun AMD7930"
 	depends on SBUS && SND
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for AMD7930 sound device on Sun.
 
@@ -17,6 +18,7 @@
 	tristate "Sun CS4231"
 	depends on SND
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for CS4231 sound device on Sun.
 
@@ -27,6 +29,7 @@
 	tristate "Sun DBRI"
 	depends on SND && SBUS
 	select SND_PCM
+	select SND_GENERIC_DRIVER
 	help
 	  Say Y here to include support for DBRI sound device on Sun.
 
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index bd8a850..46d504b 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -967,7 +967,7 @@
 	int err;
 
 	*ramd = NULL;
-	amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
+	amd = kzalloc(sizeof(*amd), GFP_KERNEL);
 	if (amd == NULL)
 		return -ENOMEM;
 
@@ -1088,6 +1088,9 @@
 	if ((err = snd_amd7930_mixer(amd)) < 0)
 		goto out_err;
 
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto out_err;
+
 	if ((err = snd_card_register(card)) < 0)
 		goto out_err;
 
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 36f9fe4..2fb27c4 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1915,6 +1915,9 @@
 	if ((err = snd_cs4231_timer(chip)) < 0)
 		goto out_err;
 
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto out_err;
+
 	if ((err = snd_card_register(card)) < 0)
 		goto out_err;
 
@@ -1966,7 +1969,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2080,7 +2083,7 @@
 	int err;
 
 	*rchip = NULL;
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 941c7b1..b5c4c15 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -1,6 +1,6 @@
 /*
  * Driver for DBRI sound chip found on Sparcs.
- * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net)
+ * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net)
  *
  * Based entirely upon drivers/sbus/audio/dbri.c which is:
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -43,6 +43,12 @@
  * audio devices. But the SUN HW group decided against it, at least on my
  * LX the speakerbox connector has at least 1 pin missing and 1 wrongly
  * connected.
+ *
+ * I've tried to stick to the following function naming conventions:
+ * snd_*	ALSA stuff
+ * cs4215_*	CS4215 codec specfic stuff
+ * dbri_*	DBRI high-level stuff
+ * other	DBRI low-level stuff
  */
 
 #include <sound/driver.h>
@@ -87,7 +93,7 @@
 #define D_DESC	(1<<5)
 
 static int dbri_debug = 0;
-module_param(dbri_debug, int, 0444);
+module_param(dbri_debug, int, 0644);
 MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
 
 #ifdef DBRI_DEBUG
@@ -320,7 +326,8 @@
 	void __iomem *regs;	/* dbri HW regs */
 	int dbri_version;	/* 'e' and up is OK */
 	int dbri_irqp;		/* intr queue pointer */
-	int wait_seen;
+	int wait_send;		/* sequence of command buffers send */
+	int wait_ackd;		/* sequence of command buffers acknowledged */
 
 	struct dbri_pipe pipes[DBRI_NO_PIPES];	/* DBRI's 32 data pipes */
 	struct dbri_desc descs[DBRI_NO_DESCS];
@@ -625,16 +632,13 @@
 
 Commands are sent to the DBRI by building a list of them in memory,
 then writing the address of the first list item to DBRI register 8.
-The list is terminated with a WAIT command, which can generate a
-CPU interrupt if required.
+The list is terminated with a WAIT command, which generates a
+CPU interrupt to signal completion.
 
 Since the DBRI can run in parallel with the CPU, several means of
-synchronization present themselves.  The original scheme (Rudolf's)
-was to set a flag when we "cmdlock"ed the DBRI, clear the flag when
-an interrupt signaled completion, and wait on a wait_queue if a routine
-attempted to cmdlock while the flag was set.  The problems arose when
-we tried to cmdlock from inside an interrupt handler, which might
-cause scheduling in an interrupt (if we waited), etc, etc
+synchronization present themselves.  The method implemented here is close
+to the original scheme (Rudolf's), and uses 2 counters (wait_send and
+wait_ackd) to synchronize the command buffer between the CPU and the DBRI.
 
 A more sophisticated scheme might involve a circular command buffer
 or an array of command buffers.  A routine could fill one with
@@ -642,70 +646,75 @@
 completion of the current command buffer, look on the list for
 the next one.
 
-I've decided to implement something much simpler - after each command,
-the CPU waits for the DBRI to finish the command by polling the P bit
-in DBRI register 0.  I've tried to implement this in such a way
-that might make implementing a more sophisticated scheme easier.
-
 Every time a routine wants to write commands to the DBRI, it must
 first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd
-in return.  After the commands have been writen, dbri_cmdsend() is
-called with the final pointer value.
+in return. dbri_cmdlock() will block if the previous commands have not
+been completed yet. After this the commands can be written to the buffer,
+and dbri_cmdsend() is called with the final pointer value to send them
+to the DBRI.
 
 */
 
+static void dbri_process_interrupt_buffer(snd_dbri_t * dbri);
+
 enum dbri_lock_t { NoGetLock, GetLock };
+#define MAXLOOPS 10
 
 static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
 {
+	int maxloops = MAXLOOPS;
+
 #ifndef SMP
 	if ((get == GetLock) && spin_is_locked(&dbri->lock)) {
 		printk(KERN_ERR "DBRI: cmdlock called while in spinlock.");
 	}
 #endif
 
+	/* Delay if previous commands are still being processed */
+	while ((--maxloops) > 0 && (dbri->wait_send != dbri->wait_ackd)) {
+		msleep_interruptible(1);
+		/* If dbri_cmdlock() got called from inside the
+		 * interrupt handler, this will do the processing.
+		 */
+		dbri_process_interrupt_buffer(dbri);
+	}
+	if (maxloops == 0) {
+		printk(KERN_ERR "DBRI: Chip never completed command buffer %d\n",
+			dbri->wait_send);
+	} else {
+		dprintk(D_CMD, "Chip completed command buffer (%d)\n",
+			MAXLOOPS - maxloops - 1);
+	}
+
 	/*if (get == GetLock) spin_lock(&dbri->lock); */
 	return &dbri->dma->cmd[0];
 }
 
-static void dbri_process_interrupt_buffer(snd_dbri_t *);
-
 static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
 {
-	int MAXLOOPS = 1000000;
-	int maxloops = MAXLOOPS;
 	volatile s32 *ptr;
+	u32	reg;
 
 	for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) {
 		dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
 	}
 
 	if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) {
-		printk("DBRI: Command buffer overflow! (bug in driver)\n");
+		printk(KERN_ERR "DBRI: Command buffer overflow! (bug in driver)\n");
 		/* Ignore the last part. */
 		cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3];
 	}
 
+	dbri->wait_send++;
+	dbri->wait_send &= 0xffff;	/* restrict it to a 16 bit counter. */
 	*(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
-	*(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
-	dbri->wait_seen = 0;
+	*(cmd++) = DBRI_CMD(D_WAIT, 1, dbri->wait_send);
+
+	/* Set command pointer and signal it is valid. */
 	sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
-	while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P))
-		barrier();
-	if (maxloops == 0) {
-		printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
-		dprintk(D_CMD, "DBRI: Chip never completed command buffer\n");
-	} else {
-		while ((--maxloops) > 0 && (!dbri->wait_seen))
-			dbri_process_interrupt_buffer(dbri);
-		if (maxloops == 0) {
-			printk(KERN_ERR "DBRI: Chip never acked WAIT\n");
-			dprintk(D_CMD, "DBRI: Chip never acked WAIT\n");
-		} else {
-			dprintk(D_CMD, "Chip completed command "
-				"buffer (%d)\n", MAXLOOPS - maxloops);
-		}
-	}
+	reg = sbus_readl(dbri->regs + REG0);
+	reg |= D_P;
+	sbus_writel(reg, dbri->regs + REG0);
 
 	/*spin_unlock(&dbri->lock); */
 }
@@ -757,10 +766,11 @@
 	for (n = 0; n < DBRI_NO_PIPES; n++)
 		dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1;
 
-	/* We should query the openprom to see what burst sizes this
-	 * SBus supports.  For now, just disable all SBus bursts */
+	/* A brute approach - DBRI falls back to working burst size by itself
+	 * On SS20 D_S does not work, so do not try so high. */
 	tmp = sbus_readl(dbri->regs + REG0);
-	tmp &= ~(D_G | D_S | D_E);
+	tmp |= D_G | D_E;
+	tmp &= ~D_S;
 	sbus_writel(tmp, dbri->regs + REG0);
 
 	/*
@@ -805,13 +815,13 @@
 	volatile int *cmd;
 
 	if (pipe < 0 || pipe > 31) {
-		printk("DBRI: reset_pipe called with illegal pipe number\n");
+		printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n");
 		return;
 	}
 
 	sdp = dbri->pipes[pipe].sdp;
 	if (sdp == 0) {
-		printk("DBRI: reset_pipe called on uninitialized pipe\n");
+		printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n");
 		return;
 	}
 
@@ -834,12 +844,12 @@
 static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
 {
 	if (pipe < 0 || pipe > 31) {
-		printk("DBRI: setup_pipe called with illegal pipe number\n");
+		printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
 		return;
 	}
 
 	if ((sdp & 0xf800) != sdp) {
-		printk("DBRI: setup_pipe called with strange SDP value\n");
+		printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n");
 		/* sdp &= 0xf800; */
 	}
 
@@ -872,13 +882,13 @@
 	int nextpipe;
 
 	if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) {
-		printk
-		    ("DBRI: link_time_slot called with illegal pipe number\n");
+		printk(KERN_ERR 
+		    "DBRI: link_time_slot called with illegal pipe number\n");
 		return;
 	}
 
 	if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) {
-		printk("DBRI: link_time_slot called on uninitialized pipe\n");
+		printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n");
 		return;
 	}
 
@@ -960,8 +970,8 @@
 	int val;
 
 	if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) {
-		printk
-		    ("DBRI: unlink_time_slot called with illegal pipe number\n");
+		printk(KERN_ERR 
+		    "DBRI: unlink_time_slot called with illegal pipe number\n");
 		return;
 	}
 
@@ -1001,22 +1011,22 @@
 	volatile s32 *cmd;
 
 	if (pipe < 16 || pipe > 31) {
-		printk("DBRI: xmit_fixed: Illegal pipe number\n");
+		printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
 		return;
 	}
 
 	if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
-		printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
+		printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe);
 		return;
 	}
 
 	if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
-		printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
+		printk(KERN_ERR "DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
 		return;
 	}
 
 	if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
-		printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
+		printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
 		return;
 	}
 
@@ -1036,17 +1046,17 @@
 static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
 {
 	if (pipe < 16 || pipe > 31) {
-		printk("DBRI: recv_fixed called with illegal pipe number\n");
+		printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
 		return;
 	}
 
 	if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
-		printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
+		printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe);
 		return;
 	}
 
 	if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
-		printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe);
+		printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe);
 		return;
 	}
 
@@ -1075,12 +1085,12 @@
 	int last_desc = -1;
 
 	if (info->pipe < 0 || info->pipe > 15) {
-		printk("DBRI: setup_descs: Illegal pipe number\n");
+		printk(KERN_ERR "DBRI: setup_descs: Illegal pipe number\n");
 		return -2;
 	}
 
 	if (dbri->pipes[info->pipe].sdp == 0) {
-		printk("DBRI: setup_descs: Uninitialized pipe %d\n",
+		printk(KERN_ERR "DBRI: setup_descs: Uninitialized pipe %d\n",
 		       info->pipe);
 		return -2;
 	}
@@ -1090,20 +1100,20 @@
 
 	if (streamno == DBRI_PLAY) {
 		if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
-			printk("DBRI: setup_descs: Called on receive pipe %d\n",
+			printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n",
 			       info->pipe);
 			return -2;
 		}
 	} else {
 		if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
-			printk
-			    ("DBRI: setup_descs: Called on transmit pipe %d\n",
+			printk(KERN_ERR 
+			    "DBRI: setup_descs: Called on transmit pipe %d\n",
 			     info->pipe);
 			return -2;
 		}
 		/* Should be able to queue multiple buffers to receive on a pipe */
 		if (pipe_active(dbri, info->pipe)) {
-			printk("DBRI: recv_on_pipe: Called on active pipe %d\n",
+			printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n",
 			       info->pipe);
 			return -2;
 		}
@@ -1120,7 +1130,7 @@
 				break;
 		}
 		if (desc == DBRI_NO_DESCS) {
-			printk("DBRI: setup_descs: No descriptors\n");
+			printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
 			return -1;
 		}
 
@@ -1165,7 +1175,7 @@
 	}
 
 	if (first_desc == -1 || last_desc == -1) {
-		printk("DBRI: setup_descs: Not enough descriptors available\n");
+		printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n");
 		return -1;
 	}
 
@@ -1270,7 +1280,7 @@
 		int divisor = 12288 / clockrate;
 
 		if (divisor > 255 || divisor * clockrate != 12288)
-			printk("DBRI: illegal bits_per_frame in setup_chi\n");
+			printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n");
 
 		*(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
 				    | D_CHI_BPF(bits_per_frame));
@@ -1474,7 +1484,6 @@
 	/* Temporarily mute outputs, and wait 1/8000 sec (125 us)
 	 * to make sure this takes.  This avoids clicking noises.
 	 */
-
 	cs4215_setdata(dbri, 1);
 	udelay(125);
 
@@ -1530,8 +1539,8 @@
 	tmp |= D_C;		/* Enable CHI */
 	sbus_writel(tmp, dbri->regs + REG0);
 
-	for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) {
-		udelay(125);
+	for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) {
+		msleep_interruptible(1);
 	}
 	if (i == 0) {
 		dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
@@ -1678,8 +1687,8 @@
 Complicated interrupts are handled by dedicated functions (which
 appear first in this file).  Any pending interrupts can be serviced by
 calling dbri_process_interrupt_buffer(), which works even if the CPU's
-interrupts are disabled.  This function is used by dbri_cmdsend()
-to make sure we're synced up with the chip after each command sequence,
+interrupts are disabled.  This function is used by dbri_cmdlock()
+to make sure we're synced up with the chip before each command sequence,
 even if we're running cli'ed.
 
 */
@@ -1765,11 +1774,13 @@
  * Called by main interrupt handler when DBRI signals transmission complete
  * on a pipe (interrupt triggered by the B bit in a transmit descriptor).
  *
- * Walks through the pipe's list of transmit buffer descriptors, releasing
- * each one's DMA buffer (if present), flagging the descriptor available,
- * and signaling its callback routine (if present), before proceeding
- * to the next one.  Stops when the first descriptor is found without
+ * Walks through the pipe's list of transmit buffer descriptors and marks
+ * them as available. Stops when the first descriptor is found without
  * TBC (Transmit Buffer Complete) set, or we've run through them all.
+ *
+ * The DMA buffers are not released, but re-used. Since the transmit buffer
+ * descriptors are not clobbered, they can be re-submitted as is. This is
+ * done by the xmit_descs() tasklet above since that could take longer.
  */
 
 static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
@@ -1885,7 +1896,11 @@
 	}
 
 	if (channel == D_INTR_CMD && command == D_WAIT) {
-		dbri->wait_seen++;
+		dbri->wait_ackd = val;
+		if (dbri->wait_send != val) {
+			printk(KERN_ERR "Processing wait command %d when %d was send.\n",
+			       val, dbri->wait_send);
+		}
 		return;
 	}
 
@@ -1994,8 +2009,7 @@
 		 * The only one I've seen is MRR, which will be triggered
 		 * if you let a transmit pipe underrun, then try to CDP it.
 		 *
-		 * If these things persist, we should probably reset
-		 * and re-init the chip.
+		 * If these things persist, we reset the chip.
 		 */
 		if ((++errcnt) % 10 == 0) {
 			dprintk(D_INT, "Interrupt errors exceeded.\n");
@@ -2094,7 +2108,7 @@
 
 	if ((ret = snd_pcm_lib_malloc_pages(substream,
 				params_buffer_bytes(hw_params))) < 0) {
-		snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret);
+		printk(KERN_ERR "malloc_pages failed with %d\n", ret);
 		return ret;
 	}
 
@@ -2455,8 +2469,7 @@
 
 	for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) {
 		if ((err = snd_ctl_add(card,
-				       snd_ctl_new1(&dbri_controls[idx],
-						    dbri))) < 0)
+				snd_ctl_new1(&dbri_controls[idx], dbri))) < 0)
 			return err;
 	}
 
@@ -2490,8 +2503,6 @@
 	int pipe;
 	snd_iprintf(buffer, "debug=%d\n", dbri_debug);
 
-	snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n",
-		    dbri->chi_in_pipe, dbri->chi_out_pipe);
 	for (pipe = 0; pipe < 32; pipe++) {
 		if (pipe_active(dbri, pipe)) {
 			struct dbri_pipe *pptr = &dbri->pipes[pipe];
@@ -2506,18 +2517,6 @@
 		}
 	}
 }
-
-static void dbri_debug_write(snd_info_entry_t * entry,
-			     snd_info_buffer_t * buffer)
-{
-	char line[80];
-	int i;
-
-	if (snd_info_get_line(buffer, line, 80) == 0) {
-		sscanf(line, "%d\n", &i);
-		dbri_debug = i & 0x3f;
-	}
-}
 #endif
 
 void snd_dbri_proc(snd_dbri_t * dbri)
@@ -2531,9 +2530,7 @@
 #ifdef DBRI_DEBUG
 	err = snd_card_proc_new(dbri->card, "debug", &entry);
 	snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
-	entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */
-	entry->c.text.write_size = 256;
-	entry->c.text.write = dbri_debug_write;
+	entry->mode = S_IFREG | S_IRUGO;	/* Readable only. */
 #endif
 }
 
@@ -2637,7 +2634,11 @@
 		return -ENOENT;
 	}
 
-	prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+	err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq));
+	if (err < 0) {
+		printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev);
+		return -ENODEV;
+	}
 
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
 			    sizeof(snd_dbri_t));
@@ -2657,26 +2658,20 @@
 	}
 
 	dbri = (snd_dbri_t *) card->private_data;
-	if ((err = snd_dbri_pcm(dbri)) < 0) {
-		snd_dbri_free(dbri);
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_dbri_pcm(dbri)) < 0)
+		goto _err;
 
-	if ((err = snd_dbri_mixer(dbri)) < 0) {
-		snd_dbri_free(dbri);
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_dbri_mixer(dbri)) < 0)
+		goto _err;
 
 	/* /proc file handling */
 	snd_dbri_proc(dbri);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_dbri_free(dbri);
-		snd_card_free(card);
-		return err;
-	}
+	if ((err = snd_card_set_generic_dev(card)) < 0)
+		goto _err;
+
+	if ((err = snd_card_register(card)) < 0)
+		goto _err;
 
 	printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
 	       dev, dbri->regs,
@@ -2684,6 +2679,11 @@
 	dev++;
 
 	return 0;
+
+ _err:
+	snd_dbri_free(dbri);
+	snd_card_free(card);
+	return err;
 }
 
 /* Probe for the dbri chip and then attach the driver. */
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 60d0b2c..9e2b4c0 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -40,7 +40,7 @@
 	snd_emux_t *emu;
 
 	*remu = NULL;
-	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
+	emu = kzalloc(sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL)
 		return -ENOMEM;
 
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index e41b28d..8ccd33f 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -146,7 +146,7 @@
 	int i, type, cap;
 
 	/* Allocate structures for this channel */
-	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
+	if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_printk("no memory\n");
 		return NULL;
 	}
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 901a7db..d0925ea 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -266,7 +266,7 @@
 	}
 
 	/* not found -- create a new one */
-	sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
+	sf = kzalloc(sizeof(*sf), GFP_KERNEL);
 	if (sf == NULL)
 		return NULL;
 	sf->id = sflist->fonts_size;
@@ -346,7 +346,7 @@
 {
 	snd_sf_zone_t *zp;
 
-	if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
+	if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
 		return NULL;
 	zp->next = sf->zones;
 	sf->zones = zp;
@@ -377,7 +377,7 @@
 {
 	snd_sf_sample_t *sp;
 
-	if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
+	if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	sp->next = sf->samples;
@@ -1362,7 +1362,7 @@
 {
 	snd_sf_list_t *sflist;
 
-	if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
+	if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	init_MUTEX(&sflist->presets_mutex);
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 8b131a1..5f75bf3 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -38,7 +38,7 @@
 {
 	snd_util_memhdr_t *hdr;
 
-	hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
+	hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
 	if (hdr == NULL)
 		return NULL;
 	hdr->size = memsize;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index bfbec58..d5ae2055 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1439,9 +1439,11 @@
 
 static snd_pcm_hardware_t snd_usb_playback =
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID),
+	.info =			SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_BATCH |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_BLOCK_TRANSFER,
 	.buffer_bytes_max =	(256*1024),
 	.period_bytes_min =	64,
 	.period_bytes_max =	(128*1024),
@@ -1451,9 +1453,11 @@
 
 static snd_pcm_hardware_t snd_usb_capture =
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID),
+	.info =			SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_MMAP_VALID |
+				SNDRV_PCM_INFO_BATCH |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_BLOCK_TRANSFER,
 	.buffer_bytes_max =	(256*1024),
 	.period_bytes_min =	64,
 	.period_bytes_max =	(128*1024),
@@ -3132,7 +3136,7 @@
 		return -ENOMEM;
 	}
 
-	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_card_free(card);
 		return -ENOMEM;
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 93dedde..e0d0365 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -841,7 +841,7 @@
 	int length;
 
 	rep->in = NULL;
-	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -913,7 +913,7 @@
 	void* buffer;
 
 	rep->out = NULL;
-	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
+	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -1537,7 +1537,7 @@
 	int out_ports, in_ports;
 	int i, err;
 
-	umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
+	umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
 	if (!umidi)
 		return -ENOMEM;
 	umidi->chip = chip;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index fa7056f..c3c08c9 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -824,7 +824,7 @@
 	if (check_ignored_ctl(state, unitid, control))
 		return;
 
-	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+	cval = kzalloc(sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return;
@@ -997,7 +997,7 @@
 	if (check_ignored_ctl(state, unitid, 0))
 		return;
 
-	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+	cval = kzalloc(sizeof(*cval), GFP_KERNEL);
 	if (! cval)
 		return;
 
@@ -1244,7 +1244,7 @@
 			continue;
 		if (check_ignored_ctl(state, unitid, valinfo->control))
 			continue;
-		cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+		cval = kzalloc(sizeof(*cval), GFP_KERNEL);
 		if (! cval) {
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 			return -ENOMEM;
@@ -1430,7 +1430,7 @@
 	if (check_ignored_ctl(state, unitid, 0))
 		return 0;
 
-	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
+	cval = kzalloc(sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return -ENOMEM;
@@ -1945,7 +1945,7 @@
 
 	strcpy(chip->card->mixername, "USB Mixer");
 
-	mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+	mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
 	if (!mixer)
 		return -ENOMEM;
 	mixer->chip = chip;
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 62dfd28..0f09e0d 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -957,7 +957,7 @@
 
 	for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
 	     i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
-		usX2Y_substream[i] = kcalloc(1, sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+		usX2Y_substream[i] = kzalloc(sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
 		if (NULL == usX2Y_substream[i]) {
 			snd_printk(KERN_ERR "cannot malloc\n");
 			return -ENOMEM;