Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
diff --git a/CREDITS b/CREDITS
index f553f8c..a347520 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2211,6 +2211,15 @@
 S: (address available on request)
 S: USA
 
+N: Ian McDonald
+E: iam4@cs.waikato.ac.nz
+E: imcdnzl@gmail.com
+W: http://wand.net.nz/~iam4
+W: http://imcdnzl.blogspot.com
+D: DCCP, CCID3
+S: Hamilton
+S: New Zealand
+
 N: Patrick McHardy
 E: kaber@trash.net
 P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE  AB4C C9D4 964E 1215 5E80
@@ -2246,19 +2255,12 @@
 S: Germany
 
 N: Arnaldo Carvalho de Melo
-E: acme@conectiva.com.br
-E: acme@kernel.org
-E: acme@gnu.org
-W: http://bazar2.conectiva.com.br/~acme
-W: http://advogato.org/person/acme
+E: acme@mandriva.com
+E: acme@ghostprotocols.net
+W: http://oops.ghostprotocols.net:81/blog/
 P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
-D: wanrouter hacking
-D: misc Makefile, Config.in, drivers and network stacks fixes
-D: IPX & LLC network stacks maintainer
-D: Cyclom 2X synchronous card driver
-D: wl3501 PCMCIA wireless card driver
-D: i18n for minicom, net-tools, util-linux, fetchmail, etc
-S: Conectiva S.A.
+D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
+S: Mandriva
 S: R. Tocantins, 89 - Cristo Rei
 S: 80050-430 - Curitiba - Paraná
 S: Brazil
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 22e5f90..eb7db3c 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -410,7 +410,26 @@
 Printing numbers in parentheses (%d) adds no value and should be avoided.
 
 
-		Chapter 13: References
+		Chapter 13: Allocating memory
+
+The kernel provides the following general purpose memory allocators:
+kmalloc(), kzalloc(), kcalloc(), and vmalloc().  Please refer to the API
+documentation for further information about them.
+
+The preferred form for passing a size of a struct is the following:
+
+	p = kmalloc(sizeof(*p), ...);
+
+The alternative form where struct name is spelled out hurts readability and
+introduces an opportunity for a bug when the pointer variable type is changed
+but the corresponding sizeof that is passed to a memory allocator is not.
+
+Casting the return value which is a void pointer is redundant. The conversion
+from void pointer to any other pointer type is guaranteed by the C programming
+language.
+
+
+		Chapter 14: References
 
 The C Programming Language, Second Edition
 by Brian W. Kernighan and Dennis M. Ritchie.
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/dell_rbu.txt b/Documentation/dell_rbu.txt
index bcfa5c3..95d7f62 100644
--- a/Documentation/dell_rbu.txt
+++ b/Documentation/dell_rbu.txt
@@ -13,6 +13,8 @@
 and notebooks (starting from those sold in 2005).
 Please go to  http://support.dell.com register and you can find info on
 OpenManage and Dell Update packages (DUP).
+Libsmbios can also be used to update BIOS on Dell systems go to
+http://linux.dell.com/libsmbios/ for details.
 
 Dell_RBU driver supports BIOS update using the monilothic image and packetized
 image methods. In case of moniolithic the driver allocates a contiguous chunk
@@ -22,8 +24,8 @@
 maintains a link list of packets for reading them back.
 If the dell_rbu driver is unloaded all the allocated memory is freed.
 
-The rbu driver needs to have an application which will inform the BIOS to
-enable the update in the next system reboot.
+The rbu driver needs to have an application (as mentioned above)which will
+inform the BIOS to enable the update in the next system reboot.
 
 The user should not unload the rbu driver after downloading the BIOS image
 or updating.
@@ -42,9 +44,11 @@
 of contiguous memory and the BIOS image is scattered in these packets.
 
 By default the driver uses monolithic memory for the update type. This can be
-changed to contiguous during the driver load time by specifying the load
+changed to packets during the driver load time by specifying the load
 parameter image_type=packet.  This can also be changed later as below
 echo packet > /sys/devices/platform/dell_rbu/image_type
+Also echoing either mono ,packet or init in to image_type will free up the
+memory allocated by the driver.
 
 Do the steps below to download the BIOS image.
 1) echo 1 > /sys/class/firmware/dell_rbu/loading
@@ -53,9 +57,13 @@
 
 The /sys/class/firmware/dell_rbu/ entries will remain till the following is
 done.
-echo -1 > /sys/class/firmware/dell_rbu/loading
-
+echo -1 > /sys/class/firmware/dell_rbu/loading.
 Until this step is completed the drivr cannot be unloaded.
+If an user by accident executes steps 1 and 3 above without executing step 2;
+it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
+The entries can be recreated by doing the following
+echo init > /sys/devices/platform/dell_rbu/image_type
+NOTE: echoing init in image_type does not change it original value.
 
 Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
 read back the image downloaded. This is useful in case of packet update
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/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/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
index d24e1b0..d803abe 100644
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -15,7 +15,7 @@
 
 The format of the data logged into the channel buffers is completely
 up to the relayfs client; relayfs does however provide hooks which
-allow clients to impose some stucture on the buffer data.  Nor does
+allow clients to impose some structure on the buffer data.  Nor does
 relayfs implement any form of data filtering - this also is left to
 the client.  The purpose is to keep relayfs as simple as possible.
 
diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt
new file mode 100644
index 0000000..a71cc6a
--- /dev/null
+++ b/Documentation/ia64/mca.txt
@@ -0,0 +1,194 @@
+An ad-hoc collection of notes on IA64 MCA and INIT processing.  Feel
+free to update it with notes about any area that is not clear.
+
+---
+
+MCA/INIT are completely asynchronous.  They can occur at any time, when
+the OS is in any state.  Including when one of the cpus is already
+holding a spinlock.  Trying to get any lock from MCA/INIT state is
+asking for deadlock.  Also the state of structures that are protected
+by locks is indeterminate, including linked lists.
+
+---
+
+The complicated ia64 MCA process.  All of this is mandated by Intel's
+specification for ia64 SAL, error recovery and and unwind, it is not as
+if we have a choice here.
+
+* MCA occurs on one cpu, usually due to a double bit memory error.
+  This is the monarch cpu.
+
+* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
+  to all the other cpus, the slaves.
+
+* Slave cpus that receive the MCA interrupt call down into SAL, they
+  end up spinning disabled while the MCA is being serviced.
+
+* If any slave cpu was already spinning disabled when the MCA occurred
+  then it cannot service the MCA interrupt.  SAL waits ~20 seconds then
+  sends an unmaskable INIT event to the slave cpus that have not
+  already rendezvoused.
+
+* Because MCA/INIT can be delivered at any time, including when the cpu
+  is down in PAL in physical mode, the registers at the time of the
+  event are _completely_ undefined.  In particular the MCA/INIT
+  handlers cannot rely on the thread pointer, PAL physical mode can
+  (and does) modify TP.  It is allowed to do that as long as it resets
+  TP on return.  However MCA/INIT events expose us to these PAL
+  internal TP changes.  Hence curr_task().
+
+* If an MCA/INIT event occurs while the kernel was running (not user
+  space) and the kernel has called PAL then the MCA/INIT handler cannot
+  assume that the kernel stack is in a fit state to be used.  Mainly
+  because PAL may or may not maintain the stack pointer internally.
+  Because the MCA/INIT handlers cannot trust the kernel stack, they
+  have to use their own, per-cpu stacks.  The MCA/INIT stacks are
+  preformatted with just enough task state to let the relevant handlers
+  do their job.
+
+* Unlike most other architectures, the ia64 struct task is embedded in
+  the kernel stack[1].  So switching to a new kernel stack means that
+  we switch to a new task as well.  Because various bits of the kernel
+  assume that current points into the struct task, switching to a new
+  stack also means a new value for current.
+
+* Once all slaves have rendezvoused and are spinning disabled, the
+  monarch is entered.  The monarch now tries to diagnose the problem
+  and decide if it can recover or not.
+
+* Part of the monarch's job is to look at the state of all the other
+  tasks.  The only way to do that on ia64 is to call the unwinder,
+  as mandated by Intel.
+
+* The starting point for the unwind depends on whether a task is
+  running or not.  That is, whether it is on a cpu or is blocked.  The
+  monarch has to determine whether or not a task is on a cpu before it
+  knows how to start unwinding it.  The tasks that received an MCA or
+  INIT event are no longer running, they have been converted to blocked
+  tasks.  But (and its a big but), the cpus that received the MCA
+  rendezvous interrupt are still running on their normal kernel stacks!
+
+* To distinguish between these two cases, the monarch must know which
+  tasks are on a cpu and which are not.  Hence each slave cpu that
+  switches to an MCA/INIT stack, registers its new stack using
+  set_curr_task(), so the monarch can tell that the _original_ task is
+  no longer running on that cpu.  That gives us a decent chance of
+  getting a valid backtrace of the _original_ task.
+
+* MCA/INIT can be nested, to a depth of 2 on any cpu.  In the case of a
+  nested error, we want diagnostics on the MCA/INIT handler that
+  failed, not on the task that was originally running.  Again this
+  requires set_curr_task() so the MCA/INIT handlers can register their
+  own stack as running on that cpu.  Then a recursive error gets a
+  trace of the failing handler's "task".
+
+[1] My (Keith Owens) original design called for ia64 to separate its
+    struct task and the kernel stacks.  Then the MCA/INIT data would be
+    chained stacks like i386 interrupt stacks.  But that required
+    radical surgery on the rest of ia64, plus extra hard wired TLB
+    entries with its associated performance degradation.  David
+    Mosberger vetoed that approach.  Which meant that separate kernel
+    stacks meant separate "tasks" for the MCA/INIT handlers.
+
+---
+
+INIT is less complicated than MCA.  Pressing the nmi button or using
+the equivalent command on the management console sends INIT to all
+cpus.  SAL picks one one of the cpus as the monarch and the rest are
+slaves.  All the OS INIT handlers are entered at approximately the same
+time.  The OS monarch prints the state of all tasks and returns, after
+which the slaves return and the system resumes.
+
+At least that is what is supposed to happen.  Alas there are broken
+versions of SAL out there.  Some drive all the cpus as monarchs.  Some
+drive them all as slaves.  Some drive one cpu as monarch, wait for that
+cpu to return from the OS then drive the rest as slaves.  Some versions
+of SAL cannot even cope with returning from the OS, they spin inside
+SAL on resume.  The OS INIT code has workarounds for some of these
+broken SAL symptoms, but some simply cannot be fixed from the OS side.
+
+---
+
+The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
+violations.  Unfortunately MCA/INIT start off as massive layer
+violations (can occur at _any_ time) and they build from there.
+
+At least ia64 makes an attempt at recovering from hardware errors, but
+it is a difficult problem because of the asynchronous nature of these
+errors.  When processing an unmaskable interrupt we sometimes need
+special code to cope with our inability to take any locks.
+
+---
+
+How is ia64 MCA/INIT different from x86 NMI?
+
+* x86 NMI typically gets delivered to one cpu.  MCA/INIT gets sent to
+  all cpus.
+
+* x86 NMI cannot be nested.  MCA/INIT can be nested, to a depth of 2
+  per cpu.
+
+* x86 has a separate struct task which points to one of multiple kernel
+  stacks.  ia64 has the struct task embedded in the single kernel
+  stack, so switching stack means switching task.
+
+* x86 does not call the BIOS so the NMI handler does not have to worry
+  about any registers having changed.  MCA/INIT can occur while the cpu
+  is in PAL in physical mode, with undefined registers and an undefined
+  kernel stack.
+
+* i386 backtrace is not very sensitive to whether a process is running
+  or not.  ia64 unwind is very, very sensitive to whether a process is
+  running or not.
+
+---
+
+What happens when MCA/INIT is delivered what a cpu is running user
+space code?
+
+The user mode registers are stored in the RSE area of the MCA/INIT on
+entry to the OS and are restored from there on return to SAL, so user
+mode registers are preserved across a recoverable MCA/INIT.  Since the
+OS has no idea what unwind data is available for the user space stack,
+MCA/INIT never tries to backtrace user space.  Which means that the OS
+does not bother making the user space process look like a blocked task,
+i.e. the OS does not copy pt_regs and switch_stack to the user space
+stack.  Also the OS has no idea how big the user space RSE and memory
+stacks are, which makes it too risky to copy the saved state to a user
+mode stack.
+
+---
+
+How do we get a backtrace on the tasks that were running when MCA/INIT
+was delivered?
+
+mca.c:::ia64_mca_modify_original_stack().  That identifies and
+verifies the original kernel stack, copies the dirty registers from
+the MCA/INIT stack's RSE to the original stack's RSE, copies the
+skeleton struct pt_regs and switch_stack to the original stack, fills
+in the skeleton structures from the PAL minstate area and updates the
+original stack's thread.ksp.  That makes the original stack look
+exactly like any other blocked task, i.e. it now appears to be
+sleeping.  To get a backtrace, just start with thread.ksp for the
+original task and unwind like any other sleeping task.
+
+---
+
+How do we identify the tasks that were running when MCA/INIT was
+delivered?
+
+If the previous task has been verified and converted to a blocked
+state, then sos->prev_task on the MCA/INIT stack is updated to point to
+the previous task.  You can look at that field in dumps or debuggers.
+To help distinguish between the handler and the original tasks,
+handlers have _TIF_MCA_INIT set in thread_info.flags.
+
+The sos data is always in the MCA/INIT handler stack, at offset
+MCA_SOS_OFFSET.  You can get that value from mca_asm.h or calculate it
+as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
+ia64_sal_os_state), with 16 byte alignment for all structures.
+
+Also the comm field of the MCA/INIT task is modified to include the pid
+of the original task, for humans to use.  For example, a comm field of
+'MCA 12159' means that pid 12159 was running when the MCA was
+delivered.
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/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/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/MAINTAINERS b/MAINTAINERS
index a67bf7d..dc8f3ba 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
@@ -683,6 +686,13 @@
 M:	g.liakhovetski@gmx.de
 S:	Maintained
 
+DCCP PROTOCOL
+P:	Arnaldo Carvalho de Melo
+M:	acme@mandriva.com
+L:	dccp@vger.kernel.org
+W:	http://www.wlug.org.nz/DCCP
+S:	Maintained
+
 DECnet NETWORK LAYER
 P:	Patrick Caulfield
 M:	patrick@tykepenguin.com
@@ -2268,12 +2278,6 @@
 L:	linux-kernel@vger.kernel.org ?
 S:	Supported
 
-SPX NETWORK LAYER
-P:	Jay Schulist
-M:	jschlst@samba.org
-L:	netdev@vger.kernel.org
-S:	Supported
-
 SRM (Alpha) environment access
 P:	Jan-Benedict Glaw
 M:	jbglaw@lug-owl.de
diff --git a/Makefile b/Makefile
index 4e0d7c6..8cf6bec 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 14
-EXTRAVERSION =-rc1
+EXTRAVERSION =-rc2
 NAME=Affluent Albatross
 
 # *DOCUMENTATION*
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 0636116..01fe990d 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -37,6 +37,7 @@
 #include <linux/namei.h>
 #include <linux/uio.h>
 #include <linux/vfs.h>
+#include <linux/rcupdate.h>
 
 #include <asm/fpu.h>
 #include <asm/io.h>
@@ -975,6 +976,7 @@
 	long timeout;
 	int ret = -EINVAL;
 	struct fdtable *fdt;
+	int max_fdset;
 
 	timeout = MAX_SCHEDULE_TIMEOUT;
 	if (tvp) {
@@ -996,8 +998,11 @@
 		}
 	}
 
+	rcu_read_lock();
 	fdt = files_fdtable(current->files);
-	if (n < 0 || n > fdt->max_fdset)
+	max_fdset = fdt->max_fdset;
+	rcu_read_unlock();
+	if (n < 0 || n > max_fdset)
 		goto out_nofds;
 
 	/*
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 9e36b07..d5da6b1 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -395,6 +395,22 @@
  */
 
 static int __init
+isa_irq_fixup(struct pci_dev *dev, int irq)
+{
+	u8 irq8;
+
+	if (irq > 0)
+		return irq;
+
+	/* This interrupt is routed via ISA bridge, so we'll
+	   just have to trust whatever value the console might
+	   have assigned.  */
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
+
+	return irq8 & 0xf;
+}
+
+static int __init
 dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[6][5] __initdata = {
@@ -407,25 +423,13 @@
 		{ 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0}  /* IdSel 10 slot 3 */
 	};
 	const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
-
 	struct pci_controller *hose = dev->sysdata;
 	int irq = COMMON_TABLE_LOOKUP;
 
-	if (irq > 0) {
+	if (irq > 0)
 		irq += 16 * hose->index;
-	} else {
-		/* ??? The Contaq IDE controller on the ISA bridge uses
-		   "legacy" interrupts 14 and 15.  I don't know if anything
-		   can wind up at the same slot+pin on hose1, so we'll
-		   just have to trust whatever value the console might
-		   have assigned.  */
 
-		u8 irq8;
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
-		irq = irq8;
-	}
-
-	return irq;
+	return isa_irq_fixup(dev, irq);
 }
 
 static int __init
@@ -453,7 +457,8 @@
 		{    24,    24,    25,    26,    27}  /* IdSel 15 slot 5 PCI2*/
 	};
 	const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5;
-	return COMMON_TABLE_LOOKUP;
+
+	return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
 static u8 __init
@@ -507,7 +512,8 @@
 		{    47,    47,    46,    45,    44}, /* IdSel 17 slot 3 */
 	};
 	const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;
-	return COMMON_TABLE_LOOKUP;
+
+	return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
 static int __init
@@ -524,14 +530,13 @@
 		{    -1,    -1,    -1,    -1,    -1}  /* IdSel 7 ISA Bridge */
 	};
 	const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
-
 	struct pci_controller *hose = dev->sysdata;
 	int irq = COMMON_TABLE_LOOKUP;
 
 	if (irq > 0)
 		irq += 16 * hose->index;
 
-	return irq;
+	return isa_irq_fixup(dev, irq);
 }
 
 static void __init
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 2786f7c..a7bd857 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -551,7 +551,7 @@
 	u16	LCM_SPIMD;
 };
 
-static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level)
+static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
 {
 	struct locomo *lchip = dev_get_drvdata(dev);
 	struct locomo_save_data *save;
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index f67ca01..30e6444 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul  7 16:41:21 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:51:52 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -135,7 +135,6 @@
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -179,6 +178,68 @@
 # CONFIG_PM is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
 # Device Drivers
 #
 
@@ -248,6 +309,7 @@
 CONFIG_MTD_IXP2000=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -334,72 +396,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -509,6 +507,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -635,7 +635,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -649,11 +649,28 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -679,30 +696,15 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -770,6 +772,7 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -812,8 +815,7 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 5c6c928..678720f 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul  7 16:49:01 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:01 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -136,7 +136,6 @@
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@
 # CONFIG_PM is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
 # Device Drivers
 #
 
@@ -249,6 +310,7 @@
 CONFIG_MTD_IXP2000=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -335,72 +397,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -510,6 +508,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -636,7 +636,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -650,11 +650,28 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -680,30 +697,15 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -771,6 +773,7 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -813,8 +816,7 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 6dc40f6..38c9a72 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul  7 16:49:08 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:10 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -136,7 +136,6 @@
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@
 # CONFIG_PM is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
 # Device Drivers
 #
 
@@ -249,6 +310,7 @@
 CONFIG_MTD_IXP2000=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -335,72 +397,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -511,6 +509,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -637,7 +637,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -651,11 +651,28 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -681,30 +698,15 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -772,6 +774,7 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -814,8 +817,7 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index d2bb0b7..261e234 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul  7 16:49:20 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:23 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -136,7 +136,6 @@
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@
 # CONFIG_PM is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
 # Device Drivers
 #
 
@@ -249,6 +310,7 @@
 CONFIG_MTD_IXP2000=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -335,72 +397,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -510,6 +508,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -636,7 +636,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -650,11 +650,28 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -680,30 +697,15 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -771,6 +773,7 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -813,8 +816,7 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index 2d6f960..12ef23d 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Thu Jul  7 16:49:13 2005
+# Linux kernel version: 2.6.13
+# Wed Sep 14 10:52:16 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -136,7 +136,6 @@
 #
 # Kernel Features
 #
-# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -180,6 +179,68 @@
 # CONFIG_PM is not set
 
 #
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
 # Device Drivers
 #
 
@@ -249,6 +310,7 @@
 CONFIG_MTD_IXP2000=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -335,72 +397,8 @@
 # CONFIG_I2O is not set
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
@@ -511,6 +509,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -637,7 +637,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_IXP2000 is not set
+CONFIG_I2C_IXP2000=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -651,11 +651,28 @@
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
 # CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SENSOR=y
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -681,30 +698,15 @@
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -772,6 +774,7 @@
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -814,8 +817,7 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 949ec44..2ad4aa2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -131,7 +131,7 @@
 		.long	sys_wait4
 /* 115 */	.long	sys_swapoff
 		.long	sys_sysinfo
-		.long	sys_ipc
+		.long	sys_ipc_wrapper
 		.long	sys_fsync
 		.long	sys_sigreturn_wrapper
 /* 120 */	.long	sys_clone_wrapper
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index db302c6..81d450a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -273,6 +273,10 @@
 		str	r5, [sp, #4]
 		b	sys_mbind
 
+sys_ipc_wrapper:
+		str	r5, [sp, #4]		@ push sixth arg
+		b	sys_ipc
+
 /*
  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
  * offset, we return EINVAL.
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index ac423e3..4c31f29 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -178,7 +178,7 @@
  * registers (r0 to r3 and lr), but not ip, as we use it as a return
  * value in some cases..
  */
-asm("	.section .sched.text,\"ax\"		\n\
+asm("	.section .sched.text,\"ax\",%progbits	\n\
 	.align	5				\n\
 	.globl	__down_failed			\n\
 __down_failed:					\n\
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ae1fa09..39b06ed 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -123,6 +123,7 @@
 	platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
 }
 
+#ifdef CONFIG_ARCH_IXDP465
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
 	.phys_ram	= PHYS_OFFSET,
@@ -134,7 +135,9 @@
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
 MACHINE_END
+#endif
 
+#ifdef CONFIG_MACH_IXDP465
 MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
 	.phys_ram	= PHYS_OFFSET,
@@ -146,7 +149,9 @@
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
 MACHINE_END
+#endif
 
+#ifdef CONFIG_ARCH_PRPMC1100
 MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
 	/* Maintainer: MontaVista Software, Inc. */
 	.phys_ram	= PHYS_OFFSET,
@@ -158,6 +163,7 @@
 	.boot_params	= 0x0100,
 	.init_machine	= ixdp425_init,
 MACHINE_END
+#endif
 
 /*
  * Avila is functionally equivalent to IXDP425 except that it adds
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..be37586 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,
 };
 
 
@@ -164,13 +198,10 @@
 {
 	struct pxamci_platform_data* p_d = dev->platform_data;
 
-	if (( 1 << vdd) & p_d->ocr_mask) {
-		printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
+	if (( 1 << vdd) & p_d->ocr_mask)
 		GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
-	} else {
-		printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
+	else
 		GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
-	}
 }
 
 static int corgi_mci_get_ro(struct device *dev)
@@ -225,7 +256,20 @@
 
 static void __init corgi_init(void)
 {
+	/* 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(&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);
 
@@ -248,42 +292,14 @@
 		mi->bank[0].size = (64*1024*1024);
 }
 
-static void __init corgi_init_irq(void)
-{
-	pxa_init_irq();
-}
-
-static struct map_desc corgi_io_desc[] __initdata = {
-/*    virtual     physical    length      */
-/*	{ 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */
-/*	{ 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/  /* SCOOP */
-	{ 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
-};
-
-static void __init corgi_map_io(void)
-{
-	pxa_map_io();
-	iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc));
-
-	/* 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;
-}
-
 #ifdef CONFIG_MACH_CORGI
 MACHINE_START(CORGI, "SHARP Corgi")
 	.phys_ram	= 0xa0000000,
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
-	.map_io		= corgi_map_io,
-	.init_irq	= corgi_init_irq,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -295,8 +311,8 @@
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
-	.map_io		= corgi_map_io,
-	.init_irq	= corgi_init_irq,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
@@ -308,8 +324,8 @@
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_corgi,
-	.map_io		= corgi_map_io,
-	.init_irq	= corgi_init_irq,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa_init_irq,
 	.init_machine	= corgi_init,
 	.timer		= &pxa_timer,
 MACHINE_END
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/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 923f6eb..1f38033 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -146,6 +146,11 @@
 	// no D+ pullup; lubbock can't connect/disconnect in software
 };
 
+static struct platform_device lub_audio_device = {
+	.name		= "pxa2xx-ac97",
+	.id		= -1,
+};
+
 static struct resource sa1111_resources[] = {
 	[0] = {
 		.start	= 0x10000000,
@@ -195,6 +200,7 @@
 
 static struct platform_device *devices[] __initdata = {
 	&sa1111_device,
+	&lub_audio_device,
 	&smc91x_device,
 };
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 47cfb8b..f256388 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -30,6 +30,8 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
 #include <asm/arch/poodle.h>
 #include <asm/arch/pxafb.h>
 
@@ -93,6 +95,83 @@
 	.resource	= locomo_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 poodle_mci_platform_data;
+
+static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+	int err;
+
+	/* setup GPIO for PXA25x MMC controller	*/
+	pxa_gpio_mode(GPIO6_MMCCLK_MD);
+	pxa_gpio_mode(GPIO8_MMCCS0_MD);
+	pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN);
+	pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT);
+
+	poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+	err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT,
+			     "MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+		return -1;
+	}
+
+	set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+	return 0;
+}
+
+static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data* p_d = dev->platform_data;
+
+	if (( 1 << vdd) & p_d->ocr_mask)
+		GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+	else
+		GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+}
+
+static void poodle_mci_exit(struct device *dev, void *data)
+{
+	free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data poodle_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init 		= poodle_mci_init,
+	.setpower 	= poodle_mci_setpower,
+	.exit		= poodle_mci_exit,
+};
+
+
+/*
+ * USB Device Controller
+ */
+static void poodle_udc_command(int cmd)
+{
+	switch(cmd)	{
+	case PXA2XX_UDC_CMD_CONNECT:
+		GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+		break;
+	case PXA2XX_UDC_CMD_DISCONNECT:
+		GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+		break;
+	}
+}
+
+static struct pxa2xx_udc_mach_info udc_info __initdata = {
+	/* no connect GPIO; poodle can't tell connection status */
+	.udc_command		= poodle_udc_command,
+};
+
+
 /* PXAFB device */
 static struct pxafb_mach_info poodle_fb_info __initdata = {
 	.pixclock	= 144700,
@@ -126,6 +205,15 @@
 {
 	int ret = 0;
 
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+
 	/* cpu initialize */
 	/* Pgsr Register */
   	PGSR0 = 0x0146dd80;
@@ -155,6 +243,9 @@
         GPSR2 = 0x00000000;
 
 	set_pxa_fb_info(&poodle_fb_info);
+	pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
+	pxa_set_udc_info(&udc_info);
+	pxa_set_mci_info(&poodle_mci_platform_data);
 
 	scoop_num = 1;
 	scoop_devs = &poodle_pcmcia_scoop[0];
@@ -171,32 +262,12 @@
 	sharpsl_save_param();
 }
 
-static struct map_desc poodle_io_desc[] __initdata = {
- /* virtual     physical    length                   */
-  { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
-};
-
-static void __init poodle_map_io(void)
-{
-	pxa_map_io();
-	iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc));
-
-	/* setup sleep mode values */
-	PWER  = 0x00000002;
-	PFER  = 0x00000000;
-	PRER  = 0x00000002;
-	PGSR0 = 0x00008000;
-	PGSR1 = 0x003F0202;
-	PGSR2 = 0x0001C000;
-	PCFR |= PCFR_OPDE;
-}
-
 MACHINE_START(POODLE, "SHARP Poodle")
 	.phys_ram	= 0xa0000000,
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
 	.fixup		= fixup_poodle,
-	.map_io		= poodle_map_io,
+	.map_io		= pxa_map_io,
 	.init_irq	= pxa_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= poodle_init,
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/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 8cb6911..25d6a4e 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -111,12 +111,11 @@
 
 static void collie_set_vpp(int vpp)
 {
-	write_scoop_reg(SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN);
-	if (vpp) {
-		write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN);
-	} else {
-		write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
-	}
+	write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN);
+	if (vpp)
+		write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN);
+	else
+		write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN);
 }
 
 static struct flash_platform_data collie_flash_data = {
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index 279e3af..f085d68 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -39,3 +39,6 @@
 
 struct irda_platform_data;
 void sa11x0_set_irda_data(struct irda_platform_data *irda);
+
+struct mcp_plat_data;
+void sa11x0_set_mcp_data(struct mcp_plat_data *data);
diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c
deleted file mode 100644
index 3e8f07f..0000000
--- a/arch/arm26/boot/compressed/hw-bse.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Bright Star Engineering Inc.
- *
- * code for readng parameters from the
- * parameter blocks of the boot block
- * flash memory
- *
- */
-
-static int strcmp(const char *s1, const char *s2)
-{
-  while (*s1 != '\0' && *s1 == *s2)
-    {
-      s1++;
-      s2++;
-    }
-
-  return (*(unsigned char *) s1) - (*(unsigned char *) s2);
-}
-
-struct pblk_t {
-  char type;
-  unsigned short size;
-};
-
-static char *bse_getflashparam(char *name) {
-  unsigned int esize;
-  char *q,*r;
-  unsigned char *p,*e;
-  struct pblk_t *thepb = (struct pblk_t *) 0x00004000;
-  struct pblk_t *altpb = (struct pblk_t *) 0x00006000;  
-  if (thepb->type&1) {
-    if (altpb->type&1) {
-      /* no valid param block */ 
-      return (char*)0;
-    } else {
-      /* altpb is valid */
-      struct pblk_t *tmp;
-      tmp = thepb;
-      thepb = altpb;
-      altpb = tmp;
-    }
-  }
-  p = (char*)thepb + sizeof(struct pblk_t);
-  e = p + thepb->size; 
-  while (p < e) {
-    q = p;
-    esize = *p;
-    if (esize == 0xFF) break;
-    if (esize == 0) break;
-    if (esize > 127) {
-      esize = (esize&0x7F)<<8 | p[1];
-      q++;
-    }
-    q++;
-    r=q;
-    if (*r && ((name == 0) || (!strcmp(name,r)))) {
-      while (*q++) ;
-      return q;
-    }
-    p+=esize;
-  }
-  return (char*)0;
-}
-
-void bse_setup(void) {
-  /* extract the linux cmdline from flash */
-  char *name=bse_getflashparam("linuxboot");
-  char *x = (char *)0xc0000100;
-  if (name) { 
-    while (*name) *x++=*name++;
-  }
-  *x=0;
-}
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index b22f003..d2703cd 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -908,11 +908,6 @@
  	  The default yes will allow the kernel to do irq load balancing.
 	  Saying no will keep the kernel from doing irq load balancing.
 
-config HAVE_DEC_LOCK
-	bool
-	depends on (SMP || PREEMPT) && X86_CMPXCHG
-	default y
-
 # turning this on wastes a bunch of space.
 # Summit needs it only when NUMA is on
 config BOOT_IOREMAP
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 1ae2aee..f1b9d2a 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -7,7 +7,6 @@
 #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)
 {
@@ -16,15 +15,6 @@
 	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/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 dc39ca6..9b8c8a1 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -848,9 +848,7 @@
 #ifdef CONFIG_X86_IO_APIC
 		else if (!memcmp(from, "acpi_skip_timer_override", 24))
 			acpi_skip_timer_override = 1;
-#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))
@@ -859,7 +857,7 @@
 		/* disable IO-APIC */
 		else if (!memcmp(from, "noapic", 6))
 			disable_ioapic_setup();
-#endif /* CONFIG_X86_LOCAL_APIC */
+#endif /* CONFIG_X86_IO_APIC */
 #endif /* CONFIG_ACPI */
 
 #ifdef CONFIG_X86_LOCAL_APIC
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/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/lib/Makefile b/arch/i386/lib/Makefile
index 7b1932d..914933e 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -7,4 +7,3 @@
 	bitops.o
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c
deleted file mode 100644
index 8b81b25..0000000
--- a/arch/i386/lib/dec_and_lock.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * x86 version of "atomic_dec_and_lock()" using
- * the atomic "cmpxchg" instruction.
- *
- * (For CPU's lacking cmpxchg, we use the slow
- * generic version, and this one never even gets
- * compiled).
- */
-
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <asm/atomic.h>
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	int counter;
-	int newcount;
-
-repeat:
-	counter = atomic_read(atomic);
-	newcount = counter-1;
-
-	if (!newcount)
-		goto slow_path;
-
-	asm volatile("lock; cmpxchgl %1,%2"
-		:"=a" (newcount)
-		:"r" (newcount), "m" (atomic->counter), "0" (counter));
-
-	/* If the above failed, "eax" will have changed */
-	if (newcount != counter)
-		goto repeat;
-	return 0;
-
-slow_path:
-	spin_lock(lock);
-	if (atomic_dec_and_test(atomic))
-		return 1;
-	spin_unlock(lock);
-	return 0;
-}
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index ed25d66..945c15a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -298,11 +298,6 @@
 
 source "mm/Kconfig"
 
-config HAVE_DEC_LOCK
-	bool
-	depends on (SMP || PREEMPT)
-	default y
-
 config IA32_SUPPORT
 	bool "Support for Linux/x86 binaries"
 	help
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 70f8ed2..67932ad 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -82,17 +82,7 @@
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-archprepare:  include/asm-ia64/.offsets.h.stamp
-
-include/asm-ia64/.offsets.h.stamp:
-	mkdir -p include/asm-ia64
-	[ -s include/asm-ia64/asm-offsets.h ] \
-	|| echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/asm-offsets.h
-	touch $@
-
-
-
-CLEAN_FILES += vmlinux.gz bootloader include/asm-ia64/.offsets.h.stamp
+CLEAN_FILES += vmlinux.gz bootloader
 
 boot:	lib/lib.a vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 31de70b..a7280d9 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -216,12 +216,6 @@
 	if (!mpnt)
 		return -ENOMEM;
 
-	if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))
-				      >> PAGE_SHIFT)) {
-		kmem_cache_free(vm_area_cachep, mpnt);
-		return -ENOMEM;
-	}
-
 	memset(mpnt, 0, sizeof(*mpnt));
 
 	down_write(&current->mm->mmap_sem);
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 28a4529..7e92647 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -899,7 +899,7 @@
 	if ((err = iosapic_init(phys_addr, gsi_base)))
 		return err;
 
-#if CONFIG_ACPI_NUMA
+#ifdef CONFIG_ACPI_NUMA
 	acpi_map_iosapic(handle, 0, NULL, NULL);
 #endif				/* CONFIG_ACPI_NUMA */
 
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index f6a2342..7722565 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -4,6 +4,7 @@
  * to extract and format the required data.
  */
 
+#define ASM_OFFSETS_C 1
 #include <linux/config.h>
 
 #include <linux/sched.h>
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index ba0b6a1..0741b066 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -491,7 +491,7 @@
 	;;
 	lfetch.fault [r16], 128
 	br.ret.sptk.many rp
-END(prefetch_switch_stack)
+END(prefetch_stack)
 
 GLOBAL_ENTRY(execve)
 	mov r15=__NR_execve			// put syscall number in place
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 6e68374..80f83d6 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -84,23 +84,23 @@
 	struct page *p;
 
 	/* whether physical address is valid or not */
-	if ( !ia64_phys_addr_valid(paddr) ) 
+	if (!ia64_phys_addr_valid(paddr))
 		return ISOLATE_NG;
 
 	/* convert physical address to physical page number */
 	p = pfn_to_page(paddr>>PAGE_SHIFT);
 
 	/* check whether a page number have been already registered or not */
-	for( i = 0; i < num_page_isolate; i++ )
-		if( page_isolate[i] == p )
+	for (i = 0; i < num_page_isolate; i++)
+		if (page_isolate[i] == p)
 			return ISOLATE_OK; /* already listed */
 
 	/* limitation check */
-	if( num_page_isolate == MAX_PAGE_ISOLATE ) 
+	if (num_page_isolate == MAX_PAGE_ISOLATE)
 		return ISOLATE_NG;
 
 	/* kick pages having attribute 'SLAB' or 'Reserved' */
-	if( PageSlab(p) || PageReserved(p) ) 
+	if (PageSlab(p) || PageReserved(p))
 		return ISOLATE_NG;
 
 	/* add attribute 'Reserved' and register the page */
@@ -139,10 +139,10 @@
  * @peidx:	pointer to index of processor error section
  */
 
-static void 
+static void
 mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx)
 {
-	/* 
+	/*
 	 * calculate the start address of
 	 *   "struct cpuid_info" and "sal_processor_static_info_t".
 	 */
@@ -164,7 +164,7 @@
 }
 
 /**
- * mca_make_slidx -  Make index of SAL error record 
+ * mca_make_slidx -  Make index of SAL error record
  * @buffer:	pointer to SAL error record
  * @slidx:	pointer to index of SAL error record
  *
@@ -172,12 +172,12 @@
  *	1 if record has platform error / 0 if not
  */
 #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \
-        { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
-          hl->hdr = ptr; \
-          list_add(&hl->list, &(sect)); \
-          slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
+	{slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \
+	hl->hdr = ptr; \
+	list_add(&hl->list, &(sect)); \
+	slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; }
 
-static int 
+static int
 mca_make_slidx(void *buffer, slidx_table_t *slidx)
 {
 	int platform_err = 0;
@@ -214,28 +214,36 @@
 		sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos);
 		if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) {
 			LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp);
-		} else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) {
+		} else if (!efi_guidcmp(sp->guid,
+				SAL_PLAT_BUS_ERR_SECT_GUID)) {
 			platform_err = 1;
 			LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp);
 		} else {
@@ -253,15 +261,16 @@
  * Return value:
  *	0 on Success / -ENOMEM on Failure
  */
-static int 
+static int
 init_record_index_pools(void)
 {
 	int i;
 	int rec_max_size;  /* Maximum size of SAL error records */
 	int sect_min_size; /* Minimum size of SAL error sections */
 	/* minimum size table of each section */
-	static int sal_log_sect_min_sizes[] = { 
-		sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t),
+	static int sal_log_sect_min_sizes[] = {
+		sizeof(sal_log_processor_info_t)
+		+ sizeof(sal_processor_static_info_t),
 		sizeof(sal_log_mem_dev_err_info_t),
 		sizeof(sal_log_sel_dev_err_info_t),
 		sizeof(sal_log_pci_bus_err_info_t),
@@ -294,7 +303,8 @@
 
 	/* - 3 - */
 	slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
-	slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+	slidx_pool.buffer = (slidx_list_t *)
+		kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
 
 	return slidx_pool.buffer ? 0 : -ENOMEM;
 }
@@ -308,6 +318,7 @@
  * is_mca_global - Check whether this MCA is global or not
  * @peidx:	pointer of index of processor error section
  * @pbci:	pointer to pal_bus_check_info_t
+ * @sos:	pointer to hand off struct between SAL and OS
  *
  * Return value:
  *	MCA_IS_LOCAL / MCA_IS_GLOBAL
@@ -317,11 +328,12 @@
 is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
 	      struct ia64_sal_os_state *sos)
 {
-	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+	pal_processor_state_info_t *psp =
+		(pal_processor_state_info_t*)peidx_psp(peidx);
 
-	/* 
+	/*
 	 * PAL can request a rendezvous, if the MCA has a global scope.
-	 * If "rz_always" flag is set, SAL requests MCA rendezvous 
+	 * If "rz_always" flag is set, SAL requests MCA rendezvous
 	 * in spite of global MCA.
 	 * Therefore it is local MCA when rendezvous has not been requested.
 	 * Failed to rendezvous, the system must be down.
@@ -381,13 +393,15 @@
  * @slidx:	pointer of index of SAL error record
  * @peidx:	pointer of index of processor error section
  * @pbci:	pointer of pal_bus_check_info
+ * @sos:	pointer to hand off struct between SAL and OS
  *
  * Return value:
  *	1 on Success / 0 on Failure
  */
 
 static int
-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_read_error(slidx_table_t *slidx,
+			peidx_table_t *peidx, pal_bus_check_info_t *pbci,
 			struct ia64_sal_os_state *sos)
 {
 	sal_log_mod_error_info_t *smei;
@@ -453,24 +467,28 @@
  * @slidx:	pointer of index of SAL error record
  * @peidx:	pointer of index of processor error section
  * @pbci:	pointer of pal_bus_check_info
+ * @sos:	pointer to hand off struct between SAL and OS
  *
  * Return value:
  *	1 on Success / 0 on Failure
  */
 
 static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx,
+			    pal_bus_check_info_t *pbci,
 			    struct ia64_sal_os_state *sos)
 {
 	int status = 0;
-	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+	pal_processor_state_info_t *psp =
+		(pal_processor_state_info_t*)peidx_psp(peidx);
 
 	if (psp->bc && pbci->eb && pbci->bsi == 0) {
 		switch(pbci->type) {
 		case 1: /* partial read */
 		case 3: /* full line(cpu) read */
 		case 9: /* I/O space read */
-			status = recover_from_read_error(slidx, peidx, pbci, sos);
+			status = recover_from_read_error(slidx, peidx, pbci,
+							 sos);
 			break;
 		case 0: /* unknown */
 		case 2: /* partial write */
@@ -481,7 +499,8 @@
 		case 8: /* write coalescing transactions */
 		case 10: /* I/O space write */
 		case 11: /* inter-processor interrupt message(IPI) */
-		case 12: /* interrupt acknowledge or external task priority cycle */
+		case 12: /* interrupt acknowledge or
+				external task priority cycle */
 		default:
 			break;
 		}
@@ -496,6 +515,7 @@
  * @slidx:	pointer of index of SAL error record
  * @peidx:	pointer of index of processor error section
  * @pbci:	pointer of pal_bus_check_info
+ * @sos:	pointer to hand off struct between SAL and OS
  *
  * Return value:
  *	1 on Success / 0 on Failure
@@ -509,15 +529,17 @@
  */
 
 static int
-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+recover_from_processor_error(int platform, slidx_table_t *slidx,
+			     peidx_table_t *peidx, pal_bus_check_info_t *pbci,
 			     struct ia64_sal_os_state *sos)
 {
-	pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
+	pal_processor_state_info_t *psp =
+		(pal_processor_state_info_t*)peidx_psp(peidx);
 
-	/* 
+	/*
 	 * We cannot recover errors with other than bus_check.
 	 */
-	if (psp->cc || psp->rc || psp->uc) 
+	if (psp->cc || psp->rc || psp->uc)
 		return 0;
 
 	/*
@@ -546,10 +568,10 @@
 	 * (e.g. a load from poisoned memory)
 	 * This means "there are some platform errors".
 	 */
-	if (platform) 
+	if (platform)
 		return recover_from_platform_error(slidx, peidx, pbci, sos);
-	/* 
-	 * On account of strange SAL error record, we cannot recover. 
+	/*
+	 * On account of strange SAL error record, we cannot recover.
 	 */
 	return 0;
 }
@@ -557,14 +579,14 @@
 /**
  * mca_try_to_recover - Try to recover from MCA
  * @rec:	pointer to a SAL error record
+ * @sos:	pointer to hand off struct between SAL and OS
  *
  * Return value:
  *	1 on Success / 0 on Failure
  */
 
 static int
-mca_try_to_recover(void *rec, 
-	struct ia64_sal_os_state *sos)
+mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 {
 	int platform_err;
 	int n_proc_err;
@@ -588,7 +610,8 @@
 	}
 
 	/* Make index of processor error section */
-	mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
+	mca_make_peidx((sal_log_processor_info_t*)
+		slidx_first_entry(&slidx.proc_err)->hdr, &peidx);
 
 	/* Extract Processor BUS_CHECK[0] */
 	*((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
@@ -598,7 +621,8 @@
 		return 0;
 	
 	/* Try to recover a processor error */
-	return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);
+	return recover_from_processor_error(platform_err, &slidx, &peidx,
+					    &pbci, sos);
 }
 
 /*
@@ -611,7 +635,7 @@
 		return -ENOMEM;
 
 	/* register external mca handlers */
-	if (ia64_reg_MCA_extension(mca_try_to_recover)){	
+	if (ia64_reg_MCA_extension(mca_try_to_recover)) {	
 		printk(KERN_ERR "ia64_reg_MCA_extension failed.\n");
 		kfree(slidx_pool.buffer);
 		return -EFAULT;
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
index 0227b76..e2f6fa1 100644
--- a/arch/ia64/kernel/mca_drv.h
+++ b/arch/ia64/kernel/mca_drv.h
@@ -6,7 +6,7 @@
  * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
  */
 /*
- * Processor error section: 
+ * Processor error section:
  *
  *  +-sal_log_processor_info_t *info-------------+
  *  | sal_log_section_hdr_t header;              |
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index 2d7e021..3f298ee 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -13,45 +13,45 @@
 #include <asm/ptrace.h>
 
 GLOBAL_ENTRY(mca_handler_bhhook)
-	invala						// clear RSE ?
-	;;						//
-	cover						// 
-	;;						//
-	clrrrb						//
+	invala				// clear RSE ?
+	;;
+	cover
+	;;
+	clrrrb
 	;;						
-	alloc		r16=ar.pfs,0,2,1,0		// make a new frame
+	alloc	r16=ar.pfs,0,2,1,0	// make a new frame
 	;;
-	mov		ar.rsc=0
+	mov	ar.rsc=0
 	;;
-	mov		r13=IA64_KR(CURRENT)		// current task pointer
+	mov	r13=IA64_KR(CURRENT)	// current task pointer
 	;;
-	mov		r2=r13
+	mov	r2=r13
 	;;
-	addl		r22=IA64_RBS_OFFSET,r2
+	addl	r22=IA64_RBS_OFFSET,r2
 	;;
-	mov		ar.bspstore=r22
+	mov	ar.bspstore=r22
 	;;
-	addl		sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
+	addl	sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
 	;;
-	adds		r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+	adds	r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
 	;;
-	st1		[r2]=r0				// clear current->thread.on_ustack flag
-	mov		loc0=r16
-	movl		loc1=mca_handler_bh		// recovery C function
+	st1	[r2]=r0		// clear current->thread.on_ustack flag
+	mov	loc0=r16
+	movl	loc1=mca_handler_bh	// recovery C function
 	;;
-	mov		out0=r8				// poisoned address
-	mov		b6=loc1
+	mov	out0=r8			// poisoned address
+	mov	b6=loc1
 	;;
-	mov		loc1=rp
+	mov	loc1=rp
 	;;
-	ssm		psr.i
+	ssm	psr.i
 	;;
-	br.call.sptk.many    rp=b6			// does not return ...
+	br.call.sptk.many rp=b6		// does not return ...
 	;;
-	mov		ar.pfs=loc0
-	mov 		rp=loc1
+	mov	ar.pfs=loc0
+	mov 	rp=loc1
 	;;
-	mov		r8=r0
+	mov	r8=r0
 	br.ret.sptk.many rp
 	;;
 END(mca_handler_bhhook)
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 1650353..d71731e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -574,7 +574,7 @@
 	return 0UL;
 }
 
-static inline unsigned long
+static inline void
 pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
 {
 	spin_unlock(&(x)->ctx_lock);
@@ -2218,12 +2218,13 @@
 pfm_free_fd(int fd, struct file *file)
 {
 	struct files_struct *files = current->files;
-	struct fdtable *fdt = files_fdtable(files);
+	struct fdtable *fdt;
 
 	/* 
 	 * there ie no fd_uninstall(), so we do it here
 	 */
 	spin_lock(&files->file_lock);
+	fdt = files_fdtable(files);
 	rcu_assign_pointer(fdt->fd[fd], NULL);
 	spin_unlock(&files->file_lock);
 
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index 799407e..cb1af59 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -15,7 +15,6 @@
 lib-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
 lib-$(CONFIG_PERFMON)	+= carta_random.o
 lib-$(CONFIG_MD_RAID5)	+= xor.o
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
 
 AFLAGS___divdi3.o	=
 AFLAGS___udivdi3.o	= -DUNSIGNED
diff --git a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c
deleted file mode 100644
index c7ce92f..0000000
--- a/arch/ia64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2003 Jerome Marchand, Bull S.A.
- *	Cleaned up by David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * This file is released under the GPLv2, or at your option any later version.
- *
- * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction.  This
- * code is an adaptation of the x86 version of "atomic_dec_and_lock()".
- */
-
-#include <linux/compiler.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-
-/*
- * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock.  Both of these
- * operations have to be done atomically, so that the count doesn't drop to zero without
- * acquiring the spinlock first.
- */
-int
-_atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock)
-{
-	int old, new;
-
-	do {
-		old = atomic_read(refcount);
-		new = old - 1;
-
-		if (unlikely (old == 1)) {
-			/* oops, we may be decrementing to zero, do it the slow way... */
-			spin_lock(lock);
-			if (atomic_dec_and_test(refcount))
-				return 1;
-			spin_unlock(lock);
-			return 0;
-		}
-	} while (cmpxchg(&refcount->counter, old, new) != old);
-	return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 1ef3987..4d100f3 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -220,11 +220,6 @@
 	  Say Y here if you are building a kernel for a desktop, embedded
 	  or real-time system.  Say N if you are unsure.
 
-config HAVE_DEC_LOCK
-	bool
-	depends on (SMP || PREEMPT)
-	default n
-
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0eb71ac..4cd724c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1009,10 +1009,6 @@
 	bool
 	default y
 
-config HAVE_DEC_LOCK
-	bool
-	default y
-
 #
 # Select some configuration options automatically based on user selections.
 #
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 4de1556..7ae4af4 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -581,18 +581,13 @@
 	}
 
 	/*
-	 * Check if we have enough memory..
+	 * Ok, looks good - let it rip.
 	 */
-	if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+	if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) {
 		ret = -ENOMEM;
 		goto out;
 	}
-
-	/*
-	 * Ok, looks good - let it rip.
-	 */
 	mm->brk = brk;
-	do_brk(oldbrk, newbrk-oldbrk);
 	ret = 0;
 
 out:
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 21b92b9..0373034 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y	+= csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o \
+lib-y	+= csum_partial_copy.o memcpy.o promlib.o \
 	   strlen_user.o strncpy_user.o strnlen_user.o
 
 obj-y	+= iomap.o
diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c
deleted file mode 100644
index fd82c84..0000000
--- a/arch/mips/lib/dec_and_lock.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * MIPS version of atomic_dec_and_lock() using cmpxchg
- *
- * 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/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	int counter;
-	int newcount;
-
-	for (;;) {
-		counter = atomic_read(atomic);
-		newcount = counter - 1;
-		if (!newcount)
-			break;		/* do it the slow way */
-
-		newcount = cmpxchg(&atomic->counter, counter, newcount);
-		if (newcount == counter)
-			return 0;
-	}
-
-	spin_lock(lock);
-	if (atomic_dec_and_test(atomic))
-		return 1;
-	spin_unlock(lock);
-	return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 347ea28..776941c 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -26,10 +26,6 @@
 	bool
 	default y
 
-config HAVE_DEC_LOCK
-	bool
-	default y
-
 config PPC
 	bool
 	default y
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/lib/Makefile b/arch/ppc/lib/Makefile
index f1e1fb4..50358e4 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ppc-specific library files..
 #
 
-obj-y			:= checksum.o string.o strcase.o dec_and_lock.o div64.o
+obj-y			:= checksum.o string.o strcase.o div64.o
 
 obj-$(CONFIG_8xx)	+= rheap.o
 obj-$(CONFIG_CPM2)	+= rheap.o
diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c
deleted file mode 100644
index b18f0d9..0000000
--- a/arch/ppc/lib/dec_and_lock.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	int counter;
-	int newcount;
-
-	for (;;) {
-		counter = atomic_read(atomic);
-		newcount = counter - 1;
-		if (!newcount)
-			break;		/* do it the slow way */
-
-		newcount = cmpxchg(&atomic->counter, counter, newcount);
-		if (newcount == counter)
-			return 0;
-	}
-
-	spin_lock(lock);
-	if (atomic_dec_and_test(atomic))
-		return 1;
-	spin_unlock(lock);
-	return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
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/Makefile b/arch/ppc/syslib/Makefile
index 8b9b226..b8d08f3 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -34,7 +34,8 @@
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o ppc405_pci.o
 endif
 endif
-obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y)
+obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
+				   ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.o i8259.o
 endif
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
new file mode 100644
index 0000000..2b5f0e7
--- /dev/null
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -0,0 +1,224 @@
+/*
+ * arch/ppc/syslib/mpc8xx_devices.c
+ *
+ * MPC8xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/mii.h>
+#include <asm/commproc.h>
+#include <asm/mpc8xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM to do not set dependences at compile time.
+ * They will get fixed up by mach_mpc8xx_fixup
+ */
+
+struct platform_device ppc_sys_platform_devices[] = {
+	[MPC8xx_CPM_FEC1] =	{
+		.name = "fsl-cpm-fec",
+		.id	= 1,
+		.num_resources = 2,
+		.resource = (struct resource[])	{
+			{
+				.name 	= "regs",
+				.start	= 0xe00,
+				.end	= 0xe88,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_FEC1,
+				.end	= MPC8xx_INT_FEC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_FEC2] =	{
+		.name = "fsl-cpm-fec",
+		.id	= 2,
+		.num_resources = 2,
+		.resource = (struct resource[])	{
+			{
+				.name	= "regs",
+				.start	= 0x1e00,
+				.end	= 0x1e88,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_FEC2,
+				.end	= MPC8xx_INT_FEC2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SCC1] = {
+		.name = "fsl-cpm-scc",
+		.id	= 1,
+		.num_resources = 3,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa00,
+				.end	= 0xa18,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name 	= "pram",
+				.start 	= 0x3c00,
+				.end 	= 0x3c80,
+				.flags 	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SCC1,
+				.end	= MPC8xx_INT_SCC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SCC2] = {
+		.name = "fsl-cpm-scc",
+		.id	= 2,
+		.num_resources	= 3,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa20,
+				.end	= 0xa38,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name 	= "pram",
+				.start 	= 0x3d00,
+				.end 	= 0x3d80,
+				.flags 	= IORESOURCE_MEM,
+			},
+
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SCC2,
+				.end	= MPC8xx_INT_SCC2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SCC3] = {
+		.name = "fsl-cpm-scc",
+		.id	= 3,
+		.num_resources	= 3,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa40,
+				.end	= 0xa58,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name 	= "pram",
+				.start 	= 0x3e00,
+				.end 	= 0x3e80,
+				.flags 	= IORESOURCE_MEM,
+			},
+
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SCC3,
+				.end	= MPC8xx_INT_SCC3,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SCC4] = {
+		.name = "fsl-cpm-scc",
+		.id	= 4,
+		.num_resources	= 3,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa60,
+				.end	= 0xa78,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name 	= "pram",
+				.start 	= 0x3f00,
+				.end 	= 0x3f80,
+				.flags 	= IORESOURCE_MEM,
+			},
+
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SCC4,
+				.end	= MPC8xx_INT_SCC4,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SMC1] = {
+		.name = "fsl-cpm-smc",
+		.id	= 1,
+		.num_resources	= 2,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa82,
+				.end	= 0xa91,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SMC1,
+				.end	= MPC8xx_INT_SMC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC8xx_CPM_SMC2] = {
+		.name = "fsl-cpm-smc",
+		.id	= 2,
+		.num_resources	= 2,
+		.resource = (struct resource[]) {
+			{
+				.name	= "regs",
+				.start	= 0xa92,
+				.end	= 0xaa1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "interrupt",
+				.start	= MPC8xx_INT_SMC2,
+				.end	= MPC8xx_INT_SMC2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+};
+
+static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
+{
+	ppc_sys_fixup_mem_resource (pdev, IMAP_ADDR);
+	return 0;
+}
+
+static int __init mach_mpc8xx_init(void)
+{
+	ppc_sys_device_fixup = mach_mpc8xx_fixup;
+	return 0;
+}
+
+postcore_initcall(mach_mpc8xx_init);
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
new file mode 100644
index 0000000..a532ccc
--- /dev/null
+++ b/arch/ppc/syslib/mpc8xx_sys.c
@@ -0,0 +1,61 @@
+/*
+ * arch/ppc/platforms/mpc8xx_sys.c
+ *
+ * MPC8xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec; 
+struct ppc_sys_spec ppc_sys_specs[] = {
+	{
+		.ppc_sys_name	= "MPC86X",
+		.mask 		= 0xFFFFFFFF,
+		.value 		= 0x00000000,
+		.num_devices	= 2,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC8xx_CPM_FEC1,
+			MPC8xx_CPM_SCC1,
+			MPC8xx_CPM_SCC2,
+			MPC8xx_CPM_SCC3,
+			MPC8xx_CPM_SCC4,
+			MPC8xx_CPM_SMC1,
+			MPC8xx_CPM_SMC2,
+		},
+	},
+	{
+		.ppc_sys_name	= "MPC885",
+		.mask 		= 0xFFFFFFFF,
+		.value 		= 0x00000000,
+		.num_devices	= 3,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC8xx_CPM_FEC1,
+			MPC8xx_CPM_FEC2,
+			MPC8xx_CPM_SCC1,
+			MPC8xx_CPM_SCC2,
+			MPC8xx_CPM_SCC3,
+			MPC8xx_CPM_SCC4,
+			MPC8xx_CPM_SMC1,
+			MPC8xx_CPM_SMC2,
+		},
+	},
+	{	/* default match */
+		.ppc_sys_name	= "",
+		.mask 		= 0x00000000,
+		.value 		= 0x00000000,
+	},
+};
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index 2e0ea92..9a7e874 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -575,7 +575,7 @@
  * we need something better to deal with that... Maybe switch to S1 for
  * cpufreq changes
  */
-int openpic2_suspend(struct sys_device *sysdev, u32 state)
+int openpic2_suspend(struct sys_device *sysdev, pm_message_t state)
 {
 	int	i;
 	unsigned long flags;
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/Kconfig b/arch/ppc64/Kconfig
index deca68a..c658650 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -28,10 +28,6 @@
 	bool
 	default y
 
-config HAVE_DEC_LOCK
-	bool
-	default y
-
 config EARLY_PRINTK
 	bool
 	default y
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/head.S b/arch/ppc64/kernel/head.S
index 58c3147..72c6104 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -1649,7 +1649,7 @@
 	ld	r3,0(r3)
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags		 */
 	andi.	r3,r3,PLATFORM_LPAR	/* Test if bit 0 is set (LPAR bit) */
-	bne	98f
+	beq	98f			/* branch if result is 0  */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
 	cmpwi	r3,0x37			/* SStar  */
@@ -1813,7 +1813,7 @@
 	ld	r3,0(r3)
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	andi.	r3,r3,PLATFORM_LPAR	/* Test if bit 0 is set (LPAR bit) */
-	bne	98f
+	beq	98f			/* branch if result is 0  */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
 	cmpwi	r3,0x37			/* SStar */
@@ -1834,7 +1834,7 @@
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	/* Test if bit 0 is set (LPAR bit) */
 	andi.	r3,r3,PLATFORM_LPAR
-	bne	98f
+	bne	98f			/* branch if result is !0  */
 	LOADADDR(r6,_SDR1)		/* Only if NOT LPAR */
 	sub	r6,r6,r26
 	ld	r6,0(r6)		/* get the value of _SDR1 */
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index bfadccc..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;
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
index 4777676..efa985f 100644
--- a/arch/ppc64/kernel/vdso.c
+++ b/arch/ppc64/kernel/vdso.c
@@ -224,10 +224,7 @@
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (vma == NULL)
 		return -ENOMEM;
-	if (security_vm_enough_memory(vdso_pages)) {
-		kmem_cache_free(vm_area_cachep, vma);
-		return -ENOMEM;
-	}
+
 	memset(vma, 0, sizeof(*vma));
 
 	/*
@@ -237,8 +234,10 @@
 	 */
 	vdso_base = get_unmapped_area(NULL, vdso_base,
 				      vdso_pages << PAGE_SHIFT, 0, 0);
-	if (vdso_base & ~PAGE_MASK)
+	if (vdso_base & ~PAGE_MASK) {
+		kmem_cache_free(vm_area_cachep, vma);
 		return (int)vdso_base;
+	}
 
 	current->thread.vdso_base = vdso_base;
 
@@ -266,7 +265,11 @@
 	vma->vm_ops = &vdso_vmops;
 
 	down_write(&mm->mmap_sem);
-	insert_vm_struct(mm, vma);
+	if (insert_vm_struct(mm, vma)) {
+		up_write(&mm->mmap_sem);
+		kmem_cache_free(vm_area_cachep, vma);
+		return -ENOMEM;
+	}
 	mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	up_write(&mm->mmap_sem);
 
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
index 76fbfa9..0b6e967 100644
--- a/arch/ppc64/lib/Makefile
+++ b/arch/ppc64/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for ppc64-specific library files..
 #
 
-lib-y := checksum.o dec_and_lock.o string.o strcase.o
+lib-y := checksum.o string.o strcase.o
 lib-y += copypage.o memcpy.o copyuser.o usercopy.o
 
 # Lock primitives are defined as no-ops in include/linux/spinlock.h
diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c
deleted file mode 100644
index 7b9d4da..0000000
--- a/arch/ppc64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ppc64 version of atomic_dec_and_lock() using cmpxchg
- *
- * 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/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * This is an implementation of the notion of "decrement a
- * reference count, and return locked if it decremented to zero".
- *
- * This implementation can be used on any architecture that
- * has a cmpxchg, and where atomic->value is an int holding
- * the value of the atomic (i.e. the high bits aren't used
- * for a lock or anything like that).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	int counter;
-	int newcount;
-
-	for (;;) {
-		counter = atomic_read(atomic);
-		newcount = counter - 1;
-		if (!newcount)
-			break;		/* do it the slow way */
-
-		newcount = cmpxchg(&atomic->counter, counter, newcount);
-		if (newcount == counter)
-			return 0;
-	}
-
-	spin_lock(lock);
-	if (atomic_dec_and_test(atomic))
-		return 1;
-	spin_unlock(lock);
-	return 0;
-}
-
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 7fbc68b..be3f25c 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -38,6 +38,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/kdebug.h>
+#include <asm/siginfo.h>
 
 /*
  * Check whether the instruction at regs->nip is a store using
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 0865251..45d44c6 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc4
-# Fri Jul 29 14:49:30 2005
+# Linux kernel version: 2.6.14-rc1
+# Wed Sep 14 16:46:19 2005
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -21,6 +21,7 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -33,6 +34,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 is not set
@@ -94,6 +96,7 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 
 #
 # I/O subsystem configuration
@@ -151,8 +154,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
@@ -165,6 +168,11 @@
 # CONFIG_NETFILTER is not set
 
 #
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
@@ -217,9 +225,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
 # CONFIG_PCMCIA is not set
 
 #
@@ -233,6 +243,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -260,6 +271,7 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -280,7 +292,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -384,6 +395,10 @@
 CONFIG_TUN=m
 
 #
+# PHY device support
+#
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -453,10 +468,6 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -465,6 +476,7 @@
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -485,11 +497,10 @@
 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_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -533,6 +544,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
@@ -572,6 +584,7 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
@@ -626,5 +639,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=m
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index ab1e49d2..8584dd8 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,7 +6,7 @@
 
 obj-y	:=  bitmap.o traps.o time.o process.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-            semaphore.o s390_ext.o debug.o profile.o irq.o
+            semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
 
 extra-$(CONFIG_ARCH_S390_31)	+= head.o 
 extra-$(CONFIG_ARCH_S390X)	+= head64.o 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 58fc7fb..9b30f4c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -108,7 +108,7 @@
 	bl	BASED(0f)
 	l	%r14,BASED(.Lcleanup_critical)
 	basr	%r14,%r14
-	tm	0(%r12),0x01		# retest problem state after cleanup
+	tm	1(%r12),0x01		# retest problem state after cleanup
 	bnz	BASED(1f)
 0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
 	slr	%r14,%r15
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d0c9ffa..7b9b4a2 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -101,7 +101,7 @@
 	clc	\psworg+8(8),BASED(.Lcritical_start)
 	jl	0f
 	brasl	%r14,cleanup_critical
-	tm	0(%r12),0x01		# retest problem state after cleanup
+	tm	1(%r12),0x01		# retest problem state after cleanup
 	jnz	1f
 0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the async. stack ?
 	slgr	%r14,%r15
diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c
new file mode 100644
index 0000000..83cb42b
--- /dev/null
+++ b/arch/s390/kernel/reipl_diag.c
@@ -0,0 +1,39 @@
+/*
+ * This file contains the implementation of the
+ * Linux re-IPL support
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Volker Sameske (sameske@de.ibm.com)
+ *
+ */
+
+#include <linux/kernel.h>
+
+static unsigned int reipl_diag_rc1;
+static unsigned int reipl_diag_rc2;
+
+/*
+ * re-IPL the system using the last used IPL parameters
+ */
+void reipl_diag(void)
+{
+        asm volatile (
+		"   la   %%r4,0\n"
+		"   la   %%r5,0\n"
+                "   diag %%r4,%2,0x308\n"
+                "0:\n"
+		"   st   %%r4,%0\n"
+		"   st   %%r5,%1\n"
+                ".section __ex_table,\"a\"\n"
+#ifdef __s390x__
+                "   .align 8\n"
+                "   .quad 0b, 0b\n"
+#else
+                "   .align 4\n"
+                "   .long 0b, 0b\n"
+#endif
+                ".previous\n"
+                : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2)
+		: "d" (3) : "cc", "4", "5" );
+}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 5ba5a54..5204778 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -261,8 +261,11 @@
  * Reboot, halt and power_off routines for non SMP.
  */
 extern void reipl(unsigned long devno);
+extern void reipl_diag(void);
 static void do_machine_restart_nonsmp(char * __unused)
 {
+	reipl_diag();
+
 	if (MACHINE_IS_VM)
 		cpcmd ("IPL", NULL, 0);
 	else
@@ -634,6 +637,7 @@
         struct cpuinfo_S390 *cpuinfo;
 	unsigned long n = (unsigned long) v - 1;
 
+	preempt_disable();
 	if (!n) {
 		seq_printf(m, "vendor_id       : IBM/S390\n"
 			       "# processors    : %i\n"
@@ -658,6 +662,7 @@
 			       cpuinfo->cpu_id.ident,
 			       cpuinfo->cpu_id.machine);
 	}
+	preempt_enable();
         return 0;
 }
 
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 85222fe..e13c87b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -65,6 +65,7 @@
 extern char vmpoff_cmd[];
 
 extern void reipl(unsigned long devno);
+extern void reipl_diag(void);
 
 static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
@@ -283,6 +284,8 @@
 	 * interrupted by an external interrupt and s390irq
 	 * locks are always held disabled).
 	 */
+	reipl_diag();
+
 	if (MACHINE_IS_VM)
 		cpcmd ("IPL", NULL, 0, NULL);
 	else
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index cd8d39fb..af0e941 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -33,14 +33,6 @@
 	depends on DEBUG_KERNEL
 	bool "Debug BOOTMEM initialization"
 
-# We have a custom atomic_dec_and_lock() implementation but it's not
-# compatible with spinlock debugging so we need to fall back on
-# the generic version in that case.
-config HAVE_DEC_LOCK
-	bool
-	depends on SMP && !DEBUG_SPINLOCK
-	default y
-
 config MCOUNT
 	bool
 	depends on STACK_DEBUG
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index cbb5e59..fb7a537 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -163,9 +163,6 @@
 EXPORT_SYMBOL(atomic64_add_ret);
 EXPORT_SYMBOL(atomic64_sub);
 EXPORT_SYMBOL(atomic64_sub_ret);
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
 
 /* Atomic bit operations. */
 EXPORT_SYMBOL(test_and_set_bit);
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index d968aeb..c295806 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -14,6 +14,4 @@
 	 copy_in_user.o user_fixup.o memmove.o \
 	 mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
 
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
-
 obj-y += iomap.o
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S
deleted file mode 100644
index 8ee288d..0000000
--- a/arch/sparc64/lib/dec_and_lock.S
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $Id: dec_and_lock.S,v 1.5 2001/11/18 00:12:56 davem Exp $
- * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
- *                 using cas and ldstub instructions.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- */
-#include <linux/config.h>
-#include <asm/thread_info.h>
-
-	.text
-	.align	64
-
-	/* CAS basically works like this:
-	 *
-	 * void CAS(MEM, REG1, REG2)
-	 * {
-	 *   START_ATOMIC();
-	 *   if (*(MEM) == REG1) {
-	 *     TMP = *(MEM);
-	 *     *(MEM) = REG2;
-	 *     REG2 = TMP;
-	 *   } else
-	 *     REG2 = *(MEM);
-	 *   END_ATOMIC();
-	 * }
-	 */
-
-	.globl	_atomic_dec_and_lock
-_atomic_dec_and_lock:	/* %o0 = counter, %o1 = lock */
-loop1:	lduw	[%o0], %g2
-	subcc	%g2, 1, %g7
-	be,pn	%icc, start_to_zero
-	 nop
-nzero:	cas	[%o0], %g2, %g7
-	cmp	%g2, %g7
-	bne,pn	%icc, loop1
-	 mov	0, %g1
-
-out:
-	membar	#StoreLoad | #StoreStore
-	retl
-	 mov	%g1, %o0
-start_to_zero:
-#ifdef CONFIG_PREEMPT
-	ldsw	[%g6 + TI_PRE_COUNT], %g3
-	add	%g3, 1, %g3
-	stw	%g3, [%g6 + TI_PRE_COUNT]
-#endif
-to_zero:
-	ldstub	[%o1], %g3
-	membar	#StoreLoad | #StoreStore
-	brnz,pn	%g3, spin_on_lock
-	 nop
-loop2:	cas	[%o0], %g2, %g7		/* ASSERT(g7 == 0) */
-	cmp	%g2, %g7
-
-	be,pt	%icc, out
-	 mov	1, %g1
-	lduw	[%o0], %g2
-	subcc	%g2, 1, %g7
-	be,pn	%icc, loop2
-	 nop
-	membar	#StoreStore | #LoadStore
-	stb	%g0, [%o1]
-#ifdef CONFIG_PREEMPT
-	ldsw	[%g6 + TI_PRE_COUNT], %g3
-	sub	%g3, 1, %g3
-	stw	%g3, [%g6 + TI_PRE_COUNT]
-#endif
-
-	b,pt	%xcc, nzero
-	 nop
-spin_on_lock:
-	ldub	[%o1], %g3
-	membar	#LoadLoad
-	brnz,pt	%g3, spin_on_lock
-	 nop
-	ba,pt	%xcc, to_zero
-	 nop
-	nop
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 8ad156a..5d92cac 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -42,3 +42,7 @@
 config ARCH_REUSE_HOST_VSYSCALL_AREA
 	bool
 	default y
+
+config X86_CMPXCHG
+	bool
+	default y
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 7a0d115..5db136e 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -13,7 +13,6 @@
 
 #include <errno.h>
 #include <unistd.h>
-#include <linux/inet.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/time.h>
@@ -55,7 +54,7 @@
 	struct mcast_data *pri = data;
 	struct sockaddr_in *sin = pri->mcast_addr;
 	struct ip_mreq mreq;
-	int fd = -EINVAL, yes = 1, err = -EINVAL;;
+	int fd, yes = 1, err = 0;
 
 
 	if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
@@ -66,13 +65,14 @@
 	if (fd < 0){
 		printk("mcast_open : data socket failed, errno = %d\n", 
 		       errno);
-		fd = -errno;
+		err = -errno;
 		goto out;
 	}
 
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
 			errno);
+		err = -errno;
 		goto out_close;
 	}
 
@@ -81,6 +81,7 @@
 		       sizeof(pri->ttl)) < 0) {
 		printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
 			errno);
+		err = -errno;
 		goto out_close;
 	}
 
@@ -88,12 +89,14 @@
 	if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
 			errno);
+		err = -errno;
 		goto out_close;
 	}
 
 	/* bind socket to mcast address */
 	if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
 		printk("mcast_open : data bind failed, errno = %d\n", errno);
+		err = -errno;
 		goto out_close;
 	}		
 	
@@ -108,14 +111,15 @@
 		       "interface on the host.\n");
 		printk("eth0 should be configured in order to use the "
 		       "multicast transport.\n");
+		err = -errno;
                 goto out_close;
 	}
 
- out:
 	return fd;
 
  out_close:
         os_close_file(fd);
+ out:
         return err;
 }
 
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index c190c24..12c9536 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -32,6 +32,7 @@
 #include "os.h"
 #include "umid.h"
 #include "irq_kern.h"
+#include "choose-mode.h"
 
 static int do_unlink_socket(struct notifier_block *notifier, 
 			    unsigned long what, void *data)
@@ -276,6 +277,7 @@
     go - continue the UML after a 'stop' \n\
     log <string> - make UML enter <string> into the kernel log\n\
     proc <file> - returns the contents of the UML's /proc/<file>\n\
+    stack <pid> - returns the stack of the specified pid\n\
 "
 
 void mconsole_help(struct mc_request *req)
@@ -479,6 +481,56 @@
 }
 #endif
 
+/* Mconsole stack trace
+ *  Added by Allan Graves, Jeff Dike
+ *  Dumps a stacks registers to the linux console.
+ *  Usage stack <pid>.
+ */
+void do_stack(struct mc_request *req)
+{
+        char *ptr = req->request.data;
+        int pid_requested= -1;
+        struct task_struct *from = NULL;
+	struct task_struct *to = NULL;
+
+        /* Would be nice:
+         * 1) Send showregs output to mconsole.
+	 * 2) Add a way to stack dump all pids.
+	 */
+
+        ptr += strlen("stack");
+        while(isspace(*ptr)) ptr++;
+
+        /* Should really check for multiple pids or reject bad args here */
+        /* What do the arguments in mconsole_reply mean? */
+        if(sscanf(ptr, "%d", &pid_requested) == 0){
+                mconsole_reply(req, "Please specify a pid", 1, 0);
+                return;
+        }
+
+        from = current;
+        to = find_task_by_pid(pid_requested);
+
+        if((to == NULL) || (pid_requested == 0)) {
+                mconsole_reply(req, "Couldn't find that pid", 1, 0);
+                return;
+        }
+        to->thread.saved_task = current;
+
+        switch_to(from, to, from);
+        mconsole_reply(req, "Stack Dumped to console and message log", 0, 0);
+}
+
+void mconsole_stack(struct mc_request *req)
+{
+	/* This command doesn't work in TT mode, so let's check and then
+	 * get out of here
+	 */
+	CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
+				   1, 0),
+		    do_stack(req));
+}
+
 /* Changed by mconsole_setup, which is __setup, and called before SMP is
  * active.
  */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index fe5afb132..310c1f8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -30,6 +30,7 @@
 	{ "go", mconsole_go, MCONSOLE_INTR },
 	{ "log", mconsole_log, MCONSOLE_INTR },
 	{ "proc", mconsole_proc, MCONSOLE_PROC },
+        { "stack", mconsole_stack, MCONSOLE_INTR },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -172,9 +173,9 @@
 	if(notify_sock < 0){
 		notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
 		if(notify_sock < 0){
-			printk("mconsole_notify - socket failed, errno = %d\n",
-			       errno);
 			err = -errno;
+			printk("mconsole_notify - socket failed, errno = %d\n",
+			       err);
 		}
 	}
 	unlock_notify();
@@ -197,8 +198,8 @@
 	n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, 
 		   sizeof(target));
 	if(n < 0){
-		printk("mconsole_notify - sendto failed, errno = %d\n", errno);
 		err = -errno;
+		printk("mconsole_notify - sendto failed, errno = %d\n", errno);
 	}
 	return(err);
 }
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index ed84d01..0306a1b 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -43,8 +43,9 @@
 
 	fd = get_pty();
 	if(fd < 0){
+		err = -errno;
 		printk("open_pts : Failed to open pts\n");
-		return(-errno);
+		return err;
 	}
 	if(data->raw){
 		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
deleted file mode 100644
index b94d2bc4f..0000000
--- a/arch/um/drivers/ubd_user.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
- */
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sched.h>
-#include <signal.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/mman.h>
-#include <sys/param.h>
-#include "asm/types.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "ubd_user.h"
-#include "os.h"
-#include "cow.h"
-
-#include <endian.h>
-#include <byteswap.h>
-
-void ignore_sigwinch_sig(void)
-{
-	signal(SIGWINCH, SIG_IGN);
-}
-
-int start_io_thread(unsigned long sp, int *fd_out)
-{
-	int pid, fds[2], err;
-
-	err = os_pipe(fds, 1, 1);
-	if(err < 0){
-		printk("start_io_thread - os_pipe failed, err = %d\n", -err);
-		goto out;
-	}
-
-	kernel_fd = fds[0];
-	*fd_out = fds[1];
-
-	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
-		    NULL);
-	if(pid < 0){
-		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		err = -errno;
-		goto out_close;
-	}
-
-	return(pid);
-
- out_close:
-	os_close_file(fds[0]);
-	os_close_file(fds[1]);
-	kernel_fd = -1;
-	*fd_out = -1;
- out:
-	return(err);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 93dc191..90e0e5f 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -110,13 +110,15 @@
 
 	fd = mkstemp(file);
 	if(fd < 0){
+		err = -errno;
 		printk("xterm_open : mkstemp failed, errno = %d\n", errno);
-		return(-errno);
+		return err;
 	}
 
 	if(unlink(file)){
+		err = -errno;
 		printk("xterm_open : unlink failed, errno = %d\n", errno);
-		return(-errno);
+		return err;
 	}
 	os_close_file(fd);
 
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index cfa368e..b1b512f 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -81,6 +81,7 @@
 extern void mconsole_go(struct mc_request *req);
 extern void mconsole_log(struct mc_request *req);
 extern void mconsole_proc(struct mc_request *req);
+extern void mconsole_stack(struct mc_request *req);
 
 extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index d6404bb..9fef412 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -51,7 +51,6 @@
 
 extern void check_devanon(void);
 extern int init_mem_user(void);
-extern int create_mem_file(unsigned long len);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
 extern int init_maps(unsigned long physmem, unsigned long iomem,
@@ -64,20 +63,6 @@
 extern void unmap_physmem(void);
 extern void map_memory(unsigned long virt, unsigned long phys,
 		       unsigned long len, int r, int w, int x);
-extern int protect_memory(unsigned long addr, unsigned long len, 
-			  int r, int w, int x, int must_succeed);
 extern unsigned long get_kmem_end(void);
-extern void check_tmpexec(void);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 4c36245..583329d 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -157,6 +157,9 @@
 extern void os_early_checks(void);
 extern int can_do_skas(void);
 
+/* mem.c */
+extern int create_mem_file(unsigned long len);
+
 /* process.c */
 extern unsigned long os_process_pc(int pid);
 extern int os_process_parent(int pid);
@@ -181,6 +184,8 @@
 /* tt.c
  * for tt mode only (will be deleted in future...)
  */
+extern int protect_memory(unsigned long addr, unsigned long len,
+			  int r, int w, int x, int must_succeed);
 extern void forward_pending_sigio(int target);
 extern int start_fork_tramp(void *arg, unsigned long temp_stack,
 			    int clone_flags, int (*tramp)(void *));
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 614b8eb..1a0001b 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
@@ -7,11 +7,11 @@
 clean-files :=
 
 obj-y = config.o exec_kern.o exitcode.o \
-	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
-	physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
-	sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \
-	tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \
-	uaccess_user.o um_arch.o umid.o user_util.o
+	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \
+	process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
+	signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
+	time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
+	umid.o user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
@@ -24,8 +24,8 @@
 
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
-USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \
-	tty_log.o umid.o user_util.o
+USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \
+	user_util.o
 
 include arch/um/scripts/Makefile.rules
 
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
index f83e1e8..33fb0bd 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/kernel/helper.c
@@ -85,8 +85,8 @@
 	data.fd = fds[1];
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if(pid < 0){
-		printk("run_helper : clone failed, errno = %d\n", errno);
 		ret = -errno;
+		printk("run_helper : clone failed, errno = %d\n", errno);
 		goto out_close;
 	}
 
@@ -122,7 +122,7 @@
 		      unsigned long *stack_out, int stack_order)
 {
 	unsigned long stack, sp;
-	int pid, status;
+	int pid, status, err;
 
 	stack = alloc_stack(stack_order, um_in_interrupt());
 	if(stack == 0) return(-ENOMEM);
@@ -130,16 +130,18 @@
 	sp = stack + (page_size() << stack_order) - sizeof(void *);
 	pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
 	if(pid < 0){
+		err = -errno;
 		printk("run_helper_thread : clone failed, errno = %d\n", 
 		       errno);
-		return(-errno);
+		return err;
 	}
 	if(stack_out == NULL){
 		CATCH_EINTR(pid = waitpid(pid, &status, 0));
 		if(pid < 0){
+			err = -errno;
 			printk("run_helper_thread - wait failed, errno = %d\n",
 			       errno);
-			pid = -errno;
+			pid = err;
 		}
 		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
@@ -156,8 +158,8 @@
 
 	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
 	if(ret < 0){
+		ret = -errno;
 		printk("helper_wait : waitpid failed, errno = %d\n", errno);
-		return(-errno);
 	}
 	return(ret);
 }
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cd7c85b..49ed5dd 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -13,6 +13,7 @@
 #include "asm/pgtable.h"
 #include "user_util.h"
 #include "mem_user.h"
+#include "os.h"
 
 static struct fs_struct init_fs = INIT_FS;
 struct mm_struct init_mm = INIT_MM(init_mm);
@@ -45,8 +46,8 @@
 
 void unprotect_stack(unsigned long stack)
 {
-	protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 
-		       1, 1, 0, 1);
+	os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
+		       1, 1, 0);
 }
 
 /*
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 64fa062..ea008b0 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -19,6 +19,10 @@
 #include "mem_user.h"
 #include "uml_uaccess.h"
 #include "os.h"
+#include "linux/types.h"
+#include "linux/string.h"
+#include "init.h"
+#include "kern_constants.h"
 
 extern char __binary_start;
 
@@ -368,6 +372,16 @@
 	return pte;
 }
 
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
+extern int parse_iomem(char *str, int *add) __init;
+
+__uml_setup("iomem=", parse_iomem,
+"iomem=<name>,<file>\n"
+"    Configure <file> as an IO memory region named <name>.\n\n"
+);
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
deleted file mode 100644
index 4a663fd..0000000
--- a/arch/um/kernel/mem_user.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * arch/um/kernel/mem_user.c
- *
- * BRIEF MODULE DESCRIPTION
- * user side memory routines for supporting IO memory inside user mode linux
- *
- * Copyright (C) 2001 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *         Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``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.
- *
- *  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 <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include "kern_util.h"
-#include "user.h"
-#include "user_util.h"
-#include "mem_user.h"
-#include "init.h"
-#include "os.h"
-#include "tempfile.h"
-#include "kern_constants.h"
-
-#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-
-static int create_tmp_file(unsigned long len)
-{
-	int fd, err;
-	char zero;
-
-	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
-	if(fd < 0) {
-		os_print_error(fd, "make_tempfile");
-		exit(1);
-	}
-
-	err = os_mode_fd(fd, 0777);
-	if(err < 0){
-		os_print_error(err, "os_mode_fd");
-		exit(1);
-	}
-	err = os_seek_file(fd, len);
-	if(err < 0){
-		os_print_error(err, "os_seek_file");
-		exit(1);
-	}
-	zero = 0;
-	err = os_write_file(fd, &zero, 1);
-	if(err != 1){
-		os_print_error(err, "os_write_file");
-		exit(1);
-	}
-
-	return(fd);
-}
-
-void check_tmpexec(void)
-{
-	void *addr;
-	int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
-	addr = mmap(NULL, UM_KERN_PAGE_SIZE,
-		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
-	printf("Checking PROT_EXEC mmap in /tmp...");
-	fflush(stdout);
-	if(addr == MAP_FAILED){
-		err = errno;
-		perror("failed");
-		if(err == EPERM)
-			printf("/tmp must be not mounted noexec\n");
-		exit(1);
-	}
-	printf("OK\n");
-	munmap(addr, UM_KERN_PAGE_SIZE);
-
-	os_close_file(fd);
-}
-
-static int have_devanon = 0;
-
-void check_devanon(void)
-{
-	int fd;
-
-	printk("Checking for /dev/anon on the host...");
-	fd = open("/dev/anon", O_RDWR);
-	if(fd < 0){
-		printk("Not available (open failed with errno %d)\n", errno);
-		return;
-	}
-
-	printk("OK\n");
-	have_devanon = 1;
-}
-
-static int create_anon_file(unsigned long len)
-{
-	void *addr;
-	int fd;
-
-	fd = open("/dev/anon", O_RDWR);
-	if(fd < 0) {
-		os_print_error(fd, "opening /dev/anon");
-		exit(1);
-	}
-
-	addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-	if(addr == MAP_FAILED){
-		perror("mapping physmem file");
-		exit(1);
-	}
-	munmap(addr, len);
-
-	return(fd);
-}
-
-int create_mem_file(unsigned long len)
-{
-	int err, fd;
-
-	if(have_devanon)
-		fd = create_anon_file(len);
-	else fd = create_tmp_file(len);
-
-	err = os_set_exec_close(fd, 1);
-	if(err < 0)
-		os_print_error(err, "exec_close");
-	return(fd);
-}
-
-struct iomem_region *iomem_regions = NULL;
-int iomem_size = 0;
-
-static int __init parse_iomem(char *str, int *add)
-{
-	struct iomem_region *new;
-	struct uml_stat buf;
-	char *file, *driver;
-	int fd, err, size;
-
-	driver = str;
-	file = strchr(str,',');
-	if(file == NULL){
-		printf("parse_iomem : failed to parse iomem\n");
-		goto out;
-	}
-	*file = '\0';
-	file++;
-	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
-	if(fd < 0){
-		os_print_error(fd, "parse_iomem - Couldn't open io file");
-		goto out;
-	}
-
-	err = os_stat_fd(fd, &buf);
-	if(err < 0){
-		os_print_error(err, "parse_iomem - cannot stat_fd file");
-		goto out_close;
-	}
-
-	new = malloc(sizeof(*new));
-	if(new == NULL){
-		perror("Couldn't allocate iomem_region struct");
-		goto out_close;
-	}
-
-	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
-
-	*new = ((struct iomem_region) { .next		= iomem_regions,
-					.driver		= driver,
-					.fd		= fd,
-					.size		= size,
-					.phys		= 0,
-					.virt		= 0 });
-	iomem_regions = new;
-	iomem_size += new->size + UM_KERN_PAGE_SIZE;
-
-	return(0);
- out_close:
-	os_close_file(fd);
- out:
-	return(1);
-}
-
-__uml_setup("iomem=", parse_iomem,
-"iomem=<name>,<file>\n"
-"    Configure <file> as an IO memory region named <name>.\n\n"
-);
-
-int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
-		   int must_succeed)
-{
-	int err;
-
-	err = os_protect_memory((void *) addr, len, r, w, x);
-	if(err < 0){
-                if(must_succeed)
-			panic("protect failed, err = %d", -err);
-		else return(err);
-	}
-	return(0);
-}
-
-#if 0
-/* Debugging facility for dumping stuff out to the host, avoiding the timing
- * problems that come with printf and breakpoints.
- * Enable in case of emergency.
- */
-
-int logging = 1;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[512];
-
-void log(char *fmt, ...)
-{
-        va_list ap;
-        struct timeval tv;
-        struct openflags flags;
-
-        if(logging == 0) return;
-        if(logging_fd < 0){
-                flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
-                logging_fd = os_open_file("log", flags, 0644);
-        }
-        gettimeofday(&tv, NULL);
-        sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec,
-                tv.tv_usec);
-        va_start(ap, fmt);
-        vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
-        va_end(ap);
-        write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index c23d8a0..39cf568 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -113,8 +113,23 @@
 
 void *_switch_to(void *prev, void *next, void *last)
 {
-	return(CHOOSE_MODE(switch_to_tt(prev, next), 
-			   switch_to_skas(prev, next)));
+        struct task_struct *from = prev;
+        struct task_struct *to= next;
+
+        to->thread.prev_sched = from;
+        set_current(to);
+
+	do {
+		current->thread.saved_task = NULL ;
+		CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+		if(current->thread.saved_task)
+			show_regs(&(current->thread.regs));
+		next= current->thread.saved_task;
+		prev= current;
+	} while(current->thread.saved_task);
+
+        return(current->thread.prev_sched);
+
 }
 
 void interrupt_end(void)
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h
index e484900..c97a80d 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/kernel/skas/include/mode_kern-skas.h
@@ -11,7 +11,7 @@
 #include "asm/ptrace.h"
 
 extern void flush_thread_skas(void);
-extern void *switch_to_skas(void *prev, void *next);
+extern void switch_to_skas(void *prev, void *next);
 extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
 			      unsigned long esp);
 extern int copy_thread_skas(int nr, unsigned long clone_flags,
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 3d1b227..efe92e8 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -24,7 +24,7 @@
 #include "proc_mm.h"
 #include "registers.h"
 
-void *switch_to_skas(void *prev, void *next)
+void switch_to_skas(void *prev, void *next)
 {
 	struct task_struct *from, *to;
 
@@ -35,16 +35,11 @@
 	if(current->pid == 0)
 		switch_timers(0);
 
-	to->thread.prev_sched = from;
-	set_current(to);
-
 	switch_threads(&from->thread.mode.skas.switch_buf, 
 		       to->thread.mode.skas.switch_buf);
 
 	if(current->pid == 0)
 		switch_timers(1);
-
-	return(current->thread.prev_sched);
 }
 
 extern void schedule_tail(struct task_struct *prev);
diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c
deleted file mode 100644
index b1674bc..0000000
--- a/arch/um/kernel/tempfile.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/param.h>
-#include "init.h"
-
-/* Modified from create_mem_file and start_debugger */
-static char *tempdir = NULL;
-
-static void __init find_tempdir(void)
-{
-	char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
-	int i;
-	char *dir = NULL;
-
-	if(tempdir != NULL) return;	/* We've already been called */
-	for(i = 0; dirs[i]; i++){
-		dir = getenv(dirs[i]);
-		if((dir != NULL) && (*dir != '\0'))
-			break;
-	}
-	if((dir == NULL) || (*dir == '\0')) 
-		dir = "/tmp";
-
-	tempdir = malloc(strlen(dir) + 2);
-	if(tempdir == NULL){
-		fprintf(stderr, "Failed to malloc tempdir, "
-			"errno = %d\n", errno);
-		return;
-	}
-	strcpy(tempdir, dir);
-	strcat(tempdir, "/");
-}
-
-int make_tempfile(const char *template, char **out_tempname, int do_unlink)
-{
-	char tempname[MAXPATHLEN];
-	int fd;
-
-	find_tempdir();
-	if (*template != '/')
-		strcpy(tempname, tempdir);
-	else
-		*tempname = 0;
-	strcat(tempname, template);
-	fd = mkstemp(tempname);
-	if(fd < 0){
-		fprintf(stderr, "open - cannot create %s: %s\n", tempname, 
-			strerror(errno));
-		return -1;
-	}
-	if(do_unlink && (unlink(tempname) < 0)){
-		perror("unlink");
-		return -1;
-	}
-	if(out_tempname){
-		*out_tempname = strdup(tempname);
-		if(*out_tempname == NULL){
-			perror("strdup");
-			return -1;
-		}
-	}
-	return(fd);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 80ed618..0a562c3 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -307,7 +307,7 @@
                 }
                 else if(pte_newprot(*pte)){
                         updated = 1;
-                        protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+                        os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1);
                 }
                 addr += PAGE_SIZE;
         }
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h
index e0ca0e0..2a35b15 100644
--- a/arch/um/kernel/tt/include/mode_kern-tt.h
+++ b/arch/um/kernel/tt/include/mode_kern-tt.h
@@ -11,7 +11,7 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 
-extern void *switch_to_tt(void *prev, void *next);
+extern void switch_to_tt(void *prev, void *next);
 extern void flush_thread_tt(void);
 extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
 			   unsigned long esp);
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
index 3085267..03e5898 100644
--- a/arch/um/kernel/tt/mem_user.c
+++ b/arch/um/kernel/tt/mem_user.c
@@ -12,6 +12,7 @@
 #include "tt.h"
 #include "mem_user.h"
 #include "user_util.h"
+#include "os.h"
 
 void remap_data(void *segment_start, void *segment_end, int w)
 {
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index a189a2b..0de05a268 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -26,7 +26,7 @@
 #include "init.h"
 #include "tt.h"
 
-void *switch_to_tt(void *prev, void *next, void *last)
+int switch_to_tt(void *prev, void *next, void *last)
 {
 	struct task_struct *from, *to, *prev_sched;
 	unsigned long flags;
@@ -36,8 +36,6 @@
 	from = prev;
 	to = next;
 
-	to->thread.prev_sched = from;
-
 	cpu = from->thread_info->cpu;
 	if(cpu == 0)
 		forward_interrupts(to->thread.mode.tt.extern_pid);
@@ -53,7 +51,6 @@
 	forward_pending_sigio(to->thread.mode.tt.extern_pid);
 
 	c = 0;
-	set_current(to);
 
 	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
 	if(err != sizeof(c))
@@ -85,8 +82,6 @@
 
 	flush_tlb_all();
 	local_irq_restore(flags);
-
-	return(current->thread.prev_sched);
 }
 
 void release_thread_tt(struct task_struct *task)
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 09f6f7c..f0a2759 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -361,11 +361,6 @@
 	uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
 				     &host_task_size, &task_size);
 
-	/* Need to check this early because mmapping happens before the
-	 * kernel is running.
-	 */
-	check_tmpexec();
-
 	brk_start = (unsigned long) sbrk(0);
 	CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
 	/* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 954ff67..a25f3ea 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -109,18 +109,14 @@
 	int err;
 
 	CATCH_EINTR(err = tcgetattr(fd, &tt));
-	if (err < 0) {
-			printk("tcgetattr failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if(err < 0)
+		return -errno;
 
 	cfmakeraw(&tt);
 
  	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
-	if (err < 0) {
-			printk("tcsetattr failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if(err < 0)
+		return -errno;
 
 	/* XXX tcsetattr could have applied only some changes
 	 * (and cfmakeraw() is a set of changes) */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 7a16624..d15ec2a 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,11 +3,11 @@
 # Licensed under the GPL
 #
 
-obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
-	tty.o user_syms.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \
+	tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/
 
-USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \
-	tty.o
+USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \
+	time.o tt.o tty.o
 
 elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
 CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index b04897c..298d563 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -117,6 +117,8 @@
         err = io_submit(ctx, 1, &iocbp);
         if(err > 0)
                 err = 0;
+	else
+		err = -errno;
 
  out:
         return err;
@@ -142,7 +144,7 @@
                                "errno = %d\n", errno);
                 }
                 else {
-			aio = (struct aio_context *) event.data;
+			aio = (struct aio_context *) (long) event.data;
 			if(update_aio(aio, event.res)){
 				do_aio(ctx, aio);
 				continue;
@@ -313,15 +315,16 @@
         int err;
 
         if(io_setup(256, &ctx)){
+		err = -errno;
                 printk("aio_thread failed to initialize context, err = %d\n",
                        errno);
-                return -errno;
+                return err;
         }
 
         err = run_helper_thread(aio_thread, NULL,
                                 CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
         if(err < 0)
-                return -errno;
+                return err;
 
         aio_pid = err;
 
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 4b83c6c..4ba9b17 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -75,7 +75,7 @@
 	struct msghdr msg;
 	struct cmsghdr *cmsg;
 	struct iovec iov;
-	int pid, n;
+	int pid, n, err;
 
 	sprintf(version_buf, "%d", UML_NET_VERSION);
 
@@ -105,9 +105,10 @@
 	n = recvmsg(me, &msg, 0);
 	*used_out = n;
 	if(n < 0){
+		err = -errno;
 		printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", 
 		       errno);
-		return(-errno);
+		return err;
 	}
 	CATCH_EINTR(waitpid(pid, NULL, 0));
 
@@ -147,9 +148,10 @@
 		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
+			err = -errno;
 			printk("TUNSETIFF failed, errno = %d\n", errno);
 			os_close_file(pri->fd);
-			return(-errno);
+			return err;
 		}
 	}
 	else {
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 1399520..e770cb0 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -54,7 +54,8 @@
                                  * a_un, so we have to use a_val, which is
                                  * all that's left.
                                  */
-				elf_aux_platform = (char *) auxv->a_un.a_val;
+				elf_aux_platform =
+					(char *) (long) auxv->a_un.a_val;
 				break;
 			case AT_PAGESZ:
 				page_size = auxv->a_un.a_val;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index fd45bb2..f55773c 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -119,15 +119,11 @@
 
 int os_new_tty_pgrp(int fd, int pid)
 {
-	if(ioctl(fd, TIOCSCTTY, 0) < 0){
-		printk("TIOCSCTTY failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if(ioctl(fd, TIOCSCTTY, 0) < 0)
+		return -errno;
 
-	if(tcsetpgrp(fd, pid) < 0){
-		printk("tcsetpgrp failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if(tcsetpgrp(fd, pid) < 0)
+		return -errno;
 
 	return(0);
 }
@@ -146,18 +142,12 @@
 	int disc, sencap;
 
 	disc = N_SLIP;
-	if(ioctl(fd, TIOCSETD, &disc) < 0){
-		printk("Failed to set slip line discipline - "
-		       "errno = %d\n", errno);
-		return(-errno);
-	}
+	if(ioctl(fd, TIOCSETD, &disc) < 0)
+		return -errno;
 
 	sencap = 0;
-	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
-		printk("Failed to set slip encapsulation - "
-		       "errno = %d\n", errno);
-		return(-errno);
-	}
+	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+		return -errno;
 
 	return(0);
 }
@@ -180,22 +170,15 @@
 	int flags;
 
 	flags = fcntl(master, F_GETFL);
-	if(flags < 0) {
-		printk("fcntl F_GETFL failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if(flags < 0)
+		return errno;
 
 	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-	   (fcntl(master, F_SETOWN, os_getpid()) < 0)){
-		printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n",
-		       errno);
-		return(-errno);
-	}
+	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
+		return -errno;
 
-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
-		printk("fcntl F_SETFL failed, errno = %d\n", errno);
-		return(-errno);
-	}
+	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+		return -errno;
 
 	return(0);
 }
@@ -255,7 +238,7 @@
 
 int os_open_file(char *file, struct openflags flags, int mode)
 {
-	int fd, f = 0;
+	int fd, err, f = 0;
 
 	if(flags.r && flags.w) f = O_RDWR;
 	else if(flags.r) f = O_RDONLY;
@@ -272,8 +255,9 @@
 		return(-errno);
 
 	if(flags.cl && fcntl(fd, F_SETFD, 1)){
+		err = -errno;
 		os_close_file(fd);
-		return(-errno);
+		return err;
 	}
 
 	return(fd);
@@ -383,9 +367,9 @@
 			return(fd);
 		}
 		if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
+			err = -errno;
 			printk("Couldn't get the block size of \"%s\", "
 			       "errno = %d\n", file, errno);
-			err = -errno;
 			os_close_file(fd);
 			return(err);
 		}
@@ -473,11 +457,14 @@
 
 int os_set_fd_async(int fd, int owner)
 {
+	int err;
+
 	/* XXX This should do F_GETFL first */
 	if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
+		err = -errno;
 		printk("os_set_fd_async : failed to set O_ASYNC and "
 		       "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
-		return(-errno);
+		return err;
 	}
 #ifdef notdef
 	if(fcntl(fd, F_SETFD, 1) < 0){
@@ -488,10 +475,11 @@
 
 	if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
 	   (fcntl(fd, F_SETOWN, owner) < 0)){
+		err = -errno;
 		printk("os_set_fd_async : Failed to fcntl F_SETOWN "
 		       "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, 
 		       owner, errno);
-		return(-errno);
+		return err;
 	}
 
 	return(0);
@@ -516,11 +504,9 @@
 	if(blocking) flags &= ~O_NONBLOCK;
 	else flags |= O_NONBLOCK;
 
-	if(fcntl(fd, F_SETFL, flags) < 0){
-		printk("Failed to change blocking on fd # %d, errno = %d\n",
-		       fd, errno);
-		return(-errno);
-	}
+	if(fcntl(fd, F_SETFL, flags) < 0)
+		return -errno;
+
 	return(0);
 }
 
@@ -609,11 +595,8 @@
 	int sock, err;
 
 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
-	if (sock < 0){
-		printk("create_unix_socket - socket failed, errno = %d\n",
-		       errno);
-		return(-errno);
-	}
+	if(sock < 0)
+		return -errno;
 
 	if(close_on_exec) {
 		err = os_set_exec_close(sock, 1);
@@ -628,11 +611,8 @@
 	snprintf(addr.sun_path, len, "%s", file);
 
 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
-	if (err < 0){
-		printk("create_listening_socket at '%s' - bind failed, "
-		       "errno = %d\n", file, errno);
-		return(-errno);
-	}
+	if(err < 0)
+		return -errno;
 
 	return(sock);
 }
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
new file mode 100644
index 0000000..8e71eda
--- /dev/null
+++ b/arch/um/os-Linux/mem.c
@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include "kern_util.h"
+#include "user.h"
+#include "user_util.h"
+#include "mem_user.h"
+#include "init.h"
+#include "os.h"
+#include "tempfile.h"
+#include "kern_constants.h"
+
+#include <sys/param.h>
+
+static char *tempdir = NULL;
+
+static void __init find_tempdir(void)
+{
+	char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+	int i;
+	char *dir = NULL;
+
+	if(tempdir != NULL) return;	/* We've already been called */
+	for(i = 0; dirs[i]; i++){
+		dir = getenv(dirs[i]);
+		if((dir != NULL) && (*dir != '\0'))
+			break;
+	}
+	if((dir == NULL) || (*dir == '\0'))
+		dir = "/tmp";
+
+	tempdir = malloc(strlen(dir) + 2);
+	if(tempdir == NULL){
+		fprintf(stderr, "Failed to malloc tempdir, "
+			"errno = %d\n", errno);
+		return;
+	}
+	strcpy(tempdir, dir);
+	strcat(tempdir, "/");
+}
+
+/*
+ * This proc still used in tt-mode
+ * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
+ * So it isn't 'static' yet.
+ */
+int make_tempfile(const char *template, char **out_tempname, int do_unlink)
+{
+	char tempname[MAXPATHLEN];
+	int fd;
+
+	find_tempdir();
+	if (*template != '/')
+		strcpy(tempname, tempdir);
+	else
+		*tempname = 0;
+	strcat(tempname, template);
+	fd = mkstemp(tempname);
+	if(fd < 0){
+		fprintf(stderr, "open - cannot create %s: %s\n", tempname,
+			strerror(errno));
+		return -1;
+	}
+	if(do_unlink && (unlink(tempname) < 0)){
+		perror("unlink");
+		return -1;
+	}
+	if(out_tempname){
+		*out_tempname = strdup(tempname);
+		if(*out_tempname == NULL){
+			perror("strdup");
+			return -1;
+		}
+	}
+	return(fd);
+}
+
+#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
+
+/*
+ * This proc is used in start_up.c
+ * So it isn't 'static'.
+ */
+int create_tmp_file(unsigned long len)
+{
+	int fd, err;
+	char zero;
+
+	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
+	if(fd < 0) {
+		exit(1);
+	}
+
+	err = fchmod(fd, 0777);
+	if(err < 0){
+		perror("os_mode_fd");
+		exit(1);
+	}
+
+        if (lseek64(fd, len, SEEK_SET) < 0) {
+ 		perror("os_seek_file");
+		exit(1);
+	}
+
+	zero = 0;
+
+	err = os_write_file(fd, &zero, 1);
+	if(err != 1){
+		errno = -err;
+		perror("os_write_file");
+		exit(1);
+	}
+
+	return(fd);
+}
+
+static int create_anon_file(unsigned long len)
+{
+	void *addr;
+	int fd;
+
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0) {
+		perror("opening /dev/anon");
+		exit(1);
+	}
+
+	addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+	if(addr == MAP_FAILED){
+		perror("mapping physmem file");
+		exit(1);
+	}
+	munmap(addr, len);
+
+	return(fd);
+}
+
+extern int have_devanon;
+
+int create_mem_file(unsigned long len)
+{
+	int err, fd;
+
+	if(have_devanon)
+		fd = create_anon_file(len);
+	else fd = create_tmp_file(len);
+
+	err = os_set_exec_close(fd, 1);
+	if(err < 0){
+		errno = -err;
+		perror("exec_close");
+	}
+	return(fd);
+}
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 040cc14..6af8317 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -4,18 +4,22 @@
  */
 
 #include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sched.h>
+#include <fcntl.h>
 #include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <sys/types.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -25,6 +29,7 @@
 #include "sysdep/sigcontext.h"
 #include "irq_user.h"
 #include "ptrace_user.h"
+#include "mem_user.h"
 #include "time_user.h"
 #include "init.h"
 #include "os.h"
@@ -32,6 +37,8 @@
 #include "choose-mode.h"
 #include "mode.h"
 #include "tempfile.h"
+#include "kern_constants.h"
+
 #ifdef UML_CONFIG_MODE_SKAS
 #include "skas.h"
 #include "skas_ptrace.h"
@@ -276,9 +283,38 @@
 	check_sysemu();
 }
 
+extern int create_tmp_file(unsigned long len);
+
+static void check_tmpexec(void)
+{
+	void *addr;
+	int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+	addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+	printf("Checking PROT_EXEC mmap in /tmp...");
+	fflush(stdout);
+	if(addr == MAP_FAILED){
+		err = errno;
+		perror("failed");
+		if(err == EPERM)
+			printf("/tmp must be not mounted noexec\n");
+		exit(1);
+	}
+	printf("OK\n");
+	munmap(addr, UM_KERN_PAGE_SIZE);
+
+	close(fd);
+}
+
 void os_early_checks(void)
 {
 	check_ptrace();
+
+	/* Need to check this early because mmapping happens before the
+	 * kernel is running.
+	 */
+	check_tmpexec();
 }
 
 static int __init noprocmm_cmd_param(char *str, int* add)
@@ -357,3 +393,72 @@
 	return(0);
 }
 #endif
+
+int have_devanon = 0;
+
+void check_devanon(void)
+{
+	int fd;
+
+	printk("Checking for /dev/anon on the host...");
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0){
+		printk("Not available (open failed with errno %d)\n", errno);
+		return;
+	}
+
+	printk("OK\n");
+	have_devanon = 1;
+}
+
+int __init parse_iomem(char *str, int *add)
+{
+	struct iomem_region *new;
+	struct uml_stat buf;
+	char *file, *driver;
+	int fd, err, size;
+
+	driver = str;
+	file = strchr(str,',');
+	if(file == NULL){
+		printf("parse_iomem : failed to parse iomem\n");
+		goto out;
+	}
+	*file = '\0';
+	file++;
+	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
+	if(fd < 0){
+		os_print_error(fd, "parse_iomem - Couldn't open io file");
+		goto out;
+	}
+
+	err = os_stat_fd(fd, &buf);
+	if(err < 0){
+		os_print_error(err, "parse_iomem - cannot stat_fd file");
+		goto out_close;
+	}
+
+	new = malloc(sizeof(*new));
+	if(new == NULL){
+		perror("Couldn't allocate iomem_region struct");
+		goto out_close;
+	}
+
+	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+	*new = ((struct iomem_region) { .next		= iomem_regions,
+					.driver		= driver,
+					.fd		= fd,
+					.size		= size,
+					.phys		= 0,
+					.virt		= 0 });
+	iomem_regions = new;
+	iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
+	return(0);
+ out_close:
+	os_close_file(fd);
+ out:
+	return(1);
+}
+
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index 5b047ab..a6db887 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -36,6 +36,20 @@
 #include "mode.h"
 #include "tempfile.h"
 
+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
+		   int must_succeed)
+{
+	int err;
+
+	err = os_protect_memory((void *) addr, len, r, w, x);
+	if(err < 0){
+                if(must_succeed)
+			panic("protect failed, err = %d", -err);
+		else return(err);
+	}
+	return(0);
+}
+
 /*
  *-------------------------
  * only for tt mode (will be deleted in future...)
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index e63323e..0969d57 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -277,11 +277,6 @@
 config HAVE_ARCH_EARLY_PFN_TO_NID
 	def_bool y
 
-config HAVE_DEC_LOCK
-	bool
-	depends on SMP
-	default y
-
 config NR_CPUS
 	int "Maximum number of CPUs (2-256)"
 	range 2 256
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index c8131f3..d9161e3 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -353,11 +353,6 @@
 	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!mpnt) 
 		return -ENOMEM; 
-	
-	if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
-		kmem_cache_free(vm_area_cachep, mpnt);
-		return -ENOMEM;
-	}
 
 	memset(mpnt, 0, sizeof(*mpnt));
 
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index adbc5f8..3a01329 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -52,17 +52,13 @@
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!vma)
 		return -ENOMEM;
-	if (security_vm_enough_memory(npages)) {
-		kmem_cache_free(vm_area_cachep, vma);
-		return -ENOMEM;
-	}
 
 	memset(vma, 0, sizeof(struct vm_area_struct));
 	/* Could randomize here */
 	vma->vm_start = VSYSCALL32_BASE;
 	vma->vm_end = VSYSCALL32_END;
 	/* MAYWRITE to allow gdb to COW and set breakpoints */
-	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYEXEC|VM_MAYWRITE;
+	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
 	vma->vm_ops = &syscall32_vm_ops;
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index eb7929e..ab3f87a 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -17,6 +17,8 @@
 #include <linux/ioport.h>
 #include <linux/string.h>
 #include <linux/kexec.h>
+#include <linux/module.h>
+
 #include <asm/page.h>
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -28,6 +30,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.
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 522944a..c8eee20 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -299,15 +299,6 @@
 #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? */
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 969365c..08203b0 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -217,7 +217,7 @@
 			panicm_found = 1;
 		}
 
-		tainted |= TAINT_MACHINE_CHECK;
+		add_taint(TAINT_MACHINE_CHECK);
 	}
 
 	/* Never do anything final in the polling timer */
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 4388b8a5..39d445e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -366,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);
@@ -407,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;
@@ -506,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/setup.c b/arch/x86_64/kernel/setup.c
index 351d8d6..238f73e 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -831,11 +831,26 @@
 #endif
 }
 
+#define HWCR 0xc0010015
+
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
 	int r;
 	int level;
 
+#ifdef CONFIG_SMP
+	unsigned long value;
+
+	// Disable TLB flush filter by setting HWCR.FFDIS:
+	// bit 6 of msr C001_0015
+	//
+	// Errata 63 for SH-B3 steppings
+	// Errata 122 for all(?) steppings
+	rdmsrl(HWCR, value);
+	value |= 1 << 6;
+	wrmsrl(HWCR, value);
+#endif
+
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
 	clear_bit(0*32+31, &c->x86_capability);
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 68ec030..fd99ddd00 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -178,10 +178,6 @@
 
 EXPORT_SYMBOL(empty_zero_page);
 
-#ifdef CONFIG_HAVE_DEC_LOCK
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
-
 EXPORT_SYMBOL(die_chain);
 EXPORT_SYMBOL(register_die_notifier);
 
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index 6b26a1c..bba5db6 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -10,5 +10,3 @@
 	usercopy.o getuser.o putuser.o  \
 	thunk.o clear_page.o copy_page.o bitstr.o bitops.o
 lib-y += memcpy.o memmove.o memset.o copy_user.o
-
-lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/x86_64/lib/dec_and_lock.c b/arch/x86_64/lib/dec_and_lock.c
deleted file mode 100644
index ab43394..0000000
--- a/arch/x86_64/lib/dec_and_lock.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * x86 version of "atomic_dec_and_lock()" using
- * the atomic "cmpxchg" instruction.
- *
- * (For CPU's lacking cmpxchg, we use the slow
- * generic version, and this one never even gets
- * compiled).
- */
-
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	int counter;
-	int newcount;
-
-repeat:
-	counter = atomic_read(atomic);
-	newcount = counter-1;
-
-	if (!newcount)
-		goto slow_path;
-
-	asm volatile("lock; cmpxchgl %1,%2"
-		:"=a" (newcount)
-		:"r" (newcount), "m" (atomic->counter), "0" (counter));
-
-	/* If the above failed, "eax" will have changed */
-	if (newcount != counter)
-		goto repeat;
-	return 0;
-
-slow_path:
-	spin_lock(lock);
-	if (atomic_dec_and_test(atomic))
-		return 1;
-	spin_unlock(lock);
-	return 0;
-}
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 2b6257b..7e841aa 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -26,10 +26,6 @@
 	bool
 	default y
 
-config HAVE_DEC_LOCK
-	bool
-	default y
-
 config GENERIC_HARDIRQS
 	bool
 	default y
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/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/paride/pf.c b/drivers/block/paride/pf.c
index 711d2f3..94af920 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -750,6 +750,14 @@
 
 static struct request_queue *pf_queue;
 
+static void pf_end_request(int uptodate)
+{
+	if (pf_req) {
+		end_request(pf_req, uptodate);
+		pf_req = NULL;
+	}
+}
+
 static void do_pf_request(request_queue_t * q)
 {
 	if (pf_busy)
@@ -765,7 +773,7 @@
 	pf_count = pf_req->current_nr_sectors;
 
 	if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
-		end_request(pf_req, 0);
+		pf_end_request(0);
 		goto repeat;
 	}
 
@@ -780,7 +788,7 @@
 		pi_do_claimed(pf_current->pi, do_pf_write);
 	else {
 		pf_busy = 0;
-		end_request(pf_req, 0);
+		pf_end_request(0);
 		goto repeat;
 	}
 }
@@ -798,9 +806,11 @@
 	if (!pf_count)
 		return 1;
 	spin_lock_irqsave(&pf_spin_lock, saved_flags);
-	end_request(pf_req, 1);
-	pf_count = pf_req->current_nr_sectors;
-	pf_buf = pf_req->buffer;
+	pf_end_request(1);
+	if (pf_req) {
+		pf_count = pf_req->current_nr_sectors;
+		pf_buf = pf_req->buffer;
+	}
 	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
 	return 1;
 }
@@ -810,7 +820,7 @@
 	unsigned long saved_flags;
 
 	spin_lock_irqsave(&pf_spin_lock, saved_flags);
-	end_request(pf_req, success);
+	pf_end_request(success);
 	pf_busy = 0;
 	do_pf_request(pf_queue);
 	spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
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 856c227..079ec34 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -168,6 +168,7 @@
 		safe_for_write(WRITE_VERIFY_12),
 		safe_for_write(WRITE_16),
 		safe_for_write(WRITE_LONG),
+		safe_for_write(WRITE_LONG_2),
 		safe_for_write(ERASE),
 		safe_for_write(GPCMD_MODE_SELECT_10),
 		safe_for_write(MODE_SELECT),
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/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 99762b6..de5d6d2 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -252,7 +252,7 @@
 		readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
 		writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
 		readl(hp->ioc_regs+HP_ZX1_TCNFG);
-		writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK);
+		writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
 		readl(hp->ioc_regs+HP_ZX1_IMASK);
 		writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
 		readl(hp->ioc_regs+HP_ZX1_IBASE);
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/epca.c b/drivers/char/epca.c
index 58d3738..407708a 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -534,7 +534,7 @@
 
 	unsigned long flags;
 	struct tty_struct *tty;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 
 	if (!(ch->asyncflags & ASYNC_INITIALIZED)) 
 		return;
@@ -618,7 +618,7 @@
 	struct channel *ch;
 	unsigned long flags;
 	int remain;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 
 	/* ----------------------------------------------------------------
 		pc_write is primarily called directly by the kernel routine
@@ -685,7 +685,7 @@
 		------------------------------------------------------------------- */
 
 		dataLen = min(bytesAvailable, dataLen);
-		memcpy(ch->txptr + head, buf, dataLen);
+		memcpy_toio(ch->txptr + head, buf, dataLen);
 		buf += dataLen;
 		head += dataLen;
 		amountCopied += dataLen;
@@ -726,7 +726,7 @@
 	struct channel *ch;
 	unsigned long flags;
 	unsigned int head, tail;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 
 	remain = 0;
 
@@ -773,7 +773,7 @@
 	int remain;
 	unsigned long flags;
 	struct channel *ch;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 
 	/* ---------------------------------------------------------
 		verifyChannel returns the channel from the tty struct
@@ -830,7 +830,7 @@
 	unsigned int tail;
 	unsigned long flags;
 	struct channel *ch;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	/* ---------------------------------------------------------
 		verifyChannel returns the channel from the tty struct
 		if it is valid.  This serves as a sanity check.
@@ -976,7 +976,7 @@
 	struct channel *ch;
 	unsigned long flags;
 	int line, retval, boardnum;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	unsigned int head;
 
 	line = tty->index;
@@ -1041,7 +1041,7 @@
 	ch->statusflags = 0;
 
 	/* Save boards current modem status */
-	ch->imodem = bc->mstat;
+	ch->imodem = readb(&bc->mstat);
 
 	/* ----------------------------------------------------------------
 	   Set receive head and tail ptrs to each other.  This indicates
@@ -1399,10 +1399,10 @@
 { /* Begin post_fep_init */
 
 	int i;
-	unsigned char *memaddr;
-	struct global_data *gd;
+	void __iomem *memaddr;
+	struct global_data __iomem *gd;
 	struct board_info *bd;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	struct channel *ch; 
 	int shrinkmem = 0, lowwater ; 
  
@@ -1461,7 +1461,7 @@
 		8 and 64 of these structures.
 	-------------------------------------------------------------------- */
 
-	bc = (struct board_chan *)(memaddr + CHANSTRUCT);
+	bc = memaddr + CHANSTRUCT;
 
 	/* -------------------------------------------------------------------
 		The below assignment will set gd to point at the BEGINING of
@@ -1470,7 +1470,7 @@
 		pointer begins at 0xd10.
 	---------------------------------------------------------------------- */
 
-	gd = (struct global_data *)(memaddr + GLOBAL);
+	gd = memaddr + GLOBAL;
 
 	/* --------------------------------------------------------------------
 		XEPORTS (address 0xc22) points at the number of channels the
@@ -1493,6 +1493,7 @@
 
 	for (i = 0; i < bd->numports; i++, ch++, bc++)  { /* Begin for each port */
 		unsigned long flags;
+		u16 tseg, rseg;
 
 		ch->brdchan        = bc;
 		ch->mailbox        = gd; 
@@ -1553,50 +1554,53 @@
 			shrinkmem = 0;
 		}
 
+		tseg = readw(&bc->tseg);
+		rseg = readw(&bc->rseg);
+
 		switch (bd->type) {
 
 			case PCIXEM:
 			case PCIXRJ:
 			case PCIXR:
 				/* Cover all the 2MEG cards */
-				ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff);
-				ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff);
-				ch->txwin = FEPWIN | ((bc->tseg) >> 11);
-				ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+				ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+				ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+				ch->txwin = FEPWIN | (tseg >> 11);
+				ch->rxwin = FEPWIN | (rseg >> 11);
 				break;
 
 			case PCXEM:
 			case EISAXEM:
 				/* Cover all the 32K windowed cards */
 				/* Mask equal to window size - 1 */
-				ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff);
-				ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff);
-				ch->txwin = FEPWIN | ((bc->tseg) >> 11);
-				ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+				ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+				ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+				ch->txwin = FEPWIN | (tseg >> 11);
+				ch->rxwin = FEPWIN | (rseg >> 11);
 				break;
 
 			case PCXEVE:
 			case PCXE:
-				ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff);
-				ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9);
-				ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff);
-				ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 );
+				ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+				ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+				ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+				ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
 				break;
 
 			case PCXI:
 			case PC64XE:
-				ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4);
-				ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4);
+				ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+				ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
 				ch->txwin = ch->rxwin = 0;
 				break;
 
 		} /* End switch bd->type */
 
 		ch->txbufhead = 0;
-		ch->txbufsize = bc->tmax + 1;
+		ch->txbufsize = readw(&bc->tmax) + 1;
 	
 		ch->rxbufhead = 0;
-		ch->rxbufsize = bc->rmax + 1;
+		ch->rxbufsize = readw(&bc->rmax) + 1;
 	
 		lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
 
@@ -1718,11 +1722,11 @@
 static void doevent(int crd)
 { /* Begin doevent */
 
-	void *eventbuf;
+	void __iomem *eventbuf;
 	struct channel *ch, *chan0;
 	static struct tty_struct *tty;
 	struct board_info *bd;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	unsigned int tail, head;
 	int event, channel;
 	int mstat, lstat;
@@ -1817,7 +1821,7 @@
 static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
                    int byte2, int ncmds, int bytecmd)
 { /* Begin fepcmd */
-	unchar *memaddr;
+	unchar __iomem *memaddr;
 	unsigned int head, cmdTail, cmdStart, cmdMax;
 	long count;
 	int n;
@@ -2000,7 +2004,7 @@
 
 	unsigned int cmdHead;
 	struct termios *ts;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	unsigned mval, hflow, cflag, iflag;
 
 	bc = ch->brdchan;
@@ -2010,7 +2014,7 @@
 	ts = tty->termios;
 	if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
 		cmdHead = readw(&bc->rin);
-		bc->rout = cmdHead;
+		writew(cmdHead, &bc->rout);
 		cmdHead = readw(&bc->tin);
 		/* Changing baud in mid-stream transmission can be wonderful */
 		/* ---------------------------------------------------------------
@@ -2116,7 +2120,7 @@
 	unchar *rptr;
 	struct termios *ts = NULL;
 	struct tty_struct *tty;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	int dataToRead, wrapgap, bytesAvailable;
 	unsigned int tail, head;
 	unsigned int wrapmask;
@@ -2154,7 +2158,7 @@
 	--------------------------------------------------------------------- */
 
 	if (!tty || !ts || !(ts->c_cflag & CREAD))  {
-		bc->rout = head;
+		writew(head, &bc->rout);
 		return;
 	}
 
@@ -2270,7 +2274,7 @@
 static int pc_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct channel *ch = (struct channel *) tty->driver_data;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	unsigned int mstat, mflag = 0;
 	unsigned long flags;
 
@@ -2351,7 +2355,7 @@
 	unsigned long flags;
 	unsigned int mflag, mstat;
 	unsigned char startc, stopc;
-	struct board_chan *bc;
+	struct board_chan __iomem *bc;
 	struct channel *ch = (struct channel *) tty->driver_data;
 	void __user *argp = (void __user *)arg;
 	
@@ -2633,7 +2637,7 @@
 		spin_lock_irqsave(&epca_lock, flags);
 		/* Just in case output was resumed because of a change in Digi-flow */
 		if (ch->statusflags & TXSTOPPED)  { /* Begin transmit resume requested */
-			struct board_chan *bc;
+			struct board_chan __iomem *bc;
 			globalwinon(ch);
 			bc = ch->brdchan;
 			if (ch->statusflags & LOWWAIT)
@@ -2727,7 +2731,7 @@
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
 { /* Begin setup_empty_event */
 
-	struct board_chan *bc = ch->brdchan;
+	struct board_chan __iomem *bc = ch->brdchan;
 
 	globalwinon(ch);
 	ch->statusflags |= EMPTYWAIT;
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
index 20eeb5a..456d6c8 100644
--- a/drivers/char/epca.h
+++ b/drivers/char/epca.h
@@ -128,17 +128,17 @@
 	unsigned long  c_cflag;
 	unsigned long  c_lflag;
 	unsigned long  c_oflag;
-	unsigned char *txptr;
-	unsigned char *rxptr;
+	unsigned char __iomem *txptr;
+	unsigned char __iomem *rxptr;
 	unsigned char *tmp_buf;
 	struct board_info           *board;
-	struct board_chan	    *brdchan;
+	struct board_chan	    __iomem *brdchan;
 	struct digi_struct          digiext;
 	struct tty_struct           *tty;
 	wait_queue_head_t           open_wait;
 	wait_queue_head_t           close_wait;
 	struct work_struct          tqueue;
-	struct global_data 	    *mailbox;
+	struct global_data 	    __iomem *mailbox;
 };
 
 struct board_info	
@@ -149,8 +149,8 @@
 	unsigned short numports;
 	unsigned long port;
 	unsigned long membase;
-	unsigned char __iomem *re_map_port;
-	unsigned char *re_map_membase;
+	void __iomem *re_map_port;
+	void __iomem *re_map_membase;
 	unsigned long  memory_seg;
 	void ( * memwinon )	(struct board_info *, unsigned int) ;
 	void ( * memwinoff ) 	(struct board_info *, unsigned int) ;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index cddb789..f921776 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -839,9 +839,6 @@
 	hvc_driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(hvc_driver, &hvc_ops);
 
-	if (tty_register_driver(hvc_driver))
-		panic("Couldn't register hvc console driver\n");
-
 	/* Always start the kthread because there can be hotplug vty adapters
 	 * added later. */
 	hvc_task = kthread_run(khvcd, NULL, "khvcd");
@@ -851,6 +848,9 @@
 		return -EIO;
 	}
 
+	if (tty_register_driver(hvc_driver))
+		panic("Couldn't register hvc console driver\n");
+
 	return 0;
 }
 module_init(hvc_init);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1e33cb0..e91268e 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -810,13 +810,14 @@
 			 * from the top and bottom of cursor position
 			 */
 			old_origin += (vc->vc_y - new_rows/2) * old_row_size;
-			end = old_origin + new_screen_size;
+			end = old_origin + (old_row_size * new_rows);
 		}
 	} else
 		/*
 		 * Cursor near the top, copy contents from the top of buffer
 		 */
-		end = (old_rows > new_rows) ? old_origin + new_screen_size :
+		end = (old_rows > new_rows) ? old_origin +
+			(old_row_size * new_rows) :
 			vc->vc_scr_end;
 
 	update_attr(vc);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index fa789ea..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
@@ -233,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
@@ -243,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
@@ -298,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
@@ -336,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
@@ -355,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)
@@ -362,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
@@ -430,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 bc6f5fe..cfd0a39 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -39,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
index c694eee..75ca84e 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -30,6 +30,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+
+#include <asm/hardware/arm_twd.h>
 #include <asm/uaccess.h>
 
 struct mpcore_wdt {
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/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 3b865f3..b667823 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -50,7 +50,7 @@
 MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
 MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("2.0");
 
 #define BIOS_SCAN_LIMIT 0xffffffff
 #define MAX_IMAGE_LENGTH 16
@@ -65,10 +65,11 @@
 	unsigned long packet_write_count;
 	unsigned long num_packets;
 	unsigned long packetsize;
+	int entry_created;
 } rbu_data;
 
-static char image_type[MAX_IMAGE_LENGTH] = "mono";
-module_param_string(image_type, image_type, sizeof(image_type), 0);
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
 MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
 
 struct packet_data {
@@ -114,7 +115,7 @@
 
 	if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
 		pr_debug("dell_rbu:%s: packet size data "
-			 "overrun\n", __FUNCTION__);
+			"overrun\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -146,12 +147,14 @@
 		pr_debug("create_packet: packetsize not specified\n");
 		return -EINVAL;
 	}
+	spin_unlock(&rbu_data.lock);
+	newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
+	spin_lock(&rbu_data.lock);
 
-	newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
 	if (!newpacket) {
 		printk(KERN_WARNING
-		       "dell_rbu:%s: failed to allocate new "
-		       "packet\n", __FUNCTION__);
+			"dell_rbu:%s: failed to allocate new "
+			"packet\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
@@ -160,15 +163,17 @@
 	 * there is no upper limit on memory
 	 * address for packetized mechanism
 	 */
-	newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
-							    ordernum);
+	spin_unlock(&rbu_data.lock);
+	newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
+		ordernum);
+	spin_lock(&rbu_data.lock);
 
 	pr_debug("create_packet: newpacket %p\n", newpacket->data);
 
 	if (!newpacket->data) {
 		printk(KERN_WARNING
-		       "dell_rbu:%s: failed to allocate new "
-		       "packet\n", __FUNCTION__);
+			"dell_rbu:%s: failed to allocate new "
+			"packet\n", __FUNCTION__);
 		kfree(newpacket);
 		return -ENOMEM;
 	}
@@ -204,9 +209,8 @@
 	return rc;
 }
 
-static int
-do_packet_read(char *data, struct list_head *ptemp_list,
-	       int length, int bytes_read, int *list_read_count)
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+	int length, int bytes_read, int *list_read_count)
 {
 	void *ptemp_buf;
 	struct packet_data *newpacket = NULL;
@@ -239,7 +243,7 @@
 	return bytes_copied;
 }
 
-static int packet_read_list(char *data, size_t * pread_length)
+static int packet_read_list(char *data, size_t *pread_length)
 {
 	struct list_head *ptemp_list;
 	int temp_count = 0;
@@ -258,8 +262,7 @@
 	ptemp_list = (&packet_data_head.list)->next;
 	while (!list_empty(ptemp_list)) {
 		bytes_copied = do_packet_read(pdest, ptemp_list,
-					      remaining_bytes, bytes_read,
-					      &temp_count);
+			remaining_bytes, bytes_read, &temp_count);
 		remaining_bytes -= bytes_copied;
 		bytes_read += bytes_copied;
 		pdest += bytes_copied;
@@ -287,7 +290,7 @@
 	ptemp_list = (&packet_data_head.list)->next;
 	while (!list_empty(ptemp_list)) {
 		newpacket =
-		    list_entry(ptemp_list, struct packet_data, list);
+			list_entry(ptemp_list, struct packet_data, list);
 		pnext_list = ptemp_list->next;
 		list_del(ptemp_list);
 		ptemp_list = pnext_list;
@@ -296,8 +299,8 @@
 		 * to make sure there are no stale RBU packets left in memory
 		 */
 		memset(newpacket->data, 0, rbu_data.packetsize);
-		free_pages((unsigned long)newpacket->data,
-			   newpacket->ordernum);
+		free_pages((unsigned long) newpacket->data,
+			newpacket->ordernum);
 		kfree(newpacket);
 	}
 	rbu_data.packet_write_count = 0;
@@ -319,14 +322,13 @@
 	 * BIOS image copied in memory.
 	 */
 	memset(rbu_data.image_update_buffer, 0,
-	       rbu_data.image_update_buffer_size);
+		rbu_data.image_update_buffer_size);
 	if (rbu_data.dma_alloc == 1)
 		dma_free_coherent(NULL, rbu_data.bios_image_size,
-				  rbu_data.image_update_buffer,
-				  dell_rbu_dmaaddr);
+			rbu_data.image_update_buffer, dell_rbu_dmaaddr);
 	else
-		free_pages((unsigned long)rbu_data.image_update_buffer,
-			   rbu_data.image_update_ordernum);
+		free_pages((unsigned long) rbu_data.image_update_buffer,
+			rbu_data.image_update_ordernum);
 
 	/*
 	 * Re-initialize the rbu_data variables after a free
@@ -366,7 +368,7 @@
 		 */
 		if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
 			printk(KERN_ERR "dell_rbu:%s: corruption "
-			       "check failed\n", __FUNCTION__);
+				"check failed\n", __FUNCTION__);
 			return -EINVAL;
 		}
 		/*
@@ -385,17 +387,16 @@
 
 	ordernum = get_order(size);
 	image_update_buffer =
-	    (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
+		(unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
 
 	img_buf_phys_addr =
-	    (unsigned long)virt_to_phys(image_update_buffer);
+		(unsigned long) virt_to_phys(image_update_buffer);
 
 	if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
-		free_pages((unsigned long)image_update_buffer, ordernum);
+		free_pages((unsigned long) image_update_buffer, ordernum);
 		ordernum = -1;
 		image_update_buffer = dma_alloc_coherent(NULL, size,
-							 &dell_rbu_dmaaddr,
-							 GFP_KERNEL);
+			&dell_rbu_dmaaddr, GFP_KERNEL);
 		dma_alloc = 1;
 	}
 
@@ -405,13 +406,13 @@
 		rbu_data.image_update_buffer = image_update_buffer;
 		rbu_data.image_update_buffer_size = size;
 		rbu_data.bios_image_size =
-		    rbu_data.image_update_buffer_size;
+			rbu_data.image_update_buffer_size;
 		rbu_data.image_update_ordernum = ordernum;
 		rbu_data.dma_alloc = dma_alloc;
 		rc = 0;
 	} else {
 		pr_debug("Not enough memory for image update:"
-			 "size = %ld\n", size);
+			"size = %ld\n", size);
 		rc = -ENOMEM;
 	}
 
@@ -438,7 +439,7 @@
 	if (pos > imagesize) {
 		retval = 0;
 		printk(KERN_WARNING "dell_rbu:read_packet_data: "
-		       "data underrun\n");
+			"data underrun\n");
 		goto read_rbu_data_exit;
 	}
 
@@ -468,11 +469,11 @@
 
 	/* check to see if we have something to return */
 	if ((rbu_data.image_update_buffer == NULL) ||
-	    (rbu_data.bios_image_size == 0)) {
+		(rbu_data.bios_image_size == 0)) {
 		pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
-			 "bios_image_size %lu\n",
-			 rbu_data.image_update_buffer,
-			 rbu_data.bios_image_size);
+			"bios_image_size %lu\n",
+			rbu_data.image_update_buffer,
+			rbu_data.bios_image_size);
 		ret_count = -ENOMEM;
 		goto read_rbu_data_exit;
 	}
@@ -497,8 +498,8 @@
 	return ret_count;
 }
 
-static ssize_t
-read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
+			loff_t pos, size_t count)
 {
 	ssize_t ret_count = 0;
 
@@ -515,62 +516,20 @@
 	return ret_count;
 }
 
-static ssize_t
-read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
-		    size_t count)
-{
-	int size = 0;
-	if (!pos)
-		size = sprintf(buffer, "%s\n", image_type);
-	return size;
-}
-
-static ssize_t
-write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
-		     size_t count)
-{
-	int rc = count;
-	spin_lock(&rbu_data.lock);
-
-	if (strlen(buffer) < MAX_IMAGE_LENGTH)
-		sscanf(buffer, "%s", image_type);
-	else
-		printk(KERN_WARNING "dell_rbu: image_type is invalid"
-		       "max chars = %d, \n incoming str--%s-- \n",
-		       MAX_IMAGE_LENGTH, buffer);
-
-	/* we must free all previous allocations */
-	packet_empty_list();
-	img_update_free();
-
-	spin_unlock(&rbu_data.lock);
-	return rc;
-
-}
-
-static struct bin_attribute rbu_data_attr = {
-	.attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
-	.read = read_rbu_data,
-};
-
-static struct bin_attribute rbu_image_type_attr = {
-	.attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
-	.read = read_rbu_image_type,
-	.write = write_rbu_image_type,
-};
-
 static void callbackfn_rbu(const struct firmware *fw, void *context)
 {
 	int rc = 0;
 
-	if (!fw || !fw->size)
+	if (!fw || !fw->size) {
+		rbu_data.entry_created = 0;
 		return;
+	}
 
 	spin_lock(&rbu_data.lock);
 	if (!strcmp(image_type, "mono")) {
 		if (!img_update_realloc(fw->size))
 			memcpy(rbu_data.image_update_buffer,
-			       fw->data, fw->size);
+				fw->data, fw->size);
 	} else if (!strcmp(image_type, "packet")) {
 		if (!rbu_data.packetsize)
 			rbu_data.packetsize = fw->size;
@@ -584,14 +543,103 @@
 	spin_unlock(&rbu_data.lock);
 
 	rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
-				     "dell_rbu", &rbu_device->dev,
-				     &context, callbackfn_rbu);
+		"dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
 	if (rc)
 		printk(KERN_ERR
-		       "dell_rbu:%s request_firmware_nowait failed"
-		       " %d\n", __FUNCTION__, rc);
+			"dell_rbu:%s request_firmware_nowait failed"
+			" %d\n", __FUNCTION__, rc);
+	else
+		rbu_data.entry_created = 1;
 }
 
+static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
+			loff_t pos, size_t count)
+{
+	int size = 0;
+	if (!pos)
+		size = sprintf(buffer, "%s\n", image_type);
+	return size;
+}
+
+static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
+			loff_t pos, size_t count)
+{
+	int rc = count;
+	int req_firm_rc = 0;
+	int i;
+	spin_lock(&rbu_data.lock);
+	/*
+	 * Find the first newline or space
+	 */
+	for (i = 0; i < count; ++i)
+		if (buffer[i] == '\n' || buffer[i] == ' ') {
+			buffer[i] = '\0';
+			break;
+		}
+	if (i == count)
+		buffer[count] = '\0';
+
+	if (strstr(buffer, "mono"))
+		strcpy(image_type, "mono");
+	else if (strstr(buffer, "packet"))
+		strcpy(image_type, "packet");
+	else if (strstr(buffer, "init")) {
+		/*
+		 * If due to the user error the driver gets in a bad
+		 * state where even though it is loaded , the
+		 * /sys/class/firmware/dell_rbu entries are missing.
+		 * to cover this situation the user can recreate entries
+		 * by writing init to image_type.
+		 */
+		if (!rbu_data.entry_created) {
+			spin_unlock(&rbu_data.lock);
+			req_firm_rc = request_firmware_nowait(THIS_MODULE,
+				FW_ACTION_NOHOTPLUG, "dell_rbu",
+				&rbu_device->dev, &context,
+				callbackfn_rbu);
+			if (req_firm_rc) {
+				printk(KERN_ERR
+					"dell_rbu:%s request_firmware_nowait"
+					" failed %d\n", __FUNCTION__, rc);
+				rc = -EIO;
+			} else
+				rbu_data.entry_created = 1;
+
+			spin_lock(&rbu_data.lock);
+		}
+	} else {
+		printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+		spin_unlock(&rbu_data.lock);
+		return -EINVAL;
+	}
+
+	/* we must free all previous allocations */
+	packet_empty_list();
+	img_update_free();
+	spin_unlock(&rbu_data.lock);
+
+	return rc;
+}
+
+static struct bin_attribute rbu_data_attr = {
+	.attr = {
+		.name = "data",
+		.owner = THIS_MODULE,
+		.mode = 0444,
+	},
+	.read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+	.attr = {
+		.name = "image_type",
+		.owner = THIS_MODULE,
+		.mode = 0644,
+	},
+	.read = read_rbu_image_type,
+	.write = write_rbu_image_type,
+};
+
 static int __init dcdrbu_init(void)
 {
 	int rc = 0;
@@ -599,11 +647,11 @@
 
 	init_packet_head();
 	rbu_device =
-	    platform_device_register_simple("dell_rbu", -1, NULL, 0);
+		platform_device_register_simple("dell_rbu", -1, NULL, 0);
 	if (!rbu_device) {
 		printk(KERN_ERR
-		       "dell_rbu:%s:platform_device_register_simple "
-		       "failed\n", __FUNCTION__);
+			"dell_rbu:%s:platform_device_register_simple "
+			"failed\n", __FUNCTION__);
 		return -EIO;
 	}
 
@@ -611,11 +659,12 @@
 	sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
 
 	rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
-				     "dell_rbu", &rbu_device->dev,
-				     &context, callbackfn_rbu);
+		"dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
 	if (rc)
 		printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
-		       " failed %d\n", __FUNCTION__, rc);
+			" failed %d\n", __FUNCTION__, rc);
+	else
+		rbu_data.entry_created = 1;
 
 	return rc;
 
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index eaebfc1..4c56411 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -5,10 +5,10 @@
  * 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.
+ * T41, T42, T43, R50, R50p, 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
+ * This driver is 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.
  *
@@ -36,12 +36,7 @@
 #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_NR_PORTS		0x30	/* number of ports: 0x1600 - 0x162f */
 
 #define HDAPS_PORT_STATE	0x1611	/* device state */
 #define HDAPS_PORT_YPOS		0x1612	/* y-axis position */
@@ -53,7 +48,7 @@
 #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 STATE_FRESH		0x50	/* accelerometer data is fresh */
 
 #define KEYBD_MASK		0x20	/* set if keyboard activity */
 #define MOUSE_MASK		0x40	/* set if mouse activity */
@@ -63,12 +58,11 @@
 #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;
+#define HDAPS_POLL_PERIOD	(HZ/20)	/* poll for input every 1/20s */
+#define HDAPS_INPUT_FUZZ	4	/* input event threshold */
+
 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 struct platform_device *pdev;
 static unsigned int hdaps_invert;
 static u8 km_activity;
 static int rest_x;
@@ -81,14 +75,14 @@
  */
 static inline u8 __get_latch(u16 port)
 {
-	return inb(port) & HDAPS_READ_MASK;
+	return inb(port) & 0xff;
 }
 
 /*
- * __check_latch - Check a port latch for a given value.  Callers must hold
- * hdaps_sem.  Returns zero if the port contains the given value.
+ * __check_latch - Check a port latch for a given value.  Returns zero if the
+ * port contains the given value.  Callers must hold hdaps_sem.
  */
-static inline unsigned int __check_latch(u16 port, u8 val)
+static inline int __check_latch(u16 port, u8 val)
 {
 	if (__get_latch(port) == val)
 		return 0;
@@ -99,7 +93,7 @@
  * __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)
+static int __wait_latch(u16 port, u8 val)
 {
 	unsigned int i;
 
@@ -109,59 +103,42 @@
 		udelay(5);
 	}
 
-	return -EINVAL;
+	return -EIO;
 }
 
 /*
- * __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.
+ * __device_refresh - request a refresh from the accelerometer.  Does not wait
+ * for refresh to complete.  Callers must hold hdaps_sem.
  */
-static int __device_refresh(unsigned int sync)
+static void __device_refresh(void)
 {
-	u8 state;
+	udelay(200);
+	if (inb(0x1604) != STATE_FRESH) {
+		outb(0x11, 0x1610);
+		outb(0x01, 0x161f);
+	}
+}
 
-	udelay(100);
-
-	state = inb(0x1604);
-	if (state == STATE_FRESH)
-		return 0;
-
-	outb(0x11, 0x1610);
-	outb(0x01, 0x161f);
-	if (sync == REFRESH_ASYNC)
-		return 0;
-
+/*
+ * __device_refresh_sync - request a synchronous refresh from the
+ * accelerometer.  We wait for the refresh to complete.  Returns zero if
+ * successful and nonzero on error.  Callers must hold hdaps_sem.
+ */
+static int __device_refresh_sync(void)
+{
+	__device_refresh();
 	return __wait_latch(0x1604, STATE_FRESH);
 }
 
 /*
- * __device_complete - Indicate to the accelerometer that we are done reading
+ * __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;
+	__device_refresh();
 }
 
 /*
@@ -174,17 +151,26 @@
 	int ret;
 
 	down(&hdaps_sem);
-	ret = __hdaps_readb_one(port, val);
-	up(&hdaps_sem);
 
+	/* do a sync refresh -- we need to be sure that we read fresh data */
+	ret = __device_refresh_sync();
+	if (ret)
+		goto out;
+
+	*val = inb(port);
+	__device_complete();
+
+out:
+	up(&hdaps_sem);
 	return ret;
 }
 
+/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
 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))
+	if (__device_refresh_sync())
 		return -EIO;
 
 	*y = inw(port2);
@@ -217,11 +203,13 @@
 	return ret;
 }
 
-/* initialize the accelerometer */
+/*
+ * hdaps_device_init - initialize the accelerometer.  Returns zero on success
+ * and negative error code on failure.  Can sleep.
+ */
 static int hdaps_device_init(void)
 {
-	unsigned int total_msecs = INIT_TIMEOUT_MSECS;
-	int ret = -ENXIO;
+	int total, ret = -ENXIO;
 
 	down(&hdaps_sem);
 
@@ -231,8 +219,10 @@
 		goto out;
 
 	/*
-	 * The 0x03 value appears to only work on some thinkpads, such as the
-	 * T42p.  Others return 0x01.
+	 * Most ThinkPads return 0x01.
+	 *
+	 * Others--namely the R50p, T41p, and T42p--return 0x03.  These laptops
+	 * have "inverted" axises.
 	 *
 	 * The 0x02 value occurs when the chip has been previously initialized.
 	 */
@@ -267,24 +257,23 @@
 	outb(0x01, 0x161f);
 	if (__wait_latch(0x161f, 0x00))
 		goto out;
-	if (__device_refresh(REFRESH_SYNC))
+	if (__device_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;
+	for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+		int x, y;
 
 		/* a read of the device helps push it into action */
-		__hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+		__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
 		if (!__wait_latch(0x1611, 0x02)) {
 			ret = 0;
 			break;
 		}
 
 		msleep(INIT_WAIT_MSECS);
-		total_msecs -= INIT_WAIT_MSECS;
 	}
 
 out:
@@ -293,96 +282,6 @@
 }
 
 
-/* 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)
@@ -412,6 +311,49 @@
 	.resume = hdaps_resume
 };
 
+/* Input class stuff */
+
+static struct input_dev hdaps_idev = {
+	.name = "hdaps",
+	.evbit = { BIT(EV_ABS) },
+	.absbit = { BIT(ABS_X) | BIT(ABS_Y) },
+	.absmin  = { [ABS_X] = -256, [ABS_Y] = -256 },
+	.absmax  = { [ABS_X] = 256, [ABS_Y] = 256 },
+	.absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+	.absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+};
+
+/*
+ * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+	__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_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 + HDAPS_POLL_PERIOD);
+		return;
+	}
+
+	if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+		goto out;
+
+	input_report_abs(&hdaps_idev, ABS_X, x - rest_x);
+	input_report_abs(&hdaps_idev, ABS_Y, y - rest_y);
+	input_sync(&hdaps_idev);
+
+	mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
+
+out:
+	up(&hdaps_sem);
+}
+
 
 /* Sysfs Files */
 
@@ -517,69 +459,6 @@
 	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);
@@ -588,10 +467,6 @@
 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,
@@ -601,9 +476,6 @@
 	&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,
 };
@@ -619,7 +491,7 @@
  * 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
+ * I fixed this; the patch is 2.6-git.  Once in a released 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)
@@ -668,6 +540,7 @@
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
 		{ .ident = NULL }
 	};
 
@@ -696,8 +569,18 @@
 	if (ret)
 		goto out_device;
 
-	if (hdaps_mousedev)
-		hdaps_mousedev_enable();
+	/* initial calibrate for the input device */
+	hdaps_calibrate();
+
+	/* initialize the input class */
+	hdaps_idev.dev = &pdev->dev;
+	input_register_device(&hdaps_idev);
+
+	/* start up our timer for the input device */
+	init_timer(&hdaps_timer);
+	hdaps_timer.function = hdaps_mousedev_poll;
+	hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
+	add_timer(&hdaps_timer);
 
 	printk(KERN_INFO "hdaps: driver successfully loaded.\n");
 	return 0;
@@ -715,8 +598,8 @@
 
 static void __exit hdaps_exit(void)
 {
-	hdaps_mousedev_disable();
-
+	del_timer_sync(&hdaps_timer);
+	input_unregister_device(&hdaps_idev);
 	sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
 	platform_device_unregister(pdev);
 	driver_unregister(&hdaps_driver);
@@ -728,9 +611,6 @@
 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");
 
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-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fdf53ce..44b595d 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -914,19 +914,23 @@
 	return ret;
 }
 
+static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
 static struct i2c_algorithm i2c_pxa_algorithm = {
-	.name		= "PXA-I2C-Algorithm",
-	.id		= I2C_ALGO_PXA,
 	.master_xfer	= i2c_pxa_xfer,
+	.functionality	= i2c_pxa_functionality,
 };
 
 static struct pxa_i2c i2c_pxa = {
 	.lock	= SPIN_LOCK_UNLOCKED,
 	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
 	.adap	= {
-		.name		= "pxa2xx-i2c",
-		.id		= I2C_ALGO_PXA,
+		.owner		= THIS_MODULE,
 		.algo		= &i2c_pxa_algorithm,
+		.name		= "pxa2xx-i2c",
 		.retries	= 5,
 	},
 };
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/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d04f62a..ace8eda 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -500,6 +500,7 @@
 	}
 
 	rq.special = args;
+	args->rq = &rq;
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
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/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/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8337b0f..4866fc3 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -61,6 +61,7 @@
 	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
 	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
 	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
+	{PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"},
 	{0, 0, NULL, NULL},
 };
 
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index c6b5bf7..dc334aa 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -611,7 +611,7 @@
 } /* sedlbauer_event */
 
 static struct pcmcia_device_id sedlbauer_ids[] = {
-	PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c),
+	PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
 	PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
 	PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
 	PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index 0fda5c8..9ffaae7 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -466,10 +466,10 @@
 #define __debug_variable st5481_debug
 #include "hisax_debug.h"
 
-#ifdef CONFIG_HISAX_DEBUG
-
 extern int st5481_debug;
 
+#ifdef CONFIG_HISAX_DEBUG
+
 #define DBG_ISO_PACKET(level,urb) \
   if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
 
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 2fcd093..0a2536d 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -172,14 +172,18 @@
 	test_and_clear_bit(buf_nr, &b_out->busy);
 
 	if (unlikely(urb->status < 0)) {
-		if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
-			WARN("urb status %d",urb->status);
-			if (b_out->busy == 0) {
-				st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
-			}
-		} else {
-			DBG(1,"urb killed"); 
-			return; // Give up
+		switch (urb->status) {
+			case -ENOENT:
+			case -ESHUTDOWN:
+			case -ECONNRESET:
+				DBG(4,"urb killed status %d", urb->status);
+				return; // Give up
+			default: 
+				WARN("urb status %d",urb->status);
+				if (b_out->busy == 0) {
+					st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
+				}
+				break;
 		}
 	}
 
@@ -205,7 +209,9 @@
 	bcs->mode = mode;
 
 	// Cancel all USB transfers on this B channel
+	b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(b_out->urb[0]);
+	b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(b_out->urb[1]);
 	b_out->busy = 0;
 
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 071b1d3..941f702 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -382,16 +382,20 @@
 	test_and_clear_bit(buf_nr, &d_out->busy);
 
 	if (unlikely(urb->status < 0)) {
-		if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
-			WARN("urb status %d",urb->status);
-			if (d_out->busy == 0) {
-				st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
-			}
-			return;
-		} else {
-			DBG(1,"urb killed"); 
-			return; // Give up
+		switch (urb->status) {
+			case -ENOENT:
+			case -ESHUTDOWN:
+			case -ECONNRESET:
+				DBG(1,"urb killed status %d", urb->status);
+				break;
+			default: 
+				WARN("urb status %d",urb->status);
+				if (d_out->busy == 0) {
+					st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
+				}
+				break;
 		}
+		return; // Give up
 	}
 
 	FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
@@ -709,14 +713,14 @@
 
 	adapter->l1m.fsm = &l1fsm;
 	adapter->l1m.state = ST_L1_F3;
-	adapter->l1m.debug = 1;
+	adapter->l1m.debug = st5481_debug & 0x100;
 	adapter->l1m.userdata = adapter;
 	adapter->l1m.printdebug = l1m_debug;
 	FsmInitTimer(&adapter->l1m, &adapter->timer);
 
 	adapter->d_out.fsm.fsm = &dout_fsm;
 	adapter->d_out.fsm.state = ST_DOUT_NONE;
-	adapter->d_out.fsm.debug = 1;
+	adapter->d_out.fsm.debug = st5481_debug & 0x100;
 	adapter->d_out.fsm.userdata = adapter;
 	adapter->d_out.fsm.printdebug = dout_debug;
 
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 7aa810d..2cf5d1a 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -43,10 +43,10 @@
 module_param(number_of_leds, int, 0);
 
 #ifdef CONFIG_HISAX_DEBUG
-static int debug = 0x1;
+static int debug = 0;
 module_param(debug, int, 0);
-int st5481_debug;
 #endif
+int st5481_debug;
 
 static LIST_HEAD(adapter_list);
 
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ab62223..ffd5b2d 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -132,11 +132,15 @@
 	struct ctrl_msg *ctrl_msg;
 	
 	if (unlikely(urb->status < 0)) {
-		if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
-			WARN("urb status %d",urb->status);
-		} else {
-			DBG(1,"urb killed");
-			return; // Give up
+		switch (urb->status) {
+			case -ENOENT:
+			case -ESHUTDOWN:
+			case -ECONNRESET:
+				DBG(1,"urb killed status %d", urb->status);
+				return; // Give up
+			default: 
+				WARN("urb status %d",urb->status);
+				break;
 		}
 	}
 
@@ -184,22 +188,22 @@
 	int status;
 
 	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		DBG(1, "urb shutting down with status: %d", urb->status);
-		return;
-	default:
-		WARN("nonzero urb status received: %d", urb->status);
-		goto exit;
+		case 0:
+			/* success */
+			break;
+		case -ECONNRESET:
+		case -ENOENT:
+		case -ESHUTDOWN:
+			/* this urb is terminated, clean up */
+			DBG(2, "urb shutting down with status: %d", urb->status);
+			return;
+		default:
+			WARN("nonzero urb status received: %d", urb->status);
+			goto exit;
 	}
 
 	
-	DBG_PACKET(1, data, INT_PKT_SIZE);
+	DBG_PACKET(2, data, INT_PKT_SIZE);
 		
 	if (urb->actual_length == 0) {
 		goto exit;
@@ -250,7 +254,7 @@
 	struct urb *urb;
 	u8 *buf;
 	
-	DBG(1,"");
+	DBG(2,"");
 	
 	if ((status = usb_reset_configuration (dev)) < 0) {
 		WARN("reset_configuration failed,status=%d",status);
@@ -330,15 +334,17 @@
 	DBG(1,"");
 
 	// Stop and free Control and Interrupt URBs
-	usb_unlink_urb(ctrl->urb);
+	usb_kill_urb(ctrl->urb);
 	if (ctrl->urb->transfer_buffer)
 		kfree(ctrl->urb->transfer_buffer);
 	usb_free_urb(ctrl->urb);
+	ctrl->urb = NULL;
 
-	usb_unlink_urb(intr->urb);
+	usb_kill_urb(intr->urb);
 	if (intr->urb->transfer_buffer)
 		kfree(intr->urb->transfer_buffer);
 	usb_free_urb(intr->urb);
+	ctrl->urb = NULL;
 }
 
 /*
@@ -406,6 +412,7 @@
 	spin_lock_init(&urb->lock);
 	urb->dev=dev;
 	urb->pipe=pipe;
+	urb->interval = 1;
 	urb->transfer_buffer=buf;
 	urb->number_of_packets = num_packets;
 	urb->transfer_buffer_length=num_packets*packet_size;
@@ -452,7 +459,9 @@
 		if (urb[j]) {
 			if (urb[j]->transfer_buffer)
 				kfree(urb[j]->transfer_buffer);
+			urb[j]->transfer_buffer = NULL;
 			usb_free_urb(urb[j]);
+			urb[j] = NULL;
 		}
 	}
 	return retval;
@@ -463,10 +472,11 @@
 	int j;
 
 	for (j = 0; j < 2; j++) {
-		usb_unlink_urb(urb[j]);
+		usb_kill_urb(urb[j]);
 		if (urb[j]->transfer_buffer)
 			kfree(urb[j]->transfer_buffer);			
 		usb_free_urb(urb[j]);
+		urb[j] = NULL;
 	}
 }
 
@@ -485,11 +495,15 @@
 	int len, count, status;
 
 	if (unlikely(urb->status < 0)) {
-		if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
-			WARN("urb status %d",urb->status);
-		} else {
-			DBG(1,"urb killed");
-			return; // Give up
+		switch (urb->status) {
+			case -ENOENT:
+			case -ESHUTDOWN:
+			case -ECONNRESET:
+				DBG(1,"urb killed status %d", urb->status);
+				return; // Give up
+			default: 
+				WARN("urb status %d",urb->status);
+				break;
 		}
 	}
 
@@ -631,7 +645,9 @@
 
 	in->mode = mode;
 
+	in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(in->urb[0]);
+	in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
 	usb_unlink_urb(in->urb[1]);
 
 	if (in->mode != L1_MODE_NULL) {
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/md/raid6.h b/drivers/md/raid6.h
index f80ee63..31cbee7 100644
--- a/drivers/md/raid6.h
+++ b/drivers/md/raid6.h
@@ -69,9 +69,13 @@
 #define __init
 #define __exit
 #define __attribute_const__ __attribute__((const))
+#define noinline __attribute__((noinline))
 
 #define preempt_enable()
 #define preempt_disable()
+#define cpu_has_feature(x) 1
+#define enable_kernel_altivec()
+#define disable_kernel_altivec()
 
 #endif /* __KERNEL__ */
 
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index acf386f..51c63c0 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -19,6 +19,7 @@
 #include "raid6.h"
 #ifndef __KERNEL__
 #include <sys/mman.h>
+#include <stdio.h>
 #endif
 
 struct raid6_calls raid6_call;
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index 1de8f03..b9afd35 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -27,16 +27,20 @@
 #ifdef CONFIG_ALTIVEC
 
 #include <altivec.h>
-#include <asm/system.h>
-#include <asm/cputable.h>
+#ifdef __KERNEL__
+# include <asm/system.h>
+# include <asm/cputable.h>
+#endif
 
 /*
- * This is the C data type to use
+ * This is the C data type to use.  We use a vector of
+ * signed char so vec_cmpgt() will generate the right
+ * instruction.
  */
 
-typedef vector unsigned char unative_t;
+typedef vector signed char unative_t;
 
-#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
+#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
 #define NSIZE	sizeof(unative_t)
 
 /*
@@ -108,7 +112,11 @@
 int raid6_have_altivec(void)
 {
 	/* This assumes either all CPUs have Altivec or none does */
+# ifdef __KERNEL__
 	return cpu_has_feature(CPU_FTR_ALTIVEC);
+# else
+	return 1;
+# endif
 }
 #endif
 
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile
index 5578067..78e0396 100644
--- a/drivers/md/raid6test/Makefile
+++ b/drivers/md/raid6test/Makefile
@@ -8,6 +8,8 @@
 CFLAGS	 = -I.. -g $(OPTFLAGS)
 LD	 = ld
 PERL	 = perl
+AR	 = ar
+RANLIB	 = ranlib
 
 .c.o:
 	$(CC) $(CFLAGS) -c -o $@ $<
@@ -18,18 +20,33 @@
 %.uc: ../%.uc
 	cp -f $< $@
 
-all:	raid6.o raid6test
+all:	raid6.a raid6test
 
-raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
+raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
 	 raid6int32.o \
 	 raid6mmx.o raid6sse1.o raid6sse2.o \
+	 raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \
 	 raid6recov.o raid6algos.o \
 	 raid6tables.o
-	$(LD) -r -o $@ $^
+	 rm -f $@
+	 $(AR) cq $@ $^
+	 $(RANLIB) $@
 
-raid6test: raid6.o test.c
+raid6test: test.c raid6.a
 	$(CC) $(CFLAGS) -o raid6test $^
 
+raid6altivec1.c: raid6altivec.uc ../unroll.pl
+	$(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+
+raid6altivec2.c: raid6altivec.uc ../unroll.pl
+	$(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+
+raid6altivec4.c: raid6altivec.uc ../unroll.pl
+	$(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+
+raid6altivec8.c: raid6altivec.uc ../unroll.pl
+	$(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+
 raid6int1.c: raid6int.uc ../unroll.pl
 	$(PERL) ../unroll.pl 1 < raid6int.uc > $@
 
@@ -52,7 +69,7 @@
 	./mktables > raid6tables.c
 
 clean:
-	rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test
+	rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test
 
 spotless: clean
 	rm -f *~
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/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index d15da6f..b7f093f 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -82,7 +82,7 @@
 	} else if (machine_is_tosa()) {
 		sharpsl_partitions[0].size=0x006a0000;
 		sharpsl_partitions[0].offset=0x00160000;
-	} else if (machine_is_spitz()) {
+	} else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) {
 		sharpsl_partitions[0].size=0x006b0000;
 		sharpsl_partitions[0].offset=0x00140000;
 	} else {
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 9853b87..88b5b5b 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -221,10 +221,16 @@
 			sharpsl_partition_info[1].size=25 * 1024 * 1024;
 		} else if (machine_is_husky()) {
 			sharpsl_partition_info[1].size=53 * 1024 * 1024;
-		} 		
+		} else if (machine_is_spitz()) {
+			sharpsl_partition_info[1].size=5 * 1024 * 1024;
+		} else if (machine_is_akita()) {
+			sharpsl_partition_info[1].size=58 * 1024 * 1024;
+		} else if (machine_is_borzoi()) {
+			sharpsl_partition_info[1].size=32 * 1024 * 1024;
+		}
 	}
 
-	if (machine_is_husky()) {
+	if (machine_is_husky() || machine_is_borzoi()) {
 		/* Need to use small eraseblock size for backward compatibility */
 		sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
 	}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 34b80de..bc53744 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -353,8 +353,6 @@
 
 	struct net_device_stats net_stats;
 	struct cp_extra_stats	cp_stats;
-	struct cp_dma_stats	*nic_stats;
-	dma_addr_t		nic_stats_dma;
 
 	unsigned		rx_tail		____cacheline_aligned;
 	struct cp_desc		*rx_ring;
@@ -1143,10 +1141,6 @@
 	cp->rx_ring = mem;
 	cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
 
-	mem += (CP_RING_BYTES - CP_STATS_SIZE);
-	cp->nic_stats = mem;
-	cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
-
 	return cp_init_rings(cp);
 }
 
@@ -1187,7 +1181,6 @@
 	pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
 	cp->rx_ring = NULL;
 	cp->tx_ring = NULL;
-	cp->nic_stats = NULL;
 }
 
 static int cp_open (struct net_device *dev)
@@ -1516,13 +1509,17 @@
 				  struct ethtool_stats *estats, u64 *tmp_stats)
 {
 	struct cp_private *cp = netdev_priv(dev);
+	struct cp_dma_stats *nic_stats;
+	dma_addr_t dma;
 	int i;
 
-	memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+	nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
+	if (!nic_stats)
+		return;
 
 	/* begin NIC statistics dump */
-	cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
-	cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
+	cpw32(StatsAddr + 4, (u64)dma >> 32);
+	cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
 	cpr32(StatsAddr);
 
 	for (i = 0; i < 1000; i++) {
@@ -1532,24 +1529,27 @@
 	}
 	cpw32(StatsAddr, 0);
 	cpw32(StatsAddr + 4, 0);
+	cpr32(StatsAddr);
 
 	i = 0;
-	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
-	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
-	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
-	tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
-	tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
-	tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
-	tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
-	tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
-	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
-	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
-	tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
-	tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
-	tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
+	tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
+	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
+	tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
+	tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
+	tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
+	tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
+	tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
+	tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
+	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
+	tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
+	tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
+	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
+	tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
 	tmp_stats[i++] = cp->cp_stats.rx_frags;
 	if (i != CP_NUM_STATS)
 		BUG();
+
+	pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
 }
 
 static struct ethtool_ops cp_ethtool_ops = {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 54fff9c..96f14ab 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1951,7 +1951,7 @@
 	---help---
 	  This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
 	  and related Gigabit Ethernet adapters. It is a new smaller driver
-	  driver with better performance and more complete ethtool support.
+	  with better performance and more complete ethtool support.
 
 	  It does not support the link failover and network management 
 	  features that "portable" vendor supplied sk98lin driver does.
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/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94c9f68..90449a0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2879,6 +2879,7 @@
 		 * This target is not on a VLAN
 		 */
 		if (rt->u.dst.dev == bond->dev) {
+			ip_rt_put(rt);
 			dprintk("basa: rtdev == bond->dev: arp_send\n");
 			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
 				      bond->master_ip, 0);
@@ -2898,6 +2899,7 @@
 		}
 
 		if (vlan_id) {
+			ip_rt_put(rt);
 			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
 				      vlan->vlan_ip, vlan_id);
 			continue;
@@ -2909,6 +2911,7 @@
 			       bond->dev->name, NIPQUAD(fl.fl4_dst),
 			       rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
 		}
+		ip_rt_put(rt);
 	}
 }
 
@@ -5036,6 +5039,14 @@
 	return 0;
 
 out_err:
+	/*
+	 * rtnl_unlock() will run netdev_run_todo(), putting the
+	 * thus-far-registered bonding devices into a state which
+	 * unregigister_netdevice() will accept
+	 */
+	rtnl_unlock();
+	rtnl_lock();
+
 	/* free and unregister all bonds that were successfully added */
 	bond_free_all();
 
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 25cc20e..fbf1c06 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1387,13 +1387,13 @@
 		ns->collisions += nic->tx_collisions;
 		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
 			le32_to_cpu(s->tx_lost_crs);
-		ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
 		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
 			nic->rx_over_length_errors;
 		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
 		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
 		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
 		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+		ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
 		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
 			le32_to_cpu(s->rx_alignment_errors) +
 			le32_to_cpu(s->rx_short_frame_errors) +
@@ -1727,12 +1727,10 @@
 
 	if(unlikely(!(rfd_status & cb_ok))) {
 		/* Don't indicate if hardware indicates errors */
-		nic->net_stats.rx_dropped++;
 		dev_kfree_skb_any(skb);
 	} else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
 		/* Don't indicate oversized frames */
 		nic->rx_over_length_errors++;
-		nic->net_stats.rx_dropped++;
 		dev_kfree_skb_any(skb);
 	} else {
 		nic->net_stats.rx_packets++;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 7c8a0a2..ee687c9 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2544,7 +2544,6 @@
 		adapter->stats.crcerrs + adapter->stats.algnerrc +
 		adapter->stats.rlec + adapter->stats.mpc + 
 		adapter->stats.cexterr;
-	adapter->net_stats.rx_dropped = adapter->stats.mpc;
 	adapter->net_stats.rx_length_errors = adapter->stats.rlec;
 	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
 	adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 5c55537..89d6d69 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1616,8 +1616,6 @@
 	    adapter->stats.icbc +
 	    adapter->stats.ecbc + adapter->stats.mpc;
 
-	adapter->net_stats.rx_dropped = adapter->stats.mpc;
-
 	/* see above
 	 * adapter->net_stats.rx_length_errors = adapter->stats.rlec;
 	 */
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c829e6a..dd451e0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -428,7 +428,7 @@
 				DBG_PRINT(INIT_DBG, 
 				"%s: Zero DMA address for TxDL. ", dev->name);
 				DBG_PRINT(INIT_DBG, 
-				"Virtual address %llx\n", (u64)tmp_v);
+				"Virtual address %p\n", tmp_v);
 				tmp_v = pci_alloc_consistent(nic->pdev,
 						     PAGE_SIZE, &tmp_p);
 				if (!tmp_v) {
@@ -657,9 +657,10 @@
 					    mac_control->zerodma_virt_addr,
 					    (dma_addr_t)0);
 			DBG_PRINT(INIT_DBG, 
-			"%s: Freeing TxDL with zero DMA addr. ", dev->name);
-			DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
-			(u64)(mac_control->zerodma_virt_addr));
+			  	"%s: Freeing TxDL with zero DMA addr. ",
+				dev->name);
+			DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+				mac_control->zerodma_virt_addr);
 		}
 		kfree(mac_control->fifos[i].list_info);
 	}
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 6ee4771..2e72d79 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5216,17 +5216,15 @@
 	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ *	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
 	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#if 0	/* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
-	{ PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
 	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
 	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, }
+	{ 0 }
 };
 
 MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index d7c9851..0208258 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"0.9"
+#define DRV_VERSION		"1.0"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
@@ -669,7 +669,7 @@
 				     PHY_M_LED_BLINK_RT(BLINK_84MS) |
 				     PHY_M_LEDC_TX_CTRL |
 				     PHY_M_LEDC_DP_CTRL);
-		
+
 			gm_phy_write(hw, port, PHY_MARV_LED_OVER,
 				     PHY_M_LED_MO_RX(MO_LED_OFF) |
 				     (skge->speed == SPEED_100 ?
@@ -876,7 +876,7 @@
 
 static void skge_link_up(struct skge_port *skge)
 {
-	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), 
+	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
 		    LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
 
 	netif_carrier_on(skge->netdev);
@@ -987,6 +987,8 @@
 {
 	const u8 zero[8]  = { 0 };
 
+	skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
 	/* reset the statistics module */
 	xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
 	xm_write16(hw, port, XM_IMSK, 0xffff);	/* disable XMAC IRQs */
@@ -1021,8 +1023,6 @@
 	(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
 	status = xm_phy_read(hw, port, PHY_BCOM_STAT);
 
-	pr_debug("bcom_check_link status=0x%x\n", status);
-
 	if ((status & PHY_ST_LSYNC) == 0) {
 		u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
 		cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1106,8 +1106,6 @@
 		{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
 	};
 
-	pr_debug("bcom_phy_init\n");
-
 	/* read Id from external PHY (all have the same address) */
 	id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
 
@@ -1340,6 +1338,8 @@
 	int port = skge->port;
 	u32 reg;
 
+	genesis_reset(hw, port);
+
 	/* Clear Tx packet arbiter timeout IRQ */
 	skge_write16(hw, B3_PA_CTRL,
 		     port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1465,7 +1465,6 @@
 	u16 cmd;
 	u32 mode, msk;
 
-	pr_debug("genesis_link_up\n");
 	cmd = xm_read16(hw, port, XM_MMU_CMD);
 
 	/*
@@ -1578,7 +1577,6 @@
 	struct skge_port *skge = netdev_priv(hw->dev[port]);
 	u16 ctrl, ct1000, adv;
 
-	pr_debug("yukon_init\n");
 	if (skge->autoneg == AUTONEG_ENABLE) {
 		u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
 
@@ -1677,9 +1675,11 @@
 
 	/* WA code for COMA mode -- set PHY reset */
 	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-	    hw->chip_rev >= CHIP_REV_YU_LITE_A3)
-		skge_write32(hw, B2_GP_IO,
-			     (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+	    hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+		reg = skge_read32(hw, B2_GP_IO);
+		reg |= GP_DIR_9 | GP_IO_9;
+		skge_write32(hw, B2_GP_IO, reg);
+	}
 
 	/* hard reset */
 	skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
@@ -1687,10 +1687,12 @@
 
 	/* WA code for COMA mode -- clear PHY reset */
 	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-	    hw->chip_rev >= CHIP_REV_YU_LITE_A3)
-		skge_write32(hw, B2_GP_IO,
-			     (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
-			     & ~GP_IO_9);
+	    hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+		reg = skge_read32(hw, B2_GP_IO);
+		reg |= GP_DIR_9;
+		reg &= ~GP_IO_9;
+		skge_write32(hw, B2_GP_IO, reg);
+	}
 
 	/* Set hardware config mode */
 	reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
@@ -1729,7 +1731,7 @@
 	}
 
 	gma_write16(hw, port, GM_GP_CTRL, reg);
-	skge_read16(hw, GMAC_IRQ_SRC);
+	skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
 
 	yukon_init(hw, port);
 
@@ -1801,20 +1803,26 @@
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
 
-	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
-	    hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
-		skge_write32(hw, B2_GP_IO,
-			     skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
-	}
+	skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+	yukon_reset(hw, port);
 
 	gma_write16(hw, port, GM_GP_CTRL,
 			 gma_read16(hw, port, GM_GP_CTRL)
 			 & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
 	gma_read16(hw, port, GM_GP_CTRL);
 
+	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+	    hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+		u32 io = skge_read32(hw, B2_GP_IO);
+
+		io |= GP_DIR_9 | GP_IO_9;
+		skge_write32(hw, B2_GP_IO, io);
+		skge_read32(hw, B2_GP_IO);
+	}
+
 	/* set GPHY Control reset */
-	skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
-	skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+	skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+	skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
 }
 
 static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1873,10 +1881,8 @@
 	int port = skge->port;
 	u16 reg;
 
-	pr_debug("yukon_link_up\n");
-
 	/* Enable Transmit FIFO Underrun */
-	skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+	skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
 
 	reg = gma_read16(hw, port, GM_GP_CTRL);
 	if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1896,7 +1902,6 @@
 	int port = skge->port;
 	u16 ctrl;
 
-	pr_debug("yukon_link_down\n");
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
 
 	ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2112,7 +2117,6 @@
 	skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
 	skge_led(skge, LED_MODE_ON);
 
-	pr_debug("skge_up completed\n");
 	return 0;
 
  free_rx_ring:
@@ -2135,15 +2139,20 @@
 
 	netif_stop_queue(dev);
 
+	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		genesis_stop(skge);
+	else
+		yukon_stop(skge);
+
+	hw->intr_mask &= ~portirqmask[skge->port];
+	skge_write32(hw, B0_IMSK, hw->intr_mask);
+
 	/* Stop transmitter */
 	skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
 	skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
 		     RB_RST_SET|RB_DIS_OP_MD);
 
-	if (hw->chip_id == CHIP_ID_GENESIS)
-		genesis_stop(skge);
-	else
-		yukon_stop(skge);
 
 	/* Disable Force Sync bit and Enable Alloc bit */
 	skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2367,8 +2376,6 @@
 	u32 mode;
 	u8 filter[8];
 
-	pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
 	mode = xm_read32(hw, port, XM_MODE);
 	mode |= XM_MD_ENA_HASH;
 	if (dev->flags & IFF_PROMISC)
@@ -2530,8 +2537,6 @@
 	unsigned int to_do = min(dev->quota, *budget);
 	unsigned int work_done = 0;
 
-	pr_debug("skge_poll\n");
-
 	for (e = ring->to_clean; work_done < to_do; e = e->next) {
 		struct skge_rx_desc *rd = e->desc;
 		struct sk_buff *skb;
@@ -2672,9 +2677,9 @@
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 		/* clear xmac errors */
 		if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
-			skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+			skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
 		if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
-			skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+			skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
 	} else {
 		/* Timestamp (unused) overflow */
 		if (hwstatus & IS_IRQ_TIST_OV)
@@ -3000,9 +3005,6 @@
 
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
 
-	if (hw->chip_id != CHIP_ID_GENESIS)
-		skge_write8(hw, GMAC_IRQ_MSK, 0);
-
 	spin_lock_bh(&hw->phy_lock);
 	for (i = 0; i < hw->ports; i++) {
 		if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3230,6 +3232,11 @@
 	dev0 = hw->dev[0];
 	unregister_netdev(dev0);
 
+	skge_write32(hw, B0_IMSK, 0);
+	skge_write16(hw, B0_LED, LED_STAT_OFF);
+	skge_pci_clear(hw);
+	skge_write8(hw, B0_CTST, CS_RST_SET);
+
 	tasklet_kill(&hw->ext_tasklet);
 
 	free_irq(pdev->irq, hw);
@@ -3238,7 +3245,7 @@
 	if (dev1)
 		free_netdev(dev1);
 	free_netdev(dev0);
-	skge_write16(hw, B0_LED, LED_STAT_OFF);
+
 	iounmap(hw->regs);
 	kfree(hw);
 	pci_set_drvdata(pdev, NULL);
@@ -3257,7 +3264,10 @@
 			struct skge_port *skge = netdev_priv(dev);
 			if (netif_running(dev)) {
 				netif_carrier_off(dev);
-				skge_down(dev);
+				if (skge->wol)
+					netif_stop_queue(dev);
+				else
+					skge_down(dev);
 			}
 			netif_device_detach(dev);
 			wol |= skge->wol;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index f1680be..efbf98c 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2008,7 +2008,7 @@
 	GM_IS_RX_FF_OR	= 1<<1,	/* Receive FIFO Overrun */
 	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
 
-#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK	(GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
 
 /*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
 						/* Bits 15.. 2:	reserved */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 4e19220..c796f41 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1817,6 +1817,10 @@
 	/* LEDs active in both modes, autosense prio = fiber */
 	spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
 
+	/* switch off fibre autoneg */
+	spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
+	spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+
 	phy->def->ops->read_link(phy);
 	pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
 		phy->speed, phy->duplex==1 ? "Full" : "Half");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7599f52..81f4aed 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -67,8 +67,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.39"
-#define DRV_MODULE_RELDATE	"September 5, 2005"
+#define DRV_MODULE_VERSION	"3.40"
+#define DRV_MODULE_RELDATE	"September 15, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -3442,31 +3442,47 @@
 	schedule_work(&tp->reset_task);
 }
 
+/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
+static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+{
+	u32 base = (u32) mapping & 0xffffffff;
+
+	return ((base > 0xffffdcc0) &&
+		(base + len + 8 < base));
+}
+
 static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
 
 static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
-				       u32 guilty_entry, int guilty_len,
-				       u32 last_plus_one, u32 *start, u32 mss)
+				       u32 last_plus_one, u32 *start,
+				       u32 base_flags, u32 mss)
 {
 	struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
-	dma_addr_t new_addr;
+	dma_addr_t new_addr = 0;
 	u32 entry = *start;
-	int i;
+	int i, ret = 0;
 
 	if (!new_skb) {
-		dev_kfree_skb(skb);
-		return -1;
+		ret = -1;
+	} else {
+		/* New SKB is guaranteed to be linear. */
+		entry = *start;
+		new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
+					  PCI_DMA_TODEVICE);
+		/* Make sure new skb does not cross any 4G boundaries.
+		 * Drop the packet if it does.
+		 */
+		if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+			ret = -1;
+			dev_kfree_skb(new_skb);
+			new_skb = NULL;
+		} else {
+			tg3_set_txd(tp, entry, new_addr, new_skb->len,
+				    base_flags, 1 | (mss << 1));
+			*start = NEXT_TX(entry);
+		}
 	}
 
-	/* New SKB is guaranteed to be linear. */
-	entry = *start;
-	new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
-				  PCI_DMA_TODEVICE);
-	tg3_set_txd(tp, entry, new_addr, new_skb->len,
-		    (skb->ip_summed == CHECKSUM_HW) ?
-		    TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
-	*start = NEXT_TX(entry);
-
 	/* Now clean up the sw ring entries. */
 	i = 0;
 	while (entry != last_plus_one) {
@@ -3491,7 +3507,7 @@
 
 	dev_kfree_skb(skb);
 
-	return 0;
+	return ret;
 }
 
 static void tg3_set_txd(struct tg3 *tp, int entry,
@@ -3517,19 +3533,10 @@
 	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
-static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
-{
-	u32 base = (u32) mapping & 0xffffffff;
-
-	return ((base > 0xffffdcc0) &&
-		(base + len + 8 < base));
-}
-
 static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tg3 *tp = netdev_priv(dev);
 	dma_addr_t mapping;
-	unsigned int i;
 	u32 len, entry, base_flags, mss;
 	int would_hit_hwbug;
 
@@ -3624,7 +3631,7 @@
 	would_hit_hwbug = 0;
 
 	if (tg3_4g_overflow_test(mapping, len))
-		would_hit_hwbug = entry + 1;
+		would_hit_hwbug = 1;
 
 	tg3_set_txd(tp, entry, mapping, len, base_flags,
 		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -3648,12 +3655,8 @@
 			tp->tx_buffers[entry].skb = NULL;
 			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
-			if (tg3_4g_overflow_test(mapping, len)) {
-				/* Only one should match. */
-				if (would_hit_hwbug)
-					BUG();
-				would_hit_hwbug = entry + 1;
-			}
+			if (tg3_4g_overflow_test(mapping, len))
+				would_hit_hwbug = 1;
 
 			if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 				tg3_set_txd(tp, entry, mapping, len,
@@ -3669,34 +3672,15 @@
 	if (would_hit_hwbug) {
 		u32 last_plus_one = entry;
 		u32 start;
-		unsigned int len = 0;
 
-		would_hit_hwbug -= 1;
-		entry = entry - 1 - skb_shinfo(skb)->nr_frags;
-		entry &= (TG3_TX_RING_SIZE - 1);
-		start = entry;
-		i = 0;
-		while (entry != last_plus_one) {
-			if (i == 0)
-				len = skb_headlen(skb);
-			else
-				len = skb_shinfo(skb)->frags[i-1].size;
-
-			if (entry == would_hit_hwbug)
-				break;
-
-			i++;
-			entry = NEXT_TX(entry);
-
-		}
+		start = entry - 1 - skb_shinfo(skb)->nr_frags;
+		start &= (TG3_TX_RING_SIZE - 1);
 
 		/* If the workaround fails due to memory/mapping
 		 * failure, silently drop this packet.
 		 */
-		if (tigon3_4gb_hwbug_workaround(tp, skb,
-						entry, len,
-						last_plus_one,
-						&start, mss))
+		if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+						&start, base_flags, mss))
 			goto out_unlock;
 
 		entry = start;
@@ -9271,6 +9255,8 @@
 	static struct pci_device_id write_reorder_chipsets[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
 		             PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
+		             PCI_DEVICE_ID_AMD_K8_NB) },
 		{ },
 	};
 	u32 misc_ctrl_reg;
@@ -9285,7 +9271,7 @@
 		tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
 #endif
 
-	/* If we have an AMD 762 chipset, write
+	/* If we have an AMD 762 or K8 chipset, write
 	 * reordering to the mailbox registers done by the host
 	 * controller can cause major troubles.  We read back from
 	 * every mailbox register write to force the writes to be
@@ -9532,7 +9518,7 @@
 		tp->write32_rx_mbox = tg3_write_indirect_mbox;
 
 		iounmap(tp->regs);
-		tp->regs = 0;
+		tp->regs = NULL;
 
 		pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
 		pci_cmd &= ~PCI_COMMAND_MEMORY;
@@ -10680,7 +10666,7 @@
 err_out_iounmap:
 	if (tp->regs) {
 		iounmap(tp->regs);
-		tp->regs = 0;
+		tp->regs = NULL;
 	}
 
 err_out_free_dev:
@@ -10705,7 +10691,7 @@
 		unregister_netdev(dev);
 		if (tp->regs) {
 			iounmap(tp->regs);
-			tp->regs = 0;
+			tp->regs = NULL;
 		}
 		free_netdev(dev);
 		pci_release_regions(pdev);
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 26cc4f6..60d1e05 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -117,7 +117,7 @@
 static int xircom_close(struct net_device *dev);
 static void xircom_up(struct xircom_private *card);
 static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-#if CONFIG_NET_POLL_CONTROLLER
+#ifdef CONFIG_NET_POLL_CONTROLLER
 static void xircom_poll_controller(struct net_device *dev);
 #endif
 
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 48c03c1..a01efa6 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -72,7 +72,7 @@
 	}
 	skb_reserve(skb, 4);
 	cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
-	data = (cisco_packet*)skb->data;
+	data = (cisco_packet*)(skb->data + 4);
 
 	data->type = htonl(type);
 	data->par1 = htonl(par1);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2be65d3..06998c2 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -6852,7 +6852,10 @@
 	/* Add frequency */
 	iwe.cmd = SIOCGIWFREQ;
 	iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
-	iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+	/* iwe.u.freq.m containt the channel (starting 1), our 
+	 * frequency_list array start at index 0...
+	 */
+	iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
 	iwe.u.freq.e = 1;
 	current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
 
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d1fb1ba..bedd7f9f 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/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 8122fe7..b1ba429 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -558,7 +558,7 @@
 	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
 	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
 
-	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
+	pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
 	pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
 
 	return 0;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0e09476..898f6da 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -2526,7 +2526,6 @@
 	int cloop;
 	u8 temp_byte;
 	u8 class_code;
-	u16 temp_word;
 	u32 rc;
 	u32 temp_register;
 	u32 base;
@@ -2682,8 +2681,7 @@
 		}		/* End of base register loop */
 
 		/* disable ROM base Address */
-		temp_word = 0x00L;
-		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+		rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
 
 		/* Set HP parameters (Cache Line Size, Latency Timer) */
 		rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 783b5ab..91c9903 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -2824,8 +2824,7 @@
 		}
 #endif
 		/* Disable ROM base Address */
-		temp_word = 0x00L;
-		rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+		rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
 
 		/* Set HP parameters (Cache Line Size, Latency Timer) */
 		rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 992db89..259d247 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -309,17 +309,25 @@
 
 	pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
 
-	/* If we're in D3, force entire word to 0.
+	/* If we're (effectively) in D3, force entire word to 0.
 	 * This doesn't affect PME_Status, disables PME_En, and
 	 * sets PowerState to 0.
 	 */
-	if (dev->current_state >= PCI_D3hot) {
-		if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+	switch (dev->current_state) {
+	case PCI_UNKNOWN: /* Boot-up */
+		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
+		 && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
 			need_restore = 1;
+		/* Fall-through: force to D0 */
+	case PCI_D3hot:
+	case PCI_D3cold:
+	case PCI_POWER_ERROR:
 		pmcsr = 0;
-	} else {
+		break;
+	default:
 		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
 		pmcsr |= state;
+		break;
 	}
 
 	/* enter specified state */
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/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index f0997c3..ba4d78e 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1045,7 +1045,18 @@
 {
 	struct yenta_socket *socket;
 	int ret;
-	
+
+	/*
+	 * If we failed to assign proper bus numbers for this cardbus
+	 * controller during PCI probe, its subordinate pci_bus is NULL.
+	 * Bail out if so.
+	 */
+	if (!dev->subordinate) {
+		printk(KERN_ERR "Yenta: no bus associated with %s! "
+			"(try 'pci=assign-busses')\n", pci_name(dev));
+		return -ENODEV;
+	}
+
 	socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
 	if (!socket)
 		return -ENOMEM;
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aac83ce..a1c52a6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.34 $
+ *   $Revision: 1.35 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -35,7 +35,7 @@
  */
 
 /* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
 			 (8*sizeof(long)))
 static unsigned long bl_dev[__BL_DEV_WORDS];
 typedef enum {add, free} range_action;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 6aeef3b..0cb47ec 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -682,9 +682,6 @@
 	del_timer(&config_timer);
 	del_timer(&cleanup_timer);
 
-	if (z90_device_work)
-		destroy_workqueue(z90_device_work);
-
 	destroy_z90crypt();
 
 	PRINTKN("Unloaded.\n");
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 96ca863..0db4f57 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
+ * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
  *
  * CTC / ESCON network driver
  *
@@ -37,10 +37,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
  *
  */
-
 #undef DEBUG
 #include <linux/module.h>
 #include <linux/init.h>
@@ -135,7 +134,7 @@
 	"TX down",
 	"Restart",
 };
-
+
 /**
  * Events of the channel statemachine
  */
@@ -249,7 +248,7 @@
 print_banner(void)
 {
 	static int printed = 0;
-	char vbuf[] = "$Revision: 1.74 $";
+	char vbuf[] = "$Revision: 1.78 $";
 	char *version = vbuf;
 
 	if (printed)
@@ -334,7 +333,7 @@
 	"Restarting",
 	"Not operational",
 };
-
+
 #ifdef DEBUG
 /**
  * Dump header and first 16 bytes of an sk_buff for debugging purposes.
@@ -671,7 +670,7 @@
 fsm_action_nop(fsm_instance * fi, int event, void *arg)
 {
 }
-
+
 /**
  * Actions for channel - statemachines.
  *****************************************************************************/
@@ -1514,7 +1513,6 @@
  	fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
 }
 
-
 /**
  * The statemachine for a channel.
  */
@@ -1625,7 +1623,7 @@
 };
 
 static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-
+
 /**
  * Functions related to setup and device detection.
  *****************************************************************************/
@@ -1976,7 +1974,7 @@
 		fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
 
 }
-
+
 /**
  * Actions for interface - statemachine.
  *****************************************************************************/
@@ -2209,13 +2207,18 @@
 	int rc = 0;
 
 	DBF_TEXT(trace, 5, __FUNCTION__);
+	/* we need to acquire the lock for testing the state
+	 * otherwise we can have an IRQ changing the state to 
+	 * TXIDLE after the test but before acquiring the lock.
+	 */
+	spin_lock_irqsave(&ch->collect_lock, saveflags);
 	if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
 		int l = skb->len + LL_HEADER_LENGTH;
 
-		spin_lock_irqsave(&ch->collect_lock, saveflags);
-		if (ch->collect_len + l > ch->max_bufsize - 2)
-			rc = -EBUSY;
-		else {
+		if (ch->collect_len + l > ch->max_bufsize - 2) {
+			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+			return -EBUSY;
+		} else {
 			atomic_inc(&skb->users);
 			header.length = l;
 			header.type = skb->protocol;
@@ -2231,7 +2234,7 @@
 		int ccw_idx;
 		struct sk_buff *nskb;
 		unsigned long hi;
-
+		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
 		/**
 		 * Protect skb against beeing free'd by upper
 		 * layers.
@@ -2256,6 +2259,7 @@
 			if (!nskb) {
 				atomic_dec(&skb->users);
 				skb_pull(skb, LL_HEADER_LENGTH + 2);
+				ctc_clear_busy(ch->netdev);
 				return -ENOMEM;
 			} else {
 				memcpy(skb_put(nskb, skb->len),
@@ -2281,6 +2285,7 @@
 				 */
 				atomic_dec(&skb->users);
 				skb_pull(skb, LL_HEADER_LENGTH + 2);
+				ctc_clear_busy(ch->netdev);
 				return -EBUSY;
 			}
 
@@ -2327,9 +2332,10 @@
 		}
 	}
 
+	ctc_clear_busy(ch->netdev);
 	return rc;
 }
-
+
 /**
  * Interface API for upper network layers
  *****************************************************************************/
@@ -2421,7 +2427,6 @@
 	dev->trans_start = jiffies;
 	if (transmit_skb(privptr->channel[WRITE], skb) != 0)
 		rc = 1;
-	ctc_clear_busy(dev);
 	return rc;
 }
 
@@ -2610,7 +2615,6 @@
 	return count;
 }
 
-
 static void
 ctc_netdev_unregister(struct net_device * dev)
 {
@@ -2685,7 +2689,6 @@
 	return count;
 }
 
-
 static ssize_t
 ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 3a02856..2ad4797 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.139 $"
+#define VERSION_QETH_H 		"$Revision: 1.142 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
@@ -1172,7 +1172,7 @@
 qeth_realloc_buffer_pool(struct qeth_card *, int);
 
 extern int
-qeth_set_large_send(struct qeth_card *);
+qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
 
 extern void
 qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 79c74f3..86582cf 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.214 $	 $Date: 2005/05/04 20:19:18 $
+ *    $Revision: 1.224 $	 $Date: 2005/05/04 20:19:18 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,14 +29,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
-	return;
-}
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -80,7 +72,7 @@
 #include "qeth_eddp.h"
 #include "qeth_tso.h"
 
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2759,11 +2751,9 @@
 		queue->card->perf_stats.outbound_do_qdio_start_time;
 #endif
 	if (rc){
-		QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
-				 "returned error (%i) on device %s.",
-				 rc, CARD_DDEV_ID(queue->card));
 		QETH_DBF_TEXT(trace, 2, "flushbuf");
 		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+		QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
 		queue->card->stats.tx_errors += count;
 		/* this must not happen under normal circumstances. if it
 		 * happens something is really wrong -> recover */
@@ -2909,11 +2899,8 @@
 	QETH_DBF_TEXT(trace, 6, "qdouhdl");
 	if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
 		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
-			QETH_DBF_SPRINTF(trace, 2, "On device %s: "
-					 "received active check "
-				         "condition (0x%08x).",
-					 CARD_BUS_ID(card), status);
-			QETH_DBF_TEXT(trace, 2, "chkcond");
+			QETH_DBF_TEXT(trace, 2, "achkcond");
+			QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
 			QETH_DBF_TEXT_(trace, 2, "%08x", status);
 			netif_stop_queue(card->dev);
 			qeth_schedule_recovery(card);
@@ -3356,26 +3343,32 @@
 static int
 qeth_halt_channels(struct qeth_card *card)
 {
-	int rc = 0;
+	int rc1 = 0, rc2=0, rc3 = 0;
 
 	QETH_DBF_TEXT(trace,3,"haltchs");
-	if ((rc = qeth_halt_channel(&card->read)))
-		return rc;
-	if ((rc = qeth_halt_channel(&card->write)))
-		return rc;
-	return  qeth_halt_channel(&card->data);
+	rc1 = qeth_halt_channel(&card->read);
+	rc2 = qeth_halt_channel(&card->write);
+	rc3 = qeth_halt_channel(&card->data);
+	if (rc1)
+		return rc1;
+	if (rc2) 
+		return rc2;
+	return rc3;
 }
 static int
 qeth_clear_channels(struct qeth_card *card)
 {
-	int rc = 0;
+	int rc1 = 0, rc2=0, rc3 = 0;
 
 	QETH_DBF_TEXT(trace,3,"clearchs");
-	if ((rc = qeth_clear_channel(&card->read)))
-		return rc;
-	if ((rc = qeth_clear_channel(&card->write)))
-		return rc;
-	return  qeth_clear_channel(&card->data);
+	rc1 = qeth_clear_channel(&card->read);
+	rc2 = qeth_clear_channel(&card->write);
+	rc3 = qeth_clear_channel(&card->data);
+	if (rc1)
+		return rc1;
+	if (rc2) 
+		return rc2;
+	return rc3;
 }
 
 static int
@@ -3445,23 +3438,23 @@
 	}
 	if ((rc = qeth_cm_enable(card))){
 		QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
-		return rc;
+		goto out_qdio;
 	}
 	if ((rc = qeth_cm_setup(card))){
 		QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
-		return rc;
+		goto out_qdio;
 	}
 	if ((rc = qeth_ulp_enable(card))){
 		QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
-		return rc;
+		goto out_qdio;
 	}
 	if ((rc = qeth_ulp_setup(card))){
 		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		return rc;
+		goto out_qdio;
 	}
 	if ((rc = qeth_alloc_qdio_buffers(card))){
 		QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
-		return rc;
+		goto out_qdio;
 	}
 	if ((rc = qeth_qdio_establish(card))){
 		QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -3795,12 +3788,16 @@
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
 		 struct qeth_hdr **hdr, int ipv)
 {
+	int rc;
 #ifdef CONFIG_QETH_VLAN
 	u16 *tag;
 #endif
 
 	QETH_DBF_TEXT(trace, 6, "prepskb");
 
+        rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+        if (rc)
+                return rc;
 #ifdef CONFIG_QETH_VLAN
 	if (card->vlangrp && vlan_tx_tag_present(*skb) &&
 	    ((ipv == 6) || card->options.layer2) ) {
@@ -4251,7 +4248,8 @@
 }
 
 static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr, 
+		     struct sk_buff *skb, int elems)
 {
 	int elements_needed = 0;
 
@@ -4261,9 +4259,10 @@
         if (elements_needed == 0 )
                 elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
                                         + skb->len) >> PAGE_SHIFT);
-        if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
                 PRINT_ERR("qeth_do_send_packet: invalid size of "
-                          "IP packet. Discarded.");
+                          "IP packet (Number=%d / Length=%d). Discarded.\n",
+                          (elements_needed+elems), skb->len);
                 return 0;
         }
         return elements_needed;
@@ -4275,7 +4274,7 @@
 	int ipv = 0;
 	int cast_type;
 	struct qeth_qdio_out_q *queue;
-	struct qeth_hdr *hdr;
+	struct qeth_hdr *hdr = NULL;
 	int elements_needed = 0;
 	enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
 	struct qeth_eddp_context *ctx = NULL;
@@ -4337,9 +4336,11 @@
 			return -EINVAL;
 		}
 	} else {
-		elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
-		if (!elements_needed)
+		int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+						 elements_needed);
+		if (!elems)
 			return -EINVAL;
+		elements_needed += elems;
 	}
 
 	if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -4504,7 +4505,11 @@
 
 	QETH_DBF_TEXT(trace,3,"arpstnoe");
 
-	/* TODO: really not supported by GuestLAN? */
+	/*
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+	 * thus we say EOPNOTSUPP for this ARP function
+	 */
 	if (card->info.guestlan)
 		return -EOPNOTSUPP;
 	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4681,14 +4686,6 @@
 
 	QETH_DBF_TEXT(trace,3,"arpquery");
 
-	/*
-	 * currently GuestLAN  does only deliver all zeros on query arp,
-	 * even though arp processing is supported (according to IPA supp.
-	 * funcs flags); since all zeros is no valueable information,
-	 * we say EOPNOTSUPP for all ARP functions
-	 */
-	/*if (card->info.guestlan)
-		return -EOPNOTSUPP; */
 	if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
 			       IPA_ARP_PROCESSING)) {
 		PRINT_WARN("ARP processing not supported "
@@ -4894,10 +4891,9 @@
 	QETH_DBF_TEXT(trace,3,"arpadent");
 
 	/*
-	 * currently GuestLAN  does only deliver all zeros on query arp,
-	 * even though arp processing is supported (according to IPA supp.
-	 * funcs flags); since all zeros is no valueable information,
-	 * we say EOPNOTSUPP for all ARP functions
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+	 * thus we say EOPNOTSUPP for this ARP function
 	 */
 	if (card->info.guestlan)
 		return -EOPNOTSUPP;
@@ -4937,10 +4933,9 @@
 	QETH_DBF_TEXT(trace,3,"arprment");
 
 	/*
-	 * currently GuestLAN  does only deliver all zeros on query arp,
-	 * even though arp processing is supported (according to IPA supp.
-	 * funcs flags); since all zeros is no valueable information,
-	 * we say EOPNOTSUPP for all ARP functions
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+	 * thus we say EOPNOTSUPP for this ARP function
 	 */
 	if (card->info.guestlan)
 		return -EOPNOTSUPP;
@@ -4978,11 +4973,10 @@
 	QETH_DBF_TEXT(trace,3,"arpflush");
 
 	/*
-	 * currently GuestLAN  does only deliver all zeros on query arp,
-	 * even though arp processing is supported (according to IPA supp.
-	 * funcs flags); since all zeros is no valueable information,
-	 * we say EOPNOTSUPP for all ARP functions
-	 */
+	 * currently GuestLAN only supports the ARP assist function
+	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+	 * thus we say EOPNOTSUPP for this ARP function
+	*/
 	if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
 		return -EOPNOTSUPP;
 	if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -7038,14 +7032,16 @@
 }
 
 int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
 {
 	int rc = 0;
 
-	if (card->dev == NULL)
+	if (card->dev == NULL) {
+		card->options.large_send = type;
 		return 0;
-
+	}
 	netif_stop_queue(card->dev);
+	card->options.large_send = type;
 	switch (card->options.large_send) {
 	case QETH_LARGE_SEND_EDDP:
 		card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,7 +7062,6 @@
 		card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
 		break;
 	}
-
 	netif_wake_queue(card->dev);
 	return rc;
 }
@@ -8257,7 +8252,6 @@
 {
 	int rc=0;
 
-	qeth_eyecatcher();
 	PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
 		   version, VERSION_QETH_C, VERSION_QETH_H,
 		   VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
@@ -8338,7 +8332,6 @@
 	printk("qeth: removed\n");
 }
 
-EXPORT_SYMBOL(qeth_eyecatcher);
 module_init(qeth_init);
 module_exit(qeth_exit);
 MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 98bedb0..dda105b 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  * This file contains code related to sysfs.
@@ -20,7 +20,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
 
 /*****************************************************************************/
 /*                                                                           */
@@ -722,10 +722,13 @@
 
 	if (!card)
 		return -EINVAL;
+	if (card->info.type == QETH_CARD_TYPE_IQD) {
+                PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+                return -EPERM;
+        }
 
 	if (((card->state != CARD_STATE_DOWN) &&
-	     (card->state != CARD_STATE_RECOVER)) ||
-	    (card->info.type != QETH_CARD_TYPE_OSAE))
+	     (card->state != CARD_STATE_RECOVER)))
 		return -EPERM;
 
 	i = simple_strtoul(buf, &tmp, 16);
@@ -771,9 +774,7 @@
 
 	if (!card)
 		return -EINVAL;
-
 	tmp = strsep((char **) &buf, "\n");
-
 	if (!strcmp(tmp, "no")){
 		type = QETH_LARGE_SEND_NO;
 	} else if (!strcmp(tmp, "EDDP")) {
@@ -786,10 +787,8 @@
 	}
 	if (card->options.large_send == type)
 		return count;
-	card->options.large_send = type;
-	if ((rc = qeth_set_large_send(card)))
+	if ((rc = qeth_set_large_send(card, type)))	
 		return rc;
-
 	return count;
 }
 
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/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 5cc53cd..d92273c 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2465,9 +2465,12 @@
  *
  *	LOCKING:
  *	None.  (executing in kernel thread context)
+ *
+ *	RETURNS:
+ *	Non-zero if qc completed, zero otherwise.
  */
 
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
 	u8 drv_stat;
@@ -2486,14 +2489,14 @@
 		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
 			ap->pio_task_state = PIO_ST_LAST_POLL;
 			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-			return;
+			return 0;
 		}
 	}
 
 	drv_stat = ata_wait_idle(ap);
 	if (!ata_ok(drv_stat)) {
 		ap->pio_task_state = PIO_ST_ERR;
-		return;
+		return 0;
 	}
 
 	qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2502,6 +2505,10 @@
 	ap->pio_task_state = PIO_ST_IDLE;
 
 	ata_poll_qc_complete(qc, drv_stat);
+
+	/* another command may start at this point */
+
+	return 1;
 }
 
 
@@ -2709,7 +2716,7 @@
 
 next_sg:
 	if (unlikely(qc->cursg >= qc->n_elem)) {
-		/* 
+		/*
 		 * The end of qc->sg is reached and the device expects
 		 * more data to transfer. In order not to overrun qc->sg
 		 * and fulfill length specified in the byte count register,
@@ -2721,7 +2728,7 @@
 		unsigned int i;
 
 		if (words) /* warning if bytes > 1 */
-			printk(KERN_WARNING "ata%u: %u bytes trailing data\n", 
+			printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
 			       ap->id, bytes);
 
 		for (i = 0; i < words; i++)
@@ -2849,9 +2856,7 @@
 	if (is_atapi_taskfile(&qc->tf)) {
 		/* no more data to transfer or unsupported ATAPI command */
 		if ((status & ATA_DRQ) == 0) {
-			ap->pio_task_state = PIO_ST_IDLE;
-
-			ata_poll_qc_complete(qc, status);
+			ap->pio_task_state = PIO_ST_LAST;
 			return;
 		}
 
@@ -2887,7 +2892,12 @@
 static void ata_pio_task(void *_data)
 {
 	struct ata_port *ap = _data;
-	unsigned long timeout = 0;
+	unsigned long timeout;
+	int qc_completed;
+
+fsm_start:
+	timeout = 0;
+	qc_completed = 0;
 
 	switch (ap->pio_task_state) {
 	case PIO_ST_IDLE:
@@ -2898,7 +2908,7 @@
 		break;
 
 	case PIO_ST_LAST:
-		ata_pio_complete(ap);
+		qc_completed = ata_pio_complete(ap);
 		break;
 
 	case PIO_ST_POLL:
@@ -2913,10 +2923,9 @@
 	}
 
 	if (timeout)
-		queue_delayed_work(ata_wq, &ap->pio_task,
-				   timeout);
-	else
-		queue_work(ata_wq, &ap->pio_task);
+		queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+	else if (!qc_completed)
+		goto fsm_start;
 }
 
 static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 3e9b641..23d095d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -201,6 +201,7 @@
 qla2100_pci_config(scsi_qla_host_t *ha)
 {
 	uint16_t w, mwi;
+	uint32_t d;
 	unsigned long flags;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
@@ -215,9 +216,9 @@
 	pci_write_config_word(ha->pdev, PCI_COMMAND, w);
 
 	/* Reset expansion ROM address decode enable */
-	pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
-	w &= ~PCI_ROM_ADDRESS_ENABLE;
-	pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+	pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+	d &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -237,6 +238,7 @@
 qla2300_pci_config(scsi_qla_host_t *ha)
 {
 	uint16_t	w, mwi;
+	uint32_t	d;
 	unsigned long   flags = 0;
 	uint32_t	cnt;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -302,9 +304,9 @@
 	pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
 
 	/* Reset expansion ROM address decode enable */
-	pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
-	w &= ~PCI_ROM_ADDRESS_ENABLE;
-	pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+	pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+	d &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -324,6 +326,7 @@
 qla24xx_pci_config(scsi_qla_host_t *ha)
 {
 	uint16_t w, mwi;
+	uint32_t d;
 	unsigned long flags = 0;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 	int pcix_cmd_reg, pcie_dctl_reg;
@@ -366,9 +369,9 @@
 	}
 
 	/* Reset expansion ROM address decode enable */
-	pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
-	w &= ~PCI_ROM_ADDRESS_ENABLE;
-	pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+	pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+	d &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
 
 	/* Get PCI bus information. */
 	spin_lock_irqsave(&ha->hardware_lock, flags);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index a63f931..b227e51 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -161,7 +161,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 	unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
-	u32 val, val2;
+	u32 val, val2 = 0;
 	u8 pmr;
 
 	if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
@@ -289,7 +289,7 @@
 	if (ent->device != 0x182) {
 		if ((pmr & SIS_PMR_COMBINED) == 0) {
 			printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
-			port2_start=0x64;
+			port2_start = 64;
 		}
 		else {
 			printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n");
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index aec39fb..b5cf394 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -463,7 +463,7 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver serial21285_reg;
+static struct uart_driver serial21285_reg;
 
 static struct console serial21285_console =
 {
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 978e124..679e678 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -689,7 +689,7 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
 static struct console amba_console = {
 	.name		= "ttyAM",
 	.write		= pl010_console_write,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 5607130..1ff629c 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -701,7 +701,7 @@
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
 static struct console amba_console = {
 	.name		= "ttyAMA",
 	.write		= pl011_console_write,
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index d822896..78c1f36 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -525,7 +525,7 @@
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver clps711x_reg;
+static struct uart_driver clps711x_reg;
 static struct console clps711x_console = {
 	.name		= "ttyCL",
 	.write		= clps711xuart_console_write,
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index a3cd0ee..0585ab2 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -781,7 +781,7 @@
 
 #ifdef CONFIG_PM
 static int
-mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level)
 {
 	struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
 
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index eaa0af8..672b359 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -589,8 +589,8 @@
 
 #ifdef CONFIG_SERIAL_PXA_CONSOLE
 
-extern struct uart_pxa_port serial_pxa_ports[];
-extern struct uart_driver serial_pxa_reg;
+static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_driver serial_pxa_reg;
 
 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
 
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 1225b14..dd8aed2 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -799,7 +799,7 @@
 	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver sa1100_reg;
+static struct uart_driver sa1100_reg;
 static struct console sa1100_console = {
 	.name		= "ttySA",
 	.write		= sa1100_console_write,
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 8302376..d01dbe5 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -632,7 +632,7 @@
 	return uart_set_options (port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver lh7a40x_reg;
+static struct uart_driver lh7a40x_reg;
 static struct console lh7a40x_console = {
 	.name		= "ttyAM",
 	.write		= lh7a40xuart_console_write,
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/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..630f2df 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -19,17 +19,18 @@
 #include <linux/fb.h>
 #include <linux/backlight.h>
 
-#include <asm/arch-pxa/corgi.h>
-#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/sharpsl.h>
 
-#define CORGI_MAX_INTENSITY 		0x3e
 #define CORGI_DEFAULT_INTENSITY		0x1f
-#define CORGI_LIMIT_MASK			0x0b
+#define CORGI_LIMIT_MASK		0x0b
 
 static int corgibl_powermode = FB_BLANK_UNBLANK;
 static int current_intensity = 0;
 static int corgibl_limit = 0;
+static void (*corgibl_mach_set_intensity)(int intensity);
 static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_properties corgibl_data;
 
 static void corgibl_send_intensity(int intensity)
 {
@@ -43,18 +44,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 +106,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 +134,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 +142,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/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/console/vgacon.c b/drivers/video/console/vgacon.c
index 0705cd7..6ef6f77 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1020,7 +1020,9 @@
 static int vgacon_resize(struct vc_data *c, unsigned int width,
 				unsigned int height)
 {
-	if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
+	if (width % 2 || width > ORIG_VIDEO_COLS ||
+	    height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+	    c->vc_font.height)
 		return -EINVAL;
 
 	if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cabd53c..6c2244c 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -425,7 +425,7 @@
  * Power management hooks.  Note that we won't be called from IRQ context,
  * unlike the blank functions above, so we may sleep.
  */
-static int imxfb_suspend(struct device *dev, u32 state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level)
 {
 	struct imxfb_info *fbi = dev_get_drvdata(dev);
 	pr_debug("%s\n",__FUNCTION__);
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/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index ace484f..12f2884 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -209,10 +209,13 @@
 
 	if (!edid && conn == 1) {
 		/* try to get from firmware */
-		edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-		if (edid)
-			memcpy(edid, fb_firmware_edid(info->device),
-			       EDID_LENGTH);
+		const u8 *e = fb_firmware_edid(info->device);
+
+		if (e != NULL) {
+			edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+			if (edid)
+				memcpy(edid, e, EDID_LENGTH);
+		}
 	}
 
 	if (out_edid)
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/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 959404a..3c98457 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -274,10 +274,13 @@
 
 	if (!edid) {
 		/* try to get from firmware */
-		edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-		if (edid)
-			memcpy(edid, fb_firmware_edid(info->device),
-			       EDID_LENGTH);
+		const u8 *e = fb_firmware_edid(info->device);
+
+		if (e) {
+			edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+			if (edid)
+				memcpy(edid, e, EDID_LENGTH);
+		}
 	}
 
 	if (out_edid)
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index d6f9474..ea17f7e 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,8 +60,6 @@
 
 #define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
 
-#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
-
 /* Chip tags.  These are used to group the adapters into
  * related families.
  */
@@ -74,8 +72,6 @@
   S3_PROSAVAGE,
   S3_SUPERSAVAGE,
   S3_SAVAGE2000,
-  S3_PROSAVAGEDDR,
-  S3_TWISTER,
   S3_LAST
 } savage_chipset;
 
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index b5ca3ef..7c28545 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1773,8 +1773,7 @@
 		}
 	}
 
-	if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-	    (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+	if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly)
 		par->display_type = DISP_LCD;
 	else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
 		par->display_type = DISP_DFP;
@@ -1783,7 +1782,7 @@
 
 	/* Check LCD panel parrmation */
 
-	if (par->chip == S3_SAVAGE_MX) {
+	if (par->display_type == DISP_LCD) {
 		unsigned char cr6b = VGArCR( 0x6b );
 
 		int panelX = (VGArSEQ (0x61) +
@@ -1922,15 +1921,15 @@
 		snprintf (info->fix.id, 16, "ProSavageKM");
 		break;
 	case FB_ACCEL_S3TWISTER_P:
-		par->chip = S3_TWISTER;
+		par->chip = S3_PROSAVAGE;
 		snprintf (info->fix.id, 16, "TwisterP");
 		break;
 	case FB_ACCEL_S3TWISTER_K:
-		par->chip = S3_TWISTER;
+		par->chip = S3_PROSAVAGE;
 		snprintf (info->fix.id, 16, "TwisterK");
 		break;
 	case FB_ACCEL_PROSAVAGE_DDR:
-		par->chip = S3_PROSAVAGEDDR;
+		par->chip = S3_PROSAVAGE;
 		snprintf (info->fix.id, 16, "ProSavageDDR");
 		break;
 	case FB_ACCEL_PROSAVAGE_DDRK:
diff --git a/fs/aio.c b/fs/aio.c
index 38f6268..0e11e31 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -562,6 +562,7 @@
 static inline void unlock_kiocb(struct kiocb *iocb)
 {
 	kiocbClearLocked(iocb);
+	smp_mb__after_clear_bit();
 	wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
 }
 
diff --git a/fs/compat.c b/fs/compat.c
index ac3fb9e..a719e15 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -44,6 +44,8 @@
 #include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
+#include <linux/acct.h>
+#include <linux/mm.h>
 
 #include <net/sock.h>		/* siocdevprivate_ioctl */
 
@@ -1487,6 +1489,8 @@
 
 		/* execve success */
 		security_bprm_free(bprm);
+		acct_update_integrals(current);
+		update_mem_hiwater(current);
 		kfree(bprm);
 		return retval;
 	}
diff --git a/fs/dcache.c b/fs/dcache.c
index 7376b612..fb10386 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -102,7 +102,8 @@
 		list_del_init(&dentry->d_alias);
 		spin_unlock(&dentry->d_lock);
 		spin_unlock(&dcache_lock);
-		fsnotify_inoderemove(inode);
+		if (!inode->i_nlink)
+			fsnotify_inoderemove(inode);
 		if (dentry->d_op && dentry->d_op->d_iput)
 			dentry->d_op->d_iput(dentry, inode);
 		else
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 6ab1dd0..403b90a 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -231,8 +231,9 @@
 
 static void ep_poll_safewake_init(struct poll_safewake *psw);
 static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile);
-static int ep_file_init(struct file *file);
+static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+		    struct eventpoll *ep);
+static int ep_alloc(struct eventpoll **pep);
 static void ep_free(struct eventpoll *ep);
 static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
 static void ep_use_epitem(struct epitem *epi);
@@ -501,38 +502,37 @@
 asmlinkage long sys_epoll_create(int size)
 {
 	int error, fd;
+	struct eventpoll *ep;
 	struct inode *inode;
 	struct file *file;
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
 		     current, size));
 
-	/* Sanity check on the size parameter */
+	/*
+	 * Sanity check on the size parameter, and create the internal data
+	 * structure ( "struct eventpoll" ).
+	 */
 	error = -EINVAL;
-	if (size <= 0)
+	if (size <= 0 || (error = ep_alloc(&ep)) != 0)
 		goto eexit_1;
 
 	/*
 	 * Creates all the items needed to setup an eventpoll file. That is,
 	 * a file structure, and inode and a free file descriptor.
 	 */
-	error = ep_getfd(&fd, &inode, &file);
-	if (error)
-		goto eexit_1;
-
-	/* Setup the file internal data structure ( "struct eventpoll" ) */
-	error = ep_file_init(file);
+	error = ep_getfd(&fd, &inode, &file, ep);
 	if (error)
 		goto eexit_2;
 
-
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
 		     current, size, fd));
 
 	return fd;
 
 eexit_2:
-	sys_close(fd);
+	ep_free(ep);
+	kfree(ep);
 eexit_1:
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
 		     current, size, error));
@@ -706,7 +706,8 @@
 /*
  * Creates the file descriptor to be used by the epoll interface.
  */
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile)
+static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+		    struct eventpoll *ep)
 {
 	struct qstr this;
 	char name[32];
@@ -756,7 +757,7 @@
 	file->f_op = &eventpoll_fops;
 	file->f_mode = FMODE_READ;
 	file->f_version = 0;
-	file->private_data = NULL;
+	file->private_data = ep;
 
 	/* Install the new setup file into the allocated fd. */
 	fd_install(fd, file);
@@ -777,14 +778,13 @@
 }
 
 
-static int ep_file_init(struct file *file)
+static int ep_alloc(struct eventpoll **pep)
 {
-	struct eventpoll *ep;
+	struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
 
-	if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL)))
+	if (!ep)
 		return -ENOMEM;
 
-	memset(ep, 0, sizeof(*ep));
 	rwlock_init(&ep->lock);
 	init_rwsem(&ep->sem);
 	init_waitqueue_head(&ep->wq);
@@ -792,9 +792,9 @@
 	INIT_LIST_HEAD(&ep->rdllist);
 	ep->rbr = RB_ROOT;
 
-	file->private_data = ep;
+	*pep = ep;
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
 		     current, ep));
 	return 0;
 }
diff --git a/fs/exec.c b/fs/exec.c
index 14dd039..a04a575 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -421,11 +421,6 @@
 	if (!mpnt)
 		return -ENOMEM;
 
-	if (security_vm_enough_memory(arg_size >> PAGE_SHIFT)) {
-		kmem_cache_free(vm_area_cachep, mpnt);
-		return -ENOMEM;
-	}
-
 	memset(mpnt, 0, sizeof(*mpnt));
 
 	down_write(&mm->mmap_sem);
@@ -745,8 +740,8 @@
         }
 
 	/*
-	 * Now there are really no other threads at all,
-	 * so it's safe to stop telling them to kill themselves.
+	 * There may be one thread left which is just exiting,
+	 * but it's safe to stop telling the group to kill themselves.
 	 */
 	sig->flags = 0;
 
@@ -785,7 +780,6 @@
 			kmem_cache_free(sighand_cachep, oldsighand);
 	}
 
-	BUG_ON(!thread_group_empty(current));
 	BUG_ON(!thread_group_leader(current));
 	return 0;
 }
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 62ffa91..7134403 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -12,39 +12,6 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
-static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf,
-				  size_t count, loff_t pos)
-{
-	struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
-	int retval;
-
-	retval = generic_file_aio_write(iocb, buf, count, pos);
-	if (retval > 0) {
-		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-		mark_inode_dirty(inode);
-//		check the locking rules
-//		if (IS_SYNC(inode))
-//			fat_sync_inode(inode);
-	}
-	return retval;
-}
-
-static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov,
-			       unsigned long nr_segs, loff_t *ppos)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	int retval;
-
-	retval = generic_file_writev(filp, iov, nr_segs, ppos);
-	if (retval > 0) {
-		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-		mark_inode_dirty(inode);
-	}
-	return retval;
-}
-
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg)
 {
@@ -148,9 +115,9 @@
 	.read		= do_sync_read,
 	.write		= do_sync_write,
 	.readv		= generic_file_readv,
-	.writev		= fat_file_writev,
+	.writev		= generic_file_writev,
 	.aio_read	= generic_file_aio_read,
-	.aio_write	= fat_file_aio_write,
+	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a7cbe68..51b1d15 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -102,6 +102,19 @@
 				  &MSDOS_I(page->mapping->host)->mmu_private);
 }
 
+static int fat_commit_write(struct file *file, struct page *page,
+			    unsigned from, unsigned to)
+{
+	struct inode *inode = page->mapping->host;
+	int err = generic_commit_write(file, page, from, to);
+	if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
+		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+		mark_inode_dirty(inode);
+	}
+	return err;
+}
+
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
 {
 	return generic_block_bmap(mapping, block, fat_get_block);
@@ -112,7 +125,7 @@
 	.writepage	= fat_writepage,
 	.sync_page	= block_sync_page,
 	.prepare_write	= fat_prepare_write,
-	.commit_write	= generic_commit_write,
+	.commit_write	= fat_commit_write,
 	.bmap		= _fat_bmap
 };
 
diff --git a/fs/file.c b/fs/file.c
index 2127a7b..fd066b2 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -69,13 +69,9 @@
 
 static void __free_fdtable(struct fdtable *fdt)
 {
-	int fdset_size, fdarray_size;
-
-	fdset_size = fdt->max_fdset / 8;
-	fdarray_size = fdt->max_fds * sizeof(struct file *);
-	free_fdset(fdt->open_fds, fdset_size);
-	free_fdset(fdt->close_on_exec, fdset_size);
-	free_fd_array(fdt->fd, fdarray_size);
+	free_fdset(fdt->open_fds, fdt->max_fdset);
+	free_fdset(fdt->close_on_exec, fdt->max_fdset);
+	free_fd_array(fdt->fd, fdt->max_fds);
 	kfree(fdt);
 }
 
diff --git a/fs/locks.c b/fs/locks.c
index c2c09b4..f7daa5f 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -124,6 +124,7 @@
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/time.h>
+#include <linux/rcupdate.h>
 
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -2205,6 +2206,7 @@
 
 	lock_kernel();
 	j = 0;
+	rcu_read_lock();
 	fdt = files_fdtable(files);
 	for (;;) {
 		unsigned long set;
@@ -2222,6 +2224,7 @@
 			set >>= 1;
 		}
 	}
+	rcu_read_unlock();
 	unlock_kernel();
 }
 EXPORT_SYMBOL(steal_locks);
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 49eafbd..c7e9237 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -92,6 +92,8 @@
 	  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.
+	- Fix various bugs in the runlist merging code.  (Based on libntfs
+	  changes by Richard Russon.)
 
 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/aops.c b/fs/ntfs/aops.c
index b6cc8cf..5e80c07 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -59,39 +59,49 @@
 	unsigned long flags;
 	struct buffer_head *first, *tmp;
 	struct page *page;
+	struct inode *vi;
 	ntfs_inode *ni;
 	int page_uptodate = 1;
 
 	page = bh->b_page;
-	ni = NTFS_I(page->mapping->host);
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
 
 	if (likely(uptodate)) {
-		s64 file_ofs, initialized_size;
+		loff_t i_size;
+		s64 file_ofs, init_size;
 
 		set_buffer_uptodate(bh);
 
 		file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) +
 				bh_offset(bh);
 		read_lock_irqsave(&ni->size_lock, flags);
-		initialized_size = ni->initialized_size;
+		init_size = ni->initialized_size;
+		i_size = i_size_read(vi);
 		read_unlock_irqrestore(&ni->size_lock, flags);
+		if (unlikely(init_size > i_size)) {
+			/* Race with shrinking truncate. */
+			init_size = i_size;
+		}
 		/* Check for the current buffer head overflowing. */
-		if (file_ofs + bh->b_size > initialized_size) {
-			char *addr;
-			int ofs = 0;
+		if (unlikely(file_ofs + bh->b_size > init_size)) {
+			u8 *kaddr;
+			int ofs;
 
-			if (file_ofs < initialized_size)
-				ofs = initialized_size - file_ofs;
-			addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
-			memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs);
+			ofs = 0;
+			if (file_ofs < init_size)
+				ofs = init_size - file_ofs;
+			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+			memset(kaddr + bh_offset(bh) + ofs, 0,
+					bh->b_size - ofs);
+			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
 			flush_dcache_page(page);
-			kunmap_atomic(addr, KM_BIO_SRC_IRQ);
 		}
 	} else {
 		clear_buffer_uptodate(bh);
 		SetPageError(page);
-		ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.",
-				(unsigned long long)bh->b_blocknr);
+		ntfs_error(ni->vol->sb, "Buffer I/O error, logical block "
+				"0x%llx.", (unsigned long long)bh->b_blocknr);
 	}
 	first = page_buffers(page);
 	local_irq_save(flags);
@@ -124,7 +134,7 @@
 		if (likely(page_uptodate && !PageError(page)))
 			SetPageUptodate(page);
 	} else {
-		char *addr;
+		u8 *kaddr;
 		unsigned int i, recs;
 		u32 rec_size;
 
@@ -132,12 +142,12 @@
 		recs = PAGE_CACHE_SIZE / rec_size;
 		/* Should have been verified before we got here... */
 		BUG_ON(!recs);
-		addr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+		kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
 		for (i = 0; i < recs; i++)
-			post_read_mst_fixup((NTFS_RECORD*)(addr +
+			post_read_mst_fixup((NTFS_RECORD*)(kaddr +
 					i * rec_size), rec_size);
+		kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
 		flush_dcache_page(page);
-		kunmap_atomic(addr, KM_BIO_SRC_IRQ);
 		if (likely(page_uptodate && !PageError(page)))
 			SetPageUptodate(page);
 	}
@@ -168,8 +178,11 @@
  */
 static int ntfs_read_block(struct page *page)
 {
+	loff_t i_size;
 	VCN vcn;
 	LCN lcn;
+	s64 init_size;
+	struct inode *vi;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
 	runlist_element *rl;
@@ -180,7 +193,8 @@
 	int i, nr;
 	unsigned char blocksize_bits;
 
-	ni = NTFS_I(page->mapping->host);
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
 	vol = ni->vol;
 
 	/* $MFT/$DATA must have its complete runlist in memory at all times. */
@@ -199,11 +213,28 @@
 	bh = head = page_buffers(page);
 	BUG_ON(!bh);
 
+	/*
+	 * We may be racing with truncate.  To avoid some of the problems we
+	 * now take a snapshot of the various sizes and use those for the whole
+	 * of the function.  In case of an extending truncate it just means we
+	 * may leave some buffers unmapped which are now allocated.  This is
+	 * not a problem since these buffers will just get mapped when a write
+	 * occurs.  In case of a shrinking truncate, we will detect this later
+	 * on due to the runlist being incomplete and if the page is being
+	 * fully truncated, truncate will throw it away as soon as we unlock
+	 * it so no need to worry what we do with it.
+	 */
 	iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits);
 	read_lock_irqsave(&ni->size_lock, flags);
 	lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits;
-	zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
+	init_size = ni->initialized_size;
+	i_size = i_size_read(vi);
 	read_unlock_irqrestore(&ni->size_lock, flags);
+	if (unlikely(init_size > i_size)) {
+		/* Race with shrinking truncate. */
+		init_size = i_size;
+	}
+	zblock = (init_size + blocksize - 1) >> blocksize_bits;
 
 	/* Loop through all the buffers in the page. */
 	rl = NULL;
@@ -366,6 +397,8 @@
  */
 static int ntfs_readpage(struct file *file, struct page *page)
 {
+	loff_t i_size;
+	struct inode *vi;
 	ntfs_inode *ni, *base_ni;
 	u8 *kaddr;
 	ntfs_attr_search_ctx *ctx;
@@ -384,14 +417,17 @@
 		unlock_page(page);
 		return 0;
 	}
-	ni = NTFS_I(page->mapping->host);
+	vi = page->mapping->host;
+	ni = NTFS_I(vi);
 	/*
 	 * Only $DATA attributes can be encrypted and only unnamed $DATA
 	 * attributes can be compressed.  Index root can have the flags set but
 	 * this means to create compressed/encrypted files, not that the
-	 * attribute is compressed/encrypted.
+	 * attribute is compressed/encrypted.  Note we need to check for
+	 * AT_INDEX_ALLOCATION since this is the type of both directory and
+	 * index inodes.
 	 */
-	if (ni->type != AT_INDEX_ROOT) {
+	if (ni->type != AT_INDEX_ALLOCATION) {
 		/* If attribute is encrypted, deny access, just like NT4. */
 		if (NInoEncrypted(ni)) {
 			BUG_ON(ni->type != AT_DATA);
@@ -456,7 +492,12 @@
 	read_lock_irqsave(&ni->size_lock, flags);
 	if (unlikely(attr_len > ni->initialized_size))
 		attr_len = ni->initialized_size;
+	i_size = i_size_read(vi);
 	read_unlock_irqrestore(&ni->size_lock, flags);
+	if (unlikely(attr_len > i_size)) {
+		/* Race with shrinking truncate. */
+		attr_len = i_size;
+	}
 	kaddr = kmap_atomic(page, KM_USER0);
 	/* Copy the data to the page. */
 	memcpy(kaddr, (u8*)ctx->attr +
@@ -1341,9 +1382,11 @@
 	 * Only $DATA attributes can be encrypted and only unnamed $DATA
 	 * attributes can be compressed.  Index root can have the flags set but
 	 * this means to create compressed/encrypted files, not that the
-	 * attribute is compressed/encrypted.
+	 * attribute is compressed/encrypted.  Note we need to check for
+	 * AT_INDEX_ALLOCATION since this is the type of both directory and
+	 * index inodes.
 	 */
-	if (ni->type != AT_INDEX_ROOT) {
+	if (ni->type != AT_INDEX_ALLOCATION) {
 		/* If file is encrypted, deny access, just like NT4. */
 		if (NInoEncrypted(ni)) {
 			unlock_page(page);
@@ -1379,8 +1422,8 @@
 			unsigned int ofs = i_size & ~PAGE_CACHE_MASK;
 			kaddr = kmap_atomic(page, KM_USER0);
 			memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs);
-			flush_dcache_page(page);
 			kunmap_atomic(kaddr, KM_USER0);
+			flush_dcache_page(page);
 		}
 		/* Handle mst protected attributes. */
 		if (NInoMstProtected(ni))
@@ -1443,34 +1486,33 @@
 	BUG_ON(PageWriteback(page));
 	set_page_writeback(page);
 	unlock_page(page);
-	/*
-	 * Here, we do not need to zero the out of bounds area everytime
-	 * because the below memcpy() already takes care of the
-	 * mmap-at-end-of-file requirements.  If the file is converted to a
-	 * non-resident one, then the code path use is switched to the
-	 * non-resident one where the zeroing happens on each ntfs_writepage()
-	 * invocation.
-	 */
 	attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
 	i_size = i_size_read(vi);
 	if (unlikely(attr_len > i_size)) {
+		/* Race with shrinking truncate or a failed truncate. */
 		attr_len = i_size;
-		ctx->attr->data.resident.value_length = cpu_to_le32(attr_len);
+		/*
+		 * If the truncate failed, fix it up now.  If a concurrent
+		 * truncate, we do its job, so it does not have to do anything.
+		 */
+		err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
+				attr_len);
+		/* Shrinking cannot fail. */
+		BUG_ON(err);
 	}
 	kaddr = kmap_atomic(page, KM_USER0);
 	/* Copy the data from the page to the mft record. */
 	memcpy((u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset),
 			kaddr, attr_len);
-	flush_dcache_mft_record_page(ctx->ntfs_ino);
 	/* Zero out of bounds area in the page cache page. */
 	memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
-	flush_dcache_page(page);
 	kunmap_atomic(kaddr, KM_USER0);
-
+	flush_dcache_mft_record_page(ctx->ntfs_ino);
+	flush_dcache_page(page);
+	/* We are done with the page. */
 	end_page_writeback(page);
-
-	/* Mark the mft record dirty, so it gets written back. */
+	/* Finally, mark the mft record dirty, so it gets written back. */
 	mark_mft_record_dirty(ctx->ntfs_ino);
 	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index dc4bbe3..7ec0451 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1166,6 +1166,8 @@
  *
  * Return 0 on success and -errno on error.  In the error case, the inode will
  * have had make_bad_inode() executed on it.
+ *
+ * Note this cannot be called for AT_INDEX_ALLOCATION.
  */
 static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 {
@@ -1242,8 +1244,8 @@
 			}
 		}
 		/*
-		 * The encryption flag set in an index root just means to
-		 * compress all files.
+		 * The compressed/sparse flag set in an index root just means
+		 * to compress all files.
 		 */
 		if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) {
 			ntfs_error(vi->i_sb, "Found mst protected attribute "
@@ -1319,8 +1321,7 @@
 					"the mapping pairs array.");
 			goto unm_err_out;
 		}
-		if ((NInoCompressed(ni) || NInoSparse(ni)) &&
-				ni->type != AT_INDEX_ROOT) {
+		if (NInoCompressed(ni) || NInoSparse(ni)) {
 			if (a->data.non_resident.compression_unit != 4) {
 				ntfs_error(vi->i_sb, "Found nonstandard "
 						"compression unit (%u instead "
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
index 3288bcc..006946e 100644
--- a/fs/ntfs/malloc.h
+++ b/fs/ntfs/malloc.h
@@ -1,7 +1,7 @@
 /*
  * malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2005 Anton Altaparmakov
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index f5b2ac9..e2665d0 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -2,7 +2,7 @@
  * runlist.c - NTFS runlist handling code.  Part of the Linux-NTFS project.
  *
  * Copyright (c) 2001-2005 Anton Altaparmakov
- * Copyright (c) 2002 Richard Russon
+ * Copyright (c) 2002-2005 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -214,8 +214,8 @@
 static inline runlist_element *ntfs_rl_append(runlist_element *dst,
 		int dsize, runlist_element *src, int ssize, int loc)
 {
-	BOOL right;
-	int magic;
+	BOOL right;	/* Right end of @src needs merging. */
+	int marker;	/* End of the inserted runs. */
 
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -236,18 +236,19 @@
 	if (right)
 		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
 
-	magic = loc + ssize;
+	/* First run after the @src runs that have been inserted. */
+	marker = loc + ssize + 1;
 
 	/* Move the tail of @dst out of the way, then copy in @src. */
-	ntfs_rl_mm(dst, magic + 1, loc + 1 + right, dsize - loc - 1 - right);
+	ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right));
 	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
 
 	/* Adjust the size of the preceding hole. */
 	dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
 
 	/* We may have changed the length of the file, so fix the end marker */
-	if (dst[magic + 1].lcn == LCN_ENOENT)
-		dst[magic + 1].vcn = dst[magic].vcn + dst[magic].length;
+	if (dst[marker].lcn == LCN_ENOENT)
+		dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
 
 	return dst;
 }
@@ -279,18 +280,17 @@
 static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
 		int dsize, runlist_element *src, int ssize, int loc)
 {
-	BOOL left = FALSE;
-	BOOL disc = FALSE;	/* Discontinuity */
-	BOOL hole = FALSE;	/* Following a hole */
-	int magic;
+	BOOL left = FALSE;	/* Left end of @src needs merging. */
+	BOOL disc = FALSE;	/* Discontinuity between @dst and @src. */
+	int marker;		/* End of the inserted runs. */
 
 	BUG_ON(!dst);
 	BUG_ON(!src);
 
-	/* disc => Discontinuity between the end of @dst and the start of @src.
-	 *	   This means we might need to insert a hole.
-	 * hole => @dst ends with a hole or an unmapped region which we can
-	 *	   extend to match the discontinuity. */
+	/*
+	 * disc => Discontinuity between the end of @dst and the start of @src.
+	 *	   This means we might need to insert a "not mapped" run.
+	 */
 	if (loc == 0)
 		disc = (src[0].vcn > 0);
 	else {
@@ -303,58 +303,49 @@
 			merged_length += src->length;
 
 		disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
-		if (disc)
-			hole = (dst[loc - 1].lcn == LCN_HOLE);
 	}
-
-	/* Space required: @dst size + @src size, less one if we merged, plus
-	 * one if there was a discontinuity, less one for a trailing hole. */
-	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc - hole);
+	/*
+	 * Space required: @dst size + @src size, less one if we merged, plus
+	 * one if there was a discontinuity.
+	 */
+	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
 	if (IS_ERR(dst))
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
 	 * original runlist.
 	 */
-
 	if (left)
 		__ntfs_rl_merge(dst + loc - 1, src);
-
-	magic = loc + ssize - left + disc - hole;
+	/*
+	 * First run after the @src runs that have been inserted.
+	 * Nominally,  @marker equals @loc + @ssize, i.e. location + number of
+	 * runs in @src.  However, if @left, then the first run in @src has
+	 * been merged with one in @dst.  And if @disc, then @dst and @src do
+	 * not meet and we need an extra run to fill the gap.
+	 */
+	marker = loc + ssize - left + disc;
 
 	/* Move the tail of @dst out of the way, then copy in @src. */
-	ntfs_rl_mm(dst, magic, loc, dsize - loc);
-	ntfs_rl_mc(dst, loc + disc - hole, src, left, ssize - left);
+	ntfs_rl_mm(dst, marker, loc, dsize - loc);
+	ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
 
-	/* Adjust the VCN of the last run ... */
-	if (dst[magic].lcn <= LCN_HOLE)
-		dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length;
+	/* Adjust the VCN of the first run after the insertion... */
+	dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
 	/* ... and the length. */
-	if (dst[magic].lcn == LCN_HOLE || dst[magic].lcn == LCN_RL_NOT_MAPPED)
-		dst[magic].length = dst[magic + 1].vcn - dst[magic].vcn;
+	if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
+		dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
 
-	/* Writing beyond the end of the file and there's a discontinuity. */
+	/* Writing beyond the end of the file and there is a discontinuity. */
 	if (disc) {
-		if (hole)
-			dst[loc - 1].length = dst[loc].vcn - dst[loc - 1].vcn;
-		else {
-			if (loc > 0) {
-				dst[loc].vcn = dst[loc - 1].vcn +
-						dst[loc - 1].length;
-				dst[loc].length = dst[loc + 1].vcn -
-						dst[loc].vcn;
-			} else {
-				dst[loc].vcn = 0;
-				dst[loc].length = dst[loc + 1].vcn;
-			}
-			dst[loc].lcn = LCN_RL_NOT_MAPPED;
+		if (loc > 0) {
+			dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
+			dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
+		} else {
+			dst[loc].vcn = 0;
+			dst[loc].length = dst[loc + 1].vcn;
 		}
-
-		magic += hole;
-
-		if (dst[magic].lcn == LCN_ENOENT)
-			dst[magic].vcn = dst[magic - 1].vcn +
-					dst[magic - 1].length;
+		dst[loc].lcn = LCN_RL_NOT_MAPPED;
 	}
 	return dst;
 }
@@ -385,9 +376,10 @@
 static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
 		int dsize, runlist_element *src, int ssize, int loc)
 {
-	BOOL left = FALSE;
-	BOOL right;
-	int magic;
+	BOOL left = FALSE;	/* Left end of @src needs merging. */
+	BOOL right;		/* Right end of @src needs merging. */
+	int tail;		/* Start of tail of @dst. */
+	int marker;		/* End of the inserted runs. */
 
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -396,9 +388,10 @@
 	right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1);
 	if (loc > 0)
 		left = ntfs_are_rl_mergeable(dst + loc - 1, src);
-
-	/* Allocate some space. We'll need less if the left, right, or both
-	 * ends were merged. */
+	/*
+	 * Allocate some space.  We will need less if the left, right, or both
+	 * ends were merged.
+	 */
 	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right);
 	if (IS_ERR(dst))
 		return dst;
@@ -410,17 +403,28 @@
 		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
 	if (left)
 		__ntfs_rl_merge(dst + loc - 1, src);
-
-	/* FIXME: What does this mean? (AIA) */
-	magic = loc + ssize - left;
+	/*
+	 * First run of @dst that needs to be moved out of the way to make
+	 * space for the runs to be copied from @src, i.e. the first run of the
+	 * tail of @dst.
+	 */
+	tail = loc + right + 1;
+	/*
+	 * First run after the @src runs that have been inserted, i.e. where
+	 * the tail of @dst needs to be moved to.
+	 * Nominally, marker equals @loc + @ssize, i.e. location + number of
+	 * runs in @src).  However, if @left, then the first run in @src has
+	 * been merged with one in @dst.
+	 */
+	marker = loc + ssize - left;
 
 	/* Move the tail of @dst out of the way, then copy in @src. */
-	ntfs_rl_mm(dst, magic, loc + right + 1, dsize - loc - right - 1);
+	ntfs_rl_mm(dst, marker, tail, dsize - tail);
 	ntfs_rl_mc(dst, loc, src, left, ssize - left);
 
-	/* We may have changed the length of the file, so fix the end marker */
-	if (dst[magic].lcn == LCN_ENOENT)
-		dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length;
+	/* We may have changed the length of the file, so fix the end marker. */
+	if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT)
+		dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
 	return dst;
 }
 
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/proc/array.c b/fs/proc/array.c
index d88d518..d84eeca 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -74,6 +74,7 @@
 #include <linux/file.h>
 #include <linux/times.h>
 #include <linux/cpuset.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -180,12 +181,14 @@
 		p->gid, p->egid, p->sgid, p->fsgid);
 	read_unlock(&tasklist_lock);
 	task_lock(p);
+	rcu_read_lock();
 	if (p->files)
 		fdt = files_fdtable(p->files);
 	buffer += sprintf(buffer,
 		"FDSize:\t%d\n"
 		"Groups:\t",
 		fdt ? fdt->max_fds : 0);
+	rcu_read_unlock();
 
 	group_info = p->group_info;
 	get_group_info(group_info);
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-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
index 681b6a6..79c9081 100644
--- a/include/asm-arm/arch-aaec2000/memory.h
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -64,10 +64,6 @@
 #define NODE_MAX_MEM_SHIFT	26
 #define NODE_MAX_MEM_SIZE	(1 << NODE_MAX_MEM_SHIFT)
 
-#else
-
-#define PFN_TO_NID(addr)	(0)
-
 #endif /* CONFIG_DISCONTIGMEM */
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
index dc4735c..45351f5 100644
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ b/include/asm-arm/arch-iop3xx/memory.h
@@ -36,6 +36,4 @@
 
 #endif
 
-#define PFN_TO_NID(addr)	(0)
-
 #endif
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 75623f8..32aece0 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -370,8 +370,6 @@
 #define GLOBAL_REG_BASE			(IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00)
 #define GLOBAL_REG(x)			(volatile unsigned long*)(GLOBAL_REG_BASE | (x))
 
-#define IXP2000_PROD_ID			GLOBAL_REG(0x00)
-
 #define IXP2000_MAJ_PROD_TYPE_MASK	0x001F0000
 #define IXP2000_MAJ_PROD_TYPE_IXP2000	0x00000000
 #define IXP2000_MIN_PROD_TYPE_MASK 	0x0000FF00
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index c0caf3e..abdcf51 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -31,20 +31,24 @@
 
 #include <asm/system.h>		/* Pickup local_irq_ functions */
 
-static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val)
+static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
 {
-	volatile unsigned long dummy;
+	unsigned long dummy;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	*reg = val;
+	*((volatile unsigned long *)reg) = val;
 	barrier();
-	dummy = *reg;
+	dummy = *((volatile unsigned long *)reg);
 	local_irq_restore(flags);
 }
 #else
-#define	ixp2000_reg_write(reg, val) (*reg = val)
+static inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
+{
+	*((volatile unsigned long *)reg) = val;
+}
 #endif	/* IXDP2400 || IXDP2401 */
+#define ixp2000_reg_read(reg)	(*((volatile unsigned long *)reg))
 
 /*
  * Boards may multiplex different devices on the 2nd channel of 
@@ -84,7 +88,7 @@
  */
 static inline unsigned ixp2000_has_broken_slowport(void)
 {
-	unsigned long id = *IXP2000_PROD_ID;
+	unsigned long id = *IXP2000_PRODUCT_ID;
 	unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK |
 				      IXP2000_MIN_PROD_TYPE_MASK);
 	return (((id_prod ==
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index 7e2fea3..c650e6f 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -85,10 +85,6 @@
        (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
 # endif
 
-#else
-
-# define PFN_TO_NID(addr)	(0)
-
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index 84f81e3..ef32d61 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -86,6 +86,5 @@
 
 #endif	/* CONFIG_ARCH_OMAP1510 */
 
-#define PHYS_TO_NID(addr) (0)
 #endif
 
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/memory.h b/include/asm-arm/arch-pxa/memory.h
index 217a80b..58bad97 100644
--- a/include/asm-arm/arch-pxa/memory.h
+++ b/include/asm-arm/arch-pxa/memory.h
@@ -67,10 +67,6 @@
 #define LOCAL_MAP_NR(addr) \
 	(((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT)
 
-#else
-
-#define PFN_TO_NID(addr)	(0)
-
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h
index 58bda9d..6b5ac51 100644
--- a/include/asm-arm/arch-pxa/poodle.h
+++ b/include/asm-arm/arch-pxa/poodle.h
@@ -37,24 +37,25 @@
 #define POODLE_GPIO_nSD_DETECT		(9)
 #define POODLE_GPIO_MAIN_BAT_LOW	(13)
 #define POODLE_GPIO_BAT_COVER		(13)
+#define POODLE_GPIO_USB_PULLUP		(20)
 #define POODLE_GPIO_ADC_TEMP_ON		(21)
 #define POODLE_GPIO_BYPASS_ON		(36)
 #define POODLE_GPIO_CHRG_ON		(38)
 #define POODLE_GPIO_CHRG_FULL		(16)
 
 /* PXA GPIOs */
-#define POODLE_IRQ_GPIO_ON_KEY		IRQ_GPIO0
-#define POODLE_IRQ_GPIO_AC_IN		IRQ_GPIO1
-#define POODLE_IRQ_GPIO_HP_IN		IRQ_GPIO4
-#define POODLE_IRQ_GPIO_CO		IRQ_GPIO16
-#define POODLE_IRQ_GPIO_TP_INT		IRQ_GPIO5
-#define POODLE_IRQ_GPIO_WAKEUP		IRQ_GPIO11
-#define POODLE_IRQ_GPIO_GA_INT		IRQ_GPIO10
-#define POODLE_IRQ_GPIO_CF_IRQ		IRQ_GPIO17
-#define POODLE_IRQ_GPIO_CF_CD		IRQ_GPIO14
-#define POODLE_IRQ_GPIO_nSD_INT		IRQ_GPIO8
-#define POODLE_IRQ_GPIO_nSD_DETECT	IRQ_GPIO9
-#define POODLE_IRQ_GPIO_MAIN_BAT_LOW	IRQ_GPIO13
+#define POODLE_IRQ_GPIO_ON_KEY		IRQ_GPIO(0)
+#define POODLE_IRQ_GPIO_AC_IN		IRQ_GPIO(1)
+#define POODLE_IRQ_GPIO_HP_IN		IRQ_GPIO(4)
+#define POODLE_IRQ_GPIO_CO		IRQ_GPIO(16)
+#define POODLE_IRQ_GPIO_TP_INT		IRQ_GPIO(5)
+#define POODLE_IRQ_GPIO_WAKEUP		IRQ_GPIO(11)
+#define POODLE_IRQ_GPIO_GA_INT		IRQ_GPIO(10)
+#define POODLE_IRQ_GPIO_CF_IRQ		IRQ_GPIO(17)
+#define POODLE_IRQ_GPIO_CF_CD		IRQ_GPIO(14)
+#define POODLE_IRQ_GPIO_nSD_INT		IRQ_GPIO(8)
+#define POODLE_IRQ_GPIO_nSD_DETECT	IRQ_GPIO(9)
+#define POODLE_IRQ_GPIO_MAIN_BAT_LOW	IRQ_GPIO(13)
 
 /* SCOOP GPIOs */
 #define POODLE_SCOOP_CHARGE_ON	SCOOP_GPCR_PA11
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/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 32d3d5b..8743ff5 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -99,10 +99,6 @@
 #define LOCAL_MAP_NR(addr) \
 	(((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT)
 
-#else
-
-#define PFN_TO_NID(addr)	(0)
-
 #endif
 
 #endif
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h
index 2cac5ec..9feff4ce 100644
--- a/include/asm-arm/futex.h
+++ b/include/asm-arm/futex.h
@@ -14,7 +14,7 @@
 	int cmp = (encoded_op >> 24) & 15;
 	int oparg = (encoded_op << 8) >> 20;
 	int cmparg = (encoded_op << 20) >> 20;
-	int oldval = 0, ret, tem;
+	int oldval = 0, ret;
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
diff --git a/include/asm-arm/hardware/arm_twd.h b/include/asm-arm/hardware/arm_twd.h
new file mode 100644
index 0000000..131d5b4
--- /dev/null
+++ b/include/asm-arm/hardware/arm_twd.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_HARDWARE_TWD_H
+#define __ASM_HARDWARE_TWD_H
+
+#define TWD_TIMER_LOAD 		0x00
+#define TWD_TIMER_COUNTER		0x04
+#define TWD_TIMER_CONTROL		0x08
+#define TWD_TIMER_INTSTAT		0x0C
+
+#define TWD_WDOG_LOAD			0x20
+#define TWD_WDOG_COUNTER		0x24
+#define TWD_WDOG_CONTROL		0x28
+#define TWD_WDOG_INTSTAT		0x2C
+#define TWD_WDOG_RESETSTAT		0x30
+#define TWD_WDOG_DISABLE		0x34
+
+#endif
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index e47bea7..a8a933a 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -160,12 +160,25 @@
 #define page_to_pfn(page)					\
 	(( (page) - page_zone(page)->zone_mem_map)		\
 	  + page_zone(page)->zone_start_pfn)
+
 #define pfn_to_page(pfn)					\
 	(PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
-#define pfn_valid(pfn)		(PFN_TO_NID(pfn) < MAX_NUMNODES)
+
+#define pfn_valid(pfn)						\
+	({							\
+		unsigned int nid = PFN_TO_NID(pfn);		\
+		int valid = nid < MAX_NUMNODES;			\
+		if (valid) {					\
+			pg_data_t *node = NODE_DATA(nid);	\
+			valid = (pfn - node->node_start_pfn) <	\
+				node->node_spanned_pages;	\
+		}						\
+		valid;						\
+	})
 
 #define virt_to_page(kaddr)					\
 	(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
 #define virt_addr_valid(kaddr)	(KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
 
 /*
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-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/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-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-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index fc54492..a79d1a7 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -57,7 +57,9 @@
 #include <linux/config.h>
 
 #include <asm/fpu.h>
+#ifndef ASM_OFFSETS_C
 #include <asm/asm-offsets.h>
+#endif
 
 /*
  * Base-2 logarithm of number of pages to allocate per task structure
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index cf4a950..171b220 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -5,7 +5,9 @@
 #ifndef _ASM_IA64_THREAD_INFO_H
 #define _ASM_IA64_THREAD_INFO_H
 
+#ifndef ASM_OFFSETS_C
 #include <asm/asm-offsets.h>
+#endif
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 
@@ -51,9 +53,14 @@
 	},					\
 }
 
+#ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()	((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
 #define alloc_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#else
+#define current_thread_info()	((struct thread_info *) 0)
+#define alloc_thread_info(tsk)	((struct thread_info *) 0)
+#endif
 #define free_thread_info(ti)	/* nothing */
 
 #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
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/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-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-ppc/irq.h b/include/asm-ppc/irq.h
index 5575247..bd96748 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -138,6 +138,16 @@
 #define	SIU_IRQ7	(14)
 #define	SIU_LEVEL7	(15)
 
+#define MPC8xx_INT_FEC1		SIU_LEVEL1
+#define MPC8xx_INT_FEC2		SIU_LEVEL3
+
+#define MPC8xx_INT_SCC1		(CPM_IRQ_OFFSET + CPMVEC_SCC1)
+#define MPC8xx_INT_SCC2		(CPM_IRQ_OFFSET + CPMVEC_SCC2)
+#define MPC8xx_INT_SCC3		(CPM_IRQ_OFFSET + CPMVEC_SCC3)
+#define MPC8xx_INT_SCC4		(CPM_IRQ_OFFSET + CPMVEC_SCC4)
+#define MPC8xx_INT_SMC1		(CPM_IRQ_OFFSET + CPMVEC_SMC1)
+#define MPC8xx_INT_SMC2		(CPM_IRQ_OFFSET + CPMVEC_SMC2)
+
 /* The internal interrupts we can configure as we see fit.
  * My personal preference is CPM at level 2, which puts it above the
  * MBX PCI/ISA/IDE interrupts.
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index dc8e598..208a2e1 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -97,6 +97,22 @@
 
 struct pt_regs;
 
+enum ppc_sys_devices {
+	MPC8xx_CPM_FEC1,
+	MPC8xx_CPM_FEC2,
+	MPC8xx_CPM_I2C,
+	MPC8xx_CPM_SCC1,
+	MPC8xx_CPM_SCC2,
+	MPC8xx_CPM_SCC3,
+	MPC8xx_CPM_SCC4,
+	MPC8xx_CPM_SPI,
+	MPC8xx_CPM_MCC1,
+	MPC8xx_CPM_MCC2,
+	MPC8xx_CPM_SMC1,
+	MPC8xx_CPM_SMC2,
+	MPC8xx_CPM_USB,
+};
+
 #endif /* !__ASSEMBLY__ */
 #endif /* CONFIG_8xx */
 #endif /* __CONFIG_8xx_DEFS */
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/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 048f7c8..549f448 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -27,6 +27,8 @@
 #include <asm/mpc83xx.h>
 #elif defined(CONFIG_85xx)
 #include <asm/mpc85xx.h>
+#elif defined(CONFIG_8xx)
+#include <asm/mpc8xx.h>
 #elif defined(CONFIG_PPC_MPC52xx)
 #include <asm/mpc52xx.h>
 #elif defined(CONFIG_MPC10X_BRIDGE)
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-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
index 9850f53..9afee4f 100644
--- a/include/asm-ppc/tlbflush.h
+++ b/include/asm-ppc/tlbflush.h
@@ -72,7 +72,7 @@
 static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
 					 unsigned long vmaddr)
 	{ _tlbie(vmaddr); }
-static inline void flush_tlb_range(struct mm_struct *mm,
+static inline void flush_tlb_range(struct vm_area_struct *vma,
 				unsigned long start, unsigned long end)
 	{ __tlbia(); }
 static inline void flush_tlb_kernel_range(unsigned long start,
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-um/processor-generic.h b/include/asm-um/processor-generic.h
index b2fc94f..2d24236 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -21,6 +21,7 @@
 	 * copy_thread) to mark that we are begin called from userspace (fork /
 	 * vfork / clone), and reset to 0 after. It is left to 0 when called
 	 * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */
+	struct task_struct *saved_task;
 	int forking;
 	int nsyscalls;
 	struct pt_regs regs;
diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h
index ea8381d..c436263 100644
--- a/include/asm-um/system-i386.h
+++ b/include/asm-um/system-i386.h
@@ -3,6 +3,4 @@
 
 #include "asm/system-generic.h"
     
-#define __HAVE_ARCH_CMPXCHG 1
-
 #endif
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index 594e610..68ac3c6 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -8,6 +8,8 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/string.h>
+#include <linux/smp.h>
+
 #include <asm/segment.h>
 #include <asm/mmu.h>
 
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 1dc110b..2cb4835 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -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-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/dccp.h b/include/linux/dccp.h
index 8bf4bac..71fab43 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -4,16 +4,6 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-/* Structure describing an Internet (DCCP) socket address. */
-struct sockaddr_dccp {
-	__u16	sdccp_family;	/* Address family   */
-	__u16	sdccp_port;	/* Port number	    */
-	__u32	sdccp_addr;	/* Internet address */
-	__u32	sdccp_service;	/* Service	    */
-	/* Pad to size of `struct sockaddr': 16 bytes . */
-	__u32	sdccp_pad;
-};
-
 /**
  * struct dccp_hdr - generic part of DCCP packet header
  *
@@ -188,6 +178,11 @@
 
 /* DCCP socket options */
 #define DCCP_SOCKOPT_PACKET_SIZE	1
+#define DCCP_SOCKOPT_SERVICE		2
+#define DCCP_SOCKOPT_CCID_RX_INFO	128
+#define DCCP_SOCKOPT_CCID_TX_INFO	192
+
+#define DCCP_SERVICE_LIST_MAX_LEN      32
 
 #ifdef __KERNEL__
 
@@ -337,7 +332,8 @@
   */
 struct dccp_options {
 	__u64	dccpo_sequence_window;
-	__u8	dccpo_ccid;
+	__u8	dccpo_rx_ccid;
+	__u8	dccpo_tx_ccid;
 	__u8	dccpo_send_ack_vector;
 	__u8	dccpo_send_ndp_count;
 };
@@ -360,14 +356,8 @@
 
 extern struct inet_timewait_death_row dccp_death_row;
 
-/* Read about the ECN nonce to see why it is 253 */
-#define DCCP_MAX_ACK_VECTOR_LEN 253
-
 struct dccp_options_received {
-	u32	dccpor_ndp:24,
-		dccpor_ack_vector_len:8;
-	u32	dccpor_ack_vector_idx:10;
-	/* 22 bits hole, try to pack */
+	u32	dccpor_ndp; /* only 24 bits */
 	u32	dccpor_timestamp;
 	u32	dccpor_timestamp_echo;
 	u32	dccpor_elapsed_time;
@@ -382,6 +372,27 @@
 	DCCP_ROLE_SERVER,
 };
 
+struct dccp_service_list {
+	__u32	dccpsl_nr;
+	__u32	dccpsl_list[0];
+};
+
+#define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1)
+
+static inline int dccp_list_has_service(const struct dccp_service_list *sl,
+					const u32 service)
+{
+	if (likely(sl != NULL)) {
+		u32 i = sl->dccpsl_nr;
+		while (i--)
+			if (sl->dccpsl_list[i] == service)
+				return 1; 
+	}
+	return 0;
+}
+
+struct dccp_ackvec;
+
 /**
  * struct dccp_sock - DCCP socket state
  *
@@ -402,7 +413,7 @@
  * @dccps_packet_size - Set thru setsockopt
  * @dccps_role - Role of this sock, one of %dccp_role
  * @dccps_ndp_count - number of Non Data Packets since last data packet
- * @dccps_hc_rx_ackpkts - receiver half connection acked packets
+ * @dccps_hc_rx_ackvec - rx half connection ack vector
  */
 struct dccp_sock {
 	/* inet_connection_sock has to be the first member of dccp_sock */
@@ -417,7 +428,8 @@
 	__u64				dccps_gss;
 	__u64				dccps_gsr;
 	__u64				dccps_gar;
-	unsigned long			dccps_service;
+	__u32				dccps_service;
+	struct dccp_service_list	*dccps_service_list;
 	struct timeval			dccps_timestamp_time;
 	__u32				dccps_timestamp_echo;
 	__u32				dccps_packet_size;
@@ -426,7 +438,7 @@
 	__u32				dccps_pmtu_cookie;
 	__u32				dccps_mss_cache;
 	struct dccp_options		dccps_options;
-	struct dccp_ackpkts		*dccps_hc_rx_ackpkts;
+	struct dccp_ackvec		*dccps_hc_rx_ackvec;
 	void				*dccps_hc_rx_ccid_private;
 	void				*dccps_hc_tx_ccid_private;
 	struct ccid			*dccps_hc_rx_ccid;
@@ -443,6 +455,11 @@
 	return (struct dccp_sock *)sk;
 }
 
+static inline int dccp_service_not_initialized(const struct sock *sk)
+{
+	return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE;
+}
+
 static inline const char *dccp_role(const struct sock *sk)
 {
 	switch (dccp_sk(sk)->dccps_role) {
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/i2c.h b/include/linux/i2c.h
index be35332..3d49a30 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -230,11 +230,6 @@
 	struct device dev;		/* the adapter device */
 	struct class_device class_dev;	/* the class device */
 
-#ifdef CONFIG_PROC_FS 
-	/* No need to set this when you initialize the adapter          */
-	int inode;
-#endif /* def CONFIG_PROC_FS */
-
 	int nr;
 	struct list_head clients;
 	struct list_head list;
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 17d0c0d..eef0876 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -42,8 +42,8 @@
 struct vlan_ethhdr {
    unsigned char	h_dest[ETH_ALEN];	   /* destination eth addr	*/
    unsigned char	h_source[ETH_ALEN];	   /* source ether addr	*/
-   unsigned short       h_vlan_proto;              /* Should always be 0x8100 */
-   unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
+   __be16               h_vlan_proto;              /* Should always be 0x8100 */
+   __be16               h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
    unsigned short	h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
@@ -55,8 +55,8 @@
 }
 
 struct vlan_hdr {
-   unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
-   unsigned short       h_vlan_encapsulated_proto; /* packet type ID field (or len) */
+   __be16               h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
+   __be16               h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
 #define VLAN_VID_MASK	0xfff
diff --git a/include/linux/joystick.h b/include/linux/joystick.h
index 06b9af7..5fd20dd 100644
--- a/include/linux/joystick.h
+++ b/include/linux/joystick.h
@@ -111,29 +111,30 @@
 #define JS_SET_ALL		8
 
 struct JS_DATA_TYPE {
-	__s32 buttons;
-	__s32 x;
-	__s32 y;
+	int32_t buttons;
+	int32_t x;
+	int32_t y;
 };
 
 struct JS_DATA_SAVE_TYPE_32 {
-	__s32 JS_TIMEOUT;
-	__s32 BUSY;
-	__s32 JS_EXPIRETIME;
-	__s32 JS_TIMELIMIT;
+	int32_t JS_TIMEOUT;
+	int32_t BUSY;
+	int32_t JS_EXPIRETIME;
+	int32_t JS_TIMELIMIT;
 	struct JS_DATA_TYPE JS_SAVE;
 	struct JS_DATA_TYPE JS_CORR;
 };
 
 struct JS_DATA_SAVE_TYPE_64 {
-	__s32 JS_TIMEOUT;
-	__s32 BUSY;
-	__s64 JS_EXPIRETIME;
-	__s64 JS_TIMELIMIT;
+	int32_t JS_TIMEOUT;
+	int32_t BUSY;
+	int64_t JS_EXPIRETIME;
+	int64_t JS_TIMELIMIT;
 	struct JS_DATA_TYPE JS_SAVE;
 	struct JS_DATA_TYPE JS_CORR;
 };
 
+#ifdef __KERNEL__
 #if BITS_PER_LONG == 64
 #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64
 #elif BITS_PER_LONG == 32
@@ -141,5 +142,6 @@
 #else
 #error Unexpected BITS_PER_LONG
 #endif
+#endif
 
 #endif /* _LINUX_JOYSTICK_H */
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/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 7e033e9..bace72a 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -133,11 +133,13 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
 #include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
 
 /* per conntrack: protocol private data */
 union ip_conntrack_proto {
 	/* insert conntrack proto private data here */
+	struct ip_ct_gre gre;
 	struct ip_ct_sctp sctp;
 	struct ip_ct_tcp tcp;
 	struct ip_ct_icmp icmp;
@@ -148,6 +150,7 @@
 };
 
 /* Add protocol helper include file here */
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
@@ -155,12 +158,20 @@
 /* per conntrack: application helper private data */
 union ip_conntrack_help {
 	/* insert conntrack helper private data (master) here */
+	struct ip_ct_pptp_master ct_pptp_info;
 	struct ip_ct_ftp_master ct_ftp_info;
 	struct ip_ct_irc_master ct_irc_info;
 };
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 #include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
+
+/* per conntrack: nat application helper private data */
+union ip_conntrack_nat_help {
+	/* insert nat helper private data here */
+	struct ip_nat_pptp nat_pptp_info;
+};
 #endif
 
 #include <linux/types.h>
@@ -223,6 +234,7 @@
 #ifdef CONFIG_IP_NF_NAT_NEEDED
 	struct {
 		struct ip_nat_info info;
+		union ip_conntrack_nat_help help;
 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
 	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
 		int masq_index;
@@ -372,7 +384,7 @@
 __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_expect *
-ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple);
+ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
 
 extern struct ip_conntrack_tuple_hash *
 __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
new file mode 100644
index 0000000..389e385
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
@@ -0,0 +1,332 @@
+/* PPTP constants and structs */
+#ifndef _CONNTRACK_PPTP_H
+#define _CONNTRACK_PPTP_H
+
+/* state of the control session */
+enum pptp_ctrlsess_state {
+	PPTP_SESSION_NONE,			/* no session present */
+	PPTP_SESSION_ERROR,			/* some session error */
+	PPTP_SESSION_STOPREQ,			/* stop_sess request seen */
+	PPTP_SESSION_REQUESTED,			/* start_sess request seen */
+	PPTP_SESSION_CONFIRMED,			/* session established */
+};
+
+/* state of the call inside the control session */
+enum pptp_ctrlcall_state {
+	PPTP_CALL_NONE,
+	PPTP_CALL_ERROR,
+	PPTP_CALL_OUT_REQ,
+	PPTP_CALL_OUT_CONF,
+	PPTP_CALL_IN_REQ,
+	PPTP_CALL_IN_REP,
+	PPTP_CALL_IN_CONF,
+	PPTP_CALL_CLEAR_REQ,
+};
+
+
+/* conntrack private data */
+struct ip_ct_pptp_master {
+	enum pptp_ctrlsess_state sstate;	/* session state */
+
+	/* everything below is going to be per-expectation in newnat,
+	 * since there could be more than one call within one session */
+	enum pptp_ctrlcall_state cstate;	/* call state */
+	u_int16_t pac_call_id;			/* call id of PAC, host byte order */
+	u_int16_t pns_call_id;			/* call id of PNS, host byte order */
+
+	/* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
+	 * and therefore imposes a fixed limit on the number of maps */
+	struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
+};
+
+/* conntrack_expect private member */
+struct ip_ct_pptp_expect {
+	enum pptp_ctrlcall_state cstate; 	/* call state */
+	u_int16_t pac_call_id;			/* call id of PAC */
+	u_int16_t pns_call_id;			/* call id of PNS */
+};
+
+
+#ifdef __KERNEL__
+
+#define IP_CONNTR_PPTP		PPTP_CONTROL_PORT
+
+#define PPTP_CONTROL_PORT	1723
+
+#define PPTP_PACKET_CONTROL	1
+#define PPTP_PACKET_MGMT	2
+
+#define PPTP_MAGIC_COOKIE	0x1a2b3c4d
+
+struct pptp_pkt_hdr {
+	__u16	packetLength;
+	__u16	packetType;
+	__u32	magicCookie;
+};
+
+/* PptpControlMessageType values */
+#define PPTP_START_SESSION_REQUEST	1
+#define PPTP_START_SESSION_REPLY	2
+#define PPTP_STOP_SESSION_REQUEST	3
+#define PPTP_STOP_SESSION_REPLY		4
+#define PPTP_ECHO_REQUEST		5
+#define PPTP_ECHO_REPLY			6
+#define PPTP_OUT_CALL_REQUEST		7
+#define PPTP_OUT_CALL_REPLY		8
+#define PPTP_IN_CALL_REQUEST		9
+#define PPTP_IN_CALL_REPLY		10
+#define PPTP_IN_CALL_CONNECT		11
+#define PPTP_CALL_CLEAR_REQUEST		12
+#define PPTP_CALL_DISCONNECT_NOTIFY	13
+#define PPTP_WAN_ERROR_NOTIFY		14
+#define PPTP_SET_LINK_INFO		15
+
+#define PPTP_MSG_MAX			15
+
+/* PptpGeneralError values */
+#define PPTP_ERROR_CODE_NONE		0
+#define PPTP_NOT_CONNECTED		1
+#define PPTP_BAD_FORMAT			2
+#define PPTP_BAD_VALUE			3
+#define PPTP_NO_RESOURCE		4
+#define PPTP_BAD_CALLID			5
+#define PPTP_REMOVE_DEVICE_ERROR	6
+
+struct PptpControlHeader {
+	__u16	messageType;
+	__u16	reserved;
+};
+
+/* FramingCapability Bitmap Values */
+#define PPTP_FRAME_CAP_ASYNC		0x1
+#define PPTP_FRAME_CAP_SYNC		0x2
+
+/* BearerCapability Bitmap Values */
+#define PPTP_BEARER_CAP_ANALOG		0x1
+#define PPTP_BEARER_CAP_DIGITAL		0x2
+
+struct PptpStartSessionRequest {
+	__u16	protocolVersion;
+	__u8	reserved1;
+	__u8	reserved2;
+	__u32	framingCapability;
+	__u32	bearerCapability;
+	__u16	maxChannels;
+	__u16	firmwareRevision;
+	__u8	hostName[64];
+	__u8	vendorString[64];
+};
+
+/* PptpStartSessionResultCode Values */
+#define PPTP_START_OK			1
+#define PPTP_START_GENERAL_ERROR	2
+#define PPTP_START_ALREADY_CONNECTED	3
+#define PPTP_START_NOT_AUTHORIZED	4
+#define PPTP_START_UNKNOWN_PROTOCOL	5
+
+struct PptpStartSessionReply {
+	__u16	protocolVersion;
+	__u8	resultCode;
+	__u8	generalErrorCode;
+	__u32	framingCapability;
+	__u32	bearerCapability;
+	__u16	maxChannels;
+	__u16	firmwareRevision;
+	__u8	hostName[64];
+	__u8	vendorString[64];
+};
+
+/* PptpStopReasons */
+#define PPTP_STOP_NONE			1
+#define PPTP_STOP_PROTOCOL		2
+#define PPTP_STOP_LOCAL_SHUTDOWN	3
+
+struct PptpStopSessionRequest {
+	__u8	reason;
+};
+
+/* PptpStopSessionResultCode */
+#define PPTP_STOP_OK			1
+#define PPTP_STOP_GENERAL_ERROR		2
+
+struct PptpStopSessionReply {
+	__u8	resultCode;
+	__u8	generalErrorCode;
+};
+
+struct PptpEchoRequest {
+	__u32 identNumber;
+};
+
+/* PptpEchoReplyResultCode */
+#define PPTP_ECHO_OK			1
+#define PPTP_ECHO_GENERAL_ERROR		2
+
+struct PptpEchoReply {
+	__u32	identNumber;
+	__u8	resultCode;
+	__u8	generalErrorCode;
+	__u16	reserved;
+};
+
+/* PptpFramingType */
+#define PPTP_ASYNC_FRAMING		1
+#define PPTP_SYNC_FRAMING		2
+#define PPTP_DONT_CARE_FRAMING		3
+
+/* PptpCallBearerType */
+#define PPTP_ANALOG_TYPE		1
+#define PPTP_DIGITAL_TYPE		2
+#define PPTP_DONT_CARE_BEARER_TYPE	3
+
+struct PptpOutCallRequest {
+	__u16	callID;
+	__u16	callSerialNumber;
+	__u32	minBPS;
+	__u32	maxBPS;
+	__u32	bearerType;
+	__u32	framingType;
+	__u16	packetWindow;
+	__u16	packetProcDelay;
+	__u16	reserved1;
+	__u16	phoneNumberLength;
+	__u16	reserved2;
+	__u8	phoneNumber[64];
+	__u8	subAddress[64];
+};
+
+/* PptpCallResultCode */
+#define PPTP_OUTCALL_CONNECT		1
+#define PPTP_OUTCALL_GENERAL_ERROR	2
+#define PPTP_OUTCALL_NO_CARRIER		3
+#define PPTP_OUTCALL_BUSY		4
+#define PPTP_OUTCALL_NO_DIAL_TONE	5
+#define PPTP_OUTCALL_TIMEOUT		6
+#define PPTP_OUTCALL_DONT_ACCEPT	7
+
+struct PptpOutCallReply {
+	__u16	callID;
+	__u16	peersCallID;
+	__u8	resultCode;
+	__u8	generalErrorCode;
+	__u16	causeCode;
+	__u32	connectSpeed;
+	__u16	packetWindow;
+	__u16	packetProcDelay;
+	__u32	physChannelID;
+};
+
+struct PptpInCallRequest {
+	__u16	callID;
+	__u16	callSerialNumber;
+	__u32	callBearerType;
+	__u32	physChannelID;
+	__u16	dialedNumberLength;
+	__u16	dialingNumberLength;
+	__u8	dialedNumber[64];
+	__u8	dialingNumber[64];
+	__u8	subAddress[64];
+};
+
+/* PptpInCallResultCode */
+#define PPTP_INCALL_ACCEPT		1
+#define PPTP_INCALL_GENERAL_ERROR	2
+#define PPTP_INCALL_DONT_ACCEPT		3
+
+struct PptpInCallReply {
+	__u16	callID;
+	__u16	peersCallID;
+	__u8	resultCode;
+	__u8	generalErrorCode;
+	__u16	packetWindow;
+	__u16	packetProcDelay;
+	__u16	reserved;
+};
+
+struct PptpInCallConnected {
+	__u16	peersCallID;
+	__u16	reserved;
+	__u32	connectSpeed;
+	__u16	packetWindow;
+	__u16	packetProcDelay;
+	__u32	callFramingType;
+};
+
+struct PptpClearCallRequest {
+	__u16	callID;
+	__u16	reserved;
+};
+
+struct PptpCallDisconnectNotify {
+	__u16	callID;
+	__u8	resultCode;
+	__u8	generalErrorCode;
+	__u16	causeCode;
+	__u16	reserved;
+	__u8	callStatistics[128];
+};
+
+struct PptpWanErrorNotify {
+	__u16	peersCallID;
+	__u16	reserved;
+	__u32	crcErrors;
+	__u32	framingErrors;
+	__u32	hardwareOverRuns;
+	__u32	bufferOverRuns;
+	__u32	timeoutErrors;
+	__u32	alignmentErrors;
+};
+
+struct PptpSetLinkInfo {
+	__u16	peersCallID;
+	__u16	reserved;
+	__u32	sendAccm;
+	__u32	recvAccm;
+};
+
+
+struct pptp_priv_data {
+	__u16	call_id;
+	__u16	mcall_id;
+	__u16	pcall_id;
+};
+
+union pptp_ctrl_union {
+		struct PptpStartSessionRequest	sreq;
+		struct PptpStartSessionReply	srep;
+		struct PptpStopSessionRequest	streq;
+		struct PptpStopSessionReply	strep;
+                struct PptpOutCallRequest       ocreq;
+                struct PptpOutCallReply         ocack;
+                struct PptpInCallRequest        icreq;
+                struct PptpInCallReply          icack;
+                struct PptpInCallConnected      iccon;
+		struct PptpClearCallRequest	clrreq;
+                struct PptpCallDisconnectNotify disc;
+                struct PptpWanErrorNotify       wanerr;
+                struct PptpSetLinkInfo          setlink;
+};
+
+extern int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+extern int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig,
+			    struct ip_conntrack_expect *exp_reply);
+
+extern void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp);
+#endif /* __KERNEL__ */
+#endif /* _CONNTRACK_PPTP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
new file mode 100644
index 0000000..8d090ef
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
@@ -0,0 +1,114 @@
+#ifndef _CONNTRACK_PROTO_GRE_H
+#define _CONNTRACK_PROTO_GRE_H
+#include <asm/byteorder.h>
+
+/* GRE PROTOCOL HEADER */
+
+/* GRE Version field */
+#define GRE_VERSION_1701	0x0
+#define GRE_VERSION_PPTP	0x1
+
+/* GRE Protocol field */
+#define GRE_PROTOCOL_PPTP	0x880B
+
+/* GRE Flags */
+#define GRE_FLAG_C		0x80
+#define GRE_FLAG_R		0x40
+#define GRE_FLAG_K		0x20
+#define GRE_FLAG_S		0x10
+#define GRE_FLAG_A		0x80
+
+#define GRE_IS_C(f)	((f)&GRE_FLAG_C)
+#define GRE_IS_R(f)	((f)&GRE_FLAG_R)
+#define GRE_IS_K(f)	((f)&GRE_FLAG_K)
+#define GRE_IS_S(f)	((f)&GRE_FLAG_S)
+#define GRE_IS_A(f)	((f)&GRE_FLAG_A)
+
+/* GRE is a mess: Four different standards */
+struct gre_hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u16	rec:3,
+		srr:1,
+		seq:1,
+		key:1,
+		routing:1,
+		csum:1,
+		version:3,
+		reserved:4,
+		ack:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	__u16	csum:1,
+		routing:1,
+		key:1,
+		seq:1,
+		srr:1,
+		rec:3,
+		ack:1,
+		reserved:4,
+		version:3;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+	__u16	protocol;
+};
+
+/* modified GRE header for PPTP */
+struct gre_hdr_pptp {
+	__u8  flags;		/* bitfield */
+	__u8  version;		/* should be GRE_VERSION_PPTP */
+	__u16 protocol;		/* should be GRE_PROTOCOL_PPTP */
+	__u16 payload_len;	/* size of ppp payload, not inc. gre header */
+	__u16 call_id;		/* peer's call_id for this session */
+	__u32 seq;		/* sequence number.  Present if S==1 */
+	__u32 ack;		/* seq number of highest packet recieved by */
+				/*  sender in this session */
+};
+
+
+/* this is part of ip_conntrack */
+struct ip_ct_gre {
+	unsigned int stream_timeout;
+	unsigned int timeout;
+};
+
+#ifdef __KERNEL__
+struct ip_conntrack_expect;
+struct ip_conntrack;
+
+/* structure for original <-> reply keymap */
+struct ip_ct_gre_keymap {
+	struct list_head list;
+
+	struct ip_conntrack_tuple tuple;
+};
+
+/* add new tuple->key_reply pair to keymap */
+int ip_ct_gre_keymap_add(struct ip_conntrack *ct,
+			 struct ip_conntrack_tuple *t,
+			 int reply);
+
+/* delete keymap entries */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct);
+
+
+/* get pointer to gre key, if present */
+static inline u_int32_t *gre_key(struct gre_hdr *greh)
+{
+	if (!greh->key)
+		return NULL;
+	if (greh->csum || greh->routing)
+		return (u_int32_t *) (greh+sizeof(*greh)+4);
+	return (u_int32_t *) (greh+sizeof(*greh));
+}
+
+/* get pointer ot gre csum, if present */
+static inline u_int16_t *gre_csum(struct gre_hdr *greh)
+{
+	if (!greh->csum)
+		return NULL;
+	return (u_int16_t *) (greh+sizeof(*greh));
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _CONNTRACK_PROTO_GRE_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index c33f0b5..14dc0f7 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -28,6 +28,9 @@
 	struct {
 		u_int16_t port;
 	} sctp;
+	struct {
+		u_int16_t key;	/* key is 32bit, pptp only uses 16 */
+	} gre;
 };
 
 /* The manipulable part of the tuple. */
@@ -61,6 +64,10 @@
 			struct {
 				u_int16_t port;
 			} sctp;
+			struct {
+				u_int16_t key;	/* key is 32bit, 
+						 * pptp only uses 16 */
+			} gre;
 		} u;
 
 		/* The protocol. */
diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h
new file mode 100644
index 0000000..eaf66c2
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_nat_pptp.h
@@ -0,0 +1,11 @@
+/* PPTP constants and structs */
+#ifndef _NAT_PPTP_H
+#define _NAT_PPTP_H
+
+/* conntrack private data */
+struct ip_nat_pptp {
+	u_int16_t pns_call_id;		/* NAT'ed PNS call id */
+	u_int16_t pac_call_id;		/* NAT'ed PAC call id */
+};
+
+#endif /* _NAT_PPTP_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 58c72a5..59f70b3 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -455,6 +455,9 @@
 
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);
+/* find specified header and get offset to it */
+extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+			 u8 target);
 
 #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
 
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 7bbd259..bdebdc5 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -20,6 +20,7 @@
 #define NETLINK_IP6_FW		13
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
 #define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
+#define NETLINK_GENERIC		16
 
 #define MAX_LINKS 32		
 
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..c49d28e 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
@@ -487,6 +491,7 @@
 #define PCI_DEVICE_ID_AMI_MEGARAID2	0x9060
 
 #define PCI_VENDOR_ID_AMD		0x1022
+#define PCI_DEVICE_ID_AMD_K8_NB		0x1100
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
@@ -682,7 +687,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 +720,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 +1000,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 +1119,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 +1168,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 +1189,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 +1197,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 +1248,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 +1353,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_ID_RME_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 +1835,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 +2002,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 +2093,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
@@ -2212,6 +2253,9 @@
 
 #define PCI_VENDOR_ID_INFINICON		0x1820
 
+#define PCI_VENDOR_ID_SITECOM		0x182d
+#define PCI_DEVICE_ID_SITECOM_DC105V2	0x3069
+
 #define PCI_VENDOR_ID_TOPSPIN		0x1867
 
 #define PCI_VENDOR_ID_TDI               0x192E
@@ -2536,6 +2580,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 +2687,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 38c8654..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)		\
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/tfrc.h b/include/linux/tfrc.h
new file mode 100644
index 0000000..7dab783
--- /dev/null
+++ b/include/linux/tfrc.h
@@ -0,0 +1,35 @@
+#ifndef _LINUX_TFRC_H_
+#define _LINUX_TFRC_H_
+/*
+ *  include/linux/tfrc.h
+ *
+ *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *  Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
+ *
+ *  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/types.h>
+
+struct tfrc_rx_info {
+  	__u32 tfrcrx_x_recv;
+	__u32 tfrcrx_rtt;
+  	__u32 tfrcrx_p;
+};
+
+struct tfrc_tx_info {
+	__u32 tfrctx_x;
+	__u32 tfrctx_x_recv;
+	__u32 tfrctx_x_calc;
+	__u32 tfrctx_rtt;
+	__u32 tfrctx_p;
+	__u32 tfrctx_rto;
+	__u32 tfrctx_ipi;
+};
+
+#endif /* _LINUX_TFRC_H_ */
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/net/ip_vs.h b/include/net/ip_vs.h
index e426641..06b4235 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -84,6 +84,7 @@
 #define IP_VS_CONN_F_IN_SEQ	0x0400		/* must do input seq adjust */
 #define IP_VS_CONN_F_SEQ_MASK	0x0600		/* in/out sequence mask */
 #define IP_VS_CONN_F_NO_CPORT	0x0800		/* no client port set yet */
+#define IP_VS_CONN_F_TEMPLATE	0x1000		/* template, not connection */
 
 /* Move it to better place one day, for now keep it unique */
 #define NFC_IPVS_PROPERTY	0x10000
@@ -739,6 +740,8 @@
 
 extern struct ip_vs_conn *ip_vs_conn_in_get
 (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+extern struct ip_vs_conn *ip_vs_ct_in_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
 extern struct ip_vs_conn *ip_vs_conn_out_get
 (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
 
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/exit.c b/kernel/exit.c
index 6d2089a..ee6d8b8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -371,6 +371,12 @@
 	struct fdtable *fdt;
 
 	j = 0;
+
+	/*
+	 * It is safe to dereference the fd table without RCU or
+	 * ->file_lock because this is the last reference to the
+	 * files structure.
+	 */
 	fdt = files_fdtable(files);
 	for (;;) {
 		unsigned long set;
diff --git a/kernel/fork.c b/kernel/fork.c
index 8149f36..533ce27 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1062,7 +1062,8 @@
 	 * parent's CPU). This avoids alot of nasty races.
 	 */
 	p->cpus_allowed = current->cpus_allowed;
-	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed)))
+	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) ||
+			!cpu_online(task_cpu(p))))
 		set_task_cpu(p, smp_processor_id());
 
 	/*
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 81b3a96..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)
diff --git a/kernel/sys.c b/kernel/sys.c
index c80412b..f723522 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1728,8 +1728,7 @@
 			error = put_user(current->pdeath_signal, (int __user *)arg2);
 			break;
 		case PR_GET_DUMPABLE:
-			if (current->mm->dumpable)
-				error = 1;
+			error = current->mm->dumpable;
 			break;
 		case PR_SET_DUMPABLE:
 			if (arg2 < 0 || arg2 > 2) {
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/dec_and_lock.c b/lib/dec_and_lock.c
index 2377af0..305a966 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -1,7 +1,41 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
+#include <asm/system.h>
 
+#ifdef __HAVE_ARCH_CMPXCHG
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ */
+int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+	int counter;
+	int newcount;
+
+	for (;;) {
+		counter = atomic_read(atomic);
+		newcount = counter - 1;
+		if (!newcount)
+			break;		/* do it the slow way */
+
+		newcount = cmpxchg(&atomic->counter, counter, newcount);
+		if (newcount == counter)
+			return 0;
+	}
+
+	spin_lock(lock);
+	if (atomic_dec_and_test(atomic))
+		return 1;
+	spin_unlock(lock);
+	return 0;
+}
+#else
 /*
  * This is an architecture-neutral, but slow,
  * implementation of the notion of "decrement
@@ -33,5 +67,6 @@
 	spin_unlock(lock);
 	return 0;
 }
+#endif
 
 EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/mm/Kconfig b/mm/Kconfig
index 4e9937a..391ffc5 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -29,7 +29,7 @@
 	  If unsure, choose this option (Flat Memory) over any other.
 
 config DISCONTIGMEM_MANUAL
-	bool "Discontigious Memory"
+	bool "Discontiguous Memory"
 	depends on ARCH_DISCONTIGMEM_ENABLE
 	help
 	  This option provides enhanced support for discontiguous
@@ -52,7 +52,7 @@
 	  memory hotplug systems.  This is normal.
 
 	  For many other systems, this will be an alternative to
-	  "Discontigious Memory".  This option provides some potential
+	  "Discontiguous Memory".  This option provides some potential
 	  performance benefits, along with decreased code complexity,
 	  but it is newer, and more experimental.
 
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/mmap.c b/mm/mmap.c
index 12334ae..8b8e05f 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1993,6 +1993,9 @@
 	__vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent);
 	if (__vma && __vma->vm_start < vma->vm_end)
 		return -ENOMEM;
+	if ((vma->vm_flags & VM_ACCOUNT) &&
+	     security_vm_enough_memory(vma_pages(vma)))
+		return -ENOMEM;
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 	return 0;
 }
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/slab.c b/mm/slab.c
index 9e876d6..437d338 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -659,7 +659,7 @@
  	* kmem_cache_create(), or __kmalloc(), before
  	* the generic caches are initialized.
  	*/
-	BUG_ON(csizep->cs_cachep == NULL);
+	BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
 #endif
 	while (size > csizep->cs_size)
 		csizep++;
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/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 145f5cd..b748648 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -120,7 +120,7 @@
 	unsigned short vid;
 	struct net_device_stats *stats;
 	unsigned short vlan_TCI;
-	unsigned short proto;
+	__be16 proto;
 
 	/* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
 	vlan_TCI = ntohs(vhdr->h_vlan_TCI);
diff --git a/net/Kconfig b/net/Kconfig
index 2bdd562..60f6f32 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -140,6 +140,7 @@
 
 	  If unsure, say N.
 
+source "net/netfilter/Kconfig"
 source "net/ipv4/netfilter/Kconfig"
 source "net/ipv6/netfilter/Kconfig"
 source "net/decnet/netfilter/Kconfig"
@@ -206,8 +207,6 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called pktgen.
 
-source "net/netfilter/Kconfig"
-
 endmenu
 
 endmenu
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/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 2d52fee..d8e36b7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -214,9 +214,11 @@
 				     .tos = RT_TOS(iph->tos)} }, .proto = 0};
 
 			if (!ip_route_output_key(&rt, &fl)) {
-				/* Bridged-and-DNAT'ed traffic doesn't
-				 * require ip_forwarding. */
-				if (((struct dst_entry *)rt)->dev == dev) {
+				/* - Bridged-and-DNAT'ed traffic doesn't
+				 *   require ip_forwarding.
+				 * - Deal with redirected traffic. */
+				if (((struct dst_entry *)rt)->dev == dev ||
+				    rt->rt_type == RTN_LOCAL) {
 					skb->dst = (struct dst_entry *)rt;
 					goto bridged_dnat;
 				}
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index fb97bb0..344a8da 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -3,6 +3,8 @@
 dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
 	  timer.o
 
+dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o
+
 obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
 
 dccp_diag-y := diag.o
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
new file mode 100644
index 0000000..6530283
--- /dev/null
+++ b/net/dccp/ackvec.c
@@ -0,0 +1,419 @@
+/*
+ *  net/dccp/ackvec.c
+ *
+ *  An implementation of the DCCP protocol
+ *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+ *
+ *      This program is free software; you can redistribute it and/or modify it
+ *      under the terms of the GNU General Public License as published by the
+ *      Free Software Foundation; version 2 of the License;
+ */
+
+#include "ackvec.h"
+#include "dccp.h"
+
+#include <linux/dccp.h>
+#include <linux/skbuff.h>
+
+#include <net/sock.h>
+
+int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
+{
+	struct dccp_sock *dp = dccp_sk(sk);
+	struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
+	int len = av->dccpav_vec_len + 2;
+	struct timeval now;
+	u32 elapsed_time;
+	unsigned char *to, *from;
+
+	dccp_timestamp(sk, &now);
+	elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
+
+	if (elapsed_time != 0)
+		dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
+
+	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
+		return -1;
+
+	/*
+	 * XXX: now we have just one ack vector sent record, so
+	 * we have to wait for it to be cleared.
+	 *
+	 * Of course this is not acceptable, but this is just for
+	 * basic testing now.
+	 */
+	if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1)
+		return -1;
+
+	DCCP_SKB_CB(skb)->dccpd_opt_len += len;
+
+	to    = skb_push(skb, len);
+	*to++ = DCCPO_ACK_VECTOR_0;
+	*to++ = len;
+
+	len  = av->dccpav_vec_len;
+	from = av->dccpav_buf + av->dccpav_buf_head;
+
+	/* Check if buf_head wraps */
+	if (av->dccpav_buf_head + len > av->dccpav_vec_len) {
+		const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head);
+
+		memcpy(to, from, tailsize);
+		to   += tailsize;
+		len  -= tailsize;
+		from = av->dccpav_buf;
+	}
+
+	memcpy(to, from, len);
+	/*
+	 *	From draft-ietf-dccp-spec-11.txt:
+	 *
+	 *	For each acknowledgement it sends, the HC-Receiver will add an
+	 *	acknowledgement record.  ack_seqno will equal the HC-Receiver
+	 *	sequence number it used for the ack packet; ack_ptr will equal
+	 *	buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
+	 *	equal buf_nonce.
+	 *
+	 * This implemention uses just one ack record for now.
+	 */
+	av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
+	av->dccpav_ack_ptr   = av->dccpav_buf_head;
+	av->dccpav_ack_ackno = av->dccpav_buf_ackno;
+	av->dccpav_ack_nonce = av->dccpav_buf_nonce;
+	av->dccpav_sent_len  = av->dccpav_vec_len;
+
+	dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
+		      "ack_ackno=%llu\n",
+		      debug_prefix, av->dccpav_sent_len,
+		      (unsigned long long)av->dccpav_ack_seqno,
+		      (unsigned long long)av->dccpav_ack_ackno);
+	return -1;
+}
+
+struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len,
+				      const unsigned int __nocast priority)
+{
+	struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority);
+
+	if (av != NULL) {
+		av->dccpav_buf_len	= len;
+		av->dccpav_buf_head	=
+			av->dccpav_buf_tail = av->dccpav_buf_len - 1;
+		av->dccpav_buf_ackno	=
+			av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU;
+		av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
+		av->dccpav_ack_ptr	= 0;
+		av->dccpav_time.tv_sec	= 0;
+		av->dccpav_time.tv_usec	= 0;
+		av->dccpav_sent_len	= av->dccpav_vec_len = 0;
+	}
+
+	return av;
+}
+
+void dccp_ackvec_free(struct dccp_ackvec *av)
+{
+	kfree(av);
+}
+
+static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
+				   const unsigned int index)
+{
+	return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
+}
+
+static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
+				 const unsigned int index)
+{
+	return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
+}
+
+/*
+ * If several packets are missing, the HC-Receiver may prefer to enter multiple
+ * bytes with run length 0, rather than a single byte with a larger run length;
+ * this simplifies table updates if one of the missing packets arrives.
+ */
+static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
+						 const unsigned int packets,
+						  const unsigned char state)
+{
+	unsigned int gap;
+	signed long new_head;
+
+	if (av->dccpav_vec_len + packets > av->dccpav_buf_len)
+		return -ENOBUFS;
+
+	gap	 = packets - 1;
+	new_head = av->dccpav_buf_head - packets;
+
+	if (new_head < 0) {
+		if (gap > 0) {
+			memset(av->dccpav_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED,
+			       gap + new_head + 1);
+			gap = -new_head;
+		}
+		new_head += av->dccpav_buf_len;
+	} 
+
+	av->dccpav_buf_head = new_head;
+
+	if (gap > 0)
+		memset(av->dccpav_buf + av->dccpav_buf_head + 1,
+		       DCCP_ACKVEC_STATE_NOT_RECEIVED, gap);
+
+	av->dccpav_buf[av->dccpav_buf_head] = state;
+	av->dccpav_vec_len += packets;
+	return 0;
+}
+
+/*
+ * Implements the draft-ietf-dccp-spec-11.txt Appendix A
+ */
+int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+		    const u64 ackno, const u8 state)
+{
+	/*
+	 * Check at the right places if the buffer is full, if it is, tell the
+	 * caller to start dropping packets till the HC-Sender acks our ACK
+	 * vectors, when we will free up space in dccpav_buf.
+	 *
+	 * We may well decide to do buffer compression, etc, but for now lets
+	 * just drop.
+	 *
+	 * From Appendix A:
+	 *
+	 *	Of course, the circular buffer may overflow, either when the
+	 *	HC-Sender is sending data at a very high rate, when the
+	 *	HC-Receiver's acknowledgements are not reaching the HC-Sender,
+	 *	or when the HC-Sender is forgetting to acknowledge those acks
+	 *	(so the HC-Receiver is unable to clean up old state). In this
+	 *	case, the HC-Receiver should either compress the buffer (by
+	 *	increasing run lengths when possible), transfer its state to
+	 *	a larger buffer, or, as a last resort, drop all received
+	 *	packets, without processing them whatsoever, until its buffer
+	 *	shrinks again.
+	 */
+
+	/* See if this is the first ackno being inserted */
+	if (av->dccpav_vec_len == 0) {
+		av->dccpav_buf[av->dccpav_buf_head] = state;
+		av->dccpav_vec_len = 1;
+	} else if (after48(ackno, av->dccpav_buf_ackno)) {
+		const u64 delta = dccp_delta_seqno(av->dccpav_buf_ackno,
+						   ackno);
+
+		/*
+		 * Look if the state of this packet is the same as the
+		 * previous ackno and if so if we can bump the head len.
+		 */
+		if (delta == 1 &&
+		    dccp_ackvec_state(av, av->dccpav_buf_head) == state &&
+		    (dccp_ackvec_len(av, av->dccpav_buf_head) <
+		     DCCP_ACKVEC_LEN_MASK))
+			av->dccpav_buf[av->dccpav_buf_head]++;
+		else if (dccp_ackvec_set_buf_head_state(av, delta, state))
+			return -ENOBUFS;
+	} else {
+		/*
+		 * A.1.2.  Old Packets
+		 *
+		 *	When a packet with Sequence Number S arrives, and
+		 *	S <= buf_ackno, the HC-Receiver will scan the table
+		 *	for the byte corresponding to S. (Indexing structures
+		 *	could reduce the complexity of this scan.)
+		 */
+		u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
+		unsigned int index = av->dccpav_buf_head;
+
+		while (1) {
+			const u8 len = dccp_ackvec_len(av, index);
+			const u8 state = dccp_ackvec_state(av, index);
+			/*
+			 * valid packets not yet in dccpav_buf have a reserved
+			 * entry, with a len equal to 0.
+			 */
+			if (state == DCCP_ACKVEC_STATE_NOT_RECEIVED &&
+			    len == 0 && delta == 0) { /* Found our
+							 reserved seat! */
+				dccp_pr_debug("Found %llu reserved seat!\n",
+					      (unsigned long long)ackno);
+				av->dccpav_buf[index] = state;
+				goto out;
+			}
+			/* len == 0 means one packet */
+			if (delta < len + 1)
+				goto out_duplicate;
+
+			delta -= len + 1;
+			if (++index == av->dccpav_buf_len)
+				index = 0;
+		}
+	}
+
+	av->dccpav_buf_ackno = ackno;
+	dccp_timestamp(sk, &av->dccpav_time);
+out:
+	dccp_pr_debug("");
+	return 0;
+
+out_duplicate:
+	/* Duplicate packet */
+	dccp_pr_debug("Received a dup or already considered lost "
+		      "packet: %llu\n", (unsigned long long)ackno);
+	return -EILSEQ;
+}
+
+#ifdef CONFIG_IP_DCCP_DEBUG
+void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
+{
+	if (!dccp_debug)
+		return;
+
+	printk("ACK vector len=%d, ackno=%llu |", len,
+	       (unsigned long long)ackno);
+
+	while (len--) {
+		const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
+		const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
+
+		printk("%d,%d|", state, rl);
+		++vector;
+	}
+
+	printk("\n");
+}
+
+void dccp_ackvec_print(const struct dccp_ackvec *av)
+{
+	dccp_ackvector_print(av->dccpav_buf_ackno,
+			     av->dccpav_buf + av->dccpav_buf_head,
+			     av->dccpav_vec_len);
+}
+#endif
+
+static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av)
+{
+	/*
+	 * As we're keeping track of the ack vector size (dccpav_vec_len) and
+	 * the sent ack vector size (dccpav_sent_len) we don't need
+	 * dccpav_buf_tail at all, but keep this code here as in the future
+	 * we'll implement a vector of ack records, as suggested in
+	 * draft-ietf-dccp-spec-11.txt Appendix A. -acme
+	 */
+#if 0
+	av->dccpav_buf_tail = av->dccpav_ack_ptr + 1;
+	if (av->dccpav_buf_tail >= av->dccpav_vec_len)
+		av->dccpav_buf_tail -= av->dccpav_vec_len;
+#endif
+	av->dccpav_vec_len -= av->dccpav_sent_len;
+}
+
+void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
+				 const u64 ackno)
+{
+	/* Check if we actually sent an ACK vector */
+	if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
+		return;
+
+	if (ackno == av->dccpav_ack_seqno) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+		struct dccp_sock *dp = dccp_sk(sk);
+		const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
+					"CLIENT rx ack: " : "server rx ack: ";
+#endif
+		dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
+			      "ack_ackno=%llu, ACKED!\n",
+			      debug_prefix, 1,
+			      (unsigned long long)av->dccpav_ack_seqno,
+			      (unsigned long long)av->dccpav_ack_ackno);
+		dccp_ackvec_trow_away_ack_record(av);
+		av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
+	}
+}
+
+static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
+					    struct sock *sk, u64 ackno,
+					    const unsigned char len,
+					    const unsigned char *vector)
+{
+	unsigned char i;
+
+	/* Check if we actually sent an ACK vector */
+	if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
+		return;
+	/*
+	 * We're in the receiver half connection, so if the received an ACK
+	 * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're
+	 * not interested.
+	 *
+	 * Extra explanation with example:
+	 * 
+	 * if we received an ACK vector with ackno 50, it can only be acking
+	 * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
+	 */
+	/* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */
+	if (before48(ackno, av->dccpav_ack_seqno)) {
+		/* dccp_pr_debug_cat("yes\n"); */
+		return;
+	}
+	/* dccp_pr_debug_cat("no\n"); */
+
+	i = len;
+	while (i--) {
+		const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
+		u64 ackno_end_rl;
+
+		dccp_set_seqno(&ackno_end_rl, ackno - rl);
+
+		/*
+		 * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
+		 * av->dccpav_ack_seqno, ackno);
+		 */
+		if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) {
+			const u8 state = (*vector &
+					  DCCP_ACKVEC_STATE_MASK) >> 6;
+			/* dccp_pr_debug_cat("yes\n"); */
+
+			if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
+#ifdef CONFIG_IP_DCCP_DEBUG
+				struct dccp_sock *dp = dccp_sk(sk);
+				const char *debug_prefix =
+					dp->dccps_role == DCCP_ROLE_CLIENT ?
+					"CLIENT rx ack: " : "server rx ack: ";
+#endif
+				dccp_pr_debug("%sACK vector 0, len=%d, "
+					      "ack_seqno=%llu, ack_ackno=%llu, "
+					      "ACKED!\n",
+					      debug_prefix, len,
+					      (unsigned long long)
+					      av->dccpav_ack_seqno,
+					      (unsigned long long)
+					      av->dccpav_ack_ackno);
+				dccp_ackvec_trow_away_ack_record(av);
+			}
+			/*
+			 * If dccpav_ack_seqno was not received, no problem
+			 * we'll send another ACK vector.
+			 */
+			av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
+			break;
+		}
+		/* dccp_pr_debug_cat("no\n"); */
+
+		dccp_set_seqno(&ackno, ackno_end_rl - 1);
+		++vector;
+	}
+}
+
+int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+		      const u8 opt, const u8 *value, const u8 len)
+{
+	if (len > DCCP_MAX_ACKVEC_LEN)
+		return -1;
+
+	/* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
+	dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,
+					DCCP_SKB_CB(skb)->dccpd_ack_seq,
+				        len, value);
+	return 0;
+}
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
new file mode 100644
index 0000000..8ca51c9
--- /dev/null
+++ b/net/dccp/ackvec.h
@@ -0,0 +1,133 @@
+#ifndef _ACKVEC_H
+#define _ACKVEC_H
+/*
+ *  net/dccp/ackvec.h
+ *
+ *  An implementation of the DCCP protocol
+ *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@mandriva.com>
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License version 2 as
+ *	published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+/* Read about the ECN nonce to see why it is 253 */
+#define DCCP_MAX_ACKVEC_LEN 253
+
+#define DCCP_ACKVEC_STATE_RECEIVED	0
+#define DCCP_ACKVEC_STATE_ECN_MARKED	(1 << 6)
+#define DCCP_ACKVEC_STATE_NOT_RECEIVED	(3 << 6)
+
+#define DCCP_ACKVEC_STATE_MASK		0xC0 /* 11000000 */
+#define DCCP_ACKVEC_LEN_MASK		0x3F /* 00111111 */
+
+/** struct dccp_ackvec - ack vector
+ *
+ * This data structure is the one defined in the DCCP draft
+ * Appendix A.
+ *
+ * @dccpav_buf_head - circular buffer head
+ * @dccpav_buf_tail - circular buffer tail
+ * @dccpav_buf_ackno - ack # of the most recent packet acknowledgeable in the
+ * 		       buffer (i.e. %dccpav_buf_head)
+ * @dccpav_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked
+ * 		       by the buffer with State 0
+ *
+ * Additionally, the HC-Receiver must keep some information about the
+ * Ack Vectors it has recently sent. For each packet sent carrying an
+ * Ack Vector, it remembers four variables:
+ *
+ * @dccpav_ack_seqno - the Sequence Number used for the packet
+ * 		       (HC-Receiver seqno)
+ * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement.
+ * @dccpav_ack_ackno - the Acknowledgement Number used for the packet
+ * 		       (HC-Sender seqno)
+ * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
+ *
+ * @dccpav_buf_len	- circular buffer length
+ * @dccpav_time		- the time in usecs
+ * @dccpav_buf - circular buffer of acknowledgeable packets
+ */
+struct dccp_ackvec {
+	unsigned int	dccpav_buf_head;
+	unsigned int	dccpav_buf_tail;
+	u64		dccpav_buf_ackno;
+	u64		dccpav_ack_seqno;
+	u64		dccpav_ack_ackno;
+	unsigned int	dccpav_ack_ptr;
+	unsigned int	dccpav_sent_len;
+	unsigned int	dccpav_vec_len;
+	unsigned int	dccpav_buf_len;
+	struct timeval	dccpav_time;
+	u8		dccpav_buf_nonce;
+	u8		dccpav_ack_nonce;
+	u8		dccpav_buf[0];
+};
+
+struct sock;
+struct sk_buff;
+
+#ifdef CONFIG_IP_DCCP_ACKVEC
+extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len,
+					  const unsigned int __nocast priority);
+extern void dccp_ackvec_free(struct dccp_ackvec *av);
+
+extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+			   const u64 ackno, const u8 state);
+
+extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
+					struct sock *sk, const u64 ackno);
+extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+			     const u8 opt, const u8 *value, const u8 len);
+
+extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb);
+
+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
+{
+	return av->dccpav_sent_len != av->dccpav_vec_len;
+}
+#else /* CONFIG_IP_DCCP_ACKVEC */
+static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len,
+					   const unsigned int __nocast priority)
+{
+	return NULL;
+}
+
+static inline void dccp_ackvec_free(struct dccp_ackvec *av)
+{
+}
+
+static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
+				  const u64 ackno, const u8 state)
+{
+	return -1;
+}
+
+static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av,
+					       struct sock *sk, const u64 ackno)
+{
+}
+
+static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
+				    const u8 opt, const u8 *value, const u8 len)
+{
+	return -1;
+}
+
+static inline int dccp_insert_option_ackvec(const struct sock *sk,
+					    const struct sk_buff *skb)
+{
+	return -1;
+}
+
+static inline int dccp_ackvec_pending(const struct dccp_ackvec *av)
+{
+	return 0;
+}
+#endif /* CONFIG_IP_DCCP_ACKVEC */
+#endif /* _ACKVEC_H */
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 962f1e9..21e5514 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -14,6 +14,7 @@
  */
 
 #include <net/sock.h>
+#include <linux/compiler.h>
 #include <linux/dccp.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -54,6 +55,14 @@
 					       struct tcp_info *info);
 	void		(*ccid_hc_tx_get_info)(struct sock *sk,
 					       struct tcp_info *info);
+	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
+						 const int optname, int len,
+						 u32 __user *optval,
+						 int __user *optlen);
+	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
+						 const int optname, int len,
+						 u32 __user *optval,
+						 int __user *optlen);
 };
 
 extern int	   ccid_register(struct ccid *ccid);
@@ -177,4 +186,26 @@
 	if (ccid->ccid_hc_tx_get_info != NULL)
 		ccid->ccid_hc_tx_get_info(sk, info);
 }
+
+static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
+					const int optname, int len,
+					u32 __user *optval, int __user *optlen)
+{
+	int rc = -ENOPROTOOPT;
+	if (ccid->ccid_hc_rx_getsockopt != NULL)
+		rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
+						 optval, optlen);
+	return rc;
+}
+
+static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
+					const int optname, int len,
+					u32 __user *optval, int __user *optlen)
+{
+	int rc = -ENOPROTOOPT;
+	if (ccid->ccid_hc_tx_getsockopt != NULL)
+		rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
+						 optval, optlen);
+	return rc;
+}
 #endif /* _CCID_H */
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 38aa849..aa68e0a 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1120,6 +1120,60 @@
 	info->tcpi_rtt = hctx->ccid3hctx_rtt;
 }
 
+static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
+				  u32 __user *optval, int __user *optlen)
+{
+	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+	const void *val;
+	
+	/* Listen socks doesn't have a private CCID block */
+	if (sk->sk_state == DCCP_LISTEN)
+		return -EINVAL;
+
+	switch (optname) {
+	case DCCP_SOCKOPT_CCID_RX_INFO:
+		if (len < sizeof(hcrx->ccid3hcrx_tfrc))
+			return -EINVAL;
+		len = sizeof(hcrx->ccid3hcrx_tfrc);
+		val = &hcrx->ccid3hcrx_tfrc;
+		break;
+	default:
+		return -ENOPROTOOPT;
+	}
+
+	if (put_user(len, optlen) || copy_to_user(optval, val, len))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
+				  u32 __user *optval, int __user *optlen)
+{
+	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+	const void *val;
+	
+	/* Listen socks doesn't have a private CCID block */
+	if (sk->sk_state == DCCP_LISTEN)
+		return -EINVAL;
+
+	switch (optname) {
+	case DCCP_SOCKOPT_CCID_TX_INFO:
+		if (len < sizeof(hctx->ccid3hctx_tfrc))
+			return -EINVAL;
+		len = sizeof(hctx->ccid3hctx_tfrc);
+		val = &hctx->ccid3hctx_tfrc;
+		break;
+	default:
+		return -ENOPROTOOPT;
+	}
+
+	if (put_user(len, optlen) || copy_to_user(optval, val, len))
+		return -EFAULT;
+
+	return 0;
+}
+
 static struct ccid ccid3 = {
 	.ccid_id		   = 3,
 	.ccid_name		   = "ccid3",
@@ -1139,6 +1193,8 @@
 	.ccid_hc_rx_packet_recv	   = ccid3_hc_rx_packet_recv,
 	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
 	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
+	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
+	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
 };
  
 module_param(ccid3_debug, int, 0444);
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index eb24877..0bde458 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -40,6 +40,7 @@
 #include <linux/list.h>
 #include <linux/time.h>
 #include <linux/types.h>
+#include <linux/tfrc.h>
 
 #define TFRC_MIN_PACKET_SIZE	   16
 #define TFRC_STD_PACKET_SIZE	  256
@@ -93,12 +94,15 @@
   * @ccid3hctx_hist - Packet history
   */
 struct ccid3_hc_tx_sock {
-	u32				ccid3hctx_x;
-	u32				ccid3hctx_x_recv;
-	u32				ccid3hctx_x_calc;
+	struct tfrc_tx_info		ccid3hctx_tfrc;
+#define ccid3hctx_x			ccid3hctx_tfrc.tfrctx_x
+#define ccid3hctx_x_recv		ccid3hctx_tfrc.tfrctx_x_recv
+#define ccid3hctx_x_calc		ccid3hctx_tfrc.tfrctx_x_calc
+#define ccid3hctx_rtt			ccid3hctx_tfrc.tfrctx_rtt
+#define ccid3hctx_p			ccid3hctx_tfrc.tfrctx_p
+#define ccid3hctx_t_rto			ccid3hctx_tfrc.tfrctx_rto
+#define ccid3hctx_t_ipi			ccid3hctx_tfrc.tfrctx_ipi
 	u16				ccid3hctx_s;
-	u32				ccid3hctx_rtt;
-	u32				ccid3hctx_p;
   	u8				ccid3hctx_state;
 	u8				ccid3hctx_last_win_count;
 	u8				ccid3hctx_idle;
@@ -106,19 +110,19 @@
 	struct timer_list		ccid3hctx_no_feedback_timer;
 	struct timeval			ccid3hctx_t_ld;
 	struct timeval			ccid3hctx_t_nom;
-	u32				ccid3hctx_t_rto;
-	u32				ccid3hctx_t_ipi;
 	u32				ccid3hctx_delta;
 	struct list_head		ccid3hctx_hist;
 	struct ccid3_options_received	ccid3hctx_options_received;
 };
 
 struct ccid3_hc_rx_sock {
+	struct tfrc_rx_info	ccid3hcrx_tfrc;
+#define ccid3hcrx_x_recv	ccid3hcrx_tfrc.tfrcrx_x_recv
+#define ccid3hcrx_rtt		ccid3hcrx_tfrc.tfrcrx_rtt
+#define ccid3hcrx_p		ccid3hcrx_tfrc.tfrcrx_p
   	u64			ccid3hcrx_seqno_last_counter:48,
 				ccid3hcrx_state:8,
 				ccid3hcrx_last_counter:4;
-	u32			ccid3hcrx_rtt;
-  	u32			ccid3hcrx_p;
   	u32			ccid3hcrx_bytes_recv;
   	struct timeval		ccid3hcrx_tstamp_last_feedback;
   	struct timeval		ccid3hcrx_tstamp_last_ack;
@@ -127,7 +131,6 @@
   	u16			ccid3hcrx_s;
   	u32			ccid3hcrx_pinv;
   	u32			ccid3hcrx_elapsed_time;
-  	u32			ccid3hcrx_x_recv;
 };
 
 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 95c4630..5871c02 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -17,6 +17,7 @@
 #include <net/snmp.h>
 #include <net/sock.h>
 #include <net/tcp.h>
+#include "ackvec.h"
 
 #ifdef CONFIG_IP_DCCP_DEBUG
 extern int dccp_debug;
@@ -258,13 +259,12 @@
 extern void	   dccp_send_close(struct sock *sk, const int active);
 
 struct dccp_skb_cb {
-	__u8 dccpd_type;
-	__u8 dccpd_reset_code;
-	__u8 dccpd_service;
-	__u8 dccpd_ccval;
+	__u8  dccpd_type:4;
+	__u8  dccpd_ccval:4;
+	__u8  dccpd_reset_code;
+	__u16 dccpd_opt_len;
 	__u64 dccpd_seq;
 	__u64 dccpd_ack_seq;
-	int  dccpd_opt_len;
 };
 
 #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
@@ -359,6 +359,17 @@
 		       (dp->dccps_gss -
 			dp->dccps_options.dccpo_sequence_window + 1));
 }
+				
+static inline int dccp_ack_pending(const struct sock *sk)
+{
+	const struct dccp_sock *dp = dccp_sk(sk);
+	return dp->dccps_timestamp_echo != 0 ||
+#ifdef CONFIG_IP_DCCP_ACKVEC
+	       (dp->dccps_options.dccpo_send_ack_vector &&
+		dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
+#endif
+	       inet_csk_ack_scheduled(sk);
+}
 
 extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb);
 extern void dccp_insert_option_elapsed_time(struct sock *sk,
@@ -372,65 +383,6 @@
 
 extern struct socket *dccp_ctl_socket;
 
-#define DCCP_ACKPKTS_STATE_RECEIVED	0
-#define DCCP_ACKPKTS_STATE_ECN_MARKED	(1 << 6)
-#define DCCP_ACKPKTS_STATE_NOT_RECEIVED	(3 << 6)
-
-#define DCCP_ACKPKTS_STATE_MASK		0xC0 /* 11000000 */
-#define DCCP_ACKPKTS_LEN_MASK		0x3F /* 00111111 */
-
-/** struct dccp_ackpkts - acknowledgeable packets
- *
- * This data structure is the one defined in the DCCP draft
- * Appendix A.
- *
- * @dccpap_buf_head - circular buffer head
- * @dccpap_buf_tail - circular buffer tail
- * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the
- * 		       buffer (i.e. %dccpap_buf_head)
- * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked
- * 		       by the buffer with State 0
- *
- * Additionally, the HC-Receiver must keep some information about the
- * Ack Vectors it has recently sent. For each packet sent carrying an
- * Ack Vector, it remembers four variables:
- *
- * @dccpap_ack_seqno - the Sequence Number used for the packet
- * 		       (HC-Receiver seqno)
- * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement.
- * @dccpap_ack_ackno - the Acknowledgement Number used for the packet
- * 		       (HC-Sender seqno)
- * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
- *
- * @dccpap_buf_len - circular buffer length
- * @dccpap_time		- the time in usecs
- * @dccpap_buf - circular buffer of acknowledgeable packets
- */
-struct dccp_ackpkts {
-	unsigned int		dccpap_buf_head;
-	unsigned int		dccpap_buf_tail;
-	u64			dccpap_buf_ackno;
-	u64			dccpap_ack_seqno;
-	u64			dccpap_ack_ackno;
-	unsigned int		dccpap_ack_ptr;
-	unsigned int		dccpap_buf_vector_len;
-	unsigned int		dccpap_ack_vector_len;
-	unsigned int		dccpap_buf_len;
-	struct timeval		dccpap_time;
-	u8			dccpap_buf_nonce;
-	u8			dccpap_ack_nonce;
-	u8			dccpap_buf[0];
-};
-
-extern struct dccp_ackpkts *
-		dccp_ackpkts_alloc(unsigned int len,
-				  const unsigned int __nocast priority);
-extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
-extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
-			    u64 ackno, u8 state);
-extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
-					 struct sock *sk, u64 ackno);
-
 extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
 
 static inline suseconds_t timeval_usecs(const struct timeval *tv)
@@ -471,15 +423,4 @@
 	}
 }
 
-#ifdef CONFIG_IP_DCCP_DEBUG
-extern void dccp_ackvector_print(const u64 ackno,
-				 const unsigned char *vector, int len);
-extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap);
-#else
-static inline void dccp_ackvector_print(const u64 ackno,
-					const unsigned char *vector,
-					int len) { }
-static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { }
-#endif
-
 #endif /* _DCCP_H */
diff --git a/net/dccp/input.c b/net/dccp/input.c
index c60bc34..1b6b2cb 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -16,6 +16,7 @@
 
 #include <net/sock.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
@@ -50,7 +51,8 @@
 		return;
 	}
 
-	dccp_set_state(sk, DCCP_CLOSING);
+	if (sk->sk_state != DCCP_CLOSING)
+		dccp_set_state(sk, DCCP_CLOSING);
 	dccp_send_close(sk, 0);
 }
 
@@ -59,8 +61,8 @@
 	struct dccp_sock *dp = dccp_sk(sk);
 
 	if (dp->dccps_options.dccpo_send_ack_vector)
-		dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk,
-					     DCCP_SKB_CB(skb)->dccpd_ack_seq);
+		dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,
+					    DCCP_SKB_CB(skb)->dccpd_ack_seq);
 }
 
 static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
@@ -163,37 +165,11 @@
 	if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
 		dccp_event_ack_recv(sk, skb);
 
-	/*
-	 * FIXME: check ECN to see if we should use
-	 * DCCP_ACKPKTS_STATE_ECN_MARKED
-	 */
-	if (dp->dccps_options.dccpo_send_ack_vector) {
-		struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
-
-		if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
-				     DCCP_SKB_CB(skb)->dccpd_seq,
-				     DCCP_ACKPKTS_STATE_RECEIVED)) {
-			LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
-						    "packets buffer full!\n");
-			ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
-			inet_csk_schedule_ack(sk);
-			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
-						  TCP_DELACK_MIN,
-						  DCCP_RTO_MAX);
-			goto discard;
-		}
-
-		/*
-		 * FIXME: this activation is probably wrong, have to study more
-		 * TCP delack machinery and how it fits into DCCP draft, but
-		 * for now it kinda "works" 8)
-		 */
-		if (!inet_csk_ack_scheduled(sk)) {
-			inet_csk_schedule_ack(sk);
-			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ,
-						  DCCP_RTO_MAX);
-		}
-	}
+	if (dp->dccps_options.dccpo_send_ack_vector &&
+	    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+			    DCCP_SKB_CB(skb)->dccpd_seq,
+			    DCCP_ACKVEC_STATE_RECEIVED))
+		goto discard;
 
 	ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
 	ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
@@ -383,9 +359,9 @@
 	}
 
 out_invalid_packet:
-	return 1; /* dccp_v4_do_rcv will send a reset, but...
-		     FIXME: the reset code should be
-			    DCCP_RESET_CODE_PACKET_ERROR */
+	/* dccp_v4_do_rcv will send a reset */
+	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
+	return 1; 
 }
 
 static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
@@ -432,6 +408,7 @@
 			   struct dccp_hdr *dh, unsigned len)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
+	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
 	const int old_state = sk->sk_state;
 	int queued = 0;
 
@@ -472,7 +449,8 @@
 		if (dh->dccph_type == DCCP_PKT_RESET)
 			goto discard;
 
-		/* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/
+		/* Caller (dccp_v4_do_rcv) will send Reset */
+		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
 		return 1;
 	}
 
@@ -486,36 +464,17 @@
 		if (dccp_parse_options(sk, skb))
 			goto discard;
 
-		if (DCCP_SKB_CB(skb)->dccpd_ack_seq !=
-		    DCCP_PKT_WITHOUT_ACK_SEQ)
+		if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
 			dccp_event_ack_recv(sk, skb);
 
 		ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
 		ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
 
-		/*
-		 * FIXME: check ECN to see if we should use
-		 * DCCP_ACKPKTS_STATE_ECN_MARKED
-		 */
-		if (dp->dccps_options.dccpo_send_ack_vector) {
-			if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
-					     DCCP_SKB_CB(skb)->dccpd_seq,
-					     DCCP_ACKPKTS_STATE_RECEIVED))
-				goto discard;
-			/*
-			 * FIXME: this activation is probably wrong, have to
-			 * study more TCP delack machinery and how it fits into
-			 * DCCP draft, but for now it kinda "works" 8)
-			 */
-			if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno ==
-			     DCCP_MAX_SEQNO + 1) &&
-			    !inet_csk_ack_scheduled(sk)) {
-				inet_csk_schedule_ack(sk);
-				inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
-							  TCP_DELACK_MIN,
-							  DCCP_RTO_MAX);
-			}
-		}
+ 		if (dp->dccps_options.dccpo_send_ack_vector &&
+		    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+ 				    DCCP_SKB_CB(skb)->dccpd_seq,
+ 				    DCCP_ACKVEC_STATE_RECEIVED))
+ 			goto discard;
 	}
 
 	/*
@@ -550,8 +509,7 @@
 		     dh->dccph_type == DCCP_PKT_REQUEST) ||
 		    (sk->sk_state == DCCP_RESPOND &&
 		     dh->dccph_type == DCCP_PKT_DATA)) {
-		dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,
-			       DCCP_PKT_SYNC);
+		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
 		goto discard;
 	} else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
 		dccp_rcv_closereq(sk, skb);
@@ -561,8 +519,14 @@
 		return 0;
 	}
 
+	if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) {
+		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK);
+		goto discard;
+	}
+
 	switch (sk->sk_state) {
 	case DCCP_CLOSED:
+		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
 		return 1;
 
 	case DCCP_REQUESTING:
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 2afaa46..40fe6af 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -23,6 +23,7 @@
 #include <net/tcp_states.h>
 #include <net/xfrm.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
@@ -246,6 +247,9 @@
 
 	dp->dccps_role = DCCP_ROLE_CLIENT;
 
+	if (dccp_service_not_initialized(sk))
+		return -EPROTO;
+
 	if (addr_len < sizeof(struct sockaddr_in))
 		return -EINVAL;
 
@@ -661,6 +665,16 @@
 					   dccp_hdr(skb)->dccph_sport);
 }
 
+static inline int dccp_bad_service_code(const struct sock *sk,
+					const __u32 service)
+{
+	const struct dccp_sock *dp = dccp_sk(sk);
+
+	if (dp->dccps_service == service)
+		return 0;
+	return !dccp_list_has_service(dp->dccps_service_list, service);
+}
+
 int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 {
 	struct inet_request_sock *ireq;
@@ -669,13 +683,22 @@
 	struct dccp_request_sock *dreq;
 	const __u32 saddr = skb->nh.iph->saddr;
 	const __u32 daddr = skb->nh.iph->daddr;
+ 	const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
+	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+	__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
 	struct dst_entry *dst = NULL;
 
 	/* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
 	if (((struct rtable *)skb->dst)->rt_flags &
-	    (RTCF_BROADCAST | RTCF_MULTICAST))
+	    (RTCF_BROADCAST | RTCF_MULTICAST)) {
+		reset_code = DCCP_RESET_CODE_NO_CONNECTION;
 		goto drop;
+	}
 
+	if (dccp_bad_service_code(sk, service)) {
+		reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
+		goto drop;
+ 	}
 	/*
 	 * TW buckets are converted to open requests without
 	 * limitations, they conserve resources and peer is
@@ -718,9 +741,9 @@
 	 * dccp_create_openreq_child.
 	 */
 	dreq = dccp_rsk(req);
-	dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq;
-	dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
-	dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service;
+	dreq->dreq_isr	   = dcb->dccpd_seq;
+	dreq->dreq_iss	   = dccp_v4_init_sequence(sk, skb);
+	dreq->dreq_service = service;
 
 	if (dccp_v4_send_response(sk, req, dst))
 		goto drop_and_free;
@@ -735,6 +758,7 @@
 	__reqsk_free(req);
 drop:
 	DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+	dcb->dccpd_reset_code = reset_code;
 	return -1;
 }
 
@@ -1005,7 +1029,6 @@
 	return 0;
 
 reset:
-	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
 	dccp_v4_ctl_send_reset(skb);
 discard:
 	kfree_skb(skb);
@@ -1090,45 +1113,7 @@
 		goto discard_it;
 
 	dh = dccp_hdr(skb);
-#if 0
-	/*
-	 * Use something like this to simulate some DATA/DATAACK loss to test
-	 * dccp_ackpkts_add, you'll get something like this on a session that
-	 * sends 10 DATA/DATAACK packets:
-	 *
-	 * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1|
-	 *
-	 * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet
-	 * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets
-	 * 						   with the same state
-	 * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet
-	 *
-	 * So...
-	 *
-	 * 281473596467422 was received
-	 * 281473596467421 was not received
-	 * 281473596467420 was received
-	 * 281473596467419 was not received
-	 * 281473596467418 was received
-	 * 281473596467417 was not received
-	 * 281473596467416 was received
-	 * 281473596467415 was not received
-	 * 281473596467414 was received
-	 * 281473596467413 was received (this one was the 3way handshake
-	 * 				 RESPONSE)
-	 *
-	 */
-	if (dh->dccph_type == DCCP_PKT_DATA ||
-	    dh->dccph_type == DCCP_PKT_DATAACK) {
-		static int discard = 0;
 
-		if (discard) {
-			discard = 0;
-			goto discard_it;
-		}
-		discard = 1;
-	}
-#endif
 	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_hdr_seq(skb);
 	DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
 
@@ -1242,11 +1227,9 @@
 	do_gettimeofday(&dp->dccps_epoch);
 
 	if (dp->dccps_options.dccpo_send_ack_vector) {
-		dp->dccps_hc_rx_ackpkts =
-			dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
-					   GFP_KERNEL);
-
-		if (dp->dccps_hc_rx_ackpkts == NULL)
+		dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
+							   GFP_KERNEL);
+		if (dp->dccps_hc_rx_ackvec == NULL)
 			return -ENOMEM;
 	}
 
@@ -1258,16 +1241,18 @@
 	 * setsockopt(CCIDs-I-want/accept). -acme
 	 */
 	if (likely(!dccp_ctl_socket_init)) {
-		dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+		dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
 						 sk);
-		dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid,
+		dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
 						 sk);
 	    	if (dp->dccps_hc_rx_ccid == NULL ||
 		    dp->dccps_hc_tx_ccid == NULL) {
 			ccid_exit(dp->dccps_hc_rx_ccid, sk);
 			ccid_exit(dp->dccps_hc_tx_ccid, sk);
-			dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
-			dp->dccps_hc_rx_ackpkts = NULL;
+			if (dp->dccps_options.dccpo_send_ack_vector) {
+				dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
+				dp->dccps_hc_rx_ackvec = NULL;
+			}
 			dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
 			return -ENOMEM;
 		}
@@ -1280,6 +1265,7 @@
 	sk->sk_write_space = dccp_write_space;
 	dp->dccps_mss_cache = 536;
 	dp->dccps_role = DCCP_ROLE_UNDEFINED;
+	dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
 
 	return 0;
 }
@@ -1301,10 +1287,17 @@
 	if (inet_csk(sk)->icsk_bind_hash != NULL)
 		inet_put_port(&dccp_hashinfo, sk);
 
+	if (dp->dccps_service_list != NULL) {
+		kfree(dp->dccps_service_list);
+		dp->dccps_service_list = NULL;
+	}
+
 	ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
 	ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
-	dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts);
-	dp->dccps_hc_rx_ackpkts = NULL;
+	if (dp->dccps_options.dccpo_send_ack_vector) {
+		dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
+		dp->dccps_hc_rx_ackvec = NULL;
+	}
 	ccid_exit(dp->dccps_hc_rx_ccid, sk);
 	ccid_exit(dp->dccps_hc_tx_ccid, sk);
 	dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 18461bc..1393461 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -19,6 +19,7 @@
 #include <net/xfrm.h>
 #include <net/inet_timewait_sock.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
@@ -93,22 +94,24 @@
 		struct inet_connection_sock *newicsk = inet_csk(sk);
 		struct dccp_sock *newdp = dccp_sk(newsk);
 
-		newdp->dccps_hc_rx_ackpkts = NULL;
-		newdp->dccps_role = DCCP_ROLE_SERVER;
-		newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
+		newdp->dccps_role	   = DCCP_ROLE_SERVER;
+		newdp->dccps_hc_rx_ackvec  = NULL;
+		newdp->dccps_service_list  = NULL;
+		newdp->dccps_service	   = dreq->dreq_service;
+		newicsk->icsk_rto	   = DCCP_TIMEOUT_INIT;
 		do_gettimeofday(&newdp->dccps_epoch);
 
 		if (newdp->dccps_options.dccpo_send_ack_vector) {
-			newdp->dccps_hc_rx_ackpkts =
-				dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN,
-						   GFP_ATOMIC);
+			newdp->dccps_hc_rx_ackvec =
+				dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN,
+						  GFP_ATOMIC);
 			/*
 			 * XXX: We're using the same CCIDs set on the parent,
 			 * i.e. sk_clone copied the master sock and left the
 			 * CCID pointers for this child, that is why we do the
 			 * __ccid_get calls.
 			 */
-			if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL))
+			if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
 				goto out_free;
 		}
 
@@ -116,7 +119,7 @@
 					     newsk) != 0 ||
 			     ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
 				     	     newsk) != 0)) {
-			dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts);
+			dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
 			ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
 			ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
 out_free:
diff --git a/net/dccp/options.c b/net/dccp/options.c
index d4c4242..0a76426 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -18,19 +18,15 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
-static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
-					     struct sock *sk,
-					     const u64 ackno,
-					     const unsigned char len,
-					     const unsigned char *vector);
-
 /* stores the default values for new connection. may be changed with sysctl */
 static const struct dccp_options dccpo_default_values = {
 	.dccpo_sequence_window	  = DCCPF_INITIAL_SEQUENCE_WINDOW,
-	.dccpo_ccid		  = DCCPF_INITIAL_CCID,
+	.dccpo_rx_ccid		  = DCCPF_INITIAL_CCID,
+	.dccpo_tx_ccid		  = DCCPF_INITIAL_CCID,
 	.dccpo_send_ack_vector	  = DCCPF_INITIAL_SEND_ACK_VECTOR,
 	.dccpo_send_ndp_count	  = DCCPF_INITIAL_SEND_NDP_COUNT,
 };
@@ -113,25 +109,13 @@
 				      opt_recv->dccpor_ndp);
 			break;
 		case DCCPO_ACK_VECTOR_0:
-			if (len > DCCP_MAX_ACK_VECTOR_LEN)
-				goto out_invalid_option;
-
+		case DCCPO_ACK_VECTOR_1:
 			if (pkt_type == DCCP_PKT_DATA)
 				continue;
 
-			opt_recv->dccpor_ack_vector_len = len;
-			opt_recv->dccpor_ack_vector_idx = value - options;
-
-			dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n",
-				      debug_prefix, len,
-				      (unsigned long long)
-				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
-			dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq,
-					     value, len);
-			dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts,
-							 sk,
-						 DCCP_SKB_CB(skb)->dccpd_ack_seq,
-							 len, value);
+			if (dp->dccps_options.dccpo_send_ack_vector &&
+			    dccp_ackvec_parse(sk, skb, opt, value, len))
+				goto out_invalid_option;
 			break;
 		case DCCPO_TIMESTAMP:
 			if (len != 4)
@@ -352,86 +336,6 @@
 
 EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
 
-static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
-{
-	struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
-	const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
-					"CLIENT TX opt: " : "server TX opt: ";
-#endif
-	struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
-	int len = ap->dccpap_buf_vector_len + 2;
-	struct timeval now;
-	u32 elapsed_time;
-	unsigned char *to, *from;
-
-	dccp_timestamp(sk, &now);
-	elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
-
-	if (elapsed_time != 0)
-		dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
-
-	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
-		LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
-					 "insert ACK Vector!\n");
-		return;
-	}
-
-	/*
-	 * XXX: now we have just one ack vector sent record, so
-	 * we have to wait for it to be cleared.
-	 *
-	 * Of course this is not acceptable, but this is just for
-	 * basic testing now.
-	 */
-	if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1)
-		return;
-
-	DCCP_SKB_CB(skb)->dccpd_opt_len += len;
-
-	to    = skb_push(skb, len);
-	*to++ = DCCPO_ACK_VECTOR_0;
-	*to++ = len;
-
-	len  = ap->dccpap_buf_vector_len;
-	from = ap->dccpap_buf + ap->dccpap_buf_head;
-
-	/* Check if buf_head wraps */
-	if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) {
-		const unsigned int tailsize = (ap->dccpap_buf_len -
-					       ap->dccpap_buf_head);
-
-		memcpy(to, from, tailsize);
-		to   += tailsize;
-		len  -= tailsize;
-		from = ap->dccpap_buf;
-	}
-
-	memcpy(to, from, len);
-	/*
-	 *	From draft-ietf-dccp-spec-11.txt:
-	 *
-	 *	For each acknowledgement it sends, the HC-Receiver will add an
-	 *	acknowledgement record.  ack_seqno will equal the HC-Receiver
-	 *	sequence number it used for the ack packet; ack_ptr will equal
-	 *	buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
-	 *	equal buf_nonce.
-	 *
-	 * This implemention uses just one ack record for now.
-	 */
-	ap->dccpap_ack_seqno	  = DCCP_SKB_CB(skb)->dccpd_seq;
-	ap->dccpap_ack_ptr	  = ap->dccpap_buf_head;
-	ap->dccpap_ack_ackno	  = ap->dccpap_buf_ackno;
-	ap->dccpap_ack_nonce	  = ap->dccpap_buf_nonce;
-	ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len;
-
-	dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
-		      "ack_ackno=%llu\n",
-		      debug_prefix, ap->dccpap_ack_vector_len,
-		      (unsigned long long) ap->dccpap_ack_seqno,
-		      (unsigned long long) ap->dccpap_ack_ackno);
-}
-
 void dccp_timestamp(const struct sock *sk, struct timeval *tv)
 {
 	const struct dccp_sock *dp = dccp_sk(sk);
@@ -528,9 +432,8 @@
 
 	if (!dccp_packet_without_ack(skb)) {
 		if (dp->dccps_options.dccpo_send_ack_vector &&
-		    (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
-		     DCCP_MAX_SEQNO + 1))
-			dccp_insert_option_ack_vector(sk, skb);
+		    dccp_ackvec_pending(dp->dccps_hc_rx_ackvec))
+			dccp_insert_option_ackvec(sk, skb);
 		if (dp->dccps_timestamp_echo != 0)
 			dccp_insert_option_timestamp_echo(sk, skb);
 	}
@@ -557,331 +460,3 @@
 		}
 	}
 }
-
-struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len,
-				        const unsigned int __nocast priority)
-{
-	struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority);
-
-	if (ap != NULL) {
-#ifdef CONFIG_IP_DCCP_DEBUG
-		memset(ap->dccpap_buf, 0xFF, len);
-#endif
-		ap->dccpap_buf_len   = len;
-		ap->dccpap_buf_head  =
-			ap->dccpap_buf_tail =
-				ap->dccpap_buf_len - 1;
-		ap->dccpap_buf_ackno =
-			ap->dccpap_ack_ackno =
-				ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
-		ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0;
-		ap->dccpap_ack_ptr   = 0;
-		ap->dccpap_time.tv_sec = 0;
-		ap->dccpap_time.tv_usec = 0;
-		ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0;
-	}
-
-	return ap;
-}
-
-void dccp_ackpkts_free(struct dccp_ackpkts *ap)
-{
-	if (ap != NULL) {
-#ifdef CONFIG_IP_DCCP_DEBUG
-		memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len);
-#endif
-		kfree(ap);
-	}
-}
-
-static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap,
-				    const unsigned int index)
-{
-	return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK;
-}
-
-static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap,
-				  const unsigned int index)
-{
-	return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK;
-}
-
-/*
- * If several packets are missing, the HC-Receiver may prefer to enter multiple
- * bytes with run length 0, rather than a single byte with a larger run length;
- * this simplifies table updates if one of the missing packets arrives.
- */
-static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
-						  const unsigned int packets,
-						  const unsigned char state)
-{
-	unsigned int gap;
-	signed long new_head;
-
-	if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len)
-		return -ENOBUFS;
-
-	gap	 = packets - 1;
-	new_head = ap->dccpap_buf_head - packets;
-
-	if (new_head < 0) {
-		if (gap > 0) {
-			memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED,
-			       gap + new_head + 1);
-			gap = -new_head;
-		}
-		new_head += ap->dccpap_buf_len;
-	} 
-
-	ap->dccpap_buf_head = new_head;
-
-	if (gap > 0)
-		memset(ap->dccpap_buf + ap->dccpap_buf_head + 1,
-		       DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap);
-
-	ap->dccpap_buf[ap->dccpap_buf_head] = state;
-	ap->dccpap_buf_vector_len += packets;
-	return 0;
-}
-
-/*
- * Implements the draft-ietf-dccp-spec-11.txt Appendix A
- */
-int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
-		     u64 ackno, u8 state)
-{
-	/*
-	 * Check at the right places if the buffer is full, if it is, tell the
-	 * caller to start dropping packets till the HC-Sender acks our ACK
-	 * vectors, when we will free up space in dccpap_buf.
-	 *
-	 * We may well decide to do buffer compression, etc, but for now lets
-	 * just drop.
-	 *
-	 * From Appendix A:
-	 *
-	 *	Of course, the circular buffer may overflow, either when the
-	 *	HC-Sender is sending data at a very high rate, when the
-	 *	HC-Receiver's acknowledgements are not reaching the HC-Sender,
-	 *	or when the HC-Sender is forgetting to acknowledge those acks
-	 *	(so the HC-Receiver is unable to clean up old state). In this
-	 *	case, the HC-Receiver should either compress the buffer (by
-	 *	increasing run lengths when possible), transfer its state to
-	 *	a larger buffer, or, as a last resort, drop all received
-	 *	packets, without processing them whatsoever, until its buffer
-	 *	shrinks again.
-	 */
-
-	/* See if this is the first ackno being inserted */
-	if (ap->dccpap_buf_vector_len == 0) {
-		ap->dccpap_buf[ap->dccpap_buf_head] = state;
-		ap->dccpap_buf_vector_len = 1;
-	} else if (after48(ackno, ap->dccpap_buf_ackno)) {
-		const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno,
-						   ackno);
-
-		/*
-		 * Look if the state of this packet is the same as the
-		 * previous ackno and if so if we can bump the head len.
-		 */
-		if (delta == 1 &&
-		    dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state &&
-		    (dccp_ackpkts_len(ap, ap->dccpap_buf_head) <
-		     DCCP_ACKPKTS_LEN_MASK))
-			ap->dccpap_buf[ap->dccpap_buf_head]++;
-		else if (dccp_ackpkts_set_buf_head_state(ap, delta, state))
-			return -ENOBUFS;
-	} else {
-		/*
-		 * A.1.2.  Old Packets
-		 *
-		 *	When a packet with Sequence Number S arrives, and
-		 *	S <= buf_ackno, the HC-Receiver will scan the table
-		 *	for the byte corresponding to S. (Indexing structures
-		 *	could reduce the complexity of this scan.)
-		 */
-		u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno);
-		unsigned int index = ap->dccpap_buf_head;
-
-		while (1) {
-			const u8 len = dccp_ackpkts_len(ap, index);
-			const u8 state = dccp_ackpkts_state(ap, index);
-			/*
-			 * valid packets not yet in dccpap_buf have a reserved
-			 * entry, with a len equal to 0.
-			 */
-			if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED &&
-			    len == 0 && delta == 0) { /* Found our
-							 reserved seat! */
-				dccp_pr_debug("Found %llu reserved seat!\n",
-					      (unsigned long long) ackno);
-				ap->dccpap_buf[index] = state;
-				goto out;
-			}
-			/* len == 0 means one packet */
-			if (delta < len + 1)
-				goto out_duplicate;
-
-			delta -= len + 1;
-			if (++index == ap->dccpap_buf_len)
-				index = 0;
-		}
-	}
-
-	ap->dccpap_buf_ackno = ackno;
-	dccp_timestamp(sk, &ap->dccpap_time);
-out:
-	dccp_pr_debug("");
-	dccp_ackpkts_print(ap);
-	return 0;
-
-out_duplicate:
-	/* Duplicate packet */
-	dccp_pr_debug("Received a dup or already considered lost "
-		      "packet: %llu\n", (unsigned long long) ackno);
-	return -EILSEQ;
-}
-
-#ifdef CONFIG_IP_DCCP_DEBUG
-void dccp_ackvector_print(const u64 ackno, const unsigned char *vector,
-			  int len)
-{
-	if (!dccp_debug)
-		return;
-
-	printk("ACK vector len=%d, ackno=%llu |", len,
-	       (unsigned long long) ackno);
-
-	while (len--) {
-		const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6;
-		const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
-
-		printk("%d,%d|", state, rl);
-		++vector;
-	}
-
-	printk("\n");
-}
-
-void dccp_ackpkts_print(const struct dccp_ackpkts *ap)
-{
-	dccp_ackvector_print(ap->dccpap_buf_ackno,
-			     ap->dccpap_buf + ap->dccpap_buf_head,
-			     ap->dccpap_buf_vector_len);
-}
-#endif
-
-static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap)
-{
-	/*
-	 * As we're keeping track of the ack vector size
-	 * (dccpap_buf_vector_len) and the sent ack vector size
-	 * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but
-	 * keep this code here as in the future we'll implement a vector of
-	 * ack records, as suggested in draft-ietf-dccp-spec-11.txt
-	 * Appendix A. -acme
-	 */
-#if 0
-	ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1;
-	if (ap->dccpap_buf_tail >= ap->dccpap_buf_len)
-		ap->dccpap_buf_tail -= ap->dccpap_buf_len;
-#endif
-	ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len;
-}
-
-void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk,
-				 u64 ackno)
-{
-	/* Check if we actually sent an ACK vector */
-	if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
-		return;
-
-	if (ackno == ap->dccpap_ack_seqno) {
-#ifdef CONFIG_IP_DCCP_DEBUG
-		struct dccp_sock *dp = dccp_sk(sk);
-		const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
-					"CLIENT rx ack: " : "server rx ack: ";
-#endif
-		dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
-			      "ack_ackno=%llu, ACKED!\n",
-			      debug_prefix, 1,
-			      (unsigned long long) ap->dccpap_ack_seqno,
-			      (unsigned long long) ap->dccpap_ack_ackno);
-		dccp_ackpkts_trow_away_ack_record(ap);
-		ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
-	}
-}
-
-static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
-					     struct sock *sk, u64 ackno,
-					     const unsigned char len,
-					     const unsigned char *vector)
-{
-	unsigned char i;
-
-	/* Check if we actually sent an ACK vector */
-	if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
-		return;
-	/*
-	 * We're in the receiver half connection, so if the received an ACK
-	 * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're
-	 * not interested.
-	 *
-	 * Extra explanation with example:
-	 * 
-	 * if we received an ACK vector with ackno 50, it can only be acking
-	 * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
-	 */
-	/* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */
-	if (before48(ackno, ap->dccpap_ack_seqno)) {
-		/* dccp_pr_debug_cat("yes\n"); */
-		return;
-	}
-	/* dccp_pr_debug_cat("no\n"); */
-
-	i = len;
-	while (i--) {
-		const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
-		u64 ackno_end_rl;
-
-		dccp_set_seqno(&ackno_end_rl, ackno - rl);
-
-		/*
-		 * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
-		 * ap->dccpap_ack_seqno, ackno);
-		 */
-		if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) {
-			const u8 state = (*vector &
-					  DCCP_ACKPKTS_STATE_MASK) >> 6;
-			/* dccp_pr_debug_cat("yes\n"); */
-
-			if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) {
-#ifdef CONFIG_IP_DCCP_DEBUG
-				struct dccp_sock *dp = dccp_sk(sk);
-				const char *debug_prefix =
-					dp->dccps_role == DCCP_ROLE_CLIENT ?
-					"CLIENT rx ack: " : "server rx ack: ";
-#endif
-				dccp_pr_debug("%sACK vector 0, len=%d, "
-					      "ack_seqno=%llu, ack_ackno=%llu, "
-					      "ACKED!\n",
-					      debug_prefix, len,
-					      (unsigned long long)
-					      ap->dccpap_ack_seqno,
-					      (unsigned long long)
-					      ap->dccpap_ack_ackno);
-				dccp_ackpkts_trow_away_ack_record(ap);
-			}
-			/*
-			 * If dccpap_ack_seqno was not received, no problem
-			 * we'll send another ACK vector.
-			 */
-			ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
-			break;
-		}
-		/* dccp_pr_debug_cat("no\n"); */
-
-		dccp_set_seqno(&ackno, ackno_end_rl - 1);
-		++vector;
-	}
-}
diff --git a/net/dccp/output.c b/net/dccp/output.c
index ea6d0e9..4786bdc 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -16,6 +16,7 @@
 
 #include <net/sock.h>
 
+#include "ackvec.h"
 #include "ccid.h"
 #include "dccp.h"
 
@@ -85,7 +86,7 @@
 		switch (dcb->dccpd_type) {
 		case DCCP_PKT_REQUEST:
 			dccp_hdr_request(skb)->dccph_req_service =
-							dcb->dccpd_service;
+							dp->dccps_service;
 			break;
 		case DCCP_PKT_RESET:
 			dccp_hdr_reset(skb)->dccph_reset_code =
@@ -225,7 +226,6 @@
 		err = dccp_wait_for_ccid(sk, skb, timeo);
 
 	if (err == 0) {
-		const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
 		struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
 		const int len = skb->len;
 
@@ -236,15 +236,7 @@
 						  inet_csk(sk)->icsk_rto,
 						  DCCP_RTO_MAX);
 			dcb->dccpd_type = DCCP_PKT_DATAACK;
-			/*
-			 * FIXME: we really should have a
-			 * dccps_ack_pending or use icsk.
-			 */
-		} else if (inet_csk_ack_scheduled(sk) ||
-			   dp->dccps_timestamp_echo != 0 ||
-			   (dp->dccps_options.dccpo_send_ack_vector &&
-			    ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 &&
-			    ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1))
+		} else if (dccp_ack_pending(sk))
 			dcb->dccpd_type = DCCP_PKT_DATAACK;
 		else
 			dcb->dccpd_type = DCCP_PKT_DATA;
@@ -270,6 +262,7 @@
 				   struct request_sock *req)
 {
 	struct dccp_hdr *dh;
+	struct dccp_request_sock *dreq;
 	const int dccp_header_size = sizeof(struct dccp_hdr) +
 				     sizeof(struct dccp_hdr_ext) +
 				     sizeof(struct dccp_hdr_response);
@@ -285,8 +278,9 @@
 	skb->dst = dst_clone(dst);
 	skb->csum = 0;
 
+	dreq = dccp_rsk(req);
 	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
-	DCCP_SKB_CB(skb)->dccpd_seq  = dccp_rsk(req)->dreq_iss;
+	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_iss;
 	dccp_insert_options(sk, skb);
 
 	skb->h.raw = skb_push(skb, dccp_header_size);
@@ -300,8 +294,9 @@
 			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
 	dh->dccph_type	= DCCP_PKT_RESPONSE;
 	dh->dccph_x	= 1;
-	dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss);
-	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr);
+	dccp_hdr_set_seq(dh, dreq->dreq_iss);
+	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
+	dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
 
 	dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr,
 					      inet_rsk(req)->rmt_addr);
@@ -397,9 +392,6 @@
 	skb_reserve(skb, MAX_DCCP_HEADER);
 
 	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
-	/* FIXME: set service to something meaningful, coming
-	 * from userspace*/
-	DCCP_SKB_CB(skb)->dccpd_service = 0;
 	skb->csum = 0;
 	skb_set_owner_w(skb, sk);
 
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 18a0e69..a1cfd0e 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -94,7 +94,15 @@
 
 static inline int dccp_listen_start(struct sock *sk)
 {
-	dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN;
+	struct dccp_sock *dp = dccp_sk(sk);
+
+	dp->dccps_role = DCCP_ROLE_LISTEN;
+	/*
+	 * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE)
+	 * before calling listen()
+	 */
+	if (dccp_service_not_initialized(sk))
+		return -EPROTO;
 	return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE);
 }
 
@@ -202,6 +210,42 @@
 	return -ENOIOCTLCMD;
 }
 
+static int dccp_setsockopt_service(struct sock *sk, const u32 service,
+				   char __user *optval, int optlen)
+{
+	struct dccp_sock *dp = dccp_sk(sk);
+	struct dccp_service_list *sl = NULL;
+
+	if (service == DCCP_SERVICE_INVALID_VALUE || 
+	    optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32))
+		return -EINVAL;
+
+	if (optlen > sizeof(service)) {
+		sl = kmalloc(optlen, GFP_KERNEL);
+		if (sl == NULL)
+			return -ENOMEM;
+
+		sl->dccpsl_nr = optlen / sizeof(u32) - 1;
+		if (copy_from_user(sl->dccpsl_list,
+				   optval + sizeof(service),
+				   optlen - sizeof(service)) ||
+		    dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) {
+			kfree(sl);
+			return -EFAULT;
+		}
+	}
+
+	lock_sock(sk);
+	dp->dccps_service = service;
+
+	if (dp->dccps_service_list != NULL)
+		kfree(dp->dccps_service_list);
+
+	dp->dccps_service_list = sl;
+	release_sock(sk);
+	return 0;
+}
+
 int dccp_setsockopt(struct sock *sk, int level, int optname,
 		    char __user *optval, int optlen)
 {
@@ -218,8 +262,10 @@
 	if (get_user(val, (int __user *)optval))
 		return -EFAULT;
 
-	lock_sock(sk);
+	if (optname == DCCP_SOCKOPT_SERVICE)
+		return dccp_setsockopt_service(sk, val, optval, optlen);
 
+	lock_sock(sk);
 	dp = dccp_sk(sk);
 	err = 0;
 
@@ -236,6 +282,37 @@
 	return err;
 }
 
+static int dccp_getsockopt_service(struct sock *sk, int len,
+				   u32 __user *optval,
+				   int __user *optlen)
+{
+	const struct dccp_sock *dp = dccp_sk(sk);
+	const struct dccp_service_list *sl;
+	int err = -ENOENT, slen = 0, total_len = sizeof(u32);
+
+	lock_sock(sk);
+	if (dccp_service_not_initialized(sk))
+		goto out;
+
+	if ((sl = dp->dccps_service_list) != NULL) {
+		slen = sl->dccpsl_nr * sizeof(u32);
+		total_len += slen;
+	}
+
+	err = -EINVAL;
+	if (total_len > len)
+		goto out;
+
+	err = 0;
+	if (put_user(total_len, optlen) ||
+	    put_user(dp->dccps_service, optval) ||
+	    (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen)))
+		err = -EFAULT;
+out:
+	release_sock(sk);
+	return err;
+}
+
 int dccp_getsockopt(struct sock *sk, int level, int optname,
 		    char __user *optval, int __user *optlen)
 {
@@ -248,8 +325,7 @@
 	if (get_user(len, optlen))
 		return -EFAULT;
 
-	len = min_t(unsigned int, len, sizeof(int));
-	if (len < 0)
+	if (len < sizeof(int))
 		return -EINVAL;
 
 	dp = dccp_sk(sk);
@@ -257,7 +333,17 @@
 	switch (optname) {
 	case DCCP_SOCKOPT_PACKET_SIZE:
 		val = dp->dccps_packet_size;
+		len = sizeof(dp->dccps_packet_size);
 		break;
+	case DCCP_SOCKOPT_SERVICE:
+		return dccp_getsockopt_service(sk, len,
+					       (u32 __user *)optval, optlen);
+	case 128 ... 191:
+		return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
+					     len, (u32 __user *)optval, optlen);
+	case 192 ... 255:
+		return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname,
+					     len, (u32 __user *)optval, optlen);
 	default:
 		return -ENOPROTOOPT;
 	}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1b63b48..90ae708 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#define VERSION "0.403"
+#define VERSION "0.404"
 
 #include <linux/config.h>
 #include <asm/uaccess.h>
@@ -224,7 +224,7 @@
   Consider a node 'n' and its parent 'tp'.
 
   If n is a leaf, every bit in its key is significant. Its presence is 
-  necessitaded by path compression, since during a tree traversal (when 
+  necessitated by path compression, since during a tree traversal (when 
   searching for a leaf - unless we are doing an insertion) we will completely 
   ignore all skipped bits we encounter. Thus we need to verify, at the end of 
   a potentially successful search, that we have indeed been walking the 
@@ -836,11 +836,12 @@
 #endif
 }
 
-/* readside most use rcu_read_lock currently dump routines
+/* readside must use rcu_read_lock currently dump routines
  via get_fa_head and dump */
 
-static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
+static struct leaf_info *find_leaf_info(struct leaf *l, int plen)
 {
+	struct hlist_head *head = &l->list;
 	struct hlist_node *node;
 	struct leaf_info *li;
 
@@ -853,7 +854,7 @@
 
 static inline struct list_head * get_fa_head(struct leaf *l, int plen)
 {
-	struct leaf_info *li = find_leaf_info(&l->list, plen);
+	struct leaf_info *li = find_leaf_info(l, plen);
 
 	if (!li)
 		return NULL;
@@ -1248,7 +1249,7 @@
 }
 
 
-/* should be clalled with rcu_read_lock */
+/* should be called with rcu_read_lock */
 static inline int check_leaf(struct trie *t, struct leaf *l,
 			     t_key key, int *plen, const struct flowi *flp,
 			     struct fib_result *res)
@@ -1590,7 +1591,7 @@
 	rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
 
 	l = fib_find_node(t, key);
-	li = find_leaf_info(&l->list, plen);
+	li = find_leaf_info(l, plen);
 
 	list_del_rcu(&fa->fa_list);
 
@@ -1714,7 +1715,6 @@
 
 	t->revision++;
 
-	rcu_read_lock();
 	for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
 		found += trie_flush_leaf(t, l);
 
@@ -1722,7 +1722,6 @@
 			trie_leaf_remove(t, ll->key);
 		ll = l;
 	}
-	rcu_read_unlock();  
 
 	if (ll && hlist_empty(&ll->list))
 		trie_leaf_remove(t, ll->key);
@@ -2029,7 +2028,7 @@
 		iter->tnode = (struct tnode *) n;
 		iter->trie = t;
 		iter->index = 0;
-		iter->depth = 0;
+		iter->depth = 1;
 		return n;
 	}
 	return NULL;
@@ -2274,11 +2273,12 @@
 				seq_puts(seq, "<local>:\n");
 			else
 				seq_puts(seq, "<main>:\n");
-		} else {
-			seq_indent(seq, iter->depth-1);
-			seq_printf(seq, "  +-- %d.%d.%d.%d/%d\n",
-				   NIPQUAD(prf), tn->pos);
-		}
+		} 
+		seq_indent(seq, iter->depth-1);
+		seq_printf(seq, "  +-- %d.%d.%d.%d/%d %d %d %d\n",
+			   NIPQUAD(prf), tn->pos, tn->bits, tn->full_children, 
+			   tn->empty_children);
+		
 	} else {
 		struct leaf *l = (struct leaf *) n;
 		int i;
@@ -2287,7 +2287,7 @@
 		seq_indent(seq, iter->depth);
 		seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
 		for (i = 32; i >= 0; i--) {
-			struct leaf_info *li = find_leaf_info(&l->list, i);
+			struct leaf_info *li = find_leaf_info(l, i);
 			if (li) {
 				struct fib_alias *fa;
 				list_for_each_entry_rcu(fa, &li->falh, fa_list) {
@@ -2383,7 +2383,7 @@
 		return 0;
 
 	for (i=32; i>=0; i--) {
-		struct leaf_info *li = find_leaf_info(&l->list, i);
+		struct leaf_info *li = find_leaf_info(l, i);
 		struct fib_alias *fa;
 		u32 mask, prefix;
 
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 44607f4..70c44e4 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1603,7 +1603,7 @@
 	}
 	pmc->sources = NULL;
 	pmc->sfmode = MCAST_EXCLUDE;
-	pmc->sfcount[MCAST_EXCLUDE] = 0;
+	pmc->sfcount[MCAST_INCLUDE] = 0;
 	pmc->sfcount[MCAST_EXCLUDE] = 1;
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index e11952e..f828fa2 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -196,6 +196,7 @@
 	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
 		if (s_addr==cp->caddr && s_port==cp->cport &&
 		    d_port==cp->vport && d_addr==cp->vaddr &&
+		    ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
 		    protocol==cp->protocol) {
 			/* HIT */
 			atomic_inc(&cp->refcnt);
@@ -227,6 +228,40 @@
 	return cp;
 }
 
+/* Get reference to connection template */
+struct ip_vs_conn *ip_vs_ct_in_get
+(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+	unsigned hash;
+	struct ip_vs_conn *cp;
+
+	hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
+
+	ct_read_lock(hash);
+
+	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+		if (s_addr==cp->caddr && s_port==cp->cport &&
+		    d_port==cp->vport && d_addr==cp->vaddr &&
+		    cp->flags & IP_VS_CONN_F_TEMPLATE &&
+		    protocol==cp->protocol) {
+			/* HIT */
+			atomic_inc(&cp->refcnt);
+			goto out;
+		}
+	}
+	cp = NULL;
+
+  out:
+	ct_read_unlock(hash);
+
+	IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
+		  ip_vs_proto_name(protocol),
+		  NIPQUAD(s_addr), ntohs(s_port),
+		  NIPQUAD(d_addr), ntohs(d_port),
+		  cp?"hit":"not hit");
+
+	return cp;
+}
 
 /*
  *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
@@ -367,7 +402,7 @@
 		  atomic_read(&dest->refcnt));
 
 	/* Update the connection counters */
-	if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+	if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
 		/* It is a normal connection, so increase the inactive
 		   connection counter because it is in TCP SYNRECV
 		   state (inactive) or other protocol inacive state */
@@ -406,7 +441,7 @@
 		  atomic_read(&dest->refcnt));
 
 	/* Update the connection counters */
-	if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+	if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
 		/* It is a normal connection, so decrease the inactconns
 		   or activeconns counter */
 		if (cp->flags & IP_VS_CONN_F_INACTIVE) {
@@ -467,7 +502,7 @@
 		/*
 		 * Invalidate the connection template
 		 */
-		if (ct->cport) {
+		if (ct->vport != 65535) {
 			if (ip_vs_conn_unhash(ct)) {
 				ct->dport = 65535;
 				ct->vport = 65535;
@@ -776,7 +811,7 @@
 		ct_write_lock_bh(hash);
 
 		list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
-			if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT))
+			if (cp->flags & IP_VS_CONN_F_TEMPLATE)
 				/* connection template */
 				continue;
 
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 3ac7eec..981cc32 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -243,10 +243,10 @@
 	if (ports[1] == svc->port) {
 		/* Check if a template already exists */
 		if (svc->port != FTPPORT)
-			ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+			ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
 					       iph->daddr, ports[1]);
 		else
-			ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+			ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
 					       iph->daddr, 0);
 
 		if (!ct || !ip_vs_check_template(ct)) {
@@ -272,14 +272,14 @@
 						    iph->daddr,
 						    ports[1],
 						    dest->addr, dest->port,
-						    0,
+						    IP_VS_CONN_F_TEMPLATE,
 						    dest);
 			else
 				ct = ip_vs_conn_new(iph->protocol,
 						    snet, 0,
 						    iph->daddr, 0,
 						    dest->addr, 0,
-						    0,
+						    IP_VS_CONN_F_TEMPLATE,
 						    dest);
 			if (ct == NULL)
 				return NULL;
@@ -298,10 +298,10 @@
 		 * port zero template: <protocol,caddr,0,vaddr,0,daddr,0>
 		 */
 		if (svc->fwmark)
-			ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0,
+			ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0,
 					       htonl(svc->fwmark), 0);
 		else
-			ct = ip_vs_conn_in_get(iph->protocol, snet, 0,
+			ct = ip_vs_ct_in_get(iph->protocol, snet, 0,
 					       iph->daddr, 0);
 
 		if (!ct || !ip_vs_check_template(ct)) {
@@ -326,14 +326,14 @@
 						    snet, 0,
 						    htonl(svc->fwmark), 0,
 						    dest->addr, 0,
-						    0,
+						    IP_VS_CONN_F_TEMPLATE,
 						    dest);
 			else
 				ct = ip_vs_conn_new(iph->protocol,
 						    snet, 0,
 						    iph->daddr, 0,
 						    dest->addr, 0,
-						    0,
+						    IP_VS_CONN_F_TEMPLATE,
 						    dest);
 			if (ct == NULL)
 				return NULL;
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 574d1f5..2e5ced3 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -297,16 +297,24 @@
 
 	p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
 	for (i=0; i<m->nr_conns; i++) {
+		unsigned flags;
+
 		s = (struct ip_vs_sync_conn *)p;
-		cp = ip_vs_conn_in_get(s->protocol,
-				       s->caddr, s->cport,
-				       s->vaddr, s->vport);
+		flags = ntohs(s->flags);
+		if (!(flags & IP_VS_CONN_F_TEMPLATE))
+			cp = ip_vs_conn_in_get(s->protocol,
+					       s->caddr, s->cport,
+					       s->vaddr, s->vport);
+		else
+			cp = ip_vs_ct_in_get(s->protocol,
+					       s->caddr, s->cport,
+					       s->vaddr, s->vport);
 		if (!cp) {
 			cp = ip_vs_conn_new(s->protocol,
 					    s->caddr, s->cport,
 					    s->vaddr, s->vport,
 					    s->daddr, s->dport,
-					    ntohs(s->flags), NULL);
+					    flags, NULL);
 			if (!cp) {
 				IP_VS_ERR("ip_vs_conn_new failed\n");
 				return;
@@ -315,11 +323,11 @@
 		} else if (!cp->dest) {
 			/* it is an entry created by the synchronization */
 			cp->state = ntohs(s->state);
-			cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED;
+			cp->flags = flags | IP_VS_CONN_F_HASHED;
 		}	/* Note that we don't touch its state and flags
 			   if it is a normal entry. */
 
-		if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) {
+		if (flags & IP_VS_CONN_F_SEQ_MASK) {
 			opt = (struct ip_vs_sync_conn_options *)&s[1];
 			memcpy(&cp->in_seq, opt, sizeof(*opt));
 			p += FULL_CONN_SIZE;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 30aa8e2..3cf9b45 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -51,6 +51,14 @@
 	  
 	  IF unsure, say `N'.
 
+config IP_NF_CONNTRACK_NETLINK
+	tristate 'Connection tracking netlink interface'
+	depends on IP_NF_CONNTRACK && NETFILTER_NETLINK
+	depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+	help
+	  This option enables support for a netlink-based userspace interface
+
+
 config IP_NF_CT_PROTO_SCTP
 	tristate  'SCTP protocol connection tracking support (EXPERIMENTAL)'
 	depends on IP_NF_CONNTRACK && EXPERIMENTAL
@@ -129,6 +137,22 @@
 
 	  To compile it as a module, choose M here.  If unsure, say Y.
 
+config IP_NF_PPTP
+	tristate  'PPTP protocol support'
+	help
+	  This module adds support for PPTP (Point to Point Tunnelling
+	  Protocol, RFC2637) conncection tracking and NAT. 
+	
+	  If you are running PPTP sessions over a stateful firewall or NAT
+	  box, you may want to enable this feature.  
+	
+	  Please note that not all PPTP modes of operation are supported yet.
+	  For more info, read top of the file
+	  net/ipv4/netfilter/ip_conntrack_pptp.c
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
 config IP_NF_QUEUE
 	tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
 	help
@@ -613,6 +637,12 @@
 	default IP_NF_NAT if IP_NF_AMANDA=y
 	default m if IP_NF_AMANDA=m
 
+config IP_NF_NAT_PPTP
+	tristate
+	depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
+	default IP_NF_NAT if IP_NF_PPTP=y
+	default m if IP_NF_PPTP=m
+
 # mangle + specific targets
 config IP_NF_MANGLE
 	tristate "Packet mangling"
@@ -774,11 +804,5 @@
 	  Allows altering the ARP packet payload: source and destination
 	  hardware and network addresses.
 
-config IP_NF_CONNTRACK_NETLINK
-        tristate 'Connection tracking netlink interface'
-        depends on IP_NF_CONNTRACK && NETFILTER_NETLINK
-        help
-          This option enables support for a netlink-based userspace interface
-
 endmenu
 
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 1ba0db7..3d45d3c 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -6,6 +6,9 @@
 ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
 iptable_nat-objs	:= ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
 
+ip_conntrack_pptp-objs	:= ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
+ip_nat_pptp-objs	:= ip_nat_helper_pptp.o ip_nat_proto_gre.o
+
 # connection tracking
 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
 
@@ -17,6 +20,7 @@
 obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
 
 # connection tracking helpers
+obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
@@ -24,6 +28,7 @@
 obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
 
 # NAT helpers 
+obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 19cba16..c1f82e0 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -233,7 +233,7 @@
 
 /* Just find a expectation corresponding to a tuple. */
 struct ip_conntrack_expect *
-ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
+ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
 {
 	struct ip_conntrack_expect *i;
 	
@@ -1143,7 +1143,10 @@
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
-			ip_conntrack_event_cache(IPCT_REFRESH, skb);
+			/* FIXME: We loose some REFRESH events if this function
+			 * is called without an skb.  I'll fix this later -HW */
+			if (skb)
+				ip_conntrack_event_cache(IPCT_REFRESH, skb);
 		}
 		ct_add_counters(ct, ctinfo, skb);
 		write_unlock_bh(&ip_conntrack_lock);
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_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
new file mode 100644
index 0000000..79db5b7
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -0,0 +1,805 @@
+/*
+ * ip_conntrack_pptp.c	- Version 3.0
+ *
+ * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft.  PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * Limitations:
+ * 	 - We blindly assume that control connections are always
+ * 	   established in PNS->PAC direction.  This is a violation
+ * 	   of RFFC2673
+ * 	 - We can only support one single call within each session
+ *
+ * TODO:
+ *	 - testing of incoming PPTP calls 
+ *
+ * Changes: 
+ * 	2002-02-05 - Version 1.3
+ * 	  - Call ip_conntrack_unexpect_related() from 
+ * 	    pptp_destroy_siblings() to destroy expectations in case
+ * 	    CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
+ * 	    (Philip Craig <philipc@snapgear.com>)
+ * 	  - Add Version information at module loadtime
+ * 	2002-02-10 - Version 1.6
+ * 	  - move to C99 style initializers
+ * 	  - remove second expectation if first arrives
+ * 	2004-10-22 - Version 2.0
+ * 	  - merge Mandrake's 2.6.x port with recent 2.6.x API changes
+ * 	  - fix lots of linear skb assumptions from Mandrake's port
+ * 	2005-06-10 - Version 2.1
+ * 	  - use ip_conntrack_expect_free() instead of kfree() on the
+ * 	    expect's (which are from the slab for quite some time)
+ * 	2005-06-10 - Version 3.0
+ * 	  - port helper to post-2.6.11 API changes,
+ * 	    funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
+ * 	2005-07-30 - Version 3.1
+ * 	  - port helper to 2.6.13 API changes
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+#define IP_CT_PPTP_VERSION "3.1"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
+
+static DEFINE_SPINLOCK(ip_pptp_lock);
+
+int
+(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
+			  struct ip_conntrack *ct,
+			  enum ip_conntrack_info ctinfo,
+			  struct PptpControlHeader *ctlh,
+			  union pptp_ctrl_union *pptpReq);
+
+int
+(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
+			    struct ip_conntrack_expect *expect_reply);
+
+void
+(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp);
+
+#if 0
+/* PptpControlMessageType names */
+const char *pptp_msg_name[] = {
+	"UNKNOWN_MESSAGE",
+	"START_SESSION_REQUEST",
+	"START_SESSION_REPLY",
+	"STOP_SESSION_REQUEST",
+	"STOP_SESSION_REPLY",
+	"ECHO_REQUEST",
+	"ECHO_REPLY",
+	"OUT_CALL_REQUEST",
+	"OUT_CALL_REPLY",
+	"IN_CALL_REQUEST",
+	"IN_CALL_REPLY",
+	"IN_CALL_CONNECT",
+	"CALL_CLEAR_REQUEST",
+	"CALL_DISCONNECT_NOTIFY",
+	"WAN_ERROR_NOTIFY",
+	"SET_LINK_INFO"
+};
+EXPORT_SYMBOL(pptp_msg_name);
+#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define SECS *HZ
+#define MINS * 60 SECS
+#define HOURS * 60 MINS
+
+#define PPTP_GRE_TIMEOUT 		(10 MINS)
+#define PPTP_GRE_STREAM_TIMEOUT 	(5 HOURS)
+
+static void pptp_expectfn(struct ip_conntrack *ct,
+			 struct ip_conntrack_expect *exp)
+{
+	DEBUGP("increasing timeouts\n");
+
+	/* increase timeout of GRE data channel conntrack entry */
+	ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
+	ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
+
+	/* Can you see how rusty this code is, compared with the pre-2.6.11
+	 * one? That's what happened to my shiny newnat of 2002 ;( -HW */
+
+	if (!ip_nat_pptp_hook_expectfn) {
+		struct ip_conntrack_tuple inv_t;
+		struct ip_conntrack_expect *exp_other;
+
+		/* obviously this tuple inversion only works until you do NAT */
+		invert_tuplepr(&inv_t, &exp->tuple);
+		DEBUGP("trying to unexpect other dir: ");
+		DUMP_TUPLE(&inv_t);
+	
+		exp_other = ip_conntrack_expect_find(&inv_t);
+		if (exp_other) {
+			/* delete other expectation.  */
+			DEBUGP("found\n");
+			ip_conntrack_unexpect_related(exp_other);
+			ip_conntrack_expect_put(exp_other);
+		} else {
+			DEBUGP("not found\n");
+		}
+	} else {
+		/* we need more than simple inversion */
+		ip_nat_pptp_hook_expectfn(ct, exp);
+	}
+}
+
+static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
+{
+	struct ip_conntrack_tuple_hash *h;
+	struct ip_conntrack_expect *exp;
+
+	DEBUGP("trying to timeout ct or exp for tuple ");
+	DUMP_TUPLE(t);
+
+	h = ip_conntrack_find_get(t, NULL);
+	if (h)  {
+		struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
+		DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+		sibling->proto.gre.timeout = 0;
+		sibling->proto.gre.stream_timeout = 0;
+		/* refresh_acct will not modify counters if skb == NULL */
+		if (del_timer(&sibling->timeout))
+			sibling->timeout.function((unsigned long)sibling);
+		ip_conntrack_put(sibling);
+		return 1;
+	} else {
+		exp = ip_conntrack_expect_find(t);
+		if (exp) {
+			DEBUGP("unexpect_related of expect %p\n", exp);
+			ip_conntrack_unexpect_related(exp);
+			ip_conntrack_expect_put(exp);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+/* timeout GRE data connections */
+static void pptp_destroy_siblings(struct ip_conntrack *ct)
+{
+	struct ip_conntrack_tuple t;
+
+	/* Since ct->sibling_list has literally rusted away in 2.6.11, 
+	 * we now need another way to find out about our sibling
+	 * contrack and expects... -HW */
+
+	/* try original (pns->pac) tuple */
+	memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
+	t.dst.protonum = IPPROTO_GRE;
+	t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+	t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+
+	if (!destroy_sibling_or_exp(&t))
+		DEBUGP("failed to timeout original pns->pac ct/exp\n");
+
+	/* try reply (pac->pns) tuple */
+	memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
+	t.dst.protonum = IPPROTO_GRE;
+	t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
+	t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
+
+	if (!destroy_sibling_or_exp(&t))
+		DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+}
+
+/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
+static inline int
+exp_gre(struct ip_conntrack *master,
+	u_int32_t seq,
+	u_int16_t callid,
+	u_int16_t peer_callid)
+{
+	struct ip_conntrack_tuple inv_tuple;
+	struct ip_conntrack_tuple exp_tuples[] = {
+		/* tuple in original direction, PNS->PAC */
+		{ .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
+			   .u = { .gre = { .key = peer_callid } }
+			 },
+		  .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
+			   .u = { .gre = { .key = callid } },
+			   .protonum = IPPROTO_GRE
+			 },
+		 },
+		/* tuple in reply direction, PAC->PNS */
+		{ .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
+			   .u = { .gre = { .key = callid } }
+			 },
+		  .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
+			   .u = { .gre = { .key = peer_callid } },
+			   .protonum = IPPROTO_GRE
+			 },
+		 }
+	};
+	struct ip_conntrack_expect *exp_orig, *exp_reply;
+	int ret = 1;
+
+	exp_orig = ip_conntrack_expect_alloc(master);
+	if (exp_orig == NULL)
+		goto out;
+
+	exp_reply = ip_conntrack_expect_alloc(master);
+	if (exp_reply == NULL)
+		goto out_put_orig;
+
+	memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
+
+	exp_orig->mask.src.ip = 0xffffffff;
+	exp_orig->mask.src.u.all = 0;
+	exp_orig->mask.dst.u.all = 0;
+	exp_orig->mask.dst.u.gre.key = 0xffff;
+	exp_orig->mask.dst.ip = 0xffffffff;
+	exp_orig->mask.dst.protonum = 0xff;
+		
+	exp_orig->master = master;
+	exp_orig->expectfn = pptp_expectfn;
+	exp_orig->flags = 0;
+
+	exp_orig->dir = IP_CT_DIR_ORIGINAL;
+
+	/* both expectations are identical apart from tuple */
+	memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
+	memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple));
+
+	exp_reply->dir = !exp_orig->dir;
+
+	if (ip_nat_pptp_hook_exp_gre)
+		ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
+	else {
+
+		DEBUGP("calling expect_related PNS->PAC");
+		DUMP_TUPLE(&exp_orig->tuple);
+
+		if (ip_conntrack_expect_related(exp_orig) != 0) {
+			DEBUGP("cannot expect_related()\n");
+			goto out_put_both;
+		}
+
+		DEBUGP("calling expect_related PAC->PNS");
+		DUMP_TUPLE(&exp_reply->tuple);
+
+		if (ip_conntrack_expect_related(exp_reply) != 0) {
+			DEBUGP("cannot expect_related()\n");
+			goto out_unexpect_orig;
+		}
+
+		/* Add GRE keymap entries */
+		if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
+			DEBUGP("cannot keymap_add() exp\n");
+			goto out_unexpect_both;
+		}
+
+		invert_tuplepr(&inv_tuple, &exp_reply->tuple);
+		if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
+			ip_ct_gre_keymap_destroy(master);
+			DEBUGP("cannot keymap_add() exp_inv\n");
+			goto out_unexpect_both;
+		}
+		ret = 0;
+	}
+
+out_put_both:
+	ip_conntrack_expect_put(exp_reply);
+out_put_orig:
+	ip_conntrack_expect_put(exp_orig);
+out:
+	return ret;
+
+out_unexpect_both:
+	ip_conntrack_unexpect_related(exp_reply);
+out_unexpect_orig:
+	ip_conntrack_unexpect_related(exp_orig);
+	goto out_put_both;
+}
+
+static inline int 
+pptp_inbound_pkt(struct sk_buff **pskb,
+		 struct tcphdr *tcph,
+		 unsigned int nexthdr_off,
+		 unsigned int datalen,
+		 struct ip_conntrack *ct,
+		 enum ip_conntrack_info ctinfo)
+{
+	struct PptpControlHeader _ctlh, *ctlh;
+	unsigned int reqlen;
+	union pptp_ctrl_union _pptpReq, *pptpReq;
+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+	u_int16_t msg, *cid, *pcid;
+	u_int32_t seq;	
+
+	ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+	if (!ctlh) {
+		DEBUGP("error during skb_header_pointer\n");
+		return NF_ACCEPT;
+	}
+	nexthdr_off += sizeof(_ctlh);
+	datalen -= sizeof(_ctlh);
+
+	reqlen = datalen;
+	if (reqlen > sizeof(*pptpReq))
+		reqlen = sizeof(*pptpReq);
+	pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+	if (!pptpReq) {
+		DEBUGP("error during skb_header_pointer\n");
+		return NF_ACCEPT;
+	}
+
+	msg = ntohs(ctlh->messageType);
+	DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+
+	switch (msg) {
+	case PPTP_START_SESSION_REPLY:
+		if (reqlen < sizeof(_pptpReq.srep)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server confirms new control session */
+		if (info->sstate < PPTP_SESSION_REQUESTED) {
+			DEBUGP("%s without START_SESS_REQUEST\n",
+				pptp_msg_name[msg]);
+			break;
+		}
+		if (pptpReq->srep.resultCode == PPTP_START_OK)
+			info->sstate = PPTP_SESSION_CONFIRMED;
+		else 
+			info->sstate = PPTP_SESSION_ERROR;
+		break;
+
+	case PPTP_STOP_SESSION_REPLY:
+		if (reqlen < sizeof(_pptpReq.strep)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server confirms end of control session */
+		if (info->sstate > PPTP_SESSION_STOPREQ) {
+			DEBUGP("%s without STOP_SESS_REQUEST\n",
+				pptp_msg_name[msg]);
+			break;
+		}
+		if (pptpReq->strep.resultCode == PPTP_STOP_OK)
+			info->sstate = PPTP_SESSION_NONE;
+		else
+			info->sstate = PPTP_SESSION_ERROR;
+		break;
+
+	case PPTP_OUT_CALL_REPLY:
+		if (reqlen < sizeof(_pptpReq.ocack)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server accepted call, we now expect GRE frames */
+		if (info->sstate != PPTP_SESSION_CONFIRMED) {
+			DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+			break;
+		}
+		if (info->cstate != PPTP_CALL_OUT_REQ &&
+		    info->cstate != PPTP_CALL_OUT_CONF) {
+			DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]);
+			break;
+		}
+		if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {
+			info->cstate = PPTP_CALL_NONE;
+			break;
+		}
+
+		cid = &pptpReq->ocack.callID;
+		pcid = &pptpReq->ocack.peersCallID;
+
+		info->pac_call_id = ntohs(*cid);
+		
+		if (htons(info->pns_call_id) != *pcid) {
+			DEBUGP("%s for unknown callid %u\n",
+				pptp_msg_name[msg], ntohs(*pcid));
+			break;
+		}
+
+		DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], 
+			ntohs(*cid), ntohs(*pcid));
+		
+		info->cstate = PPTP_CALL_OUT_CONF;
+
+		seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+				       + sizeof(struct PptpControlHeader)
+				       + ((void *)pcid - (void *)pptpReq);
+			
+		if (exp_gre(ct, seq, *cid, *pcid) != 0)
+			printk("ip_conntrack_pptp: error during exp_gre\n");
+		break;
+
+	case PPTP_IN_CALL_REQUEST:
+		if (reqlen < sizeof(_pptpReq.icack)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server tells us about incoming call request */
+		if (info->sstate != PPTP_SESSION_CONFIRMED) {
+			DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+			break;
+		}
+		pcid = &pptpReq->icack.peersCallID;
+		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+		info->cstate = PPTP_CALL_IN_REQ;
+		info->pac_call_id = ntohs(*pcid);
+		break;
+
+	case PPTP_IN_CALL_CONNECT:
+		if (reqlen < sizeof(_pptpReq.iccon)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server tells us about incoming call established */
+		if (info->sstate != PPTP_SESSION_CONFIRMED) {
+			DEBUGP("%s but no session\n", pptp_msg_name[msg]);
+			break;
+		}
+		if (info->sstate != PPTP_CALL_IN_REP
+		    && info->sstate != PPTP_CALL_IN_CONF) {
+			DEBUGP("%s but never sent IN_CALL_REPLY\n",
+				pptp_msg_name[msg]);
+			break;
+		}
+
+		pcid = &pptpReq->iccon.peersCallID;
+		cid = &info->pac_call_id;
+
+		if (info->pns_call_id != ntohs(*pcid)) {
+			DEBUGP("%s for unknown CallID %u\n", 
+				pptp_msg_name[msg], ntohs(*cid));
+			break;
+		}
+
+		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+		info->cstate = PPTP_CALL_IN_CONF;
+
+		/* we expect a GRE connection from PAC to PNS */
+		seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+				       + sizeof(struct PptpControlHeader)
+				       + ((void *)pcid - (void *)pptpReq);
+			
+		if (exp_gre(ct, seq, *cid, *pcid) != 0)
+			printk("ip_conntrack_pptp: error during exp_gre\n");
+
+		break;
+
+	case PPTP_CALL_DISCONNECT_NOTIFY:
+		if (reqlen < sizeof(_pptpReq.disc)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* server confirms disconnect */
+		cid = &pptpReq->disc.callID;
+		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+		info->cstate = PPTP_CALL_NONE;
+
+		/* untrack this call id, unexpect GRE packets */
+		pptp_destroy_siblings(ct);
+		break;
+
+	case PPTP_WAN_ERROR_NOTIFY:
+		break;
+
+	case PPTP_ECHO_REQUEST:
+	case PPTP_ECHO_REPLY:
+		/* I don't have to explain these ;) */
+		break;
+	default:
+		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
+			? pptp_msg_name[msg]:pptp_msg_name[0], msg);
+		break;
+	}
+
+
+	if (ip_nat_pptp_hook_inbound)
+		return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
+						pptpReq);
+
+	return NF_ACCEPT;
+
+}
+
+static inline int
+pptp_outbound_pkt(struct sk_buff **pskb,
+		  struct tcphdr *tcph,
+		  unsigned int nexthdr_off,
+		  unsigned int datalen,
+		  struct ip_conntrack *ct,
+		  enum ip_conntrack_info ctinfo)
+{
+	struct PptpControlHeader _ctlh, *ctlh;
+	unsigned int reqlen;
+	union pptp_ctrl_union _pptpReq, *pptpReq;
+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+	u_int16_t msg, *cid, *pcid;
+
+	ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
+	if (!ctlh)
+		return NF_ACCEPT;
+	nexthdr_off += sizeof(_ctlh);
+	datalen -= sizeof(_ctlh);
+	
+	reqlen = datalen;
+	if (reqlen > sizeof(*pptpReq))
+		reqlen = sizeof(*pptpReq);
+	pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
+	if (!pptpReq)
+		return NF_ACCEPT;
+
+	msg = ntohs(ctlh->messageType);
+	DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+
+	switch (msg) {
+	case PPTP_START_SESSION_REQUEST:
+		/* client requests for new control session */
+		if (info->sstate != PPTP_SESSION_NONE) {
+			DEBUGP("%s but we already have one",
+				pptp_msg_name[msg]);
+		}
+		info->sstate = PPTP_SESSION_REQUESTED;
+		break;
+	case PPTP_STOP_SESSION_REQUEST:
+		/* client requests end of control session */
+		info->sstate = PPTP_SESSION_STOPREQ;
+		break;
+
+	case PPTP_OUT_CALL_REQUEST:
+		if (reqlen < sizeof(_pptpReq.ocreq)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			/* FIXME: break; */
+		}
+
+		/* client initiating connection to server */
+		if (info->sstate != PPTP_SESSION_CONFIRMED) {
+			DEBUGP("%s but no session\n",
+				pptp_msg_name[msg]);
+			break;
+		}
+		info->cstate = PPTP_CALL_OUT_REQ;
+		/* track PNS call id */
+		cid = &pptpReq->ocreq.callID;
+		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
+		info->pns_call_id = ntohs(*cid);
+		break;
+	case PPTP_IN_CALL_REPLY:
+		if (reqlen < sizeof(_pptpReq.icack)) {
+			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
+			break;
+		}
+
+		/* client answers incoming call */
+		if (info->cstate != PPTP_CALL_IN_REQ
+		    && info->cstate != PPTP_CALL_IN_REP) {
+			DEBUGP("%s without incall_req\n", 
+				pptp_msg_name[msg]);
+			break;
+		}
+		if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {
+			info->cstate = PPTP_CALL_NONE;
+			break;
+		}
+		pcid = &pptpReq->icack.peersCallID;
+		if (info->pac_call_id != ntohs(*pcid)) {
+			DEBUGP("%s for unknown call %u\n", 
+				pptp_msg_name[msg], ntohs(*pcid));
+			break;
+		}
+		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
+		/* part two of the three-way handshake */
+		info->cstate = PPTP_CALL_IN_REP;
+		info->pns_call_id = ntohs(pptpReq->icack.callID);
+		break;
+
+	case PPTP_CALL_CLEAR_REQUEST:
+		/* client requests hangup of call */
+		if (info->sstate != PPTP_SESSION_CONFIRMED) {
+			DEBUGP("CLEAR_CALL but no session\n");
+			break;
+		}
+		/* FUTURE: iterate over all calls and check if
+		 * call ID is valid.  We don't do this without newnat,
+		 * because we only know about last call */
+		info->cstate = PPTP_CALL_CLEAR_REQ;
+		break;
+	case PPTP_SET_LINK_INFO:
+		break;
+	case PPTP_ECHO_REQUEST:
+	case PPTP_ECHO_REPLY:
+		/* I don't have to explain these ;) */
+		break;
+	default:
+		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 
+			pptp_msg_name[msg]:pptp_msg_name[0], msg);
+		/* unknown: no need to create GRE masq table entry */
+		break;
+	}
+	
+	if (ip_nat_pptp_hook_outbound)
+		return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
+						 pptpReq);
+
+	return NF_ACCEPT;
+}
+
+
+/* track caller id inside control connection, call expect_related */
+static int 
+conntrack_pptp_help(struct sk_buff **pskb,
+		    struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+
+{
+	struct pptp_pkt_hdr _pptph, *pptph;
+	struct tcphdr _tcph, *tcph;
+	u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
+	u_int32_t datalen;
+	int dir = CTINFO2DIR(ctinfo);
+	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+	unsigned int nexthdr_off;
+
+	int oldsstate, oldcstate;
+	int ret;
+
+	/* don't do any tracking before tcp handshake complete */
+	if (ctinfo != IP_CT_ESTABLISHED 
+	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
+		DEBUGP("ctinfo = %u, skipping\n", ctinfo);
+		return NF_ACCEPT;
+	}
+	
+	nexthdr_off = (*pskb)->nh.iph->ihl*4;
+	tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
+	BUG_ON(!tcph);
+	nexthdr_off += tcph->doff * 4;
+ 	datalen = tcplen - tcph->doff * 4;
+
+	if (tcph->fin || tcph->rst) {
+		DEBUGP("RST/FIN received, timeouting GRE\n");
+		/* can't do this after real newnat */
+		info->cstate = PPTP_CALL_NONE;
+
+		/* untrack this call id, unexpect GRE packets */
+		pptp_destroy_siblings(ct);
+	}
+
+	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
+	if (!pptph) {
+		DEBUGP("no full PPTP header, can't track\n");
+		return NF_ACCEPT;
+	}
+	nexthdr_off += sizeof(_pptph);
+	datalen -= sizeof(_pptph);
+
+	/* if it's not a control message we can't do anything with it */
+	if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
+	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
+		DEBUGP("not a control packet\n");
+		return NF_ACCEPT;
+	}
+
+	oldsstate = info->sstate;
+	oldcstate = info->cstate;
+
+	spin_lock_bh(&ip_pptp_lock);
+
+	/* FIXME: We just blindly assume that the control connection is always
+	 * established from PNS->PAC.  However, RFC makes no guarantee */
+	if (dir == IP_CT_DIR_ORIGINAL)
+		/* client -> server (PNS -> PAC) */
+		ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+					ctinfo);
+	else
+		/* server -> client (PAC -> PNS) */
+		ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
+				       ctinfo);
+	DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
+		oldsstate, info->sstate, oldcstate, info->cstate);
+	spin_unlock_bh(&ip_pptp_lock);
+
+	return ret;
+}
+
+/* control protocol helper */
+static struct ip_conntrack_helper pptp = { 
+	.list = { NULL, NULL },
+	.name = "pptp", 
+	.me = THIS_MODULE,
+	.max_expected = 2,
+	.timeout = 5 * 60,
+	.tuple = { .src = { .ip = 0, 
+		 	    .u = { .tcp = { .port =  
+				    __constant_htons(PPTP_CONTROL_PORT) } } 
+			  }, 
+		   .dst = { .ip = 0, 
+			    .u = { .all = 0 },
+			    .protonum = IPPROTO_TCP
+			  } 
+		 },
+	.mask = { .src = { .ip = 0, 
+			   .u = { .tcp = { .port = 0xffff } } 
+			 }, 
+		  .dst = { .ip = 0, 
+			   .u = { .all = 0 },
+			   .protonum = 0xff 
+		 	 } 
+		},
+	.help = conntrack_pptp_help
+};
+
+extern void __exit ip_ct_proto_gre_fini(void);
+extern int __init ip_ct_proto_gre_init(void);
+
+/* ip_conntrack_pptp initialization */
+static int __init init(void)
+{
+	int retcode;
+ 
+	retcode = ip_ct_proto_gre_init();
+	if (retcode < 0)
+		return retcode;
+
+	DEBUGP(" registering helper\n");
+	if ((retcode = ip_conntrack_helper_register(&pptp))) {
+		printk(KERN_ERR "Unable to register conntrack application "
+				"helper for pptp: %d\n", retcode);
+		ip_ct_proto_gre_fini();
+		return retcode;
+	}
+
+	printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	ip_conntrack_helper_unregister(&pptp);
+	ip_ct_proto_gre_fini();
+	printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
+EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
+EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);
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_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 15aef35..b08a432 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1270,7 +1270,7 @@
 	if (err < 0)
 		return err;
 
-	exp = ip_conntrack_expect_find_get(&tuple);
+	exp = ip_conntrack_expect_find(&tuple);
 	if (!exp)
 		return -ENOENT;
 
@@ -1318,7 +1318,7 @@
 			return err;
 
 		/* bump usage count to 2 */
-		exp = ip_conntrack_expect_find_get(&tuple);
+		exp = ip_conntrack_expect_find(&tuple);
 		if (!exp)
 			return -ENOENT;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
new file mode 100644
index 0000000..de3cb9d
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -0,0 +1,327 @@
+/*
+ * ip_conntrack_proto_gre.c - Version 3.0 
+ *
+ * Connection tracking protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two 
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/list.h>
+
+static DEFINE_RWLOCK(ip_ct_gre_lock);
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
+
+#include <linux/netfilter_ipv4/listhelp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
+
+/* shamelessly stolen from ip_conntrack_proto_udp.c */
+#define GRE_TIMEOUT		(30*HZ)
+#define GRE_STREAM_TIMEOUT	(180*HZ)
+
+#if 0
+#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
+#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \
+			NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \
+			NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key))
+#else
+#define DEBUGP(x, args...)
+#define DUMP_TUPLE_GRE(x)
+#endif
+				
+/* GRE KEYMAP HANDLING FUNCTIONS */
+static LIST_HEAD(gre_keymap_list);
+
+static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
+				const struct ip_conntrack_tuple *t)
+{
+	return ((km->tuple.src.ip == t->src.ip) &&
+		(km->tuple.dst.ip == t->dst.ip) &&
+		(km->tuple.dst.protonum == t->dst.protonum) &&
+		(km->tuple.dst.u.all == t->dst.u.all));
+}
+
+/* look up the source key for a given tuple */
+static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
+{
+	struct ip_ct_gre_keymap *km;
+	u_int32_t key = 0;
+
+	read_lock_bh(&ip_ct_gre_lock);
+	km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+			struct ip_ct_gre_keymap *, t);
+	if (km)
+		key = km->tuple.src.u.gre.key;
+	read_unlock_bh(&ip_ct_gre_lock);
+	
+	DEBUGP("lookup src key 0x%x up key for ", key);
+	DUMP_TUPLE_GRE(t);
+
+	return key;
+}
+
+/* add a single keymap entry, associate with specified master ct */
+int
+ip_ct_gre_keymap_add(struct ip_conntrack *ct,
+		     struct ip_conntrack_tuple *t, int reply)
+{
+	struct ip_ct_gre_keymap **exist_km, *km, *old;
+
+	if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+		DEBUGP("refusing to add GRE keymap to non-pptp session\n");
+		return -1;
+	}
+
+	if (!reply) 
+		exist_km = &ct->help.ct_pptp_info.keymap_orig;
+	else
+		exist_km = &ct->help.ct_pptp_info.keymap_reply;
+
+	if (*exist_km) {
+		/* check whether it's a retransmission */
+		old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
+				struct ip_ct_gre_keymap *, t);
+		if (old == *exist_km) {
+			DEBUGP("retransmission\n");
+			return 0;
+		}
+
+		DEBUGP("trying to override keymap_%s for ct %p\n", 
+			reply? "reply":"orig", ct);
+		return -EEXIST;
+	}
+
+	km = kmalloc(sizeof(*km), GFP_ATOMIC);
+	if (!km)
+		return -ENOMEM;
+
+	memcpy(&km->tuple, t, sizeof(*t));
+	*exist_km = km;
+
+	DEBUGP("adding new entry %p: ", km);
+	DUMP_TUPLE_GRE(&km->tuple);
+
+	write_lock_bh(&ip_ct_gre_lock);
+	list_append(&gre_keymap_list, km);
+	write_unlock_bh(&ip_ct_gre_lock);
+
+	return 0;
+}
+
+/* destroy the keymap entries associated with specified master ct */
+void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct)
+{
+	DEBUGP("entering for ct %p\n", ct);
+
+	if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
+		DEBUGP("refusing to destroy GRE keymap to non-pptp session\n");
+		return;
+	}
+
+	write_lock_bh(&ip_ct_gre_lock);
+	if (ct->help.ct_pptp_info.keymap_orig) {
+		DEBUGP("removing %p from list\n", 
+			ct->help.ct_pptp_info.keymap_orig);
+		list_del(&ct->help.ct_pptp_info.keymap_orig->list);
+		kfree(ct->help.ct_pptp_info.keymap_orig);
+		ct->help.ct_pptp_info.keymap_orig = NULL;
+	}
+	if (ct->help.ct_pptp_info.keymap_reply) {
+		DEBUGP("removing %p from list\n",
+			ct->help.ct_pptp_info.keymap_reply);
+		list_del(&ct->help.ct_pptp_info.keymap_reply->list);
+		kfree(ct->help.ct_pptp_info.keymap_reply);
+		ct->help.ct_pptp_info.keymap_reply = NULL;
+	}
+	write_unlock_bh(&ip_ct_gre_lock);
+}
+
+
+/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
+
+/* invert gre part of tuple */
+static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
+			    const struct ip_conntrack_tuple *orig)
+{
+	tuple->dst.u.gre.key = orig->src.u.gre.key;
+	tuple->src.u.gre.key = orig->dst.u.gre.key;
+
+	return 1;
+}
+
+/* gre hdr info to tuple */
+static int gre_pkt_to_tuple(const struct sk_buff *skb,
+			   unsigned int dataoff,
+			   struct ip_conntrack_tuple *tuple)
+{
+	struct gre_hdr_pptp _pgrehdr, *pgrehdr;
+	u_int32_t srckey;
+	struct gre_hdr _grehdr, *grehdr;
+
+	/* first only delinearize old RFC1701 GRE header */
+	grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr);
+	if (!grehdr || grehdr->version != GRE_VERSION_PPTP) {
+		/* try to behave like "ip_conntrack_proto_generic" */
+		tuple->src.u.all = 0;
+		tuple->dst.u.all = 0;
+		return 1;
+	}
+
+	/* PPTP header is variable length, only need up to the call_id field */
+	pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
+	if (!pgrehdr)
+		return 1;
+
+	if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
+		DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+		return 0;
+	}
+
+	tuple->dst.u.gre.key = pgrehdr->call_id;
+	srckey = gre_keymap_lookup(tuple);
+	tuple->src.u.gre.key = srckey;
+
+	return 1;
+}
+
+/* print gre part of tuple */
+static int gre_print_tuple(struct seq_file *s,
+			   const struct ip_conntrack_tuple *tuple)
+{
+	return seq_printf(s, "srckey=0x%x dstkey=0x%x ", 
+			  ntohs(tuple->src.u.gre.key),
+			  ntohs(tuple->dst.u.gre.key));
+}
+
+/* print private data for conntrack */
+static int gre_print_conntrack(struct seq_file *s,
+			       const struct ip_conntrack *ct)
+{
+	return seq_printf(s, "timeout=%u, stream_timeout=%u ",
+			  (ct->proto.gre.timeout / HZ),
+			  (ct->proto.gre.stream_timeout / HZ));
+}
+
+/* Returns verdict for packet, and may modify conntrack */
+static int gre_packet(struct ip_conntrack *ct,
+		      const struct sk_buff *skb,
+		      enum ip_conntrack_info conntrackinfo)
+{
+	/* If we've seen traffic both ways, this is a GRE connection.
+	 * Extend timeout. */
+	if (ct->status & IPS_SEEN_REPLY) {
+		ip_ct_refresh_acct(ct, conntrackinfo, skb,
+				   ct->proto.gre.stream_timeout);
+		/* Also, more likely to be important, and not a probe. */
+		set_bit(IPS_ASSURED_BIT, &ct->status);
+	} else
+		ip_ct_refresh_acct(ct, conntrackinfo, skb,
+				   ct->proto.gre.timeout);
+	
+	return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int gre_new(struct ip_conntrack *ct,
+		   const struct sk_buff *skb)
+{ 
+	DEBUGP(": ");
+	DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+	/* initialize to sane value.  Ideally a conntrack helper
+	 * (e.g. in case of pptp) is increasing them */
+	ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
+	ct->proto.gre.timeout = GRE_TIMEOUT;
+
+	return 1;
+}
+
+/* Called when a conntrack entry has already been removed from the hashes
+ * and is about to be deleted from memory */
+static void gre_destroy(struct ip_conntrack *ct)
+{
+	struct ip_conntrack *master = ct->master;
+	DEBUGP(" entering\n");
+
+	if (!master)
+		DEBUGP("no master !?!\n");
+	else
+		ip_ct_gre_keymap_destroy(master);
+}
+
+/* protocol helper struct */
+static struct ip_conntrack_protocol gre = { 
+	.proto		 = IPPROTO_GRE,
+	.name		 = "gre", 
+	.pkt_to_tuple	 = gre_pkt_to_tuple,
+	.invert_tuple	 = gre_invert_tuple,
+	.print_tuple	 = gre_print_tuple,
+	.print_conntrack = gre_print_conntrack,
+	.packet		 = gre_packet,
+	.new		 = gre_new,
+	.destroy	 = gre_destroy,
+	.me 		 = THIS_MODULE,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+	.tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
+#endif
+};
+
+/* ip_conntrack_proto_gre initialization */
+int __init ip_ct_proto_gre_init(void)
+{
+	return ip_conntrack_protocol_register(&gre);
+}
+
+void __exit ip_ct_proto_gre_fini(void)
+{
+	struct list_head *pos, *n;
+
+	/* delete all keymap entries */
+	write_lock_bh(&ip_ct_gre_lock);
+	list_for_each_safe(pos, n, &gre_keymap_list) {
+		DEBUGP("deleting keymap %p at module unload time\n", pos);
+		list_del(pos);
+		kfree(pos);
+	}
+	write_unlock_bh(&ip_ct_gre_lock);
+
+	ip_conntrack_protocol_unregister(&gre); 
+}
+
+EXPORT_SYMBOL(ip_ct_gre_keymap_add);
+EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index ae3e3e6..d3c7808 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -993,11 +993,11 @@
 
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_put);
-EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
 EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
 
 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
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/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 1adedb7..c3ea891 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -578,6 +578,8 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
+EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
 #endif
 
 int __init ip_nat_init(void)
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
new file mode 100644
index 0000000..3cdd068
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -0,0 +1,401 @@
+/*
+ * ip_nat_pptp.c	- Version 3.0
+ *
+ * NAT support for PPTP (Point to Point Tunneling Protocol).
+ * PPTP is a a protocol for creating virtual private networks.
+ * It is a specification defined by Microsoft and some vendors
+ * working with Microsoft.  PPTP is built on top of a modified
+ * version of the Internet Generic Routing Encapsulation Protocol.
+ * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
+ * PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ * TODO: - NAT to a unique tuple, not to TCP source port
+ * 	   (needs netfilter tuple reservation)
+ *
+ * Changes:
+ *     2002-02-10 - Version 1.3
+ *       - Use ip_nat_mangle_tcp_packet() because of cloned skb's
+ *	   in local connections (Philip Craig <philipc@snapgear.com>)
+ *       - add checks for magicCookie and pptp version
+ *       - make argument list of pptp_{out,in}bound_packet() shorter
+ *       - move to C99 style initializers
+ *       - print version number at module loadtime
+ *     2003-09-22 - Version 1.5
+ *       - use SNATed tcp sourceport as callid, since we get called before
+ *	   TCP header is mangled (Philip Craig <philipc@snapgear.com>)
+ *     2004-10-22 - Version 2.0
+ *       - kernel 2.6.x version
+ *     2005-06-10 - Version 3.0
+ *       - kernel >= 2.6.11 version,
+ *	   funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_nat_pptp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
+
+#define IP_NAT_PPTP_VERSION "3.0"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
+
+
+#if 0
+extern const char *pptp_msg_name[];
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+				       __FUNCTION__, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+static void pptp_nat_expected(struct ip_conntrack *ct,
+			      struct ip_conntrack_expect *exp)
+{
+	struct ip_conntrack *master = ct->master;
+	struct ip_conntrack_expect *other_exp;
+	struct ip_conntrack_tuple t;
+	struct ip_ct_pptp_master *ct_pptp_info;
+	struct ip_nat_pptp *nat_pptp_info;
+
+	ct_pptp_info = &master->help.ct_pptp_info;
+	nat_pptp_info = &master->nat.help.nat_pptp_info;
+
+	/* And here goes the grand finale of corrosion... */
+
+	if (exp->dir == IP_CT_DIR_ORIGINAL) {
+		DEBUGP("we are PNS->PAC\n");
+		/* therefore, build tuple for PAC->PNS */
+		t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+		t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id);
+		t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+		t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id);
+		t.dst.protonum = IPPROTO_GRE;
+	} else {
+		DEBUGP("we are PAC->PNS\n");
+		/* build tuple for PNS->PAC */
+		t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+		t.src.u.gre.key = 
+			htons(master->nat.help.nat_pptp_info.pns_call_id);
+		t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+		t.dst.u.gre.key = 
+			htons(master->nat.help.nat_pptp_info.pac_call_id);
+		t.dst.protonum = IPPROTO_GRE;
+	}
+
+	DEBUGP("trying to unexpect other dir: ");
+	DUMP_TUPLE(&t);
+	other_exp = ip_conntrack_expect_find(&t);
+	if (other_exp) {
+		ip_conntrack_unexpect_related(other_exp);
+		ip_conntrack_expect_put(other_exp);
+		DEBUGP("success\n");
+	} else {
+		DEBUGP("not found!\n");
+	}
+
+	ip_nat_follow_master(ct, exp);
+}
+
+/* outbound packets == from PNS to PAC */
+static int
+pptp_outbound_pkt(struct sk_buff **pskb,
+		  struct ip_conntrack *ct,
+		  enum ip_conntrack_info ctinfo,
+		  struct PptpControlHeader *ctlh,
+		  union pptp_ctrl_union *pptpReq)
+
+{
+	struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
+	struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
+
+	u_int16_t msg, *cid = NULL, new_callid;
+
+	new_callid = htons(ct_pptp_info->pns_call_id);
+	
+	switch (msg = ntohs(ctlh->messageType)) {
+		case PPTP_OUT_CALL_REQUEST:
+			cid = &pptpReq->ocreq.callID;
+			/* FIXME: ideally we would want to reserve a call ID
+			 * here.  current netfilter NAT core is not able to do
+			 * this :( For now we use TCP source port. This breaks
+			 * multiple calls within one control session */
+
+			/* save original call ID in nat_info */
+			nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
+
+			/* don't use tcph->source since we are at a DSTmanip
+			 * hook (e.g. PREROUTING) and pkt is not mangled yet */
+			new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
+
+			/* save new call ID in ct info */
+			ct_pptp_info->pns_call_id = ntohs(new_callid);
+			break;
+		case PPTP_IN_CALL_REPLY:
+			cid = &pptpReq->icreq.callID;
+			break;
+		case PPTP_CALL_CLEAR_REQUEST:
+			cid = &pptpReq->clrreq.callID;
+			break;
+		default:
+			DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
+			      (msg <= PPTP_MSG_MAX)? 
+			      pptp_msg_name[msg]:pptp_msg_name[0]);
+			/* fall through */
+
+		case PPTP_SET_LINK_INFO:
+			/* only need to NAT in case PAC is behind NAT box */
+		case PPTP_START_SESSION_REQUEST:
+		case PPTP_START_SESSION_REPLY:
+		case PPTP_STOP_SESSION_REQUEST:
+		case PPTP_STOP_SESSION_REPLY:
+		case PPTP_ECHO_REQUEST:
+		case PPTP_ECHO_REPLY:
+			/* no need to alter packet */
+			return NF_ACCEPT;
+	}
+
+	/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
+	 * down to here */
+
+	IP_NF_ASSERT(cid);
+
+	DEBUGP("altering call id from 0x%04x to 0x%04x\n",
+		ntohs(*cid), ntohs(new_callid));
+
+	/* mangle packet */
+	if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+		(void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
+				 	sizeof(new_callid), 
+					(char *)&new_callid,
+				 	sizeof(new_callid)) == 0)
+		return NF_DROP;
+
+	return NF_ACCEPT;
+}
+
+static int
+pptp_exp_gre(struct ip_conntrack_expect *expect_orig,
+	     struct ip_conntrack_expect *expect_reply)
+{
+	struct ip_ct_pptp_master *ct_pptp_info = 
+				&expect_orig->master->help.ct_pptp_info;
+	struct ip_nat_pptp *nat_pptp_info = 
+				&expect_orig->master->nat.help.nat_pptp_info;
+
+	struct ip_conntrack *ct = expect_orig->master;
+
+	struct ip_conntrack_tuple inv_t;
+	struct ip_conntrack_tuple *orig_t, *reply_t;
+
+	/* save original PAC call ID in nat_info */
+	nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
+
+	/* alter expectation */
+	orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+	/* alter expectation for PNS->PAC direction */
+	invert_tuplepr(&inv_t, &expect_orig->tuple);
+	expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id);
+	expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
+	expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
+	inv_t.src.ip = reply_t->src.ip;
+	inv_t.dst.ip = reply_t->dst.ip;
+	inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
+	inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
+
+	if (!ip_conntrack_expect_related(expect_orig)) {
+		DEBUGP("successfully registered expect\n");
+	} else {
+		DEBUGP("can't expect_related(expect_orig)\n");
+		return 1;
+	}
+
+	/* alter expectation for PAC->PNS direction */
+	invert_tuplepr(&inv_t, &expect_reply->tuple);
+	expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id);
+	expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
+	expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
+	inv_t.src.ip = orig_t->src.ip;
+	inv_t.dst.ip = orig_t->dst.ip;
+	inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
+	inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
+
+	if (!ip_conntrack_expect_related(expect_reply)) {
+		DEBUGP("successfully registered expect\n");
+	} else {
+		DEBUGP("can't expect_related(expect_reply)\n");
+		ip_conntrack_unexpect_related(expect_orig);
+		return 1;
+	}
+
+	if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) {
+		DEBUGP("can't register original keymap\n");
+		ip_conntrack_unexpect_related(expect_orig);
+		ip_conntrack_unexpect_related(expect_reply);
+		return 1;
+	}
+
+	if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) {
+		DEBUGP("can't register reply keymap\n");
+		ip_conntrack_unexpect_related(expect_orig);
+		ip_conntrack_unexpect_related(expect_reply);
+		ip_ct_gre_keymap_destroy(ct);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* inbound packets == from PAC to PNS */
+static int
+pptp_inbound_pkt(struct sk_buff **pskb,
+		 struct ip_conntrack *ct,
+		 enum ip_conntrack_info ctinfo,
+		 struct PptpControlHeader *ctlh,
+		 union pptp_ctrl_union *pptpReq)
+{
+	struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
+	u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
+
+	int ret = NF_ACCEPT, rv;
+
+	new_pcid = htons(nat_pptp_info->pns_call_id);
+
+	switch (msg = ntohs(ctlh->messageType)) {
+	case PPTP_OUT_CALL_REPLY:
+		pcid = &pptpReq->ocack.peersCallID;	
+		cid = &pptpReq->ocack.callID;
+		break;
+	case PPTP_IN_CALL_CONNECT:
+		pcid = &pptpReq->iccon.peersCallID;
+		break;
+	case PPTP_IN_CALL_REQUEST:
+		/* only need to nat in case PAC is behind NAT box */
+		break;
+	case PPTP_WAN_ERROR_NOTIFY:
+		pcid = &pptpReq->wanerr.peersCallID;
+		break;
+	case PPTP_CALL_DISCONNECT_NOTIFY:
+		pcid = &pptpReq->disc.callID;
+		break;
+	case PPTP_SET_LINK_INFO:
+		pcid = &pptpReq->setlink.peersCallID;
+		break;
+
+	default:
+		DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? 
+			pptp_msg_name[msg]:pptp_msg_name[0]);
+		/* fall through */
+
+	case PPTP_START_SESSION_REQUEST:
+	case PPTP_START_SESSION_REPLY:
+	case PPTP_STOP_SESSION_REQUEST:
+	case PPTP_STOP_SESSION_REPLY:
+	case PPTP_ECHO_REQUEST:
+	case PPTP_ECHO_REPLY:
+		/* no need to alter packet */
+		return NF_ACCEPT;
+	}
+
+	/* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
+	 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
+
+	/* mangle packet */
+	IP_NF_ASSERT(pcid);
+	DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
+		ntohs(*pcid), ntohs(new_pcid));
+	
+	rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
+				      (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
+				      sizeof(new_pcid), (char *)&new_pcid, 
+				      sizeof(new_pcid));
+	if (rv != NF_ACCEPT) 
+		return rv;
+
+	if (new_cid) {
+		IP_NF_ASSERT(cid);
+		DEBUGP("altering call id from 0x%04x to 0x%04x\n",
+			ntohs(*cid), ntohs(new_cid));
+		rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
+					      (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), 
+					      sizeof(new_cid),
+					      (char *)&new_cid, 
+					      sizeof(new_cid));
+		if (rv != NF_ACCEPT)
+			return rv;
+	}
+
+	/* check for earlier return value of 'switch' above */
+	if (ret != NF_ACCEPT)
+		return ret;
+
+	/* great, at least we don't need to resize packets */
+	return NF_ACCEPT;
+}
+
+
+extern int __init ip_nat_proto_gre_init(void);
+extern void __exit ip_nat_proto_gre_fini(void);
+
+static int __init init(void)
+{
+	int ret;
+
+	DEBUGP("%s: registering NAT helper\n", __FILE__);
+
+	ret = ip_nat_proto_gre_init();
+	if (ret < 0)
+		return ret;
+
+	BUG_ON(ip_nat_pptp_hook_outbound);
+	ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
+
+	BUG_ON(ip_nat_pptp_hook_inbound);
+	ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
+
+	BUG_ON(ip_nat_pptp_hook_exp_gre);
+	ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
+
+	BUG_ON(ip_nat_pptp_hook_expectfn);
+	ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
+
+	printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	DEBUGP("cleanup_module\n" );
+
+	ip_nat_pptp_hook_expectfn = NULL;
+	ip_nat_pptp_hook_exp_gre = NULL;
+	ip_nat_pptp_hook_inbound = NULL;
+	ip_nat_pptp_hook_outbound = NULL;
+
+	ip_nat_proto_gre_fini();
+	/* Make sure noone calls it, meanwhile */
+	synchronize_net();
+
+	printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
new file mode 100644
index 0000000..7c12854
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -0,0 +1,214 @@
+/*
+ * ip_nat_proto_gre.c - Version 2.0
+ *
+ * NAT protocol helper module for GRE.
+ *
+ * GRE is a generic encapsulation protocol, which is generally not very
+ * suited for NAT, as it has no protocol-specific part as port numbers.
+ *
+ * It has an optional key field, which may help us distinguishing two 
+ * connections between the same two hosts.
+ *
+ * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
+ *
+ * PPTP is built on top of a modified version of GRE, and has a mandatory
+ * field called "CallID", which serves us for the same purpose as the key
+ * field in plain GRE.
+ *
+ * Documentation about PPTP can be found in RFC 2637
+ *
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/netfilter_ipv4/ip_nat_protocol.h>
+#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
+				       __FUNCTION__, ## args)
+#else
+#define DEBUGP(x, args...)
+#endif
+
+/* is key in given range between min and max */
+static int
+gre_in_range(const struct ip_conntrack_tuple *tuple,
+	     enum ip_nat_manip_type maniptype,
+	     const union ip_conntrack_manip_proto *min,
+	     const union ip_conntrack_manip_proto *max)
+{
+	u_int32_t key;
+
+	if (maniptype == IP_NAT_MANIP_SRC)
+		key = tuple->src.u.gre.key;
+	else
+		key = tuple->dst.u.gre.key;
+
+	return ntohl(key) >= ntohl(min->gre.key)
+		&& ntohl(key) <= ntohl(max->gre.key);
+}
+
+/* generate unique tuple ... */
+static int 
+gre_unique_tuple(struct ip_conntrack_tuple *tuple,
+		 const struct ip_nat_range *range,
+		 enum ip_nat_manip_type maniptype,
+		 const struct ip_conntrack *conntrack)
+{
+	static u_int16_t key;
+	u_int16_t *keyptr;
+	unsigned int min, i, range_size;
+
+	if (maniptype == IP_NAT_MANIP_SRC)
+		keyptr = &tuple->src.u.gre.key;
+	else
+		keyptr = &tuple->dst.u.gre.key;
+
+	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
+		DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+		min = 1;
+		range_size = 0xffff;
+	} else {
+		min = ntohl(range->min.gre.key);
+		range_size = ntohl(range->max.gre.key) - min + 1;
+	}
+
+	DEBUGP("min = %u, range_size = %u\n", min, range_size); 
+
+	for (i = 0; i < range_size; i++, key++) {
+		*keyptr = htonl(min + key % range_size);
+		if (!ip_nat_used_tuple(tuple, conntrack))
+			return 1;
+	}
+
+	DEBUGP("%p: no NAT mapping\n", conntrack);
+
+	return 0;
+}
+
+/* manipulate a GRE packet according to maniptype */
+static int
+gre_manip_pkt(struct sk_buff **pskb,
+	      unsigned int iphdroff,
+	      const struct ip_conntrack_tuple *tuple,
+	      enum ip_nat_manip_type maniptype)
+{
+	struct gre_hdr *greh;
+	struct gre_hdr_pptp *pgreh;
+	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
+	unsigned int hdroff = iphdroff + iph->ihl*4;
+
+	/* pgreh includes two optional 32bit fields which are not required
+	 * to be there.  That's where the magic '8' comes from */
+	if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8))
+		return 0;
+
+	greh = (void *)(*pskb)->data + hdroff;
+	pgreh = (struct gre_hdr_pptp *) greh;
+
+	/* we only have destination manip of a packet, since 'source key' 
+	 * is not present in the packet itself */
+	if (maniptype == IP_NAT_MANIP_DST) {
+		/* key manipulation is always dest */
+		switch (greh->version) {
+		case 0:
+			if (!greh->key) {
+				DEBUGP("can't nat GRE w/o key\n");
+				break;
+			}
+			if (greh->csum) {
+				/* FIXME: Never tested this code... */
+				*(gre_csum(greh)) = 
+					ip_nat_cheat_check(~*(gre_key(greh)),
+							tuple->dst.u.gre.key,
+							*(gre_csum(greh)));
+			}
+			*(gre_key(greh)) = tuple->dst.u.gre.key;
+			break;
+		case GRE_VERSION_PPTP:
+			DEBUGP("call_id -> 0x%04x\n", 
+				ntohl(tuple->dst.u.gre.key));
+			pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key));
+			break;
+		default:
+			DEBUGP("can't nat unknown GRE version\n");
+			return 0;
+			break;
+		}
+	}
+	return 1;
+}
+
+/* print out a nat tuple */
+static unsigned int 
+gre_print(char *buffer, 
+	  const struct ip_conntrack_tuple *match,
+	  const struct ip_conntrack_tuple *mask)
+{
+	unsigned int len = 0;
+
+	if (mask->src.u.gre.key)
+		len += sprintf(buffer + len, "srckey=0x%x ", 
+				ntohl(match->src.u.gre.key));
+
+	if (mask->dst.u.gre.key)
+		len += sprintf(buffer + len, "dstkey=0x%x ",
+				ntohl(match->src.u.gre.key));
+
+	return len;
+}
+
+/* print a range of keys */
+static unsigned int 
+gre_print_range(char *buffer, const struct ip_nat_range *range)
+{
+	if (range->min.gre.key != 0 
+	    || range->max.gre.key != 0xFFFF) {
+		if (range->min.gre.key == range->max.gre.key)
+			return sprintf(buffer, "key 0x%x ",
+					ntohl(range->min.gre.key));
+		else
+			return sprintf(buffer, "keys 0x%u-0x%u ",
+					ntohl(range->min.gre.key),
+					ntohl(range->max.gre.key));
+	} else
+		return 0;
+}
+
+/* nat helper struct */
+static struct ip_nat_protocol gre = { 
+	.name		= "GRE", 
+	.protonum	= IPPROTO_GRE,
+	.manip_pkt	= gre_manip_pkt,
+	.in_range	= gre_in_range,
+	.unique_tuple	= gre_unique_tuple,
+	.print		= gre_print,
+	.print_range	= gre_print_range,
+#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
+    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
+	.range_to_nfattr	= ip_nat_port_range_to_nfattr,
+	.nfattr_to_range	= ip_nat_port_nfattr_to_range,
+#endif
+};
+				  
+int __init ip_nat_proto_gre_init(void)
+{
+	return ip_nat_protocol_register(&gre);
+}
+
+void __exit ip_nat_proto_gre_fini(void)
+{
+	ip_nat_protocol_unregister(&gre);
+}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7d38913..9bcb398 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -13,6 +13,7 @@
 #include <linux/config.h>
 #include <linux/proc_fs.h>
 #include <linux/jhash.h>
+#include <linux/bitops.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -30,7 +31,7 @@
 #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 
-#define CLUSTERIP_VERSION "0.7"
+#define CLUSTERIP_VERSION "0.8"
 
 #define DEBUG_CLUSTERIP
 
@@ -49,13 +50,14 @@
 struct clusterip_config {
 	struct list_head list;			/* list of all configs */
 	atomic_t refcount;			/* reference count */
+	atomic_t entries;			/* number of entries/rules
+						 * referencing us */
 
 	u_int32_t clusterip;			/* the IP address */
 	u_int8_t clustermac[ETH_ALEN];		/* the MAC address */
 	struct net_device *dev;			/* device */
 	u_int16_t num_total_nodes;		/* total number of nodes */
-	u_int16_t num_local_nodes;		/* number of local nodes */
-	u_int16_t local_nodes[CLUSTERIP_MAX_NODES];	/* node number array */
+	unsigned long local_nodes;		/* node number array */
 
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *pde;		/* proc dir entry */
@@ -66,8 +68,7 @@
 
 static LIST_HEAD(clusterip_configs);
 
-/* clusterip_lock protects the clusterip_configs list _AND_ the configurable
- * data within all structurses (num_local_nodes, local_nodes[]) */
+/* clusterip_lock protects the clusterip_configs list */
 static DEFINE_RWLOCK(clusterip_lock);
 
 #ifdef CONFIG_PROC_FS
@@ -76,23 +77,48 @@
 #endif
 
 static inline void
-clusterip_config_get(struct clusterip_config *c) {
+clusterip_config_get(struct clusterip_config *c)
+{
 	atomic_inc(&c->refcount);
 }
 
 static inline void
-clusterip_config_put(struct clusterip_config *c) {
-	if (atomic_dec_and_test(&c->refcount)) {
+clusterip_config_put(struct clusterip_config *c)
+{
+	if (atomic_dec_and_test(&c->refcount))
+		kfree(c);
+}
+
+/* increase the count of entries(rules) using/referencing this config */
+static inline void
+clusterip_config_entry_get(struct clusterip_config *c)
+{
+	atomic_inc(&c->entries);
+}
+
+/* decrease the count of entries using/referencing this config.  If last
+ * entry(rule) is removed, remove the config from lists, but don't free it
+ * yet, since proc-files could still be holding references */
+static inline void
+clusterip_config_entry_put(struct clusterip_config *c)
+{
+	if (atomic_dec_and_test(&c->entries)) {
 		write_lock_bh(&clusterip_lock);
 		list_del(&c->list);
 		write_unlock_bh(&clusterip_lock);
+
 		dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
 		dev_put(c->dev);
-		kfree(c);
+
+		/* In case anyone still accesses the file, the open/close
+		 * functions are also incrementing the refcount on their own,
+		 * so it's safe to remove the entry even if it's in use. */
+#ifdef CONFIG_PROC_FS
+		remove_proc_entry(c->pde->name, c->pde->parent);
+#endif
 	}
 }
 
-
 static struct clusterip_config *
 __clusterip_config_find(u_int32_t clusterip)
 {
@@ -111,7 +137,7 @@
 }
 
 static inline struct clusterip_config *
-clusterip_config_find_get(u_int32_t clusterip)
+clusterip_config_find_get(u_int32_t clusterip, int entry)
 {
 	struct clusterip_config *c;
 
@@ -122,11 +148,24 @@
 		return NULL;
 	}
 	atomic_inc(&c->refcount);
+	if (entry)
+		atomic_inc(&c->entries);
 	read_unlock_bh(&clusterip_lock);
 
 	return c;
 }
 
+static void
+clusterip_config_init_nodelist(struct clusterip_config *c,
+			       const struct ipt_clusterip_tgt_info *i)
+{
+	int n;
+
+	for (n = 0; n < i->num_local_nodes; n++) {
+		set_bit(i->local_nodes[n] - 1, &c->local_nodes);
+	}
+}
+
 static struct clusterip_config *
 clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
 			struct net_device *dev)
@@ -143,11 +182,11 @@
 	c->clusterip = ip;
 	memcpy(&c->clustermac, &i->clustermac, ETH_ALEN);
 	c->num_total_nodes = i->num_total_nodes;
-	c->num_local_nodes = i->num_local_nodes;
-	memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes));
+	clusterip_config_init_nodelist(c, i);
 	c->hash_mode = i->hash_mode;
 	c->hash_initval = i->hash_initval;
 	atomic_set(&c->refcount, 1);
+	atomic_set(&c->entries, 1);
 
 #ifdef CONFIG_PROC_FS
 	/* create proc dir entry */
@@ -171,53 +210,28 @@
 static int
 clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
 {
-	int i;
 
-	write_lock_bh(&clusterip_lock);
-
-	if (c->num_local_nodes >= CLUSTERIP_MAX_NODES
-	    || nodenum > CLUSTERIP_MAX_NODES) {
-		write_unlock_bh(&clusterip_lock);
+	if (nodenum == 0 ||
+	    nodenum > c->num_total_nodes)
 		return 1;
-	}
 
-	/* check if we alrady have this number in our array */
-	for (i = 0; i < c->num_local_nodes; i++) {
-		if (c->local_nodes[i] == nodenum) {
-			write_unlock_bh(&clusterip_lock);
-			return 1;
-		}
-	}
+	/* check if we already have this number in our bitfield */
+	if (test_and_set_bit(nodenum - 1, &c->local_nodes))
+		return 1;
 
-	c->local_nodes[c->num_local_nodes++] = nodenum;
-
-	write_unlock_bh(&clusterip_lock);
 	return 0;
 }
 
 static int
 clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
 {
-	int i;
-
-	write_lock_bh(&clusterip_lock);
-
-	if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) {
-		write_unlock_bh(&clusterip_lock);
+	if (nodenum == 0 ||
+	    nodenum > c->num_total_nodes)
 		return 1;
-	}
 		
-	for (i = 0; i < c->num_local_nodes; i++) {
-		if (c->local_nodes[i] == nodenum) {
-			int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1));
-			memmove(&c->local_nodes[i], &c->local_nodes[i+1], size);
-			c->num_local_nodes--;
-			write_unlock_bh(&clusterip_lock);
-			return 0;
-		}
-	}
+	if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
+		return 0;
 
-	write_unlock_bh(&clusterip_lock);
 	return 1;
 }
 
@@ -285,25 +299,7 @@
 static inline int
 clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
 {
-	int i;
-
-	read_lock_bh(&clusterip_lock);
-
-	if (config->num_local_nodes == 0) {
-		read_unlock_bh(&clusterip_lock);
-		return 0;
-	}
-
-	for (i = 0; i < config->num_local_nodes; i++) {
-		if (config->local_nodes[i] == hash) {
-			read_unlock_bh(&clusterip_lock);
-			return 1;
-		}
-	}
-
-	read_unlock_bh(&clusterip_lock);
-
-	return 0;
+	return test_bit(hash - 1, &config->local_nodes);
 }
 
 /*********************************************************************** 
@@ -415,8 +411,26 @@
 
 	/* FIXME: further sanity checks */
 
-	config = clusterip_config_find_get(e->ip.dst.s_addr);
-	if (!config) {
+	config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
+	if (config) {
+		if (cipinfo->config != NULL) {
+			/* Case A: This is an entry that gets reloaded, since
+			 * it still has a cipinfo->config pointer. Simply
+			 * increase the entry refcount and return */
+			if (cipinfo->config != config) {
+				printk(KERN_ERR "CLUSTERIP: Reloaded entry "
+				       "has invalid config pointer!\n");
+				return 0;
+			}
+			clusterip_config_entry_get(cipinfo->config);
+		} else {
+			/* Case B: This is a new rule referring to an existing
+			 * clusterip config. */
+			cipinfo->config = config;
+			clusterip_config_entry_get(cipinfo->config);
+		}
+	} else {
+		/* Case C: This is a completely new clusterip config */
 		if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
 			printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
 			return 0;
@@ -443,10 +457,9 @@
 			}
 			dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
 		}
+		cipinfo->config = config;
 	}
 
-	cipinfo->config = config;
-
 	return 1;
 }
 
@@ -455,13 +468,10 @@
 {
 	struct ipt_clusterip_tgt_info *cipinfo = matchinfo;
 
-	/* we first remove the proc entry and then drop the reference
-	 * count.  In case anyone still accesses the file, the open/close
-	 * functions are also incrementing the refcount on their own */
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry(cipinfo->config->pde->name,
-			  cipinfo->config->pde->parent);
-#endif
+	/* if no more entries are referencing the config, remove it
+	 * from the list and destroy the proc entry */
+	clusterip_config_entry_put(cipinfo->config);
+
 	clusterip_config_put(cipinfo->config);
 }
 
@@ -533,7 +543,7 @@
 
 	/* if there is no clusterip configuration for the arp reply's 
 	 * source ip, we don't want to mangle it */
-	c = clusterip_config_find_get(payload->src_ip);
+	c = clusterip_config_find_get(payload->src_ip, 0);
 	if (!c)
 		return NF_ACCEPT;
 
@@ -574,56 +584,69 @@
 
 #ifdef CONFIG_PROC_FS
 
+struct clusterip_seq_position {
+	unsigned int pos;	/* position */
+	unsigned int weight;	/* number of bits set == size */
+	unsigned int bit;	/* current bit */
+	unsigned long val;	/* current value */
+};
+
 static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
 {
 	struct proc_dir_entry *pde = s->private;
 	struct clusterip_config *c = pde->data;
-	unsigned int *nodeidx;
+	unsigned int weight;
+	u_int32_t local_nodes;
+	struct clusterip_seq_position *idx;
 
-	read_lock_bh(&clusterip_lock);
-	if (*pos >= c->num_local_nodes)
+	/* FIXME: possible race */
+	local_nodes = c->local_nodes;
+	weight = hweight32(local_nodes);
+	if (*pos >= weight)
 		return NULL;
 
-	nodeidx = kmalloc(sizeof(unsigned int), GFP_KERNEL);
-	if (!nodeidx)
+	idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL);
+	if (!idx)
 		return ERR_PTR(-ENOMEM);
 
-	*nodeidx = *pos;
-	return nodeidx;
+	idx->pos = *pos;
+	idx->weight = weight;
+	idx->bit = ffs(local_nodes);
+	idx->val = local_nodes;
+	clear_bit(idx->bit - 1, &idx->val);
+
+	return idx;
 }
 
 static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	struct proc_dir_entry *pde = s->private;
-	struct clusterip_config *c = pde->data;
-	unsigned int *nodeidx = (unsigned int *)v;
+	struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
 
-	*pos = ++(*nodeidx);
-	if (*pos >= c->num_local_nodes) {
+	*pos = ++idx->pos;
+	if (*pos >= idx->weight) {
 		kfree(v);
 		return NULL;
 	}
-	return nodeidx;
+	idx->bit = ffs(idx->val);
+	clear_bit(idx->bit - 1, &idx->val);
+	return idx;
 }
 
 static void clusterip_seq_stop(struct seq_file *s, void *v)
 {
 	kfree(v);
-
-	read_unlock_bh(&clusterip_lock);
 }
 
 static int clusterip_seq_show(struct seq_file *s, void *v)
 {
-	struct proc_dir_entry *pde = s->private;
-	struct clusterip_config *c = pde->data;
-	unsigned int *nodeidx = (unsigned int *)v;
+	struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v;
 
-	if (*nodeidx != 0) 
+	if (idx->pos != 0) 
 		seq_putc(s, ',');
-	seq_printf(s, "%u", c->local_nodes[*nodeidx]);
 
-	if (*nodeidx == c->num_local_nodes-1)
+	seq_printf(s, "%u", idx->bit);
+
+	if (idx->pos == idx->weight - 1)
 		seq_putc(s, '\n');
 
 	return 0;
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/ipv4/raw.c b/net/ipv4/raw.c
index 304bb0a..4b0d7e4 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -361,7 +361,7 @@
 
 			if (type && code) {
 				get_user(fl->fl_icmp_type, type);
-				__get_user(fl->fl_icmp_code, code);
+			        get_user(fl->fl_icmp_code, code);
 				probed = 1;
 			}
 			break;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 29222b96..a7537c7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -979,14 +979,19 @@
 			if (!before(TCP_SKB_CB(skb)->seq, end_seq))
 				break;
 
+			in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
+				!before(end_seq, TCP_SKB_CB(skb)->end_seq);
+
 			pcount = tcp_skb_pcount(skb);
 
-			if (pcount > 1 &&
-			    (after(start_seq, TCP_SKB_CB(skb)->seq) ||
-			     before(end_seq, TCP_SKB_CB(skb)->end_seq))) {
+			if (pcount > 1 && !in_sack &&
+			    after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
 				unsigned int pkt_len;
 
-				if (after(start_seq, TCP_SKB_CB(skb)->seq))
+				in_sack = !after(start_seq,
+						 TCP_SKB_CB(skb)->seq);
+
+				if (!in_sack)
 					pkt_len = (start_seq -
 						   TCP_SKB_CB(skb)->seq);
 				else
@@ -999,9 +1004,6 @@
 
 			fack_count += pcount;
 
-			in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
-				!before(end_seq, TCP_SKB_CB(skb)->end_seq);
-
 			sacked = TCP_SKB_CB(skb)->sacked;
 
 			/* Account D-SACK for retransmitted packet. */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index c10e443..5dd6dd7 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -435,6 +435,8 @@
 	int nsize, old_factor;
 	u16 flags;
 
+	BUG_ON(len >= skb->len);
+
 	nsize = skb_headlen(skb) - len;
 	if (nsize < 0)
 		nsize = 0;
@@ -459,9 +461,7 @@
 	flags = TCP_SKB_CB(skb)->flags;
 	TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
 	TCP_SKB_CB(buff)->flags = flags;
-	TCP_SKB_CB(buff)->sacked =
-		(TCP_SKB_CB(skb)->sacked &
-		 (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
+	TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
 	TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
 
 	if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -499,6 +499,12 @@
 			tcp_skb_pcount(buff);
 
 		tp->packets_out -= diff;
+
+		if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
+			tp->sacked_out -= diff;
+		if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+			tp->retrans_out -= diff;
+
 		if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
 			tp->lost_out -= diff;
 			tp->left_out -= diff;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 29fed6e..519899f 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1968,7 +1968,7 @@
 	}
 	pmc->mca_sources = NULL;
 	pmc->mca_sfmode = MCAST_EXCLUDE;
-	pmc->mca_sfcount[MCAST_EXCLUDE] = 0;
+	pmc->mca_sfcount[MCAST_INCLUDE] = 0;
 	pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
 }
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1cb8adb..2da514b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1955,6 +1955,57 @@
 #endif
 }
 
+/*
+ * find specified header up to transport protocol header.
+ * If found target header, the offset to the header is set to *offset
+ * and return 0. otherwise, return -1.
+ *
+ * Notes: - non-1st Fragment Header isn't skipped.
+ *	  - ESP header isn't skipped.
+ *	  - The target header may be trancated.
+ */
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
+{
+	unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
+	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	unsigned int len = skb->len - start;
+
+	while (nexthdr != target) {
+		struct ipv6_opt_hdr _hdr, *hp;
+		unsigned int hdrlen;
+
+		if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE)
+			return -1;
+		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+		if (hp == NULL)
+			return -1;
+		if (nexthdr == NEXTHDR_FRAGMENT) {
+			unsigned short _frag_off, *fp;
+			fp = skb_header_pointer(skb,
+						start+offsetof(struct frag_hdr,
+							       frag_off),
+						sizeof(_frag_off),
+						&_frag_off);
+			if (fp == NULL)
+				return -1;
+
+			if (ntohs(*fp) & ~0x7)
+				return -1;
+			hdrlen = 8;
+		} else if (nexthdr == NEXTHDR_AUTH)
+			hdrlen = (hp->hdrlen + 2) << 2; 
+		else
+			hdrlen = ipv6_optlen(hp); 
+
+		nexthdr = hp->nexthdr;
+		len -= hdrlen;
+		start += hdrlen;
+	}
+
+	*offset = start;
+	return 0;
+}
+
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
@@ -1963,6 +2014,7 @@
 EXPORT_SYMBOL(ip6t_register_target);
 EXPORT_SYMBOL(ip6t_unregister_target);
 EXPORT_SYMBOL(ip6t_ext_hdr);
+EXPORT_SYMBOL(ipv6_find_hdr);
 
 module_init(init);
 module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d5b94f1..dde3779 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -48,92 +48,21 @@
       unsigned int protoff,
       int *hotdrop)
 {
-	struct ip_auth_hdr *ah = NULL, _ah;
+	struct ip_auth_hdr *ah, _ah;
 	const struct ip6t_ah *ahinfo = matchinfo;
-	unsigned int temp;
-	int len;
-	u8 nexthdr;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
 
-	/*DEBUGP("IPv6 AH entered\n");*/
-	/* if (opt->auth == 0) return 0;
-	* It does not filled on output */
-
-	/* type of the 1st exthdr */
-	nexthdr = skb->nh.ipv6h->nexthdr;
-	/* pointer to the 1st exthdr */
-	ptr = sizeof(struct ipv6hdr);
-	/* available length */
-	len = skb->len - ptr;
-	temp = 0;
-
-	while (ip6t_ext_hdr(nexthdr)) {
-		struct ipv6_opt_hdr _hdr, *hp;
-
-		DEBUGP("ipv6_ah header iteration \n");
-
-		/* Is there enough space for the next ext header? */
-		if (len < sizeof(struct ipv6_opt_hdr))
-			return 0;
-		/* No more exthdr -> evaluate */
-		if (nexthdr == NEXTHDR_NONE)
-			break;
-		/* ESP -> evaluate */
-		if (nexthdr == NEXTHDR_ESP)
-			break;
-
-		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-		BUG_ON(hp == NULL);
-
-		/* Calculate the header length */
-		if (nexthdr == NEXTHDR_FRAGMENT)
-			hdrlen = 8;
-		else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hp->hdrlen+2)<<2;
-		else
-			hdrlen = ipv6_optlen(hp);
-
-		/* AH -> evaluate */
-		if (nexthdr == NEXTHDR_AUTH) {
-			temp |= MASK_AH;
-			break;
-		}
-
-		
-		/* set the flag */
-		switch (nexthdr) {
-		case NEXTHDR_HOP:
-		case NEXTHDR_ROUTING:
-		case NEXTHDR_FRAGMENT:
-		case NEXTHDR_AUTH:
-		case NEXTHDR_DEST:
-			break;
-		default:
-			DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
-			return 0;
-		}
-
-		nexthdr = hp->nexthdr;
-		len -= hdrlen;
-		ptr += hdrlen;
-		if (ptr > skb->len) {
-			DEBUGP("ipv6_ah: new pointer too large! \n");
-			break;
-		}
-	}
-
-	/* AH header not found */
-	if (temp != MASK_AH)
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0)
 		return 0;
 
-	if (len < sizeof(struct ip_auth_hdr)){
+	ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
+	if (ah == NULL) {
 		*hotdrop = 1;
 		return 0;
 	}
 
-	ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
-	BUG_ON(ah == NULL);
+	hdrlen = (ah->hdrlen + 2) << 2;
 
 	DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
 	DEBUGP("RES %04X ", ah->reserved);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 540925e..c450a63 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -63,8 +63,6 @@
        struct ipv6_opt_hdr _optsh, *oh;
        const struct ip6t_opts *optinfo = matchinfo;
        unsigned int temp;
-       unsigned int len;
-       u8 nexthdr;
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
@@ -72,97 +70,25 @@
        u8 _optlen, *lp = NULL;
        unsigned int optlen;
        
-       /* type of the 1st exthdr */
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       /* pointer to the 1st exthdr */
-       ptr = sizeof(struct ipv6hdr);
-       /* available length */
-       len = skb->len - ptr;
-       temp = 0;
-
-        while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr _hdr, *hp;
-
-              DEBUGP("ipv6_opts header iteration \n");
-
-              /* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
-              /* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
-                     break;
-              }
-              /* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
-                     break;
-              }
-
-	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-	      BUG_ON(hp == NULL);
-
-              /* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hp->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hp);
-
-              /* OPTS -> evaluate */
 #if HOPBYHOP
-                if (nexthdr == NEXTHDR_HOP) {
-                     temp |= MASK_HOPOPTS;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
 #else
-                if (nexthdr == NEXTHDR_DEST) {
-                     temp |= MASK_DSTOPTS;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
 #endif
-                     break;
-              }
+		return 0;
 
-
-              /* set the flag */
-              switch (nexthdr){
-                     case NEXTHDR_HOP:
-                     case NEXTHDR_ROUTING:
-                     case NEXTHDR_FRAGMENT:
-                     case NEXTHDR_AUTH:
-                     case NEXTHDR_DEST:
-                            break;
-                     default:
-                            DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
-                            return 0;
-                            break;
-              }
-
-                nexthdr = hp->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_opts: new pointer is too large! \n");
-			break;
-		}
-        }
-
-       /* OPTIONS header not found */
-#if HOPBYHOP
-       if ( temp != MASK_HOPOPTS ) return 0;
-#else
-       if ( temp != MASK_DSTOPTS ) return 0;
-#endif
-
-       if (len < (int)sizeof(struct ipv6_opt_hdr)){
+       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+       if (oh == NULL){
 	       *hotdrop = 1;
        		return 0;
        }
 
-       if (len < hdrlen){
+       hdrlen = ipv6_optlen(oh);
+       if (skb->len - ptr < hdrlen){
 	       /* Packet smaller than it's length field */
        		return 0;
        }
 
-       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
-       BUG_ON(oh == NULL);
-
        DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
        DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e39dd23..24bc0cd 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -48,87 +48,22 @@
       unsigned int protoff,
       int *hotdrop)
 {
-	struct ip_esp_hdr _esp, *eh = NULL;
+	struct ip_esp_hdr _esp, *eh;
 	const struct ip6t_esp *espinfo = matchinfo;
-	unsigned int temp;
-	int len;
-	u8 nexthdr;
 	unsigned int ptr;
 
 	/* Make sure this isn't an evil packet */
 	/*DEBUGP("ipv6_esp entered \n");*/
 
-	/* type of the 1st exthdr */
-	nexthdr = skb->nh.ipv6h->nexthdr;
-	/* pointer to the 1st exthdr */
-	ptr = sizeof(struct ipv6hdr);
-	/* available length */
-	len = skb->len - ptr;
-	temp = 0;
-
-	while (ip6t_ext_hdr(nexthdr)) {
-		struct ipv6_opt_hdr _hdr, *hp;
-		int hdrlen;
-
-		DEBUGP("ipv6_esp header iteration \n");
-
-		/* Is there enough space for the next ext header? */
-		if (len < sizeof(struct ipv6_opt_hdr))
-			return 0;
-		/* No more exthdr -> evaluate */
-		if (nexthdr == NEXTHDR_NONE)
-			break;
-		/* ESP -> evaluate */
-		if (nexthdr == NEXTHDR_ESP) {
-			temp |= MASK_ESP;
-			break;
-		}
-
-		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-		BUG_ON(hp == NULL);
-
-		/* Calculate the header length */
-		if (nexthdr == NEXTHDR_FRAGMENT)
-			hdrlen = 8;
-		else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hp->hdrlen+2)<<2;
-		else
-			hdrlen = ipv6_optlen(hp);
-
-		/* set the flag */
-		switch (nexthdr) {
-		case NEXTHDR_HOP:
-		case NEXTHDR_ROUTING:
-		case NEXTHDR_FRAGMENT:
-		case NEXTHDR_AUTH:
-		case NEXTHDR_DEST:
-			break;
-		default:
-			DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
-			return 0;
-		}
-
-		nexthdr = hp->nexthdr;
-		len -= hdrlen;
-		ptr += hdrlen;
-		if (ptr > skb->len) {
-			DEBUGP("ipv6_esp: new pointer too large! \n");
-			break;
-		}
-	}
-
-	/* ESP header not found */
-	if (temp != MASK_ESP)
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0)
 		return 0;
 
-	if (len < sizeof(struct ip_esp_hdr)) {
+	eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
+	if (eh == NULL) {
 		*hotdrop = 1;
 		return 0;
 	}
 
-	eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
-	BUG_ON(eh == NULL);
-
 	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
 
 	return (eh != NULL)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4bfa30a..085d5f8 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -48,90 +48,18 @@
       unsigned int protoff,
       int *hotdrop)
 {
-       struct frag_hdr _frag, *fh = NULL;
+       struct frag_hdr _frag, *fh;
        const struct ip6t_frag *fraginfo = matchinfo;
-       unsigned int temp;
-       int len;
-       u8 nexthdr;
        unsigned int ptr;
-       unsigned int hdrlen = 0;
 
-       /* type of the 1st exthdr */
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       /* pointer to the 1st exthdr */
-       ptr = sizeof(struct ipv6hdr);
-       /* available length */
-       len = skb->len - ptr;
-       temp = 0;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0)
+		return 0;
 
-        while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr _hdr, *hp;
-
-              DEBUGP("ipv6_frag header iteration \n");
-
-              /* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
-              /* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
-                     break;
-              }
-              /* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
-                     break;
-              }
-
-	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-	      BUG_ON(hp == NULL);
-
-              /* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hp->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hp);
-
-              /* FRAG -> evaluate */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                     temp |= MASK_FRAGMENT;
-                     break;
-              }
-
-
-              /* set the flag */
-              switch (nexthdr){
-                     case NEXTHDR_HOP:
-                     case NEXTHDR_ROUTING:
-                     case NEXTHDR_FRAGMENT:
-                     case NEXTHDR_AUTH:
-                     case NEXTHDR_DEST:
-                            break;
-                     default:
-                            DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr);
-                            return 0;
-                            break;
-              }
-
-                nexthdr = hp->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_frag: new pointer too large! \n");
-			break;
-		}
-        }
-
-       /* FRAG header not found */
-       if ( temp != MASK_FRAGMENT ) return 0;
-
-       if (len < sizeof(struct frag_hdr)){
-	       *hotdrop = 1;
-       		return 0;
-       }
-
-       fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
-       BUG_ON(fh == NULL);
+	fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
+	if (fh == NULL){
+		*hotdrop = 1;
+		return 0;
+	}
 
        DEBUGP("INFO %04X ", fh->frag_off);
        DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 27f3650..1d09485 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -63,8 +63,6 @@
        struct ipv6_opt_hdr _optsh, *oh;
        const struct ip6t_opts *optinfo = matchinfo;
        unsigned int temp;
-       unsigned int len;
-       u8 nexthdr;
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
@@ -72,97 +70,25 @@
        u8 _optlen, *lp = NULL;
        unsigned int optlen;
        
-       /* type of the 1st exthdr */
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       /* pointer to the 1st exthdr */
-       ptr = sizeof(struct ipv6hdr);
-       /* available length */
-       len = skb->len - ptr;
-       temp = 0;
-
-        while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr _hdr, *hp;
-
-              DEBUGP("ipv6_opts header iteration \n");
-
-              /* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
-              /* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
-                     break;
-              }
-              /* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
-                     break;
-              }
-
-	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-	      BUG_ON(hp == NULL);
-
-              /* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hp->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hp);
-
-              /* OPTS -> evaluate */
 #if HOPBYHOP
-                if (nexthdr == NEXTHDR_HOP) {
-                     temp |= MASK_HOPOPTS;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
 #else
-                if (nexthdr == NEXTHDR_DEST) {
-                     temp |= MASK_DSTOPTS;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
 #endif
-                     break;
-              }
+		return 0;
 
-
-              /* set the flag */
-              switch (nexthdr){
-                     case NEXTHDR_HOP:
-                     case NEXTHDR_ROUTING:
-                     case NEXTHDR_FRAGMENT:
-                     case NEXTHDR_AUTH:
-                     case NEXTHDR_DEST:
-                            break;
-                     default:
-                            DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
-                            return 0;
-                            break;
-              }
-
-                nexthdr = hp->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_opts: new pointer is too large! \n");
-			break;
-		}
-        }
-
-       /* OPTIONS header not found */
-#if HOPBYHOP
-       if ( temp != MASK_HOPOPTS ) return 0;
-#else
-       if ( temp != MASK_DSTOPTS ) return 0;
-#endif
-
-       if (len < (int)sizeof(struct ipv6_opt_hdr)){
+       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+       if (oh == NULL){
 	       *hotdrop = 1;
        		return 0;
        }
 
-       if (len < hdrlen){
+       hdrlen = ipv6_optlen(oh);
+       if (skb->len - ptr < hdrlen){
 	       /* Packet smaller than it's length field */
        		return 0;
        }
 
-       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
-       BUG_ON(oh == NULL);
-
        DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
        DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 2bb6700..beb2fd5 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -50,98 +50,29 @@
       unsigned int protoff,
       int *hotdrop)
 {
-       struct ipv6_rt_hdr _route, *rh = NULL;
+       struct ipv6_rt_hdr _route, *rh;
        const struct ip6t_rt *rtinfo = matchinfo;
        unsigned int temp;
-       unsigned int len;
-       u8 nexthdr;
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
        struct in6_addr *ap, _addr;
 
-       /* type of the 1st exthdr */
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       /* pointer to the 1st exthdr */
-       ptr = sizeof(struct ipv6hdr);
-       /* available length */
-       len = skb->len - ptr;
-       temp = 0;
+	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0)
+		return 0;
 
-        while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr _hdr, *hp;
-
-              DEBUGP("ipv6_rt header iteration \n");
-
-              /* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
-              /* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
-                     break;
-              }
-              /* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
-                     break;
-              }
-
-	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
-	      BUG_ON(hp == NULL);
-
-              /* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hp->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hp);
-
-              /* ROUTING -> evaluate */
-                if (nexthdr == NEXTHDR_ROUTING) {
-                     temp |= MASK_ROUTING;
-                     break;
-              }
-
-
-              /* set the flag */
-              switch (nexthdr){
-                     case NEXTHDR_HOP:
-                     case NEXTHDR_ROUTING:
-                     case NEXTHDR_FRAGMENT:
-                     case NEXTHDR_AUTH:
-                     case NEXTHDR_DEST:
-                            break;
-                     default:
-                            DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr);
-                            return 0;
-                            break;
-              }
-
-                nexthdr = hp->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_rt: new pointer is too large! \n");
-			break;
-		}
-        }
-
-       /* ROUTING header not found */
-       if ( temp != MASK_ROUTING ) return 0;
-
-       if (len < (int)sizeof(struct ipv6_rt_hdr)){
+       rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+       if (rh == NULL){
 	       *hotdrop = 1;
        		return 0;
        }
 
-       if (len < hdrlen){
+       hdrlen = ipv6_optlen(rh);
+       if (skb->len - ptr < hdrlen){
 	       /* Pcket smaller than its length field */
        		return 0;
        }
 
-       rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
-       BUG_ON(rh == NULL);
-
        DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
        DEBUGP("TYPE %04X ", rh->type);
        DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5aa3691..a1265a3 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -627,7 +627,7 @@
 
 			if (type && code) {
 				get_user(fl->fl_icmp_type, type);
-				__get_user(fl->fl_icmp_code, code);
+				get_user(fl->fl_icmp_code, code);
 				probed = 1;
 			}
 			break;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 69b1468..6001948 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -405,9 +405,8 @@
 				continue;
 
 			if (!ipv6_addr_any(&np->rcv_saddr)) {
-				if (ipv6_addr_equal(&np->rcv_saddr, loc_addr))
-					return s;
-				continue;
+				if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr))
+					continue;
 			}
 			if(!inet6_mc_check(s, loc_addr, rmt_addr))
 				continue;
@@ -640,6 +639,7 @@
 	int tclass = -1;
 	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
 	int err;
+	int connected = 0;
 
 	/* destination address check */
 	if (sin6) {
@@ -749,6 +749,7 @@
 		fl->fl_ip_dport = inet->dport;
 		daddr = &np->daddr;
 		fl->fl6_flowlabel = np->flow_label;
+		connected = 1;
 	}
 
 	if (!fl->oif)
@@ -771,6 +772,7 @@
 		}
 		if (!(opt->opt_nflen|opt->opt_flen))
 			opt = NULL;
+		connected = 0;
 	}
 	if (opt == NULL)
 		opt = np->opt;
@@ -788,10 +790,13 @@
 		ipv6_addr_copy(&final, &fl->fl6_dst);
 		ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
 		final_p = &final;
+		connected = 0;
 	}
 
-	if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
+	if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) {
 		fl->oif = np->mcast_oif;
+		connected = 0;
+	}
 
 	err = ip6_dst_lookup(sk, &dst, fl);
 	if (err)
@@ -847,7 +852,7 @@
 	else if (!corkreq)
 		err = udp_v6_push_pending_frames(sk, up);
 
-	if (dst)
+	if (dst && connected)
 		ip6_dst_store(sk, dst,
 			      ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ?
 			      &np->daddr : NULL);
diff --git a/net/socket.c b/net/socket.c
index c699e93..f926447 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1862,7 +1862,8 @@
 		if (err < 0)
 			goto out_freeiov;
 	}
-	err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg));
+	err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT),
+			 COMPAT_FLAGS(msg));
 	if (err)
 		goto out_freeiov;
 	if (MSG_CMSG_COMPAT & flags)
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/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..1caac01 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,32 +250,45 @@
 			      "maintainer about this event.\n");
 		return -EINVAL;
 	}
-	len = strlen(buff);
+
+	if (count < 0 || count >= PAGE_SIZE)
+		return -EINVAL;
+	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;
 	}
 	for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
-		if (hashedPassword[i] != tmp[i]) {
+		if (hashedPassword[i] != tmp[i])
 			return -EPERM;
-		}
 	}
 	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.
@@ -579,9 +479,8 @@
  */
 static int seclvl_umount(struct vfsmount *mnt, int flags)
 {
-	if (current->pid == 1) {
+	if (current->pid == 1)
 		return 0;
-	}
 	if (seclvl == 2) {
 		seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
 			      "level %d\n", seclvl);
@@ -647,22 +546,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 +588,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 +615,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 +633,10 @@
  */
 static void __exit seclvl_exit(void)
 {
-	sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr);
-	if (*passwd || *sha1_passwd) {
-		sysfs_remove_file(&seclvl_subsys.kset.kobj,
-				  &sysfs_attr_passwd.attr);
-	}
-	subsystem_unregister(&seclvl_subsys);
+	securityfs_remove(seclvl_ino);
+	if (*passwd || *sha1_passwd)
+		securityfs_remove(passwd_ino);
+	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..b2d5db2 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -650,7 +650,7 @@
 	return 0;
 }
 
-static int aaci_suspend(struct amba_device *dev, u32 state)
+static int aaci_suspend(struct amba_device *dev, pm_message_t state)
 {
 	snd_card_t *card = amba_get_drvdata(dev);
 	return card ? aaci_do_suspend(card) : 0;
@@ -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 0419c433..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..cd313af 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;
@@ -242,11 +228,11 @@
 } rme32_t;
 
 static struct pci_device_id snd_rme32_ids[] = {
-	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32,
+	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
-	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_8,
+	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
-	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_PRO,
+	{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
 	{0,}
 };
@@ -254,7 +240,7 @@
 MODULE_DEVICE_TABLE(pci, snd_rme32_ids);
 
 #define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START)
-#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414)
+#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414)
 
 static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream);
 
@@ -541,21 +527,21 @@
 			RME32_WCR_FREQ_1;
 		break;
 	case 64000:
-		if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
 			return -EINVAL;
 		rme32->wcreg |= RME32_WCR_DS_BM;
 		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 
 			~RME32_WCR_FREQ_1;
 		break;
 	case 88200:
-		if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
 			return -EINVAL;
 		rme32->wcreg |= RME32_WCR_DS_BM;
 		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & 
 			~RME32_WCR_FREQ_0;
 		break;
 	case 96000:
-		if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO)
+		if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO)
 			return -EINVAL;
 		rme32->wcreg |= RME32_WCR_DS_BM;
 		rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 
@@ -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;
 	}
@@ -893,7 +881,7 @@
 		runtime->hw = snd_rme32_spdif_fd_info;
 	else
 		runtime->hw = snd_rme32_spdif_info;
-	if (rme32->pci->device == PCI_DEVICE_ID_DIGI32_PRO) {
+	if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) {
 		runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
 		runtime->hw.rate_max = 96000;
 	}
@@ -1420,8 +1408,8 @@
 	}
 
 	/* set up ALSA pcm device for ADAT */
-	if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
-	    (pci->device == PCI_DEVICE_ID_DIGI32_PRO)) {
+	if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) ||
+	    (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) {
 		/* ADAT is not available on DIGI32 and DIGI32 Pro */
 		rme32->adat_pcm = NULL;
 	}
@@ -1651,11 +1639,11 @@
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	switch (rme32->pci->device) {
-	case PCI_DEVICE_ID_DIGI32:
-	case PCI_DEVICE_ID_DIGI32_8:
+	case PCI_DEVICE_ID_RME_DIGI32:
+	case PCI_DEVICE_ID_RME_DIGI32_8:
 		uinfo->value.enumerated.items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI32_PRO:
+	case PCI_DEVICE_ID_RME_DIGI32_PRO:
 		uinfo->value.enumerated.items = 4;
 		break;
 	default:
@@ -1682,11 +1670,11 @@
 	ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32);
 
 	switch (rme32->pci->device) {
-	case PCI_DEVICE_ID_DIGI32:
-	case PCI_DEVICE_ID_DIGI32_8:
+	case PCI_DEVICE_ID_RME_DIGI32:
+	case PCI_DEVICE_ID_RME_DIGI32_8:
 		items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI32_PRO:
+	case PCI_DEVICE_ID_RME_DIGI32_PRO:
 		items = 4;
 		break;
 	default:
@@ -1709,11 +1697,11 @@
 	int change, items = 3;
 
 	switch (rme32->pci->device) {
-	case PCI_DEVICE_ID_DIGI32:
-	case PCI_DEVICE_ID_DIGI32_8:
+	case PCI_DEVICE_ID_RME_DIGI32:
+	case PCI_DEVICE_ID_RME_DIGI32_8:
 		items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI32_PRO:
+	case PCI_DEVICE_ID_RME_DIGI32_PRO:
 		items = 4;
 		break;
 	default:
@@ -1994,13 +1982,13 @@
 
 	strcpy(card->driver, "Digi32");
 	switch (rme32->pci->device) {
-	case PCI_DEVICE_ID_DIGI32:
+	case PCI_DEVICE_ID_RME_DIGI32:
 		strcpy(card->shortname, "RME Digi32");
 		break;
-	case PCI_DEVICE_ID_DIGI32_8:
+	case PCI_DEVICE_ID_RME_DIGI32_8:
 		strcpy(card->shortname, "RME Digi32/8");
 		break;
-	case PCI_DEVICE_ID_DIGI32_PRO:
+	case PCI_DEVICE_ID_RME_DIGI32_PRO:
 		strcpy(card->shortname, "RME Digi32 PRO");
 		break;
 	}
@@ -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..c495cae 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;
@@ -252,13 +233,13 @@
 } rme96_t;
 
 static struct pci_device_id snd_rme96_ids[] = {
-	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96,
+	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8,
+	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PRO,
+	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST,
+	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 
 	{ 0, }
 };
@@ -267,12 +248,12 @@
 
 #define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START)
 #define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2)
-#define	RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST)
-#define	RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO || \
-				     (rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST)
+#define	RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST)
+#define	RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \
+				     (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST)
 #define	RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4)
-#define	RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \
-			          ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO && (rme96)->rev == 2))
+#define	RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \
+			          ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2))
 #define	RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1)
 
 static int
@@ -849,9 +830,9 @@
 			RME96_WCR_INP_1;
 		break;
 	case RME96_INPUT_XLR:
-		if ((rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST &&
-		     rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PRO) ||
-		    (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST &&
+		if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&
+		     rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) ||
+		    (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST &&
 		     rme96->rev > 4))
 		{
 			/* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */
@@ -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;
 
@@ -1615,7 +1598,7 @@
 	rme96->spdif_pcm->info_flags = 0;
 
 	/* set up ALSA pcm device for ADAT */
-	if (pci->device == PCI_DEVICE_ID_DIGI96) {
+	if (pci->device == PCI_DEVICE_ID_RME_DIGI96) {
 		/* ADAT is not available on the base model */
 		rme96->adat_pcm = NULL;
 	} else {
@@ -1875,14 +1858,14 @@
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
 	switch (rme96->pci->device) {
-	case PCI_DEVICE_ID_DIGI96:
-	case PCI_DEVICE_ID_DIGI96_8:
+	case PCI_DEVICE_ID_RME_DIGI96:
+	case PCI_DEVICE_ID_RME_DIGI96_8:
 		uinfo->value.enumerated.items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PRO:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
 		uinfo->value.enumerated.items = 4;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
 		if (rme96->rev > 4) {
 			/* PST */
 			uinfo->value.enumerated.items = 4;
@@ -1912,14 +1895,14 @@
 	ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96);
 	
 	switch (rme96->pci->device) {
-	case PCI_DEVICE_ID_DIGI96:
-	case PCI_DEVICE_ID_DIGI96_8:
+	case PCI_DEVICE_ID_RME_DIGI96:
+	case PCI_DEVICE_ID_RME_DIGI96_8:
 		items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PRO:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
 		items = 4;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
 		if (rme96->rev > 4) {
 			/* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */
 			if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) {
@@ -1949,14 +1932,14 @@
 	int change, items = 3;
 	
 	switch (rme96->pci->device) {
-	case PCI_DEVICE_ID_DIGI96:
-	case PCI_DEVICE_ID_DIGI96_8:
+	case PCI_DEVICE_ID_RME_DIGI96:
+	case PCI_DEVICE_ID_RME_DIGI96_8:
 		items = 3;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PRO:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
 		items = 4;
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
 		if (rme96->rev > 4) {
 			items = 4;
 		} else {
@@ -1970,7 +1953,7 @@
 	val = ucontrol->value.enumerated.item[0] % items;
 	
 	/* special case for PST */
-	if (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && rme96->rev > 4) {
+	if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) {
 		if (val == RME96_INPUT_XLR) {
 			val = RME96_INPUT_ANALOG;
 		}
@@ -2392,16 +2375,16 @@
 	
 	strcpy(card->driver, "Digi96");
 	switch (rme96->pci->device) {
-	case PCI_DEVICE_ID_DIGI96:
+	case PCI_DEVICE_ID_RME_DIGI96:
 		strcpy(card->shortname, "RME Digi96");
 		break;
-	case PCI_DEVICE_ID_DIGI96_8:
+	case PCI_DEVICE_ID_RME_DIGI96_8:
 		strcpy(card->shortname, "RME Digi96/8");
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PRO:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PRO:
 		strcpy(card->shortname, "RME Digi96/8 PRO");
 		break;
-	case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST:
+	case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST:
 		pci_read_config_byte(rme96->pci, 8, &val);
 		if (val < 5) {
 			strcpy(card->shortname, "RME Digi96/8 PAD");
@@ -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;