Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
diff --git a/CREDITS b/CREDITS
index 0bf31ea..787564b 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3382,7 +3382,7 @@
 
 N: Geert Uytterhoeven
 E: geert@linux-m68k.org
-W: http://home.tvd.be/cr26864/
+W: http://users.telenet.be/geertu/
 P: 1024/862678A6 C51D 361C 0BD1 4C90 B275  C553 6EEA 11BA 8626 78A6
 D: m68k/Amiga and PPC/CHRP Longtrail coordinator
 D: Frame buffer device and XF68_FBDev maintainer
@@ -3392,8 +3392,8 @@
 D: Atari Falcon chipset IDE
 D: Amiga Gayle chipset IDE
 D: mipsel NEC DDB Vrc-5074
-S: Emiel Vlieberghlaan 2A/21
-S: B-3010 Kessel-Lo
+S: Haterbeekstraat 55B
+S: B-3200 Aarschot
 S: Belgium
 
 N: Chris Vance
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 1af0f2d..2ffb0d6 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -33,7 +33,9 @@
 
 Consistent memory is memory for which a write by either the device or
 the processor can immediately be read by the processor or device
-without having to worry about caching effects.
+without having to worry about caching effects.  (You may however need
+to make sure to flush the processor's write buffers before telling
+devices to read that memory.)
 
 This routine allocates a region of <size> bytes of consistent memory.
 it also returns a <dma_handle> which may be cast to an unsigned
@@ -304,12 +306,12 @@
 could not be created and the driver should take appropriate action (eg
 reduce current DMA mapping usage or delay and try again later).
 
-int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	   enum dma_data_direction direction)
-int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-	   int nents, int direction)
+	int
+	dma_map_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction direction)
+	int
+	pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+		int nents, int direction)
 
 Maps a scatter gather list from the block layer.
 
@@ -327,12 +329,33 @@
 aborting the request or even oopsing is better than doing nothing and
 corrupting the filesystem.
 
-void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-	     int nents, int direction)
+With scatterlists, you use the resulting mapping like this:
+
+	int i, count = dma_map_sg(dev, sglist, nents, direction);
+	struct scatterlist *sg;
+
+	for (i = 0, sg = sglist; i < count; i++, sg++) {
+		hw_address[i] = sg_dma_address(sg);
+		hw_len[i] = sg_dma_len(sg);
+	}
+
+where nents is the number of entries in the sglist.
+
+The implementation is free to merge several consecutive sglist entries
+into one (e.g. with an IOMMU, or if several pages just happen to be
+physically contiguous) and returns the actual number of sg entries it
+mapped them to. On failure 0, is returned.
+
+Then you should loop count times (note: this can be less than nents times)
+and use sg_dma_address() and sg_dma_len() macros where you previously
+accessed sg->address and sg->length as shown above.
+
+	void
+	dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+		int nhwentries, enum dma_data_direction direction)
+	void
+	pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+		int nents, int direction)
 
 unmap the previously mapped scatter/gather list.  All the parameters
 must be the same as those and passed in to the scatter/gather mapping
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index ee4bb73..7c71769 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -58,11 +58,15 @@
 something like __va().  [ EDIT: Update this when we integrate
 Gerd Knorr's generic code which does this. ]
 
-This rule also means that you may not use kernel image addresses
-(ie. items in the kernel's data/text/bss segment, or your driver's)
-nor may you use kernel stack addresses for DMA.  Both of these items
-might be mapped somewhere entirely different than the rest of physical
-memory.
+This rule also means that you may use neither kernel image addresses
+(items in data/text/bss segments), nor module image addresses, nor
+stack addresses for DMA.  These could all be mapped somewhere entirely
+different than the rest of physical memory.  Even if those classes of
+memory could physically work with DMA, you'd need to ensure the I/O
+buffers were cacheline-aligned.  Without that, you'd see cacheline
+sharing problems (data corruption) on CPUs with DMA-incoherent caches.
+(The CPU could write to one word, DMA would write to a different one
+in the same cache line, and one of them could be overwritten.)
 
 Also, this means that you cannot take the return of a kmap()
 call and DMA to/from that.  This is similar to vmalloc().
@@ -194,7 +198,7 @@
 Finally, if your device can only drive the low 24-bits of
 address during PCI bus mastering you might do something like:
 
-	if (pci_set_dma_mask(pdev, 0x00ffffff)) {
+	if (pci_set_dma_mask(pdev, DMA_24BIT_MASK)) {
 		printk(KERN_WARNING
 		       "mydev: 24-bit DMA addressing not available.\n");
 		goto ignore_this_device;
@@ -212,7 +216,7 @@
 functions) and the various different functions have _different_
 DMA addressing limitations, you may wish to probe each mask and
 only provide the functionality which the machine can handle.  It
-is important that the last call to pci_set_dma_mask() be for the 
+is important that the last call to pci_set_dma_mask() be for the
 most specific mask.
 
 Here is pseudo-code showing how this might be done:
@@ -284,6 +288,11 @@
 
              in order to get correct behavior on all platforms.
 
+	     Also, on some platforms your driver may need to flush CPU write
+	     buffers in much the same way as it needs to flush write buffers
+	     found in PCI bridges (such as by reading a register's value
+	     after writing it).
+
 - Streaming DMA mappings which are usually mapped for one DMA transfer,
   unmapped right after it (unless you use pci_dma_sync_* below) and for which
   hardware can optimize for sequential accesses.
@@ -303,6 +312,9 @@
 
 Neither type of DMA mapping has alignment restrictions that come
 from PCI, although some devices may have such restrictions.
+Also, systems with caches that aren't DMA-coherent will work better
+when the underlying buffers don't share cache lines with other data.
+
 
 		 Using Consistent DMA mappings.
 
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 7d87dd7..5a2882d 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -2,7 +2,7 @@
 # This makefile is used to generate the kernel documentation,
 # primarily based on in-line comments in various source files.
 # See Documentation/kernel-doc-nano-HOWTO.txt for instruction in how
-# to ducument the SRC - and how to read it.
+# to document the SRC - and how to read it.
 # To add a new book the only step required is to add the book to the
 # list of DOCBOOKS.
 
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 8c9c670..ca02e04 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -322,7 +322,6 @@
   <chapter id="sysfs">
      <title>The Filesystem for Exporting Kernel Objects</title>
 !Efs/sysfs/file.c
-!Efs/sysfs/dir.c
 !Efs/sysfs/symlink.c
 !Efs/sysfs/bin.c
   </chapter>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 5bcbb6e..f869b03 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -705,7 +705,7 @@
 
 	<sect1><title>ata_scsi_error()</title>
 	<para>
-	ata_scsi_error() is the current hostt->eh_strategy_handler()
+	ata_scsi_error() is the current transportt->eh_strategy_handler()
 	for libata.  As discussed above, this will be entered in two
 	cases - timeout and ATAPI error completion.  This function
 	calls low level libata driver's eng_timeout() callback, the
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 6c9e746..915ae8c 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -603,7 +603,8 @@
 
 
 ----------
-Thanks to Paolo Ciarrocchi who allowed the "Development Process" section
+Thanks to Paolo Ciarrocchi who allowed the "Development Process"
+(http://linux.tar.bz/articles/2.6-development_process) section
 to be based on text he had written, and to Randy Dunlap and Gerrit
 Huizenga for some of the list of things you should and should not say.
 Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
diff --git a/Documentation/acpi-hotkey.txt b/Documentation/acpi-hotkey.txt
index 744f1ae..38040fa 100644
--- a/Documentation/acpi-hotkey.txt
+++ b/Documentation/acpi-hotkey.txt
@@ -30,7 +30,7 @@
 echo "event_num:event_type:event_argument" > 
 	/proc/acpi/hotkey/action.
 The result of the execution of this aml method is 
-attached to /proc/acpi/hotkey/poll_method, which is dnyamically
+attached to /proc/acpi/hotkey/poll_method, which is dynamically
 created.  Please use command "cat /proc/acpi/hotkey/polling_method" 
 to retrieve it.
 
diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
new file mode 100644
index 0000000..5fa130a
--- /dev/null
+++ b/Documentation/block/switching-sched.txt
@@ -0,0 +1,22 @@
+As of the Linux 2.6.10 kernel, it is now possible to change the
+IO scheduler for a given block device on the fly (thus making it possible,
+for instance, to set the CFQ scheduler for the system default, but
+set a specific device to use the anticipatory or noop schedulers - which
+can improve that device's throughput).
+
+To set a specific scheduler, simply do this:
+
+echo SCHEDNAME > /sys/block/DEV/queue/scheduler
+
+where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
+device name (hda, hdb, sga, or whatever you happen to have).
+
+The list of defined schedulers can be found by simply doing
+a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
+will be displayed, with the currently selected scheduler in brackets:
+
+# cat /sys/block/hda/queue/scheduler
+noop anticipatory deadline [cfq]
+# echo anticipatory > /sys/block/hda/queue/scheduler
+# cat /sys/block/hda/queue/scheduler
+noop [anticipatory] deadline cfq
diff --git a/Documentation/cpu-freq/index.txt b/Documentation/cpu-freq/index.txt
index 5009805..ffdb532 100644
--- a/Documentation/cpu-freq/index.txt
+++ b/Documentation/cpu-freq/index.txt
@@ -53,4 +53,4 @@
 * http://lists.linux.org.uk/mailman/listinfo/cpufreq
 
 Clock and voltage scaling for the SA-1100:
-* http://www.lart.tudelft.nl/projects/scaling
+* http://www.lartmaker.nl/projects/scaling
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 59d0c74..421bcff 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -25,8 +25,9 @@
 
 ---------------------------
 
-What:	drivers depending on OBSOLETE_OSS_DRIVER
-When:	January 2006
+What:	drivers that were depending on OBSOLETE_OSS_DRIVER
+        (config options already removed)
+When:	before 2.6.19
 Why:	OSS drivers with ALSA replacements
 Who:	Adrian Bunk <bunk@stusta.de>
 
@@ -71,14 +72,6 @@
 
 ---------------------------
 
-What:	remove EXPORT_SYMBOL(panic_timeout)
-When:	April 2006
-Files:	kernel/panic.c
-Why:	No modular usage in the kernel.
-Who:	Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What:	remove EXPORT_SYMBOL(insert_resource)
 When:	April 2006
 Files:	kernel/resource.c
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index c8bce82..89b1d19 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -246,6 +246,7 @@
 devices/
 firmware/
 net/
+fs/
 
 devices/ contains a filesystem representation of the device tree. It maps
 directly to the internal kernel device tree, which is a hierarchy of
@@ -264,6 +265,10 @@
 for devices on that particular bus (this assumes that drivers do not
 span multiple bus types).
 
+fs/ contains a directory for some filesystems.  Currently each
+filesystem wanting to export attributes must create its own hierarchy
+below fs/ (see ./fuse.txt for an example).
+
 
 More information can driver-model specific features can be found in
 Documentation/driver-model/. 
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index adaa899..3a2e552 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -694,7 +694,7 @@
 ----------------------
 
 This describes how the VFS can manipulate an open file. As of kernel
-2.6.13, the following members are defined:
+2.6.17, the following members are defined:
 
 struct file_operations {
 	loff_t (*llseek) (struct file *, loff_t, int);
@@ -723,6 +723,10 @@
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
 	int (*flock) (struct file *, int, struct file_lock *);
+	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned 
+int);
+	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned  
+int);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -790,6 +794,12 @@
 
   flock: called by the flock(2) system call
 
+  splice_write: called by the VFS to splice data from a pipe to a file. This
+		method is used by the splice(2) system call
+
+  splice_read: called by the VFS to splice data from file to a pipe. This
+	       method is used by the splice(2) system call
+
 Note that the file operations are implemented by the specific
 filesystem in which the inode resides. When opening a device node
 (character or block special) most filesystems will call special
diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
index 0ed9b0a..8b0a5fc 100644
--- a/Documentation/fujitsu/frv/kernel-ABI.txt
+++ b/Documentation/fujitsu/frv/kernel-ABI.txt
@@ -1,17 +1,19 @@
-				 =================================
-				 INTERNAL KERNEL ABI FOR FR-V ARCH
-				 =================================
+			=================================
+			INTERNAL KERNEL ABI FOR FR-V ARCH
+			=================================
 
-The internal FRV kernel ABI is not quite the same as the userspace ABI. A number of the registers
-are used for special purposed, and the ABI is not consistent between modules vs core, and MMU vs
-no-MMU.
+The internal FRV kernel ABI is not quite the same as the userspace ABI. A
+number of the registers are used for special purposed, and the ABI is not
+consistent between modules vs core, and MMU vs no-MMU.
 
-This partly stems from the fact that FRV CPUs do not have a separate supervisor stack pointer, and
-most of them do not have any scratch registers, thus requiring at least one general purpose
-register to be clobbered in such an event. Also, within the kernel core, it is possible to simply
-jump or call directly between functions using a relative offset. This cannot be extended to modules
-for the displacement is likely to be too far. Thus in modules the address of a function to call
-must be calculated in a register and then used, requiring two extra instructions.
+This partly stems from the fact that FRV CPUs do not have a separate
+supervisor stack pointer, and most of them do not have any scratch
+registers, thus requiring at least one general purpose register to be
+clobbered in such an event. Also, within the kernel core, it is possible to
+simply jump or call directly between functions using a relative offset.
+This cannot be extended to modules for the displacement is likely to be too
+far. Thus in modules the address of a function to call must be calculated
+in a register and then used, requiring two extra instructions.
 
 This document has the following sections:
 
@@ -39,7 +41,8 @@
 CPU OPERATING MODES
 ===================
 
-The FR-V CPU has three basic operating modes. In order of increasing capability:
+The FR-V CPU has three basic operating modes. In order of increasing
+capability:
 
   (1) User mode.
 
@@ -47,42 +50,46 @@
 
   (2) Kernel mode.
 
-      Normal kernel mode. There are many additional control registers available that may be
-      accessed in this mode, in addition to all the stuff available to user mode. This has two
-      submodes:
+      Normal kernel mode. There are many additional control registers
+      available that may be accessed in this mode, in addition to all the
+      stuff available to user mode. This has two submodes:
 
       (a) Exceptions enabled (PSR.T == 1).
 
-      	  Exceptions will invoke the appropriate normal kernel mode handler. On entry to the
-      	  handler, the PSR.T bit will be cleared.
+	  Exceptions will invoke the appropriate normal kernel mode
+	  handler. On entry to the handler, the PSR.T bit will be cleared.
 
       (b) Exceptions disabled (PSR.T == 0).
 
-      	  No exceptions or interrupts may happen. Any mandatory exceptions will cause the CPU to
-      	  halt unless the CPU is told to jump into debug mode instead.
+	  No exceptions or interrupts may happen. Any mandatory exceptions
+	  will cause the CPU to halt unless the CPU is told to jump into
+	  debug mode instead.
 
   (3) Debug mode.
 
-      No exceptions may happen in this mode. Memory protection and management exceptions will be
-      flagged for later consideration, but the exception handler won't be invoked. Debugging traps
-      such as hardware breakpoints and watchpoints will be ignored. This mode is entered only by
-      debugging events obtained from the other two modes.
+      No exceptions may happen in this mode. Memory protection and
+      management exceptions will be flagged for later consideration, but
+      the exception handler won't be invoked. Debugging traps such as
+      hardware breakpoints and watchpoints will be ignored. This mode is
+      entered only by debugging events obtained from the other two modes.
 
-      All kernel mode registers may be accessed, plus a few extra debugging specific registers.
+      All kernel mode registers may be accessed, plus a few extra debugging
+      specific registers.
 
 
 =================================
 INTERNAL KERNEL-MODE REGISTER ABI
 =================================
 
-There are a number of permanent register assignments that are set up by entry.S in the exception
-prologue. Note that there is a complete set of exception prologues for each of user->kernel
-transition and kernel->kernel transition. There are also user->debug and kernel->debug mode
-transition prologues.
+There are a number of permanent register assignments that are set up by
+entry.S in the exception prologue. Note that there is a complete set of
+exception prologues for each of user->kernel transition and kernel->kernel
+transition. There are also user->debug and kernel->debug mode transition
+prologues.
 
 
 	REGISTER	FLAVOUR	USE
-	===============	=======	====================================================
+	===============	=======	==============================================
 	GR1			Supervisor stack pointer
 	GR15			Current thread info pointer
 	GR16			GP-Rel base register for small data
@@ -92,10 +99,12 @@
 	GR31		NOMMU	Destroyed by debug mode entry
 	GR31		MMU	Destroyed by TLB miss kernel mode entry
 	CCR.ICC2		Virtual interrupt disablement tracking
-	CCCR.CC3		Cleared by exception prologue (atomic op emulation)
+	CCCR.CC3		Cleared by exception prologue 
+				(atomic op emulation)
 	SCR0		MMU	See mmu-layout.txt.
 	SCR1		MMU	See mmu-layout.txt.
-	SCR2		MMU	Save for EAR0 (destroyed by icache insns in debug mode)
+	SCR2		MMU	Save for EAR0 (destroyed by icache insns 
+					       in debug mode)
 	SCR3		MMU	Save for GR31 during debug exceptions
 	DAMR/IAMR	NOMMU	Fixed memory protection layout.
 	DAMR/IAMR	MMU	See mmu-layout.txt.
@@ -104,18 +113,21 @@
 Certain registers are also used or modified across function calls:
 
 	REGISTER	CALL				RETURN
-	===============	===============================	===============================
+	===============	===============================	======================
 	GR0		Fixed Zero			-
 	GR2		Function call frame pointer
 	GR3		Special				Preserved
 	GR3-GR7		-				Clobbered
-	GR8		Function call arg #1		Return value (or clobbered)
-	GR9		Function call arg #2		Return value MSW (or clobbered)
+	GR8		Function call arg #1		Return value 
+							(or clobbered)
+	GR9		Function call arg #2		Return value MSW 
+							(or clobbered)
 	GR10-GR13	Function call arg #3-#6		Clobbered
 	GR14		-				Clobbered
 	GR15-GR16	Special				Preserved
 	GR17-GR27	-				Preserved
-	GR28-GR31	Special				Only accessed explicitly
+	GR28-GR31	Special				Only accessed 
+							explicitly
 	LR		Return address after CALL	Clobbered
 	CCR/CCCR	-				Mostly Clobbered
 
@@ -124,46 +136,53 @@
 INTERNAL DEBUG-MODE REGISTER ABI
 ================================
 
-This is the same as the kernel-mode register ABI for functions calls. The difference is that in
-debug-mode there's a different stack and a different exception frame. Almost all the global
-registers from kernel-mode (including the stack pointer) may be changed.
+This is the same as the kernel-mode register ABI for functions calls. The
+difference is that in debug-mode there's a different stack and a different
+exception frame. Almost all the global registers from kernel-mode
+(including the stack pointer) may be changed.
 
 	REGISTER	FLAVOUR	USE
-	===============	=======	====================================================
+	===============	=======	==============================================
 	GR1			Debug stack pointer
 	GR16			GP-Rel base register for small data
-	GR31			Current debug exception frame pointer (__debug_frame)
+	GR31			Current debug exception frame pointer 
+				(__debug_frame)
 	SCR3		MMU	Saved value of GR31
 
 
-Note that debug mode is able to interfere with the kernel's emulated atomic ops, so it must be
-exceedingly careful not to do any that would interact with the main kernel in this regard. Hence
-the debug mode code (gdbstub) is almost completely self-contained. The only external code used is
-the sprintf family of functions.
+Note that debug mode is able to interfere with the kernel's emulated atomic
+ops, so it must be exceedingly careful not to do any that would interact
+with the main kernel in this regard. Hence the debug mode code (gdbstub) is
+almost completely self-contained. The only external code used is the
+sprintf family of functions.
 
-Futhermore, break.S is so complicated because single-step mode does not switch off on entry to an
-exception. That means unless manually disabled, single-stepping will blithely go on stepping into
-things like interrupts. See gdbstub.txt for more information.
+Futhermore, break.S is so complicated because single-step mode does not
+switch off on entry to an exception. That means unless manually disabled,
+single-stepping will blithely go on stepping into things like interrupts.
+See gdbstub.txt for more information.
 
 
 ==========================
 VIRTUAL INTERRUPT HANDLING
 ==========================
 
-Because accesses to the PSR is so slow, and to disable interrupts we have to access it twice (once
-to read and once to write), we don't actually disable interrupts at all if we don't have to. What
-we do instead is use the ICC2 condition code flags to note virtual disablement, such that if we
-then do take an interrupt, we note the flag, really disable interrupts, set another flag and resume
-execution at the point the interrupt happened. Setting condition flags as a side effect of an
-arithmetic or logical instruction is really fast. This use of the ICC2 only occurs within the
+Because accesses to the PSR is so slow, and to disable interrupts we have
+to access it twice (once to read and once to write), we don't actually
+disable interrupts at all if we don't have to. What we do instead is use
+the ICC2 condition code flags to note virtual disablement, such that if we
+then do take an interrupt, we note the flag, really disable interrupts, set
+another flag and resume execution at the point the interrupt happened.
+Setting condition flags as a side effect of an arithmetic or logical
+instruction is really fast. This use of the ICC2 only occurs within the
 kernel - it does not affect userspace.
 
 The flags we use are:
 
  (*) CCR.ICC2.Z [Zero flag]
 
-     Set to virtually disable interrupts, clear when interrupts are virtually enabled. Can be
-     modified by logical instructions without affecting the Carry flag.
+     Set to virtually disable interrupts, clear when interrupts are
+     virtually enabled. Can be modified by logical instructions without
+     affecting the Carry flag.
 
  (*) CCR.ICC2.C [Carry flag]
 
@@ -176,8 +195,9 @@
 
 	ICC2.Z is 0, ICC2.C is 1.
 
- (2) An interrupt occurs. The exception prologue examines ICC2.Z and determines that nothing needs
-     doing. This is done simply with an unlikely BEQ instruction.
+ (2) An interrupt occurs. The exception prologue examines ICC2.Z and
+     determines that nothing needs doing. This is done simply with an
+     unlikely BEQ instruction.
 
  (3) The interrupts are disabled (local_irq_disable)
 
@@ -187,48 +207,56 @@
 
 	ICC2.Z would be set to 0.
 
-     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would be used to trap if
-     interrupts were now virtually enabled, but physically disabled - which they're not, so the
-     trap isn't taken. The kernel would then be back to state (1).
+     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
+     be used to trap if interrupts were now virtually enabled, but
+     physically disabled - which they're not, so the trap isn't taken. The
+     kernel would then be back to state (1).
 
- (5) An interrupt occurs. The exception prologue examines ICC2.Z and determines that the interrupt
-     shouldn't actually have happened. It jumps aside, and there disabled interrupts by setting
-     PSR.PIL to 14 and then it clears ICC2.C.
+ (5) An interrupt occurs. The exception prologue examines ICC2.Z and
+     determines that the interrupt shouldn't actually have happened. It
+     jumps aside, and there disabled interrupts by setting PSR.PIL to 14
+     and then it clears ICC2.C.
 
  (6) If interrupts were then saved and disabled again (local_irq_save):
 
-	ICC2.Z would be shifted into the save variable and masked off (giving a 1).
+	ICC2.Z would be shifted into the save variable and masked off 
+	(giving a 1).
 
-	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be unaffected (ie: 0).
+	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
+	unaffected (ie: 0).
 
  (7) If interrupts were then restored from state (6) (local_irq_restore):
 
-	ICC2.Z would be set to indicate the result of XOR'ing the saved value (ie: 1) with 1, which
-	gives a result of 0 - thus leaving ICC2.Z set.
+	ICC2.Z would be set to indicate the result of XOR'ing the saved
+	value (ie: 1) with 1, which gives a result of 0 - thus leaving
+	ICC2.Z set.
 
 	ICC2.C would remain unaffected (ie: 0).
 
-     A TIHI #2 instruction would be used to again assay the current state, but this would do
-     nothing as Z==1.
+     A TIHI #2 instruction would be used to again assay the current state,
+     but this would do nothing as Z==1.
 
  (8) If interrupts were then enabled (local_irq_enable):
 
-	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both flags would now be 0.
+	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
+	flags would now be 0.
 
-     A TIHI #2 instruction again issued to assay the current state would then trap as both Z==0
-     [interrupts virtually enabled] and C==0 [interrupts really disabled] would then be true.
+     A TIHI #2 instruction again issued to assay the current state would
+     then trap as both Z==0 [interrupts virtually enabled] and C==0
+     [interrupts really disabled] would then be true.
 
- (9) The trap #2 handler would simply enable hardware interrupts (set PSR.PIL to 0), set ICC2.C to
-     1 and return.
+ (9) The trap #2 handler would simply enable hardware interrupts 
+     (set PSR.PIL to 0), set ICC2.C to 1 and return.
 
 (10) Immediately upon returning, the pending interrupt would be taken.
 
-(11) The interrupt handler would take the path of actually processing the interrupt (ICC2.Z is
-     clear, BEQ fails as per step (2)).
+(11) The interrupt handler would take the path of actually processing the
+     interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
 
-(12) The interrupt handler would then set ICC2.C to 1 since hardware interrupts are definitely
-     enabled - or else the kernel wouldn't be here.
+(12) The interrupt handler would then set ICC2.C to 1 since hardware
+     interrupts are definitely enabled - or else the kernel wouldn't be here.
 
 (13) On return from the interrupt handler, things would be back to state (1).
 
-This trap (#2) is only available in kernel mode. In user mode it will result in SIGILL.
+This trap (#2) is only available in kernel mode. In user mode it will
+result in SIGILL.
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index d9f23c0..77b995d 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -12,18 +12,22 @@
                       teletext adapters)
 
 It currently supports the following devices:
- * Philips adapter
- * home brew teletext adapter
- * Velleman K8000 adapter
- * ELV adapter
- * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
- * Barco LPT->DVI (K5800236) adapter
+ * (type=0) Philips adapter
+ * (type=1) home brew teletext adapter
+ * (type=2) Velleman K8000 adapter
+ * (type=3) ELV adapter
+ * (type=4) Analog Devices ADM1032 evaluation board
+ * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
+ * (type=6) Barco LPT->DVI (K5800236) adapter
 
 These devices use different pinout configurations, so you have to tell
 the driver what you have, using the type module parameter. There is no
 way to autodetect the devices. Support for different pinout configurations
 can be easily added when needed.
 
+Earlier kernels defaulted to type=0 (Philips).  But now, if the type
+parameter is missing, the driver will simply fail to initialize.
+
 
 Building your own adapter
 -------------------------
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
new file mode 100644
index 0000000..85a64de
--- /dev/null
+++ b/Documentation/isdn/README.gigaset
@@ -0,0 +1,286 @@
+GigaSet 307x Device Driver
+==========================
+
+1.   Requirements
+     ------------
+1.1. Hardware
+     --------
+     This release supports the connection of the Gigaset 307x/417x family of
+     ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
+     connection. The following devices are reported to be compatible:
+     307x/417x:
+        Gigaset SX255isdn
+        Gigaset SX353isdn
+        Sinus 45 [AB] isdn (Deutsche Telekom)
+        Sinus 721X/XA
+        Vox Chicago 390 ISDN (KPN Telecom)
+     M101:
+        Sinus 45 Data 1 (Telekom)
+     M105:
+        Gigaset USB Adapter DECT
+        Sinus 45 Data 2 (Telekom)
+        Sinus 721 data
+        Chicago 390 USB (KPN)
+     See also http://www.erbze.info/sinus_gigaset.htm and
+              http://gigaset307x.sourceforge.net/
+
+     We had also reports from users of Gigaset M105 who could use the drivers
+     with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
+     If you have another device that works with our driver, please let us know.
+     For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
+     are just versions without answering machine of models known to work, so
+     they should work just as well; but so far we are lacking positive reports
+     on these.
+
+     Chances of getting an USB device to work are good if the output of
+        lsusb
+     at the command line contains one of the following:
+        ID 0681:0001
+        ID 0681:0002
+        ID 0681:0009
+        ID 0681:0021
+        ID 0681:0022
+
+1.2. Software
+     --------
+     The driver works with ISDN4linux and so can be used with any software
+     which is able to use ISDN4linux for ISDN connections (voice or data).
+     CAPI4Linux support is planned but not yet available.
+
+     There are some user space tools available at
+     http://sourceforge.net/projects/gigaset307x/
+     which provide access to additional device specific functions like SMS,
+     phonebook or call journal.
+
+
+2.   How to use the driver
+     ---------------------
+2.1. Modules
+     -------
+     To get the device working, you have to load the proper kernel module. You
+     can do this using
+         modprobe modulename
+     where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
+     connection to the base).
+
+2.2. Device nodes for user space programs
+     ------------------------------------
+     The device can be accessed from user space (eg. by the user space tools
+     mentioned in 1.2.) through the device nodes:
+
+     - /dev/ttyGU0 for M105 (USB data boxes)
+     - /dev/ttyGB0 for the base driver (direct USB connection)
+
+     You can also select a "default device" which is used by the frontends when
+     no device node is given as parameter, by creating a symlink /dev/ttyG to
+     one of them, eg.:
+
+        ln -s /dev/ttyGB0 /dev/ttyG
+
+2.3. ISDN4linux
+     ----------
+     This is the "normal" mode of operation. After loading the module you can
+     set up the ISDN system just as you'd do with any ISDN card.
+     Your distribution should provide some configuration utility.
+     If not, you can use some HOWTOs like
+         http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
+     If this doesn't work, because you have some recent device like SX100 where
+     debug output (see section 3.2.) shows something like this when dialing
+         CMD Received: ERROR
+         Available Params: 0
+         Connection State: 0, Response: -1
+         gigaset_process_response: resp_code -1 in ConState 0 !
+         Timeout occurred
+     you might need to use unimodem mode:
+
+2.4. Unimodem mode
+     -------------
+     This is needed for some devices [e.g. SX100] as they have problems with
+     the "normal" commands.
+
+     If you have installed the command line tool gigacontr, you can enter
+     unimodem mode using
+         gigacontr --mode unimodem
+     You can switch back using
+         gigacontr --mode isdn
+
+     You can also load the driver using e.g.
+         modprobe usb_gigaset startmode=0
+     to prevent the driver from starting in "isdn4linux mode".
+
+     In this mode the device works like a modem connected to a serial port
+     (the /dev/ttyGU0, ... mentioned above) which understands the commands
+         ATZ                 init, reset
+             => OK or ERROR
+         ATD
+         ATDT                dial
+             => OK, CONNECT,
+                BUSY,
+                NO DIAL TONE,
+                NO CARRIER,
+                NO ANSWER
+         <pause>+++<pause>   change to command mode when connected
+         ATH                 hangup
+
+     You can use some configuration tool of your distribution to configure this
+     "modem" or configure pppd/wvdial manually. There are some example ppp
+     configuration files and chat scripts in the gigaset-VERSION/ppp directory.
+     Please note that the USB drivers are not able to change the state of the
+     control lines (the M105 driver can be configured to use some undocumented
+     control requests, if you really need the control lines, though). This means
+     you must use "Stupid Mode" if you are using wvdial or you should use the
+     nocrtscts option of pppd.
+     You must also assure that the ppp_async module is loaded with the parameter
+     flag_time=0. You can do this e.g. by adding a line like
+
+        options ppp_async flag_time=0
+
+     to /etc/modprobe.conf. If your distribution has some local module
+     configuration file like /etc/modprobe.conf.local,
+     using that should be preferred.
+
+2.5. Call-ID (CID) mode
+     ------------------
+     Call-IDs are numbers used to tag commands to, and responses from, the
+     Gigaset base in order to support the simultaneous handling of multiple
+     ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem
+     mode"). Without Call-IDs (in Unimodem mode), only a very limited set of
+     functions is available. It allows outgoing data connections only, but
+     does not signal incoming calls or other base events.
+
+     DECT cordless data devices (M10x) permanently occupy the cordless
+     connection to the base while Call-IDs are activated. As the Gigaset
+     bases only support one DECT data connection at a time, this prevents
+     other DECT cordless data devices from accessing the base.
+
+     During active operation, the driver switches to the necessary mode
+     automatically. However, for the reasons above, the mode chosen when
+     the device is not in use (idle) can be selected by the user.
+     - If you want to receive incoming calls, you can use the default
+       settings (CID mode).
+     - If you have several DECT data devices (M10x) which you want to use
+       in turn, select Unimodem mode by passing the parameter "cidmode=0" to
+       the driver ("modprobe usb_gigaset cidmode=0" or modprobe.conf).
+
+     If you want both of these at once, you are out of luck.
+
+     You can also use /sys/module/<name>/parameters/cidmode for changing
+     the CID mode setting (<name> is usb_gigaset or bas_gigaset).
+
+
+3.   Troubleshooting
+     ---------------
+3.1. Solutions to frequently reported problems
+     -----------------------------------------
+     Problem:
+        You have a slow provider and isdn4linux gives up dialing too early.
+     Solution:
+        Load the isdn module using the dialtimeout option. You can do this e.g.
+        by adding a line like
+
+           options isdn dialtimeout=15
+
+        to /etc/modprobe.conf. If your distribution has some local module
+        configuration file like /etc/modprobe.conf.local,
+        using that should be preferred.
+
+     Problem:
+        Your isdn script aborts with a message about isdnlog.
+     Solution:
+        Try deactivating (or commenting out) isdnlog. This driver does not
+        support it.
+
+     Problem:
+        You have two or more DECT data adapters (M101/M105) and only the
+        first one you turn on works.
+     Solution:
+        Select Unimodem mode for all DECT data adapters. (see section 2.4.)
+
+3.2. Telling the driver to provide more information
+     ----------------------------------------------
+     Building the driver with the "Gigaset debugging" kernel configuration
+     option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional
+     information useful for debugging.
+
+     You can control the amount of debugging information the driver produces by
+     writing an appropriate value to /sys/module/gigaset/parameters/debug, e.g.
+        echo 0 > /sys/module/gigaset/parameters/debug
+     switches off debugging output completely,
+        echo 0x10a020 > /sys/module/gigaset/parameters/debug
+     enables the standard set of debugging output messages. These values are
+     bit patterns where every bit controls a certain type of debugging output.
+     See the constants DEBUG_* in the source file gigaset.h for details.
+
+     The initial value can be set using the debug parameter when loading the
+     module "gigaset", e.g. by adding a line
+        options gigaset debug=0
+     to /etc/modprobe.conf, ...
+
+     Generated debugging information can be found
+     - as output of the command
+         dmesg
+     - in system log files written by your syslog daemon, usually
+       in /var/log/, e.g. /var/log/messages.
+
+3.3. Reporting problems and bugs
+     ---------------------------
+     If you can't solve problems with the driver on your own, feel free to
+     use one of the forums, bug trackers, or mailing lists on
+         http://sourceforge.net/projects/gigaset307x
+     or write an electronic mail to the maintainers.
+
+     Try to provide as much information as possible, such as
+     - distribution
+     - kernel version (uname -r)
+     - gcc version (gcc --version)
+     - hardware architecture (uname -m, ...)
+     - type and firmware version of your device (base and wireless module,
+       if any)
+     - output of "lsusb -v" (if using an USB device)
+     - error messages
+     - relevant system log messages (it would help if you activate debug
+       output as described in 3.2.)
+
+     For help with general configuration problems not specific to our driver,
+     such as isdn4linux and network configuration issues, please refer to the
+     appropriate forums and newsgroups.
+
+3.4. Reporting problem solutions
+     ---------------------------
+     If you solved a problem with our drivers, wrote startup scripts for your
+     distribution, ... feel free to contact us (using one of the places
+     mentioned in 3.3.). We'd like to add scripts, hints, documentation
+     to the driver and/or the project web page.
+
+
+4.   Links, other software
+     ---------------------
+     - Sourceforge project developing this driver and associated tools
+         http://sourceforge.net/projects/gigaset307x
+     - Yahoo! Group on the Siemens Gigaset family of devices
+         http://de.groups.yahoo.com/group/Siemens-Gigaset
+     - Siemens Gigaset/T-Sinus compatibility table
+         http://www.erbze.info/sinus_gigaset.htm
+
+
+5.   Credits
+     -------
+     Thanks to
+
+     Karsten Keil
+        for his help with isdn4linux
+     Deti Fliegl
+        for his base driver code
+     Dennis Dietrich
+        for his kernel 2.6 patches
+     Andreas Rummel
+        for his work and logs to get unimodem mode working
+     Andreas Degert
+        for his logs and patches to get cx 100 working
+     Dietrich Feist
+        for his generous donation of one M105 and two M101 cordless adapters
+     Christoph Schweers
+        for his generous donation of a M34 device
+
+     and all the other people who sent logs and other information.
+
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index fcccf24..61fc079 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -44,7 +44,7 @@
 of modules. The author of an external modules should supply
 a makefile that hides most of the complexity so one only has to type
 'make' to build the module. A complete example will be present in
-chapter ¤. Creating a kbuild file for an external module".
+chapter 4, "Creating a kbuild file for an external module".
 
 
 === 2. How to build external modules
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f8cb55c..b3a6187 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1,4 +1,4 @@
-February 2003             Kernel Parameters                     v2.5.59
+                          Kernel Parameters
                           ~~~~~~~~~~~~~~~~~
 
 The following is a consolidated list of the kernel parameters as implemented
@@ -17,9 +17,17 @@
 
 	usbcore.blinkenlights=1
 
-The text in square brackets at the beginning of the description states the
-restrictions on the kernel for the said kernel parameter to be valid. The
-restrictions referred to are that the relevant option is valid if:
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable:
 
 	ACPI	ACPI support is enabled.
 	ALSA	ALSA sound support is enabled.
@@ -1046,10 +1054,10 @@
 	noltlbs		[PPC] Do not use large page/tlb entries for kernel
 			lowmem mapping on PPC40x.
 
-	nomce		[IA-32] Machine Check Exception
-
 	nomca		[IA-64] Disable machine check abort handling
 
+	nomce		[IA-32] Machine Check Exception
+
 	noresidual	[PPC] Don't use residual data on PReP machines.
 
 	noresume	[SWSUSP] Disables resume and restores original swap
@@ -1682,20 +1690,6 @@
 
 
 ______________________________________________________________________
-Changelog:
-
-2000-06-??	Mr. Unknown
-	The last known update (for 2.4.0) - the changelog was not kept before.
-
-2002-11-24	Petr Baudis <pasky@ucw.cz>
-		Randy Dunlap <randy.dunlap@verizon.net>
-	Update for 2.5.49, description for most of the options introduced,
-	references to other documentation (C files, READMEs, ..), added S390,
-	PPC, SPARC, MTD, ALSA and OSS category. Minor corrections and
-	reformatting.
-
-2005-10-19	Randy Dunlap <rdunlap@xenotime.net>
-	Lots of typos, whitespace, some reformatting.
 
 TODO:
 
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index b18e216..5696e87 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -919,11 +919,11 @@
     int settle_time = 60;
 
     /* Parse the simple command-line */
-    if (ac == 2)
-	disk = av[1];
-    else if (ac == 4) {
-	settle_time = atoi(av[2]);
-	disk = av[3];
+    if (argc == 2)
+	disk = argv[1];
+    else if (argc == 4) {
+	settle_time = atoi(argv[2]);
+	disk = argv[3];
     } else
 	usage();
 
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index f855031..92f0056 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -610,6 +610,7 @@
 
 	CPU 1			CPU 2
 	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
 	STORE A = 1
 	STORE B = 2
 	<write barrier>
@@ -651,7 +652,20 @@
 (which would be B) coming after the the LOAD of C.
 
 If, however, a data dependency barrier were to be placed between the load of C
-and the load of *C (ie: B) on CPU 2, then the following will occur:
+and the load of *C (ie: B) on CPU 2:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
+	STORE A = 1
+	STORE B = 2
+	<write barrier>
+	STORE C = &B		LOAD X
+	STORE D = 4		LOAD C (gets &B)
+				<data dependency barrier>
+				LOAD *C (reads B)
+
+then the following will occur:
 
 	+-------+       :      :                :       :
 	|       |       +------+                +-------+
@@ -829,8 +843,8 @@
  (*) smp_mb__after_atomic_inc();
 
      These are for use with atomic add, subtract, increment and decrement
-     functions, especially when used for reference counting.  These functions
-     do not imply memory barriers.
+     functions that don't return a value, especially when used for reference
+     counting.  These functions do not imply memory barriers.
 
      As an example, consider a piece of code that marks an object as being dead
      and then decrements the object's reference count:
@@ -1263,15 +1277,17 @@
 ATOMIC OPERATIONS
 -----------------
 
-Though they are technically interprocessor interaction considerations, atomic
-operations are noted specially as they do _not_ generally imply memory
-barriers.  The possible offenders include:
+Whilst they are technically interprocessor interaction considerations, atomic
+operations are noted specially as some of them imply full memory barriers and
+some don't, but they're very heavily relied on as a group throughout the
+kernel.
+
+Any atomic operation that modifies some state in memory and returns information
+about the state (old or new) implies an SMP-conditional general memory barrier
+(smp_mb()) on each side of the actual operation.  These include:
 
 	xchg();
 	cmpxchg();
-	test_and_set_bit();
-	test_and_clear_bit();
-	test_and_change_bit();
 	atomic_cmpxchg();
 	atomic_inc_return();
 	atomic_dec_return();
@@ -1282,21 +1298,31 @@
 	atomic_sub_and_test();
 	atomic_add_negative();
 	atomic_add_unless();
+	test_and_set_bit();
+	test_and_clear_bit();
+	test_and_change_bit();
 
-These may be used for such things as implementing LOCK operations or controlling
-the lifetime of objects by decreasing their reference counts.  In such cases
-they need preceding memory barriers.
+These are used for such things as implementing LOCK-class and UNLOCK-class
+operations and adjusting reference counters towards object destruction, and as
+such the implicit memory barrier effects are necessary.
 
-The following may also be possible offenders as they may be used as UNLOCK
-operations.
 
+The following operation are potential problems as they do _not_ imply memory
+barriers, but might be used for implementing such things as UNLOCK-class
+operations:
+
+	atomic_set();
 	set_bit();
 	clear_bit();
 	change_bit();
-	atomic_set();
+
+With these the appropriate explicit memory barrier should be used if necessary
+(smp_mb__before_clear_bit() for instance).
 
 
-The following are a little tricky:
+The following also do _not_ imply memory barriers, and so may require explicit
+memory barriers under some circumstances (smp_mb__before_atomic_dec() for
+instance)):
 
 	atomic_add();
 	atomic_sub();
@@ -1317,10 +1343,12 @@
 
 
 Basically, each usage case has to be carefully considered as to whether memory
-barriers are needed or not.  The simplest rule is probably: if the atomic
-operation is protected by a lock, then it does not require a barrier unless
-there's another operation within the critical section with respect to which an
-ordering must be maintained.
+barriers are needed or not.
+
+[!] Note that special memory barrier primitives are available for these
+situations because on some CPUs the atomic instructions used imply full memory
+barriers, and so barrier instructions are superfluous in conjunction with them,
+and in such cases the special barrier primitives will be no-ops.
 
 See Documentation/atomic_ops.txt for more information.
 
diff --git a/Documentation/mtrr.txt b/Documentation/mtrr.txt
index b78af1c32..c39ac39 100644
--- a/Documentation/mtrr.txt
+++ b/Documentation/mtrr.txt
@@ -138,19 +138,29 @@
 
 */
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <errno.h>
-#define MTRR_NEED_STRINGS
 #include <asm/mtrr.h>
 
 #define TRUE 1
 #define FALSE 0
 #define ERRSTRING strerror (errno)
 
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+    "uncachable",               /* 0 */
+    "write-combining",          /* 1 */
+    "?",                        /* 2 */
+    "?",                        /* 3 */
+    "write-through",            /* 4 */
+    "write-protect",            /* 5 */
+    "write-back",               /* 6 */
+};
 
 int main ()
 {
@@ -232,13 +242,22 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <errno.h>
-#define MTRR_NEED_STRINGS
 #include <asm/mtrr.h>
 
 #define TRUE 1
 #define FALSE 0
 #define ERRSTRING strerror (errno)
 
+static char *mtrr_strings[MTRR_NUM_TYPES] =
+{
+    "uncachable",               /* 0 */
+    "write-combining",          /* 1 */
+    "?",                        /* 2 */
+    "?",                        /* 3 */
+    "write-through",            /* 4 */
+    "write-protect",            /* 5 */
+    "write-back",               /* 6 */
+};
 
 int main (int argc, char **argv)
 {
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt
index 4fc8e98..aaf99d5 100644
--- a/Documentation/networking/packet_mmap.txt
+++ b/Documentation/networking/packet_mmap.txt
@@ -254,7 +254,7 @@
 
 	<block number> * <block size> / <frame size>
 
-Suposse the following parameters, which apply for 2.6 kernel and an
+Suppose the following parameters, which apply for 2.6 kernel and an
 i386 architecture:
 
 	<size-max> = 131072 bytes
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index ec3d109..76750fb 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -138,7 +138,7 @@
 ethernet frames when using tap.
 
 5. What is the difference between BPF and TUN/TAP driver?
-BFP is an advanced packet filter. It can be attached to existing
+BPF is an advanced packet filter. It can be attached to existing
 network interface. It does not provide a virtual network interface.
 A TUN/TAP driver does provide a virtual network interface and it is possible
 to attach BPF to this interface.
diff --git a/Documentation/networking/xfrm_sync.txt b/Documentation/networking/xfrm_sync.txt
new file mode 100644
index 0000000..8be626f
--- /dev/null
+++ b/Documentation/networking/xfrm_sync.txt
@@ -0,0 +1,166 @@
+
+The sync patches work is based on initial patches from
+Krisztian <hidden@balabit.hu> and others and additional patches
+from Jamal <hadi@cyberus.ca>.
+
+The end goal for syncing is to be able to insert attributes + generate
+events so that the an SA can be safely moved from one machine to another
+for HA purposes.
+The idea is to synchronize the SA so that the takeover machine can do
+the processing of the SA as accurate as possible if it has access to it.
+
+We already have the ability to generate SA add/del/upd events.
+These patches add ability to sync and have accurate lifetime byte (to
+ensure proper decay of SAs) and replay counters to avoid replay attacks
+with as minimal loss at failover time.
+This way a backup stays as closely uptodate as an active member.
+
+Because the above items change for every packet the SA receives,
+it is possible for a lot of the events to be generated.
+For this reason, we also add a nagle-like algorithm to restrict
+the events. i.e we are going to set thresholds to say "let me
+know if the replay sequence threshold is reached or 10 secs have passed"
+These thresholds are set system-wide via sysctls or can be updated
+per SA.
+
+The identified items that need to be synchronized are:
+- the lifetime byte counter
+note that: lifetime time limit is not important if you assume the failover
+machine is known ahead of time since the decay of the time countdown
+is not driven by packet arrival.
+- the replay sequence for both inbound and outbound
+
+1) Message Structure
+----------------------
+
+nlmsghdr:aevent_id:optional-TLVs.
+
+The netlink message types are:
+
+XFRM_MSG_NEWAE and XFRM_MSG_GETAE.
+
+A XFRM_MSG_GETAE does not have TLVs.
+A XFRM_MSG_NEWAE will have at least two TLVs (as is
+discussed further below).
+
+aevent_id structure looks like:
+
+   struct xfrm_aevent_id {
+             struct xfrm_usersa_id           sa_id;
+             __u32                           flags;
+   };
+
+xfrm_usersa_id in this message layout identifies the SA.
+
+flags are used to indicate different things. The possible
+flags are:
+        XFRM_AE_RTHR=1, /* replay threshold*/
+        XFRM_AE_RVAL=2, /* replay value */
+        XFRM_AE_LVAL=4, /* lifetime value */
+        XFRM_AE_ETHR=8, /* expiry timer threshold */
+        XFRM_AE_CR=16, /* Event cause is replay update */
+        XFRM_AE_CE=32, /* Event cause is timer expiry */
+        XFRM_AE_CU=64, /* Event cause is policy update */
+
+How these flags are used is dependent on the direction of the
+message (kernel<->user) as well the cause (config, query or event).
+This is described below in the different messages.
+
+The pid will be set appropriately in netlink to recognize direction
+(0 to the kernel and pid = processid that created the event
+when going from kernel to user space)
+
+A program needs to subscribe to multicast group XFRMNLGRP_AEVENTS
+to get notified of these events.
+
+2) TLVS reflect the different parameters:
+-----------------------------------------
+
+a) byte value (XFRMA_LTIME_VAL)
+This TLV carries the running/current counter for byte lifetime since
+last event.
+
+b)replay value (XFRMA_REPLAY_VAL)
+This TLV carries the running/current counter for replay sequence since
+last event.
+
+c)replay threshold (XFRMA_REPLAY_THRESH)
+This TLV carries the threshold being used by the kernel to trigger events
+when the replay sequence is exceeded.
+
+d) expiry timer (XFRMA_ETIMER_THRESH)
+This is a timer value in milliseconds which is used as the nagle
+value to rate limit the events.
+
+3) Default configurations for the parameters:
+----------------------------------------------
+
+By default these events should be turned off unless there is
+at least one listener registered to listen to the multicast
+group XFRMNLGRP_AEVENTS.
+
+Programs installing SAs will need to specify the two thresholds, however,
+in order to not change existing applications such as racoon
+we also provide default threshold values for these different parameters
+in case they are not specified.
+
+the two sysctls/proc entries are:
+a) /proc/sys/net/core/sysctl_xfrm_aevent_etime
+used to provide default values for the XFRMA_ETIMER_THRESH in incremental
+units of time of 100ms. The default is 10 (1 second)
+
+b) /proc/sys/net/core/sysctl_xfrm_aevent_rseqth
+used to provide default values for XFRMA_REPLAY_THRESH parameter
+in incremental packet count. The default is two packets.
+
+4) Message types
+----------------
+
+a) XFRM_MSG_GETAE issued by user-->kernel.
+XFRM_MSG_GETAE does not carry any TLVs.
+The response is a XFRM_MSG_NEWAE which is formatted based on what
+XFRM_MSG_GETAE queried for.
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+*if XFRM_AE_RTHR flag is set, then XFRMA_REPLAY_THRESH is also retrieved
+*if XFRM_AE_ETHR flag is set, then XFRMA_ETIMER_THRESH is also retrieved
+
+b) XFRM_MSG_NEWAE is issued by either user space to configure
+or kernel to announce events or respond to a XFRM_MSG_GETAE.
+
+i) user --> kernel to configure a specific SA.
+any of the values or threshold parameters can be updated by passing the
+appropriate TLV.
+A response is issued back to the sender in user space to indicate success
+or failure.
+In the case of success, additionally an event with
+XFRM_MSG_NEWAE is also issued to any listeners as described in iii).
+
+ii) kernel->user direction as a response to XFRM_MSG_GETAE
+The response will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+The threshold TLVs will be included if explicitly requested in
+the XFRM_MSG_GETAE message.
+
+iii) kernel->user to report as event if someone sets any values or
+thresholds for an SA using XFRM_MSG_NEWAE (as described in #i above).
+In such a case XFRM_AE_CU flag is set to inform the user that
+the change happened as a result of an update.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+iv) kernel->user to report event when replay threshold or a timeout
+is exceeded.
+In such a case either XFRM_AE_CR (replay exceeded) or XFRM_AE_CE (timeout
+happened) is set to inform the user what happened.
+Note the two flags are mutually exclusive.
+The message will always have XFRMA_LTIME_VAL and XFRMA_REPLAY_VAL TLVs.
+
+Exceptions to threshold settings
+--------------------------------
+
+If you have an SA that is getting hit by traffic in bursts such that
+there is a period where the timer threshold expires with no packets
+seen, then an odd behavior is seen as follows:
+The first packet arrival after a timer expiry will trigger a timeout
+aevent; i.e we dont wait for a timeout period or a packet threshold
+to be reached. This is done for simplicity and efficiency reasons.
+
+-JHS
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 711210b..66bbbf1 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -259,7 +259,17 @@
 to be handled by platform and generic code, not individual drivers.
 
 
-8. Obsolete functions
+8. Vendor and device identifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For the future, let's avoid adding device ids to include/linux/pci_ids.h.
+
+PCI_VENDOR_ID_xxx for vendors, and a hex constant for device ids.
+
+Rationale:  PCI_VENDOR_ID_xxx constants are re-used, but device ids are not.
+    Further, device ids are arbitrary hex numbers, normally used only in a
+    single location, the pci_device_id table.
+
+9. Obsolete functions
 ~~~~~~~~~~~~~~~~~~~~~
 There are several functions which you might come across when trying to
 port an old driver to the new PCI interface.  They are no longer present
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 97420f0..4739c5c 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* New release helper (as of 2.6.17)
+   Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
+   necessary now is calling pcmcia_disable_device. As there is no valid
+   reason left to call pcmcia_release_io and pcmcia_release_irq, the
+   exports for them were removed.
+
 * Unify detach and REMOVAL event code, as well as attach and INSERTION
   code (as of 2.6.16)
        void (*remove)          (struct pcmcia_device *dev);
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index d18a57d..43a889f 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -140,7 +140,7 @@
 IBM TP T42			s3_bios (2)
 IBM ThinkPad T42p (2373-GTG)	s3_bios (2)
 IBM TP X20			??? (*)
-IBM TP X30			s3_bios (2)
+IBM TP X30			s3_bios, s3_mode (4)
 IBM TP X31 / Type 2672-XXH      none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
 IBM TP X32			none (1), but backlight is on and video is trashed after long suspend. s3_bios,s3_mode (4) works too. Perhaps that gets better results?
 IBM Thinkpad X40 Type 2371-7JG  s3_bios,s3_mode (4)
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index 331afd7..ce767b9 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -19,9 +19,9 @@
 	[2-1-1] Overview
 	[2-1-2] Flow of scmds through EH
 	[2-1-3] Flow of control
-    [2-2] EH through hostt->eh_strategy_handler()
-	[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
-	[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+    [2-2] EH through transportt->eh_strategy_handler()
+	[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
+	[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
 	[2-2-3] Things to consider
 
 
@@ -413,9 +413,9 @@
 	    layer of failure of the scmds.
 
 
-[2-2] EH through hostt->eh_strategy_handler()
+[2-2] EH through transportt->eh_strategy_handler()
 
- hostt->eh_strategy_handler() is invoked in the place of
+ transportt->eh_strategy_handler() is invoked in the place of
 scsi_unjam_host() and it is responsible for whole recovery process.
 On completion, the handler should have made lower layers forget about
 all failed scmds and either ready for new commands or offline.  Also,
@@ -424,7 +424,7 @@
 except for #1 must be implemented by eh_strategy_handler().
 
 
-[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions
 
  The following conditions are true on entry to the handler.
 
@@ -437,7 +437,7 @@
  - shost->host_failed == shost->host_busy
 
 
-[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions
+[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions
 
  The following conditions must be true on exit from the handler.
 
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 8bbae3e..75a535a 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -804,7 +804,6 @@
    eh_bus_reset_handler - issue SCSI bus reset
    eh_device_reset_handler - issue SCSI device reset
    eh_host_reset_handler - reset host (host bus adapter)
-   eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
    info - supply information about given host
    ioctl - driver can respond to ioctls
    proc_info - supports /proc/scsi/{driver_name}/{host_no}
@@ -970,24 +969,6 @@
 
 
 /**
- *      eh_strategy_handler - driver supplied alternate to scsi_unjam_host()
- *      @shp: host on which error has occurred
- *
- *      Returns TRUE if host unjammed, else FALSE.
- *
- *      Locks: none
- *
- *      Calling context: kernel thread
- *
- *      Notes: Invoked from scsi_eh thread. LLD supplied alternate to 
- *      scsi_unjam_host() found in scsi_error.c
- *
- *      Optionally defined in: LLD
- **/
-     int eh_strategy_handler(struct Scsi_Host * shp)
-
-
-/**
  *      info - supply information about given host: driver name plus data
  *             to distinguish given host
  *      @shp: host to supply information about
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 42ef997..df82116 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -3,14 +3,11 @@
 			--------------------
 
 
-   $Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
-
-
 This document is meant as a brief overview of some aspects of the new serial
 driver.  It is not complete, any questions you have should be directed to
 <rmk@arm.linux.org.uk>
 
-The reference implementation is contained within serial_amba.c.
+The reference implementation is contained within amba_pl011.c.
 
 
 
@@ -31,6 +28,11 @@
 the correct port structure (via uart_get_console) and decoding command line
 arguments (uart_parse_options).
 
+There is also a helper function (uart_write_console) which performs a
+character by character write, translating newlines to CRLF sequences.
+Driver writers are recommended to use this function rather than implementing
+their own version.
+
 
 Locking
 -------
@@ -86,6 +88,7 @@
 		- TIOCM_DTR	DTR signal.
 		- TIOCM_OUT1	OUT1 signal.
 		- TIOCM_OUT2	OUT2 signal.
+		- TIOCM_LOOP	Set the port into loopback mode.
 	If the appropriate bit is set, the signal should be driven
 	active.  If the bit is clear, the signal should be driven
 	inactive.
@@ -141,6 +144,10 @@
   enable_ms(port)
 	Enable the modem status interrupts.
 
+	This method may be called multiple times.  Modem status
+	interrupts should be disabled when the shutdown method is
+	called.
+
 	Locking: port->lock taken.
 	Interrupts: locally disabled.
 	This call must not sleep
@@ -160,6 +167,8 @@
 	state.  Enable the port for reception.  It should not activate
 	RTS nor DTR; this will be done via a separate call to set_mctrl.
 
+	This method will only be called when the port is initially opened.
+
 	Locking: port_sem taken.
 	Interrupts: globally disabled.
 
@@ -169,6 +178,11 @@
 	RTS nor DTR; this will have already been done via a separate
 	call to set_mctrl.
 
+	Drivers must not access port->info once this call has completed.
+
+	This method will only be called when there are no more users of
+	this port.
+
 	Locking: port_sem taken.
 	Interrupts: caller dependent.
 
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 1def604..0ee2c7d 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -120,6 +120,34 @@
     enable  	- enable card
 		- Default: enabled, for PCI and ISA PnP cards
 
+  Module snd-adlib
+  ----------------
+
+    Module for AdLib FM cards.
+
+    port	- port # for OPL chip
+
+    This module supports multiple cards. It does not support autoprobe, so
+    the port must be specified. For actual AdLib FM cards it will be 0x388.
+    Note that this card does not have PCM support and no mixer; only FM
+    synthesis.
+
+    Make sure you have "sbiload" from the alsa-tools package available and,
+    after loading the module, find out the assigned ALSA sequencer port
+    number through "sbiload -l". Example output:
+
+      Port     Client name                       Port name
+      64:0     OPL2 FM synth                     OPL2 FM Port
+
+    Load the std.sb and drums.sb patches also supplied by sbiload:
+
+      sbiload -p 64:0 std.sb drums.sb
+
+    If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
+    instead. To have the card produce sound, use aplaymidi from alsa-utils:
+
+      aplaymidi -p 64:0 foo.mid
+
   Module snd-ad1816a
   ------------------
 
@@ -190,6 +218,15 @@
 
     The power-management is supported.
 
+  Module snd-als300
+  -----------------
+
+    Module for  Avance Logic ALS300 and ALS300+
+
+    This module supports multiple cards.
+
+    The power-management is supported.
+
   Module snd-als4000
   ------------------
 
@@ -701,6 +738,7 @@
 	  uniwill	3-jack
 	  F1734		2-jack
 	  lg		LG laptop (m1 express dual)
+	  lg-lw		LG LW20 laptop
 	  test		for testing/debugging purpose, almost all controls can be
 			adjusted.  Appearing only when compiled with
 			$CONFIG_SND_DEBUG=y
@@ -1013,6 +1051,23 @@
 
     The power-management is supported.
 
+  Module snd-miro
+  ---------------
+
+    Module for Miro soundcards: miroSOUND PCM 1 pro, 
+				miroSOUND PCM 12,
+				miroSOUND PCM 20 Radio.
+
+    port	- Port # (0x530,0x604,0xe80,0xf40)
+    irq		- IRQ # (5,7,9,10,11)
+    dma1	- 1st dma # (0,1,3)
+    dma2	- 2nd dma # (0,1)
+    mpu_port	- MPU-401 port # (0x300,0x310,0x320,0x330)
+    mpu_irq	- MPU-401 irq # (5,7,9,10)
+    fm_port	- FM Port # (0x388)
+    wss		- enable WSS mode
+    ide		- enable onboard ide support
+
   Module snd-mixart
   -----------------
 
@@ -1202,6 +1257,20 @@
 
     The power-management is supported.
 
+  Module snd-riptide
+  ------------------
+
+    Module for Conexant Riptide chip
+
+      joystick_port	- Joystick port # (default: 0x200)
+      mpu_port		- MPU401 port # (default: 0x330)
+      opl3_port		- OPL3 port # (default: 0x388)
+
+    This module supports multiple cards.
+    The driver requires the firmware loader support on kernel.
+    You need to install the firmware file "riptide.hex" to the standard
+    firmware path (e.g. /lib/firmware).
+
   Module snd-rme32
   ----------------
 
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 6feef9e..68eeebc 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1123,8 +1123,8 @@
           if ((err = pci_enable_device(pci)) < 0)
                   return err;
           /* check PCI availability (28bit DMA) */
-          if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
-              pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+          if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+              pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
                   printk(KERN_ERR "error to set 28bit mask DMA\n");
                   pci_disable_device(pci);
                   return -ENXIO;
@@ -1216,7 +1216,7 @@
         The allocation of PCI resources is done in the
       <function>probe()</function> function, and usually an extra
       <function>xxx_create()</function> function is written for this
-      purpose. 
+      purpose.
       </para>
 
       <para>
@@ -1225,7 +1225,7 @@
       allocating resources. Also, you need to set the proper PCI DMA
       mask to limit the accessed i/o range. In some cases, you might
       need to call <function>pci_set_master()</function> function,
-      too. 
+      too.
       </para>
 
       <para>
@@ -1236,8 +1236,8 @@
 <![CDATA[
   if ((err = pci_enable_device(pci)) < 0)
           return err;
-  if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
-      pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+  if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+      pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
           printk(KERN_ERR "error to set 28bit mask DMA\n");
           pci_disable_device(pci);
           return -ENXIO;
@@ -1256,13 +1256,13 @@
       functions. Unlike ALSA ver.0.5.x., there are no helpers for
       that. And these resources must be released in the destructor
       function (see below). Also, on ALSA 0.9.x, you don't need to
-      allocate (pseudo-)DMA for PCI like ALSA 0.5.x. 
+      allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
       </para>
 
       <para>
         Now assume that this PCI device has an I/O port with 8 bytes
         and an interrupt. Then struct <structname>mychip</structname> will have the
-        following fields: 
+        following fields:
 
         <informalexample>
           <programlisting>
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 8c71954..bca5090 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -52,7 +52,7 @@
  51 -> ProVideo PV952                           [1540:9524]
  52 -> AverMedia AverTV/305                     [1461:2108]
  53 -> ASUS TV-FM 7135                          [1043:4845]
- 54 -> LifeView FlyTV Platinum FM               [5168:0214,1489:0214]
+ 54 -> LifeView FlyTV Platinum FM / Gold        [5168:0214,1489:0214,5168:0304]
  55 -> LifeView FlyDVB-T DUO                    [5168:0306]
  56 -> Avermedia AVerTV 307                     [1461:a70a]
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
@@ -84,7 +84,7 @@
  83 -> Terratec Cinergy 250 PCI TV              [153b:1160]
  84 -> LifeView FlyDVB Trio                     [5168:0319]
  85 -> AverTV DVB-T 777                         [1461:2c05]
- 86 -> LifeView FlyDVB-T                        [5168:0301]
+ 86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
  87 -> ADS Instant TV Duo Cardbus PTV331        [0331:1421]
  88 -> Tevion/KWorld DVB-T 220RF                [17de:7201]
  89 -> ELSA EX-VISION 700TV                     [1048:226c]
@@ -92,3 +92,4 @@
  91 -> AVerMedia A169 B                         [1461:7360]
  92 -> AVerMedia A169 B1                        [1461:6360]
  93 -> Medion 7134 Bridge #2                    [16be:0005]
+ 94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
diff --git a/Documentation/usb/et61x251.txt b/Documentation/video4linux/et61x251.txt
similarity index 100%
rename from Documentation/usb/et61x251.txt
rename to Documentation/video4linux/et61x251.txt
diff --git a/Documentation/usb/ibmcam.txt b/Documentation/video4linux/ibmcam.txt
similarity index 99%
rename from Documentation/usb/ibmcam.txt
rename to Documentation/video4linux/ibmcam.txt
index c250036..4a40a2e 100644
--- a/Documentation/usb/ibmcam.txt
+++ b/Documentation/video4linux/ibmcam.txt
@@ -122,7 +122,7 @@
 - A Linux box with USB support (2.3/2.4; 2.2 w/backport may work)
 
 - A Video4Linux compatible frame grabber program such as xawtv.
-  
+
 HOW TO COMPILE THE DRIVER:
 
 You need to compile the driver only if you are a developer
diff --git a/Documentation/usb/ov511.txt b/Documentation/video4linux/ov511.txt
similarity index 99%
rename from Documentation/usb/ov511.txt
rename to Documentation/video4linux/ov511.txt
index a7fc043..142741e 100644
--- a/Documentation/usb/ov511.txt
+++ b/Documentation/video4linux/ov511.txt
@@ -9,7 +9,7 @@
 
 This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
 Any camera using the OV511/OV511+ and the OV6620/OV7610/20/20AE should work.
-Video capture devices that use the Philips SAA7111A decoder also work. It 
+Video capture devices that use the Philips SAA7111A decoder also work. It
 supports streaming and capture of color or monochrome video via the Video4Linux
 API. Most V4L apps are compatible with it. Most resolutions with a width and
 height that are a multiple of 8 are supported.
@@ -52,15 +52,15 @@
 
 	chmod 666 /dev/video
 	chmod 666 /dev/video0 (if necessary)
-	
+
 Now you are ready to run a video app! Both vidcat and xawtv work well for me
 at 640x480.
-	
+
 [Using vidcat:]
 
 	vidcat -s 640x480 -p c > test.jpg
 	xview test.jpg
-	
+
 [Using xawtv:]
 
 From the main xawtv directory:
@@ -70,7 +70,7 @@
 	make
 	make install
 
-Now you should be able to run xawtv. Right click for the options dialog. 
+Now you should be able to run xawtv. Right click for the options dialog.
 
 MODULE PARAMETERS:
 
@@ -286,4 +286,3 @@
 and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
 image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
 Matsuoka for their work as well.
-
diff --git a/Documentation/usb/se401.txt b/Documentation/video4linux/se401.txt
similarity index 100%
rename from Documentation/usb/se401.txt
rename to Documentation/video4linux/se401.txt
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
similarity index 98%
rename from Documentation/usb/sn9c102.txt
rename to Documentation/video4linux/sn9c102.txt
index b957bea..142920b 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -174,7 +174,7 @@
 -------------------------------------------------------------------------------
 Name:           video_nr
 Type:           short array (min = 0, max = 64)
-Syntax:         <-1|n[,...]> 
+Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
                 -1 = use next available
                  n = use minor number n
@@ -187,7 +187,7 @@
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
                 before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
                 all the applications support this feature. This parameter is
@@ -206,7 +206,7 @@
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
-Syntax:         <n> 
+Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
                 0 = none (use carefully)
                 1 = critical errors
@@ -267,7 +267,7 @@
 frame header of the most recent requested and captured video frame. The header
 is always 18-bytes long and is appended to every video frame by the SN9C10x
 controllers. As an example, this additional information can be used by the user
-application for implementing auto-exposure features via software. 
+application for implementing auto-exposure features via software.
 
 The following table describes the frame header:
 
@@ -441,7 +441,7 @@
 value and is disposed in memory according to the pattern shown below:
 
 B[0]   G[1]    B[2]    G[3]    ...   B[m-2]         G[m-1]
-G[m]   R[m+1]  G[m+2]  R[m+2]  ...   G[2m-2]        R[2m-1] 
+G[m]   R[m+1]  G[m+2]  R[m+2]  ...   G[2m-2]        R[2m-1]
 ...
 ...                                  B[(n-1)(m-2)]  G[(n-1)(m-1)]
 ...                                  G[n(m-2)]      R[n(m-1)]
@@ -472,12 +472,12 @@
 The algorithm purely describes the conversion from compressed Bayer code used
 in the SN9C10x chips to uncompressed Bayer. Additional steps are required to
 convert this to a color image (i.e. a color interpolation algorithm).
- 
+
 The following Huffman codes have been found:
-0: +0 (relative to reference pixel value) 
+0: +0 (relative to reference pixel value)
 100: +4
 101: -4?
-1110xxxx: set absolute value to xxxx.0000 
+1110xxxx: set absolute value to xxxx.0000
 1101: +11
 1111: -11
 11001: +20
diff --git a/Documentation/usb/stv680.txt b/Documentation/video4linux/stv680.txt
similarity index 85%
rename from Documentation/usb/stv680.txt
rename to Documentation/video4linux/stv680.txt
index 6448041..4f8946f 100644
--- a/Documentation/usb/stv680.txt
+++ b/Documentation/video4linux/stv680.txt
@@ -5,15 +5,15 @@
 
 INTRODUCTION:
 
-STMicroelectronics produces the STV0680B chip, which comes in two 
-types, -001 and -003. The -003 version allows the recording and downloading 
-of sound clips from the camera, and allows a flash attachment. Otherwise, 
-it uses the same commands as the -001 version. Both versions support a 
-variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20 
-CIF pictures. The STV0680 supports either a serial or a usb interface, and 
+STMicroelectronics produces the STV0680B chip, which comes in two
+types, -001 and -003. The -003 version allows the recording and downloading
+of sound clips from the camera, and allows a flash attachment. Otherwise,
+it uses the same commands as the -001 version. Both versions support a
+variety of SDRAM sizes and sensors, allowing for a maximum of 26 VGA or 20
+CIF pictures. The STV0680 supports either a serial or a usb interface, and
 video is possible through the usb interface.
 
-The following cameras are known to work with this driver, although any 
+The following cameras are known to work with this driver, although any
 camera with Vendor/Product codes of 0553/0202 should work:
 
 Aiptek Pencam (various models)
@@ -34,15 +34,15 @@
 MODULE OPTIONS:
 
 When the driver is compiled as a module, you can set a "swapRGB=1"
-option, if necessary, for those applications that require it 
-(such as xawtv). However, the driver should detect and set this 
+option, if necessary, for those applications that require it
+(such as xawtv). However, the driver should detect and set this
 automatically, so this option should not normally be used.
 
 
 KNOWN PROBLEMS:
 
-The driver seems to work better with the usb-ohci than the usb-uhci host 
-controller driver. 
+The driver seems to work better with the usb-ohci than the usb-uhci host
+controller driver.
 
 HELP:
 
@@ -50,6 +50,4 @@
 http://personal.clt.bellsouth.net/~kjsisson or at
 http://stv0680-usb.sourceforge.net
 
-Any questions to me can be send to:  kjsisson@bellsouth.net
-
-
+Any questions to me can be send to:  kjsisson@bellsouth.net
\ No newline at end of file
diff --git a/Documentation/usb/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
similarity index 96%
rename from Documentation/usb/w9968cf.txt
rename to Documentation/video4linux/w9968cf.txt
index 9d46cd0..3b704f2 100644
--- a/Documentation/usb/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -1,5 +1,5 @@
 
-                   W996[87]CF JPEG USB Dual Mode Camera Chip 
+                   W996[87]CF JPEG USB Dual Mode Camera Chip
                      Driver for Linux 2.6 (basic version)
                    =========================================
 
@@ -115,7 +115,7 @@
 ======================
 For it to work properly, the driver needs kernel support for Video4Linux, USB
 and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
-actually using any external "ovcamchip" module, given that the W996[87]CF 
+actually using any external "ovcamchip" module, given that the W996[87]CF
 driver depends on the version of the module present in the official kernels.
 
 The following options of the kernel configuration file must be enabled and
@@ -197,16 +197,16 @@
                  enabled for the 'ovcamchip' module to be loaded and for
                  this parameter to be present.
 -------------------------------------------------------------------------------
-Name:           simcams 
-Type:           int 
-Syntax:         <n> 
+Name:           simcams
+Type:           int
+Syntax:         <n>
 Description:    Number of cameras allowed to stream simultaneously.
                 n may vary from 0 to 32.
 Default:        32
 -------------------------------------------------------------------------------
 Name:           video_nr
 Type:           int array (min = 0, max = 32)
-Syntax:         <-1|n[,...]> 
+Syntax:         <-1|n[,...]>
 Description:    Specify V4L minor mode number.
                 -1 = use next available
                  n = use minor number n
@@ -219,7 +219,7 @@
 -------------------------------------------------------------------------------
 Name:           packet_size
 Type:           int array (min = 0, max = 32)
-Syntax:         <n[,...]> 
+Syntax:         <n[,...]>
 Description:    Specify the maximum data payload size in bytes for alternate
                 settings, for each device. n is scaled between 63 and 1023.
 Default:        1023
@@ -234,7 +234,7 @@
 -------------------------------------------------------------------------------
 Name:           double_buffer
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
                 It should be enabled if you want smooth video output: if you
                 obtain out of sync. video, disable it, or try to
@@ -243,13 +243,13 @@
 -------------------------------------------------------------------------------
 Name:           clamping
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    Video data clamping: 0 disabled, 1 enabled.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           filter_type
 Type:           int array (min = 0, max = 32)
-Syntax:         <0|1|2[,...]> 
+Syntax:         <0|1|2[,...]>
 Description:    Video filter type.
                 0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
                 The filter is used to reduce noise and aliasing artifacts
@@ -258,13 +258,13 @@
 -------------------------------------------------------------------------------
 Name:           largeview
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    Large view: 0 disabled, 1 enabled.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           upscaling
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    Software scaling (for non-compressed video only):
                 0 disabled, 1 enabled.
                 Disable it if you have a slow CPU or you don't have enough
@@ -341,8 +341,8 @@
 -------------------------------------------------------------------------------
 Name:           bandingfilter
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
-Description:    Banding filter to reduce effects of fluorescent 
+Syntax:         <0|1[,...]>
+Description:    Banding filter to reduce effects of fluorescent
                 lighting:
                 0 disabled, 1 enabled.
                 This filter tries to reduce the pattern of horizontal
@@ -374,7 +374,7 @@
 -------------------------------------------------------------------------------
 Name:           monochrome
 Type:           bool array (min = 0, max = 32)
-Syntax:         <0|1[,...]> 
+Syntax:         <0|1[,...]>
 Description:    The image sensor is monochrome:
                 0 = no, 1 = yes
 Default:        0 for every device.
@@ -400,19 +400,19 @@
 -------------------------------------------------------------------------------
 Name:           contrast
 Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]> 
+Syntax:         <n[,...]>
 Description:    Set picture contrast (0-65535).
 Default:        50000 for every device.
 -------------------------------------------------------------------------------
 Name:           whiteness
 Type:           long array (min = 0, max = 32)
-Syntax:         <n[,...]> 
+Syntax:         <n[,...]>
 Description:    Set picture whiteness (0-65535).
 Default:        32768 for every device.
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           int
-Syntax:         <n> 
+Syntax:         <n>
 Description:    Debugging information level, from 0 to 6:
                 0 = none (use carefully)
                 1 = critical errors
diff --git a/Documentation/usb/zc0301.txt b/Documentation/video4linux/zc0301.txt
similarity index 100%
rename from Documentation/usb/zc0301.txt
rename to Documentation/video4linux/zc0301.txt
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 1ad9af1..687104b 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -27,12 +27,21 @@
 the configured hugepage size - this is needed for generating the proper
 alignment and size of the arguments to the above system calls.
 
-The output of "cat /proc/meminfo" will have output like:
+The output of "cat /proc/meminfo" will have lines like:
 
 .....
 HugePages_Total: xxx
 HugePages_Free:  yyy
-Hugepagesize:    zzz KB
+HugePages_Rsvd:  www
+Hugepagesize:    zzz kB
+
+where:
+HugePages_Total is the size of the pool of hugepages.
+HugePages_Free is the number of hugepages in the pool that are not yet
+allocated.
+HugePages_Rsvd is short for "reserved," and is the number of hugepages
+for which a commitment to allocate from the pool has been made, but no
+allocation has yet been made. It's vaguely analogous to overcommit.
 
 /proc/filesystems should also show a filesystem of type "hugetlbfs" configured
 in the kernel.
@@ -42,11 +51,11 @@
 pre-configured) hugepages.
 The allocation (or deallocation) of hugetlb pages is possible only if there are
 enough physically contiguous free pages in system (freeing of hugepages is
-possible only if there are enough hugetlb pages free that can be transfered
+possible only if there are enough hugetlb pages free that can be transferred
 back to regular memory pool).
 
-Pages that are used as hugetlb pages are reserved inside the kernel and can
-not be used for other purposes.
+Pages that are used as hugetlb pages are reserved inside the kernel and cannot
+be used for other purposes.
 
 Once the kernel with Hugetlb page support is built and running, a user can
 use either the mmap system call or shared memory system calls to start using
@@ -60,7 +69,7 @@
 This command will try to configure 20 hugepages in the system.  The success
 or failure of allocation depends on the amount of physically contiguous
 memory that is preset in system at this time.  System administrators may want
-to put this command in one of the local rc init file.  This will enable the
+to put this command in one of the local rc init files.  This will enable the
 kernel to request huge pages early in the boot process (when the possibility
 of getting physical contiguous pages is still very high).
 
@@ -78,8 +87,8 @@
 mode of root of file system to value & 0777.  This value is given in octal.
 By default the value 0755 is picked. The size option sets the maximum value of
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
-rounded down to HPAGE_SIZE.  The option nr_inode sets the maximum number of
-inodes that /mnt/huge can use.  If the size or nr_inode options are not
+rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
+inodes that /mnt/huge can use.  If the size or nr_inodes options are not
 provided on command line then no limits are set.  For size and nr_inodes
 options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
 example, size=2K has the same meaning as size=2048. An example is given at
@@ -88,7 +97,7 @@
 read and write system calls are not supported on files that reside on hugetlb
 file systems.
 
-A regular chown, chgrp and chmod commands (with right permissions) could be
+Regular chown, chgrp, and chmod commands (with right permissions) could be
 used to change the file attributes on hugetlbfs.
 
 Also, it is important to note that no such mount command is required if the
@@ -96,8 +105,8 @@
 wish to use hugetlb page via shared memory segment should be a member of
 a supplementary group and system admin needs to configure that gid into
 /proc/sys/vm/hugetlb_shm_group.  It is possible for same or different
-applications to use any combination of mmaps and shm* calls.  Though the
-mount of filesystem will be required for using mmaps.
+applications to use any combination of mmaps and shm* calls, though the
+mount of filesystem will be required for using mmap calls.
 
 *******************************************************************
 
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 1921353..f2cd6ef 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -151,6 +151,11 @@
 
   numa=fake=X   Fake X nodes and ignore NUMA setup of the actual machine.
 
+  numa=hotadd=percent
+		Only allow hotadd memory to preallocate page structures upto
+		percent of already available memory.
+		numa=hotadd=0 will disable hotadd memory.
+
 ACPI
 
   acpi=off	Don't enable ACPI
diff --git a/Kbuild b/Kbuild
index 95d6a00..2d4f95e 100644
--- a/Kbuild
+++ b/Kbuild
@@ -18,7 +18,7 @@
 	"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
 endef
 # Override default regexp for specific architectures
-sed-$(CONFIG_MIPS) := "/^@@@/s///p"
+sed-$(CONFIG_MIPS) := "/^@@@/{s/^@@@//; s/ \#.*\$$//; p;}"
 
 quiet_cmd_offsets = GEN     $@
 define cmd_offsets
diff --git a/MAINTAINERS b/MAINTAINERS
index c946581..d6a8e5b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -411,6 +411,7 @@
 P:	Ralf Baechle
 M:	ralf@linux-mips.org
 L:	linux-hams@vger.kernel.org
+W:	http://www.linux-ax25.org/
 S:	Maintained
 
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
@@ -420,6 +421,14 @@
 W:	http://www.baycom.org/~tom/ham/ham.html
 S:	Maintained
 
+BCM43XX WIRELESS DRIVER
+P:	Michael Buesch
+M:	mb@bu3sch.de
+P:	Stefano Brivio
+M:	st3@riseup.net
+W:	http://bcm43xx.berlios.de/
+S:	Maintained
+
 BEFS FILE SYSTEM
 P:	Sergey S. Kostyliov
 M:	rathamahata@php4.ru
@@ -1451,6 +1460,19 @@
 M:	jjciarla@raiz.uncu.edu.ar
 S:	Maintained
 
+IPATH DRIVER:
+P:	Bryan O'Sullivan
+M:	support@pathscale.com
+L:	openib-general@openib.org
+S:	Supported
+
+IPMI SUBSYSTEM
+P:	Corey Minyard
+M:	minyard@acm.org
+L:	openipmi-developer@lists.sourceforge.net
+W:	http://openipmi.sourceforge.net/
+S:	Supported
+
 IPX NETWORK LAYER
 P:	Arnaldo Carvalho de Melo
 M:	acme@conectiva.com.br
@@ -1550,9 +1572,7 @@
 
 KEXEC
 P:	Eric Biederman
-P:	Randy Dunlap
 M:	ebiederm@xmission.com
-M:	rdunlap@xenotime.net
 W:	http://www.xmission.com/~ebiederm/files/kexec/
 L:	linux-kernel@vger.kernel.org
 L:	fastboot@osdl.org
@@ -1865,6 +1885,7 @@
 P:	Ralf Baechle
 M:	ralf@linux-mips.org
 L:	linux-hams@vger.kernel.org
+W:	http://www.linux-ax25.org/
 S:	Maintained
 
 NETWORK BLOCK DEVICE
@@ -2052,8 +2073,12 @@
 M:	matthew@wil.cx
 P:	Grant Grundler
 M:	grundler@parisc-linux.org
+P:	Kyle McMartin
+M:	kyle@parisc-linux.org
 L:	parisc-linux@parisc-linux.org
 W:	http://www.parisc-linux.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
+T:	cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
 S:	Maintained
 
 PCI ERROR RECOVERY
@@ -2256,6 +2281,7 @@
 P:	Ralf Baechle
 M:	ralf@linux-mips.org
 L:	linux-hams@vger.kernel.org
+W:	http://www.linux-ax25.org/
 S:	Maintained
 
 RISCOM8 DRIVER
@@ -3054,13 +3080,6 @@
 L:	lm-sensors@lm-sensors.org
 S:	Odd Fixes
 
-WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
-P:	Nenad Corbic
-M:	ncorbic@sangoma.com
-M:	dm@sangoma.com
-W:	http://www.sangoma.com
-S:	Supported
-
 WATCHDOG DEVICE DRIVERS
 P:	Wim Van Sebroeck
 M:	wim@iguana.be
diff --git a/Makefile b/Makefile
index af6210d..6bf9962 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 16
-EXTRAVERSION =
+SUBLEVEL = 17
+EXTRAVERSION =-rc3
 NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
@@ -1112,7 +1112,6 @@
 install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
 PHONY += _emodinst_
 _emodinst_:
-	$(Q)rm -rf $(MODLIB)/$(install-dir)
 	$(Q)mkdir -p $(MODLIB)/$(install-dir)
 	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
 
@@ -1275,40 +1274,43 @@
 
 # Single targets
 # ---------------------------------------------------------------------------
-# The directory part is taken from first prerequisite, so this
-# works even with external modules
-%.s: %.c prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-%.i: %.c prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-%.o: %.c prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-%.lst: %.c prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-%.s: %.S prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
-%.o: %.S prepare scripts FORCE
-	$(Q)$(MAKE) $(build)=$(dir $<) $(dir $<)$(notdir $@)
+# Single targets are compatible with:
+# - build whith mixed source and output
+# - build with separate output dir 'make O=...'
+# - external modules
+#
+#  target-dir => where to store outputfile
+#  build-dir  => directory in kernel source tree to use
 
-# For external modules we shall include any directory of the target,
-# but usual case there is no directory part.
-# make M=`pwd` module.o     => $(dir $@)=./
-# make M=`pwd` foo/module.o => $(dir $@)=foo/
-# make M=`pwd` /            => $(dir $@)=/
- 
 ifeq ($(KBUILD_EXTMOD),)
-        target-dir = $(@D)
+        build-dir  = $(patsubst %/,%,$(dir $@))
+        target-dir = $(dir $@)
 else
         zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
-        target-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+        build-dir  = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
+        target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
 endif
 
-/ %/:      scripts prepare FORCE
+%.s: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.i: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.o: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.lst: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.s: %.S prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.o: %.S prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+
+# Modules
+/ %/: prepare scripts FORCE
 	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
-	$(build)=$(target-dir)
-%.ko: scripts FORCE
+	$(build)=$(build-dir)
+%.ko: prepare scripts FORCE
 	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1)   \
-	$(build)=$(target-dir) $(@:.ko=.o)
+	$(build)=$(build-dir) $(@:.ko=.o)
 	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
 
 # FIXME Should go into a make.lib or something 
diff --git a/README b/README
index 05e0555..3e26472 100644
--- a/README
+++ b/README
@@ -165,10 +165,31 @@
 	"make xconfig"     X windows (Qt) based configuration tool.
 	"make gconfig"     X windows (Gtk) based configuration tool.
 	"make oldconfig"   Default all questions based on the contents of
-			   your existing ./.config file.
+			   your existing ./.config file and asking about
+			   new config symbols.
 	"make silentoldconfig"
 			   Like above, but avoids cluttering the screen
 			   with questions already answered.
+	"make defconfig"   Create a ./.config file by using the default
+			   symbol values from arch/$ARCH/defconfig.
+	"make allyesconfig"
+			   Create a ./.config file by setting symbol
+			   values to 'y' as much as possible.
+	"make allmodconfig"
+			   Create a ./.config file by setting symbol
+			   values to 'm' as much as possible.
+	"make allnoconfig" Create a ./.config file by setting symbol
+			   values to 'n' as much as possible.
+	"make randconfig"  Create a ./.config file by setting symbol
+			   values to random values.
+
+   The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+   also use the environment variable KCONFIG_ALLCONFIG to specify a
+   filename that contains config options that the user requires to be
+   set to a specific value.  If KCONFIG_ALLCONFIG=filename is not used,
+   "make *config" checks for a file named "all{yes/mod/no/random}.config"
+   for symbol values that are to be forced.  If this file is not found,
+   it checks for a file named "all.config" to contain forced values.
    
 	NOTES on "make config":
 	- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 9bef61b..8290b69 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -549,6 +549,11 @@
 	  Access).  This option is for configuring high-end multiprocessor
 	  server machines.  If in doubt, say N.
 
+config NODES_SHIFT
+	int
+	default "7"
+	depends on NEED_MULTIPLE_NODES
+
 # LARGE_VMALLOC is racy, if you *really* need it then fix it first
 config ALPHA_LARGE_VMALLOC
 	bool
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 9d6186d..c645c5e 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -76,7 +76,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(memcmp);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index a15e18a..558b833 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -24,6 +24,7 @@
 #include <linux/config.h>	/* CONFIG_ALPHA_LCA etc */
 #include <linux/mc146818rtc.h>
 #include <linux/console.h>
+#include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/string.h>
@@ -471,6 +472,22 @@
 	return 0;
 }
 
+static int __init
+register_cpus(void)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+		if (!p)
+			return -ENOMEM;
+		register_cpu(p, i, NULL);
+	}
+	return 0;
+}
+
+arch_initcall(register_cpus);
+
 void __init
 setup_arch(char **cmdline_p)
 {
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 02c2db0..1852554 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -439,7 +439,7 @@
 			if ((cpu->flags & 0x1cc) == 0x1cc) {
 				smp_num_probed++;
 				/* Assume here that "whami" == index */
-				cpu_set(i, cpu_possible_map);
+				cpu_set(i, cpu_present_mask);
 				cpu->pal_revision = boot_cpu_palrev;
 			}
 
@@ -450,9 +450,8 @@
 		}
 	} else {
 		smp_num_probed = 1;
-		cpu_set(boot_cpuid, cpu_possible_map);
+		cpu_set(boot_cpuid, cpu_present_mask);
 	}
-	cpu_present_mask = cpumask_of_cpu(boot_cpuid);
 
 	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
 	       smp_num_probed, cpu_possible_map.bits[0]);
@@ -488,9 +487,8 @@
 smp_prepare_boot_cpu(void)
 {
 	/*
-	 * Mark the boot cpu (current cpu) as both present and online
+	 * Mark the boot cpu (current cpu) as online
 	 */ 
-	cpu_set(smp_processor_id(), cpu_present_mask);
 	cpu_set(smp_processor_id(), cpu_online_map);
 }
 
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index 338551c..bbdef1b 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -43,8 +43,8 @@
 
 	.align	4
 $multiword:
-	subq	$24, 1, $2	# clear the final bits in the prev word
-	or	$2, $24, $2
+	subq	$27, 1, $2	# clear the final bits in the prev word
+	or	$2, $27, $2
 	zapnot	$1, $2, $1
 	subq	$18, 1, $18
 
@@ -70,8 +70,8 @@
 	bne	$18, 0b
 
 1:	ldq_u	$1, 0($16)	# clear the leading bits in the final word
-	subq	$27, 1, $2
-	or	$2, $27, $2
+	subq	$24, 1, $2
+	or	$2, $24, $2
 
 	zap	$1, $2, $1
 	stq_u	$1, 0($16)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dc5a933..1dbf6dd 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -512,6 +512,12 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+config NODES_SHIFT
+	int
+	default "4" if ARCH_LH7A40X
+	default "2"
+	depends on NEED_MULTIPLE_NODES
+
 source "mm/Kconfig"
 
 config LEDS
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 95a9627..6f8e84c 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -66,7 +66,7 @@
 tune-$(CONFIG_CPU_V6)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
 
 ifeq ($(CONFIG_AEABI),y)
-CFLAGS_ABI	:=-mabi=aapcs -mno-thumb-interwork
+CFLAGS_ABI	:=-mabi=aapcs-linux -mno-thumb-interwork
 else
 CFLAGS_ABI	:=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
 endif
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index eed6161..153a07e 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -18,6 +18,7 @@
     _start = .;
     *(.start)
     *(.text)
+    *(.text.*)
     *(.fixup)
     *(.gnu.warning)
     *(.rodata)
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 5e830f4..314ebd3 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -18,6 +18,18 @@
 #include <asm/io.h>
 #include <asm/hardware/scoop.h>
 
+/* PCMCIA to Scoop linkage
+
+   There is no easy way to link multiple scoop devices into one
+   single entity for the pxa2xx_pcmcia device so this structure
+   is used which is setup by the platform code.
+
+   This file is never modular so this symbol is always
+   accessile to the board support files.
+*/
+struct scoop_pcmcia_config *platform_scoop_config;
+EXPORT_SYMBOL(platform_scoop_config);
+
 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
 
 struct  scoop_dev {
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 1fe73d1..9e1c1cc 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -379,7 +379,7 @@
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
 CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
 
 #
 # NAND Flash Device Drivers
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index b7d934c..6e0805a 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -370,7 +370,7 @@
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
 CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
 
 #
 # NAND Flash Device Drivers
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 8dcc8e8..b69e88b 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 14:54:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:21:01 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -28,6 +30,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -67,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -94,6 +93,7 @@
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -112,7 +112,6 @@
 #
 # Cirrus EP93xx Implementation Options
 #
-CONFIG_CRUNCH=y
 
 #
 # EP93xx Platforms
@@ -232,12 +231,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -346,7 +348,6 @@
 # CONFIG_MTD_OTP is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -371,7 +372,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -412,7 +412,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -576,13 +576,13 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+CONFIG_EP93XX_WATCHDOG=y
 
 #
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -626,9 +626,7 @@
 # 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_RTC_X1205_I2C is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
 CONFIG_I2C_DEBUG_BUS=y
@@ -690,7 +688,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -702,6 +709,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -718,6 +726,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 
@@ -776,15 +785,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -813,6 +813,7 @@
 # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 # CONFIG_USB_SERIAL_VISOR is not set
 # CONFIG_USB_SERIAL_IPAQ is not set
 # CONFIG_USB_SERIAL_IR is not set
@@ -825,6 +826,7 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=y
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
@@ -865,6 +867,32 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_EP93XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -912,7 +940,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1044,6 +1071,7 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK=y
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -1053,6 +1081,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index 7b02ca0..e6f3e48 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -1,18 +1,19 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb  8 04:49:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:12:49 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -29,6 +30,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -60,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -68,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -89,11 +87,13 @@
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 CONFIG_ARCH_IXP2000=y
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -123,6 +123,7 @@
 CONFIG_ARCH_IXDP2X00=y
 CONFIG_ARCH_IXDP2401=y
 CONFIG_ARCH_IXDP2801=y
+CONFIG_MACH_IXDP28X5=y
 CONFIG_ARCH_IXDP2X01=y
 # CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
@@ -147,7 +148,6 @@
 # Bus support
 #
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -160,6 +160,7 @@
 #
 # CONFIG_PREEMPT is not set
 # CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
 # CONFIG_AEABI is not set
 # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -213,6 +214,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -232,12 +234,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -347,7 +352,6 @@
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 # CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_XIP is not set
 
 #
 # Mapping drivers for chip access
@@ -366,7 +370,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -614,8 +617,9 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -623,6 +627,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -650,7 +655,6 @@
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -696,7 +700,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -715,9 +718,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -730,6 +731,11 @@
 # CONFIG_SPI_MASTER is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
@@ -742,6 +748,7 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -776,7 +783,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -804,6 +820,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -821,6 +838,12 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -870,7 +893,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -972,6 +994,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
index 1a2751e..9ce898a 100644
--- a/arch/arm/configs/ixp23xx_defconfig
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Tue Mar 21 03:27:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Wed Apr 19 21:13:50 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -28,6 +30,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -59,7 +58,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -67,6 +65,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -143,7 +142,6 @@
 # Bus support
 #
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -230,12 +228,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -365,7 +366,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -527,7 +527,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -735,6 +734,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -776,7 +776,6 @@
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -821,7 +820,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -840,9 +838,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -907,7 +903,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
@@ -919,6 +924,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -935,6 +941,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1000,9 +1007,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1017,15 +1022,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1076,6 +1072,12 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1127,7 +1129,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1268,6 +1269,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 2ce0e3a..a601b8b 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,7 +29,7 @@
   obj-y		+= io.o
 endif
 
-head-y			:= head.o
+head-y			:= head$(MMUEXT).o
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
 extra-y := $(head-y) init_task.o vmlinux.lds
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 1574941..c49b5d4 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -100,23 +100,11 @@
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(__memzero);
 
@@ -190,8 +178,6 @@
 
 	/* syscalls */
 EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index b093ab8..0bea658 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -20,10 +20,11 @@
 #include <asm/mach-types.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
-#include <asm/constants.h>
+#include <asm/thread_info.h>
 #include <asm/system.h>
 
 #define PROCINFO_INITFUNC       12
+#define MACHINFO_TYPE		0
 
 /*
  * Kernel startup entry point.
@@ -79,5 +80,6 @@
 
 	mov	pc, r13				@ clear the BSS and jump
 						@ to start_kernel
+	.ltorg
 
 #include "head-common.S"
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280..9fc9af8 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@
 			dump_cache("cache", cpu, CACHE_ISIZE(info));
 		}
 	}
+
+	if (arch_is_coherent())
+		printk("Cache coherency enabled\n");
 }
 
 int cpu_architecture(void)
@@ -319,6 +322,12 @@
 	sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
 	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
+#ifndef CONFIG_ARM_THUMB
+	elf_hwcap &= ~HWCAP_THUMB;
+#endif
+#ifndef CONFIG_VFP
+	elf_hwcap &= ~HWCAP_VFP;
+#endif
 
 	cpu_proc_init();
 }
@@ -398,7 +407,7 @@
 }
 __early_param("initrd=", early_initrd);
 
-static void __init add_memory(unsigned long start, unsigned long size)
+static void __init arm_add_memory(unsigned long start, unsigned long size)
 {
 	/*
 	 * Ensure that start/size are aligned to a page boundary.
@@ -436,7 +445,7 @@
 	if (**p == '@')
 		start = memparse(*p + 1, p);
 
-	add_memory(start, size);
+	arm_add_memory(start, size);
 }
 __early_param("mem=", early_mem);
 
@@ -578,7 +587,7 @@
 			tag->u.mem.start, tag->u.mem.size / 1024);
 		return -EINVAL;
 	}
-	add_memory(tag->u.mem.start, tag->u.mem.size);
+	arm_add_memory(tag->u.mem.start, tag->u.mem.size);
 	return 0;
 }
 
@@ -798,7 +807,7 @@
 {
 	int cpu;
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
 
 	return 0;
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index 75e6ee3..ef88c41 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -16,11 +16,12 @@
 #obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
 
 # LEDs support
-#led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
-#led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
-#led-$(CONFIG_MACH_CSB337)	+= leds.o
-#led-$(CONFIG_MACH_CSB637)	+= leds.o
+led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
+led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
+led-$(CONFIG_MACH_CSB337)	+= leds.o
+led-$(CONFIG_MACH_CSB637)	+= leds.o
 #led-$(CONFIG_MACH_KB9200)	+= leds.o
+#led-$(CONFIG_MACH_KAFA)	+= leds.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # VGA support
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 54022e5..f45104c 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -67,6 +67,9 @@
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = CSB337_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 8195f9d..f2c2d6e 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -67,6 +67,9 @@
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = CSB637_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8a78336..2d7200e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -70,6 +70,9 @@
 	/* Initialize clocks: 18.432 MHz crystal */
 	at91_clock_init(18432000);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = DK_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
@@ -118,9 +121,14 @@
 	at91_add_device_udc(&dk_udc_data);
 	/* Compact Flash */
 	at91_add_device_cf(&dk_cf_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	/* DataFlash card */
+	at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
 	/* MMC */
-	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(&dk_mmc_data);
+#endif
 	/* VGA */
 //	dk_add_device_video();
 }
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index fd0752e..80d90f5 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -70,6 +70,9 @@
 	/* Initialize clocks: 18.432 MHz crystal */
 	at91_clock_init(18432000);
 
+	/* Setup the LEDs */
+	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
 #ifdef CONFIG_SERIAL_AT91
 	at91_console_port = EK_SERIAL_CONSOLE;
 	memcpy(at91_serial_map, serial, sizeof(serial));
@@ -111,9 +114,14 @@
 	at91_add_device_usbh(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	/* DataFlash card */
+	at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
 	/* MMC */
-	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
 	at91_add_device_mmc(&ek_mmc_data);
+#endif
 	/* VGA */
 //	ek_add_device_video();
 }
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 57eedd5..bfe47bd 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -28,10 +28,10 @@
 static u64 ohci_dmamask = 0xffffffffUL;
 static struct at91_usbh_data usbh_data;
 
-static struct resource at91rm9200_usbh_resource[] = {
+static struct resource at91_usbh_resource[] = {
 	[0] = {
 		.start	= AT91_UHP_BASE,
-		.end	= AT91_UHP_BASE + SZ_1M -1,
+		.end	= AT91_UHP_BASE + SZ_1M - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -49,8 +49,8 @@
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &usbh_data,
 	},
-	.resource	= at91rm9200_usbh_resource,
-	.num_resources	= ARRAY_SIZE(at91rm9200_usbh_resource),
+	.resource	= at91_usbh_resource,
+	.num_resources	= ARRAY_SIZE(at91_usbh_resource),
 };
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -121,6 +121,19 @@
 static u64 eth_dmamask = 0xffffffffUL;
 static struct at91_eth_data eth_data;
 
+static struct resource at91_eth_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_EMAC,
+		.end	= AT91_BASE_EMAC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_EMAC,
+		.end	= AT91_ID_EMAC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device at91rm9200_eth_device = {
 	.name		= "at91_ether",
 	.id		= -1,
@@ -129,7 +142,8 @@
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &eth_data,
 	},
-	.num_resources	= 0,
+	.resource	= at91_eth_resources,
+	.num_resources	= ARRAY_SIZE(at91_eth_resources),
 };
 
 void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -180,13 +194,23 @@
 #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
 static struct at91_cf_data cf_data;
 
+static struct resource at91_cf_resources[] = {
+	[0] = {
+		.start	= AT91_CF_BASE,
+		/* ties up CS4, CS5, and CS6 */
+		.end	= AT91_CF_BASE + (0x30000000 - 1),
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	},
+};
+
 static struct platform_device at91rm9200_cf_device = {
 	.name		= "at91_cf",
 	.id		= -1,
 	.dev		= {
 				.platform_data		= &cf_data,
 	},
-	.num_resources	= 0,
+	.resource	= at91_cf_resources,
+	.num_resources	= ARRAY_SIZE(at91_cf_resources),
 };
 
 void __init at91_add_device_cf(struct at91_cf_data *data)
@@ -224,15 +248,20 @@
 static struct at91_mmc_data mmc_data;
 
 static struct resource at91_mmc_resources[] = {
-	{
+	[0] = {
 		.start	= AT91_BASE_MCI,
 		.end	= AT91_BASE_MCI + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91_ID_MCI,
+		.end	= AT91_ID_MCI,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91rm9200_mci",
+	.name		= "at91_mci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -290,4 +319,123 @@
 void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+static struct resource at91_nand_resources[] = {
+	{
+		.start	= AT91_SMARTMEDIA_BASE,
+		.end	= AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device at91_nand_device = {
+	.name		= "at91_nand",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &nand_data,
+	},
+	.resource	= at91_nand_resources,
+	.num_resources	= ARRAY_SIZE(at91_nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+	if (!data)
+		return;
+
+	/* enable pin */
+	if (data->enable_pin)
+		at91_set_gpio_output(data->enable_pin, 1);
+
+	/* ready/busy pin */
+	if (data->rdy_pin)
+		at91_set_gpio_input(data->rdy_pin, 1);
+
+	/* card detect pin */
+	if (data->det_pin)
+		at91_set_gpio_input(data->det_pin, 1);
+
+	at91_set_A_periph(AT91_PIN_PC1, 0);		/* SMOE */
+	at91_set_A_periph(AT91_PIN_PC3, 0);		/* SMWE */
+
+	nand_data = *data;
+	platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+static struct platform_device at91rm9200_twi_device = {
+	.name		= "at91_i2c",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+void __init at91_add_device_i2c(void)
+{
+	/* pins used for TWI interface */
+	at91_set_A_periph(AT91_PIN_PA25, 0);		/* TWD */
+	at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+	at91_set_A_periph(AT91_PIN_PA26, 0);		/* TWCK */
+	at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+	platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+	.name		= "at91_rtc",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+void __init at91_add_device_rtc(void)
+{
+	platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+	at91_leds_cpu   = cpu_led;
+	at91_leds_timer = timer_led;
+}
+
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
 /* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
new file mode 100644
index 0000000..28150e8
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/leds.c
@@ -0,0 +1,100 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ *  Copyright (C) SAN People (Pty) Ltd
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+	at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+	at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+	unsigned long is_off = at91_get_gpio_value(led);
+	if (is_off)
+		at91_led_on(led);
+	else
+		at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch(evt) {
+	case led_start:		/* System startup */
+		at91_led_on(at91_leds_cpu);
+		break;
+
+	case led_stop:		/* System stop / suspend */
+		at91_led_off(at91_leds_cpu);
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:		/* Every 50 timer ticks */
+		at91_led_toggle(at91_leds_timer);
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:	/* Entering idle state */
+		at91_led_off(at91_leds_cpu);
+		break;
+
+	case led_idle_end:	/* Exit idle state */
+		at91_led_on(at91_leds_cpu);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+	if (!at91_leds_timer || !at91_leds_cpu)
+		return -ENODEV;
+
+	/* Enable PIO to access the LEDs */
+	at91_set_gpio_output(at91_leds_timer, 1);
+	at91_set_gpio_output(at91_leds_cpu, 1);
+
+	leds_event = at91_leds_event;
+
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 2d892e4..dcd4176 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -424,6 +424,14 @@
 	.periphid	= 0x00041010,
 };
 
+
+static struct platform_device ep93xx_rtc_device = {
+       .name           = "ep93xx-rtc",
+       .id             = -1,
+       .num_resources  = 0,
+};
+
+
 void __init ep93xx_init_devices(void)
 {
 	unsigned int v;
@@ -439,4 +447,6 @@
 	amba_device_register(&uart1_device, &iomem_resource);
 	amba_device_register(&uart2_device, &iomem_resource);
 	amba_device_register(&uart3_device, &iomem_resource);
+
+	platform_device_register(&ep93xx_rtc_device);
 }
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 777e75d..9be01b0c 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -17,6 +17,8 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -39,6 +41,16 @@
 		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
 		.length		= TS72XX_OPTIONS2_SIZE,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_RTC_INDEX_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+		.length		= TS72XX_RTC_INDEX_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_RTC_DATA_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+		.length		= TS72XX_RTC_DATA_SIZE,
+		.type		= MT_DEVICE,
 	}
 };
 
@@ -99,11 +111,38 @@
 	}
 }
 
+static unsigned char ts72xx_rtc_readb(unsigned long addr)
+{
+	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+	return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
+{
+	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+	__raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+	.readb			= ts72xx_rtc_readb,
+	.writeb			= ts72xx_rtc_writeb,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+	.name			= "rtc-m48t86",
+	.id			= -1,
+	.dev			= {
+		.platform_data		= &ts72xx_rtc_ops,
+	},
+	.num_resources		= 0,
+};
+
 static void __init ts72xx_init_machine(void)
 {
 	ep93xx_init_devices();
 	if (board_is_ts7200())
 		physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+	platform_device_register(&ts72xx_rtc_device);
 }
 
 MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 71a59e1..4ca51dc 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -7,11 +7,18 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
- *  03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ *  2004-03-03 Sascha Hauer <sascha@saschahauer.de>
  *             initial version heavily inspired by
  *             linux/arch/arm/mach-pxa/dma.c
+ *
+ *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Changed to support scatter gather DMA
+ *             by taking Russell's code from RiscPC
+ *
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -22,69 +29,368 @@
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/dma.h>
+#include <asm/arch/imx-dma.h>
 
-static struct dma_channel {
-	char *name;
-	void (*irq_handler) (int, void *, struct pt_regs *);
-	void (*err_handler) (int, void *, struct pt_regs *);
-	void *data;
-} dma_channels[11];
+struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
 
-/* set err_handler to NULL to have the standard info-only error handler */
-int
-imx_request_dma(char *name, imx_dma_prio prio,
-		void (*irq_handler) (int, void *, struct pt_regs *),
-		void (*err_handler) (int, void *, struct pt_regs *), void *data)
+/*
+ * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @lastcount: number of bytes transferred during last transfer
+ *
+ * Functions prepares DMA controller for next sg data chunk transfer.
+ * The @lastcount argument informs function about number of bytes transferred
+ * during last block. Zero value can be used for @lastcount to setup DMA
+ * for the first chunk.
+ */
+static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
 {
-	unsigned long flags;
-	int i, found = 0;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned int nextcount;
+	unsigned int nextaddr;
 
-	/* basic sanity checks */
-	if (!name || !irq_handler)
-		return -EINVAL;
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return 0;
+	}
 
-	local_irq_save(flags);
+	imxdma->resbytes -= lastcount;
 
-	/* try grabbing a DMA channel with the requested priority */
-	for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
-		if (!dma_channels[i].name) {
-			found = 1;
-			break;
+	if (!imxdma->sg) {
+		pr_debug("imxdma%d: no sg data\n", dma_ch);
+		return 0;
+	}
+
+	imxdma->sgbc += lastcount;
+	if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
+		if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
+			pr_debug("imxdma%d: sg transfer limit reached\n",
+				 dma_ch);
+			imxdma->sgcount=0;
+			imxdma->sg = NULL;
+			return 0;
+		} else {
+			imxdma->sgcount--;
+			imxdma->sg++;
+			imxdma->sgbc = 0;
 		}
 	}
+	nextcount = imxdma->sg->length - imxdma->sgbc;
+	nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
 
-	if (!found) {
-		/* requested prio group is full, try hier priorities */
-		for (i = prio - 1; i >= 0; i--) {
-			if (!dma_channels[i].name) {
-				found = 1;
-				break;
-			}
-		}
-	}
+	if(imxdma->resbytes < nextcount)
+		nextcount = imxdma->resbytes;
 
-	if (found) {
-		DIMR &= ~(1 << i);
-		dma_channels[i].name = name;
-		dma_channels[i].irq_handler = irq_handler;
-		dma_channels[i].err_handler = err_handler;
-		dma_channels[i].data = data;
-	} else {
-		printk(KERN_WARNING "No more available DMA channels for %s\n",
-		       name);
-		i = -ENODEV;
-	}
+	if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
+		DAR(dma_ch) = nextaddr;
+	else
+		SAR(dma_ch) = nextaddr;
 
-	local_irq_restore(flags);
-	return i;
+	CNTR(dma_ch) = nextcount;
+	pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
+		 dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
+
+	return nextcount;
 }
 
-void
-imx_free_dma(int dma_ch)
+/*
+ * imx_dma_setup_sg_base - scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ *
+ * Functions sets up i.MX DMA state for emulated scatter-gather transfer
+ * and sets up channel registers to be ready for the first chunk
+ */
+static int
+imx_dma_setup_sg_base(imx_dmach_t dma_ch,
+		      struct scatterlist *sg, unsigned int sgcount)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = sg;
+	imxdma->sgcount = sgcount;
+	imxdma->sgbc = 0;
+	return imx_dma_sg_next(dma_ch, 0);
+}
+
+/**
+ * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @dma_address: the DMA/physical memory address of the linear data block
+ *		to transfer
+ * @dma_length: length of the data block in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ *           or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel source and destination addresses for transfer
+ * specified by provided parameters. The scatter-gather emulation is disabled,
+ * because linear data block
+ * form the physical address range is transfered.
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ *		Zero indicates success.
+ */
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+		     unsigned int dma_length, unsigned int dev_addr,
+		     dmamode_t dmamode)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = NULL;
+	imxdma->sgcount = 0;
+	imxdma->dma_mode = dmamode;
+	imxdma->resbytes = dma_length;
+
+	if (!dma_address) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if (!dma_length) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
+			dma_ch, (unsigned int)dma_address, dma_length,
+			dev_addr);
+		SAR(dma_ch) = dev_addr;
+		DAR(dma_ch) = (unsigned int)dma_address;
+	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+		pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
+			dma_ch, (unsigned int)dma_address, dma_length,
+			dev_addr);
+		SAR(dma_ch) = (unsigned int)dma_address;
+		DAR(dma_ch) = dev_addr;
+	} else {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	CNTR(dma_ch) = dma_length;
+
+	return 0;
+}
+
+/**
+ * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ * @dma_length: total length of the transfer request in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ *           or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel state and registers to be ready for transfer
+ * specified by provided parameters. The scatter-gather emulation is set up
+ * according to the parameters.
+ *
+ * The full preparation of the transfer requires setup of more register
+ * by the caller before imx_dma_enable() can be called.
+ *
+ * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
+ *
+ * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
+ *
+ * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
+ * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
+ *
+ * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
+ *
+ * The typical setup for %DMA_MODE_WRITE is specified by next options combination
+ *
+ * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
+ *
+ * Be carefull there and do not mistakenly mix source and target device
+ * port sizes constants, they are really different:
+ * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
+ * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
+ *
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+		 unsigned int dev_addr, dmamode_t dmamode)
+{
+	int res;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	imxdma->sg = NULL;
+	imxdma->sgcount = 0;
+	imxdma->dma_mode = dmamode;
+	imxdma->resbytes = dma_length;
+
+	if (!sg || !sgcount) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if (!sg->length) {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
+			dma_ch, sg, sgcount, dma_length, dev_addr);
+		SAR(dma_ch) = dev_addr;
+	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+		pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
+			dma_ch, sg, sgcount, dma_length, dev_addr);
+		DAR(dma_ch) = dev_addr;
+	} else {
+		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
+		       dma_ch);
+		return -EINVAL;
+	}
+
+	res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
+	if (res <= 0) {
+		printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
+ * @dma_ch: i.MX DMA channel number
+ * @irq_handler: the pointer to the function called if the transfer
+ *		ends successfully
+ * @err_handler: the pointer to the function called if the premature
+ *		end caused by error occurs
+ * @data: user specified value to be passed to the handlers
+ */
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+		       void (*irq_handler) (int, void *, struct pt_regs *),
+		       void (*err_handler) (int, void *, struct pt_regs *),
+		       void *data)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return -ENODEV;
+	}
+
+	local_irq_save(flags);
+	DISR = (1 << dma_ch);
+	imxdma->irq_handler = irq_handler;
+	imxdma->err_handler = err_handler;
+	imxdma->data = data;
+	local_irq_restore(flags);
+	return 0;
+}
+
+/**
+ * imx_dma_enable - function to start i.MX DMA channel operation
+ * @dma_ch: i.MX DMA channel number
+ *
+ * The channel has to be allocated by driver through imx_dma_request()
+ * or imx_dma_request_by_prio() function.
+ * The transfer parameters has to be set to the channel registers through
+ * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
+ * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
+ * be set prior this function call by the channel user.
+ */
+void imx_dma_enable(imx_dmach_t dma_ch)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
+
+	if (!imxdma->name) {
+		printk(KERN_CRIT "%s: called for  not allocated channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	DISR = (1 << dma_ch);
+	DIMR &= ~(1 << dma_ch);
+	CCR(dma_ch) |= CCR_CEN;
+	local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_disable - stop, finish i.MX DMA channel operatin
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_disable(imx_dmach_t dma_ch)
 {
 	unsigned long flags;
 
-	if (!dma_channels[dma_ch].name) {
+	pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
+
+	local_irq_save(flags);
+	DIMR |= (1 << dma_ch);
+	CCR(dma_ch) &= ~CCR_CEN;
+	DISR = (1 << dma_ch);
+	local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_request - request/allocate specified channel number
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ */
+int imx_dma_request(imx_dmach_t dma_ch, const char *name)
+{
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+	unsigned long flags;
+
+	/* basic sanity checks */
+	if (!name)
+		return -EINVAL;
+
+	if (dma_ch >= IMX_DMA_CHANNELS) {
+		printk(KERN_CRIT "%s: called for  non-existed channel %d\n",
+		       __FUNCTION__, dma_ch);
+		return -EINVAL;
+	}
+
+	local_irq_save(flags);
+	if (imxdma->name) {
+		local_irq_restore(flags);
+		return -ENODEV;
+	}
+
+	imxdma->name = name;
+	imxdma->irq_handler = NULL;
+	imxdma->err_handler = NULL;
+	imxdma->data = NULL;
+	imxdma->sg = NULL;
+	local_irq_restore(flags);
+	return 0;
+}
+
+/**
+ * imx_dma_free - release previously acquired channel
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_free(imx_dmach_t dma_ch)
+{
+	unsigned long flags;
+	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+	if (!imxdma->name) {
 		printk(KERN_CRIT
 		       "%s: trying to free channel %d which is already freed\n",
 		       __FUNCTION__, dma_ch);
@@ -92,27 +398,84 @@
 	}
 
 	local_irq_save(flags);
-	DIMR &= ~(1 << dma_ch);
-	dma_channels[dma_ch].name = NULL;
+	/* Disable interrupts */
+	DIMR |= (1 << dma_ch);
+	CCR(dma_ch) &= ~CCR_CEN;
+	imxdma->name = NULL;
 	local_irq_restore(flags);
 }
 
-static irqreturn_t
-dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ * @prio: one of the hardware distinguished priority level:
+ *        %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
+ *
+ * This function tries to find free channel in the specified priority group
+ * if the priority cannot be achieved it tries to look for free channel
+ * in the higher and then even lower priority groups.
+ *
+ * Return value: If there is no free channel to allocate, -%ENODEV is returned.
+ *               Zero value indicates successful channel allocation.
+ */
+int
+imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name,
+			imx_dma_prio prio)
+{
+	int i;
+	int best;
+
+	switch (prio) {
+	case (DMA_PRIO_HIGH):
+		best = 8;
+		break;
+	case (DMA_PRIO_MEDIUM):
+		best = 4;
+		break;
+	case (DMA_PRIO_LOW):
+	default:
+		best = 0;
+		break;
+	}
+
+	for (i = best; i < IMX_DMA_CHANNELS; i++) {
+		if (!imx_dma_request(i, name)) {
+			*pdma_ch = i;
+			return 0;
+		}
+	}
+
+	for (i = best - 1; i >= 0; i--) {
+		if (!imx_dma_request(i, name)) {
+			*pdma_ch = i;
+			return 0;
+		}
+	}
+
+	printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__);
+
+	return -ENODEV;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i, disr = DISR;
-	struct dma_channel *channel;
+	struct imx_dma_channel *channel;
 	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
 
 	DISR = disr;
-	for (i = 0; i < 11; i++) {
-		channel = &dma_channels[i];
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+		channel = &imx_dma_channels[i];
 
-		if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+		if ((err_mask & 1 << i) && channel->name
+		    && channel->err_handler) {
 			channel->err_handler(i, channel->data, regs);
 			continue;
 		}
 
+		imx_dma_channels[i].sg = NULL;
+
 		if (DBTOSR & (1 << i)) {
 			printk(KERN_WARNING
 			       "Burst timeout on channel %d (%s)\n",
@@ -141,17 +504,27 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i, disr = DISR;
 
+	pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
+		     disr);
+
 	DISR = disr;
-	for (i = 0; i < 11; i++) {
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		if (disr & (1 << i)) {
-			struct dma_channel *channel = &dma_channels[i];
-			if (channel->name && channel->irq_handler) {
-				channel->irq_handler(i, channel->data, regs);
+			struct imx_dma_channel *channel = &imx_dma_channels[i];
+			if (channel->name) {
+				if (imx_dma_sg_next(i, CNTR(i))) {
+					CCR(i) &= ~CCR_CEN;
+					mb();
+					CCR(i) |= CCR_CEN;
+				} else {
+					if (channel->irq_handler)
+						channel->irq_handler(i,
+							channel->data, regs);
+				}
 			} else {
 				/*
 				 * IRQ for an unregistered DMA channel:
@@ -165,10 +538,10 @@
 	return IRQ_HANDLED;
 }
 
-static int __init
-imx_dma_init(void)
+static int __init imx_dma_init(void)
 {
 	int ret;
+	int i;
 
 	/* reset DMA module */
 	DCR = DCR_DRST;
@@ -189,15 +562,27 @@
 	DCR = DCR_DEN;
 
 	/* clear all interrupts */
-	DISR = 0x3ff;
+	DISR = (1 << IMX_DMA_CHANNELS) - 1;
 
 	/* enable interrupts */
-	DIMR = 0;
+	DIMR = (1 << IMX_DMA_CHANNELS) - 1;
+
+	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+		imx_dma_channels[i].sg = NULL;
+		imx_dma_channels[i].dma_num = i;
+	}
 
 	return ret;
 }
 
 arch_initcall(imx_dma_init);
 
-EXPORT_SYMBOL(imx_request_dma);
-EXPORT_SYMBOL(imx_free_dma);
+EXPORT_SYMBOL(imx_dma_setup_single);
+EXPORT_SYMBOL(imx_dma_setup_sg);
+EXPORT_SYMBOL(imx_dma_setup_handlers);
+EXPORT_SYMBOL(imx_dma_enable);
+EXPORT_SYMBOL(imx_dma_disable);
+EXPORT_SYMBOL(imx_dma_request);
+EXPORT_SYMBOL(imx_dma_free);
+EXPORT_SYMBOL(imx_dma_request_by_prio);
+EXPORT_SYMBOL(imx_dma_channels);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 37613ad6..9d8331b 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -33,6 +33,7 @@
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
+#include <asm/arch/mmc.h>
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -175,13 +176,25 @@
 	},
 };
 
+static u64 imxmmmc_dmamask = 0xffffffffUL;
+
 static struct platform_device imx_mmc_device = {
 	.name		= "imx-mmc",
 	.id		= 0,
+	.dev		= {
+		.dma_mask = &imxmmmc_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
 	.num_resources	= ARRAY_SIZE(imx_mmc_resources),
 	.resource	= imx_mmc_resources,
 };
 
+void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
+{
+	imx_mmc_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(imx_set_mmc_info);
+
 static struct resource imx_uart1_resources[] = {
 	[0] = {
 		.start	= 0x00206000,
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 8ab1b04..e34d0df 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -25,6 +25,7 @@
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
+#include <asm/arch/mmc.h>
 #include <linux/interrupt.h>
 #include "generic.h"
 
@@ -51,12 +52,29 @@
 	&cs89x0_device,
 };
 
+#ifdef CONFIG_MMC_IMX
+static int mx1ads_mmc_card_present(void)
+{
+	/* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
+	return (SSR(1) & (1 << 20) ? 0 : 1);
+}
+
+static struct imxmmc_platform_data mx1ads_mmc_info = {
+       .card_present = mx1ads_mmc_card_present,
+};
+#endif
+
 static void __init
 mx1ads_init(void)
 {
 #ifdef CONFIG_LEDS
 	imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
 #endif
+#ifdef CONFIG_MMC_IMX
+	/* SD/MMC card detect */
+	imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
+	imx_set_mmc_info(&mx1ads_mmc_info);
+#endif
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 2327c97..bf688c1 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -44,6 +44,15 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/pci.h>
 
+static int __init espresso_pci_init(void)
+{
+	if (machine_is_espresso())
+		ixp23xx_pci_slave_init();
+
+	return 0;
+};
+subsys_initcall(espresso_pci_init);
+
 static void __init espresso_init(void)
 {
 	physmap_configure(0x90000000, 0x02000000, 2, NULL);
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 5330ad7..ac72f94 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -201,7 +201,7 @@
 	return 0;
 }
 
-void __init ixp23xx_pci_preinit(void)
+static void __init ixp23xx_pci_common_init(void)
 {
 #ifdef __ARMEB__
 	*IXP23XX_PCI_CONTROL |= 0x20000;	/* set I/O swapping */
@@ -219,7 +219,18 @@
 		*IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
 	} else {
 		*IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+
+		/*
+		 * Enable coherency on A2 silicon.
+		 */
+		if (arch_is_coherent())
+			*IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
 	}
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+	ixp23xx_pci_common_init();
 
 	hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
 			"PCI config cycle to non-existent device");
@@ -273,3 +284,8 @@
 
 	return 1;
 }
+
+void ixp23xx_pci_slave_init(void)
+{
+	ixp23xx_pci_common_init();
+}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a0888e1..00b761f 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -91,7 +91,7 @@
 /*
  * IRQ -> GPIO mapping table
  */
-static char irq2gpio[32] = {
+static signed char irq2gpio[32] = {
 	-1, -1, -1, -1, -1, -1,  0,  1,
 	-1, -1, -1, -1, -1, -1, -1, -1,
 	-1, -1, -1,  2,  3,  4,  5,  6,
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 86a0f0d..f8d716c 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -69,12 +69,6 @@
 	  Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
 	  such a board.
 
-config MACH_NETSTAR
-	bool "NetStar"
-	depends on ARCH_OMAP1 && ARCH_OMAP15XX
-	help
-	  Support for NetStar PBX. Say Y here if you have such a board.
-
 config MACH_OMAP_PALMTE
 	bool "Palm Tungsten E"
 	depends on ARCH_OMAP1 && ARCH_OMAP15XX
@@ -85,6 +79,20 @@
           informations.
           Say Y here if you have such a PDA, say NO otherwise.
 
+config MACH_NOKIA770
+	bool "Nokia 770"
+	depends on ARCH_OMAP1 && ARCH_OMAP16XX
+	help
+	  Support for the Nokia 770 Internet Tablet. Say Y here if you
+	  have such a device.
+
+config MACH_AMS_DELTA
+	bool "Amstrad E3 (Delta)"
+	depends on ARCH_OMAP1 && ARCH_OMAP15XX
+	help
+	  Support for the Amstrad E3 (codename Delta) videophone. Say Y here
+	  if you have such a device.
+
 config MACH_OMAP_GENERIC
 	bool "Generic OMAP board"
 	depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index b0b0015..9ea7195 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,13 @@
 #
 
 # Common support
-obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER)		+= time.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
 led-y := leds.o
 
 # Specific board support
@@ -14,8 +20,9 @@
 obj-$(CONFIG_MACH_OMAP_OSK)		+= board-osk.o
 obj-$(CONFIG_MACH_OMAP_H3)		+= board-h3.o
 obj-$(CONFIG_MACH_VOICEBLUE)		+= board-voiceblue.o
-obj-$(CONFIG_MACH_NETSTAR)		+= board-netstar.o
 obj-$(CONFIG_MACH_OMAP_PALMTE)		+= board-palmte.o
+obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o
 
 ifeq ($(CONFIG_ARCH_OMAP15XX),y)
 # Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
new file mode 100644
index 0000000..6178f04
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-omap1/board-ams-delta.c
+ *
+ * Modified from board-generic.c
+ *
+ * Board specific inits for the Amstrad E3 (codename Delta) videophone
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * 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/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board-ams-delta.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+void ams_delta_latch1_write(u8 mask, u8 value)
+{
+	ams_delta_latch1_reg &= ~mask;
+	ams_delta_latch1_reg |= value;
+	*(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg;
+}
+
+void ams_delta_latch2_write(u16 mask, u16 value)
+{
+	ams_delta_latch2_reg &= ~mask;
+	ams_delta_latch2_reg |= value;
+	*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
+}
+
+static void __init ams_delta_init_irq(void)
+{
+	omap1_init_common_hw();
+	omap_init_irq();
+	omap_gpio_init();
+}
+
+static struct map_desc ams_delta_io_desc[] __initdata = {
+	// AMS_DELTA_LATCH1
+	{
+		.virtual	= AMS_DELTA_LATCH1_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	},
+	// AMS_DELTA_LATCH2
+	{
+		.virtual	= AMS_DELTA_LATCH2_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	},
+	// AMS_DELTA_MODEM
+	{
+		.virtual	= AMS_DELTA_MODEM_VIRT,
+		.pfn		= __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
+		.length		= 0x01000000,
+		.type		= MT_DEVICE
+	}
+};
+
+static struct omap_uart_config ams_delta_uart_config __initdata = {
+	.enabled_uarts = 1,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] = {
+	{ OMAP_TAG_UART,	&ams_delta_uart_config },
+};
+
+static void __init ams_delta_init(void)
+{
+	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+
+	omap_board_config = ams_delta_config;
+	omap_board_config_size = ARRAY_SIZE(ams_delta_config);
+	omap_serial_init();
+
+	/* Clear latch2 (NAND, LCD, modem enable) */
+	ams_delta_latch2_write(~0, 0);
+}
+
+static void __init ams_delta_map_io(void)
+{
+	omap1_map_common_io();
+}
+
+MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
+	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
+	.phys_io	= 0xfff00000,
+	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
+	.boot_params	= 0x10000100,
+	.map_io		= ams_delta_map_io,
+	.init_irq	= ams_delta_init_irq,
+	.init_machine	= ams_delta_init,
+	.timer		= &omap_timer,
+MACHINE_END
+
+EXPORT_SYMBOL(ams_delta_latch1_write);
+EXPORT_SYMBOL(ams_delta_latch2_write);
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index a177e78..33d01ad 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -88,7 +88,7 @@
 static void __init omap_generic_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		generic_config[0].data = &generic1510_usb_config;
 	}
 #endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 89f0cc7..cd3a06d 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -35,12 +37,55 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h2_partitions[] = {
+static int h2_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_F10),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_9),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_2),
+	KEY(1, 3, KEY_F9),
+	KEY(1, 4, KEY_F7),
+	KEY(1, 5, KEY_0),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_6),
+	KEY(2, 2, KEY_1),
+	KEY(2, 3, KEY_F2),
+	KEY(2, 4, KEY_F6),
+	KEY(2, 5, KEY_HOME),
+	KEY(3, 0, KEY_8),
+	KEY(3, 1, KEY_5),
+	KEY(3, 2, KEY_F12),
+	KEY(3, 3, KEY_F3),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_END),
+	KEY(4, 0, KEY_7),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_F11),
+	KEY(4, 3, KEY_F1),
+	KEY(4, 4, KEY_F4),
+	KEY(4, 5, KEY_ESC),
+	KEY(5, 0, KEY_F13),
+	KEY(5, 1, KEY_F14),
+	KEY(5, 2, KEY_F15),
+	KEY(5, 3, KEY_F16),
+	KEY(5, 4, KEY_SLEEP),
+	0
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -71,26 +116,26 @@
 	}
 };
 
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= h2_partitions,
-	.nr_parts	= ARRAY_SIZE(h2_partitions),
+	.parts		= h2_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(h2_nor_partitions),
 };
 
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
 	/* This is on CS3, wherever it's mapped */
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &h2_flash_data,
+		.platform_data	= &h2_nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &h2_flash_resource,
+	.resource	= &h2_nor_resource,
 };
 
 static struct resource h2_smc91x_resources[] = {
@@ -113,9 +158,119 @@
 	.resource	= h2_smc91x_resources,
 };
 
+static struct resource h2_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = h2_keymap,
+	.rep	= 1,
+};
+
+static struct platform_device h2_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h2_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(h2_kp_resources),
+	.resource	= h2_kp_resources,
+};
+
+#define H2_IRDA_FIRSEL_GPIO_PIN	17
+
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+static int h2_transceiver_mode(struct device *dev, int state)
+{
+	if (state & IR_SIRMODE)
+		omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+	else    /* MIR/FIR */
+		omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1);
+
+	return 0;
+}
+#endif
+
+static struct omap_irda_config h2_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.rx_channel		= OMAP_DMA_UART3_RX,
+	.tx_channel		= OMAP_DMA_UART3_TX,
+	.dest_start		= UART3_THR,
+	.src_start		= UART3_RHR,
+	.tx_trigger		= 0,
+	.rx_trigger		= 0,
+};
+
+static struct resource h2_irda_resources[] = {
+	[0] = {
+		.start	= INT_UART3,
+		.end	= INT_UART3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+static struct platform_device h2_irda_device = {
+	.name		= "omapirda",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &h2_irda_data,
+	},
+	.num_resources	= ARRAY_SIZE(h2_irda_resources),
+	.resource	= h2_irda_resources,
+};
+
+static struct platform_device h2_lcd_device = {
+	.name		= "lcd_h2",
+	.id		= -1,
+};
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+	.spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+	.spcr1 = RINTM(3) | RRST,
+	.rcr2  = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+                RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+	.rcr1  = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+	.xcr2  = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+                XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+	.xcr1  = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+	.srgr1 = FWID(15),
+	.srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+	.pcr0  = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+	//.pcr0 = CLKXP | CLKRP,        /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+	.name                   = "H2 TSC2101",
+	.mcbsp_regs_alsa        = &mcbsp_regs,
+	.codec_configure_dev    = NULL, // tsc2101_configure,
+	.codec_set_samplerate   = NULL, // tsc2101_set_samplerate,
+	.codec_clock_setup      = NULL, // tsc2101_clock_setup,
+	.codec_clock_on         = NULL, // tsc2101_clock_on,
+	.codec_clock_off        = NULL, // tsc2101_clock_off,
+	.get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h2_mcbsp1_device = {
+	.name	= "omap_alsa_mcbsp",
+	.id	= 1,
+	.dev = {
+		.platform_data	= &alsa_config,
+	},
+};
+
 static struct platform_device *h2_devices[] __initdata = {
-	&h2_flash_device,
+	&h2_nor_device,
 	&h2_smc91x_device,
+	&h2_irda_device,
+	&h2_kp_device,
+	&h2_lcd_device,
+	&h2_mcbsp1_device,
 };
 
 static void __init h2_init_smc91x(void)
@@ -164,7 +319,6 @@
 };
 
 static struct omap_lcd_config h2_lcd_config __initdata = {
-	.panel_name	= "h2",
 	.ctrl_name	= "internal",
 };
 
@@ -177,16 +331,34 @@
 
 static void __init h2_init(void)
 {
-	/* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
-	 * and NAND (either 16bit or 8bit) on CS3.
+	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+	 * notice whether a NAND chip is enabled at probe time.
+	 *
+	 * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+	 * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3.  Try
+	 * detecting that in code here, to avoid probing every possible flash
+	 * configuration...
 	 */
-	h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
-	h2_flash_resource.end += SZ_32M - 1;
+	h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+	h2_nor_resource.end += SZ_32M - 1;
+
+	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
 
 	/* MMC:  card detect and WP */
 	// omap_cfg_reg(U19_ARMIO1);		/* CD */
 	omap_cfg_reg(BALLOUT_V8_ARMIO3);	/* WP */
 
+	/* Irda */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+	omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+	if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) {
+		omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+		h2_irda_data.transceiver_mode = h2_transceiver_mode;
+	}
+#endif
+
 	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
 	omap_board_config = h2_config;
 	omap_board_config_size = ARRAY_SIZE(h2_config);
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d9f3862..4b8d0ec 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -21,8 +21,11 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/errno.h>
+#include <linux/workqueue.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -33,15 +36,59 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/dma.h>
 #include <asm/arch/common.h>
 
 extern int omap_gpio_init(void);
 
-static struct mtd_partition h3_partitions[] = {
+static int h3_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_F10),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_9),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_2),
+	KEY(1, 3, KEY_F9),
+	KEY(1, 4, KEY_F7),
+	KEY(1, 5, KEY_0),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_6),
+	KEY(2, 2, KEY_1),
+	KEY(2, 3, KEY_F2),
+	KEY(2, 4, KEY_F6),
+	KEY(2, 5, KEY_HOME),
+	KEY(3, 0, KEY_8),
+	KEY(3, 1, KEY_5),
+	KEY(3, 2, KEY_F12),
+	KEY(3, 3, KEY_F3),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_END),
+	KEY(4, 0, KEY_7),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_F11),
+	KEY(4, 3, KEY_F1),
+	KEY(4, 4, KEY_F4),
+	KEY(4, 5, KEY_ESC),
+	KEY(5, 0, KEY_F13),
+	KEY(5, 1, KEY_F14),
+	KEY(5, 2, KEY_F15),
+	KEY(5, 3, KEY_F16),
+	KEY(5, 4, KEY_SLEEP),
+	0
+};
+
+
+static struct mtd_partition nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -72,26 +119,80 @@
 	}
 };
 
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= h3_partitions,
-	.nr_parts	= ARRAY_SIZE(h3_partitions),
+	.parts		= nor_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
 	/* This is on CS3, wherever it's mapped */
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &h3_flash_data,
+		.platform_data	= &nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &h3_flash_resource,
+	.resource	= &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+	/* REVISIT: enable these partitions if you make NAND BOOT work */
+	{
+		.name		= "xloader",
+		.offset		= 0,
+		.size		= 64 * 1024,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "bootloader",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 256 * 1024,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+	{
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 192 * 1024,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 2 * SZ_1M,
+	},
+#endif
+	{
+		.name		= "filesystem",
+		.size		= MTDPART_SIZ_FULL,
+		.offset		= MTDPART_OFS_APPEND,
+	},
+};
+
+/* dip switches control NAND chip access:  8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+	.options	= NAND_SAMSUNG_LP_OPTIONS,
+	.parts		= nand_partitions,
+	.nr_parts	= ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+	.name		= "omapnand",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &nand_resource,
 };
 
 static struct resource smc91x_resources[] = {
@@ -138,10 +239,136 @@
 	.resource       = intlat_resources,
 };
 
+static struct resource h3_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = h3_keymap,
+	.rep	= 1,
+};
+
+static struct platform_device h3_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h3_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(h3_kp_resources),
+	.resource	= h3_kp_resources,
+};
+
+
+/* Select between the IrDA and aGPS module
+ */
+static int h3_select_irda(struct device *dev, int state)
+{
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x26))) {
+		printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+		return err;
+	}
+
+	/* 'P6' enable/disable IRDA_TX and IRDA_RX */
+	if (state & IR_SEL) { /* IrDA */
+		if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
+			printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+			return err;
+		}
+	} else {
+		if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
+			printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+			return err;
+		}
+	}
+	return err;
+}
+
+static void set_trans_mode(void *data)
+{
+	int *mode = data;
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+	}
+
+	expa &= ~0x03;
+
+	if (*mode & IR_SIRMODE) {
+		expa |= 0x01;
+	} else { /* MIR/FIR */
+		expa |= 0x03;
+	}
+
+	if ((err = write_gpio_expa(expa, 0x27)) != 0) {
+		printk(KERN_ERR "Error writing to I/O expander\n");
+	}
+}
+
+static int h3_transceiver_mode(struct device *dev, int mode)
+{
+	struct omap_irda_config *irda_config = dev->platform_data;
+
+	cancel_delayed_work(&irda_config->gpio_expa);
+	PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+	schedule_work(&irda_config->gpio_expa);
+
+	return 0;
+}
+
+static struct omap_irda_config h3_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.transceiver_mode	= h3_transceiver_mode,
+	.select_irda	 	= h3_select_irda,
+	.rx_channel		= OMAP_DMA_UART3_RX,
+	.tx_channel		= OMAP_DMA_UART3_TX,
+	.dest_start		= UART3_THR,
+	.src_start		= UART3_RHR,
+	.tx_trigger		= 0,
+	.rx_trigger		= 0,
+};
+
+static struct resource h3_irda_resources[] = {
+	[0] = {
+		.start	= INT_UART3,
+		.end	= INT_UART3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h3_irda_device = {
+	.name		= "omapirda",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &h3_irda_data,
+	},
+	.num_resources	= ARRAY_SIZE(h3_irda_resources),
+	.resource	= h3_irda_resources,
+};
+
+static struct platform_device h3_lcd_device = {
+	.name		= "lcd_h3",
+	.id		= -1,
+};
+
 static struct platform_device *devices[] __initdata = {
-	&flash_device,
+	&nor_device,
+	&nand_device,
         &smc91x_device,
 	&intlat_device,
+	&h3_irda_device,
+	&h3_kp_device,
+	&h3_lcd_device,
 };
 
 static struct omap_usb_config h3_usb_config __initdata = {
@@ -171,7 +398,6 @@
 };
 
 static struct omap_lcd_config h3_lcd_config __initdata = {
-	.panel_name	= "h3",
 	.ctrl_name	= "internal",
 };
 
@@ -182,11 +408,36 @@
 	{ OMAP_TAG_LCD,		&h3_lcd_config },
 };
 
+#define H3_NAND_RB_GPIO_PIN	10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+	return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
 static void __init h3_init(void)
 {
-	h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
-	h3_flash_resource.end += OMAP_CS3_SIZE - 1;
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
+	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
+	 * notice whether a NAND chip is enabled at probe time.
+	 *
+	 * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+	 * (which on H2 may be 16bit) on CS3.  Try detecting that in code here,
+	 * to avoid probing every possible flash configuration...
+	 */
+	nor_resource.end = nor_resource.start = omap_cs3_phys();
+	nor_resource.end += SZ_32M - 1;
+
+	nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+	nand_resource.end += SZ_4K - 1;
+	if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+		nand_data.dev_ready = nand_dev_ready;
+
+	/* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+	/* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+	omap_cfg_reg(V2_1710_GPIO10);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 	omap_board_config = h3_config;
 	omap_board_config_size = ARRAY_SIZE(h3_config);
 	omap_serial_init();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a04e433..e90c137 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -34,8 +35,22 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/tc.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
 
+static int innovator_keymap[] = {
+	KEY(0, 0, KEY_F1),
+	KEY(0, 3, KEY_DOWN),
+	KEY(1, 1, KEY_F2),
+	KEY(1, 2, KEY_RIGHT),
+	KEY(2, 0, KEY_F3),
+	KEY(2, 1, KEY_F4),
+	KEY(2, 2, KEY_UP),
+	KEY(3, 2, KEY_ENTER),
+	KEY(3, 3, KEY_LEFT),
+	0
+};
+
 static struct mtd_partition innovator_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -97,6 +112,31 @@
 	.resource	= &innovator_flash_resource,
 };
 
+static struct resource innovator_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = innovator_keymap,
+};
+
+static struct platform_device innovator_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &innovator_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(innovator_kp_resources),
+	.resource	= innovator_kp_resources,
+};
+
+
 #ifdef CONFIG_ARCH_OMAP15XX
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -129,9 +169,16 @@
 	.resource	= innovator1510_smc91x_resources,
 };
 
+static struct platform_device innovator1510_lcd_device = {
+	.name		= "lcd_inn1510",
+	.id		= -1,
+};
+
 static struct platform_device *innovator1510_devices[] __initdata = {
 	&innovator_flash_device,
 	&innovator1510_smc91x_device,
+	&innovator_kp_device,
+	&innovator1510_lcd_device,
 };
 
 #endif /* CONFIG_ARCH_OMAP15XX */
@@ -158,9 +205,16 @@
 	.resource	= innovator1610_smc91x_resources,
 };
 
+static struct platform_device innovator1610_lcd_device = {
+	.name		= "inn1610_lcd",
+	.id		= -1,
+};
+
 static struct platform_device *innovator1610_devices[] __initdata = {
 	&innovator_flash_device,
 	&innovator1610_smc91x_device,
+	&innovator_kp_device,
+	&innovator1610_lcd_device,
 };
 
 #endif /* CONFIG_ARCH_OMAP16XX */
@@ -206,7 +260,6 @@
 };
 
 static struct omap_lcd_config innovator1510_lcd_config __initdata = {
-	.panel_name	= "inn1510",
 	.ctrl_name	= "internal",
 };
 #endif
@@ -228,7 +281,6 @@
 };
 
 static struct omap_lcd_config innovator1610_lcd_config __initdata = {
-	.panel_name	= "inn1610",
 	.ctrl_name	= "internal",
 };
 #endif
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
deleted file mode 100644
index 7520e60..0000000
--- a/arch/arm/mach-omap1/board-netstar.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Modified from board-generic.c
- *
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Code for Netstar OMAP board.
- *
- * 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/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
-
-extern void __init omap_init_time(void);
-extern int omap_gpio_init(void);
-
-static struct resource netstar_smc91x_resources[] = {
-	[0] = {
-		.start	= OMAP_CS1_PHYS + 0x300,
-		.end	= OMAP_CS1_PHYS + 0x300 + 16,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= OMAP_GPIO_IRQ(8),
-		.end	= OMAP_GPIO_IRQ(8),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device netstar_smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(netstar_smc91x_resources),
-	.resource	= netstar_smc91x_resources,
-};
-
-static struct platform_device *netstar_devices[] __initdata = {
-	&netstar_smc91x_device,
-};
-
-static struct omap_uart_config netstar_uart_config __initdata = {
-	.enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-};
-
-static struct omap_board_config_kernel netstar_config[] = {
-	{ OMAP_TAG_UART,	&netstar_uart_config },
-};
-
-static void __init netstar_init_irq(void)
-{
-	omap1_init_common_hw();
-	omap_init_irq();
-	omap_gpio_init();
-}
-
-static void __init netstar_init(void)
-{
-	/* green LED */
-	omap_request_gpio(4);
-	omap_set_gpio_direction(4, 0);
-	/* smc91x reset */
-	omap_request_gpio(7);
-	omap_set_gpio_direction(7, 0);
-	omap_set_gpio_dataout(7, 1);
-	udelay(2);	/* wait at least 100ns */
-	omap_set_gpio_dataout(7, 0);
-	mdelay(50);	/* 50ms until PHY ready */
-	/* smc91x interrupt pin */
-	omap_request_gpio(8);
-
-	omap_request_gpio(12);
-	omap_request_gpio(13);
-	omap_request_gpio(14);
-	omap_request_gpio(15);
-	set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING);
-	set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING);
-
-	platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
-
-	/* Switch on green LED */
-	omap_set_gpio_dataout(4, 0);
-	/* Switch off red LED */
-	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
-	omap_writeb(0x80, OMAP_LPG1_LCR);
-
-	omap_board_config = netstar_config;
-	omap_board_config_size = ARRAY_SIZE(netstar_config);
-	omap_serial_init();
-}
-
-static void __init netstar_map_io(void)
-{
-	omap1_map_common_io();
-}
-
-#define MACHINE_PANICED		1
-#define MACHINE_REBOOTING	2
-#define MACHINE_REBOOT		4
-static unsigned long machine_state;
-
-static int panic_event(struct notifier_block *this, unsigned long event,
-	 void *ptr)
-{
-	if (test_and_set_bit(MACHINE_PANICED, &machine_state))
-		return NOTIFY_DONE;
-
-	/* Switch off green LED */
-	omap_set_gpio_dataout(4, 1);
-	/* Flash red LED */
-	omap_writeb(0x78, OMAP_LPG1_LCR);
-	omap_writeb(0x01, OMAP_LPG1_PMR);	/* Enable clock */
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
-	.notifier_call	= panic_event,
-};
-
-static int __init netstar_late_init(void)
-{
-	/* TODO: Setup front panel switch here */
-
-	/* Setup panic notifier */
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
-	return 0;
-}
-
-postcore_initcall(netstar_late_init);
-
-MACHINE_START(NETSTAR, "NetStar OMAP5910")
-	/* Maintainer: Ladislav Michl <michl@2n.cz> */
-	.phys_io	= 0xfff00000,
-	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
-	.boot_params	= 0x10000100,
-	.map_io		= netstar_map_io,
-	.init_irq	= netstar_init_irq,
-	.init_machine	= netstar_init,
-	.timer		= &omap_timer,
-MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
new file mode 100644
index 0000000..02b980d
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,268 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nokia770.c
+ *
+ * Modified from board-generic.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/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
+
+static void __init omap_nokia770_init_irq(void)
+{
+	/* On Nokia 770, the SleepX signal is masked with an
+	 * MPUIO line by default.  It has to be unmasked for it
+	 * to become functional */
+
+	/* SleepX mask direction */
+	omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+	/* Unmask SleepX signal */
+	omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
+	omap1_init_common_hw();
+	omap_init_irq();
+}
+
+static int nokia770_keymap[] = {
+	KEY(0, 1, GROUP_0 | KEY_UP),
+	KEY(0, 2, GROUP_1 | KEY_F5),
+	KEY(1, 0, GROUP_0 | KEY_LEFT),
+	KEY(1, 1, GROUP_0 | KEY_ENTER),
+	KEY(1, 2, GROUP_0 | KEY_RIGHT),
+	KEY(2, 0, GROUP_1 | KEY_ESC),
+	KEY(2, 1, GROUP_0 | KEY_DOWN),
+	KEY(2, 2, GROUP_1 | KEY_F4),
+	KEY(3, 0, GROUP_2 | KEY_F7),
+	KEY(3, 1, GROUP_2 | KEY_F8),
+	KEY(3, 2, GROUP_2 | KEY_F6),
+	0
+};
+
+static struct resource nokia770_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+	.rows   = 8,
+	.cols   = 8,
+	.keymap = nokia770_keymap
+};
+
+static struct platform_device nokia770_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &nokia770_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(nokia770_kp_resources),
+	.resource	= nokia770_kp_resources,
+};
+
+static struct platform_device *nokia770_devices[] __initdata = {
+        &nokia770_kp_device,
+};
+
+static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
+	.x_max		= 0x0fff,
+	.y_max		= 0x0fff,
+	.x_plate_ohms	= 180,
+	.pressure_max	= 255,
+	.debounce_max	= 10,
+	.debounce_tol	= 3,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+	[0] = {
+		.modalias       = "lcd_lph8923",
+		.bus_num        = 2,
+		.chip_select    = 3,
+		.max_speed_hz   = 12000000,
+	},
+	[1] = {
+		.modalias       = "ads7846",
+		.bus_num        = 2,
+		.chip_select    = 0,
+		.max_speed_hz   = 2500000,
+		.irq		= OMAP_GPIO_IRQ(15),
+		.platform_data	= &nokia770_ads7846_platform_data,
+	},
+};
+
+
+/* assume no Mini-AB port */
+
+static struct omap_usb_config nokia770_usb_config __initdata = {
+	.otg		= 1,
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 6,
+};
+
+static struct omap_mmc_config nokia770_mmc_config __initdata = {
+	.mmc[0] = {
+		.enabled	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+	.mmc[1] = {
+		.enabled	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+};
+
+static struct omap_board_config_kernel nokia770_config[] = {
+	{ OMAP_TAG_USB,		NULL },
+	{ OMAP_TAG_MMC,		&nokia770_mmc_config },
+};
+
+/*
+ * audio power control
+ */
+#define	HEADPHONE_GPIO		14
+#define	AMPLIFIER_CTRL_GPIO	58
+
+static struct clk *dspxor_ck;
+static DECLARE_MUTEX(audio_pwr_sem);
+/*
+ * audio_pwr_state
+ * +--+-------------------------+---------------------------------------+
+ * |-1|down			|power-up request -> 0			|
+ * +--+-------------------------+---------------------------------------+
+ * | 0|up			|power-down(1) request -> 1		|
+ * |  |				|power-down(2) request -> (ignore)	|
+ * +--+-------------------------+---------------------------------------+
+ * | 1|up,			|power-up request -> 0			|
+ * |  |received down(1) request	|power-down(2) request -> -1		|
+ * +--+-------------------------+---------------------------------------+
+ */
+static int audio_pwr_state = -1;
+
+/*
+ * audio_pwr_up / down should be called under audio_pwr_sem
+ */
+static void nokia770_audio_pwr_up(void)
+{
+	clk_enable(dspxor_ck);
+
+	/* Turn on codec */
+	tlv320aic23_power_up();
+
+	if (omap_get_gpio_datain(HEADPHONE_GPIO))
+		/* HP not connected, turn on amplifier */
+		omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1);
+	else
+		/* HP connected, do not turn on amplifier */
+		printk("HP connected\n");
+}
+
+static void codec_delayed_power_down(void *arg)
+{
+	down(&audio_pwr_sem);
+	if (audio_pwr_state == -1)
+		tlv320aic23_power_down();
+	clk_disable(dspxor_ck);
+	up(&audio_pwr_sem);
+}
+
+static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+
+static void nokia770_audio_pwr_down(void)
+{
+	/* Turn off amplifier */
+	omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0);
+
+	/* Turn off codec: schedule delayed work */
+	schedule_delayed_work(&codec_power_down_work, HZ / 20);	/* 50ms */
+}
+
+void nokia770_audio_pwr_up_request(int stage)
+{
+	down(&audio_pwr_sem);
+	if (audio_pwr_state == -1)
+		nokia770_audio_pwr_up();
+	/* force audio_pwr_state = 0, even if it was 1. */
+	audio_pwr_state = 0;
+	up(&audio_pwr_sem);
+}
+
+void nokia770_audio_pwr_down_request(int stage)
+{
+	down(&audio_pwr_sem);
+	switch (stage) {
+	case 1:
+		if (audio_pwr_state == 0)
+			audio_pwr_state = 1;
+		break;
+	case 2:
+		if (audio_pwr_state == 1) {
+			nokia770_audio_pwr_down();
+			audio_pwr_state = -1;
+		}
+		break;
+	}
+	up(&audio_pwr_sem);
+}
+
+static void __init omap_nokia770_init(void)
+{
+	nokia770_config[0].data = &nokia770_usb_config;
+
+	platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+	spi_register_board_info(nokia770_spi_board_info,
+				ARRAY_SIZE(nokia770_spi_board_info));
+	omap_board_config = nokia770_config;
+	omap_board_config_size = ARRAY_SIZE(nokia770_config);
+	omap_serial_init();
+	omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
+	omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
+	dspxor_ck = clk_get(0, "dspxor_ck");
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+	omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+	.phys_io	= 0xfff00000,
+	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
+	.boot_params	= 0x10000100,
+	.map_io		= omap_nokia770_map_io,
+	.init_irq	= omap_nokia770_init_irq,
+	.init_machine	= omap_nokia770_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 543fa13..1160093 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,6 +33,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -44,7 +45,24 @@
 #include <asm/arch/usb.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+
+static int osk_keymap[] = {
+	KEY(0, 0, KEY_F1),
+	KEY(0, 3, KEY_UP),
+	KEY(1, 1, KEY_LEFTCTRL),
+	KEY(1, 2, KEY_LEFT),
+	KEY(2, 0, KEY_SPACE),
+	KEY(2, 1, KEY_ESC),
+	KEY(2, 2, KEY_DOWN),
+	KEY(3, 2, KEY_ENTER),
+	KEY(3, 3, KEY_RIGHT),
+	0
+};
+
 
 static struct mtd_partition osk_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
@@ -133,9 +151,69 @@
 	.resource	= osk5912_cf_resources,
 };
 
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+	.spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+	.spcr1 = RINTM(3) | RRST,
+	.rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+	    RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+	.rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+	.xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+	    XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+	.xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+	.srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+	.srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+	/*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
+	.pcr0 = CLKXP | CLKRP,  /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+	.name			= "OSK AIC23",
+	.mcbsp_regs_alsa	= &mcbsp_regs,
+	.codec_configure_dev	= NULL, // aic23_configure,
+	.codec_set_samplerate	= NULL, // aic23_set_samplerate,
+	.codec_clock_setup	= NULL, // aic23_clock_setup,
+	.codec_clock_on		= NULL, // aic23_clock_on,
+	.codec_clock_off	= NULL, // aic23_clock_off,
+	.get_default_samplerate	= NULL, // aic23_get_default_samplerate,
+};
+
 static struct platform_device osk5912_mcbsp1_device = {
-	.name		= "omap_mcbsp",
-	.id		= 1,
+	.name	= "omap_alsa_mcbsp",
+ 	.id	= 1,
+	.dev = {
+		.platform_data	= &alsa_config,
+	},
+};
+
+static struct resource osk5912_kp_resources[] = {
+	[0] = {
+		.start	= INT_KEYBOARD,
+		.end	= INT_KEYBOARD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = osk_keymap,
+};
+
+static struct platform_device osk5912_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &osk_kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(osk5912_kp_resources),
+	.resource	= osk5912_kp_resources,
+};
+
+static struct platform_device osk5912_lcd_device = {
+	.name		= "lcd_osk",
+	.id		= -1,
 };
 
 static struct platform_device *osk5912_devices[] __initdata = {
@@ -143,6 +221,8 @@
 	&osk5912_smc91x_device,
 	&osk5912_cf_device,
 	&osk5912_mcbsp1_device,
+	&osk5912_kp_device,
+	&osk5912_lcd_device,
 };
 
 static void __init osk_init_smc91x(void)
@@ -197,7 +277,6 @@
 };
 
 static struct omap_lcd_config osk_lcd_config __initdata = {
-	.panel_name	= "osk",
 	.ctrl_name	= "internal",
 };
 
@@ -255,8 +334,18 @@
 static void __init osk_mistral_init(void) { }
 #endif
 
+#define EMIFS_CS3_VAL	(0x88013141)
+
 static void __init osk_init(void)
 {
+	/* Workaround for wrong CS3 (NOR flash) timing
+	 * There are some U-Boot versions out there which configure
+	 * wrong CS3 memory timings. This mainly leads to CRC
+	 * or similiar errors if you use NOR flash (e.g. with JFFS2)
+	 */
+	if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
+		EMIFS_CCS(3) = EMIFS_CS3_VAL;
+
 	osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
 	osk_flash_resource.end += SZ_32M - 1;
 	platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index e488f72..4bc8a62 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -38,6 +38,15 @@
 	omap_init_irq();
 }
 
+static struct platform_device palmte_lcd_device = {
+	.name		= "lcd_palmte",
+	.id		= -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&palmte_lcd_device,
+};
+
 static struct omap_usb_config palmte_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0,
@@ -55,7 +64,6 @@
 };
 
 static struct omap_lcd_config palmte_lcd_config __initdata = {
-	.panel_name	= "palmte",
 	.ctrl_name	= "internal",
 };
 
@@ -69,6 +77,8 @@
 {
 	omap_board_config = palmte_config;
 	omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3913a3c..64b45d8 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -28,9 +30,44 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
 #include <asm/arch/common.h>
 #include <asm/arch/board.h>
 
+static int p2_keymap[] = {
+	KEY(0,0,KEY_UP),
+	KEY(0,1,KEY_RIGHT),
+	KEY(0,2,KEY_LEFT),
+	KEY(0,3,KEY_DOWN),
+	KEY(0,4,KEY_CENTER),
+	KEY(0,5,KEY_0_5),
+	KEY(1,0,KEY_SOFT2),
+	KEY(1,1,KEY_SEND),
+	KEY(1,2,KEY_END),
+	KEY(1,3,KEY_VOLUMEDOWN),
+	KEY(1,4,KEY_VOLUMEUP),
+	KEY(1,5,KEY_RECORD),
+	KEY(2,0,KEY_SOFT1),
+	KEY(2,1,KEY_3),
+	KEY(2,2,KEY_6),
+	KEY(2,3,KEY_9),
+	KEY(2,4,KEY_SHARP),
+	KEY(2,5,KEY_2_5),
+	KEY(3,0,KEY_BACK),
+	KEY(3,1,KEY_2),
+	KEY(3,2,KEY_5),
+	KEY(3,3,KEY_8),
+	KEY(3,4,KEY_0),
+	KEY(3,5,KEY_HEADSETHOOK),
+	KEY(4,0,KEY_HOME),
+	KEY(4,1,KEY_1),
+	KEY(4,2,KEY_4),
+	KEY(4,3,KEY_7),
+	KEY(4,4,KEY_STAR),
+	KEY(4,5,KEY_POWER),
+	0
+};
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= H2P2_DBG_FPGA_ETHR_START,	/* Physical */
@@ -44,7 +81,7 @@
 	},
 };
 
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
 	      .name		= "bootloader",
@@ -75,27 +112,47 @@
 	},
 };
 
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-	.parts		= p2_partitions,
-	.nr_parts	= ARRAY_SIZE(p2_partitions),
+	.parts		= nor_partitions,
+	.nr_parts	= ARRAY_SIZE(nor_partitions),
 };
 
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
 	.start		= OMAP_CS0_PHYS,
 	.end		= OMAP_CS0_PHYS + SZ_32M - 1,
 	.flags		= IORESOURCE_MEM,
 };
 
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
 	.name		= "omapflash",
 	.id		= 0,
 	.dev		= {
-		.platform_data	= &p2_flash_data,
+		.platform_data	= &nor_data,
 	},
 	.num_resources	= 1,
-	.resource	= &p2_flash_resource,
+	.resource	= &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+	.options	= NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+	.start		= OMAP_CS3_PHYS,
+	.end		= OMAP_CS3_PHYS + SZ_4K - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+	.name		= "omapnand",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &nand_resource,
 };
 
 static struct platform_device smc91x_device = {
@@ -105,17 +162,55 @@
 	.resource	= smc91x_resources,
 };
 
-static struct platform_device *devices[] __initdata = {
-	&p2_flash_device,
-	&smc91x_device,
+static struct resource kp_resources[] = {
+	[0] = {
+		.start	= INT_730_MPUIO_KEYPAD,
+		.end	= INT_730_MPUIO_KEYPAD,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
+static struct omap_kp_platform_data kp_data = {
+	.rows	= 8,
+	.cols	= 8,
+	.keymap = p2_keymap,
+};
+
+static struct platform_device kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &kp_data,
+	},
+	.num_resources	= ARRAY_SIZE(kp_resources),
+	.resource	= kp_resources,
+};
+
+static struct platform_device lcd_device = {
+	.name		= "lcd_p2",
+	.id		= -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&nor_device,
+	&nand_device,
+	&smc91x_device,
+	&kp_device,
+	&lcd_device,
+};
+
+#define P2_NAND_RB_GPIO_PIN	62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+	return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
 static struct omap_uart_config perseus2_uart_config __initdata = {
 	.enabled_uarts = ((1 << 0) | (1 << 1)),
 };
 
 static struct omap_lcd_config perseus2_lcd_config __initdata = {
-	.panel_name	= "p2",
 	.ctrl_name	= "internal",
 };
 
@@ -126,7 +221,13 @@
 
 static void __init omap_perseus2_init(void)
 {
-	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+	if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+		nand_data.dev_ready = nand_dev_ready;
+
+	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 
 	omap_board_config = perseus2_config;
 	omap_board_config_size = ARRAY_SIZE(perseus2_config);
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 52e4a9d..447a586 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -155,9 +155,9 @@
 };
 
 static struct omap_board_config_kernel voiceblue_config[] = {
-	{ OMAP_TAG_USB, &voiceblue_usb_config },
-	{ OMAP_TAG_MMC, &voiceblue_mmc_config },
-	{ OMAP_TAG_UART,	&voiceblue_uart_config },
+	{ OMAP_TAG_USB,  &voiceblue_usb_config },
+	{ OMAP_TAG_MMC,  &voiceblue_mmc_config },
+	{ OMAP_TAG_UART, &voiceblue_uart_config },
 };
 
 static void __init voiceblue_init_irq(void)
@@ -235,7 +235,7 @@
 static int __init voiceblue_setup(void)
 {
 	/* Setup panic notifier */
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+	notifier_chain_register(&panic_notifier_list, &panic_block);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 75110ba..619db18 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -345,7 +345,7 @@
 	 */
 	for (dsor = 2; dsor < 96; ++dsor) {
 		if ((dsor & 1) && dsor > 8)
-		  	continue;
+			continue;
 		if (rate >= 96000000 / dsor)
 			break;
 	}
@@ -687,6 +687,11 @@
 			clk_register(*clkp);
 			continue;
 		}
+
+		if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
+			clk_register(*clkp);
+			continue;
+		}
 	}
 
 	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -784,7 +789,7 @@
 	clk_enable(&armxor_ck.clk);
 	clk_enable(&armtim_ck.clk); /* This should be done by timer code */
 
-	if (cpu_is_omap1510())
+	if (cpu_is_omap15xx())
 		clk_enable(&arm_gpio_ck);
 
 	return 0;
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 4f18d1b..b7c6881 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -151,7 +151,7 @@
 	.name		= "ck_ref",
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -160,7 +160,7 @@
 	.name		= "ck_dpll1",
 	.parent		= &ck_ref,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_PROPAGATES | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -183,7 +183,8 @@
 	.name		= "arm_ck",
 	.parent		= &ck_dpll1,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
+			  ALWAYS_ENABLED,
 	.rate_offset	= CKCTL_ARMDIV_OFFSET,
 	.recalc		= &omap1_ckctl_recalc,
 	.enable		= &omap1_clk_enable_generic,
@@ -195,7 +196,8 @@
 		.name		= "armper_ck",
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  RATE_CKCTL | CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | RATE_CKCTL |
+				  CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_PERCK,
 		.rate_offset	= CKCTL_PERDIV_OFFSET,
@@ -209,7 +211,7 @@
 static struct clk arm_gpio_ck = {
 	.name		= "arm_gpio_ck",
 	.parent		= &ck_dpll1,
-	.flags		= CLOCK_IN_OMAP1510,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
 	.enable_reg	= (void __iomem *)ARM_IDLECT2,
 	.enable_bit	= EN_GPIOCK,
 	.recalc		= &followparent_recalc,
@@ -222,7 +224,7 @@
 		.name		= "armxor_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_XORPCK,
 		.recalc		= &followparent_recalc,
@@ -237,7 +239,7 @@
 		.name		= "armtim_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_TIMCK,
 		.recalc		= &followparent_recalc,
@@ -252,7 +254,7 @@
 		.name		= "armwdt_ck",
 		.parent		= &ck_ref,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_WDTCK,
 		.recalc		= &omap1_watchdog_recalc,
@@ -344,9 +346,9 @@
 		.name		= "tc_ck",
 		.parent		= &ck_dpll1,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IN_OMAP730 | RATE_CKCTL |
-				  RATE_PROPAGATES | ALWAYS_ENABLED |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
+				  RATE_CKCTL | RATE_PROPAGATES |
+				  ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
 		.rate_offset	= CKCTL_TCDIV_OFFSET,
 		.recalc		= &omap1_ckctl_recalc,
 		.enable		= &omap1_clk_enable_generic,
@@ -358,7 +360,8 @@
 static struct clk arminth_ck1510 = {
 	.name		= "arminth_ck",
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	/* Note: On 1510 the frequency follows TC_CK
 	 *
@@ -372,7 +375,8 @@
 	/* No-idle controlled by "tc_ck" */
 	.name		= "tibp_ck",
 	.parent		= &tc_ck.clk,
-	.flags		= CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
@@ -417,7 +421,7 @@
 	.name		= "dma_ck",
 	.parent		= &tc_ck.clk,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
 	.recalc		= &followparent_recalc,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
@@ -437,7 +441,7 @@
 		.name		= "api_ck",
 		.parent		= &tc_ck.clk,
 		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-				  CLOCK_IDLE_CONTROL,
+				  CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_APICK,
 		.recalc		= &followparent_recalc,
@@ -451,7 +455,8 @@
 	.clk = {
 		.name		= "lb_ck",
 		.parent		= &tc_ck.clk,
-		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+				  CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_LBCK,
 		.recalc		= &followparent_recalc,
@@ -495,8 +500,8 @@
 	.clk = {
 		.name		= "lcd_ck",
 		.parent		= &ck_dpll1,
-		.flags		= CLOCK_IN_OMAP1510 | RATE_CKCTL |
-				  CLOCK_IDLE_CONTROL,
+		.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+				  RATE_CKCTL | CLOCK_IDLE_CONTROL,
 		.enable_reg	= (void __iomem *)ARM_IDLECT2,
 		.enable_bit	= EN_LCDCK,
 		.rate_offset	= CKCTL_LCDDIV_OFFSET,
@@ -512,8 +517,9 @@
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
-			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 29,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -544,8 +550,8 @@
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
-			  CLOCK_NO_IDLE_PARENT,
+			  CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
+			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 30,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -559,8 +565,9 @@
 	/* Direct from ULPD, no real parent */
 	.parent		= &armper_ck.clk,
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
-			  ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+			  ENABLE_REG_32BIT | ALWAYS_ENABLED |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 31,	/* Chooses between 12MHz and 48MHz */
 	.set_rate	= &omap1_set_uart_rate,
@@ -590,7 +597,7 @@
 	/* Direct from ULPD, no parent */
 	.rate		= 6000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT,
+			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)ULPD_CLOCK_CTRL,
 	.enable_bit	= USB_MCLK_EN_BIT,
 	.enable		= &omap1_clk_enable_generic,
@@ -601,7 +608,7 @@
 	.name		= "usb_hhc_ck",
 	/* Direct from ULPD, no parent */
 	.rate		= 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
-	.flags		= CLOCK_IN_OMAP1510 |
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
 			  RATE_FIXED | ENABLE_REG_32BIT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= USB_HOST_HHC_UHOST_EN,
@@ -637,7 +644,9 @@
 	.name		= "mclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
+ 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+ 	.enable_reg	= (void __iomem *)SOFT_REQ_REG,
+ 	.enable_bit	= 6,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -659,7 +668,7 @@
 	.name		= "bclk",
 	/* Direct from ULPD, no parent. May be enabled by ext hardware. */
 	.rate		= 12000000,
-	.flags		= CLOCK_IN_OMAP1510 | RATE_FIXED,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
 	.enable		= &omap1_clk_enable_generic,
 	.disable	= &omap1_clk_disable_generic,
 };
@@ -678,12 +687,14 @@
 };
 
 static struct clk mmc1_ck = {
-	.name		= "mmc1_ck",
+	.name		= "mmc_ck",
+	.id		= 1,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+			  CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+			  CLOCK_NO_IDLE_PARENT,
 	.enable_reg	= (void __iomem *)MOD_CONF_CTRL_0,
 	.enable_bit	= 23,
 	.enable		= &omap1_clk_enable_generic,
@@ -691,7 +702,8 @@
 };
 
 static struct clk mmc2_ck = {
-	.name		= "mmc2_ck",
+	.name		= "mmc_ck",
+	.id		= 2,
 	/* Functional clock is direct from ULPD, interface clock is ARMPER */
 	.parent		= &armper_ck.clk,
 	.rate		= 48000000,
@@ -706,7 +718,7 @@
 static struct clk virtual_ck_mpu = {
 	.name		= "mpu",
 	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
-			  VIRTUAL_CLOCK | ALWAYS_ENABLED,
+			  CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
 	.parent		= &arm_ck, /* Is smarter alias for */
 	.recalc		= &followparent_recalc,
 	.set_rate	= &omap1_select_table_rate,
@@ -715,6 +727,20 @@
 	.disable	= &omap1_clk_disable_generic,
 };
 
+/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
+remains active during MPU idle whenever this is enabled */
+static struct clk i2c_fck = {
+	.name		= "i2c_fck",
+	.id		= 1,
+	.flags		= CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+			  VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+			  ALWAYS_ENABLED,
+	.parent		= &armxor_ck.clk,
+	.recalc		= &followparent_recalc,
+	.enable		= &omap1_clk_enable_generic,
+	.disable	= &omap1_clk_disable_generic,
+};
+
 static struct clk * onchip_clks[] = {
 	/* non-ULPD clocks */
 	&ck_ref,
@@ -763,6 +789,7 @@
 	&mmc2_ck,
 	/* Virtual clocks */
 	&virtual_ck_mpu,
+	&i2c_fck,
 };
 
 #endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ecbc475..847329c 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -25,10 +25,6 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
 
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
 #if	defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE)
 
 static u64 irda_dmamask = 0xffffffff;
@@ -37,7 +33,6 @@
 	.name = "omap1610-ir",
 	.id = -1,
 	.dev = {
-		.release	= omap_nop_release,
 		.dma_mask	= &irda_dmamask,
 	},
 };
@@ -84,9 +79,6 @@
 static struct platform_device omap_rtc_device = {
 	.name           = "omap_rtc",
 	.id             = -1,
-	.dev = {
-		.release        = omap_nop_release,
-	},
 	.num_resources	= ARRAY_SIZE(rtc_resources),
 	.resource	= rtc_resources,
 };
@@ -99,6 +91,42 @@
 static inline void omap_init_rtc(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP1_STI_BASE		IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_CHANNEL_BASE	(OMAP1_STI_BASE + 0x400)
+
+static struct resource sti_resources[] = {
+	{
+		.start		= OMAP1_STI_BASE,
+		.end		= OMAP1_STI_BASE + SZ_1K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP1_STI_CHANNEL_BASE,
+		.end		= OMAP1_STI_CHANNEL_BASE + SZ_1K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= INT_1610_STI,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device sti_device = {
+	.name		= "sti",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(sti_resources),
+	.resource	= sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+	platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -129,6 +157,7 @@
 	 */
 	omap_init_irda();
 	omap_init_rtc();
+	omap_init_sti();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 82d556b..be3a2a4 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,6 +18,7 @@
 #include <asm/io.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
 
 extern int omap1_clk_init(void);
 extern void omap_check_revision(void);
@@ -110,7 +111,7 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 	}
 #endif
@@ -121,6 +122,7 @@
 #endif
 
 	omap_sram_init();
+	omapfb_reserve_mem();
 }
 
 /*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index ed65a7d..a0431c0 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -60,7 +60,7 @@
 	unsigned long wake_enable;
 };
 
-static unsigned int irq_bank_count = 0;
+static unsigned int irq_bank_count;
 static struct omap_irq_bank *irq_banks;
 
 static inline unsigned int irq_bank_readl(int bank, int offset)
@@ -142,28 +142,28 @@
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct omap_irq_bank omap730_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3f8e22f },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfdb9c1f2 },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3f8e22f },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xfdb9c1f2 },
 	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0x800040f3 },
 };
 #endif
 
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct omap_irq_bank omap1510_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3febfff },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xffbfffed },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3febfff },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xffbfffed },
 };
 static struct omap_irq_bank omap310_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3faefc3 },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0x65b3c061 },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3faefc3 },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0x65b3c061 },
 };
 #endif
 
 #if defined(CONFIG_ARCH_OMAP16XX)
 
 static struct omap_irq_bank omap1610_irq_banks[] = {
-	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3fefe8f },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfdb7c1fd },
+	{ .base_reg = OMAP_IH1_BASE,		.trigger_map = 0xb3fefe8f },
+	{ .base_reg = OMAP_IH2_BASE,		.trigger_map = 0xfdb7c1fd },
 	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0xffffb7ff },
 	{ .base_reg = OMAP_IH2_BASE + 0x200,	.trigger_map = 0xffffffff },
 };
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index d4b8d62..10fe0b3 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -35,16 +35,20 @@
 
 #ifdef CONFIG_ARCH_OMAP730
 struct pin_config __initdata_or_module omap730_pins[] = {
-MUX_CFG_730("E2_730_KBR0",	12,   21,    0,	  0,   20,   1,	  NA,	 0,  0)
-MUX_CFG_730("J7_730_KBR1",	12,   25,    0,	  0,   24,   1,	  NA,	 0,  0)
-MUX_CFG_730("E1_730_KBR2",	12,   29,    0,	  0,   28,   1,	  NA,	 0,  0)
-MUX_CFG_730("F3_730_KBR3",	13,    1,    0,	  0,   0,    1,	  NA,	 0,  0)
-MUX_CFG_730("D2_730_KBR4",	13,    5,    0,	  0,   4,    1,	  NA,	 0,  0)
-MUX_CFG_730("C2_730_KBC0",	13,    9,    0,	  0,	8,   1,	  NA,	 0,  0)
-MUX_CFG_730("D3_730_KBC1",	13,   13,    0,	  0,   12,   1,	  NA,	 0,  0)
-MUX_CFG_730("E4_730_KBC2",	13,   17,    0,	  0,   16,   1,	  NA,	 0,  0)
-MUX_CFG_730("F4_730_KBC3",	13,   21,    0,	  0,   20,   1,	  NA,	 0,  0)
-MUX_CFG_730("E3_730_KBC4",	13,   25,    0,	  0,   24,   1,	  NA,	 0,  0)
+MUX_CFG_730("E2_730_KBR0",        12,   21,    0,   20,   1, 0)
+MUX_CFG_730("J7_730_KBR1",        12,   25,    0,   24,   1, 0)
+MUX_CFG_730("E1_730_KBR2",        12,   29,    0,   28,   1, 0)
+MUX_CFG_730("F3_730_KBR3",        13,    1,    0,    0,   1, 0)
+MUX_CFG_730("D2_730_KBR4",        13,    5,    0,    4,   1, 0)
+MUX_CFG_730("C2_730_KBC0",        13,    9,    0,    8,   1, 0)
+MUX_CFG_730("D3_730_KBC1",        13,   13,    0,   12,   1, 0)
+MUX_CFG_730("E4_730_KBC2",        13,   17,    0,   16,   1, 0)
+MUX_CFG_730("F4_730_KBC3",        13,   21,    0,   20,   1, 0)
+MUX_CFG_730("E3_730_KBC4",        13,   25,    0,   24,   1, 0)
+
+MUX_CFG_730("AA17_730_USB_DM",     2,   21,    0,   20,   0, 0)
+MUX_CFG_730("W16_730_USB_PU_EN",   2,   25,    0,   24,   0, 0)
+MUX_CFG_730("W17_730_USB_VBUSI",   2,   29,    0,   28,   0, 0)
 };
 #endif
 
@@ -73,8 +77,8 @@
 MUX_CFG("Y15_1610_UART3_RTS",	 A,    0,    1,	  2,   6,   0,	 NA,	 0,  0)
 
 /* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT",		 	 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
-MUX_CFG("PWL",		 	 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
+MUX_CFG("PWT",			 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
+MUX_CFG("PWL",			 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
 
 /* USB internal master generic */
 MUX_CFG("R18_USB_VBUS",		 7,    9,    2,	  1,  11,   0,	 NA,	 0,  1)
@@ -151,7 +155,7 @@
 
 /* Misc ballouts */
 MUX_CFG("BALLOUT_V8_ARMIO3",	 B,   18,    0,	  2,  25,   1,	 NA,	 0,  1)
-MUX_CFG("N20_HDQ",	       6,   18,    1,   1,   4,   0,    1,     4,  0)
+MUX_CFG("N20_HDQ",		 6,   18,    1,   1,   4,   0,    1,     4,  0)
 
 /* OMAP-1610 MMC2 */
 MUX_CFG("W8_1610_MMC2_DAT0",	 B,   21,    6,	  2,  23,   1,	  2,	 1,  1)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 0000000..ddf6b07
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,770 @@
+/*
+ * linux/arch/arm/mach-omap1/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.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 <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/dmtimer.h>
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+{
+	return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+					      const char * buf,
+					      size_t n)
+{
+	unsigned short value;
+	if (sscanf(buf, "%hu", &value) != 1 ||
+	    (value != 0 && value != 1)) {
+		printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+		return -EINVAL;
+	}
+	enable_dyn_sleep = value;
+	return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+	.attr   = {
+		.name = __stringify(sleep_while_idle),
+		.mode = 0644,
+	},
+	.show   = omap_pm_sleep_while_idle_show,
+	.store  = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+	extern __u32 arm_idlect1_mask;
+	__u32 use_idlect1 = arm_idlect1_mask;
+#ifndef CONFIG_OMAP_MPU_TIMER
+	int do_sleep;
+#endif
+
+	local_irq_disable();
+	local_fiq_disable();
+	if (need_resched()) {
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+
+	/*
+	 * Since an interrupt may set up a timer, we don't want to
+	 * reprogram the hardware timer with interrupts enabled.
+	 * Re-enable interrupts only after returning from idle.
+	 */
+	timer_dyn_reprogram();
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+#warning Enable 32kHz OS timer in order to allow sleep states in idle
+	use_idlect1 = use_idlect1 & ~(1 << 9);
+#else
+
+	do_sleep = 0;
+	while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+		extern int vbus_active;
+		/* Clock requirements? */
+		if (vbus_active)
+			break;
+#endif
+		do_sleep = 1;
+		break;
+	}
+
+#ifdef CONFIG_OMAP_DM_TIMER
+	use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+	if (omap_dma_running()) {
+		use_idlect1 &= ~(1 << 6);
+		if (omap_lcd_dma_ext_running())
+			use_idlect1 &= ~(1 << 12);
+	}
+
+	/* We should be able to remove the do_sleep variable and multiple
+	 * tests above as soon as drivers, timer and DMA code have been fixed.
+	 * Even the sleep block count should become obsolete. */
+	if ((use_idlect1 != ~0) || !do_sleep) {
+
+		__u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
+		if (cpu_is_omap15xx())
+			use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST;
+		else
+			use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL;
+		omap_writel(use_idlect1, ARM_IDLECT1);
+		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
+		omap_writel(saved_idlect1, ARM_IDLECT1);
+
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+	omap_sram_suspend(omap_readl(ARM_IDLECT1),
+			  omap_readl(ARM_IDLECT2));
+#endif
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+	u32 level1_wake = 0;
+	u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
+
+	/*
+	 * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+	 * and the L2 wakeup interrupts: keypad and UART2. Note that the
+	 * drivers must still separately call omap_set_gpio_wakeup() to
+	 * wake up to a GPIO interrupt.
+	 */
+	if (cpu_is_omap730())
+		level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+	else if (cpu_is_omap15xx())
+		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+	else if (cpu_is_omap16xx())
+		level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+			OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
+
+	omap_writel(~level1_wake, OMAP_IH1_MIR);
+
+	if (cpu_is_omap730()) {
+		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+		omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
+				OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
+				OMAP_IH2_1_MIR);
+	} else if (cpu_is_omap15xx()) {
+		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+		omap_writel(~level2_wake,  OMAP_IH2_MIR);
+	} else if (cpu_is_omap16xx()) {
+		level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+		omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+		/* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
+		omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
+			    OMAP_IH2_1_MIR);
+		omap_writel(~0x0, OMAP_IH2_2_MIR);
+		omap_writel(~0x0, OMAP_IH2_3_MIR);
+	}
+
+	/*  New IRQ agreement, recalculate in cascade order */
+	omap_writel(1, OMAP_IH2_CONTROL);
+	omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#define EN_DSPCK	13	/* ARM_CKCTL */
+#define EN_APICK	6	/* ARM_IDLECT2 */
+#define DSP_EN		1	/* ARM_RSTCT1 */
+
+void omap_pm_suspend(void)
+{
+	unsigned long arg0 = 0, arg1 = 0;
+
+	printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+	omap_serial_wake_trigger(1);
+
+	if (machine_is_omap_osk()) {
+		/* Stop LED1 (D9) blink */
+		tps65010_set_led(LED1, OFF);
+	}
+
+	omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
+	/*
+	 * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
+	 */
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	/*
+	 * Step 2: save registers
+	 *
+	 * The omap is a strange/beautiful device. The caches, memory
+	 * and register state are preserved across power saves.
+	 * We have to save and restore very little register state to
+	 * idle the omap.
+         *
+	 * Save interrupt, MPUI, ARM and UPLD control registers.
+	 */
+
+	if (cpu_is_omap730()) {
+		MPUI730_SAVE(OMAP_IH1_MIR);
+		MPUI730_SAVE(OMAP_IH2_0_MIR);
+		MPUI730_SAVE(OMAP_IH2_1_MIR);
+		MPUI730_SAVE(MPUI_CTRL);
+		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI730_SAVE(EMIFS_CONFIG);
+		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_SAVE(OMAP_IH1_MIR);
+		MPUI1510_SAVE(OMAP_IH2_MIR);
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(OMAP_IH1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_0_MIR);
+		MPUI1610_SAVE(OMAP_IH2_1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_2_MIR);
+		MPUI1610_SAVE(OMAP_IH2_3_MIR);
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+	}
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	if (!(cpu_is_omap15xx()))
+		ARM_SAVE(ARM_IDLECT3);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+
+	/* (Step 3 removed - we now allow deep sleep by default) */
+
+	/*
+	 * Step 4: OMAP DSP Shutdown
+	 */
+
+	/* stop DSP */
+	omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
+
+	/* shut down dsp_ck */
+	omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
+
+	/* temporarily enabling api_ck to access DSP registers */
+	omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+	/* save DSP registers */
+	DSP_SAVE(DSP_IDLECT2);
+
+	/* Stop all DSP domain clocks */
+	__raw_writew(0, DSP_IDLECT2);
+
+	/*
+	 * Step 5: Wakeup Event Setup
+	 */
+
+	omap_pm_wakeup_setup();
+
+	/*
+	 * Step 6: ARM and Traffic controller shutdown
+	 */
+
+	/* disable ARM watchdog */
+	omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+	omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+	/*
+	 * Step 6b: ARM and Traffic controller shutdown
+	 *
+	 * Step 6 continues here. Prepare jump to power management
+	 * assembly code in internal SRAM.
+	 *
+	 * Since the omap_cpu_suspend routine has been copied to
+	 * SRAM, we'll do an indirect procedure call to it and pass the
+	 * contents of arm_idlect1 and arm_idlect2 so it can restore
+	 * them when it wakes up and it will return.
+	 */
+
+	arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+	arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+	/*
+	 * Step 6c: ARM and Traffic controller shutdown
+	 *
+	 * Jump to assembly code. The processor will stay there
+	 * until wake up.
+	 */
+        omap_sram_suspend(arg0, arg1);
+
+	/*
+	 * If we are here, processor is woken up!
+	 */
+
+	/*
+	 * Restore DSP clocks
+	 */
+
+	/* again temporarily enabling api_ck to access DSP registers */
+	omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+	/* Restore DSP domain clocks */
+	DSP_RESTORE(DSP_IDLECT2);
+
+	/*
+	 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+	 */
+
+	if (!(cpu_is_omap15xx()))
+		ARM_RESTORE(ARM_IDLECT3);
+	ARM_RESTORE(ARM_CKCTL);
+	ARM_RESTORE(ARM_EWUPCT);
+	ARM_RESTORE(ARM_RSTCT1);
+	ARM_RESTORE(ARM_RSTCT2);
+	ARM_RESTORE(ARM_SYSST);
+	ULPD_RESTORE(ULPD_CLOCK_CTRL);
+	ULPD_RESTORE(ULPD_STATUS_REQ);
+
+	if (cpu_is_omap730()) {
+		MPUI730_RESTORE(EMIFS_CONFIG);
+		MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+		MPUI730_RESTORE(OMAP_IH1_MIR);
+		MPUI730_RESTORE(OMAP_IH2_0_MIR);
+		MPUI730_RESTORE(OMAP_IH2_1_MIR);
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_RESTORE(MPUI_CTRL);
+		MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1510_RESTORE(EMIFS_CONFIG);
+		MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_RESTORE(OMAP_IH1_MIR);
+		MPUI1510_RESTORE(OMAP_IH2_MIR);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_RESTORE(MPUI_CTRL);
+		MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1610_RESTORE(EMIFS_CONFIG);
+		MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+		MPUI1610_RESTORE(OMAP_IH1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+	}
+
+	omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+	/*
+	 * Reenable interrupts
+	 */
+
+	local_irq_enable();
+	local_fiq_enable();
+
+	omap_serial_wake_trigger(0);
+
+	printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+	if (machine_is_omap_osk()) {
+		/* Let LED1 (D9) blink again */
+		tps65010_set_led(LED1, BLINK);
+	}
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+	char *page_buffer,
+	char **my_first_byte,
+	off_t virtual_start,
+	int length,
+	int *eof,
+	void *data)
+{
+	int my_buffer_offset = 0;
+	char * const my_base = page_buffer;
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	if (!(cpu_is_omap15xx()))
+		ARM_SAVE(ARM_IDLECT3);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+
+	ULPD_SAVE(ULPD_IT_STATUS);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_SOFT_REQ);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+	ULPD_SAVE(ULPD_DPLL_CTRL);
+	ULPD_SAVE(ULPD_POWER_CTRL);
+
+	if (cpu_is_omap730()) {
+		MPUI730_SAVE(MPUI_CTRL);
+		MPUI730_SAVE(MPUI_DSP_STATUS);
+		MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI730_SAVE(EMIFS_CONFIG);
+	} else if (cpu_is_omap15xx()) {
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_STATUS);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_STATUS);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+	}
+
+	if (virtual_start == 0) {
+		g_read_completed = 0;
+
+		my_buffer_offset += sprintf(my_base + my_buffer_offset,
+		   "ARM_CKCTL_REG:            0x%-8x     \n"
+		   "ARM_IDLECT1_REG:          0x%-8x     \n"
+		   "ARM_IDLECT2_REG:          0x%-8x     \n"
+		   "ARM_IDLECT3_REG:	      0x%-8x     \n"
+		   "ARM_EWUPCT_REG:           0x%-8x     \n"
+		   "ARM_RSTCT1_REG:           0x%-8x     \n"
+		   "ARM_RSTCT2_REG:           0x%-8x     \n"
+		   "ARM_SYSST_REG:            0x%-8x     \n"
+		   "ULPD_IT_STATUS_REG:       0x%-4x     \n"
+		   "ULPD_CLOCK_CTRL_REG:      0x%-4x     \n"
+		   "ULPD_SOFT_REQ_REG:        0x%-4x     \n"
+		   "ULPD_DPLL_CTRL_REG:       0x%-4x     \n"
+		   "ULPD_STATUS_REQ_REG:      0x%-4x     \n"
+		   "ULPD_POWER_CTRL_REG:      0x%-4x     \n",
+		   ARM_SHOW(ARM_CKCTL),
+		   ARM_SHOW(ARM_IDLECT1),
+		   ARM_SHOW(ARM_IDLECT2),
+		   ARM_SHOW(ARM_IDLECT3),
+		   ARM_SHOW(ARM_EWUPCT),
+		   ARM_SHOW(ARM_RSTCT1),
+		   ARM_SHOW(ARM_RSTCT2),
+		   ARM_SHOW(ARM_SYSST),
+		   ULPD_SHOW(ULPD_IT_STATUS),
+		   ULPD_SHOW(ULPD_CLOCK_CTRL),
+		   ULPD_SHOW(ULPD_SOFT_REQ),
+		   ULPD_SHOW(ULPD_DPLL_CTRL),
+		   ULPD_SHOW(ULPD_STATUS_REQ),
+		   ULPD_SHOW(ULPD_POWER_CTRL));
+
+		if (cpu_is_omap730()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI730_CTRL_REG	     0x%-8x \n"
+			   "MPUI730_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI730_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI730_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI730_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI730_SHOW(MPUI_CTRL),
+			   MPUI730_SHOW(MPUI_DSP_STATUS),
+			   MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI730_SHOW(EMIFS_CONFIG));
+		} else if (cpu_is_omap15xx()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1510_CTRL_REG             0x%-8x \n"
+			   "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI1510_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI1510_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI1510_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI1510_SHOW(MPUI_CTRL),
+			   MPUI1510_SHOW(MPUI_DSP_STATUS),
+			   MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI1510_SHOW(EMIFS_CONFIG));
+		} else if (cpu_is_omap16xx()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1610_CTRL_REG             0x%-8x \n"
+			   "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+			   "MPUI1610_DSP_API_CONFIG_REG:  0x%-8x \n"
+			   "MPUI1610_SDRAM_CONFIG_REG:    0x%-8x \n"
+			   "MPUI1610_EMIFS_CONFIG_REG:    0x%-8x \n",
+			   MPUI1610_SHOW(MPUI_CTRL),
+			   MPUI1610_SHOW(MPUI_DSP_STATUS),
+			   MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+			   MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+			   MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+			   MPUI1610_SHOW(EMIFS_CONFIG));
+		}
+
+		g_read_completed++;
+	} else if (g_read_completed >= 1) {
+		 *eof = 1;
+		 return 0;
+	}
+	g_read_completed++;
+
+	*my_first_byte = page_buffer;
+	return  my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+	struct proc_dir_entry *entry;
+
+	entry = create_proc_read_entry("driver/omap_pm",
+				       S_IWUSR | S_IRUGO, NULL,
+				       omap_pm_read_proc, NULL);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+static void (*saved_idle)(void) = NULL;
+
+/*
+ *	omap_pm_prepare - Do preliminary suspend work.
+ *	@state:		suspend state we're entering.
+ *
+ */
+static int omap_pm_prepare(suspend_state_t state)
+{
+	int error = 0;
+
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return error;
+}
+
+
+/*
+ *	omap_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+
+static int omap_pm_enter(suspend_state_t state)
+{
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		omap_pm_suspend();
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/**
+ *	omap_pm_finish - Finish up suspend sequence.
+ *	@state:		State we're coming out of.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+
+static int omap_pm_finish(suspend_state_t state)
+{
+	pm_idle = saved_idle;
+	return 0;
+}
+
+
+static irqreturn_t  omap_wakeup_interrupt(int  irq, void *  dev,
+				     struct pt_regs *  regs)
+{
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+	.name		= "peripheral wakeup",
+	.flags		= SA_INTERRUPT,
+	.handler	= omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
+	.pm_disk_mode	= 0,
+	.prepare	= omap_pm_prepare,
+	.enter		= omap_pm_enter,
+	.finish		= omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+	printk("Power Management for TI OMAP.\n");
+
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+	if (cpu_is_omap730()) {
+		omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+						omap730_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+						   omap730_cpu_suspend_sz);
+	} else if (cpu_is_omap15xx()) {
+		omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+						omap1510_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+						   omap1510_cpu_suspend_sz);
+	} else if (cpu_is_omap16xx()) {
+		omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+						omap1610_idle_loop_suspend_sz);
+		omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+						   omap1610_cpu_suspend_sz);
+	}
+
+	if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+		printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+		return -ENODEV;
+	}
+
+	pm_idle = omap_pm_idle;
+
+	if (cpu_is_omap730())
+		setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+	else if (cpu_is_omap16xx())
+		setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
+	/* Program new power ramp-up time
+	 * (0 for most boards since we don't lower voltage when in deep sleep)
+	 */
+	omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+	/* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+	omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+	/* Configure IDLECT3 */
+	if (cpu_is_omap730())
+		omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+	else if (cpu_is_omap16xx())
+		omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+	pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+	omap_pm_init_proc();
+#endif
+
+	subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+
+	if (cpu_is_omap16xx()) {
+		/* configure LOW_PWR pin */
+		omap_cfg_reg(T20_1610_LOW_PWR);
+	}
+
+	return 0;
+}
+__initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index e924e0c..9b4cd69 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -30,9 +30,9 @@
 #include <asm/arch/pm.h>
 #endif
 
-static struct clk * uart1_ck = NULL;
-static struct clk * uart2_ck = NULL;
-static struct clk * uart3_ck = NULL;
+static struct clk * uart1_ck;
+static struct clk * uart2_ck;
+static struct clk * uart3_ck;
 
 static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
 					  int offset)
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S
similarity index 92%
rename from arch/arm/plat-omap/sleep.S
rename to arch/arm/mach-omap1/sleep.S
index 4cd7d29..e58295e 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/plat-omap/sleep.S
+ * linux/arch/arm/mach-omap1/sleep.S
  *
  * Low-level OMAP730/1510/1610 sleep/wakeUp support
  *
@@ -383,60 +383,133 @@
 	mcr	p15, 0, r0, c7, c10, 4
 	nop
 
-	@ load base address of Traffic Controller
+	@ Load base address of Traffic Controller
 	mov	r6, #TCMIF_ASM_BASE & 0xff000000
 	orr	r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
 	orr	r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
 
-	@ prepare to put SDRAM into self-refresh manually
+	@ Prepare to put SDRAM into self-refresh manually
 	ldr	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 	orr	r9, r7, #SELF_REFRESH_MODE & 0xff000000
 	orr	r9, r9, #SELF_REFRESH_MODE & 0x000000ff
 	str	r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 
-	@ prepare to put EMIFS to Sleep
+	@ Prepare to put EMIFS to Sleep
 	ldr	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 	orr	r9, r8, #IDLE_EMIFS_REQUEST & 0xff
 	str	r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 
-	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	@ Load base address of ARM_IDLECT1 and ARM_IDLECT2
 	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
 	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
 	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
 
-	@ turn off clock domains
-	@ do not disable PERCK (0x04)
+	@ Turn off clock domains
+	@ Do not disable PERCK (0x04)
 	mov	r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
 	orr	r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
 	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 
-	@ request ARM idle
+	@ Request ARM idle
 	mov	r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
 	orr	r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
 	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
-	@ disable instruction cache
-	mrc	p15, 0, r9, c1, c0, 0
-	bic	r2, r9, #0x1000
-	mcr	p15, 0, r2, c1, c0, 0
-	nop
-
 /*
  * Let's wait for the next wake up event to wake us up. r0 can't be
  * used here because r0 holds ARM_IDLECT1
  */
 	mov	r2, #0
 	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
+
+	@ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
+	@ according to this formula:
+	@ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
+	@ Max DPLL_MULT = 18
+	@ DPLL_DIV = 1
+	@ ARMDIV = 1
+	@ => 74 nop-instructions
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@10
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@20
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@30
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@40
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@50
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@60
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop	@70
+	nop
+	nop
+	nop
+	nop	@74
 /*
  * omap1610_cpu_suspend()'s resume point.
  *
  * It will just start executing here, so we'll restore stuff from the
  * stack.
  */
-	@ re-enable Icache
-	mcr	p15, 0, r9, c1, c0, 0
-
-	@ reset the ARM_IDLECT1 and ARM_IDLECT2.
+	@ Restore the ARM_IDLECT1 and ARM_IDLECT2.
 	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 
@@ -444,7 +517,7 @@
 	str	r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 	str	r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 
-	@ restore regs and return
+	@ Restore regs and return
 	ldmfd	sp!, {r0 - r12, pc}
 
 ENTRY(omap1610_cpu_suspend_sz)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index cdbf4d7..a85fe60 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -51,8 +51,6 @@
 
 struct sys_timer omap_timer;
 
-#ifdef CONFIG_OMAP_MPU_TIMER
-
 /*
  * ---------------------------------------------------------------------------
  * MPU timer
@@ -222,195 +220,6 @@
 
 	return cycles_2_ns(ticks64);
 }
-#endif	/* CONFIG_OMAP_MPU_TIMER */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#error OMAP 32KHz timer does not currently work on 15XX!
-#endif
-
-/*
- * ---------------------------------------------------------------------------
- * 32KHz OS timer
- *
- * This currently works only on 16xx, as 1510 does not have the continuous
- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
- * on 1510 would be possible, but the timer would not be as accurate as
- * with the 32KHz synchronized timer.
- * ---------------------------------------------------------------------------
- */
-#define OMAP_32K_TIMER_BASE		0xfffb9000
-#define OMAP_32K_TIMER_CR		0x08
-#define OMAP_32K_TIMER_TVR		0x00
-#define OMAP_32K_TIMER_TCR		0x04
-
-#define OMAP_32K_TICKS_PER_HZ		(32768 / HZ)
-
-/*
- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
- * so with HZ = 100, TVR = 327.68.
- */
-#define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
-#define TIMER_32K_SYNCHRONIZED		0xfffbc410
-
-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
-				(((nr_jiffies) * (clock_rate)) / HZ)
-
-static inline void omap_32k_timer_write(int val, int reg)
-{
-	omap_writew(val, reg + OMAP_32K_TIMER_BASE);
-}
-
-static inline unsigned long omap_32k_timer_read(int reg)
-{
-	return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
-}
-
-/*
- * The 32KHz synchronized timer is an additional timer on 16xx.
- * It is always running.
- */
-static inline unsigned long omap_32k_sync_timer_read(void)
-{
-	return omap_readl(TIMER_32K_SYNCHRONIZED);
-}
-
-static inline void omap_32k_timer_start(unsigned long load_val)
-{
-	omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
-	omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
-}
-
-static inline void omap_32k_timer_stop(void)
-{
-	omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
-}
-
-/*
- * Rounds down to nearest usec. Note that this will overflow for larger values.
- */
-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
-{
-	return (ticks_32k * 5*5*5*5*5*5) >> 9;
-}
-
-/*
- * Rounds down to nearest nsec.
- */
-static inline unsigned long long
-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
-	return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
-}
-
-static unsigned long omap_32k_last_tick = 0;
-
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
-	unsigned long now = omap_32k_sync_timer_read();
-	return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
-	return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
-}
-
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
-					    struct pt_regs *regs)
-{
-	unsigned long flags;
-	unsigned long now;
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-	now = omap_32k_sync_timer_read();
-
-	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
-		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
-		timer_tick(regs);
-	}
-
-	/* Restart timer so we don't drift off due to modulo or dynamic tick.
-	 * By default we program the next timer to be continuous to avoid
-	 * latencies during high system load. During dynamic tick operation the
-	 * continuous timer can be overridden from pm_idle to be longer.
-	 */
-	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
-	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
-	/* No need to reprogram timer, just use the next interrupt */
-	return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
-	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-	return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
-	.enable		= omap_32k_timer_enable_dyn_tick,
-	.disable	= omap_32k_timer_disable_dyn_tick,
-	.reprogram	= omap_32k_timer_reprogram,
-	.handler	= omap_32k_timer_interrupt,
-};
-#endif	/* CONFIG_NO_IDLE_HZ */
-
-static struct irqaction omap_32k_timer_irq = {
-	.name		= "32KHz timer",
-	.flags		= SA_INTERRUPT | SA_TIMER,
-	.handler	= omap_32k_timer_interrupt,
-};
-
-static __init void omap_init_32k_timer(void)
-{
-
-#ifdef CONFIG_NO_IDLE_HZ
-	omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
-	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
-	omap_timer.offset  = omap_32k_timer_gettimeoffset;
-	omap_32k_last_tick = omap_32k_sync_timer_read();
-	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-}
-#endif	/* CONFIG_OMAP_32K_TIMER */
 
 /*
  * ---------------------------------------------------------------------------
@@ -419,13 +228,7 @@
  */
 static void __init omap_timer_init(void)
 {
-#if defined(CONFIG_OMAP_MPU_TIMER)
 	omap_init_mpu_timer();
-#elif defined(CONFIG_OMAP_32K_TIMER)
-	omap_init_32k_timer();
-#else
-#error No system timer selected in Kconfig!
-#endif
 }
 
 struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 5788809..537dd2e 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -20,3 +20,6 @@
 	bool "OMAP 2420 H4 board"
 	depends on ARCH_OMAP2 && ARCH_OMAP24XX
 
+config MACH_OMAP_APOLLON
+	bool "OMAP 2420 Apollon board"
+	depends on ARCH_OMAP2 && ARCH_OMAP24XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 4204116..111eaa6 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,11 +3,15 @@
 #
 
 # Common support
-obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o
 
 obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
 
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
+obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
 
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
new file mode 100644
index 0000000..6c6ba17
--- /dev/null
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -0,0 +1,285 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-apollon.c
+ *
+ * Copyright (C) 2005,2006 Samsung Electronics
+ * Author: Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Modified from mach-omap/omap2/board-h4.c
+ *
+ * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * 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/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include "prcm-regs.h"
+
+/* LED & Switch macros */
+#define LED0_GPIO13		13
+#define LED1_GPIO14		14
+#define LED2_GPIO15		15
+#define SW_ENTER_GPIO16		16
+#define SW_UP_GPIO17		17
+#define SW_DOWN_GPIO58		58
+
+static struct mtd_partition apollon_partitions[] = {
+	{
+		.name		= "X-Loader + U-Boot",
+		.offset		= 0,
+		.size		= SZ_128K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	{
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_128K,
+	},
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M,
+	},
+	{
+		.name		= "rootfs",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_16M,
+	},
+	{
+		.name		= "filesystem00",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_32M,
+	},
+	{
+		.name		= "filesystem01",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data apollon_flash_data = {
+	.parts		= apollon_partitions,
+	.nr_parts	= ARRAY_SIZE(apollon_partitions),
+};
+
+static struct resource apollon_flash_resource = {
+	.start		= APOLLON_CS0_BASE,
+	.end		= APOLLON_CS0_BASE + SZ_128K,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device apollon_onenand_device = {
+	.name		= "onenand",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &apollon_flash_data,
+	},
+	.num_resources	= ARRAY_SIZE(&apollon_flash_resource),
+	.resource	= &apollon_flash_resource,
+};
+
+static struct resource apollon_smc91x_resources[] = {
+	[0] = {
+		.start	= APOLLON_ETHR_START,		/* Physical */
+		.end	= APOLLON_ETHR_START + 0xf,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+		.end	= OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device apollon_smc91x_device = {
+	.name		= "smc91x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
+	.resource	= apollon_smc91x_resources,
+};
+
+static struct platform_device apollon_lcd_device = {
+	.name		= "apollon_lcd",
+	.id		= -1,
+};
+
+static struct platform_device *apollon_devices[] __initdata = {
+	&apollon_onenand_device,
+	&apollon_smc91x_device,
+	&apollon_lcd_device,
+};
+
+static inline void __init apollon_init_smc91x(void)
+{
+	/* Make sure CS1 timings are correct */
+	GPMC_CONFIG1_1 = 0x00011203;
+	GPMC_CONFIG2_1 = 0x001f1f01;
+	GPMC_CONFIG3_1 = 0x00080803;
+	GPMC_CONFIG4_1 = 0x1c091c09;
+	GPMC_CONFIG5_1 = 0x041f1f1f;
+	GPMC_CONFIG6_1 = 0x000004c4;
+	GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+	udelay(100);
+
+	omap_cfg_reg(W4__24XX_GPIO74);
+	if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
+		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+			APOLLON_ETHR_GPIO_IRQ);
+		return;
+	}
+	omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_apollon_init_irq(void)
+{
+	omap2_init_common_hw();
+	omap_init_irq();
+	omap_gpio_init();
+	apollon_init_smc91x();
+}
+
+static struct omap_uart_config apollon_uart_config __initdata = {
+	.enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
+};
+
+static struct omap_mmc_config apollon_mmc_config __initdata = {
+	.mmc [0] = {
+		.enabled 	= 0,
+		.wire4		= 0,
+		.wp_pin		= -1,
+		.power_pin	= -1,
+		.switch_pin	= -1,
+	},
+};
+
+static struct omap_lcd_config apollon_lcd_config __initdata = {
+	.ctrl_name	= "internal",
+};
+
+static struct omap_board_config_kernel apollon_config[] = {
+	{ OMAP_TAG_UART,	&apollon_uart_config },
+	{ OMAP_TAG_MMC,		&apollon_mmc_config },
+	{ OMAP_TAG_LCD,		&apollon_lcd_config },
+};
+
+static void __init apollon_led_init(void)
+{
+	/* LED0 - AA10 */
+	omap_cfg_reg(AA10_242X_GPIO13);
+	omap_request_gpio(LED0_GPIO13);
+	omap_set_gpio_direction(LED0_GPIO13, 0);
+	omap_set_gpio_dataout(LED0_GPIO13, 0);
+	/* LED1  - AA6 */
+	omap_cfg_reg(AA6_242X_GPIO14);
+	omap_request_gpio(LED1_GPIO14);
+	omap_set_gpio_direction(LED1_GPIO14, 0);
+	omap_set_gpio_dataout(LED1_GPIO14, 0);
+	/* LED2  - AA4 */
+	omap_cfg_reg(AA4_242X_GPIO15);
+	omap_request_gpio(LED2_GPIO15);
+	omap_set_gpio_direction(LED2_GPIO15, 0);
+	omap_set_gpio_dataout(LED2_GPIO15, 0);
+}
+
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+	static unsigned int led0, led1, led2;
+
+	if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
+		omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
+	else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
+		omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
+	else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
+		omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
+
+	return IRQ_HANDLED;
+}
+
+static void __init apollon_sw_init(void)
+{
+	/* Enter SW - Y11 */
+	omap_cfg_reg(Y11_242X_GPIO16);
+	omap_request_gpio(SW_ENTER_GPIO16);
+	omap_set_gpio_direction(SW_ENTER_GPIO16, 1);
+	/* Up SW - AA12 */
+	omap_cfg_reg(AA12_242X_GPIO17);
+	omap_request_gpio(SW_UP_GPIO17);
+	omap_set_gpio_direction(SW_UP_GPIO17, 1);
+	/* Down SW - AA8 */
+	omap_cfg_reg(AA8_242X_GPIO58);
+	omap_request_gpio(SW_DOWN_GPIO58);
+	omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
+
+	set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
+				SA_SHIRQ, "enter sw",
+				&apollon_sw_interrupt))
+		return;
+	set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
+				SA_SHIRQ, "up sw",
+				&apollon_sw_interrupt))
+		return;
+	set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+	if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
+				SA_SHIRQ, "down sw",
+				&apollon_sw_interrupt))
+		return;
+}
+
+static void __init omap_apollon_init(void)
+{
+	apollon_led_init();
+	apollon_sw_init();
+
+	/* REVISIT: where's the correct place */
+	omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+	/*
+ 	 * Make sure the serial ports are muxed on at this point.
+	 * You have to mux them off in device drivers later on
+	 * if not needed.
+	 */
+	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
+	omap_board_config = apollon_config;
+	omap_board_config_size = ARRAY_SIZE(apollon_config);
+	omap_serial_init();
+}
+
+static void __init omap_apollon_map_io(void)
+{
+	omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.phys_io	= 0x48000000,
+	.io_pg_offst	= ((0xd8000000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= omap_apollon_map_io,
+	.init_irq	= omap_apollon_init_irq,
+	.init_machine	= omap_apollon_init,
+	.timer		= &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a300d63..4933fce 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -17,6 +17,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
@@ -25,15 +27,57 @@
 #include <asm/mach/flash.h>
 
 #include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/irda.h>
 #include <asm/arch/board.h>
 #include <asm/arch/common.h>
-#include <asm/arch/prcm.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/arch/dma.h>
+#include "prcm-regs.h"
 
 #include <asm/io.h>
 #include <asm/delay.h>
 
+static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+static int h4_keymap[] = {
+	KEY(0, 0, KEY_LEFT),
+	KEY(0, 1, KEY_RIGHT),
+	KEY(0, 2, KEY_A),
+	KEY(0, 3, KEY_B),
+	KEY(0, 4, KEY_C),
+	KEY(1, 0, KEY_DOWN),
+	KEY(1, 1, KEY_UP),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_F),
+	KEY(1, 4, KEY_G),
+	KEY(2, 0, KEY_ENTER),
+	KEY(2, 1, KEY_I),
+	KEY(2, 2, KEY_J),
+	KEY(2, 3, KEY_K),
+	KEY(2, 4, KEY_3),
+	KEY(3, 0, KEY_M),
+	KEY(3, 1, KEY_N),
+	KEY(3, 2, KEY_O),
+	KEY(3, 3, KEY_P),
+	KEY(3, 4, KEY_Q),
+	KEY(4, 0, KEY_R),
+	KEY(4, 1, KEY_4),
+	KEY(4, 2, KEY_T),
+	KEY(4, 3, KEY_U),
+	KEY(4, 4, KEY_ENTER),
+	KEY(5, 0, KEY_V),
+	KEY(5, 1, KEY_W),
+	KEY(5, 2, KEY_L),
+	KEY(5, 3, KEY_S),
+	KEY(5, 4, KEY_ENTER),
+	0
+};
+
 static struct mtd_partition h4_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -108,9 +152,123 @@
 	.resource	= h4_smc91x_resources,
 };
 
+/* Select between the IrDA and aGPS module
+ */
+static int h4_select_irda(struct device *dev, int state)
+{
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x21))) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+		return err;
+	}
+
+	/* 'P6' enable/disable IRDA_TX and IRDA_RX */
+	if (state & IR_SEL) {	/* IrDa */
+		if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
+			printk(KERN_ERR "Error writing to I/O expander\n");
+			return err;
+		}
+	} else {
+		if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
+			printk(KERN_ERR "Error writing to I/O expander\n");
+			return err;
+		}
+	}
+	return err;
+}
+
+static void set_trans_mode(void *data)
+{
+	int *mode = data;
+	unsigned char expa;
+	int err = 0;
+
+	if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
+		printk(KERN_ERR "Error reading from I/O expander\n");
+	}
+
+	expa &= ~0x01;
+
+	if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+		expa |= 0x01;
+	}
+
+	if ((err = write_gpio_expa(expa, 0x20)) != 0) {
+		printk(KERN_ERR "Error writing to I/O expander\n");
+	}
+}
+
+static int h4_transceiver_mode(struct device *dev, int mode)
+{
+	struct omap_irda_config *irda_config = dev->platform_data;
+
+	cancel_delayed_work(&irda_config->gpio_expa);
+	PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+	schedule_work(&irda_config->gpio_expa);
+
+	return 0;
+}
+
+static struct omap_irda_config h4_irda_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+	.transceiver_mode	= h4_transceiver_mode,
+	.select_irda	 	= h4_select_irda,
+	.rx_channel		= OMAP24XX_DMA_UART3_RX,
+	.tx_channel		= OMAP24XX_DMA_UART3_TX,
+	.dest_start		= OMAP_UART3_BASE,
+	.src_start		= OMAP_UART3_BASE,
+	.tx_trigger		= OMAP24XX_DMA_UART3_TX,
+	.rx_trigger		= OMAP24XX_DMA_UART3_RX,
+};
+
+static struct resource h4_irda_resources[] = {
+	[0] = {
+		.start	= INT_24XX_UART3_IRQ,
+		.end	= INT_24XX_UART3_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device h4_irda_device = {
+	.name		= "omapirda",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &h4_irda_data,
+	},
+	.num_resources	= 1,
+	.resource	= h4_irda_resources,
+};
+
+static struct omap_kp_platform_data h4_kp_data = {
+	.rows		= 6,
+	.cols		= 7,
+	.keymap 	= h4_keymap,
+	.rep		= 1,
+	.row_gpios 	= row_gpios,
+	.col_gpios 	= col_gpios,
+};
+
+static struct platform_device h4_kp_device = {
+	.name		= "omap-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &h4_kp_data,
+	},
+};
+
+static struct platform_device h4_lcd_device = {
+	.name		= "lcd_h4",
+	.id		= -1,
+};
+
 static struct platform_device *h4_devices[] __initdata = {
 	&h4_smc91x_device,
 	&h4_flash_device,
+	&h4_irda_device,
+	&h4_kp_device,
+	&h4_lcd_device,
 };
 
 static inline void __init h4_init_smc91x(void)
@@ -157,7 +315,6 @@
 };
 
 static struct omap_lcd_config h4_lcd_config __initdata = {
-	.panel_name	= "h4",
 	.ctrl_name	= "internal",
 };
 
@@ -174,6 +331,19 @@
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+	omap_cfg_reg(K15_24XX_UART3_TX);
+	omap_cfg_reg(K14_24XX_UART3_RX);
+#endif
+
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+	if (omap_has_menelaus()) {
+		row_gpios[5] = 0;
+		col_gpios[2] = 15;
+		col_gpios[6] = 18;
+	}
+#endif
+
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap_board_config = h4_config;
 	omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180f675..72eb4bf 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -28,14 +28,14 @@
 
 #include <asm/arch/clock.h>
 #include <asm/arch/sram.h>
-#include <asm/arch/prcm.h>
 
+#include "prcm-regs.h"
+#include "memory.h"
 #include "clock.h"
 
 //#define DOWN_VARIABLE_DPLL 1			/* Experimental */
 
 static struct prcm_config *curr_prcm_set;
-static struct memory_timings mem_timings;
 static u32 curr_perf_level = PRCM_FULL_SPEED;
 
 /*-------------------------------------------------------------------------
@@ -54,11 +54,13 @@
 
 static u32 omap2_get_dpll_rate(struct clk * tclk)
 {
-	int dpll_clk, dpll_mult, dpll_div, amult;
+	long long dpll_clk;
+	int dpll_mult, dpll_div, amult;
 
 	dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff;	/* 10 bits */
 	dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f;	/* 4 bits */
-	dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+	dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+	do_div(dpll_clk, dpll_div + 1);
 	amult = CM_CLKSEL2_PLL & 0x3;
 	dpll_clk *= amult;
 
@@ -385,75 +387,23 @@
 		return 0;
 }
 
-static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
-{
-	unsigned long dll_cnt;
-	u32 fast_dll = 0;
-
-	mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
-
-	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
-	 * In the case of 2422, its ok to use CS1 instead of CS0.
-	 */
-
-#if 0	/* FIXME: Enable after 24xx cpu detection works */
-	ctype = get_cpu_type();
-	if (cpu_is_omap2422())
-		mem_timings.base_cs = 1;
-	else
-#endif
-		mem_timings.base_cs = 0;
-
-	if (mem_timings.m_type != M_DDR)
-		return;
-
-	/* With DDR we need to determine the low frequency DLL value */
-	if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
-		mem_timings.dll_mode = M_UNLOCK;
-	else
-		mem_timings.dll_mode = M_LOCK;
-
-	if (mem_timings.base_cs == 0) {
-		fast_dll = SDRC_DLLA_CTRL;
-		dll_cnt = SDRC_DLLA_STATUS & 0xff00;
-	} else {
-		fast_dll = SDRC_DLLB_CTRL;
-		dll_cnt = SDRC_DLLB_STATUS & 0xff00;
-	}
-	if (force_lock_to_unlock_mode) {
-		fast_dll &= ~0xff00;
-		fast_dll |= dll_cnt;		/* Current lock mode */
-	}
-	mem_timings.fast_dll_ctrl = fast_dll;
-
-	/* No disruptions, DDR will be offline & C-ABI not followed */
-	omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
-			    mem_timings.fast_dll_ctrl,
-			    mem_timings.base_cs,
-			    force_lock_to_unlock_mode);
-	mem_timings.slow_dll_ctrl &= 0xff00;	/* Keep lock value */
-
-	/* Turn status into unlock ctrl */
-	mem_timings.slow_dll_ctrl |=
-		((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
-
-	/* 90 degree phase for anything below 133Mhz */
-	mem_timings.slow_dll_ctrl |= (1 << 1);
-}
-
 static u32 omap2_reprogram_sdrc(u32 level, u32 force)
 {
+	u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
 	u32 prev = curr_perf_level, flags;
 
 	if ((curr_perf_level == level) && !force)
 		return prev;
 
+	m_type = omap2_memory_get_type();
+	slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+	fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+
 	if (level == PRCM_HALF_SPEED) {
 		local_irq_save(flags);
 		PRCM_VOLTSETUP = 0xffff;
 		omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
-					  mem_timings.slow_dll_ctrl,
-					  mem_timings.m_type);
+					  slow_dll_ctrl, m_type);
 		curr_perf_level = PRCM_HALF_SPEED;
 		local_irq_restore(flags);
 	}
@@ -461,8 +411,7 @@
 		local_irq_save(flags);
 		PRCM_VOLTSETUP = 0xffff;
 		omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
-					  mem_timings.fast_dll_ctrl,
-					  mem_timings.m_type);
+					  fast_dll_ctrl, m_type);
 		curr_perf_level = PRCM_FULL_SPEED;
 		local_irq_restore(flags);
 	}
@@ -650,7 +599,7 @@
 		case 13:				/* dss2 */
 			mask = 0x1; break;
 		case 25:				/* usb */
-			mask = 0xf; break;
+			mask = 0x7; break;
 		}
 	}
 
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6cab20b..6c78d47 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -33,20 +33,6 @@
 #define RATE_IN_242X	(1 << 0)
 #define RATE_IN_243X	(1 << 1)
 
-/* Memory timings */
-#define M_DDR		1
-#define M_LOCK_CTRL	(1 << 2)
-#define M_UNLOCK	0
-#define M_LOCK		1
-
-struct memory_timings {
-	u32 m_type;		/* ddr = 1, sdr = 0 */
-	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
-	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
-	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
-	u32 base_cs;		/* base chip select to use for calculations */
-};
-
 /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
  * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
  * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -731,6 +717,16 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+static struct clk emul_ck = {
+	.name		= "emul_ck",
+	.parent		= &func_54m_ck,
+	.flags		= CLOCK_IN_OMAP242X,
+	.enable_reg	= (void __iomem *)&PRCM_CLKEMUL_CTRL,
+	.enable_bit	= 0,
+	.recalc		= &omap2_propagate_rate,
+
+};
+
 /*
  * MPU clock domain
  *	Clocks:
@@ -1702,7 +1698,8 @@
 };
 
 static struct clk i2c2_ick = {
-	.name		= "i2c2_ick",
+	.name		= "i2c_ick",
+	.id		= 2,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1711,7 +1708,8 @@
 };
 
 static struct clk i2c2_fck = {
-	.name		= "i2c2_fck",
+	.name		= "i2c_fck",
+	.id		= 2,
 	.parent		= &func_12m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1729,7 +1727,8 @@
 };
 
 static struct clk i2c1_ick = {
-	.name		= "i2c1_ick",
+	.name		= "i2c_ick",
+	.id		= 1,
 	.parent		= &l4_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1738,7 +1737,8 @@
 };
 
 static struct clk i2c1_fck = {
-	.name		= "i2c1_fck",
+	.name		= "i2c_fck",
+	.id		= 1,
 	.parent		= &func_12m_ck,
 	.flags		= CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
 	.enable_reg	= (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1971,6 +1971,7 @@
 	&wdt1_osc_ck,
 	&sys_clkout,
 	&sys_clkout2,
+	&emul_ck,
 	/* mpu domain clocks */
 	&mpu_ck,
 	/* dsp domain clocks */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 7181edb..fb7f91d 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -25,10 +25,6 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
 
-extern void omap_nop_release(struct device *dev);
-
-/*-------------------------------------------------------------------------*/
-
 #if 	defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 
 #define OMAP2_I2C_BASE2		0x48072000
@@ -49,9 +45,6 @@
 static struct platform_device omap_i2c_device2 = {
         .name           = "i2c_omap",
         .id             = 2,
-        .dev = {
-                .release        = omap_nop_release,
-        },
 	.num_resources	= ARRAY_SIZE(i2c_resources2),
 	.resource	= i2c_resources2,
 };
@@ -74,6 +67,44 @@
 
 #endif
 
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP2_STI_BASE		IO_ADDRESS(0x48068000)
+#define OMAP2_STI_CHANNEL_BASE	0x54000000
+#define OMAP2_STI_IRQ		4
+
+static struct resource sti_resources[] = {
+	{
+		.start		= OMAP2_STI_BASE,
+		.end		= OMAP2_STI_BASE + 0x7ff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP2_STI_CHANNEL_BASE,
+		.end		= OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP2_STI_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device sti_device = {
+	.name		= "sti",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(sti_resources),
+	.resource	= sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+	platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -82,6 +113,7 @@
 	 * in alphabetical order so they're easier to sort through.
 	 */
 	omap_init_i2c();
+	omap_init_sti();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8ea67bf..7d57116 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,9 +16,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mach/map.h>
+#include <asm/tlb.h>
 #include <asm/io.h>
+
+#include <asm/mach/map.h>
+
 #include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
 
 extern void omap_sram_init(void);
 extern int omap2_clk_init(void);
@@ -43,11 +47,24 @@
 	}
 };
 
-void __init omap_map_common_io(void)
+void __init omap2_map_common_io(void)
 {
 	iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+
+	/* Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but we must also do it here because of the CPU
+	 * revision check below.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
 	omap2_check_revision();
 	omap_sram_init();
+	omapfb_reserve_mem();
+}
+
+void __init omap2_init_common_hw(void)
+{
 	omap2_mux_init();
 	omap2_clk_init();
 }
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
new file mode 100644
index 0000000..1d925d6
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.c
+ *
+ * Memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "prcm-regs.h"
+#include "memory.h"
+
+static struct memory_timings mem_timings;
+
+u32 omap2_memory_get_slow_dll_ctrl(void)
+{
+	return mem_timings.slow_dll_ctrl;
+}
+
+u32 omap2_memory_get_fast_dll_ctrl(void)
+{
+	return mem_timings.fast_dll_ctrl;
+}
+
+u32 omap2_memory_get_type(void)
+{
+	return mem_timings.m_type;
+}
+
+void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+	unsigned long dll_cnt;
+	u32 fast_dll = 0;
+
+	mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+	/* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+	 * In the case of 2422, its ok to use CS1 instead of CS0.
+	 */
+	if (cpu_is_omap2422())
+		mem_timings.base_cs = 1;
+	else
+		mem_timings.base_cs = 0;
+
+	if (mem_timings.m_type != M_DDR)
+		return;
+
+	/* With DDR we need to determine the low frequency DLL value */
+	if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+		mem_timings.dll_mode = M_UNLOCK;
+	else
+		mem_timings.dll_mode = M_LOCK;
+
+	if (mem_timings.base_cs == 0) {
+		fast_dll = SDRC_DLLA_CTRL;
+		dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+	} else {
+		fast_dll = SDRC_DLLB_CTRL;
+		dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+	}
+	if (force_lock_to_unlock_mode) {
+		fast_dll &= ~0xff00;
+		fast_dll |= dll_cnt;		/* Current lock mode */
+	}
+	/* set fast timings with DLL filter disabled */
+	mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8));
+
+	/* No disruptions, DDR will be offline & C-ABI not followed */
+	omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+			    mem_timings.fast_dll_ctrl,
+			    mem_timings.base_cs,
+			    force_lock_to_unlock_mode);
+	mem_timings.slow_dll_ctrl &= 0xff00;	/* Keep lock value */
+
+	/* Turn status into unlock ctrl */
+	mem_timings.slow_dll_ctrl |=
+		((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+	/* 90 degree phase for anything below 133Mhz + disable DLL filter */
+	mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
+}
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
new file mode 100644
index 0000000..d212eea
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.h
+ *
+ * Interface for memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.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.
+ */
+
+/* Memory timings */
+#define M_DDR		1
+#define M_LOCK_CTRL	(1 << 2)
+#define M_UNLOCK	0
+#define M_LOCK		1
+
+struct memory_timings {
+	u32 m_type;		/* ddr = 1, sdr = 0 */
+	u32 dll_mode;		/* use lock mode = 1, unlock mode = 0 */
+	u32 slow_dll_ctrl;	/* unlock mode, dll value for slow speed */
+	u32 fast_dll_ctrl;	/* unlock mode, dll value for fast speed */
+	u32 base_cs;		/* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ea46548..1197dc3 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -50,9 +50,54 @@
 /* Menelaus interrupt */
 MUX_CFG_24XX("W19_24XX_SYS_NIRQ",	0x12c,	0,	1,	1,	1)
 
+/* 24xx clocks */
+MUX_CFG_24XX("W14_24XX_SYS_CLKOUT",	0x137,	0,	1,	1,	1)
+
+/* 24xx McBSP */
+MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX",	0x124,	1,	1,	0,	1)
+MUX_CFG_24XX("R14_24XX_MCBSP2_FSX",	0x125,	1,	1,	0,	1)
+MUX_CFG_24XX("W15_24XX_MCBSP2_DR",	0x126,	1,	1,	0,	1)
+MUX_CFG_24XX("V15_24XX_MCBSP2_DX",	0x127,	1,	1,	0,	1)
+
 /* 24xx GPIO */
+MUX_CFG_24XX("M21_242X_GPIO11",	 0x0c9,  3,      1,      1,      1)
+MUX_CFG_24XX("AA10_242X_GPIO13",	0x0e5,  3,      0,      0,      1)
+MUX_CFG_24XX("AA6_242X_GPIO14",	 0x0e6,  3,      0,      0,      1)
+MUX_CFG_24XX("AA4_242X_GPIO15",	 0x0e7,  3,      0,      0,      1)
+MUX_CFG_24XX("Y11_242X_GPIO16",	 0x0e8,  3,      0,      0,      1)
+MUX_CFG_24XX("AA12_242X_GPIO17",	0x0e9,  3,      0,      0,      1)
+MUX_CFG_24XX("AA8_242X_GPIO58",	 0x0ea,  3,      0,      0,      1)
 MUX_CFG_24XX("Y20_24XX_GPIO60",		0x12c,	3,	0,	0,	1)
+MUX_CFG_24XX("W4__24XX_GPIO74",	 0x0f2,  3,      0,      0,      1)
 MUX_CFG_24XX("M15_24XX_GPIO92",		0x10a,	3,	0,	0,	1)
+MUX_CFG_24XX("V14_24XX_GPIO117",	0x128,	3,	1,	0,	1)
+
+/* TSC IRQ */
+MUX_CFG_24XX("P20_24XX_TSC_IRQ",	0x108,	0,	0,	0,	1)
+
+/* UART3  */
+MUX_CFG_24XX("K15_24XX_UART3_TX",	0x118,	0,	0,	0,	1)
+MUX_CFG_24XX("K14_24XX_UART3_RX",	0x119,	0,	0,	0,	1)
+
+/* Keypad GPIO*/
+MUX_CFG_24XX("T19_24XX_KBR0",		0x106,	3,	1,	1,	1)
+MUX_CFG_24XX("R19_24XX_KBR1",		0x107,	3,	1,	1,	1)
+MUX_CFG_24XX("V18_24XX_KBR2",		0x139,	3,	1,	1,	1)
+MUX_CFG_24XX("M21_24XX_KBR3",		0xc9,	3,	1,	1,	1)
+MUX_CFG_24XX("E5__24XX_KBR4",		0x138,	3,	1,	1,	1)
+MUX_CFG_24XX("M18_24XX_KBR5",		0x10e,	3,	1,	1,	1)
+MUX_CFG_24XX("R20_24XX_KBC0",		0x108,	3,	0,	0,	1)
+MUX_CFG_24XX("M14_24XX_KBC1",		0x109,	3,	0,	0,	1)
+MUX_CFG_24XX("H19_24XX_KBC2",		0x114,	3,	0,	0,	1)
+MUX_CFG_24XX("V17_24XX_KBC3",		0x135,	3,	0,	0,	1)
+MUX_CFG_24XX("P21_24XX_KBC4",		0xca,	3,	0,	0,	1)
+MUX_CFG_24XX("L14_24XX_KBC5",		0x10f,	3,	0,	0,	1)
+MUX_CFG_24XX("N19_24XX_KBC6",		0x110,	3,	0,	0,	1)
+
+/* 24xx Menelaus Keypad GPIO */
+MUX_CFG_24XX("B3__24XX_KBR5",		0x30,	3,	1,	1,	1)
+MUX_CFG_24XX("AA4_24XX_KBC2",		0xe7,	3,	0,	0,	1)
+MUX_CFG_24XX("B13_24XX_KBC6",		0x110,	3,	0,	0,	1)
 
 };
 
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 0000000..562168f
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+	local_irq_disable();
+	local_fiq_disable();
+	if (need_resched()) {
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+
+	/*
+	 * Since an interrupt may set up a timer, we don't want to
+	 * reprogram the hardware timer with interrupts enabled.
+	 * Re-enable interrupts only after returning from idle.
+	 */
+	timer_dyn_reprogram();
+
+	omap2_sram_idle();
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+	int error = 0;
+
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		/* FIXME: Add suspend */
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+	pm_idle = saved_idle;
+	return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+	.pm_disk_mode	= 0,
+	.prepare	= omap2_pm_prepare,
+	.enter		= omap2_pm_enter,
+	.finish		= omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+	printk("Power Management for TI OMAP.\n");
+
+	vclk = clk_get(NULL, "virt_prcm_set");
+	if (IS_ERR(vclk)) {
+		printk(KERN_ERR "Could not get PM vclk\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+	omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+					 omap24xx_idle_loop_suspend_sz);
+
+	omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+					    omap24xx_cpu_suspend_sz);
+
+	pm_set_ops(&omap_pm_ops);
+	pm_idle = omap2_pm_idle;
+
+	return 0;
+}
+
+__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h
similarity index 69%
rename from arch/arm/mach-omap2/prcm.h
rename to arch/arm/mach-omap2/prcm-regs.h
index 2eb89b9..22ac7be 100644
--- a/arch/arm/mach-omap2/prcm.h
+++ b/arch/arm/mach-omap2/prcm-regs.h
@@ -1,5 +1,7 @@
 /*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/arch/arm/mach-omap2/prcm-reg.h
+ *
+ * OMAP24XX Power Reset and Clock Management (PRCM) registers
  *
  * Copyright (C) 2005 Texas Instruments, Inc.
  *
@@ -18,8 +20,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_H
 
 /* SET_PERFORMANCE_LEVEL PARAMETERS */
 #define PRCM_HALF_SPEED 1
@@ -159,54 +161,63 @@
 #define CM_FCLKEN_MDM		PRCM_REG32(0xC00)
 #define CM_ICLKEN_MDM		PRCM_REG32(0xC10)
 #define CM_IDLEST_MDM		PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM		PRCM_REG32(0xC30)
 #define CM_CLKSEL_MDM		PRCM_REG32(0xC40)
+#define CM_CLKSTCTRL_MDM	PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM		PRCM_REG32(0xC50)
+#define RM_RSTST_MDM		PRCM_REG32(0xC58)
+#define PM_WKEN_MDM		PRCM_REG32(0xCA0)
+#define PM_WKST_MDM		PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM		PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM		PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM		PRCM_REG32(0xCE4)
 
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE		(OMAP24XX_L4_IO_BASE+0x50000)
+#define OMAP24XX_L4_IO_BASE	0x48000000
+
+#define DISP_BASE		(OMAP24XX_L4_IO_BASE + 0x50000)
 #define DISP_REG32(offset)	__REG32(DISP_BASE + (offset))
 
-#define GPMC_BASE		(OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset)	__REG32(GPMC_BASE + (offset))
+#define OMAP24XX_GPMC_BASE	(L3_24XX_BASE + 0xa000)
+#define GPMC_REG32(offset)	__REG32(OMAP24XX_GPMC_BASE + (offset))
 
-#define GPT1_BASE		(OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE		(0x48028000)
 #define GPT1_REG32(offset)	__REG32(GPT1_BASE + (offset))
 
 /* Misc sysconfig */
 #define DISPC_SYSCONFIG		DISP_REG32(0x410)
-#define SPI_BASE		(OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE		(OMAP24XX_L4_IO_BASE + 0x98000)
 #define MCSPI1_SYSCONFIG	__REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE+0x2000 + 0x10)
+#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
 
-//#define DSP_MMU_SYSCONFIG	0x5A000010
-#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG	0x5D000010
-//#define DSP_DMA_SYSCONFIG	0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE+0x602C)
+#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE + 0x602C)
 #define GPMC_SYSCONFIG		GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG		0x5C060010
-#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG		__REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG	0x67FFFE10
+#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE	(L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG		__REG32(DISP_BASE + 0x8010)
 
 /* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE+0x8A000)
+#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE + 0x8A000)
 
+/* FIXME: Move these to timer code */
 #define GPTIMER1_SYSCONFIG	GPT1_REG32(0x010)
 #define GPTIMER2_SYSCONFIG	__REG32(OMAP24XX_GPT2 + 0x10)
 #define GPTIMER3_SYSCONFIG	__REG32(OMAP24XX_GPT3 + 0x10)
@@ -220,12 +231,18 @@
 #define GPTIMER11_SYSCONFIG	__REG32(OMAP24XX_GPT11 + 0x10)
 #define GPTIMER12_SYSCONFIG	__REG32(OMAP24XX_GPT12 + 0x10)
 
-#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE	0x48018000
+#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
 
-#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4)+0x10))
+#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4) + 0x10))
+
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG		__REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
 
 /* GP TIMER 1 */
 #define GPTIMER1_TISTAT		GPT1_REG32(0x014)
@@ -243,15 +260,15 @@
 #define GPTIMER1_TCAR2		GPT1_REG32(0x044)
 
 /* rkw -- base fix up please... */
-#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE + 0x78018)
 
 /* SDRC */
-#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE + 0x084)
 
 /* GPIO 1 */
 #define GPIO1_BASE		GPIOX_BASE(1)
@@ -278,6 +295,8 @@
 #define GPIO2_DATAIN		GPIO2_REG32(0x038)
 #define GPIO2_OE		GPIO2_REG32(0x034)
 #define GPIO2_DATAOUT		GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE	GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME	GPIO2_REG32(0x054)
 
 /* GPIO 3 */
 #define GPIO3_BASE		GPIOX_BASE(3)
@@ -294,6 +313,8 @@
 #define GPIO3_DATAOUT		GPIO3_REG32(0x03C)
 #define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
 #define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
 
 /* GPIO 4 */
 #define GPIO4_BASE		GPIOX_BASE(4)
@@ -311,10 +332,26 @@
 #define GPIO4_DEBOUNCENABLE	GPIO4_REG32(0x050)
 #define GPIO4_DEBOUNCINGTIME	GPIO4_REG32(0x054)
 
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset)	__REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1	GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1	GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2	GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2	GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE	GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT	GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT	GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN		GPIO5_REG32(0x038)
+#define GPIO5_OE		GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT		GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE	GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME	GPIO5_REG32(0x054)
+#endif
 
 /* IO CONFIG */
-#define CONTROL_BASE		(OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset)	__REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE		(L4_24XX_BASE)
+#define CONTROL_REG32(offset)		__REG32(OMAP24XX_CTRL_BASE + (offset))
 
 #define CONTROL_PADCONF_SPI1_NCS2	CONTROL_REG32(0x104)
 #define CONTROL_PADCONF_SYS_XTALOUT	CONTROL_REG32(0x134)
@@ -322,15 +359,18 @@
 #define CONTROL_PADCONF_MCBSP1_DX	CONTROL_REG32(0x10C)
 #define CONTROL_PADCONF_GPMC_NCS4	CONTROL_REG32(0x090)
 #define CONTROL_PADCONF_DSS_D5		CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)	/* 2420 */
 #define CONTROL_PADCONF_DSS_D13		CONTROL_REG32(0x0C0)
 #define CONTROL_PADCONF_DSS_VSYNC	CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0	CONTROL_REG32(0x0BC)	/* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX	CONTROL_REG32(0x108)	/* 2430 */
 
 /* CONTROL */
 #define CONTROL_DEVCONF		CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1	CONTROL_REG32(0x2E8)
 
 /* INTERRUPT CONTROLLER */
-#define INTC_BASE		(OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE		((L4_24XX_BASE) + 0xfe000)
 #define INTC_REG32(offset)	__REG32(INTC_BASE + (offset))
 
 #define INTC1_U_BASE		INTC_REG32(0x000)
@@ -348,10 +388,12 @@
 #define INTC_ISR_CLEAR2		INTC_REG32(0x0D4)
 #define INTC_SIR_IRQ		INTC_REG32(0x040)
 #define INTC_CONTROL		INTC_REG32(0x048)
-#define INTC_ILR11		INTC_REG32(0x12C)
+#define INTC_ILR11		INTC_REG32(0x12C)	/* PRCM on MPU PIC */
+#define INTC_ILR30		INTC_REG32(0x178)
+#define INTC_ILR31		INTC_REG32(0x17C)
 #define INTC_ILR32		INTC_REG32(0x180)
-#define INTC_ILR37		INTC_REG32(0x194)
-#define INTC_SYSCONFIG		INTC_REG32(0x010)
+#define INTC_ILR37		INTC_REG32(0x194)	/* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG		INTC_REG32(0x010)	/* GPT1 on MPU PIC */
 
 /* RAM FIREWALL */
 #define RAMFW_BASE		(0x68005000)
@@ -373,6 +415,24 @@
 #define GPMC_CONFIG6_0		GPMC_REG32(0x074)
 #define GPMC_CONFIG7_0		GPMC_REG32(0x078)
 
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1		GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1		GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1		GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1		GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1		GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1		GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1		GPMC_REG32(0x0a8)
+
+/* GPMC CS3 */
+#define GPMC_CONFIG1_3		GPMC_REG32(0x0F0)
+#define GPMC_CONFIG2_3		GPMC_REG32(0x0F4)
+#define GPMC_CONFIG3_3		GPMC_REG32(0x0F8)
+#define GPMC_CONFIG4_3		GPMC_REG32(0x0FC)
+#define GPMC_CONFIG5_3		GPMC_REG32(0x100)
+#define GPMC_CONFIG6_3		GPMC_REG32(0x104)
+#define GPMC_CONFIG7_3		GPMC_REG32(0x108)
+
 /* DSS */
 #define DSS_CONTROL		DISP_REG32(0x040)
 #define DISPC_CONTROL		DISP_REG32(0x440)
@@ -405,11 +465,15 @@
 #define DISPC_DATA_CYCLE2	DISP_REG32(0x5D8)
 #define DISPC_DATA_CYCLE3	DISP_REG32(0x5DC)
 
-/* Wake up define for board */
-#define GPIO97			(1 << 1)
-#define GPIO88			(1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL		__REG8(0x480AC001)
+#define USBOTG_POWER		__REG32(0x480AC000)
 
-#endif /* __ASSEMBLER__ */
+/* HS MMC */
+#define MMCHS1_SYSCONFIG	__REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG	__REG32(0x480b4010)
+
+#endif	/* __ASSEMBLER__ */
 
 #endif
 
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
new file mode 100644
index 0000000..8893479
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm.c
+ *
+ * OMAP 24xx Power Reset and Clock Management (PRCM) functions
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include "prcm-regs.h"
+
+u32 omap_prcm_get_reset_sources(void)
+{
+	return RM_RSTST_WKUP & 0x7f;
+}
+EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+/* Resets clock rates and reboots the system. Only called from system.h */
+void omap_prcm_arch_reset(char mode)
+{
+	u32 rate;
+	struct clk *vclk, *sclk;
+
+	vclk = clk_get(NULL, "virt_prcm_set");
+	sclk = clk_get(NULL, "sys_ck");
+	rate = clk_get_rate(sclk);
+	clk_set_rate(vclk, rate);	/* go to bypass for OMAP limitation */
+	RM_RSTCTRL_WKUP |= 2;
+}
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 0000000..00299cb
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V		IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define	A_SDRC_POWER_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V		(0xC0000000)
+#define A_SDRC_MANUAL_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+	.text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+	stmfd	sp!, {r0, lr}		@ save registers on stack
+	mov	r0, #0			@ clear for mcr setup
+	mcr	p15, 0, r0, c7, c0, 4	@ wait for interrupt
+	ldmfd	sp!, {r0, pc}		@ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+	.word	. - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 :	DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ *	2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ *	2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't.  We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL.  Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF.	It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
+	mov	r3, #0x0		@ clear for mrc call
+	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, hope SDR/DDR finished
+	nop
+	nop
+	ldr	r3, A_SDRC_POWER	@ addr of sdrc power
+	ldr	r4, [r3]		@ value of sdrc power
+	orr	r4, r4, #0x40		@ enable self refresh on idle req
+	mov	r5, #0x2000		@ set delay (DPLL relock + DLL relock)
+	str	r4, [r3]		@ make it so
+	mov	r2, #0
+	nop
+	mcr	p15, 0, r2, c7, c0, 4	@ wait for interrupt
+	nop
+loop:
+	subs	r5, r5, #0x1		@ awake, wait just a bit
+	bne	loop
+
+	/* The DPLL has on before we take the DDR out of self refresh */
+	bic	r4, r4, #0x40		@ now clear self refresh bit.
+	str	r4, [r3]		@ put vlaue back.
+	ldr	r4, A_SDRC0		@ make a clock happen
+	ldr	r4, [r4]
+	nop				@ start auto refresh only after clk ok
+	movs	r0, r0			@ see if DDR or SDR
+	ldrne	r1, A_SDRC_DLLA_CTRL_S	@ get addr of DLL ctrl
+	strne	r0, [r1]		@ rewrite DLLA to force DLL reload
+	addne	r1, r1, #0x8		@ move to DLLB
+	strne	r0, [r1]		@ rewrite DLLB to force DLL reload
+
+	mov	r5, #0x1000
+loop2:
+	subs	r5, r5, #0x1
+	bne	loop2
+	/* resume*/
+	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return
+
+A_SDRC_POWER:
+	.word A_SDRC_POWER_V
+A_SDRC0:
+	.word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+	.word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+	.word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+	.word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+	.word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+	.word	. - omap24xx_cpu_suspend
+
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e2..d261e4f 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
 /*
- * linux/arch/arm/mach-omap1/sram.S
+ * linux/arch/arm/mach-omap2/sram.S
  *
  * Omap2 specific functions that need to be run in internal SRAM
  *
@@ -28,7 +28,7 @@
 #include <asm/arch/io.h>
 #include <asm/hardware.h>
 
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
 
 #define TIMER_32KSYNCT_CR_V	IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
 
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index b371d72..8a25a1c 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -196,12 +196,9 @@
 	int ret;
 
 	/* Chip Select - Disable All */
-	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*/
+	pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
+        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+        pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
 
 	ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index b45560a..a042473 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -307,6 +307,10 @@
 		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 = (32*1024*1024);
 }
 
 MACHINE_START(POODLE, "SHARP Poodle")
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index ed07c41..ce7d810 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -50,9 +50,15 @@
 
 	  <http://zoo.weinigel.se/n30>.
 
+config MACH_SMDK
+	bool
+	help
+	  Common machine code for SMDK2410 and SMDK2440
+
 config ARCH_SMDK2410
 	bool "SMDK2410/A9M2410"
 	select CPU_S3C2410
+	select MACH_SMDK
 	help
 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
            <http://www.fsforth.de>
@@ -60,6 +66,7 @@
 config ARCH_S3C2440
 	bool "SMDK2440"
 	select CPU_S3C2440
+	select MACH_SMDK
 	help
 	  Say Y here if you are using the SMDK2440.
 
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1b3b476..3e5712d 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -48,3 +48,5 @@
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
 obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+
+obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
\ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index fec02c9..6de713a 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -249,7 +249,7 @@
 
 	/* if we started the UPLL, then allow to settle */
 
-	if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF))
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
 		udelay(200);
 
 	return 0;
@@ -367,6 +367,8 @@
 		source = S3C2410_MISCCR_CLK0_UPLL;
 	else if (parent == &clk_f)
 		source = S3C2410_MISCCR_CLK0_FCLK;
+	else if (parent == &clk_h)
+		source = S3C2410_MISCCR_CLK0_HCLK;
 	else if (parent == &clk_p)
 		source = S3C2410_MISCCR_CLK0_PCLK;
 	else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
@@ -376,6 +378,8 @@
 	else
 		return -EINVAL;
 
+	clk->parent = parent;
+
 	if (clk == &s3c24xx_dclk0)
 		mask = S3C2410_MISCCR_CLK0_MASK;
 	else {
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
new file mode 100644
index 0000000..c940890
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -0,0 +1,135 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include "common-smdk.h"
+#include "devs.h"
+#include "pm.h"
+
+/* NAND parititon from 2.4.18-swl5 */
+
+static struct mtd_partition smdk_default_nand_part[] = {
+	[0] = {
+		.name	= "Boot Agent",
+		.size	= SZ_16K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "S3C2410 flash partition 1",
+		.offset = 0,
+		.size	= SZ_2M,
+	},
+	[2] = {
+		.name	= "S3C2410 flash partition 2",
+		.offset = SZ_4M,
+		.size	= SZ_4M,
+	},
+	[3] = {
+		.name	= "S3C2410 flash partition 3",
+		.offset	= SZ_8M,
+		.size	= SZ_2M,
+	},
+	[4] = {
+		.name	= "S3C2410 flash partition 4",
+		.offset = SZ_1M * 10,
+		.size	= SZ_4M,
+	},
+	[5] = {
+		.name	= "S3C2410 flash partition 5",
+		.offset	= SZ_1M * 14,
+		.size	= SZ_1M * 10,
+	},
+	[6] = {
+		.name	= "S3C2410 flash partition 6",
+		.offset	= SZ_1M * 24,
+		.size	= SZ_1M * 24,
+	},
+	[7] = {
+		.name	= "S3C2410 flash partition 7",
+		.offset = SZ_1M * 48,
+		.size	= SZ_16M,
+	}
+};
+
+static struct s3c2410_nand_set smdk_nand_sets[] = {
+	[0] = {
+		.name		= "NAND",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(smdk_default_nand_part),
+		.partitions	= smdk_default_nand_part,
+	},
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand smdk_nand_info = {
+	.tacls		= 20,
+	.twrph0		= 60,
+	.twrph1		= 20,
+	.nr_sets	= ARRAY_SIZE(smdk_nand_sets),
+	.sets		= smdk_nand_sets,
+};
+
+/* devices we initialise */
+
+static struct platform_device __initdata *smdk_devs[] = {
+	&s3c_device_nand,
+};
+
+void __init smdk_machine_init(void)
+{
+	/* Configure the LEDs (even if we have no LED support)*/
+
+	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+	s3c2410_gpio_setpin(S3C2410_GPF4, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF5, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF6, 1);
+	s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+
+	s3c_device_nand.dev.platform_data = &smdk_nand_info;
+
+	platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+	s3c2410_pm_init();
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
new file mode 100644
index 0000000..0e3a3be
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * 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.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 3e327b8..cc97fbf 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -232,8 +232,8 @@
 
 static struct s3c2410_platform_nand anubis_nand_info = {
 	.tacls		= 25,
-	.twrph0		= 80,
-	.twrph1		= 80,
+	.twrph0		= 55,
+	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
 	.sets		= anubis_nand_sets,
 	.select_chip	= anubis_nand_select,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 0260ed5..306afc1 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -32,6 +32,11 @@
 #include <linux/serial_core.h>
 #include <linux/serial.h>
 
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -46,6 +51,7 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-lcd.h>
 
+#include <asm/arch/nand.h>
 #include <asm/arch/fb.h>
 
 #include "clock.h"
@@ -170,12 +176,39 @@
 	},
 };
 
+static struct mtd_partition rx3715_nand_part[] = {
+	[0] = {
+		.name		= "Whole Flash",
+		.offset		= 0,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct s3c2410_nand_set rx3715_nand_sets[] = {
+	[0] = {
+		.name		= "Internal",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(rx3715_nand_part),
+		.partitions	= rx3715_nand_part,
+	},
+};
+
+static struct s3c2410_platform_nand rx3715_nand_info = {
+	.tacls		= 25,
+	.twrph0		= 50,
+	.twrph1		= 15,
+	.nr_sets	= ARRAY_SIZE(rx3715_nand_sets),
+	.sets		= rx3715_nand_sets,
+};
+
 static struct platform_device *rx3715_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
+	&s3c_device_nand,
 };
 
 static struct s3c24xx_board rx3715_board __initdata = {
@@ -185,6 +218,8 @@
 
 static void __init rx3715_map_io(void)
 {
+	s3c_device_nand.dev.platform_data = &rx3715_nand_info;
+
 	s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
 	s3c24xx_init_clocks(16934000);
 	s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 1e76e1f..2db932d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -28,7 +28,8 @@
  * Ben Dooks <ben@simtec.co.uk>
  *
  * 10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD  Added static to non-exported items
+ * 20-Sep-2005 BJD   Added static to non-exported items
+ * 01-Apr-2006 BJD   Moved init code to common smdk
  *
  ***********************************************************************/
 
@@ -54,6 +55,8 @@
 #include "devs.h"
 #include "cpu.h"
 
+#include "common-smdk.h"
+
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
 };
@@ -107,11 +110,6 @@
 	s3c24xx_set_board(&smdk2410_board);
 }
 
-static void __init smdk2410_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
 	/* Maintainer: Jonas Dietsche */
@@ -119,7 +117,8 @@
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.map_io		= smdk2410_map_io,
-	.init_irq	= smdk2410_init_irq,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= smdk_machine_init,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
 
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index f431572..5fffd1d 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -53,7 +53,8 @@
 #include "clock.h"
 #include "devs.h"
 #include "cpu.h"
-#include "pm.h"
+
+#include "common-smdk.h"
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
@@ -197,21 +198,9 @@
 
 static void __init smdk2440_machine_init(void)
 {
-	/* Configure the LEDs (even if we have no LED support)*/
-
-	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
-	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
-
-	s3c2410_gpio_setpin(S3C2410_GPF4, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF5, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF6, 0);
-	s3c2410_gpio_setpin(S3C2410_GPF7, 0);
-
 	s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
 
-	s3c2410_pm_init();
+	smdk_machine_init();
 }
 
 MACHINE_START(S3C2440, "SMDK2440")
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index 57a1597..d7a30ed 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -139,7 +139,7 @@
 
 		clkdivn = __raw_readl(S3C2410_CLKDIVN);
 		clkdivn |= S3C2440_CLKDIVN_UCLK;
-		__raw_writel(camdivn, S3C2410_CLKDIVN);
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
 
 		mutex_unlock(&clocks_mutex);
 	}
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 1024540..676b5c5 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -11,7 +11,8 @@
  * published by the Free Software Foundation.
  *
  * ChangeLog:
- *  03-06-2004 John Lenz <jelenz@wisc.edu>
+ *  2006 Pavel Machek <pavel@suse.cz>
+ *  03-06-2004 John Lenz <lenz@cs.wisc.edu>
  *  06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
  *  04-16-2001 Lineo Japan,Inc. ...
  */
@@ -87,12 +88,75 @@
 	.sclk_rate      = 11981000,
 };
 
+#ifdef CONFIG_SHARP_LOCOMO
+/*
+ * low-level UART features.
+ */
+static struct locomo_dev *uart_dev = NULL;
+
+static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ 	if (!uart_dev) return;
+
+ 	if (mctrl & TIOCM_RTS)
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+ 	else
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+
+ 	if (mctrl & TIOCM_DTR)
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+ 	else
+		locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+}
+
+static u_int collie_uart_get_mctrl(struct uart_port *port)
+{
+	int ret = TIOCM_CD;
+	unsigned int r;
+	if (!uart_dev) return ret;
+
+	r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+	if (r & LOCOMO_GPIO_CTS)
+		ret |= TIOCM_CTS;
+	if (r & LOCOMO_GPIO_DSR)
+		ret |= TIOCM_DSR;
+
+	return ret;
+}
 
 static struct sa1100_port_fns collie_port_fns __initdata = {
 	.set_mctrl	= collie_uart_set_mctrl,
 	.get_mctrl	= collie_uart_get_mctrl,
 };
 
+static int collie_uart_probe(struct locomo_dev *dev)
+{
+	uart_dev = dev;
+	return 0;
+}
+
+static int collie_uart_remove(struct locomo_dev *dev)
+{
+	uart_dev = NULL;
+	return 0;
+}
+
+static struct locomo_driver collie_uart_driver = {
+	.drv = {
+		.name = "collie_uart",
+	},
+	.devid	= LOCOMO_DEVID_UART,
+	.probe	= collie_uart_probe,
+	.remove	= collie_uart_remove,
+};
+
+static int __init collie_uart_init(void) {
+	return locomo_driver_register(&collie_uart_driver);
+}
+device_initcall(collie_uart_init);
+
+#endif
+
 
 static struct resource locomo_resources[] = {
 	[0] = {
@@ -218,6 +282,12 @@
 {
 	sa1100_map_io();
 	iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+
+#ifdef CONFIG_SHARP_LOCOMO
+	sa1100_register_uart_fns(&collie_port_fns);
+#endif
+	sa1100_register_uart(0, 3);
+	sa1100_register_uart(1, 1);
 }
 
 MACHINE_START(COLLIE, "Sharp-Collie")
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 5c4055b..54e3c5b 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -10,7 +10,7 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/hardware.h>
+#include <asm/memory.h>
 #include <asm/page.h>
 #include "proc-macros.S"
 
@@ -46,6 +46,11 @@
  */
 #define CACHE_DLIMIT	(CACHE_DSIZE * 4)
 
+	.data
+flush_base:
+	.long	FLUSH_BASE
+	.text
+
 /*
  *	flush_user_cache_all()
  *
@@ -63,11 +68,21 @@
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 __flush_whole_cache:
-	mov	r0, #FLUSH_BASE
-	add	r1, r0, #CACHE_DSIZE
-1:	ldr	r2, [r0], #32
-	cmp	r0, r1
+	ldr	r3, =flush_base
+	ldr	r1, [r3, #0]
+	eor	r1, r1, #CACHE_DSIZE
+	str	r1, [r3, #0]
+	add	r2, r1, #CACHE_DSIZE
+1:	ldr	r3, [r1], #32
+	cmp	r1, r2
 	blo	1b
+#ifdef FLUSH_BASE_MINICACHE
+	add	r2, r2, #FLUSH_BASE_MINICACHE - FLUSH_BASE
+	sub	r1, r2, #512			@ only 512 bytes
+1:	ldr	r3, [r1], #32
+	cmp	r1, r2
+	blo	1b
+#endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain write buffer
 	mov	pc, lr
 
@@ -82,6 +97,7 @@
  *	- flags	- vma_area_struct flags describing address space
  */
 ENTRY(v4wb_flush_user_cache_range)
+	mov	ip, #0
 	sub	r3, r1, r0			@ calculate total size
 	tst	r2, #VM_EXEC			@ executable region?
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd..50e6b6b 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 
+#include <asm/memory.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/sizes.h>
@@ -272,6 +273,17 @@
 void *
 dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
+	if (arch_is_coherent()) {
+		void *virt;
+
+		virt = kmalloc(size, gfp);
+		if (!virt)
+			return NULL;
+		*handle =  virt_to_dma(dev, virt);
+
+		return virt;
+	}
+
 	return __dma_alloc(dev, size, handle, gfp,
 			   pgprot_noncached(pgprot_kernel));
 }
@@ -350,6 +362,11 @@
 
 	WARN_ON(irqs_disabled());
 
+	if (arch_is_coherent()) {
+		kfree(cpu_addr);
+		return;
+	}
+
 	size = PAGE_ALIGN(size);
 
 	spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 8827912..9ea1f87 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -20,6 +20,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/setup.h>
+#include <asm/sizes.h>
 #include <asm/tlb.h>
 
 #include <asm/mach/arch.h>
@@ -455,14 +456,14 @@
 #ifdef FLUSH_BASE
 	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
 	map.virtual = FLUSH_BASE;
-	map.length = PGDIR_SIZE;
+	map.length = SZ_1M;
 	map.type = MT_CACHECLEAN;
 	create_mapping(&map);
 #endif
 #ifdef FLUSH_BASE_MINICACHE
-	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + PGDIR_SIZE);
+	map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
 	map.virtual = FLUSH_BASE_MINICACHE;
-	map.length = PGDIR_SIZE;
+	map.length = SZ_1M;
 	map.type = MT_MINICLEAN;
 	create_mapping(&map);
 #endif
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5e5d05b..f14b2d0 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -389,6 +389,17 @@
 	kern_pgprot = user_pgprot = cp->pte;
 
 	/*
+	 * Enable CPU-specific coherency if supported.
+	 * (Only available on XSC3 at the moment.)
+	 */
+	if (arch_is_coherent()) {
+		if (cpu_is_xsc3()) {
+			mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+		}
+	}
+
+	/*
 	 * ARMv6 and above have extended page tables.
 	 */
 	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index c916a6c..a2dd5ae 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -26,22 +26,7 @@
  * the cache line size of the I and D cache
  */
 #define DCACHELINESIZE	32
-#define FLUSH_OFFSET	32768
 
-	.macro flush_110_dcache	rd, ra, re
-	ldr	\rd, =flush_base
-	ldr	\ra, [\rd]
-	eor	\ra, \ra, #FLUSH_OFFSET
-	str	\ra, [\rd]
-	add	\re, \ra, #16384		@ only necessary for 16k
-1001:	ldr	\rd, [\ra], #DCACHELINESIZE
-	teq	\re, \ra
-	bne	1001b
-	.endm
-
-	.data
-flush_base:
-	.long	FLUSH_BASE
 	.text
 
 /*
@@ -145,13 +130,11 @@
  */
 	.align	5
 ENTRY(cpu_sa110_switch_mm)
-	flush_110_dcache	r3, ip, r1
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
+	str	lr, [sp, #-4]!
+	bl	v4wb_flush_kern_cache_all	@ clears IP
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
-	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, lr
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	ldr	pc, [sp], #4
 
 /*
  * cpu_sa110_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 41f21f2..777ad99 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -30,30 +30,6 @@
  * the cache line size of the I and D cache
  */
 #define DCACHELINESIZE	32
-#define FLUSH_OFFSET	32768
-
-	.macro flush_1100_dcache rd, ra, re
-	ldr	\rd, =flush_base
-	ldr	\ra, [\rd]
-	eor	\ra, \ra, #FLUSH_OFFSET
-	str	\ra, [\rd]
-	add	\re, \ra, #8192			@ only necessary for 8k
-1001:	ldr	\rd, [\ra], #DCACHELINESIZE
-	teq	\re, \ra
-	bne	1001b
-#ifdef FLUSH_BASE_MINICACHE
-	add	\ra, \ra, #FLUSH_BASE_MINICACHE - FLUSH_BASE
-	add	\re, \ra, #512			@ only 512 bytes
-1002:	ldr	\rd, [\ra], #DCACHELINESIZE
-	teq	\re, \ra
-	bne	1002b
-#endif
-	.endm
-
-	.data
-flush_base:
-	.long	FLUSH_BASE
-	.text
 
 	__INIT
 
@@ -79,9 +55,8 @@
 	stmfd	sp!, {lr}
 	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, ip
-	flush_1100_dcache r0, r1, r2		@ clean caches
-	mov	r0, #0
-	mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
+	bl	v4wb_flush_kern_cache_all
+	mcr	p15, 0, ip, c15, c2, 2		@ Disable clock switching
 	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 	bic	r0, r0, #0x1000			@ ...i............
 	bic	r0, r0, #0x000e			@ ............wca.
@@ -167,14 +142,12 @@
  */
 	.align	5
 ENTRY(cpu_sa1100_switch_mm)
-	flush_1100_dcache r3, ip, r1
-	mov	ip, #0
-	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+	str	lr, [sp, #-4]!
+	bl	v4wb_flush_kern_cache_all	@ clears IP
 	mcr	p15, 0, ip, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, lr
+	ldr	pc, [sp], #4
 
 /*
  * cpu_sa1100_set_pte(ptep, pte)
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index b9dfce5..80873b3 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -371,7 +371,7 @@
 ENTRY(cpu_xsc3_set_pte)
 	str	r1, [r0], #-2048		@ linux version
 
-	bic	r2, r1, #0xff0
+	bic	r2, r1, #0xdf0			@ Keep C, B, coherency bits
 	orr	r2, r2, #PTE_TYPE_EXT		@ extended page
 
 	eor	r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 0887bb2..ec49495 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -70,13 +70,13 @@
 
 config OMAP_32K_TIMER
 	bool "Use 32KHz timer"
-	depends on ARCH_OMAP16XX
+	depends on ARCH_OMAP16XX || ARCH_OMAP24XX
 	help
 	  Select this option if you want to enable the OMAP 32KHz timer.
 	  This timer saves power compared to the OMAP_MPU_TIMER, and has
 	  support for no tick during idle. The 32KHz timer provides less
 	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-	  currently only available for OMAP-16xx.
+	  currently only available for OMAP16XX and 24XX.
 
 endchoice
 
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9ccf194..2896b45 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,16 +3,16 @@
 #
 
 # Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
 obj-m :=
 obj-n :=
 obj-  :=
 
+obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o
+
 # OCPI interconnect support for 1710, 1610 and 5912
 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3c2bfc0..32ec04c 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/semaphore.h>
@@ -37,17 +38,38 @@
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
 
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
 struct clk * clk_get(struct device *dev, const char *id)
 {
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
 
 	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(p, &clocks, node) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			goto found;
+		}
+	}
+
 	list_for_each_entry(p, &clocks, node) {
 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
 			clk = p;
 			break;
 		}
 	}
+
+found:
 	mutex_unlock(&clocks_mutex);
 
 	return clk;
@@ -59,6 +81,9 @@
 	unsigned long flags;
 	int ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_enable)
 		ret = arch_clock->clk_enable(clk);
@@ -72,6 +97,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_disable)
 		arch_clock->clk_disable(clk);
@@ -84,6 +112,9 @@
 	unsigned long flags;
 	int ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	ret = clk->usecount;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -97,6 +128,9 @@
 	unsigned long flags;
 	unsigned long ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return 0;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	ret = clk->rate;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -121,6 +155,9 @@
 	unsigned long flags;
 	long ret = 0;
 
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_round_rate)
 		ret = arch_clock->clk_round_rate(clk, rate);
@@ -133,7 +170,10 @@
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_rate)
@@ -147,7 +187,10 @@
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret = -EINVAL;
+
+	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
+		return ret;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_set_parent)
@@ -163,6 +206,9 @@
 	unsigned long flags;
 	struct clk * ret = NULL;
 
+	if (clk == NULL || IS_ERR(clk))
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_get_parent)
 		ret = arch_clock->clk_get_parent(clk);
@@ -199,6 +245,9 @@
 /* Used for clocks that always have same value as the parent clock */
 void followparent_recalc(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	clk->rate = clk->parent->rate;
 }
 
@@ -207,6 +256,9 @@
 {
 	struct clk *clkp;
 
+	if (tclk == NULL || IS_ERR(tclk))
+		return;
+
 	list_for_each_entry(clkp, &clocks, node) {
 		if (likely(clkp->parent != tclk))
 			continue;
@@ -217,6 +269,9 @@
 
 int clk_register(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
 	mutex_lock(&clocks_mutex);
 	list_add(&clk->node, &clocks);
 	if (clk->init)
@@ -229,6 +284,9 @@
 
 void clk_unregister(struct clk *clk)
 {
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	mutex_lock(&clocks_mutex);
 	list_del(&clk->node);
 	mutex_unlock(&clocks_mutex);
@@ -239,6 +297,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_deny_idle)
 		arch_clock->clk_deny_idle(clk);
@@ -250,6 +311,9 @@
 {
 	unsigned long flags;
 
+	if (clk == NULL || IS_ERR(clk))
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (arch_clock->clk_allow_idle)
 		arch_clock->clk_allow_idle(clk);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 9dcce90..5d5d6eb 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -24,14 +24,7 @@
 #include <asm/arch/board.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/gpio.h>
-
-
-void omap_nop_release(struct device *dev)
-{
-        /* Nothing */
-}
-
-/*-------------------------------------------------------------------------*/
+#include <asm/arch/menelaus.h>
 
 #if 	defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
 
@@ -58,9 +51,6 @@
 static struct platform_device omap_i2c_device1 = {
         .name           = "i2c_omap",
         .id             = 1,
-        .dev = {
-                .release        = omap_nop_release,
-        },
 	.num_resources	= ARRAY_SIZE(i2c_resources1),
 	.resource	= i2c_resources1,
 };
@@ -98,6 +88,62 @@
 #endif
 
 /*-------------------------------------------------------------------------*/
+#if	defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+static void omap_init_kp(void)
+{
+	if (machine_is_omap_h2() || machine_is_omap_h3()) {
+		omap_cfg_reg(F18_1610_KBC0);
+		omap_cfg_reg(D20_1610_KBC1);
+		omap_cfg_reg(D19_1610_KBC2);
+		omap_cfg_reg(E18_1610_KBC3);
+		omap_cfg_reg(C21_1610_KBC4);
+
+		omap_cfg_reg(G18_1610_KBR0);
+		omap_cfg_reg(F19_1610_KBR1);
+		omap_cfg_reg(H14_1610_KBR2);
+		omap_cfg_reg(E20_1610_KBR3);
+		omap_cfg_reg(E19_1610_KBR4);
+		omap_cfg_reg(N19_1610_KBR5);
+	} else if (machine_is_omap_perseus2()) {
+		omap_cfg_reg(E2_730_KBR0);
+		omap_cfg_reg(J7_730_KBR1);
+		omap_cfg_reg(E1_730_KBR2);
+		omap_cfg_reg(F3_730_KBR3);
+		omap_cfg_reg(D2_730_KBR4);
+
+		omap_cfg_reg(C2_730_KBC0);
+		omap_cfg_reg(D3_730_KBC1);
+		omap_cfg_reg(E4_730_KBC2);
+		omap_cfg_reg(F4_730_KBC3);
+		omap_cfg_reg(E3_730_KBC4);
+	} else if (machine_is_omap_h4()) {
+		omap_cfg_reg(T19_24XX_KBR0);
+		omap_cfg_reg(R19_24XX_KBR1);
+		omap_cfg_reg(V18_24XX_KBR2);
+		omap_cfg_reg(M21_24XX_KBR3);
+		omap_cfg_reg(E5__24XX_KBR4);
+		if (omap_has_menelaus()) {
+			omap_cfg_reg(B3__24XX_KBR5);
+			omap_cfg_reg(AA4_24XX_KBC2);
+			omap_cfg_reg(B13_24XX_KBC6);
+		} else {
+			omap_cfg_reg(M18_24XX_KBR5);
+			omap_cfg_reg(H19_24XX_KBC2);
+			omap_cfg_reg(N19_24XX_KBC6);
+		}
+		omap_cfg_reg(R20_24XX_KBC0);
+		omap_cfg_reg(M14_24XX_KBC1);
+		omap_cfg_reg(V17_24XX_KBC3);
+		omap_cfg_reg(P21_24XX_KBC4);
+		omap_cfg_reg(L14_24XX_KBC5);
+	}
+}
+#else
+static inline void omap_init_kp(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
 
 #if	defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
@@ -130,7 +176,6 @@
 	.name		= "mmci-omap",
 	.id		= 1,
 	.dev = {
-		.release	= omap_nop_release,
 		.dma_mask	= &mmc1_dmamask,
 		.platform_data	= &mmc1_conf,
 	},
@@ -160,7 +205,6 @@
 	.name		= "mmci-omap",
 	.id		= 2,
 	.dev = {
-		.release	= omap_nop_release,
 		.dma_mask	= &mmc2_dmamask,
 		.platform_data	= &mmc2_conf,
 	},
@@ -240,6 +284,52 @@
 static inline void omap_init_mmc(void) {}
 #endif
 
+/*-------------------------------------------------------------------------*/
+
+/* Numbering for the SPI-capable controllers when used for SPI:
+ * spi		= 1
+ * uwire	= 2
+ * mmc1..2	= 3..4
+ * mcbsp1..3	= 5..7
+ */
+
+#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)
+
+#define	OMAP_UWIRE_BASE		0xfffb3000
+
+static struct resource uwire_resources[] = {
+	{
+		.start		= OMAP_UWIRE_BASE,
+		.end		= OMAP_UWIRE_BASE + 0x20,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device omap_uwire_device = {
+	.name	   = "omap_uwire",
+	.id	     = -1,
+	.num_resources	= ARRAY_SIZE(uwire_resources),
+	.resource	= uwire_resources,
+};
+
+static void omap_init_uwire(void)
+{
+	/* FIXME define and use a boot tag; not all boards will be hooking
+	 * up devices to the microwire controller, and multi-board configs
+	 * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
+	 */
+
+	/* board-specific code must configure chipselects (only a few
+	 * are normally used) and SCLK/SDI/SDO (each has two choices).
+	 */
+	(void) platform_device_register(&omap_uwire_device);
+}
+#else
+static inline void omap_init_uwire(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 #if	defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
 
 #ifdef CONFIG_ARCH_OMAP24XX
@@ -259,9 +349,6 @@
 static struct platform_device omap_wdt_device = {
 	.name	   = "omap_wdt",
 	.id	     = -1,
-	.dev = {
-		.release	= omap_nop_release,
-	},
 	.num_resources	= ARRAY_SIZE(wdt_resources),
 	.resource	= wdt_resources,
 };
@@ -295,9 +382,6 @@
 static struct platform_device omap_rng_device = {
 	.name	   = "omap_rng",
 	.id	     = -1,
-	.dev = {
-		.release	= omap_nop_release,
-	},
 	.num_resources	= ARRAY_SIZE(rng_resources),
 	.resource	= rng_resources,
 };
@@ -310,40 +394,6 @@
 static inline void omap_init_rng(void) {}
 #endif
 
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static struct omap_lcd_config omap_fb_conf;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
-	.name		= "omapfb",
-	.id		= -1,
-	.dev = {
-		.release		= omap_nop_release,
-		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
-		.platform_data		= &omap_fb_conf,
-	},
-	.num_resources = 0,
-};
-
-static inline void omap_init_fb(void)
-{
-	const struct omap_lcd_config *conf;
-
-	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
-	if (conf != NULL)
-		omap_fb_conf = *conf;
-	platform_device_register(&omap_fb_device);
-}
-
-#else
-
-static inline void omap_init_fb(void) {}
-
-#endif
-
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -369,9 +419,10 @@
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_init_fb();
 	omap_init_i2c();
+	omap_init_kp();
 	omap_init_mmc();
+	omap_init_uwire();
 	omap_init_wdt();
 	omap_init_rng();
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a4e5ac7..5dac423 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1258,6 +1258,11 @@
 	omap_writew(w, OMAP1610_DMA_LCD_CTRL);
 }
 
+int omap_lcd_dma_ext_running(void)
+{
+	return lcd_dma.ext_ctrl && lcd_dma.active;
+}
+
 /*----------------------------------------------------------------------------*/
 
 static int __init omap_init_dma(void)
@@ -1389,6 +1394,7 @@
 EXPORT_SYMBOL(omap_enable_lcd_dma);
 EXPORT_SYMBOL(omap_setup_lcd_dma);
 EXPORT_SYMBOL(omap_stop_lcd_dma);
+EXPORT_SYMBOL(omap_lcd_dma_ext_running);
 EXPORT_SYMBOL(omap_set_lcd_dma_b1);
 EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
 EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 38d7ebf..eba3cb5 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -97,6 +97,32 @@
 }
 
 
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+	int n;
+
+	/* If ARMXOR cannot be idled this function call is unnecessary */
+	if (!(inputmask & (1 << 1)))
+		return inputmask;
+
+	/* If any active timer is using ARMXOR return modified mask */
+	for (n = 0; dm_timers[n].base; ++n)
+		if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)&
+		    OMAP_TIMER_CTRL_ST) {
+			if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0)
+				inputmask &= ~(1 << 1);
+			else
+				inputmask &= ~(1 << 2);
+		}
+
+	return inputmask;
+}
+
+
 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
 	int n = (timer - dm_timers) << 1;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
new file mode 100644
index 0000000..305e9b9
--- /dev/null
+++ b/arch/arm/plat-omap/fb.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+	.name		= "omapfb",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &omap_fb_dma_mask,
+		.coherent_dma_mask	= ~(u32)0,
+		.platform_data		= &omapfb_config,
+	},
+	.num_resources = 0,
+};
+
+/* called from map_io */
+void omapfb_reserve_mem(void)
+{
+	const struct omap_fbmem_config *fbmem_conf;
+
+	omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
+	omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+
+	fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+
+	if (fbmem_conf != NULL) {
+		/* indicate that the bootloader already initialized the
+		 * fb device, so we'll skip that part in the fb driver
+		 */
+		omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
+		omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
+		if (fbmem_conf->fb_sdram_size) {
+			pr_info("Reserving %u bytes SDRAM for frame buffer\n",
+				fbmem_conf->fb_sdram_size);
+			reserve_bootmem(fbmem_conf->fb_sdram_start,
+					fbmem_conf->fb_sdram_size);
+		}
+	}
+}
+
+static inline int omap_init_fb(void)
+{
+	const struct omap_lcd_config *conf;
+
+	conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+	if (conf == NULL)
+		return 0;
+
+	omapfb_config.lcd = *conf;
+
+	return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void omapfb_reserve_mem(void) {}
+
+#endif
+
+
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e..d3c8ea7 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@
 static inline struct gpio_bank *get_gpio_bank(int gpio)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1];
@@ -223,7 +223,7 @@
 		return 0;
 	}
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510() && gpio < 16)
+	if (cpu_is_omap15xx() && gpio < 16)
 		return 0;
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@
 	u32 gpio_bit = 1 << gpio;
 
 	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-		trigger & IRQT_LOW);
+		trigger & __IRQT_LOWLVL);
 	MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-		trigger & IRQT_HIGH);
+		trigger & __IRQT_HIGHLVL);
 	MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-		trigger & IRQT_RISING);
+		trigger & __IRQT_RISEDGE);
 	MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-		trigger & IRQT_FALLING);
+		trigger & __IRQT_FALEDGE);
 	/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
 	 * triggering requested. */
 }
@@ -422,9 +422,9 @@
 	case METHOD_MPUIO:
 		reg += OMAP_MPUIO_GPIO_INT_EDGE;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -432,9 +432,9 @@
 	case METHOD_GPIO_1510:
 		reg += OMAP1510_GPIO_INT_CONTROL;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -446,20 +446,21 @@
 			reg += OMAP1610_GPIO_EDGE_CTRL1;
 		gpio &= 0x07;
 		/* We allow only edge triggering, i.e. two lowest bits */
-		if (trigger & ~IRQT_BOTHEDGE)
+		if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
 			BUG();
-		/* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
-		trigger &= 0x03;
 		l = __raw_readl(reg);
 		l &= ~(3 << (gpio << 1));
-		l |= trigger << (gpio << 1);
+		if (trigger & __IRQT_RISEDGE)
+			l |= 2 << (gpio << 1);
+		if (trigger & __IRQT_FALEDGE)
+			l |= 1 << (gpio << 1);
 		break;
 	case METHOD_GPIO_730:
 		reg += OMAP730_GPIO_INT_CONTROL;
 		l = __raw_readl(reg);
-		if (trigger == IRQT_RISING)
+		if (trigger & __IRQT_RISEDGE)
 			l |= 1 << gpio;
-		else if (trigger == IRQT_FALLING)
+		else if (trigger & __IRQT_FALEDGE)
 			l &= ~(1 << gpio);
 		else
 			goto bad;
@@ -491,7 +492,9 @@
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
 
-	if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+	if (type & IRQT_PROBE)
+		return -EINVAL;
+	if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
 		return -EINVAL;
 
 	bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@
 	if (bank->method == METHOD_GPIO_24XX)
 		isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
 #endif
-
 	while(1) {
-		isr = __raw_readl(isr_reg);
-		_enable_gpio_irqbank(bank, isr, 0);
-		_clear_gpio_irqbank(bank, isr);
-		_enable_gpio_irqbank(bank, isr, 1);
-		desc->chip->unmask(irq);
+		u32 isr_saved, level_mask = 0;
+
+		isr_saved = isr = __raw_readl(isr_reg);
+
+		if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+			isr &= 0x0000ffff;
+
+		if (cpu_is_omap24xx())
+			level_mask =
+				__raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT0) |
+				__raw_readl(bank->base +
+					OMAP24XX_GPIO_LEVELDETECT1);
+
+		/* clear edge sensitive interrupts before handler(s) are
+		called so that we don't miss any interrupt occurred while
+		executing them */
+		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+		_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+		_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+		/* if there is only edge sensitive GPIO pin interrupts
+		configured, we could unmask GPIO bank interrupt immediately */
+		if (!level_mask)
+			desc->chip->unmask(irq);
 
 		if (!isr)
 			break;
@@ -774,6 +796,20 @@
 			d = irq_desc + gpio_irq;
 			desc_handle_irq(gpio_irq, d, regs);
 		}
+
+		if (cpu_is_omap24xx()) {
+			/* clear level sensitive interrupts after handler(s) */
+			_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+			_clear_gpio_irqbank(bank, isr_saved & level_mask);
+			_enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+		}
+
+		/* if bank has any level sensitive GPIO pin interrupt
+		configured, we must unmask the bank interrupt only after
+		handler(s) are executed in order to avoid spurious bank
+		interrupt */
+		if (level_mask)
+			desc->chip->unmask(irq);
 	}
 }
 
@@ -848,7 +884,7 @@
 
 	initialized = 1;
 
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		gpio_ick = clk_get(NULL, "arm_gpio_ck");
 		if (IS_ERR(gpio_ick))
 			printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@
 	}
 
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		printk(KERN_INFO "OMAP1510 GPIO hardware\n");
 		gpio_bank_count = 2;
 		gpio_bank = gpio_bank_1510;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1cd2cac..196aac3 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -34,7 +34,7 @@
 #ifdef CONFIG_MCBSP_DEBUG
 #define DBG(x...)	printk(x)
 #else
-#define DBG(x...)	do { } while (0)
+#define DBG(x...)			do { } while (0)
 #endif
 
 struct omap_mcbsp {
@@ -44,6 +44,7 @@
 	omap_mcbsp_word_length       rx_word_length;
 	omap_mcbsp_word_length       tx_word_length;
 
+	omap_mcbsp_io_type_t         io_type; /* IRQ or poll */
 	/* IRQ based TX/RX */
 	int                          rx_irq;
 	int                          tx_irq;
@@ -64,10 +65,19 @@
 };
 
 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+#ifdef CONFIG_ARCH_OMAP1
 static struct clk *mcbsp_dsp_ck = 0;
 static struct clk *mcbsp_api_ck = 0;
 static struct clk *mcbsp_dspxor_ck = 0;
-
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+static struct clk *mcbsp1_ick = 0;
+static struct clk *mcbsp1_fck = 0;
+static struct clk *mcbsp2_ick = 0;
+static struct clk *mcbsp2_fck = 0;
+static struct clk *sys_ck = 0;
+static struct clk *sys_clkout = 0;
+#endif
 
 static void omap_mcbsp_dump_reg(u8 id)
 {
@@ -88,7 +98,6 @@
 	DBG("***********************\n");
 }
 
-
 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
@@ -109,7 +118,6 @@
 	return IRQ_HANDLED;
 }
 
-
 static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
 {
 	struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
@@ -176,7 +184,7 @@
 		return 0;
 	}
 
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
 		if (id > OMAP_MAX_MCBSP_COUNT) {
 			printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
 			return -1;
@@ -187,9 +195,10 @@
 	return -1;
 }
 
+#ifdef CONFIG_ARCH_OMAP1
 static void omap_mcbsp_dsp_request(void)
 {
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 		clk_enable(mcbsp_dsp_ck);
 		clk_enable(mcbsp_api_ck);
 
@@ -207,12 +216,49 @@
 
 static void omap_mcbsp_dsp_free(void)
 {
-	if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+	if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
 		clk_disable(mcbsp_dspxor_ck);
 		clk_disable(mcbsp_dsp_ck);
 		clk_disable(mcbsp_api_ck);
 	}
 }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static void omap2_mcbsp2_mux_setup(void)
+{
+	omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+	omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+	omap_cfg_reg(W15_24XX_MCBSP2_DR);
+	omap_cfg_reg(V15_24XX_MCBSP2_DX);
+	omap_cfg_reg(V14_24XX_GPIO117);
+	omap_cfg_reg(W14_24XX_SYS_CLKOUT);
+}
+#endif
+
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+	if (omap_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	spin_lock(&mcbsp[id].lock);
+
+	if (!mcbsp[id].free) {
+		printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return -EINVAL;
+	}
+
+	mcbsp[id].io_type = io_type;
+
+	spin_unlock(&mcbsp[id].lock);
+
+	return 0;
+}
 
 int omap_mcbsp_request(unsigned int id)
 {
@@ -221,12 +267,26 @@
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
 
+#ifdef CONFIG_ARCH_OMAP1
 	/*
 	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
 	 * are DSP public peripherals.
 	 */
 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
 		omap_mcbsp_dsp_request();
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+	if (cpu_is_omap24xx()) {
+		if (id == OMAP_MCBSP1) {
+			clk_enable(mcbsp1_ick);
+			clk_enable(mcbsp1_fck);
+		} else {
+			clk_enable(mcbsp2_ick);
+			clk_enable(mcbsp2_fck);
+		}
+	}
+#endif
 
 	spin_lock(&mcbsp[id].lock);
 	if (!mcbsp[id].free) {
@@ -238,30 +298,33 @@
 	mcbsp[id].free = 0;
 	spin_unlock(&mcbsp[id].lock);
 
-	/* We need to get IRQs here */
-	err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
-			  "McBSP",
-			  (void *) (&mcbsp[id]));
-	if (err != 0) {
-		printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
-		       mcbsp[id].tx_irq, mcbsp[id].id);
-		return err;
+	if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+		/* We need to get IRQs here */
+		err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+				  "McBSP",
+				  (void *) (&mcbsp[id]));
+		if (err != 0) {
+			printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+			       mcbsp[id].tx_irq, mcbsp[id].id);
+			return err;
+		}
+
+		init_completion(&(mcbsp[id].tx_irq_completion));
+
+
+		err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+				  "McBSP",
+				  (void *) (&mcbsp[id]));
+		if (err != 0) {
+			printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+			       mcbsp[id].rx_irq, mcbsp[id].id);
+			free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+			return err;
+		}
+
+		init_completion(&(mcbsp[id].rx_irq_completion));
 	}
 
-	init_completion(&(mcbsp[id].tx_irq_completion));
-
-
-	err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
-			  "McBSP",
-			  (void *) (&mcbsp[id]));
-	if (err != 0) {
-		printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
-		       mcbsp[id].rx_irq, mcbsp[id].id);
-		free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
-		return err;
-	}
-
-	init_completion(&(mcbsp[id].rx_irq_completion));
 	return 0;
 
 }
@@ -271,8 +334,24 @@
 	if (omap_mcbsp_check(id) < 0)
 		return;
 
-	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
-		omap_mcbsp_dsp_free();
+#ifdef CONFIG_ARCH_OMAP1
+	if (cpu_class_is_omap1()) {
+		if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+			omap_mcbsp_dsp_free();
+	}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+	if (cpu_is_omap24xx()) {
+		if (id == OMAP_MCBSP1) {
+			clk_disable(mcbsp1_ick);
+			clk_disable(mcbsp1_fck);
+		} else {
+			clk_disable(mcbsp2_ick);
+			clk_disable(mcbsp2_fck);
+		}
+	}
+#endif
 
 	spin_lock(&mcbsp[id].lock);
 	if (mcbsp[id].free) {
@@ -284,9 +363,11 @@
 	mcbsp[id].free = 1;
 	spin_unlock(&mcbsp[id].lock);
 
-	/* Free IRQs */
-	free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
-	free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+	if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+		/* Free IRQs */
+		free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+		free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+	}
 }
 
 /*
@@ -461,6 +542,115 @@
 }
 
 
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+	u32 io_base = mcbsp[id].io_base;
+	omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+	omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+	if (tx_word_length != rx_word_length)
+		return -EINVAL;
+
+	/* First we wait for the transmitter to be ready */
+	spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+	while (!(spcr2 & XRDY)) {
+		spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+		if (attempts++ > 1000) {
+			/* We must reset the transmitter */
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+			udelay(10);
+			printk("McBSP transmitter not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Now we can push the data */
+	if (tx_word_length > OMAP_MCBSP_WORD_16)
+		OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+	OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+
+	/* We wait for the receiver to be ready */
+	spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+	while (!(spcr1 & RRDY)) {
+		spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+		if (attempts++ > 1000) {
+			/* We must reset the receiver */
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+			udelay(10);
+			printk("McBSP receiver not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Receiver is ready, let's read the dummy data */
+	if (rx_word_length > OMAP_MCBSP_WORD_16)
+		word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+	return 0;
+}
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
+{
+	u32 io_base = mcbsp[id].io_base, clock_word = 0;
+	omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+	omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+	u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+	if (tx_word_length != rx_word_length)
+		return -EINVAL;
+
+	/* First we wait for the transmitter to be ready */
+	spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+	while (!(spcr2 & XRDY)) {
+		spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+		if (attempts++ > 1000) {
+			/* We must reset the transmitter */
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+			udelay(10);
+			printk("McBSP transmitter not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* We first need to enable the bus clock */
+	if (tx_word_length > OMAP_MCBSP_WORD_16)
+		OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
+	OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
+
+	/* We wait for the receiver to be ready */
+	spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+	while (!(spcr1 & RRDY)) {
+		spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+		if (attempts++ > 1000) {
+			/* We must reset the receiver */
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+			udelay(10);
+			OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+			udelay(10);
+			printk("McBSP receiver not ready\n");
+			return -EAGAIN;
+		}
+	}
+
+	/* Receiver is ready, there is something for us */
+	if (rx_word_length > OMAP_MCBSP_WORD_16)
+		word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+	word[0] = (word_lsb | (word_msb << 16));
+
+	return 0;
+}
+
+
 /*
  * Simple DMA based buffer rx/tx routines.
  * Nothing fancy, just a single buffer tx/rx through DMA.
@@ -471,6 +661,9 @@
 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
 {
 	int dma_tx_ch;
+	int src_port = 0;
+	int dest_port = 0;
+	int sync_dev = 0;
 
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
@@ -487,20 +680,27 @@
 
 	init_completion(&(mcbsp[id].tx_dma_completion));
 
+	if (cpu_class_is_omap1()) {
+		src_port = OMAP_DMA_PORT_TIPB;
+		dest_port = OMAP_DMA_PORT_EMIFF;
+	}
+	if (cpu_is_omap24xx())
+		sync_dev = mcbsp[id].dma_tx_sync;
+
 	omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
 				     OMAP_DMA_DATA_TYPE_S16,
 				     length >> 1, 1,
 				     OMAP_DMA_SYNC_ELEMENT,
-				     0, 0);
+	 sync_dev, 0);
 
 	omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
-				 OMAP_DMA_PORT_TIPB,
+				 src_port,
 				 OMAP_DMA_AMODE_CONSTANT,
 				 mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
 				 0, 0);
 
 	omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
-				OMAP_DMA_PORT_EMIFF,
+				dest_port,
 				OMAP_DMA_AMODE_POST_INC,
 				buffer,
 				0, 0);
@@ -514,6 +714,9 @@
 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
 {
 	int dma_rx_ch;
+	int src_port = 0;
+	int dest_port = 0;
+	int sync_dev = 0;
 
 	if (omap_mcbsp_check(id) < 0)
 		return -EINVAL;
@@ -530,20 +733,27 @@
 
 	init_completion(&(mcbsp[id].rx_dma_completion));
 
+	if (cpu_class_is_omap1()) {
+		src_port = OMAP_DMA_PORT_TIPB;
+		dest_port = OMAP_DMA_PORT_EMIFF;
+	}
+	if (cpu_is_omap24xx())
+		sync_dev = mcbsp[id].dma_rx_sync;
+
 	omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
 				     OMAP_DMA_DATA_TYPE_S16,
 				     length >> 1, 1,
 				     OMAP_DMA_SYNC_ELEMENT,
-				     0, 0);
+	 sync_dev, 0);
 
 	omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
-				OMAP_DMA_PORT_TIPB,
+				src_port,
 				OMAP_DMA_AMODE_CONSTANT,
 				mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
 				0, 0);
 
 	omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
-				 OMAP_DMA_PORT_EMIFF,
+				 dest_port,
 				 OMAP_DMA_AMODE_POST_INC,
 				 buffer,
 				 0, 0);
@@ -688,6 +898,23 @@
 };
 #endif
 
+#if defined(CONFIG_ARCH_OMAP24XX)
+static const struct omap_mcbsp_info mcbsp_24xx[] = {
+	[0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
+		.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
+		.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
+		.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+		.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+		},
+	[1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
+		.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
+		.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
+		.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+		.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+		},
+};
+#endif
+
 static int __init omap_mcbsp_init(void)
 {
 	int mcbsp_count = 0, i;
@@ -695,6 +922,7 @@
 
 	printk("Initializing OMAP McBSP system\n");
 
+#ifdef CONFIG_ARCH_OMAP1
 	mcbsp_dsp_ck = clk_get(0, "dsp_ck");
 	if (IS_ERR(mcbsp_dsp_ck)) {
 		printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
@@ -710,6 +938,29 @@
 		printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
 		return PTR_ERR(mcbsp_dspxor_ck);
 	}
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+	mcbsp1_ick = clk_get(0, "mcbsp1_ick");
+	if (IS_ERR(mcbsp1_ick)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
+		return PTR_ERR(mcbsp1_ick);
+	}
+	mcbsp1_fck = clk_get(0, "mcbsp1_fck");
+	if (IS_ERR(mcbsp1_fck)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
+		return PTR_ERR(mcbsp1_fck);
+	}
+	mcbsp2_ick = clk_get(0, "mcbsp2_ick");
+	if (IS_ERR(mcbsp2_ick)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
+		return PTR_ERR(mcbsp2_ick);
+	}
+	mcbsp2_fck = clk_get(0, "mcbsp2_fck");
+	if (IS_ERR(mcbsp2_fck)) {
+		printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
+		return PTR_ERR(mcbsp2_fck);
+	}
+#endif
 
 #ifdef CONFIG_ARCH_OMAP730
 	if (cpu_is_omap730()) {
@@ -718,7 +969,7 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		mcbsp_info = mcbsp_1510;
 		mcbsp_count = ARRAY_SIZE(mcbsp_1510);
 	}
@@ -729,6 +980,19 @@
 		mcbsp_count = ARRAY_SIZE(mcbsp_1610);
 	}
 #endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+	if (cpu_is_omap24xx()) {
+		mcbsp_info = mcbsp_24xx;
+		mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
+
+		/* REVISIT: where's the right place? */
+		omap2_mcbsp2_mux_setup();
+		sys_ck = clk_get(0, "sys_ck");
+		sys_clkout = clk_get(0, "sys_clkout");
+		clk_set_parent(sys_clkout, sys_ck);
+		clk_enable(sys_clkout);
+	}
+#endif
 	for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
 		if (i >= mcbsp_count) {
 			mcbsp[i].io_base = 0;
@@ -741,6 +1005,7 @@
 		mcbsp[i].dma_rx_lch = -1;
 
 		mcbsp[i].io_base = mcbsp_info[i].virt_base;
+		mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
 		mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
 		mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
 		mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
@@ -751,11 +1016,11 @@
 	return 0;
 }
 
-
 arch_initcall(omap_mcbsp_init);
 
 EXPORT_SYMBOL(omap_mcbsp_config);
 EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
 EXPORT_SYMBOL(omap_mcbsp_free);
 EXPORT_SYMBOL(omap_mcbsp_start);
 EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -763,4 +1028,6 @@
 EXPORT_SYMBOL(omap_mcbsp_recv_word);
 EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
 EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 5cc6775..37792d4 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -62,9 +62,6 @@
 	if (!cpu_is_omap16xx())
 		return -ENODEV;
 
-	/* Make sure there's clock for OCPI */
-	clk_enable(ocpi_ck);
-
 	/* Enable access for OHCI in OCPI */
 	val = omap_readl(OCPI_PROT);
 	val &= ~0xff;
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index 093efd7..1a24e2c 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -38,6 +38,7 @@
 #include <linux/pm.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
+#include <linux/pm.h>
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index ee82763..b7bf09b 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -16,24 +16,94 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <asm/mach/map.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
+#include <asm/mach/map.h>
+
 #include <asm/arch/sram.h>
+#include <asm/arch/board.h>
 
 #define OMAP1_SRAM_PA		0x20000000
 #define OMAP1_SRAM_VA		0xd0000000
 #define OMAP2_SRAM_PA		0x40200000
+#define OMAP2_SRAM_PUB_PA	0x4020f800
 #define OMAP2_SRAM_VA		0xd0000000
+#define OMAP2_SRAM_PUB_VA	0xd0000800
 
+#if defined(CONFIG_ARCH_OMAP24XX)
+#define SRAM_BOOTLOADER_SZ	0x00
+#else
 #define SRAM_BOOTLOADER_SZ	0x80
+#endif
+
+#define VA_REQINFOPERM0		IO_ADDRESS(0x68005048)
+#define VA_READPERM0		IO_ADDRESS(0x68005050)
+#define VA_WRITEPERM0		IO_ADDRESS(0x68005058)
+#define VA_CONTROL_STAT		IO_ADDRESS(0x480002F8)
+#define GP_DEVICE		0x300
+#define TYPE_MASK		0x700
+
+#define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
 
 static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
+unsigned long omap_fb_sram_start;
+unsigned long omap_fb_sram_size;
+
+/* Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies.  The default accessable size for all device types is 2k. A GP
+ * device allows ARM11 but not other initators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+	int type = 0;
+
+	if (cpu_is_omap242x())
+		type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
+
+	if (type == GP_DEVICE) {
+		/* RAMFW: R/W access to all initators for all qualifier sets */
+		if (cpu_is_omap242x()) {
+			__raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
+			__raw_writel(0xCFDE, VA_READPERM0);  /* all i-read */
+			__raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */
+		}
+		return 0;
+	} else
+		return 1; /* assume locked with no PPA or security driver */
+}
+
+void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
+		      unsigned long *start, unsigned long *size)
+{
+	const struct omap_fbmem_config *fbmem_conf;
+
+	fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+	if (fbmem_conf != NULL) {
+		*start = fbmem_conf->fb_sram_start;
+		*size = fbmem_conf->fb_sram_size;
+	} else {
+		*size = 0;
+		*start = 0;
+	}
+
+	if (*size && (
+	    *start < start_avail ||
+	    *start + *size > start_avail + size_avail)) {
+		printk(KERN_ERR "invalid FB SRAM configuration\n");
+		*start = start_avail;
+		*size = size_avail;
+	}
+
+	if (*size)
+		pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
+}
+
 /*
  * The amount of SRAM depends on the core type.
  * Note that we cannot try to test for SRAM here because writes
@@ -42,26 +112,45 @@
  */
 void __init omap_detect_sram(void)
 {
-	if (!cpu_is_omap24xx())
+	unsigned long sram_start;
+
+	if (cpu_is_omap24xx()) {
+		if (is_sram_locked()) {
+			omap_sram_base = OMAP2_SRAM_PUB_VA;
+			sram_start = OMAP2_SRAM_PUB_PA;
+			omap_sram_size = 0x800; /* 2K */
+		} else {
+			omap_sram_base = OMAP2_SRAM_VA;
+			sram_start = OMAP2_SRAM_PA;
+			if (cpu_is_omap242x())
+				omap_sram_size = 0xa0000; /* 640K */
+			else if (cpu_is_omap243x())
+				omap_sram_size = 0x10000; /* 64K */
+		}
+	} else {
 		omap_sram_base = OMAP1_SRAM_VA;
-	else
-		omap_sram_base = OMAP2_SRAM_VA;
+		sram_start = OMAP1_SRAM_PA;
 
-	if (cpu_is_omap730())
-		omap_sram_size = 0x32000;	/* 200K */
-	else if (cpu_is_omap15xx())
-		omap_sram_size = 0x30000;	/* 192K */
-	else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
-		omap_sram_size = 0x4000;	/* 16K */
-	else if (cpu_is_omap1611())
-		omap_sram_size = 0x3e800;	/* 250K */
-	else if (cpu_is_omap2420())
-		omap_sram_size = 0xa0014;	/* 640K */
-	else {
-		printk(KERN_ERR "Could not detect SRAM size\n");
-		omap_sram_size = 0x4000;
+		if (cpu_is_omap730())
+			omap_sram_size = 0x32000;	/* 200K */
+		else if (cpu_is_omap15xx())
+			omap_sram_size = 0x30000;	/* 192K */
+		else if (cpu_is_omap1610() || cpu_is_omap1621() ||
+		     cpu_is_omap1710())
+			omap_sram_size = 0x4000;	/* 16K */
+		else if (cpu_is_omap1611())
+			omap_sram_size = 0x3e800;	/* 250K */
+		else {
+			printk(KERN_ERR "Could not detect SRAM size\n");
+			omap_sram_size = 0x4000;
+		}
 	}
-
+	get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
+			 omap_sram_size - SRAM_BOOTLOADER_SZ,
+			 &omap_fb_sram_start, &omap_fb_sram_size);
+	if (omap_fb_sram_size)
+		omap_sram_size -= sram_start + omap_sram_size -
+				  omap_fb_sram_start;
 	omap_sram_ceil = omap_sram_base + omap_sram_size;
 }
 
@@ -80,12 +169,20 @@
  */
 void __init omap_map_sram(void)
 {
+	unsigned long base;
+
 	if (omap_sram_size == 0)
 		return;
 
 	if (cpu_is_omap24xx()) {
 		omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
-		omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+
+		if (is_sram_locked())
+			base = OMAP2_SRAM_PUB_PA;
+		else
+			base = OMAP2_SRAM_PA;
+		base = ROUND_DOWN(base, PAGE_SIZE);
+		omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
 	}
 
 	omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
@@ -93,7 +190,8 @@
 	iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
 
 	printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
-	       omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+	__pfn_to_phys(omap_sram_io_desc[0].pfn),
+	omap_sram_io_desc[0].virtual,
 	       omap_sram_io_desc[0].length);
 
 	/*
@@ -118,8 +216,9 @@
 		printk(KERN_ERR "Not enough space in SRAM\n");
 		return NULL;
 	}
+
 	omap_sram_ceil -= size;
-	omap_sram_ceil &= ~0x3;
+	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
 	memcpy((void *)omap_sram_ceil, start, size);
 
 	return (void *)omap_sram_ceil;
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
new file mode 100644
index 0000000..b2a943b
--- /dev/null
+++ b/arch/arm/plat-omap/timer32k.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/plat-omap/timer32k.c
+ *
+ * OMAP 32K Timer
+ *
+ * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Partial timer rewrite and additional dynamic tick timer support by
+ * Tony Lindgen <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * MPU timer code based on the older MPU timer code for OMAP
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+struct sys_timer omap_timer;
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED		0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED		0x48004010
+#else
+#error OMAP 32KHz timer does not currently work on 15XX!
+#endif
+
+/* 16xx specific defines */
+#define OMAP1_32K_TIMER_BASE		0xfffb9000
+#define OMAP1_32K_TIMER_CR		0x08
+#define OMAP1_32K_TIMER_TVR		0x00
+#define OMAP1_32K_TIMER_TCR		0x04
+
+/* 24xx specific defines */
+#define OMAP2_GP_TIMER_BASE		0x48028000
+#define CM_CLKSEL_WKUP			0x48008440
+#define GP_TIMER_TIDR			0x00
+#define GP_TIMER_TISR			0x18
+#define GP_TIMER_TIER			0x1c
+#define GP_TIMER_TCLR			0x24
+#define GP_TIMER_TCRR			0x28
+#define GP_TIMER_TLDR			0x2c
+#define GP_TIMER_TTGR			0x30
+#define GP_TIMER_TSICR			0x40
+
+#define OMAP_32K_TICKS_PER_HZ		(32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
+				(((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+	if (cpu_class_is_omap1())
+		omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+
+	if (cpu_is_omap24xx())
+		omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+	if (cpu_class_is_omap1())
+		return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+
+	if (cpu_is_omap24xx())
+		return omap_readl(OMAP2_GP_TIMER_BASE + reg);
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+	return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+	if (cpu_class_is_omap1()) {
+		omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+		omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+	}
+
+	if (cpu_is_omap24xx()) {
+		omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
+		omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
+		omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
+	}
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+	if (cpu_class_is_omap1())
+		omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+
+	if (cpu_is_omap24xx())
+		omap_32k_timer_write(0x0, GP_TIMER_TCLR);
+}
+
+/*
+ * Rounds down to nearest usec. Note that this will overflow for larger values.
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+	return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+/*
+ * Rounds down to nearest nsec.
+ */
+static inline unsigned long long
+omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+{
+	return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+	unsigned long now = omap_32k_sync_timer_read();
+	return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+	return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+					    struct pt_regs *regs)
+{
+	unsigned long flags;
+	unsigned long now;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	if (cpu_is_omap24xx()) {
+		u32 status = omap_32k_timer_read(GP_TIMER_TISR);
+		omap_32k_timer_write(status, GP_TIMER_TISR);
+	}
+
+	now = omap_32k_sync_timer_read();
+
+	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+		timer_tick(regs);
+	}
+
+	/* Restart timer so we don't drift off due to modulo or dynamic tick.
+	 * By default we program the next timer to be continuous to avoid
+	 * latencies during high system load. During dynamic tick operation the
+	 * continuous timer can be overridden from pm_idle to be longer.
+	 */
+	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+	/* No need to reprogram timer, just use the next interrupt */
+	return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+	return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+	.enable		= omap_32k_timer_enable_dyn_tick,
+	.disable	= omap_32k_timer_disable_dyn_tick,
+	.reprogram	= omap_32k_timer_reprogram,
+	.handler	= omap_32k_timer_interrupt,
+};
+#endif	/* CONFIG_NO_IDLE_HZ */
+
+static struct irqaction omap_32k_timer_irq = {
+	.name		= "32KHz timer",
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= omap_32k_timer_interrupt,
+};
+
+static struct clk * gpt1_ick;
+static struct clk * gpt1_fck;
+
+static __init void omap_init_32k_timer(void)
+{
+#ifdef CONFIG_NO_IDLE_HZ
+	omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
+	if (cpu_class_is_omap1())
+		setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+	if (cpu_is_omap24xx())
+		setup_irq(37, &omap_32k_timer_irq);
+	omap_timer.offset  = omap_32k_timer_gettimeoffset;
+	omap_32k_last_tick = omap_32k_sync_timer_read();
+
+	/* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+	if (cpu_is_omap24xx()) {
+		omap_32k_timer_write(0, GP_TIMER_TCLR);
+		omap_writel(0, CM_CLKSEL_WKUP);		/* 32KHz clock source */
+
+		gpt1_ick = clk_get(NULL, "gpt1_ick");
+		if (IS_ERR(gpt1_ick))
+			printk(KERN_ERR "Could not get gpt1_ick\n");
+		else
+			clk_enable(gpt1_ick);
+
+		gpt1_fck = clk_get(NULL, "gpt1_fck");
+		if (IS_ERR(gpt1_fck))
+			printk(KERN_ERR "Could not get gpt1_fck\n");
+		else
+			clk_enable(gpt1_fck);
+
+		mdelay(100);		/* Wait for clocks to stabilize */
+
+		omap_32k_timer_write(0x7, GP_TIMER_TISR);
+	}
+
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+	omap_init_32k_timer();
+}
+
+struct sys_timer omap_timer = {
+	.init		= omap_timer_init,
+	.offset		= NULL,		/* Initialized later */
+};
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 9b367a6..009038c 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -197,7 +197,7 @@
 			 dd, d, exceptions);
 		vfp_put_double(dd, d);
 	}
-	return exceptions & ~VFP_NAN_FLAG;
+	return exceptions;
 }
 
 /*
@@ -588,6 +588,7 @@
 	struct vfp_double vdm;
 	u32 d, exceptions = 0;
 	int rmode = fpscr & FPSCR_RMODE_MASK;
+	int tm;
 
 	vfp_double_unpack(&vdm, vfp_get_double(dm));
 	vfp_double_dump("VDM", &vdm);
@@ -595,10 +596,14 @@
 	/*
 	 * Do we have denormalised number?
 	 */
-	if (vfp_double_type(&vdm) & VFP_DENORMAL)
+	tm = vfp_double_type(&vdm);
+	if (tm & VFP_DENORMAL)
 		exceptions |= FPSCR_IDC;
 
-	if (vdm.exponent >= 1023 + 32) {
+	if (tm & VFP_NAN) {
+		d = 0;
+		exceptions |= FPSCR_IOC;
+	} else if (vdm.exponent >= 1023 + 32) {
 		d = 0x7fffffff;
 		if (vdm.sign)
 			d = ~d;
@@ -1122,9 +1127,9 @@
 {
 	u32 op = inst & FOP_MASK;
 	u32 exceptions = 0;
-	unsigned int dd = vfp_get_sd(inst);
-	unsigned int dn = vfp_get_sn(inst);
-	unsigned int dm = vfp_get_sm(inst);
+	unsigned int dd = vfp_get_dd(inst);
+	unsigned int dn = vfp_get_dn(inst);
+	unsigned int dm = vfp_get_dm(inst);
 	unsigned int vecitr, veclen, vecstride;
 	u32 (*fop)(int, int, s32, u32);
 
@@ -1141,7 +1146,7 @@
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
 		 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-	fop = (op == FOP_EXT) ? fop_extfns[dn] : fop_fns[FOP_TO_IDX(op)];
+	fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
 	if (!fop)
 		goto invalid;
 
@@ -1149,17 +1154,13 @@
 		u32 except;
 
 		if (op == FOP_EXT)
-			pr_debug("VFP: itr%d (d%u.%u) = op[%u] (d%u.%u)\n",
+			pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dd >> 1, dd & 1, dn,
-				 dm >> 1, dm & 1);
+				 dd, dn, dm);
 		else
-			pr_debug("VFP: itr%d (d%u.%u) = (d%u.%u) op[%u] (d%u.%u)\n",
+			pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dd >> 1, dd & 1,
-				 dn >> 1, dn & 1,
-				 FOP_TO_IDX(op),
-				 dm >> 1, dm & 1);
+				 dd, dn, FOP_TO_IDX(op), dm);
 
 		except = fop(dd, dn, dm, fpscr);
 		pr_debug("VFP: itr%d: exceptions=%08x\n",
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index b7ed57e..a3f65b4 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -189,11 +189,10 @@
 
 	.globl	vfp_get_double
 vfp_get_double:
-	mov	r0, r0, lsr #1
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mrrc	p10, 1, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
+	mrrc	p11, 1, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
 	mov	pc, lr
 	.endr
 
@@ -204,10 +203,9 @@
 
 	.globl	vfp_put_double
 vfp_put_double:
-	mov	r0, r0, lsr #1
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mcrr	p10, 1, r1, r2, c\dr	@ fmrrd	r1, r2, d\dr
+	mcrr	p11, 1, r1, r2, c\dr	@ fmdrr	r1, r2, d\dr
 	mov	pc, lr
 	.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 22f3da4..37ff814 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -180,7 +180,7 @@
 		 * emulate it.
 		 */
 	}
-	return exceptions;
+	return exceptions & ~VFP_NAN_FLAG;
 }
 
 /*
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 14dd696..dae2c2f 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -203,7 +203,7 @@
 		vfp_put_float(sd, d);
 	}
 
-	return exceptions & ~VFP_NAN_FLAG;
+	return exceptions;
 }
 
 /*
@@ -632,6 +632,7 @@
 	struct vfp_single vsm;
 	u32 d, exceptions = 0;
 	int rmode = fpscr & FPSCR_RMODE_MASK;
+	int tm;
 
 	vfp_single_unpack(&vsm, m);
 	vfp_single_dump("VSM", &vsm);
@@ -639,10 +640,14 @@
 	/*
 	 * Do we have a denormalised number?
 	 */
+	tm = vfp_single_type(&vsm);
 	if (vfp_single_type(&vsm) & VFP_DENORMAL)
 		exceptions |= FPSCR_IDC;
 
-	if (vsm.exponent >= 127 + 32) {
+	if (tm & VFP_NAN) {
+		d = 0;
+		exceptions |= FPSCR_IOC;
+	} else if (vsm.exponent >= 127 + 32) {
 		/*
 		 * m >= 2^31-2^7: invalid
 		 */
@@ -1188,7 +1193,7 @@
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
 		 (veclen >> FPSCR_LENGTH_BIT) + 1);
 
-	fop = (op == FOP_EXT) ? fop_extfns[sn] : fop_fns[FOP_TO_IDX(op)];
+	fop = (op == FOP_EXT) ? fop_extfns[FEXT_TO_IDX(inst)] : fop_fns[FOP_TO_IDX(op)];
 	if (!fop)
 		goto invalid;
 
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index a6a1b33..9d66c27 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -152,7 +152,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(memset);
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index de39725..d578590 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -39,7 +39,6 @@
 /* String functions */
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strchr);
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 1d21c8d..a9b5952 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1170,12 +1170,6 @@
 # syscall vector table
 #
 ###############################################################################
-#ifdef CONFIG_MMU
-#define __MMU(X) X
-#else
-#define __MMU(X) sys_ni_syscall
-#endif
-
 	.section .rodata
 ALIGN
 	.globl		sys_call_table
@@ -1305,7 +1299,7 @@
 	.long sys_newuname
 	.long sys_ni_syscall	/* old "cacheflush" */
 	.long sys_adjtimex
-	.long __MMU(sys_mprotect) /* 125 */
+	.long sys_mprotect	/* 125 */
 	.long sys_sigprocmask
 	.long sys_ni_syscall	/* old "create_module" */
 	.long sys_init_module
@@ -1324,16 +1318,16 @@
 	.long sys_getdents
 	.long sys_select
 	.long sys_flock
-	.long __MMU(sys_msync)
+	.long sys_msync
 	.long sys_readv		/* 145 */
 	.long sys_writev
 	.long sys_getsid
 	.long sys_fdatasync
 	.long sys_sysctl
-	.long __MMU(sys_mlock)		/* 150 */
-	.long __MMU(sys_munlock)
-	.long __MMU(sys_mlockall)
-	.long __MMU(sys_munlockall)
+	.long sys_mlock		/* 150 */
+	.long sys_munlock
+	.long sys_mlockall
+	.long sys_munlockall
 	.long sys_sched_setparam
 	.long sys_sched_getparam   /* 155 */
 	.long sys_sched_setscheduler
@@ -1343,7 +1337,7 @@
 	.long sys_sched_get_priority_min  /* 160 */
 	.long sys_sched_rr_get_interval
 	.long sys_nanosleep
-	.long __MMU(sys_mremap)
+	.long sys_mremap
 	.long sys_setresuid16
 	.long sys_getresuid16	/* 165 */
 	.long sys_ni_syscall	/* for vm86 */
@@ -1398,8 +1392,8 @@
 	.long sys_setfsuid		/* 215 */
 	.long sys_setfsgid
 	.long sys_pivot_root
-	.long __MMU(sys_mincore)
-	.long __MMU(sys_madvise)
+	.long sys_mincore
+	.long sys_madvise
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
 	.long sys_ni_syscall	/* reserved for TUX */
@@ -1437,7 +1431,7 @@
 	.long sys_epoll_create
 	.long sys_epoll_ctl	/* 255 */
 	.long sys_epoll_wait
- 	.long __MMU(sys_remap_file_pages)
+ 	.long sys_remap_file_pages
  	.long sys_set_tid_address
  	.long sys_timer_create
  	.long sys_timer_settime		/* 260 */
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 07c8ffa..0f273a7 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -27,7 +27,6 @@
 EXPORT_SYMBOL(iounmap);
 
 EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index b6cd78c..f8d6dee 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -25,7 +25,6 @@
 /* platform dependent support */
 
 EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index f17bd1d..c6fe99e 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -53,6 +53,35 @@
 
 menu "Processor type and features"
 
+config SMP
+	bool "Symmetric multi-processing support"
+	---help---
+	  This enables support for systems with more than one CPU. If you have
+	  a system with only one CPU, like most personal computers, say N. If
+	  you have a system with more than one CPU, say Y.
+
+	  If you say N here, the kernel will run on single and multiprocessor
+	  machines, but will use only one CPU of a multiprocessor machine. If
+	  you say Y here, the kernel will run on many, but not all,
+	  singleprocessor machines. On a singleprocessor machine, the kernel
+	  will run faster if you say N here.
+
+	  Note that if you say Y here and choose architecture "586" or
+	  "Pentium" under "Processor family", the kernel will not work on 486
+	  architectures. Similarly, multiprocessor kernels for the "PPro"
+	  architecture may not work on all Pentium based boards.
+
+	  People using multiprocessor machines who say Y here should also say
+	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+	  Management" code will be disabled if you say Y here.
+
+	  See also the <file:Documentation/smp.txt>,
+	  <file:Documentation/i386/IO-APIC.txt>,
+	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  If you don't know what to do here, say N.
+
 choice
 	prompt "Subarchitecture Type"
 	default X86_PC
@@ -178,35 +207,6 @@
 	depends on HPET_TIMER && RTC=y
 	default y
 
-config SMP
-	bool "Symmetric multi-processing support"
-	---help---
-	  This enables support for systems with more than one CPU. If you have
-	  a system with only one CPU, like most personal computers, say N. If
-	  you have a system with more than one CPU, say Y.
-
-	  If you say N here, the kernel will run on single and multiprocessor
-	  machines, but will use only one CPU of a multiprocessor machine. If
-	  you say Y here, the kernel will run on many, but not all,
-	  singleprocessor machines. On a singleprocessor machine, the kernel
-	  will run faster if you say N here.
-
-	  Note that if you say Y here and choose architecture "586" or
-	  "Pentium" under "Processor family", the kernel will not work on 486
-	  architectures. Similarly, multiprocessor kernels for the "PPro"
-	  architecture may not work on all Pentium based boards.
-
-	  People using multiprocessor machines who say Y here should also say
-	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
-	  Management" code will be disabled if you say Y here.
-
-	  See also the <file:Documentation/smp.txt>,
-	  <file:Documentation/i386/IO-APIC.txt>,
-	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  If you don't know what to do here, say N.
-
 config NR_CPUS
 	int "Maximum number of CPUs (2-255)"
 	range 2 255
@@ -467,7 +467,7 @@
 
 choice
 	depends on EXPERIMENTAL && !X86_PAE
-	prompt "Memory split"
+	prompt "Memory split" if EMBEDDED
 	default VMSPLIT_3G
 	help
 	  Select the desired split between kernel and user memory.
@@ -522,6 +522,12 @@
 comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
 	depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
 
+config NODES_SHIFT
+	int
+	default "4" if X86_NUMAQ
+	default "3"
+	depends on NEED_MULTIPLE_NODES
+
 config HAVE_ARCH_BOOTMEM_NODE
 	bool
 	depends on NUMA
@@ -750,22 +756,13 @@
 
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-	depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER && !X86_PC
+	depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
 	---help---
 	  Say Y here to experiment with turning CPUs off and on.  CPUs
 	  can be controlled through /sys/devices/system/cpu.
 
 	  Say N.
 
-config DOUBLEFAULT
-	default y
-	bool "Enable doublefault exception handler" if EMBEDDED
-	help
-          This option allows trapping of rare doublefault exceptions that
-          would otherwise cause a system to silently reboot. Disabling this
-          option saves about 4k and might cause you much additional grey
-          hair.
-
 endmenu
 
 
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 79603b3..eb13048 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -311,5 +311,5 @@
 
 config X86_TSC
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
+	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ
 	default y
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 6e97df6..c92191b 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -81,4 +81,13 @@
 	depends on X86_LOCAL_APIC && !X86_VISWS
 	default y
 
+config DOUBLEFAULT
+	default y
+	bool "Enable doublefault exception handler" if EMBEDDED
+	help
+          This option allows trapping of rare doublefault exceptions that
+          would otherwise cause a system to silently reboot. Disabling this
+          option saves about 4k and might cause you much additional grey
+          hair.
+
 endmenu
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 0000a26..c9343c3 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -97,6 +97,7 @@
 #define PARAM_VESAPM_OFF	0x30
 #define PARAM_LFB_PAGES		0x32
 #define PARAM_VESA_ATTRIB	0x34
+#define PARAM_CAPABILITIES	0x36
 
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
@@ -233,6 +234,10 @@
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
 
+# store mode capabilities
+	movl 10(%di), %eax
+	movl %eax, %fs:(PARAM_CAPABILITIES)
+
 # switching the DAC to 8-bit is for <= 8 bpp only
 	movw	%fs:(PARAM_LFB_DEPTH), %ax
 	cmpw	$8, %ax
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5b9ed21..96fb8a0 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -6,7 +6,7 @@
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
-		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
+		pci-dma.o i386_ksyms.o i387.o bootflag.o \
 		quirks.o i8237.o topology.o alternative.o
 
 obj-y				+= cpu/
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 0330661..049a255 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -215,7 +215,7 @@
 {
 	struct acpi_table_madt *madt = NULL;
 
-	if (!phys_addr || !size)
+	if (!phys_addr || !size || !cpu_has_apic)
 		return -EINVAL;
 
 	madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -693,6 +693,9 @@
 {
 	int count;
 
+	if (!cpu_has_apic)
+		return -ENODEV;
+
 	/* 
 	 * Note that the LAPIC address is obtained from the MADT (32-bit value)
 	 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
@@ -751,6 +754,9 @@
 		return -ENODEV;
 	}
 
+	if (!cpu_has_apic)
+		return -ENODEV;
+
 	/*
 	 * if "noapic" boot option, don't look for IO-APICs
 	 */
@@ -1096,6 +1102,9 @@
 	dmi_check_system(acpi_dmi_table);
 #endif
 
+	if (!cpu_has_apic)
+		return -ENODEV;
+
 	/*
 	 * If acpi_disabled, bail out
 	 * One exception: acpi=ht continues far enough to enumerate LAPICs
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 6273bf7..254cee9 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,6 +62,18 @@
 
 static void apic_pm_activate(void);
 
+int modern_apic(void)
+{
+	unsigned int lvr, version;
+	/* AMD systems use old APIC versions, so check the CPU */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+		boot_cpu_data.x86 >= 0xf)
+		return 1;
+	lvr = apic_read(APIC_LVR);
+	version = GET_APIC_VERSION(lvr);
+	return version >= 0x14;
+}
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -119,10 +131,7 @@
 
 int get_physical_broadcast(void)
 {
-	unsigned int lvr, version;
-	lvr = apic_read(APIC_LVR);
-	version = GET_APIC_VERSION(lvr);
-	if (!APIC_INTEGRATED(version) || version >= 0x14)
+	if (modern_apic())
 		return 0xff;
 	else
 		return 0xf;
@@ -349,9 +358,9 @@
 
 void __init sync_Arb_IDs(void)
 {
-	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
-	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
-	if (ver >= 0x14)	/* P4 or higher */
+	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
+	   And not needed on AMD */
+	if (modern_apic())
 		return;
 	/*
 	 * Wait for idle.
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index da30a37..df0e174 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1079,7 +1079,7 @@
 			break;
 	}
 
-	if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
+	if (error == APM_NOT_ENGAGED) {
 		static int tried;
 		int eng_error;
 		if (tried++ == 0) {
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 0810f81..786d1a5 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -207,13 +207,13 @@
 		set_bit(X86_FEATURE_K7, c->x86_capability); 
 		break;
 	}
+	if (c->x86 >= 6)
+		set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
 
 	display_cacheinfo(c);
 
 	if (cpuid_eax(0x80000000) >= 0x80000008) {
 		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
-		if (c->x86_max_cores & (c->x86_max_cores - 1))
-			c->x86_max_cores = 1;
 	}
 
 	if (cpuid_eax(0x80000000) >= 0x80000007) {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 712a26b..71fffa1 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -46,7 +46,7 @@
 
 #define PFX "powernow-k8: "
 #define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.1"
+#define VERSION "version 1.60.2"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -55,7 +55,7 @@
 static struct powernow_k8_data *powernow_data[NR_CPUS];
 
 #ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL };
+static cpumask_t cpu_core_map[1];
 #endif
 
 /* Return a frequency in MHz, given an input fid */
@@ -905,11 +905,17 @@
 {
 	cpumask_t oldmask = CPU_MASK_ALL;
 	struct powernow_k8_data *data = powernow_data[pol->cpu];
-	u32 checkfid = data->currfid;
-	u32 checkvid = data->currvid;
+	u32 checkfid;
+	u32 checkvid;
 	unsigned int newstate;
 	int ret = -EIO;
 
+	if (!data)
+		return -EINVAL;
+
+	checkfid = data->currfid;
+	checkvid = data->currvid;
+
 	/* only run on specific CPU from here on */
 	oldmask = current->cpus_allowed;
 	set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
@@ -969,6 +975,9 @@
 {
 	struct powernow_k8_data *data = powernow_data[pol->cpu];
 
+	if (!data)
+		return -EINVAL;
+
 	return cpufreq_frequency_table_verify(pol, data->powernow_table);
 }
 
@@ -977,7 +986,7 @@
 {
 	struct powernow_k8_data *data;
 	cpumask_t oldmask = CPU_MASK_ALL;
-	int rc, i;
+	int rc;
 
 	if (!cpu_online(pol->cpu))
 		return -ENODEV;
@@ -1063,8 +1072,7 @@
 	printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
 	       data->currfid, data->currvid);
 
-	for_each_cpu_mask(i, cpu_core_map[pol->cpu])
-		powernow_data[i] = data;
+	powernow_data[pol->cpu] = data;
 
 	return 0;
 
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index 9df87b0..c8547a6 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -642,7 +642,7 @@
 	return;
 }
 
-static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
+static int cacheinfo_cpu_callback(struct notifier_block *nfb,
 					unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 006141d..1d9a4ab 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -168,7 +168,7 @@
 	return err;
 }
 
-static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
 
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index e3c5fca0..2b0cfce 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -69,7 +69,7 @@
 	 * for the data I pass, and I need tags
 	 * on the data to indicate what information I have
 	 * squirrelled away.  ELF notes happen to provide
-	 * all of that that no need to invent something new.
+	 * all of that, so there is no need to invent something new.
 	 */
 	buf = (u32*)per_cpu_ptr(crash_notes, cpu);
 	if (!buf)
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 0553250..036a985 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -19,7 +19,6 @@
 EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
 #ifdef CONFIG_SMP
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f197687..38806f4 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -43,7 +43,7 @@
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 /* insert a jmp code */
-static inline void set_jmp_op(void *from, void *to)
+static __always_inline void set_jmp_op(void *from, void *to)
 {
 	struct __arch_jmp_op {
 		char op;
@@ -57,7 +57,7 @@
 /*
  * returns non-zero if opcodes can be boosted.
  */
-static inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t opcode)
 {
 	switch (opcode & 0xf0 ) {
 	case 0x70:
@@ -88,7 +88,7 @@
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
 {
 	switch (opcode) {
 	case 0xfa:		/* cli */
@@ -138,7 +138,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -146,7 +146,7 @@
 	kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -154,7 +154,7 @@
 	kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -164,7 +164,7 @@
 		kcb->kprobe_saved_eflags &= ~IF_MASK;
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
 	regs->eflags |= TF_MASK;
 	regs->eflags &= ~IF_MASK;
@@ -242,10 +242,6 @@
 			kcb->kprobe_status = KPROBE_REENTER;
 			return 1;
 		} else {
-			if (regs->eflags & VM_MASK) {
-			/* We are in virtual-8086 mode. Return 0 */
-				goto no_kprobe;
-			}
 			if (*addr != BREAKPOINT_INSTRUCTION) {
 			/* The breakpoint instruction was removed by
 			 * another cpu right after we hit, no further
@@ -265,11 +261,6 @@
 
 	p = get_kprobe(addr);
 	if (!p) {
-		if (regs->eflags & VM_MASK) {
-			/* We are in virtual-8086 mode. Return 0 */
-			goto no_kprobe;
-		}
-
 		if (*addr != BREAKPOINT_INSTRUCTION) {
 			/*
 			 * The breakpoint instruction was removed right
@@ -452,10 +443,11 @@
 		*tos &= ~(TF_MASK | IF_MASK);
 		*tos |= kcb->kprobe_old_eflags;
 		break;
-	case 0xc3:		/* ret/lret */
-	case 0xcb:
-	case 0xc2:
+	case 0xc2:		/* iret/ret/lret */
+	case 0xc3:
 	case 0xca:
+	case 0xcb:
+	case 0xcf:
 	case 0xea:		/* jmp absolute -- eip is correct */
 		/* eip is already adjusted, no more changes required */
 		p->ainsn.boostable = 1;
@@ -463,10 +455,13 @@
 	case 0xe8:		/* call relative - Fix return addr */
 		*tos = orig_eip + (*tos - copy_eip);
 		break;
+	case 0x9a:		/* call absolute -- same as call absolute, indirect */
+		*tos = orig_eip + (*tos - copy_eip);
+		goto no_change;
 	case 0xff:
 		if ((p->ainsn.insn[1] & 0x30) == 0x10) {
-			/* call absolute, indirect */
 			/*
+			 * call absolute, indirect
 			 * Fix return addr; eip is correct.
 			 * But this is not boostable
 			 */
@@ -507,7 +502,7 @@
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
  * remain disabled thoroughout this function.
  */
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -543,7 +538,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 8d8aa9d..34d21e2 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -38,12 +38,6 @@
 int smp_found_config;
 unsigned int __initdata maxcpus = NR_CPUS;
 
-#ifdef CONFIG_HOTPLUG_CPU
-#define CPU_HOTPLUG_ENABLED	(1)
-#else
-#define CPU_HOTPLUG_ENABLED	(0)
-#endif
-
 /*
  * Various Linux-internal data structures created from the
  * MP-table.
@@ -110,21 +104,6 @@
 static int mpc_record; 
 static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
 
-#ifdef CONFIG_X86_NUMAQ
-static int MP_valid_apicid(int apicid, int version)
-{
-	return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
-}
-#else
-static int MP_valid_apicid(int apicid, int version)
-{
-	if (version >= 0x14)
-		return apicid < 0xff;
-	else
-		return apicid < 0xf;
-}
-#endif
-
 static void __devinit MP_processor_info (struct mpc_config_processor *m)
 {
  	int ver, apicid;
@@ -190,12 +169,6 @@
 
 	ver = m->mpc_apicver;
 
-	if (!MP_valid_apicid(apicid, ver)) {
-		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
-			m->mpc_apicid, MAX_APICS);
-		return;
-	}
-
 	/*
 	 * Validate version
 	 */
@@ -225,7 +198,14 @@
 	cpu_set(num_processors, cpu_possible_map);
 	num_processors++;
 
-	if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
+	/*
+	 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+	 * but we need to work other dependencies like SMP_SUSPEND etc
+	 * before this can be done without some confusion.
+	 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+	 *       - Ashok Raj <ashok.raj@intel.com>
+	 */
+	if (num_processors > 8) {
 		switch (boot_cpu_data.x86_vendor) {
 		case X86_VENDOR_INTEL:
 			if (!APIC_XAPIC(ver)) {
@@ -249,6 +229,13 @@
 
 	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
 
+	if (m->mpc_busid >= MAX_MP_BUSSES) {
+		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+			" is too large, max. supported is %d\n",
+			m->mpc_busid, str, MAX_MP_BUSSES - 1);
+		return;
+	}
+
 	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
 	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 1d0a55e..7a32823 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -251,7 +251,7 @@
 	return err;
 }
 
-static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
 
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 10e21a4..99aab41 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -51,7 +51,5 @@
 
 		cur->reboot_fixup(dev);
 	}
-
-	printk(KERN_WARNING "No reboot fixup found for your hardware\n");
 }
 
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index eacc3f0..80cb3b2 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -963,6 +963,36 @@
 	return 0;
 }
 
+ /*
+  * This function checks if the entire range <start,end> is mapped with type.
+  *
+  * Note: this function only works correct if the e820 table is sorted and
+  * not-overlapping, which is the case
+  */
+int __init
+e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+	int i;
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		if (type && ei->type != type)
+			continue;
+		/* is the region (part) in overlap with the current region ?*/
+		if (ei->addr >= end || ei->addr + ei->size <= start)
+			continue;
+		/* if the region is at the beginning of <start,end> we move
+		 * start to the end of the region since it's ok until there
+		 */
+		if (ei->addr <= start)
+			start = ei->addr + ei->size;
+		/* if start is now at or beyond end, we're done, full
+		 * coverage */
+		if (start >= end)
+			return 1; /* we're done */
+	}
+	return 0;
+}
+
 /*
  * Find the highest page frame number we have available
  */
@@ -1317,8 +1347,8 @@
 /*
  * Request address space for all standard resources
  *
- * This is called just before pcibios_assign_resources(), which is also
- * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
+ * This is called just before pcibios_init(), which is also a
+ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
  */
 static int __init request_standard_resources(void)
 {
@@ -1339,7 +1369,7 @@
 	return 0;
 }
 
-fs_initcall(request_standard_resources);
+subsys_initcall(request_standard_resources);
 
 static void __init register_memory(void)
 {
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index a696990..825b2b4 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -313,7 +313,9 @@
 			if (tsc_values[i] < avg)
 				realdelta = -realdelta;
 
-			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
+			if (realdelta > 0)
+				printk(KERN_INFO "CPU#%d had %ld usecs TSC "
+					"skew, fixed it up.\n", i, realdelta);
 		}
 
 		sum += delta;
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 4f58b9c..f48bef1 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -314,3 +314,4 @@
 	.long sys_get_robust_list
 	.long sys_splice
 	.long sys_sync_file_range
+	.long sys_tee			/* 315 */
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index e385279..2d22f57 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -365,6 +365,9 @@
 
 	if (++die.lock_owner_depth < 3) {
 		int nl = 0;
+		unsigned long esp;
+		unsigned short ss;
+
 		handle_BUG(regs);
 		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -387,8 +390,19 @@
 			printk("\n");
 		if (notify_die(DIE_OOPS, str, regs, err,
 					current->thread.trap_no, SIGSEGV) !=
-				NOTIFY_STOP)
+				NOTIFY_STOP) {
 			show_registers(regs);
+			/* Executive summary in case the oops scrolled away */
+			esp = (unsigned long) (&regs->esp);
+			savesegment(ss, ss);
+			if (user_mode(regs)) {
+				esp = regs->esp;
+				ss = regs->xss & 0xffff;
+			}
+			printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+			print_symbol("%s", regs->eip);
+			printk(" SS:ESP %04x:%08lx\n", ss, esp);
+		}
 		else
 			regs = NULL;
   	} else
diff --git a/arch/i386/mach-voyager/voyager_cat.c b/arch/i386/mach-voyager/voyager_cat.c
index 23967fe..10d21df 100644
--- a/arch/i386/mach-voyager/voyager_cat.c
+++ b/arch/i386/mach-voyager/voyager_cat.c
@@ -106,15 +106,20 @@
 
 /* the I/O port assignments for the VIC and QIC */
 static struct resource vic_res = {
-	"Voyager Interrupt Controller", 0xFC00, 0xFC6F };
+	.name	= "Voyager Interrupt Controller",
+	.start	= 0xFC00,
+	.end	= 0xFC6F
+};
 static struct resource qic_res = {
-	"Quad Interrupt Controller", 0xFC70, 0xFCFF };
+	.name	= "Quad Interrupt Controller",
+	.start	= 0xFC70,
+	.end	= 0xFCFF
+};
 
 /* This function is used to pack a data bit stream inside a message.
  * It writes num_bits of the data buffer in msg starting at start_bit.
  * Note: This function assumes that any unused bit in the data stream
  * is set to zero so that the ors will work correctly */
-#define BITS_PER_BYTE 8
 static void
 cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
 {
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 9f66ac5..ae6534a 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -651,6 +651,7 @@
  * Specifically, in the case of x86, we will always add
  * memory to the highmem for now.
  */
+#ifdef CONFIG_HOTPLUG_MEMORY
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 int add_memory(u64 start, u64 size)
 {
@@ -667,6 +668,7 @@
 	return -EINVAL;
 }
 #endif
+#endif
 
 kmem_cache_t *pgd_cache;
 kmem_cache_t *pmd_cache;
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 99012b9..5d81fb5 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -4,6 +4,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 #include "pci.h"
 
 /*
@@ -18,8 +19,10 @@
 {
 	unsigned long flags;
 
-	if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+	if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+		*value = -1;
 		return -EINVAL;
+	}
 
 	spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -91,8 +94,10 @@
 	unsigned long flags;
 	int dev, fn;
 
-	if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
+	if ((bus > 255) || (devfn > 255) || (reg > 255)) {
+		*value = -1;
 		return -EINVAL;
+	}
 
 	dev = PCI_SLOT(devfn);
 	fn = PCI_FUNC(devfn);
@@ -188,6 +193,10 @@
 
 	if (pci_probe & PCI_NO_CHECKS)
 		return 1;
+	/* Assume Type 1 works for newer systems.
+	   This handles machines that don't have anything on PCI Bus 0. */
+	if (dmi_get_year(DMI_BIOS_DATE) >= 2001)
+		return 1;
 
 	for (devfn = 0; devfn < 0x100; devfn++) {
 		if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 3ca59ca..06dab00 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -588,7 +588,9 @@
 	case PCI_DEVICE_ID_VIA_82C596:
 	case PCI_DEVICE_ID_VIA_82C686:
 	case PCI_DEVICE_ID_VIA_8231:
+	case PCI_DEVICE_ID_VIA_8233A:
 	case PCI_DEVICE_ID_VIA_8235:
+	case PCI_DEVICE_ID_VIA_8237:
 		/* FIXME: add new ones for 8233/5 */
 		r->name = "VIA";
 		r->get = pirq_via_get;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 6137890..6b1ea0c 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,14 +12,20 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <asm/e820.h>
 #include "pci.h"
 
+#define MMCONFIG_APER_SIZE (256*1024*1024)
+
+/* Assume systems with more busses have correct MCFG */
+#define MAX_CHECK_BUS 16
+
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
 
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
 
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
@@ -29,8 +35,8 @@
 	int cfg_num = -1;
 	struct acpi_table_mcfg_config *cfg;
 
-	if (seg == 0 && bus == 0 &&
-	    test_bit(PCI_SLOT(devfn), fallback_slots))
+	if (seg == 0 && bus < MAX_CHECK_BUS &&
+	    test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
 		return 0;
 
 	while (1) {
@@ -74,8 +80,10 @@
 	unsigned long flags;
 	u32 base;
 
-	if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
+	if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
+		*value = -1;
 		return -EINVAL;
+	}
 
 	base = get_base_addr(seg, bus, devfn);
 	if (!base)
@@ -146,29 +154,34 @@
    Normally this can be expressed in the MCFG by not listing them
    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
    Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them.
-   We only do this for bus 0/seg 0 */
+   and fallback for them. */
 static __init void unreachable_devices(void)
 {
-	int i;
+	int i, k;
 	unsigned long flags;
 
-	for (i = 0; i < 32; i++) {
-		u32 val1;
-		u32 addr;
+	for (k = 0; k < MAX_CHECK_BUS; k++) {
+		for (i = 0; i < 32; i++) {
+			u32 val1;
+			u32 addr;
 
-		pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
-		if (val1 == 0xffffffff)
-			continue;
+			pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
+			if (val1 == 0xffffffff)
+				continue;
 
-		/* Locking probably not needed, but safer */
-		spin_lock_irqsave(&pci_config_lock, flags);
-		addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
-		if (addr != 0)
-			pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
-		if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
-			set_bit(i, fallback_slots);
-		spin_unlock_irqrestore(&pci_config_lock, flags);
+			/* Locking probably not needed, but safer */
+			spin_lock_irqsave(&pci_config_lock, flags);
+			addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
+			if (addr != 0)
+				pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
+			if (addr == 0 ||
+			    readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
+				set_bit(i, fallback_slots);
+				printk(KERN_NOTICE
+			"PCI: No mmconfig possible on %x:%x\n", k, i);
+			}
+			spin_unlock_irqrestore(&pci_config_lock, flags);
+		}
 	}
 }
 
@@ -183,6 +196,14 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
+	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			E820_RESERVED)) {
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+		return;
+	}
+
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	raw_pci_ops = &pci_mmcfg;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index edffe25..0f3076a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -260,15 +260,6 @@
 	  than 64 will cause the use of a CPU mask array, causing a small
 	  performance hit.
 
-config IA64_NR_NODES
-	int "Maximum number of NODEs (256-1024)" if (IA64_SGI_SN2 || IA64_GENERIC)
-	range 256 1024
-	depends on IA64_SGI_SN2 || IA64_GENERIC
-	default "256"
-	help
-	  This option specifies the maximum number of nodes in your SSI system.
-	  If in doubt, use the default.
-
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
 	depends on SMP && EXPERIMENTAL
@@ -352,6 +343,16 @@
 	  Access).  This option is for configuring high-end multiprocessor
 	  server systems.  If in doubt, say N.
 
+config NODES_SHIFT
+	int "Max num nodes shift(3-10)"
+	range 3 10
+	default "8"
+	depends on NEED_MULTIPLE_NODES
+	help
+	  This option specifies the maximum number of nodes in your SSI system.
+	  MAX_NUMNODES will be 2^(This value).
+	  If in doubt, use the default.
+
 # VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
 # VIRTUAL_MEM_MAP has been retained for historical reasons.
 config VIRTUAL_MEM_MAP
@@ -412,6 +413,8 @@
 config SGI_SN
 	def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
 
+source "drivers/sn/Kconfig"
+
 source "drivers/firmware/Kconfig"
 
 source "fs/Kconfig.binfmt"
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index a718034..f6a8853 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc5
-# Mon Feb 27 16:06:38 2006
+# Linux kernel version: 2.6.17-rc3
+# Thu Apr 27 11:48:23 2006
 #
 
 #
@@ -24,6 +24,7 @@
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_CPUSETS=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -38,10 +39,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -53,7 +50,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -62,6 +58,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -84,8 +81,10 @@
 CONFIG_MMU=y
 CONFIG_SWIOTLB=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_TIME_INTERPOLATION=y
+CONFIG_DMI=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
@@ -116,7 +115,6 @@
 CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
 CONFIG_NR_CPUS=1024
-CONFIG_IA64_NR_NODES=256
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_SCHED_SMT=y
 CONFIG_PREEMPT=y
@@ -136,6 +134,7 @@
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
 CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=8
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
@@ -187,7 +186,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -231,6 +229,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_TCP_DIAG=m
@@ -238,9 +237,11 @@
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
@@ -468,9 +469,14 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
-# CONFIG_SCSI_QLA_FC is not set
+CONFIG_SCSI_QLA_FC=y
+CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
+# CONFIG_SCSI_QLA21XX is not set
+CONFIG_SCSI_QLA22XX=y
+CONFIG_SCSI_QLA2300=y
+CONFIG_SCSI_QLA2322=y
+# CONFIG_SCSI_QLA24XX is not set
 # CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -486,6 +492,7 @@
 CONFIG_MD_RAID1=y
 # CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=y
 # CONFIG_MD_FAULTY is not set
@@ -694,6 +701,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=y
+# CONFIG_AGP_VIA is not set
 CONFIG_AGP_SGI_TIOCA=y
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=m
@@ -735,10 +743,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -747,6 +751,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -757,6 +762,7 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -769,6 +775,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -829,9 +836,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -846,15 +851,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -905,15 +901,29 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
 # CONFIG_INFINIBAND_USER_MAD is not set
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SRP=m
 
 #
@@ -923,10 +933,15 @@
 CONFIG_SGI_IOC3=y
 
 #
-# EDAC - error detection and reporting (RAS)
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -997,7 +1012,6 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index 4e7a6a1..da03c06 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -35,6 +35,9 @@
 
 static void elf32_set_personality (void);
 
+static unsigned long __attribute ((unused))
+randomize_stack_top(unsigned long stack_top);
+
 #define setup_arg_pages(bprm,tos,exec)		ia32_setup_arg_pages(bprm,exec)
 #define elf_map				elf32_map
 
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 95fe044..a32cd59 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -334,7 +334,7 @@
 	data8 sys_setdomainname
 	data8 sys32_newuname
 	data8 sys32_modify_ldt
-	data8 sys_ni_syscall	/* adjtimex */
+	data8 compat_sys_adjtimex
 	data8 sys32_mprotect	  /* 125 */
 	data8 compat_sys_sigprocmask
 	data8 sys_ni_syscall	/* create_module */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 59e871d..09a0dbc 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -7,7 +7,7 @@
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
 	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
-	 unwind.o mca.o mca_asm.o topology.o dmi_scan.o
+	 unwind.o mca.o mca_asm.o topology.o
 
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
 obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
@@ -30,7 +30,6 @@
 obj-$(CONFIG_KPROBES)		+= kprobes.o jprobes.o
 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)	+= uncached.o
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
-dmi_scan-y			+= ../../i386/kernel/dmi_scan.o
 
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index 4a5574f..fff8292 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -1,105 +1,104 @@
 /*
- * arch/ia64/kernel/acpi-ext.c
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ *	Alex Williamson <alex.williamson@hp.com>
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
- *
- * Vendor specific extensions to ACPI.
+ * 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/module.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
-#include <linux/efi.h>
 
 #include <asm/acpi-ext.h>
 
-struct acpi_vendor_descriptor {
-	u8 guid_id;
-	efi_guid_t guid;
+/*
+ * Device CSRs that do not appear in PCI config space should be described
+ * via ACPI.  This would normally be done with Address Space Descriptors
+ * marked as "consumer-only," but old versions of Windows and Linux ignore
+ * the producer/consumer flag, so HP invented a vendor-defined resource to
+ * describe the location and size of CSR space.
+ */
+
+struct acpi_vendor_uuid hp_ccsr_uuid = {
+	.subtype = 2,
+	.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
+	    0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
 };
 
-struct acpi_vendor_info {
-	struct acpi_vendor_descriptor *descriptor;
-	u8 *data;
-	u32 length;
-};
-
-acpi_status
-acpi_vendor_resource_match(struct acpi_resource *resource, void *context)
-{
-	struct acpi_vendor_info *info = (struct acpi_vendor_info *)context;
-	struct acpi_resource_vendor *vendor;
-	struct acpi_vendor_descriptor *descriptor;
-	u32 byte_length;
-
-	if (resource->type != ACPI_RESOURCE_TYPE_VENDOR)
-		return AE_OK;
-
-	vendor = (struct acpi_resource_vendor *)&resource->data;
-	descriptor = (struct acpi_vendor_descriptor *)vendor->byte_data;
-	if (vendor->byte_length <= sizeof(*info->descriptor) ||
-	    descriptor->guid_id != info->descriptor->guid_id ||
-	    efi_guidcmp(descriptor->guid, info->descriptor->guid))
-		return AE_OK;
-
-	byte_length = vendor->byte_length - sizeof(struct acpi_vendor_descriptor);
-	info->data = acpi_os_allocate(byte_length);
-	if (!info->data)
-		return AE_NO_MEMORY;
-
-	memcpy(info->data,
-	       vendor->byte_data + sizeof(struct acpi_vendor_descriptor),
-	       byte_length);
-	info->length = byte_length;
-	return AE_CTRL_TERMINATE;
-}
-
-acpi_status
-acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor * id,
-			  u8 ** data, u32 * byte_length)
-{
-	struct acpi_vendor_info info;
-
-	info.descriptor = id;
-	info.data = NULL;
-
-	acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match,
-			    &info);
-	if (!info.data)
-		return AE_NOT_FOUND;
-
-	*data = info.data;
-	*byte_length = info.length;
-	return AE_OK;
-}
-
-struct acpi_vendor_descriptor hp_ccsr_descriptor = {
-	.guid_id = 2,
-	.guid =
-	    EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01,
-		     0x37, 0x0e, 0xad)
-};
-
-acpi_status hp_acpi_csr_space(acpi_handle obj, u64 * csr_base, u64 * csr_length)
+static acpi_status hp_ccsr_locate(acpi_handle obj, u64 *base, u64 *length)
 {
 	acpi_status status;
-	u8 *data;
-	u32 length;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_resource *resource;
+	struct acpi_resource_vendor_typed *vendor;
 
-	status =
-	    acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
+	status = acpi_get_vendor_resource(obj, METHOD_NAME__CRS, &hp_ccsr_uuid,
+		&buffer);
 
-	if (ACPI_FAILURE(status) || length != 16)
+	resource = buffer.pointer;
+	vendor = &resource->data.vendor_typed;
+
+	if (ACPI_FAILURE(status) || vendor->byte_length < 16) {
+		status = AE_NOT_FOUND;
+		goto exit;
+	}
+
+	memcpy(base, vendor->byte_data, sizeof(*base));
+	memcpy(length, vendor->byte_data + 8, sizeof(*length));
+
+  exit:
+	acpi_os_free(buffer.pointer);
+	return status;
+}
+
+struct csr_space {
+	u64	base;
+	u64	length;
+};
+
+static acpi_status find_csr_space(struct acpi_resource *resource, void *data)
+{
+	struct csr_space *space = data;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+
+	status = acpi_resource_to_address64(resource, &addr);
+	if (ACPI_SUCCESS(status) &&
+	    addr.resource_type == ACPI_MEMORY_RANGE &&
+	    addr.address_length &&
+	    addr.producer_consumer == ACPI_CONSUMER) {
+		space->base = addr.minimum;
+		space->length = addr.address_length;
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;		/* keep looking */
+}
+
+static acpi_status hp_crs_locate(acpi_handle obj, u64 *base, u64 *length)
+{
+	struct csr_space space = { 0, 0 };
+
+	acpi_walk_resources(obj, METHOD_NAME__CRS, find_csr_space, &space);
+	if (!space.length)
 		return AE_NOT_FOUND;
 
-	memcpy(csr_base, data, sizeof(*csr_base));
-	memcpy(csr_length, data + 8, sizeof(*csr_length));
-	acpi_os_free(data);
-
+	*base = space.base;
+	*length = space.length;
 	return AE_OK;
 }
 
+acpi_status hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+{
+	acpi_status status;
+
+	status = hp_ccsr_locate(obj, csr_base, csr_length);
+	if (ACPI_SUCCESS(status))
+		return status;
+
+	return hp_crs_locate(obj, csr_base, csr_length);
+}
 EXPORT_SYMBOL(hp_acpi_csr_space);
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 750e8e7..bcb80ca 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1606,5 +1606,10 @@
 	data8 sys_ni_syscall			// 1295 reserved for ppoll
 	data8 sys_unshare
 	data8 sys_splice
+	data8 sys_set_robust_list
+	data8 sys_get_robust_list
+	data8 sys_sync_file_range		// 1300
+	data8 sys_tee
+	data8 sys_vmsplice
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 789881c..f9039f8 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -251,7 +251,7 @@
 	update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
 }
 
-static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
 	       	unsigned long *kprobe_inst, uint *major_opcode)
 {
 	unsigned long kprobe_inst_p0, kprobe_inst_p1;
@@ -278,7 +278,7 @@
 }
 
 /* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
+static int __kprobes in_ivt_functions(unsigned long addr)
 {
 	return (addr >= (unsigned long)__start_ivt_text
 		&& addr < (unsigned long)__end_ivt_text);
@@ -308,19 +308,19 @@
 	return 0;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
-static inline void set_current_kprobe(struct kprobe *p,
+static void __kprobes set_current_kprobe(struct kprobe *p,
 			struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 8963171..6a08806 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -581,10 +581,12 @@
 {
 	unsigned long flags;
 	int cpu = smp_processor_id();
+	struct ia64_mca_notify_die nd =
+		{ .sos = NULL, .monarch_cpu = &monarch_cpu };
 
 	/* Mask all interrupts */
 	local_irq_save(flags);
-	if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, 0, 0, 0)
+	if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -594,7 +596,7 @@
 	 */
 	ia64_sal_mc_rendez();
 
-	if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, 0, 0, 0)
+	if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -602,7 +604,7 @@
 	while (monarch_cpu != -1)
 	       cpu_relax();	/* spin until monarch leaves */
 
-	if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, 0, 0, 0)
+	if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -961,7 +963,7 @@
  */
 
 static void
-ia64_wait_for_slaves(int monarch)
+ia64_wait_for_slaves(int monarch, const char *type)
 {
 	int c, wait = 0, missing = 0;
 	for_each_online_cpu(c) {
@@ -987,7 +989,7 @@
 	}
 	if (!missing)
 		goto all_in;
-	printk(KERN_INFO "OS MCA slave did not rendezvous on cpu");
+	printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
 	for_each_online_cpu(c) {
 		if (c == monarch)
 			continue;
@@ -998,7 +1000,7 @@
 	return;
 
 all_in:
-	printk(KERN_INFO "All OS MCA slaves have reached rendezvous\n");
+	printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
 	return;
 }
 
@@ -1023,6 +1025,8 @@
 		&sos->proc_state_param;
 	int recover, cpu = smp_processor_id();
 	task_t *previous_current;
+	struct ia64_mca_notify_die nd =
+		{ .sos = sos, .monarch_cpu = &monarch_cpu };
 
 	oops_in_progress = 1;	/* FIXME: make printk NMI/MCA/INIT safe */
 	console_loglevel = 15;	/* make sure printks make it to console */
@@ -1031,10 +1035,10 @@
 
 	previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
 	monarch_cpu = cpu;
-	if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, 0, 0, 0)
+	if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
-	ia64_wait_for_slaves(cpu);
+	ia64_wait_for_slaves(cpu, "MCA");
 
 	/* Wakeup all the processors which are spinning in the rendezvous loop.
 	 * They will leave SAL, then spin in the OS with interrupts disabled
@@ -1043,7 +1047,7 @@
 	 * spinning in SAL does not work.
 	 */
 	ia64_mca_wakeup_all();
-	if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, 0, 0, 0)
+	if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -1064,7 +1068,7 @@
 		ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
 		sos->os_status = IA64_MCA_CORRECTED;
 	}
-	if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, 0, 0, recover)
+	if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -1351,10 +1355,14 @@
 	static atomic_t monarchs;
 	task_t *previous_current;
 	int cpu = smp_processor_id();
+	struct ia64_mca_notify_die nd =
+		{ .sos = sos, .monarch_cpu = &monarch_cpu };
 
 	oops_in_progress = 1;	/* FIXME: make printk NMI/MCA/INIT safe */
 	console_loglevel = 15;	/* make sure printks make it to console */
 
+	(void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
+
 	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
 		sos->proc_state_param, cpu, sos->monarch);
 	salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
@@ -1390,15 +1398,15 @@
 		ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
 		while (monarch_cpu == -1)
 		       cpu_relax();	/* spin until monarch enters */
-		if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, 0, 0, 0)
+		if (notify_die(DIE_INIT_SLAVE_ENTER, "INIT", regs, (long)&nd, 0, 0)
 				== NOTIFY_STOP)
 			ia64_mca_spin(__FUNCTION__);
-		if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, 0, 0, 0)
+		if (notify_die(DIE_INIT_SLAVE_PROCESS, "INIT", regs, (long)&nd, 0, 0)
 				== NOTIFY_STOP)
 			ia64_mca_spin(__FUNCTION__);
 		while (monarch_cpu != -1)
 		       cpu_relax();	/* spin until monarch leaves */
-		if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, 0, 0, 0)
+		if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
 				== NOTIFY_STOP)
 			ia64_mca_spin(__FUNCTION__);
 		printk("Slave on cpu %d returning to normal service.\n", cpu);
@@ -1409,7 +1417,7 @@
 	}
 
 	monarch_cpu = cpu;
-	if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, 0, 0, 0)
+	if (notify_die(DIE_INIT_MONARCH_ENTER, "INIT", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 
@@ -1421,15 +1429,15 @@
 	 */
 	printk("Delaying for 5 seconds...\n");
 	udelay(5*1000000);
-	ia64_wait_for_slaves(cpu);
+	ia64_wait_for_slaves(cpu, "INIT");
 	/* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
 	 * to default_monarch_init_process() above and just print all the
 	 * tasks.
 	 */
-	if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, 0, 0, 0)
+	if (notify_die(DIE_INIT_MONARCH_PROCESS, "INIT", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
-	if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, 0, 0, 0)
+	if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
 			== NOTIFY_STOP)
 		ia64_mca_spin(__FUNCTION__);
 	printk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
@@ -1631,6 +1639,7 @@
 			printk(KERN_INFO "Increasing MCA rendezvous timeout from "
 				"%ld to %ld milliseconds\n", timeout, isrv.v0);
 			timeout = isrv.v0;
+			(void) notify_die(DIE_MCA_NEW_TIMEOUT, "MCA", NULL, timeout, 0, 0);
 			continue;
 		}
 		printk(KERN_ERR "Failed to register rendezvous interrupt "
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 60a464b..6dff024 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -827,7 +827,7 @@
 	ld8 r9=[temp2],16	// sal_gp
 	;;
 	ld8 r22=[temp1],16	// pal_min_state, virtual
-	ld8 r21=[temp2],16	// prev_IA64_KR_CURRENT
+	ld8 r13=[temp2],16	// prev_IA64_KR_CURRENT
 	;;
 	ld8 r16=[temp1],16	// prev_IA64_KR_CURRENT_STACK
 	ld8 r20=[temp2],16	// prev_task
@@ -848,7 +848,7 @@
 	mov cr.iim=temp3
 	mov cr.iha=temp4
 	dep r22=0,r22,62,1	// pal_min_state, physical, uncached
-	mov IA64_KR(CURRENT)=r21
+	mov IA64_KR(CURRENT)=r13
 	ld8 r8=[temp1]		// os_status
 	ld8 r10=[temp2]		// context
 
@@ -856,7 +856,7 @@
 	 * avoid any dependencies on the algorithm in ia64_switch_to(), just
 	 * purge any existing CURRENT_STACK mapping and insert the new one.
 	 *
-	 * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains
+	 * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains
 	 * prev_IA64_KR_CURRENT, these values may have been changed by the C
 	 * code.  Do not use r8, r9, r10, r22, they contain values ready for
 	 * the return to SAL.
@@ -873,7 +873,7 @@
 	;;
 	srlz.d
 
-	extr.u r19=r21,61,3			// r21 = prev_IA64_KR_CURRENT
+	extr.u r19=r13,61,3			// r13 = prev_IA64_KR_CURRENT
 	shl r20=r16,IA64_GRANULE_SHIFT		// r16 = prev_IA64_KR_CURRENT_STACK
 	movl r21=PAGE_KERNEL			// page properties
 	;;
@@ -883,7 +883,7 @@
 (p6)	br.spnt 1f				// the dreaded cpu 0 idle task in region 5:(
 	;;
 	mov cr.itir=r18
-	mov cr.ifa=r21
+	mov cr.ifa=r13
 	mov r20=IA64_TR_CURRENT_STACK
 	;;
 	itr.d dtr[r20]=r21
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 37c88eb..ca6666b 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -62,6 +62,11 @@
 	ISOLATE_NONE
 } isolate_status_t;
 
+typedef enum {
+	MCA_NOT_RECOVERED = 0,
+	MCA_RECOVERED	  = 1
+} recovery_status_t;
+
 /*
  *  This pool keeps pointers to the section part of SAL error record
  */
@@ -71,6 +76,18 @@
 	int	     max_idx; /* Maximum index of section pointer list pool */
 } slidx_pool;
 
+static int
+fatal_mca(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vprintk(fmt, args);
+	va_end(args);
+
+	return MCA_NOT_RECOVERED;
+}
+
 /**
  * mca_page_isolate - isolate a poisoned page in order not to use it later
  * @paddr:	poisoned memory location
@@ -424,7 +441,7 @@
 
 	/* Is target address valid? */
 	if (!pbci->tv)
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
 
 	/*
 	 * cpu read or memory-mapped io read
@@ -442,7 +459,7 @@
 
 	/* Is minstate valid? */
 	if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
 	psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
 	psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
 
@@ -476,12 +493,13 @@
 			psr2->bn  = 1;
 			psr2->i  = 0;
 
-			return 1;
+			return MCA_RECOVERED;
 		}
 
 	}
 
-	return 0;
+	return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
+			  " iip 0x%lx\n", pmsa->pmsa_iip);
 }
 
 /**
@@ -567,13 +585,13 @@
 	 * The machine check is corrected.
 	 */
 	if (psp->cm == 1)
-		return 1;
+		return MCA_RECOVERED;
 
 	/*
 	 * The error was not contained.  Software must be reset.
 	 */
 	if (psp->us || psp->ci == 0)
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: error not contained\n");
 
 	/*
 	 * The cache check and bus check bits have four possible states
@@ -584,20 +602,22 @@
 	 *    1  1	Memory error, attempt recovery
 	 */
 	if (psp->bc == 0 || pbci == NULL)
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: No bus check\n");
 
 	/*
 	 * Sorry, we cannot handle so many.
 	 */
 	if (peidx_bus_check_num(peidx) > 1)
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
 	/*
 	 * Well, here is only one bus error.
 	 */
-	if (pbci->ib || pbci->cc)
-		return 0;
+	if (pbci->ib)
+		return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+	if (pbci->cc)
+		return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
 	if (pbci->eb && pbci->bsi > 0)
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
 
 	/*
 	 * This is a local MCA and estimated as recoverble external bus error.
@@ -609,7 +629,7 @@
 	/*
 	 * On account of strange SAL error record, we cannot recover.
 	 */
-	return 0;
+	return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
 }
 
 /**
@@ -638,12 +658,10 @@
 
 	 /* Now, OS can recover when there is one processor error section */
 	if (n_proc_err > 1)
-		return 0;
-	else if (n_proc_err == 0) {
+		return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+	else if (n_proc_err == 0)
 		/* Weird SAL record ... We need not to recover */
-
-		return 1;
-	}
+		return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
 
 	/* Make index of processor error section */
 	mca_make_peidx((sal_log_processor_info_t*)
@@ -654,7 +672,7 @@
 
 	/* Check whether MCA is global or not */
 	if (is_mca_global(&peidx, &pbci, sos))
-		return 0;
+		return fatal_mca(KERN_ALERT "MCA: global MCA\n");
 	
 	/* Try to recover a processor error */
 	return recover_from_processor_error(platform_err, &slidx, &peidx,
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 7a2f0a7..3a30cfc 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -947,7 +947,7 @@
 percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
 {
 	unsigned int i;
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		memcpy(pcpudst + __per_cpu_offset[i], src, size);
 	}
 }
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 6386f63..859fb37 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -959,7 +959,7 @@
 	}
 }
 
-static int __devinit palinfo_cpu_callback(struct notifier_block *nfb,
+static int palinfo_cpu_callback(struct notifier_block *nfb,
 								unsigned long action,
 								void *hcpu)
 {
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 9d5a823..663a186 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -572,7 +572,7 @@
 };
 
 #ifdef	CONFIG_HOTPLUG_CPU
-static int __devinit
+static int
 salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 {
 	unsigned int i, cpu = (unsigned long)hcpu;
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index b47476d..4f3a16b 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -305,13 +305,10 @@
 
 static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu)
 {
-	if (all_cpu_cache_info[cpu].cache_leaves) {
-		kfree(all_cpu_cache_info[cpu].cache_leaves);
-		all_cpu_cache_info[cpu].cache_leaves = NULL;
-	}
+	kfree(all_cpu_cache_info[cpu].cache_leaves);
+	all_cpu_cache_info[cpu].cache_leaves = NULL;
 	all_cpu_cache_info[cpu].num_cache_leaves = 0;
 	memset(&all_cpu_cache_info[cpu].kobj, 0, sizeof(struct kobject));
-
 	return;
 }
 
@@ -429,7 +426,7 @@
  * When a cpu is hot-plugged, do a check and initiate
  * cache kobject if necessary
  */
-static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
+static int cache_cpu_callback(struct notifier_block *nfb,
 		unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index ec9eeb8..b6bcc9f 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -519,6 +519,68 @@
 }
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+	unsigned long end_address, hole_next_pfn;
+	unsigned long stop_address;
+
+	end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
+	end_address = PAGE_ALIGN(end_address);
+
+	stop_address = (unsigned long) &vmem_map[
+		pgdat->node_start_pfn + pgdat->node_spanned_pages];
+
+	do {
+		pgd_t *pgd;
+		pud_t *pud;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		pgd = pgd_offset_k(end_address);
+		if (pgd_none(*pgd)) {
+			end_address += PGDIR_SIZE;
+			continue;
+		}
+
+		pud = pud_offset(pgd, end_address);
+		if (pud_none(*pud)) {
+			end_address += PUD_SIZE;
+			continue;
+		}
+
+		pmd = pmd_offset(pud, end_address);
+		if (pmd_none(*pmd)) {
+			end_address += PMD_SIZE;
+			continue;
+		}
+
+		pte = pte_offset_kernel(pmd, end_address);
+retry_pte:
+		if (pte_none(*pte)) {
+			end_address += PAGE_SIZE;
+			pte++;
+			if ((end_address < stop_address) &&
+			    (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
+				goto retry_pte;
+			continue;
+		}
+		/* Found next valid vmem_map page */
+		break;
+	} while (end_address < stop_address);
+
+	end_address = min(end_address, stop_address);
+	end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
+	hole_next_pfn = end_address / sizeof(struct page);
+	return hole_next_pfn - pgdat->node_start_pfn;
+}
+#else
+static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
+{
+	return i + 1;
+}
+#endif
+
 /**
  * show_mem - give short summary of memory stats
  *
@@ -547,8 +609,10 @@
 			struct page *page;
 			if (pfn_valid(pgdat->node_start_pfn + i))
 				page = pfn_to_page(pgdat->node_start_pfn + i);
-			else
+			else {
+				i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
 				continue;
+			}
 			if (PageReserved(page))
 				reserved++;
 			else if (PageSwapCache(page))
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index af7eb08..d98ec49 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -60,6 +60,9 @@
 	struct siginfo si;
 	unsigned long mask;
 
+	/* mmap_sem is performance critical.... */
+	prefetchw(&mm->mmap_sem);
+
 	/*
 	 * If we're in an interrupt or have no user context, we must not take the fault..
 	 */
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 9ba32b2..ab829a2 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -31,7 +31,6 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
-
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
@@ -707,7 +706,7 @@
  *
  * Simply writes @size bytes of @val to @port.
  */
-int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
+int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
 {
 	int ret = size;
 
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index d917afa..739c948 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -284,6 +284,8 @@
 	/* find nearest node with cpus and nearest memory */
 	for (router=NULL, j=0; j < op->ports; j++) {
 		dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id);
+		if (dest && SN_HWPERF_IS_ROUTER(dest))
+			router = dest;
 		if (!dest || SN_HWPERF_FOREIGN(dest) ||
 		    !SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
 			continue;
@@ -299,8 +301,6 @@
 				*near_mem_node = c;
 			found_mem++;
 		}
-		if (SN_HWPERF_IS_ROUTER(dest))
-			router = dest;
 	}
 
 	if (router && (!found_cpu || !found_mem)) {
@@ -493,7 +493,7 @@
 		 * numalink ports
 		 */
 		sz = obj->ports * sizeof(struct sn_hwperf_port_info);
-		if ((ptdata = vmalloc(sz)) == NULL)
+		if ((ptdata = kmalloc(sz, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 		e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
 				      SN_HWPERF_ENUM_PORTS, obj->id, sz,
@@ -541,7 +541,7 @@
 				(SN_HWPERF_IS_NL3ROUTER(obj) ||
 				SN_HWPERF_IS_NL3ROUTER(p)) ?  "LLP3" : "LLP4");
 		}
-		vfree(ptdata);
+		kfree(ptdata);
 	}
 
 	return 0;
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index d0abddd..8255a9b 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -1831,7 +1831,7 @@
 {
 	struct xpc_partition *part = &xpc_partitions[partid];
 	enum xpc_retval ret = xpcUnknownReason;
-	struct xpc_msg *msg;
+	struct xpc_msg *msg = NULL;
 
 
 	DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 9421142..2a89cfc 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -136,9 +136,7 @@
 		}
 
 		if (L1_CACHE_ALIGN(len) > buf_len) {
-			if (buf_base != NULL) {
-				kfree(buf_base);
-			}
+			kfree(buf_base);
 			buf_len = L1_CACHE_ALIGN(len);
 			buf = (u64) xpc_kmalloc_cacheline_aligned(buf_len,
 							GFP_KERNEL, &buf_base);
@@ -159,9 +157,7 @@
 		}
 	}
 
-	if (buf_base != NULL) {
-		kfree(buf_base);
-	}
+	kfree(buf_base);
 
 	if (status != SALRET_OK) {
 		rp_pa = 0;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index fa073cc..8332956 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -682,9 +682,6 @@
 	int ate_index, last_ate, ps;
 	struct tioce *ce_mmr;
 
-	if (!TIOCE_M32_ADDR(base))
-		return;
-
 	ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
 	ps = ce_kern->ce_ate3240_pagesize;
 	ate_index = ATE_PAGE(base, ps);
@@ -693,6 +690,9 @@
 	if (ate_index < 64)
 		ate_index = 64;
 
+	if (last_ate >= TIOCE_NUM_M3240_ATES)
+		last_ate = TIOCE_NUM_M3240_ATES - 1;
+
 	while (ate_index <= last_ate) {
 		u64 ate;
 
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 05c864c..41fd490 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -285,6 +285,11 @@
 	depends on SMP && BROKEN
 	default n
 
+config NODES_SHIFT
+	int
+	default "1"
+	depends on NEED_MULTIPLE_NODES
+
 # turning this on wastes a bunch of space.
 # Summit needs it only when NUMA is on
 config BOOT_IOREMAP
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 3871b65..920bb74 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -20,7 +20,7 @@
  * Stack layout in 'ret_from_system_call':
  * 	ptrace needs to have all regs on the stack.
  *	if the order here is changed, it needs to be
- *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	updated in fork.c:copy_thread, signal.c:do_signal,
  *	ptrace.c and ptrace.h
  *
  * M32Rx/M32R2				M32R
@@ -41,18 +41,17 @@
  *       @(0x38,sp) - syscall_nr	ditto
  *       @(0x3c,sp) - acc0h		@(0x3c,sp) - acch
  *       @(0x40,sp) - acc0l		@(0x40,sp) - accl
- *       @(0x44,sp) - acc1h		@(0x44,sp) - psw
- *       @(0x48,sp) - acc1l		@(0x48,sp) - bpc
- *       @(0x4c,sp) - psw		@(0x4c,sp) - bbpsw
- *       @(0x50,sp) - bpc		@(0x50,sp) - bbpc
- *       @(0x54,sp) - bbpsw		@(0x54,sp) - spu (cr3)
- *       @(0x58,sp) - bbpc		@(0x58,sp) - fp (r13)
- *       @(0x5c,sp) - spu (cr3)		@(0x5c,sp) - lr (r14)
- *       @(0x60,sp) - fp (r13)		@(0x60,sp) - spi (cr12)
- *       @(0x64,sp) - lr (r14)		@(0x64,sp) - orig_r0
- *       @(0x68,sp) - spi (cr2)
- *       @(0x6c,sp) - orig_r0
- *
+ *       @(0x44,sp) - acc1h		@(0x44,sp) - dummy_acc1h
+ *       @(0x48,sp) - acc1l		@(0x48,sp) - dummy_acc1l
+ *       @(0x4c,sp) - psw		ditto
+ *       @(0x50,sp) - bpc		ditto
+ *       @(0x54,sp) - bbpsw		ditto
+ *       @(0x58,sp) - bbpc		ditto
+ *       @(0x5c,sp) - spu (cr3)		ditto
+ *       @(0x60,sp) - fp (r13)		ditto
+ *       @(0x64,sp) - lr (r14)		ditto
+ *       @(0x68,sp) - spi (cr2)		ditto
+ *       @(0x6c,sp) - orig_r0		ditto
  */
 
 #include <linux/config.h>
@@ -102,6 +101,12 @@
 #define ACC0L(reg)		@(0x40,reg)
 #define ACC1H(reg)		@(0x44,reg)
 #define ACC1L(reg)		@(0x48,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg)		@(0x3C,reg)
+#define ACCL(reg)		@(0x40,reg)
+#else
+#error unknown isa configuration
+#endif
 #define PSW(reg)		@(0x4C,reg)
 #define BPC(reg)		@(0x50,reg)
 #define BBPSW(reg)		@(0x54,reg)
@@ -111,21 +116,6 @@
 #define LR(reg)			@(0x64,reg)
 #define SP(reg)			@(0x68,reg)
 #define ORIG_R0(reg)		@(0x6C,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg)		@(0x3C,reg)
-#define ACCL(reg)		@(0x40,reg)
-#define PSW(reg)		@(0x44,reg)
-#define BPC(reg)		@(0x48,reg)
-#define BBPSW(reg)		@(0x4C,reg)
-#define BBPC(reg)		@(0x50,reg)
-#define SPU(reg)		@(0x54,reg)
-#define FP(reg)			@(0x58,reg)  /* FP = R13 */
-#define LR(reg)			@(0x5C,reg)
-#define SP(reg)			@(0x60,reg)
-#define ORIG_R0(reg)		@(0x64,reg)
-#else
-#error unknown isa configuration
-#endif
 
 CF_MASK		= 0x00000001
 TF_MASK		= 0x00000100
@@ -142,7 +132,7 @@
 #endif
 
 ENTRY(ret_from_fork)
-	ld	r0, @sp+
+	pop	r0
 	bl	schedule_tail
 	GET_THREAD_INFO(r8)
 	bra	syscall_exit
@@ -231,7 +221,7 @@
 	RESTORE_ALL
 
 	# perform work that needs to be done immediately before resumption
-	# r9 : frags
+	# r9 : flags
 	ALIGN
 work_pending:
 	and3	r4, r9, #_TIF_NEED_RESCHED
@@ -320,7 +310,7 @@
 ;    GET_ICU_STATUS;
 	seth	r0, #shigh(M32R_ICU_ISTS_ADDR)
 	ld	r0, @(low(M32R_ICU_ISTS_ADDR),r0)
-	st	r0, @-sp
+	push	r0
 #if defined(CONFIG_SMP)
 	/*
 	 * If IRQ == 0      --> Nothing to do,  Not write IMASK
@@ -557,7 +547,7 @@
 #endif  /* CONFIG_PLAT_M32104UT */
 	bl	do_IRQ
 #endif  /* CONFIG_SMP */
-	ld	r14, @sp+
+	pop	r14
 	seth	r0, #shigh(M32R_ICU_IMASK_ADDR)
 	st	r14, @(low(M32R_ICU_IMASK_ADDR),r0)
 #else
@@ -1015,4 +1005,3 @@
 	.long sys_waitid
 
 syscall_table_size=(.-sys_call_table)
-
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index be8b711..c50330f 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -23,9 +23,6 @@
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
@@ -38,13 +35,6 @@
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL(__get_user_1);
-EXPORT_SYMBOL(__get_user_2);
-EXPORT_SYMBOL(__get_user_4);
-
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
-
 EXPORT_SYMBOL(strncpy_from_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(clear_user);
@@ -59,11 +49,8 @@
 EXPORT_SYMBOL(dcache_dummy);
 #endif
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_callout_map);
 
 /* Global SMP stuff */
-EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(smp_call_function);
 
 /* TLB flushing */
@@ -83,27 +70,11 @@
 EXPORT_SYMBOL(__muldi3);
 
 /* memory and string operations */
-EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memcpy);
-/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
-/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
 EXPORT_SYMBOL(memset);
-/* EXPORT_SYMBOL(memset_io); // not implement yet */
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
-
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strncpy);
 
 EXPORT_SYMBOL(_inb);
 EXPORT_SYMBOL(_inw);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 5dfc7ea..065f5e7 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -116,6 +116,10 @@
 
 void machine_restart(char *__unused)
 {
+#if defined(CONFIG_PLAT_MAPPI3)
+	outw(1, (unsigned long)PLD_REBOOT);
+#endif
+
 	printk("Please push reset button!\n");
 	while (1)
 		cpu_relax();
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 0d78942..3cd3c29 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -9,6 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/stddef.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
@@ -219,8 +220,6 @@
 extern unsigned long setup_memory(void);
 #endif	/* CONFIG_DISCONTIGMEM */
 
-#define M32R_PCC_PCATCR	0x00ef7014	/* will move to m32r.h */
-
 void __init setup_arch(char **cmdline_p)
 {
 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
@@ -269,15 +268,14 @@
 	paging_init();
 }
 
-static struct cpu cpu[NR_CPUS];
+static struct cpu cpu_devices[NR_CPUS];
 
 static int __init topology_init(void)
 {
-	int cpu_id;
+	int i;
 
-	for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
-		if (cpu_possible(cpu_id))
-			register_cpu(&cpu[cpu_id], cpu_id, NULL);
+	for_each_present_cpu(i)
+		register_cpu(&cpu_devices[i], i, NULL);
 
 	return 0;
 }
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index cb33097..6498ee7 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -118,6 +118,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	COPY(acch);
 	COPY(accl);
+	COPY(dummy_acc1h);
+	COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
@@ -203,6 +205,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	COPY(acch);
 	COPY(accl);
+	COPY(dummy_acc1h);
+	COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index d7ec16e..840b434 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -39,8 +39,10 @@
  *		Martin J. Bligh	: 	Added support for multi-quad systems
  */
 
+#include <linux/module.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/irq.h>
@@ -72,11 +74,15 @@
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
 
 cpumask_t cpu_bootout_map;
 cpumask_t cpu_bootin_map;
-cpumask_t cpu_callout_map;
 static cpumask_t cpu_callin_map;
+cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
+cpumask_t cpu_possible_map = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_possible_map);
 
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
@@ -110,7 +116,6 @@
 
 void smp_prepare_boot_cpu(void);
 void smp_prepare_cpus(unsigned int);
-static void smp_tune_scheduling(void);
 static void init_ipi_lock(void);
 static void do_boot_cpu(int);
 int __cpu_up(unsigned int);
@@ -177,6 +182,9 @@
 	}
 	for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
 		physid_set(phys_id, phys_cpu_present_map);
+#ifndef CONFIG_HOTPLUG_CPU
+	cpu_present_map = cpu_possible_map;
+#endif
 
 	show_mp_info(nr_cpu);
 
@@ -186,7 +194,6 @@
 	 * Setup boot CPU information
 	 */
 	smp_store_cpu_info(0); /* Final full version of the data */
-	smp_tune_scheduling();
 
 	/*
 	 * If SMP should be disabled, then really disable it!
@@ -230,11 +237,6 @@
 	Dprintk("Boot done.\n");
 }
 
-static void __init smp_tune_scheduling(void)
-{
-	/* Nothing to do. */
-}
-
 /*
  * init_ipi_lock : Initialize IPI locks.
  */
@@ -629,4 +631,3 @@
 	physid_2_cpu[phys_id] = -1;
 	cpu_2_physid[cpu_id] = -1;
 }
-
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
index e632d10..d16b4e4 100644
--- a/arch/m32r/lib/Makefile
+++ b/arch/m32r/lib/Makefile
@@ -2,6 +2,6 @@
 # Makefile for M32R-specific library files..
 #
 
-lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
-	  putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+lib-y  := checksum.o ashxdi3.o memset.o memcpy.o \
+	  delay.o strlen.o usercopy.o csum_partial_copy.o
 
diff --git a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
deleted file mode 100644
index 58a0db0..0000000
--- a/arch/m32r/lib/getuser.S
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * __get_user functions.
- *
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient, especially as they
- * return an error value in addition to the "real"
- * return value.
- */
-
-#include <linux/config.h>
-
-/*
- * __get_user_X
- *
- * Inputs:	r0 contains the address
- *
- * Outputs:	r0 is error code (0 or -EFAULT)
- *		r1 contains zero-extended value
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
-	.text
-	.balign 4
-	.globl __get_user_1
-__get_user_1:
-1:	ldub	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __get_user_2
-__get_user_2:
-2:	lduh	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __get_user_4
-__get_user_4:
-3:	ld	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-bad_get_user:
-	ldi	r1, #0		    ||	ldi	r0, #-14
-	jmp	r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
-	.text
-	.balign 4
-	.globl __get_user_1
-__get_user_1:
-1:	ldub	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __get_user_2
-__get_user_2:
-2:	lduh	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __get_user_4
-__get_user_4:
-3:	ld	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-bad_get_user:
-	ldi	r1, #0
-	ldi	r0, #-14
-	jmp	r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
-	.long 1b,bad_get_user
-	.long 2b,bad_get_user
-	.long 3b,bad_get_user
-.previous
-
-	.end
diff --git a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
deleted file mode 100644
index 218154c..0000000
--- a/arch/m32r/lib/putuser.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * __put_user functions.
- *
- * (C) Copyright 1998 Linus Torvalds
- * (C) Copyright 2001 Hirokazu Takata
- *
- * These functions have a non-standard call interface
- * to make them more efficient.
- */
-
-#include <linux/config.h>
-
-/*
- * __put_user_X
- *
- * Inputs:	r0 contains the address
- *		r1 contains the value
- *
- * Outputs:	r0 is error code (0 or -EFAULT)
- *		r1 is corrupted (will contain "current_task").
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-#ifdef CONFIG_ISA_DUAL_ISSUE
-
-	.text
-	.balign 4
-	.globl __put_user_1
-__put_user_1:
-1:	stb	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __put_user_2
-__put_user_2:
-2:	sth	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __put_user_4
-__put_user_4:
-3:	st	r1, @r0		    ||	ldi	r0, #0
-	jmp	r14
-
-bad_put_user:
-	ldi	r0, #-14	    ||	jmp	r14
-
-#else /* not CONFIG_ISA_DUAL_ISSUE */
-
-	.text
-	.balign 4
-	.globl __put_user_1
-__put_user_1:
-1:	stb	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __put_user_2
-__put_user_2:
-2:	sth	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-	.balign 4
-	.globl __put_user_4
-__put_user_4:
-3:	st	r1, @r0
-	ldi	r0, #0
-	jmp	r14
-
-bad_put_user:
-	ldi	r0, #-14
-	jmp	r14
-
-#endif /* not CONFIG_ISA_DUAL_ISSUE */
-
-.section __ex_table,"a"
-	.long 1b,bad_put_user
-	.long 2b,bad_put_user
-	.long 3b,bad_put_user
-.previous
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index c331951..5b7952e 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,7 +57,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index f9b4ea1..4320d5d 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -26,7 +26,6 @@
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e15709c..ee5fbb0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -816,6 +816,10 @@
 	bool
 	default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+	bool
+	default y
+
 #
 # Select some configuration options automatically based on user selections.
 #
@@ -1063,6 +1067,7 @@
 config CPU_MIPS32_R1
 	bool "MIPS32 Release 1"
 	depends on SYS_HAS_CPU_MIPS32_R1
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
@@ -1080,6 +1085,7 @@
 config CPU_MIPS32_R2
 	bool "MIPS32 Release 2"
 	depends on SYS_HAS_CPU_MIPS32_R2
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
@@ -1093,6 +1099,7 @@
 config CPU_MIPS64_R1
 	bool "MIPS64 Release 1"
 	depends on SYS_HAS_CPU_MIPS64_R1
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1111,6 +1118,7 @@
 config CPU_MIPS64_R2
 	bool "MIPS64 Release 2"
 	depends on SYS_HAS_CPU_MIPS64_R2
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1125,6 +1133,7 @@
 config CPU_R3000
 	bool "R3000"
 	depends on SYS_HAS_CPU_R3000
+	select CPU_HAS_WB
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
 	help
@@ -1154,6 +1163,7 @@
 config CPU_R4300
 	bool "R4300"
 	depends on SYS_HAS_CPU_R4300
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	help
@@ -1162,6 +1172,7 @@
 config CPU_R4X00
 	bool "R4x00"
 	depends on SYS_HAS_CPU_R4X00
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	help
@@ -1171,6 +1182,7 @@
 config CPU_TX49XX
 	bool "R49XX"
 	depends on SYS_HAS_CPU_TX49XX
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1178,6 +1190,7 @@
 config CPU_R5000
 	bool "R5000"
 	depends on SYS_HAS_CPU_R5000
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	help
@@ -1186,12 +1199,14 @@
 config CPU_R5432
 	bool "R5432"
 	depends on SYS_HAS_CPU_R5432
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 
 config CPU_R6000
 	bool "R6000"
 	depends on EXPERIMENTAL
+	select CPU_HAS_LLSC
 	depends on SYS_HAS_CPU_R6000
 	select CPU_SUPPORTS_32BIT_KERNEL
 	help
@@ -1201,6 +1216,7 @@
 config CPU_NEVADA
 	bool "RM52xx"
 	depends on SYS_HAS_CPU_NEVADA
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	help
@@ -1210,6 +1226,7 @@
 	bool "R8000"
 	depends on EXPERIMENTAL
 	depends on SYS_HAS_CPU_R8000
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_64BIT_KERNEL
 	help
@@ -1219,6 +1236,7 @@
 config CPU_R10000
 	bool "R10000"
 	depends on SYS_HAS_CPU_R10000
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1229,6 +1247,7 @@
 config CPU_RM7000
 	bool "RM7000"
 	depends on SYS_HAS_CPU_RM7000
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1237,6 +1256,7 @@
 config CPU_RM9000
 	bool "RM9000"
 	depends on SYS_HAS_CPU_RM9000
+	select CPU_HAS_LLSC
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
@@ -1245,6 +1265,7 @@
 config CPU_SB1
 	bool "SB1"
 	depends on SYS_HAS_CPU_SB1
+	select CPU_HAS_LLSC
 	select CPU_SUPPORTS_32BIT_KERNEL
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select CPU_SUPPORTS_HIGHMEM
@@ -1443,6 +1464,12 @@
 	prompt "MIPS MT options"
 	depends on MIPS_MT
 
+config MIPS_MT_SMTC
+	bool "SMTC: Use all TCs on all VPEs for SMP"
+	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_SRS
+	select SMP
+
 config MIPS_MT_SMP
 	bool "Use 1 TC on each available VPE for SMP"
 	select SMP
@@ -1456,6 +1483,11 @@
 
 endchoice
 
+config MIPS_MT_FPAFF
+	bool "Dynamic FPU affinity for FP-intensive threads"
+	depends on MIPS_MT
+	default y
+
 config MIPS_VPE_LOADER_TOM
 	bool "Load VPE program into memory hidden from linux"
 	depends on MIPS_VPE_LOADER
@@ -1472,6 +1504,16 @@
 	depends on MIPS_VPE_LOADER
 	help
 
+config MIPS_APSP_KSPD
+	bool "Enable KSPD"
+	depends on MIPS_VPE_APSP_API
+	default y
+	help
+	  KSPD is a kernel daemon that accepts syscall requests from the SP
+	  side, actions them and returns the results. It also handles the
+	  "exit" syscall notifying other kernel modules the SP program is
+	  exiting.  You probably want to say yes here.
+
 config SB1_PASS_1_WORKAROUNDS
 	bool
 	depends on CPU_SB1_PASS_1
@@ -1491,38 +1533,15 @@
 	bool "Support for 64-bit physical address space"
 	depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && 32BIT
 
-config CPU_ADVANCED
-	bool "Override CPU Options"
-	depends on 32BIT
-	help
-	  Saying yes here allows you to select support for various features
-	  your CPU may or may not have.  Most people should say N here.
-
 config CPU_HAS_LLSC
-	bool "ll/sc Instructions available" if CPU_ADVANCED
-	default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX
-	help
-	  MIPS R4000 series and later provide the Load Linked (ll)
-	  and Store Conditional (sc) instructions. More information is
-	  available at <http://www.go-ecs.com/mips/miptek1.htm>.
-
-	  Say Y here if your CPU has the ll and sc instructions.  Say Y here
-	  for better performance, N if you don't know.  You must say Y here
-	  for multiprocessor machines.
+	bool
 
 config CPU_HAS_WB
-	bool "Writeback Buffer available" if CPU_ADVANCED
-	default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
-	help
-	  Say N here for slightly better performance.  You must say Y here for
-	  machines which require flushing of write buffers in software.  Saying
-	  Y is the safe option; N may result in kernel malfunction and crashes.
-
-menu "MIPSR2 Interrupt handling"
-	depends on CPU_MIPSR2 && CPU_ADVANCED
+	bool
 
 config CPU_MIPSR2_IRQ_VI
 	bool "Vectored interrupt mode"
+	depends on CPU_MIPSR2
 	help
 	   Vectored interrupt mode allowing faster dispatching of interrupts.
 	   The board support code needs to be written to take advantage of this
@@ -1532,6 +1551,7 @@
 
 config CPU_MIPSR2_IRQ_EI
 	bool "External interrupt controller mode"
+	depends on CPU_MIPSR2
 	help
 	   Extended interrupt mode takes advantage of an external interrupt
 	   controller to allow fast dispatching from many possible interrupt
@@ -1545,7 +1565,6 @@
 	   Allow the kernel to use shadow register sets for fast interrupts.
 	   Interrupt handlers must be specially written to use shadow sets.
 	   Say N unless you know that shadow register set upport is needed.
-endmenu
 
 config CPU_HAS_SYNC
 	bool
@@ -1590,11 +1609,16 @@
 	def_bool y
 	depends on !NUMA
 
+config NODES_SHIFT
+	int
+	default "6"
+	depends on NEED_MULTIPLE_NODES
+
 source "mm/Kconfig"
 
 config SMP
 	bool "Multi-Processing support"
-	depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
+	depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP || MIPS_MT_SMTC
 	---help---
 	  This enables support for systems with more than one CPU. If you have
 	  a system with only one CPU, like most personal computers, say N. If
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index d3c5cc3..515f9e6 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -6,7 +6,13 @@
 	bool "Are you using a crosscompiler"
 	help
 	  Say Y here if you are compiling the kernel on a different
-	  architecture than the one it is intended to run on.
+	  architecture than the one it is intended to run on.  This is just a
+	  convenience option which will select the appropriate value for
+	  the CROSS_COMPILE make variable which otherwise has to be passed on
+	  the command line from mips-linux-, mipsel-linux-, mips64-linux- and
+	  mips64el-linux- as appropriate for a particular kernel configuration.
+	  You will have to pass the value for CROSS_COMPILE manually if the
+	  name prefix for your tools is different.
 
 config CMDLINE
 	string "Default kernel command string"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 9a69e0f..133900a 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -105,18 +105,18 @@
 cflags-$(CONFIG_CPU_VR41XX)	+= -march=r4100 -Wa,--trap
 cflags-$(CONFIG_CPU_R4X00)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_TX49XX)	+= -march=r4600 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32r2 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R1)	+= $(call cc-option,-march=mips64,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS64_R1)	+= $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R2)	+= $(call cc-option,-march=mips64r2,-mips2 -mtune=r4600 ) \
+cflags-$(CONFIG_CPU_MIPS64_R2)	+= $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
 			-Wa,-mips64r2 -Wa,--trap
 cflags-$(CONFIG_CPU_R5000)	+= -march=r5000 -Wa,--trap
-cflags-$(CONFIG_CPU_R5432)	+= $(call cc-options,-march=r5400,-march=r5000) \
+cflags-$(CONFIG_CPU_R5432)	+= $(call cc-option,-march=r5400,-march=r5000) \
 			-Wa,--trap
-cflags-$(CONFIG_CPU_NEVADA)	+= $(call cc-options,-march=rm5200,-march=r5000) \
+cflags-$(CONFIG_CPU_NEVADA)	+= $(call cc-option,-march=rm5200,-march=r5000) \
 			-Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)	+= $(call cc-option,-march=rm7000,-march=r5000) \
 			-Wa,--trap
@@ -615,7 +615,10 @@
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \
 	egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \
-	sed -e 's/^\#define /-D/' -e 's/ /="/' -e 's/$$/"/')
+	sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/")
+ifdef CONFIG_64BIT
+CHECKFLAGS		+= -m64
+endif
 endif
 
 OBJCOPYFLAGS		+= --remove-section=.reginfo
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
index a1edfd1..bf682f5 100644
--- a/arch/mips/au1000/common/Makefile
+++ b/arch/mips/au1000/common/Makefile
@@ -6,7 +6,7 @@
 # Makefile for the Alchemy Au1000 CPU, generic files.
 #
 
-obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+obj-y += prom.o irq.o puts.o time.o reset.o \
 	au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
 	sleeper.o cputable.o dma.o dbdma.o gpio.o
 
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
deleted file mode 100644
index 1c4ca88..0000000
--- a/arch/mips/au1000/common/int-handler.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: ppopov@mvista.com
- *
- * Interrupt dispatcher for Au1000 boards.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set	macro
-	.set	noat
-	.align	5
-
-NESTED(au1000_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-	mfc0	t0,CP0_CAUSE		# get pending interrupts
-	mfc0	t1,CP0_STATUS		# get enabled interrupts
-	and	t0,t1			# isolate allowed ones
-
-	andi	t0,0xff00		# isolate pending bits
-	beqz	t0, 3f			# spurious interrupt
-
-	andi	a0, t0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	move	a0, sp
-	jal	mips_timer_interrupt
-	j	ret_from_irq
-
-1:
-	andi	a0, t0, CAUSEF_IP2	# Interrupt Controller 0, Request 0
-	beq	a0, zero, 2f
-	move	a0,sp
-	jal	intc0_req0_irqdispatch
-	j	ret_from_irq
-2:
-	andi	a0, t0, CAUSEF_IP3	# Interrupt Controller 0, Request 1
-	beq	a0, zero, 3f
-	move	a0,sp
-	jal	intc0_req1_irqdispatch
-	j	ret_from_irq
-3:
-	andi	a0, t0, CAUSEF_IP4	# Interrupt Controller 1, Request 0
-	beq	a0, zero, 4f
-	move	a0,sp
-	jal	intc1_req0_irqdispatch
-	j	ret_from_irq
-4:
-	andi	a0, t0, CAUSEF_IP5	# Interrupt Controller 1, Request 1
-	beq	a0, zero, 5f
-	move	a0, sp
-	jal	intc1_req1_irqdispatch
-	j	ret_from_irq
-
-5:
-	move	a0, sp
-	j	spurious_interrupt
-END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
index 1339a09..da61de7 100644
--- a/arch/mips/au1000/common/irq.c
+++ b/arch/mips/au1000/common/irq.c
@@ -66,7 +66,6 @@
 #define EXT_INTC1_REQ1 5 /* IP 5 */
 #define MIPS_TIMER_IP  7 /* IP 7 */
 
-extern asmlinkage void au1000_IRQ(void);
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
 
@@ -446,7 +445,6 @@
 	extern int au1xxx_ic0_nr_irqs;
 
 	cp0_status = read_c0_status();
-	set_except_vector(0, au1000_IRQ);
 
 	/* Initialize interrupt controllers to a safe state.
 	*/
@@ -661,3 +659,21 @@
 	au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
 }
 #endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		mips_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)
+		intc0_req0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		intc0_req1_irqdispatch(regs);
+	else if (pending & CAUSEF_IP4)
+		intc1_req0_irqdispatch(regs);
+	else if (pending  & CAUSEF_IP5)
+		intc1_req1_irqdispatch(regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 720e757..225ac8f 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o int-handler.o reset.o setup.o
+obj-y	 := irq.o reset.o setup.o
 
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
deleted file mode 100644
index e75d5e3..0000000
--- a/arch/mips/cobalt/int-handler.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-cobalt/cobalt.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-		.text
-		.align	5
-		NESTED(cobalt_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-
-		PTR_LA	ra, ret_from_irq
-		move	a0, sp
-		j	cobalt_irq
-
-		END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index f9a1088..0b75f4f 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -20,8 +20,6 @@
 
 #include <asm/mach-cobalt/cobalt.h>
 
-extern void cobalt_handle_int(void);
-
 /*
  * We have two types of interrupts that we handle, ones that come in through
  * the CPU interrupt lines, and ones that come in on the via chip. The CPU
@@ -79,7 +77,7 @@
 		do_IRQ(irq, regs);
 }
 
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned pending;
 
@@ -122,8 +120,6 @@
 	 */
 	GALILEO_OUTL(0, GT_INTRMASK_OFS);
 
-	set_except_vector(0, cobalt_handle_int);
-
 	init_i8259_irqs();				/*  0 ... 15 */
 	mips_cpu_irq_init(COBALT_CPU_IRQ);		/* 16 ... 23 */
 
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 9e1ae95..4b080bc 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:52 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -127,11 +129,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -149,7 +151,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -165,6 +166,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -178,10 +180,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -193,7 +191,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -202,6 +199,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -221,7 +220,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -249,6 +247,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -281,6 +280,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -322,9 +322,12 @@
 CONFIG_IP_VS_FTP=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
@@ -348,11 +351,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -376,20 +382,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -407,6 +412,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -427,12 +433,10 @@
 CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_FRAG=m
 CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_TARGET_REJECT=m
@@ -478,6 +482,11 @@
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
@@ -492,11 +501,6 @@
 CONFIG_IPDDP_DECAP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -556,6 +560,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -694,9 +701,8 @@
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -715,6 +721,7 @@
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -921,6 +928,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=m
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -930,6 +938,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -988,10 +997,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -1022,6 +1027,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -1039,15 +1045,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1120,7 +1144,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1140,7 +1163,6 @@
 # CONFIG_QNX4FS_FS is not set
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -1232,6 +1254,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 3298410..d85cda5 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:53 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:55 2006
 #
 CONFIG_MIPS=y
 
@@ -80,6 +80,8 @@
 # CONFIG_SIBYTE_SB1250_PROF is not set
 # CONFIG_SIBYTE_TBPROF is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -154,7 +156,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -172,6 +173,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -186,10 +188,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -201,7 +199,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -210,6 +207,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -230,7 +228,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_DEBUG=y
 CONFIG_MMU=y
 
@@ -249,6 +246,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_BUILD_ELF64=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -284,12 +283,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -301,6 +303,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -310,11 +317,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -377,7 +379,7 @@
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -575,6 +577,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -637,7 +640,6 @@
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 CONFIG_I2C_SIBYTE=y
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -656,9 +658,7 @@
 CONFIG_SENSORS_PCF8574=y
 CONFIG_SENSORS_PCA9539=y
 CONFIG_SENSORS_PCF8591=y
-CONFIG_SENSORS_RTC8564=y
 CONFIG_SENSORS_MAX6875=y
-# CONFIG_RTC_X1205_I2C is not set
 CONFIG_I2C_DEBUG_CORE=y
 CONFIG_I2C_DEBUG_ALGO=y
 CONFIG_I2C_DEBUG_BUS=y
@@ -686,10 +686,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -714,6 +710,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -731,15 +728,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -785,7 +800,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 6c2961a..ca0af16 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:54 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:06 2006
 #
 CONFIG_MIPS=y
 
@@ -72,6 +72,8 @@
 CONFIG_PCI_VR41XX=y
 # CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -151,6 +155,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -187,6 +187,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -206,7 +209,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -224,6 +226,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
@@ -233,6 +236,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -255,12 +259,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -272,6 +279,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -281,11 +293,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -302,10 +309,7 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -348,10 +352,12 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -578,6 +584,11 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -601,6 +612,7 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -636,10 +648,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -670,6 +678,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -687,15 +696,50 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -712,7 +756,7 @@
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
 
@@ -735,10 +779,9 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -805,44 +848,20 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -852,8 +871,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 8336b21..7d269e6 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
 #
 CONFIG_MIPS=y
 
@@ -63,7 +63,10 @@
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -113,7 +116,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -135,7 +137,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -151,6 +152,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -164,10 +166,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,6 +180,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -201,7 +201,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -229,6 +228,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -247,12 +247,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -264,6 +267,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -273,11 +281,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -298,6 +301,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -343,7 +349,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -593,6 +599,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -602,6 +609,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -660,10 +668,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -694,6 +698,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -711,15 +716,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -765,7 +788,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -828,6 +850,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 7f07140..579b665 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:56 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:57 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -152,6 +153,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -190,6 +187,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -245,6 +244,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -267,7 +267,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -278,6 +279,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -294,10 +297,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -321,6 +327,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -330,11 +341,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -356,6 +362,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -412,7 +421,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -434,7 +442,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -471,7 +478,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -722,10 +729,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -756,6 +759,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
 #
@@ -773,14 +777,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -836,7 +858,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -945,6 +966,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 98590ca..e5eb538 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:57 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -152,6 +153,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -165,10 +167,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -190,6 +187,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -234,6 +233,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -256,7 +256,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -267,6 +268,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -283,10 +286,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -310,6 +316,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -319,11 +330,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -345,6 +351,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -401,7 +410,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -423,7 +431,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -460,7 +467,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -690,10 +697,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -711,6 +714,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -755,6 +759,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
 #
@@ -772,14 +777,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -835,7 +858,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -944,6 +966,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 9288847..a43fb23 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:58 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:58 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_COHERENT=y
 CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
@@ -114,11 +116,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +154,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -191,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -244,6 +243,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -263,7 +263,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -274,6 +275,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -288,10 +291,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -315,6 +321,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -324,11 +335,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -403,7 +409,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -425,7 +430,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -763,10 +767,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -784,6 +784,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -794,6 +795,7 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 
@@ -816,6 +818,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -832,6 +835,7 @@
 # CONFIG_USB_GADGET_GOKU is not set
 # CONFIG_USB_GADGET_LH7A40X is not set
 # CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 # CONFIG_USB_GADGET_DUALSPEED is not set
 
@@ -844,14 +848,32 @@
 CONFIG_MMC_AU1X=y
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -913,7 +935,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1027,6 +1048,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=48M"
 
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 5a415b1..ad632d8 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:59 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:59 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -138,7 +140,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +155,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -192,6 +189,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -211,7 +210,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -253,6 +251,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -275,7 +274,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -302,10 +304,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -420,7 +428,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -486,7 +492,7 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -714,6 +720,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -725,6 +732,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -790,10 +798,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -802,6 +806,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -825,9 +830,11 @@
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -846,6 +853,7 @@
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -877,6 +885,7 @@
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -905,34 +914,22 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS_DRIVER=y
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
 # CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_AU1000 is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 is not set
 
 #
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -958,7 +955,6 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
@@ -985,9 +981,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 CONFIG_USB_YEALINK=m
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1001,15 +995,6 @@
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1059,15 +1044,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1123,7 +1126,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1232,6 +1234,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 8dc1f18..8130e23 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:00 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +154,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -191,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -210,7 +209,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -252,6 +250,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -274,7 +273,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -285,6 +285,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -301,10 +303,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -328,6 +333,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -337,11 +347,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -363,6 +368,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -419,7 +427,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -442,7 +449,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -489,7 +495,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -754,6 +760,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -765,6 +772,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -830,10 +838,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -858,6 +862,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -875,15 +880,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -939,7 +962,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1048,6 +1070,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index 8fae63e..8d88ac1 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:00 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -152,6 +152,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -202,7 +201,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_ISA=y
 CONFIG_MMU=y
 
@@ -231,6 +229,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -252,12 +251,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -269,6 +271,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -278,11 +285,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -303,6 +305,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -348,7 +353,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -571,6 +576,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -580,6 +586,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -638,10 +645,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -659,6 +662,7 @@
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -670,7 +674,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -708,6 +711,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -725,15 +729,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -776,7 +798,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -840,6 +861,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any"
 
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index a0fcd44..8c911b6 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:02 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
 #
 CONFIG_MIPS=y
 
@@ -65,6 +65,8 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_DDB5477_BUS_FREQUENCY=0
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,7 +116,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -136,7 +137,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -152,6 +152,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -183,6 +180,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -202,7 +201,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -230,6 +228,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -251,12 +250,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -268,6 +270,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -277,11 +284,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -302,6 +304,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -346,7 +351,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -556,6 +561,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -565,6 +571,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -623,10 +630,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -657,6 +660,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -674,15 +678,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -725,7 +747,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -792,6 +813,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any"
 
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 5a181ea..d838496 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:03 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:01 2006
 #
 CONFIG_MIPS=y
 
@@ -63,11 +63,13 @@
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_EARLY_PRINTK=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
@@ -113,7 +115,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_WB=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +136,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -151,6 +151,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -165,10 +166,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -180,7 +177,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -189,6 +185,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -233,11 +231,10 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -254,12 +251,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -271,6 +271,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -280,11 +285,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -305,6 +305,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -345,7 +348,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -567,10 +570,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -588,6 +587,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -617,6 +617,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -633,14 +634,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -686,7 +705,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -705,7 +723,6 @@
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 CONFIG_UFS_FS=y
-CONFIG_UFS_FS_WRITE=y
 
 #
 # Network File Systems
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 8fbfc06..0760f43 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:04 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:20 2006
 #
 CONFIG_MIPS=y
 
@@ -70,6 +70,8 @@
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -144,11 +148,10 @@
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -162,10 +165,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -177,7 +176,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -185,6 +183,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -219,85 +220,12 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# 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
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_NET is not set
 
 #
 # Device Drivers
@@ -313,7 +241,6 @@
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=m
 
 #
 # Memory Technology Devices (MTD)
@@ -335,11 +262,11 @@
 #
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -398,81 +325,8 @@
 #
 
 #
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_DM9000 is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# 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
 #
-# CONFIG_ISDN is not set
 
 #
 # Telephony Support
@@ -508,11 +362,7 @@
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -531,6 +381,10 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -565,6 +419,7 @@
 #
 # Ftape, the floppy tape device driver
 #
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -600,10 +455,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -611,7 +462,6 @@
 #
 # Digital Video Broadcasting Devices
 #
-# CONFIG_DVB is not set
 
 #
 # Graphics support
@@ -635,6 +485,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -651,14 +502,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -669,13 +538,12 @@
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
 
@@ -698,10 +566,9 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -722,29 +589,6 @@
 # CONFIG_UFS_FS is not set
 
 #
-# Network File Systems
-#
-CONFIG_NFS_FS=m
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=m
-CONFIG_EXPORTFS=m
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# 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
 #
 # CONFIG_PARTITION_ADVANCED is not set
@@ -767,44 +611,20 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -814,8 +634,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index f2d43be..7067f60 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:05 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:02 2006
 #
 CONFIG_MIPS=y
 
@@ -65,6 +65,8 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_EVB_PCI1 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,7 +118,6 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -138,7 +139,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +154,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,7 +179,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_KMOD is not set
@@ -191,6 +187,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -210,7 +208,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -238,6 +235,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -258,12 +256,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -275,6 +276,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -284,11 +290,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -309,6 +310,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -352,7 +356,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -550,6 +554,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -559,6 +564,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -617,10 +623,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -651,6 +653,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -668,15 +671,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -719,7 +740,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -783,6 +803,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
 
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index ac5841c..00b56ed 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:06 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:03 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -142,7 +143,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -158,6 +158,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -171,10 +172,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_KMOD is not set
@@ -195,6 +191,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -240,6 +238,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -260,12 +259,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -277,6 +279,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -286,11 +293,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -311,6 +313,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -349,7 +354,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -567,10 +572,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -601,6 +602,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -617,14 +619,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -667,7 +687,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -731,6 +750,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 42d5cd7..607e298 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@
 CONFIG_IP22_CPU_SCACHE=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -160,6 +160,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -197,6 +193,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -242,6 +240,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -264,6 +263,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@
 CONFIG_IP_VS_FTP=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@
 CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_FRAG=m
 CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -546,7 +553,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,14 +877,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -944,7 +966,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -963,7 +984,6 @@
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -1078,6 +1098,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 8c40590..f724b4b 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc4
-# Tue Feb 21 13:44:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:04 2006
 #
 CONFIG_MIPS=y
 
@@ -70,6 +70,8 @@
 # CONFIG_REPLICATE_KTEXT is not set
 # CONFIG_REPLICATE_EXHANDLERS is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARC=y
 CONFIG_DMA_IP27=y
@@ -123,6 +125,7 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_NODES_SHIFT=6
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM_MANUAL=y
@@ -162,6 +165,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -175,10 +179,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -190,7 +190,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -199,6 +198,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -219,7 +219,6 @@
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -237,6 +236,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -274,12 +274,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -363,6 +366,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -407,7 +413,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -473,7 +479,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -491,6 +496,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -654,6 +660,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -727,10 +734,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -755,6 +758,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -772,17 +776,31 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
 # File systems
@@ -840,7 +858,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -922,6 +939,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 7fdcaf5..8f11d35 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:09 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARC=y
 CONFIG_DMA_IP32=y
@@ -142,7 +144,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -159,6 +160,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -172,10 +174,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -189,6 +187,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -208,7 +207,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -226,6 +224,7 @@
 #
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -240,6 +239,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -261,12 +261,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -278,6 +281,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -287,11 +295,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -312,6 +315,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -357,7 +363,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -428,7 +434,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -615,6 +620,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -624,6 +630,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -682,10 +689,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -716,6 +719,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -733,15 +737,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -784,7 +806,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -861,6 +882,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index c716996..757adf2 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:10 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:05 2006
 #
 CONFIG_MIPS=y
 
@@ -65,6 +65,8 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_IT8172_REVC is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,7 +117,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -137,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +154,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -183,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -192,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -237,6 +235,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -258,12 +257,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -275,6 +277,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -284,11 +291,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -309,6 +311,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -387,7 +392,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -424,7 +428,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -666,10 +670,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -704,7 +704,6 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-# CONFIG_OBSOLETE_OSS_DRIVER is not set
 CONFIG_SOUND_IT8172=y
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
@@ -714,6 +713,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -730,14 +730,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -780,7 +798,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -846,6 +863,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index a8376d1..021761a 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:11 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -112,7 +114,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -134,7 +135,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -151,6 +151,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -164,10 +165,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -179,7 +176,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -188,6 +184,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -207,7 +205,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -235,6 +232,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -256,12 +254,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -273,6 +274,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -282,11 +288,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -307,6 +308,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -350,7 +354,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -565,6 +569,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -574,6 +579,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -631,10 +637,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -665,6 +667,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -682,15 +685,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -733,7 +754,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -797,6 +817,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 3160153..08f6c30 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:12 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:06 2006
 #
 CONFIG_MIPS=y
 
@@ -65,6 +65,8 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_JAGUAR_DMALOW=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -122,7 +124,6 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@
 # Code maturity level options
 #
 # CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -160,6 +160,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
@@ -172,10 +173,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@
 #
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -195,6 +191,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -214,7 +212,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -241,6 +238,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -260,16 +258,19 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_NETFILTER is not set
@@ -338,10 +339,9 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
 CONFIG_ATA_OVER_ETH=m
 
 #
@@ -423,6 +423,7 @@
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=y
 # CONFIG_E100 is not set
@@ -446,6 +447,7 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
@@ -514,6 +516,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -523,6 +526,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -579,10 +583,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -607,6 +607,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -624,12 +625,29 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
 #
 
 #
@@ -672,7 +690,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -718,6 +735,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 53fbef1..38b1e02 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:13 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -111,7 +113,6 @@
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +134,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -149,6 +149,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -162,10 +163,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -180,6 +177,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -199,7 +198,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -227,6 +225,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -248,12 +247,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -265,6 +267,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -274,11 +281,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -299,6 +301,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -343,7 +348,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -551,7 +556,12 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
 # CONFIG_UNIX98_PTYS is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -610,10 +620,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -631,6 +637,7 @@
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -642,7 +649,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -679,6 +685,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -696,15 +703,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -745,7 +770,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -809,6 +833,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index ef0fa9f..4d25990 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:14 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:07 2006
 #
 CONFIG_MIPS=y
 
@@ -68,6 +68,8 @@
 CONFIG_DS1603=y
 CONFIG_LASAT_SYSCTL=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -119,7 +121,6 @@
 CONFIG_R5000_CPU_SCACHE=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -141,7 +142,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -157,6 +157,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -170,10 +171,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -186,7 +183,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -195,6 +191,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -214,7 +212,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -242,6 +239,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -259,12 +257,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -276,6 +277,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -285,11 +291,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -310,6 +311,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -366,7 +370,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -389,7 +392,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -430,7 +432,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -672,6 +674,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -681,6 +684,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -739,10 +743,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -773,6 +773,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -790,15 +791,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -847,7 +866,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -914,6 +932,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 367d279..977f52b 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:15 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:08 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -128,16 +130,21 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
 CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
 CONFIG_MIPS_VPE_LOADER_TOM=y
 CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_MIPSR2_IRQ_VI is not set
+# CONFIG_CPU_MIPSR2_IRQ_EI is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -155,7 +162,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -171,6 +177,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -184,10 +191,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -199,7 +202,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -208,6 +210,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -227,7 +231,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -255,6 +258,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -287,6 +291,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -328,9 +333,12 @@
 CONFIG_IP_VS_FTP=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
@@ -354,11 +362,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 # CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -382,20 +393,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -413,6 +423,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -433,12 +444,10 @@
 CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_FRAG=m
 CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_TARGET_REJECT=m
@@ -484,6 +493,11 @@
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
@@ -498,11 +512,6 @@
 CONFIG_IPDDP_DECAP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -562,6 +571,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -734,7 +746,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -753,6 +764,7 @@
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -956,6 +968,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -965,6 +978,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -1022,10 +1036,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -1056,6 +1066,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -1073,15 +1084,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1154,7 +1183,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1174,7 +1202,6 @@
 # CONFIG_QNX4FS_FS is not set
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -1266,6 +1293,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index fe78961..00560e0 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:16 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,16 +116,19 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT=y
+# CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_MT_SMP is not set
 CONFIG_MIPS_VPE_LOADER=y
+CONFIG_MIPS_MT_FPAFF=y
 CONFIG_MIPS_VPE_LOADER_TOM=y
 CONFIG_MIPS_VPE_APSP_API=y
+CONFIG_MIPS_APSP_KSPD=y
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -141,7 +146,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -157,6 +161,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -171,10 +176,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -186,7 +187,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -195,6 +195,7 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -238,6 +239,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -268,12 +270,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -290,6 +295,11 @@
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -299,11 +309,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -397,7 +402,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=y
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -532,7 +537,7 @@
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -596,10 +601,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -624,6 +625,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -640,14 +642,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -690,8 +710,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
-# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index e4620e7..286a018 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:17 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:09 2006
 #
 CONFIG_MIPS=y
 
@@ -72,6 +72,8 @@
 CONFIG_PCI_VR41XX=y
 CONFIG_VRC4173=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -90,7 +92,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -103,18 +105,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -135,7 +140,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -151,6 +155,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -164,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -179,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -187,6 +187,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -206,7 +209,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -225,6 +227,7 @@
 # CONFIG_YENTA is not set
 # CONFIG_PD6729 is not set
 # CONFIG_I82092 is not set
+# CONFIG_PCMCIA_VRC4173 is not set
 
 #
 # PCI Hotplug Support
@@ -236,6 +239,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
@@ -245,6 +249,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -264,12 +269,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -281,6 +289,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -290,11 +303,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -316,6 +324,9 @@
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -360,7 +371,7 @@
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 CONFIG_ATA_OVER_ETH=m
 
@@ -475,6 +486,7 @@
 # Wireless LAN (non-hamradio)
 #
 CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
 
 #
 # Obsolete Wireless cards support (pre-802.11)
@@ -513,6 +525,7 @@
 #
 # CONFIG_PRISM54 is not set
 # CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -604,6 +617,8 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_VR41XX is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -634,6 +649,7 @@
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_CARDMAN_4000 is not set
 # CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -669,10 +685,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -681,6 +693,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -703,6 +716,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -756,9 +770,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -772,15 +784,6 @@
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -832,15 +835,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -883,7 +904,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -946,6 +966,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
 
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 925d8ad..1ce4310 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:18 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -120,7 +122,6 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -161,6 +161,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -174,10 +175,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -189,7 +186,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -198,6 +194,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -217,7 +215,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -245,6 +242,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -266,6 +264,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -278,9 +277,12 @@
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 CONFIG_NETFILTER=y
@@ -299,10 +301,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -332,6 +337,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -341,11 +351,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -367,6 +372,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -411,7 +419,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 CONFIG_ATA_OVER_ETH=m
 
@@ -475,7 +483,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -690,6 +697,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -699,6 +707,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -756,10 +765,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -777,6 +782,7 @@
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -788,7 +794,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -832,6 +837,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -849,15 +855,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -914,7 +938,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1025,6 +1048,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="ip=any root=nfs"
 
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index ee1cf9b..8a6aa50 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:19 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:10 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -139,7 +141,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -155,6 +156,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -168,10 +170,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -185,6 +183,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -204,7 +203,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -222,6 +220,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -236,6 +235,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -256,12 +256,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -273,6 +276,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -282,11 +290,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -351,7 +357,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -542,6 +548,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -551,6 +558,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -609,10 +617,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -643,6 +647,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -660,15 +665,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -711,7 +734,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -778,6 +800,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index d80ff27..f9ee35e 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:20 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,7 +123,6 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -144,7 +145,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -160,6 +160,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -191,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -236,6 +235,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -256,12 +256,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -273,6 +276,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -282,11 +290,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -307,6 +310,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -346,7 +352,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -563,10 +569,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -597,6 +599,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -613,14 +616,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -663,7 +684,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -730,6 +750,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index c0f508d..b48bdee 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:21 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:11 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -142,7 +144,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -158,6 +159,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -171,10 +173,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -188,6 +186,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -207,7 +206,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -225,6 +223,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -239,6 +238,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
@@ -259,12 +259,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -276,6 +279,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -285,11 +293,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -310,6 +313,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=y
 CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_SOFTMAC=y
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -354,7 +360,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -545,6 +551,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -554,6 +561,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -612,10 +620,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -646,6 +650,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -663,15 +668,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -714,7 +737,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -781,6 +803,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 194b3c7..01aac40 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:22 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:12 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -116,11 +118,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -138,7 +140,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +155,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -183,7 +181,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -192,6 +189,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -247,6 +246,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -269,7 +269,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -280,6 +281,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -296,10 +299,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -323,6 +329,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -332,11 +343,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -358,6 +364,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -414,7 +423,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -436,7 +444,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -473,7 +480,7 @@
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -716,10 +723,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -750,6 +753,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
 #
@@ -767,14 +771,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -830,7 +852,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -939,6 +960,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 8985725..398c3c2 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:24 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +154,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -191,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -210,7 +209,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -253,6 +251,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -275,7 +274,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -302,10 +304,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -420,7 +428,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -485,7 +491,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -750,6 +756,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -761,6 +768,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -826,10 +834,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -854,6 +858,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -871,15 +876,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -935,7 +958,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1044,6 +1066,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index adbf997..ea282a5 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:25 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:13 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -115,11 +117,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 CONFIG_64BIT_PHYS_ADDR=y
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +139,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +154,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -182,7 +180,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -191,6 +188,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -210,7 +209,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -253,6 +251,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -275,7 +274,8 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -286,6 +286,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -302,10 +304,13 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -329,6 +334,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -338,11 +348,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -364,6 +369,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -420,7 +428,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -443,7 +450,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -485,7 +491,7 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -742,6 +748,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -753,6 +760,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -818,10 +826,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -846,6 +850,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -863,15 +868,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -927,7 +950,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1036,6 +1058,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index b5db700..4c57e56 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:26 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,11 +116,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -136,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +154,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +179,6 @@
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -190,6 +187,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -209,7 +208,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
@@ -238,6 +236,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -257,12 +256,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -274,6 +276,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -283,11 +290,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -469,7 +471,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -671,6 +672,7 @@
 # Non-8250 serial port support
 #
 # CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -723,6 +725,7 @@
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -730,10 +733,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -742,6 +741,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -764,6 +764,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -827,9 +828,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -844,15 +843,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -902,15 +892,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -956,7 +964,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1067,6 +1074,7 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
 CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 4187287..3c8f351 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:28 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:14 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -114,12 +116,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_ADVANCED=y
 CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_WB is not set
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -137,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +154,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +168,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +178,6 @@
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -190,6 +186,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -209,7 +207,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_MMU=y
 
 #
@@ -237,6 +234,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -256,6 +254,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -268,9 +267,12 @@
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 CONFIG_NETFILTER=y
@@ -287,10 +289,12 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -320,6 +324,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -329,11 +338,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -521,7 +525,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -757,6 +760,7 @@
 # Non-8250 serial port support
 #
 # CONFIG_SERIAL_IP3106 is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -816,7 +820,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -835,9 +838,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -867,6 +868,7 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
 # CONFIG_SENSORS_GL518SM is not set
@@ -901,10 +903,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -913,6 +911,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -922,6 +921,7 @@
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -933,7 +933,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -970,6 +969,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1030,9 +1030,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1047,15 +1045,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1106,15 +1095,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1171,7 +1178,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1280,6 +1286,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 31f5afa..4bcc01d 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Sun Feb 12 19:18:55 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:15 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_COHERENT=y
 CONFIG_GENERIC_ISA_DMA=y
@@ -115,16 +117,17 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_SMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -147,6 +150,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
@@ -159,10 +163,6 @@
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_SHMEM is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=1
@@ -177,6 +177,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -196,6 +198,7 @@
 #
 CONFIG_ISA=y
 CONFIG_MMU=y
+CONFIG_I8253=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -241,12 +244,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -308,7 +314,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -530,10 +536,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -552,6 +554,7 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
@@ -565,6 +568,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -581,15 +585,28 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
 
 #
@@ -632,7 +649,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 
 #
 # Miscellaneous filesystems
@@ -680,6 +696,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index b126f76..3d44193 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:30 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
 #
 CONFIG_MIPS=y
 
@@ -71,6 +71,8 @@
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND is not set
 # CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -121,10 +123,9 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_ADVANCED=y
 CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_WB=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -145,7 +146,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -162,6 +162,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -175,10 +176,6 @@
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -190,7 +187,6 @@
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -199,6 +195,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -218,7 +216,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_ISA=y
 CONFIG_MMU=y
 
@@ -247,6 +244,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -267,6 +265,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -279,9 +278,12 @@
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 CONFIG_NETFILTER=y
@@ -300,10 +302,12 @@
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -333,6 +337,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -342,11 +351,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -369,6 +373,9 @@
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -425,7 +432,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -447,7 +453,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -702,6 +707,7 @@
 # Wireless LAN (non-hamradio)
 #
 CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
 
 #
 # Obsolete Wireless cards support (pre-802.11)
@@ -715,6 +721,8 @@
 #
 # CONFIG_IPW2100 is not set
 CONFIG_IPW2200=m
+# CONFIG_IPW2200_MONITOR is not set
+# CONFIG_IPW_QOS is not set
 # CONFIG_IPW2200_DEBUG is not set
 # CONFIG_HERMES is not set
 # CONFIG_ATMEL is not set
@@ -724,6 +732,7 @@
 #
 # CONFIG_PRISM54 is not set
 # CONFIG_HOSTAP is not set
+# CONFIG_BCM43XX is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -821,7 +830,12 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
+# CONFIG_SERIAL_TXX9_CONSOLE is not set
+# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -874,6 +888,7 @@
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -881,10 +896,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -893,6 +904,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -902,6 +914,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
@@ -913,7 +926,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 CONFIG_FB_ATY=y
@@ -934,6 +946,7 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
@@ -954,6 +967,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1003,9 +1017,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 CONFIG_USB_YEALINK=m
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1019,15 +1031,6 @@
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1078,15 +1081,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1148,7 +1169,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1266,6 +1286,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 463ed3d..edfb967 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:31 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:16 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARC=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
@@ -122,7 +124,6 @@
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -145,7 +146,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -163,6 +163,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -176,10 +177,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -191,7 +188,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -200,6 +196,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -220,10 +218,10 @@
 CONFIG_HW_HAS_EISA=y
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_ISA=y
 # CONFIG_EISA is not set
 CONFIG_MMU=y
+CONFIG_I8253=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -250,6 +248,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=m
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -272,6 +271,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -284,9 +284,12 @@
 # CONFIG_IP_VS is not set
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
@@ -309,11 +312,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
@@ -337,20 +343,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -368,6 +373,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -388,12 +394,10 @@
 CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_FRAG=m
 CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_TARGET_REJECT=m
@@ -439,21 +443,22 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-CONFIG_BRIDGE=m
-# CONFIG_VLAN_8021Q is not set
-CONFIG_DECNET=m
-# CONFIG_DECNET_ROUTER 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
 
 #
 # TIPC Configuration (EXPERIMENTAL)
 #
 # CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+# 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
@@ -533,6 +538,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -620,6 +628,7 @@
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -700,12 +709,11 @@
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -731,6 +739,7 @@
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -965,6 +974,7 @@
 # Serial drivers
 #
 CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -977,6 +987,7 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -1027,12 +1038,19 @@
 # Dallas's 1-wire bus
 #
 CONFIG_W1=m
-CONFIG_W1_MATROX=m
-CONFIG_W1_DS9490=m
-# CONFIG_W1_DS9490_BRIDGE is not set
-CONFIG_W1_THERM=m
-CONFIG_W1_SMEM=m
-# CONFIG_W1_DS2433 is not set
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+# CONFIG_W1_MASTER_DS9490 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
 
 #
 # Hardware Monitoring support
@@ -1045,10 +1063,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -1057,6 +1071,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+CONFIG_USB_DABUSB=m
 
 #
 # Graphics support
@@ -1067,6 +1082,7 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
 # CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
@@ -1080,6 +1096,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -1151,9 +1168,7 @@
 # CONFIG_USB_ACECAD is not set
 CONFIG_USB_KBTAB=m
 CONFIG_USB_POWERMATE=m
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-CONFIG_USB_EGALAX=m
+# CONFIG_USB_TOUCHSCREEN is not set
 CONFIG_USB_YEALINK=m
 CONFIG_USB_XPAD=m
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1168,15 +1183,6 @@
 CONFIG_USB_MICROTEK=m
 
 #
-# USB Multimedia devices
-#
-CONFIG_USB_DABUSB=m
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 CONFIG_USB_CATC=m
@@ -1213,6 +1219,7 @@
 CONFIG_USB_SERIAL_CYPRESS_M8=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 CONFIG_USB_SERIAL_VISOR=m
 CONFIG_USB_SERIAL_IPAQ=m
 CONFIG_USB_SERIAL_IR=m
@@ -1237,6 +1244,7 @@
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_SERIAL_HP4X=m
 CONFIG_USB_SERIAL_SAFE=m
@@ -1281,15 +1289,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -1358,7 +1384,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1379,7 +1404,6 @@
 CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -1500,6 +1524,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index da68c3f..e388a3d 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:32 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
 #
 CONFIG_MIPS=y
 
@@ -81,6 +81,8 @@
 # CONFIG_SIBYTE_SB1250_PROF is not set
 # CONFIG_SIBYTE_TBPROF is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -158,7 +160,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -175,6 +176,7 @@
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_CPUSETS=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -188,10 +190,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -203,7 +201,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -212,6 +209,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -231,7 +229,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -249,6 +246,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
 CONFIG_MIPS32_COMPAT=y
 CONFIG_COMPAT=y
 CONFIG_MIPS32_O32=y
@@ -263,6 +261,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -284,12 +283,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -301,6 +303,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -310,11 +317,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -335,6 +337,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -589,6 +594,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -647,10 +653,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -675,6 +677,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -692,15 +695,33 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -746,7 +767,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -812,6 +832,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 # CONFIG_SB1XXX_CORELIS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 9a936d7..6b8a6a4 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:33 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:17 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -118,11 +120,11 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -140,7 +142,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -154,6 +155,7 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_IKCONFIG is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -167,10 +169,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -185,6 +183,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -296,12 +296,6 @@
 #
 
 #
-# Network device support
-#
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
 # ISDN subsystem
 #
 
@@ -397,10 +391,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -424,6 +414,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -440,14 +431,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -489,7 +498,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -543,6 +551,8 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index c2dee0d..dba0bdc 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:34 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:41 2006
 #
 CONFIG_MIPS=y
 
@@ -68,12 +68,14 @@
 # CONFIG_NEC_CMBVR4133 is not set
 CONFIG_TANBAC_TB022X=y
 CONFIG_TANBAC_TB0226=y
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
 # CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +157,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -189,6 +189,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -208,7 +211,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_MMU=y
 
 #
@@ -226,6 +228,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
@@ -235,11 +238,10 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -263,12 +265,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -280,6 +285,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -289,11 +299,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -310,10 +315,7 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -358,11 +360,12 @@
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -397,14 +400,14 @@
 # SCSI Transport Attributes
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=y
-CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
-CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
@@ -424,7 +427,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -507,8 +509,8 @@
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -625,6 +627,11 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -685,10 +692,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -697,6 +700,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -719,6 +723,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -756,7 +761,7 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
@@ -783,9 +788,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -800,15 +803,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -816,7 +810,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
+# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
@@ -860,15 +854,50 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -911,7 +940,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -952,9 +980,7 @@
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -970,46 +996,7 @@
 #
 # Native Language Support
 #
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-CONFIG_NLS_CODEPAGE_932=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
 
 #
 # Profiling support
@@ -1023,44 +1010,20 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,115200"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -1069,9 +1032,8 @@
 #
 # Library routines
 #
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index be99261..5a924c1 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:35 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:08:59 2006
 #
 CONFIG_MIPS=y
 
@@ -68,12 +68,14 @@
 # CONFIG_NEC_CMBVR4133 is not set
 CONFIG_TANBAC_TB022X=y
 # CONFIG_TANBAC_TB0226 is not set
-CONFIG_TANBAC_TB0287=y
+# CONFIG_TANBAC_TB0287 is not set
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
 # CONFIG_VRC4173 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -92,7 +94,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -105,18 +107,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,7 +142,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -153,6 +157,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -166,10 +171,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -181,7 +182,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -189,6 +189,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -208,7 +211,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-# CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_MMU=y
 
 #
@@ -226,6 +228,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
@@ -235,11 +238,10 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -264,12 +266,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -281,6 +286,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -290,11 +300,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -311,10 +316,7 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -325,12 +327,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+# CONFIG_FW_LOADER is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -363,10 +365,8 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -443,30 +443,7 @@
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-CONFIG_8139TOO=y
-CONFIG_8139TOO_PIO=y
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_PCI is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -483,7 +460,6 @@
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
 # CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 
@@ -510,19 +486,8 @@
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -583,6 +548,11 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -607,6 +577,7 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -642,10 +613,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -654,6 +621,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -676,6 +644,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -731,9 +700,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -747,15 +714,6 @@
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -807,46 +765,65 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_VR41XX=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
+# CONFIG_EXT3_FS is not set
 # CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_SECURITY is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
+# CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_XFS_FS=y
-CONFIG_XFS_EXPORT=y
-CONFIG_XFS_QUOTA=y
-# CONFIG_XFS_SECURITY is not set
-CONFIG_XFS_POSIX_ACL=y
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=m
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
@@ -855,20 +832,14 @@
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_ISO9660_FS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -880,7 +851,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -921,9 +891,7 @@
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -939,46 +907,7 @@
 #
 # Native Language Support
 #
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-CONFIG_NLS_CODEPAGE_932=m
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
 
 #
 # Profiling support
@@ -992,44 +921,20 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -1038,9 +943,8 @@
 #
 # Library routines
 #
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644
index 0000000..9f215ea
--- /dev/null
+++ b/arch/mips/configs/tb0287_defconfig
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:17 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0287=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE 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_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_TANBAC_TB0219 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+CONFIG_FB_SMIVGX=y
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# 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
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 7132e29..ac7765e 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:36 2006
+# Linux kernel version: 2.6.17-rc2
+# Tue Apr 25 00:09:33 2006
 #
 CONFIG_MIPS=y
 
@@ -70,6 +70,8 @@
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
@@ -88,7 +90,7 @@
 # CONFIG_CPU_MIPS64_R2 is not set
 # CONFIG_CPU_R3000 is not set
 # CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
+CONFIG_CPU_VR41XX=y
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
@@ -101,18 +103,21 @@
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
 #
-# CONFIG_32BIT is not set
+CONFIG_32BIT=y
 # CONFIG_64BIT is not set
 CONFIG_PAGE_SIZE_4KB=y
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
 # CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
@@ -133,7 +138,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -149,6 +153,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -162,10 +167,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -177,7 +178,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -185,6 +185,9 @@
 #
 # Block layer
 #
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -220,6 +223,7 @@
 # CONFIG_I82365 is not set
 # CONFIG_TCIC is not set
 CONFIG_PCMCIA_PROBE=y
+CONFIG_PCMCIA_VRC4171=y
 
 #
 # PCI Hotplug Support
@@ -230,6 +234,7 @@
 #
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
 
 #
 # Networking
@@ -239,6 +244,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -258,12 +264,15 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -275,6 +284,11 @@
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -284,11 +298,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -305,10 +314,8 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
+# CONFIG_IEEE80211 is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -347,10 +354,12 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -468,7 +477,38 @@
 #
 # Wireless LAN (non-hamradio)
 #
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
 
 #
 # PCMCIA network device support
@@ -512,10 +552,7 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
@@ -533,11 +570,7 @@
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -556,6 +589,10 @@
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -568,20 +605,7 @@
 #
 # Watchdog Cards
 #
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-
-#
-# ISA-based Watchdog Cards
-#
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_WDT is not set
+# CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -597,6 +621,7 @@
 # CONFIG_SYNCLINK_CS is not set
 # CONFIG_CARDMAN_4000 is not set
 # CONFIG_CARDMAN_4040 is not set
+# CONFIG_GPIO_VR41XX is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -632,10 +657,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -667,6 +688,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -683,14 +705,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -710,7 +750,7 @@
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 CONFIG_FUSE_FS=m
 
@@ -733,10 +773,9 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -802,44 +841,20 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -849,8 +864,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6745785..b52d709 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:40:37 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:51:20 2006
 #
 CONFIG_MIPS=y
 
@@ -65,6 +65,8 @@
 # CONFIG_TOSHIBA_RBTX4938 is not set
 # CONFIG_HYPERTRANSPORT is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_COHERENT=y
 CONFIG_CPU_BIG_ENDIAN=y
@@ -116,7 +118,6 @@
 CONFIG_CPU_HAS_PREFETCH=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -140,7 +141,6 @@
 # Code maturity level options
 #
 # CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -157,6 +157,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
@@ -170,10 +171,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -184,7 +181,6 @@
 #
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -194,6 +190,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -213,7 +211,6 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 CONFIG_MMU=y
 
@@ -241,6 +238,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=m
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -261,16 +259,19 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_NETFILTER is not set
@@ -340,10 +341,9 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
 CONFIG_ATA_OVER_ETH=m
 
 #
@@ -433,6 +433,7 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_R8169 is not set
 # CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
@@ -497,6 +498,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -506,6 +508,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -563,10 +566,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -591,6 +590,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -608,12 +608,29 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
 #
 
 #
@@ -656,7 +673,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 
 #
 # Miscellaneous filesystems
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
index 488206b..304c021 100644
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -3,6 +3,6 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o
+obj-y			+= setup.o irq.o nile4_pic.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644
index a786441..0000000
--- a/arch/mips/ddb5xxx/ddb5074/int-handler.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- *  Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(ddbIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-#if 1
-	mfc0	t2,CP0_STATUS		# get enabled interrupts
-	and	s0,t2			# isolate allowed ones
-#endif
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
-
-	/* Wheee, local level zero interrupt. */
-	jal	ddb_local0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
-
-	/* Wheee, local level one interrupt. */
-	move	a0, sp
-	jal	ddb_local1_irqdispatch
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	beq	a0, zero, 1f
-	 nop
-
-	/* Wheee, an asynchronous bus error... */
-	move	a0, sp
-	jal	ddb_buserror_irq
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	/* Here by mistake?  This is possible, what can happen
-	 * is that by the time we take the exception the IRQ
-	 * pin goes low, so just leave if this is the case.
-	 */
-	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
-	beq	a0, zero, 1f
-
-	/* Must be one of the 8254 timers... */
-	move	a0, sp
-	jal	ddb_8254timer_irq
-	 nop
-1:
-	j	ret_from_irq
-	 nop
-	END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
index 45088a1..60c087b 100644
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -21,8 +21,6 @@
 #include <asm/ddb5xxx/ddb5074.h>
 
 
-extern asmlinkage void ddbIRQ(void);
-
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 #define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
@@ -90,7 +88,7 @@
 
 }
 
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
 	u32 mask;
 	int nile4_irq;
@@ -118,29 +116,41 @@
 		}
 }
 
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
 {
 	printk("ddb_local1_irqdispatch called\n");
 }
 
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
 {
 	printk("ddb_buserror_irq called\n");
 }
 
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
 {
 	printk("ddb_8254timer_irq called\n");
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & CAUSEF_IP2)
+		ddb_local0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		ddb_local1_irqdispatch();
+	else if (pending & CAUSEF_IP6)
+		ddb_buserror_irq();
+	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+		ddb_8254timer_irq();
+}
+
 void __init arch_init_irq(void)
 {
 	/* setup cascade interrupts */
 	setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
 
-	set_except_vector(0, ddbIRQ);
-
 	nile4_irq_setup(NILE4_IRQ_BASE);
 	m1543_irq_setup();
 	init_i8259_irqs();
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
index 61eec36..ab0312c 100644
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y			+= setup.o irq.o nile4_pic.o vrc5476_irq.o
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644
index 12c292e..0000000
--- a/arch/mips/ddb5xxx/ddb5476/int-handler.S
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5476_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-        andi    t1, t0, STATUSF_IP7     /* cpu timer */
-        bnez    t1, ll_cpu_ip7
-        andi    t1, t0, STATUSF_IP2	/* vrc5476 & i8259 */
-        bnez    t1, ll_cpu_ip2
-        andi    t1, t0, STATUSF_IP3
-        bnez    t1, ll_cpu_ip3
-        andi    t1, t0, STATUSF_IP4
-        bnez    t1, ll_cpu_ip4
-        andi    t1, t0, STATUSF_IP5
-        bnez    t1, ll_cpu_ip5
-        andi    t1, t0, STATUSF_IP6
-        bnez    t1, ll_cpu_ip6
-        andi    t1, t0, STATUSF_IP0     /* software int 0 */
-        bnez    t1, ll_cpu_ip0
-        andi    t1, t0, STATUSF_IP1     /* software int 1 */
-        bnez    t1, ll_cpu_ip1
-        nop
-
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	// j	spurious_interrupt
-	move 	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-	nop
-
-	.align	5
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip2:		/* jump to second-level dispatching */
-	move	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-
-ll_cpu_ip3:
-	li	a0, CPU_IRQ_BASE + 3
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip4:
-	li	a0, CPU_IRQ_BASE + 4
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip5:
-	li	a0, CPU_IRQ_BASE + 5
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip6:
-	li	a0, CPU_IRQ_BASE + 6
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip7:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-	END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
index 5388b58..7583a1f 100644
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -110,11 +110,36 @@
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
 
-extern asmlinkage void ddb5476_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 extern void mips_cpu_irq_init(u32 irq_base);
 extern void vrc5476_irq_init(u32 irq_base);
 
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & STATUSF_IP2)
+		vrc5476_irq_dispatch(regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(CPU_IRQ_BASE + 3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(CPU_IRQ_BASE + 4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(CPU_IRQ_BASE + 5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(CPU_IRQ_BASE + 6, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+	vrc5476_irq_dispatch(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	/* hardware initialization */
@@ -137,7 +162,4 @@
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
-	/* setup the grandpa intr vector */
-	set_except_vector(0, ddb5476_handle_int);
 }
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index f66fe5b..a3c5e7b 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -77,11 +77,9 @@
 }
 
 
-asmlinkage void
+void
 vrc5476_irq_dispatch(struct pt_regs *regs)
 {
-	extern void spurious_interrupt(void);
-
 	u32 mask;
 	int nile4_irq;
 
@@ -107,5 +105,5 @@
 			return;
 		}
 	}
-	spurious_interrupt();
+	spurious_interrupt(regs);
 }
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index b79b43c..ea68815 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,7 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y	 		+= int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y	 		+= irq.o irq_5477.o setup.o lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644
index a2502a1..0000000
--- a/arch/mips/ddb5xxx/ddb5477/int-handler.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5477_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-	andi	t1, t0, STATUSF_IP7	/* cpu timer */
-	bnez	t1, ll_cputimer_irq
-	andi	t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
-	bnez	t1, ll_vrc5477_irq
-	andi	t1, t0, STATUSF_IP0	/* software int 0 */
-	bnez	t1, ll_cpu_ip0
-	andi	t1, t0, STATUSF_IP1	/* software int 1 */
-	bnez	t1, ll_cpu_ip1
-	nop
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	j	spurious_interrupt
-	nop
-	END(ddb5477_handle_int)
-
-	.align	5
-
-ll_vrc5477_irq:
-	move	a0, sp
-	jal	vrc5477_irq_dispatch
-	j	ret_from_irq
-
-ll_cputimer_irq:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 9ffe1a9..de433cf 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -75,7 +75,6 @@
 
 extern void vrc5477_irq_init(u32 base);
 extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
@@ -135,9 +134,6 @@
 	/* setup cascade interrupts */
 	setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
-	/* hook up the first-level interrupt handler */
-	set_except_vector(0, ddb5477_handle_int);
 }
 
 u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define	NUM_5477_IRQS	32
-asmlinkage void
+static void
 vrc5477_irq_dispatch(struct pt_regs *regs)
 {
 	u32 intStatus;
@@ -197,3 +193,21 @@
 		}
 	}
 }
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & VR5477INTS)
+		vrc5477_irq_dispatch(regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/dec/boot/decstation.c b/arch/mips/dec/boot/decstation.c
index 56fd427..4db8bac 100644
--- a/arch/mips/dec/boot/decstation.c
+++ b/arch/mips/dec/boot/decstation.c
@@ -1,6 +1,7 @@
 /*
  * arch/mips/dec/decstation.c
  */
+#include <asm/sections.h>
 
 #define RELOC
 #define INITRD
@@ -24,7 +25,7 @@
 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
 
-extern int _ftext, _end;		/* begin and end of kernel image */
+extern int _ftext;			/* begin and end of kernel image */
 extern void kernel_entry(int, char **, unsigned long, int *);
 
 void * memcpy(void * dest, const void *src, unsigned int count)
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 41fa372..e8ec93e 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -36,7 +36,7 @@
 		.text
 		.set	noreorder
 /*
- * decstation_handle_int: Interrupt handler for DECstations
+ * plat_irq_dispatch: Interrupt handler for DECstations
  *
  * We follow the model in the Indy interrupt code by David Miller, where he
  * says: a lot of complication here is taken away because:
@@ -125,11 +125,7 @@
  * just take another exception, big deal.
  */
 		.align	5
-		NESTED(decstation_handle_int, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI				# TEST: interrupts should be off
-		.set	at
+		NESTED(plat_irq_dispatch, PT_SIZE, ra)
 		.set	noreorder
 
 		/*
@@ -282,9 +278,11 @@
 #endif
 
 spurious:
-		j	spurious_interrupt
+		jal	spurious_interrupt
 		 nop
-		END(decstation_handle_int)
+		j	ret_from_irq
+		 nop
+		END(plat_irq_dispatch)
 
 /*
  * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 7c1ca8f..ad5d436 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -48,8 +48,6 @@
 extern void dec_machine_power_off(void);
 extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
 
-extern asmlinkage void decstation_handle_int(void);
-
 unsigned long dec_kn_slot_base, dec_kn_slot_size;
 
 EXPORT_SYMBOL(dec_kn_slot_base);
@@ -744,7 +742,6 @@
 		panic("Don't know how to set this up!");
 		break;
 	}
-	set_except_vector(0, decstation_handle_int);
 
 	/* Free the FPU interrupt if the exception is present. */
 	if (!cpu_has_nofpuex) {
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 42d5cd7..607e298 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc1
-# Fri Jan 27 15:39:51 2006
+# Linux kernel version: 2.6.17-rc2
+# Mon Apr 24 14:50:54 2006
 #
 CONFIG_MIPS=y
 
@@ -64,6 +64,8 @@
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARC=y
 CONFIG_DMA_NONCOHERENT=y
@@ -121,7 +123,6 @@
 CONFIG_IP22_CPU_SCACHE=y
 # CONFIG_MIPS_MT is not set
 # CONFIG_64BIT_PHYS_ADDR is not set
-# CONFIG_CPU_ADVANCED is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -143,7 +144,6 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -160,6 +160,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
@@ -173,10 +174,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -188,7 +185,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -197,6 +193,8 @@
 # Block layer
 #
 # CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -242,6 +240,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
@@ -264,6 +263,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -305,9 +305,12 @@
 CONFIG_IP_VS_FTP=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
@@ -330,11 +333,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -357,20 +363,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -388,6 +393,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -408,12 +414,10 @@
 CONFIG_IP6_NF_MATCH_OPTS=m
 CONFIG_IP6_NF_MATCH_FRAG=m
 CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
 CONFIG_IP6_NF_MATCH_OWNER=m
 CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_POLICY=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_TARGET_REJECT=m
@@ -435,6 +439,11 @@
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -444,11 +453,6 @@
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
 CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -508,6 +512,9 @@
 # CONFIG_IEEE80211_DEBUG is not set
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_SOFTMAC=m
+# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -546,7 +553,7 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -812,10 +819,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -857,6 +860,7 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -873,14 +877,32 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=m
@@ -944,7 +966,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -963,7 +984,6 @@
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_SYSV_FS is not set
 CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
@@ -1078,6 +1098,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
index 58c02f9..cd868ec 100644
--- a/arch/mips/galileo-boards/ev96100/Makefile
+++ b/arch/mips/galileo-boards/ev96100/Makefile
@@ -6,4 +6,4 @@
 # Makefile for the Galileo EV96100 board.
 #
 
-obj-y		+= init.o irq.o puts.o reset.o time.o int-handler.o setup.o
+obj-y		+= init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
deleted file mode 100644
index ff4d10a..0000000
--- a/arch/mips/galileo-boards/ev96100/int-handler.S
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.set	noat
-	.align	5
-
-NESTED(ev96100IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-	mfc0	t0, CP0_CAUSE		# get pending interrupts
-	mfc0	t1, CP0_STATUS		# get enabled interrupts
-	and	t0, t1			# isolate allowed ones
-
-	# FIX ME add R7000 extensions
-	andi	t0,0xff00		# isolate pending bits
-	andi	a0, t0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	move	a0, sp
-	jal	mips_timer_interrupt
-	j	ret_from_irq
-
-1:	beqz	t0, 3f			# spurious interrupt
-
-	move	a0, t0
-	move	a1, sp
-	jal	ev96100_cpu_irq
-	j	ret_from_irq
-
-3:	j	spurious_interrupt
-	END(ev96100IRQ)
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
index 97bf094..ee5d672 100644
--- a/arch/mips/galileo-boards/ev96100/irq.c
+++ b/arch/mips/galileo-boards/ev96100/irq.c
@@ -40,8 +40,6 @@
 #include <linux/interrupt.h>
 #include <asm/irq_cpu.h>
 
-extern asmlinkage void ev96100IRQ(void);
-
 static inline unsigned int ffz8(unsigned int word)
 {
 	unsigned long k;
@@ -54,13 +52,26 @@
 	return k;
 }
 
-asmlinkage void ev96100_cpu_irq(unsigned int pendin)
+extern void mips_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
 {
 	do_IRQ(ffz8(pending >> 8), regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		mips_timer_interrupt(regs);
+	else if (pending)
+		ev96100_cpu_irq(pending, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, ev96100IRQ);
 	mips_cpu_irq_init(0);
 }
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
index ebe91c5..b2c53a8 100644
--- a/arch/mips/gt64120/ev64120/Makefile
+++ b/arch/mips/gt64120/ev64120/Makefile
@@ -6,6 +6,6 @@
 # Makefile for the Galileo EV64120 board.
 #
 
-obj-y	+= int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+obj-y	+= irq.o promcon.o reset.o serialGT.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
deleted file mode 100644
index 752435f..0000000
--- a/arch/mips/gt64120/ev64120/int-handler.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * galileo_handle_int -
- *      We check for the timer first, then check PCI ints A and D.
- *      Then check for serial IRQ and fall through.
- */
-		.align	5
-		.set	reorder
-		.set	noat
-		NESTED(galileo_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0,CP0_CAUSE
-		mfc0	t2,CP0_STATUS
-
-		and	t0,t2
-
-		andi	t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
-		bnez	t1,ll_gt64120_irq
-		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
-		bnez	t1,ll_pci_intA
-		andi	t1,t0,STATUSF_IP5 /* int3 hardware line */
-		bnez	t1,ll_pci_intD
-		andi	t1,t0,STATUSF_IP6 /* int4 hardware line */
-		bnez	t1,ll_serial_irq
-		andi	t1,t0,STATUSF_IP7 /* compare int */
-		bnez	t1,ll_compare_irq
-		nop
-
-    /* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(galileo_handle_int)
-
-
-		.align	5
-		.set	reorder
-ll_gt64120_irq:
-		li	a0,4
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_compare_irq:
-		li 	a0,7
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_pci_intA:
-		move	a0,sp
-		jal	pci_intA
-		nop
-		j	ret_from_irq
-		nop
-
-#if 0
-		.align	5
-		.set	reorder
-ll_pci_intB:
-		move 	a0,sp
-		jal	pci_intB
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_pci_intC:
-		move 	a0,sp
-		jal	pci_intC
-		nop
-		j	ret_from_irq
-		nop
-#endif
-
-		.align	5
-		.set	reorder
-ll_pci_intD:
-		move 	a0,sp
-		jal	pci_intD
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_serial_irq:
-		li	a0,6
-		move	a1,sp
-		jal	do_IRQ
-		nop
-		j	ret_from_irq
-		nop
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
index 3b18615..46c468b 100644
--- a/arch/mips/gt64120/ev64120/irq.c
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -46,14 +46,22 @@
 #include <asm/system.h>
 #include <asm/gt64120.h>
 
-asmlinkage inline void pci_intA(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
-	do_IRQ(GT_INTA, regs);
-}
+	unsigned int pending = read_c0_status() & read_c0_cause();
 
-asmlinkage inline void pci_intD(struct pt_regs *regs)
-{
-	do_IRQ(GT_INTD, regs);
+	if (pending & STATUSF_IP4)		/* int2 hardware line (timer) */
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP2)		/* int0 hardware line */
+		do_IRQ(GT_INTA, regs);
+	else if (pending & STATUSF_IP5)		/* int3 hardware line */
+		do_IRQ(GT_INTD, regs);
+	else if (pending & STATUSF_IP6)		/* int4 hardware line */
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)		/* compare int */
+		do_IRQ(7, regs);
+	else
+		spurious_interrupt(regs);
 }
 
 static void disable_ev64120_irq(unsigned int irq_nr)
@@ -109,16 +117,11 @@
 
 void gt64120_irq_setup(void)
 {
-	extern asmlinkage void galileo_handle_int(void);
-
 	/*
 	 * Clear all of the interrupts while we change the able around a bit.
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the exception_handler array. */
-	set_except_vector(0, galileo_handle_int);
-
 	local_irq_disable();
 
 	/*
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 7b59c65..6f708df 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum's Ocelot board.
 #
 
-obj-y	 		+= int-handler.o irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
deleted file mode 100644
index 808acef..0000000
--- a/arch/mips/gt64120/momenco_ocelot/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		 andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pri_enet_irq
-		 andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_sec_enet_irq
-		 andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_uart1_irq
-		 andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_irq
-		 andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_galileo_irq
-		 andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		 sll	t2, t1, 8
-
-		 and	t0, t2
-		 srl	t0, t0, 16
-
-		 andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_pmc1_irq
-		 andi	t1, t0, STATUSF_IP9	/* int7 hardware line */
-		bnez	t1, ll_pmc2_irq
-		 andi	t1, t0, STATUSF_IP10	/* int8 hardware line */
-		bnez	t1, ll_cpci_abcd_irq
-		 andi	t1, t0, STATUSF_IP11	/* int9 hardware line */
-		bnez	t1, ll_uart2_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot_handle_int)
-
-		.align	5
-ll_pri_enet_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_sec_enet_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart1_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc1_irq:
-		li	a0, 8
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc2_irq:
-		li	a0, 9
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_abcd_irq:
-		li	a0, 10
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart2_irq:
-		li	a0, 11
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
index 4f108da..885f67f 100644
--- a/arch/mips/gt64120/momenco_ocelot/irq.c
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -48,7 +48,38 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP2)		/* int0 hardware line */
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)		/* int1 hardware line */
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)		/* int2 hardware line */
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)		/* int3 hardware line */
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)		/* int4 hardware line */
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)		/* cpu timer */
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)		/* int6 hardware line */
+			do_IRQ(8, regs);
+		else if (pending & STATUSF_IP9)		/* int7 hardware line */
+			do_IRQ(9, regs);
+		else if (pending & STATUSF_IP10)	/* int8 hardware line */
+			do_IRQ(10, regs);
+		else if (pending & STATUSF_IP11)	/* int9 hardware line */
+			do_IRQ(11, regs);
+	}
+}
 
 void __init arch_init_irq(void)
 {
@@ -59,9 +90,6 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
-
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 }
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
index 0e7853f..6343153 100644
--- a/arch/mips/ite-boards/generic/Makefile
+++ b/arch/mips/ite-boards/generic/Makefile
@@ -6,7 +6,7 @@
 # Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
 #
 
-obj-y			+= it8172_setup.o irq.o int-handler.o pmon_prom.o \
+obj-y			+= it8172_setup.o irq.o pmon_prom.o \
 			   time.o lpc.o puts.o reset.o
 
 obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
deleted file mode 100644
index d190d8a..0000000
--- a/arch/mips/ite-boards/generic/int-handler.S
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set    macro
-	.set    noat
-	.align	5
-
-NESTED(it8172_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-
-        /* We're working with 'reorder' set at this point. */
-	/*
-	 * Get pending interrupts
-	 */
-
-	mfc0	t0,CP0_CAUSE		# get pending interrupts
-	mfc0	t1,CP0_STATUS		# get enabled interrupts
-	and	t0,t1			# isolate allowed ones
-
-	andi	t0,0xff00		# isolate pending bits
-        beqz    t0, 3f                  # spurious interrupt
-
-        andi    a0, t0, CAUSEF_IP7
-        beq     a0, zero, 1f
-
-        li	a0, 127			# MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
-        move    a1, sp
-        jal     ll_timer_interrupt
-	j	ret_from_irq
-        nop
-
-1:
-        andi    a0, t0, CAUSEF_IP2      # the only int we expect at this time
-        beq     a0, zero, 3f
-	move	a0,sp
-	jal	it8172_hw0_irqdispatch
-
-	mfc0	t0,CP0_STATUS		# disable interrupts
-	ori	t0,1
-	xori	t0,1
-	mtc0	t0,CP0_STATUS
-        nop
-        nop
-        nop
-
-	la      a1, ret_from_irq
-	jr	a1
-        nop
-
-3:
-	move a0, sp
-	jal	mips_spurious_interrupt
-        nop
-	la      a1, ret_from_irq
-	jr	a1
-        nop
-
-END(it8172_IRQ)
-
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
index e67f961..77be721 100644
--- a/arch/mips/ite-boards/generic/irq.c
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -62,12 +62,8 @@
 
 #define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
 
-void disable_it8172_irq(unsigned int irq_nr);
-void enable_it8172_irq(unsigned int irq_nr);
-
 extern void set_debug_traps(void);
 extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
-extern asmlinkage void it8172_IRQ(void);
 
 struct it8172_intc_regs volatile *it8172_hw0_icregs =
 	(struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
@@ -181,8 +177,6 @@
 	int i;
         unsigned long flags;
 
-        set_except_vector(0, it8172_IRQ);
-
 	/* mask all interrupts */
 	it8172_hw0_icregs->lb_mask  = 0xffff;
 	it8172_hw0_icregs->lpc_mask = 0xffff;
@@ -282,6 +276,18 @@
 	do_IRQ(irq, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (!pending)
+		mips_spurious_interrupt(regs);
+	else if (pending & CAUSEF_IP7)
+		ll_timer_interrupt(127, regs);
+	else if (pending & CAUSEF_IP2)
+		it8172_hw0_irqdispatch(regs);
+}
+
 void show_pending_irqs(void)
 {
 	fputs("intstatus:  ");
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
index b79817b..dee497a 100644
--- a/arch/mips/ite-boards/generic/time.c
+++ b/arch/mips/ite-boards/generic/time.c
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
 
 #include <asm/time.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c
index b774db0..05cf921 100644
--- a/arch/mips/ite-boards/ivr/init.c
+++ b/arch/mips/ite-boards/ivr/init.c
@@ -34,13 +34,13 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <asm/sections.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
 
-extern char _end;
 extern void  __init prom_init_cmdline(void);
 extern unsigned long __init prom_get_memsize(void);
 extern void __init it8172_init_ram_resource(unsigned long memsize);
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
index e8ec8be..ea2a754 100644
--- a/arch/mips/ite-boards/qed-4n-s01b/init.c
+++ b/arch/mips/ite-boards/qed-4n-s01b/init.c
@@ -34,13 +34,13 @@
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <asm/sections.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
 
-extern char _end;
 extern void  __init prom_init_cmdline(void);
 extern unsigned long __init prom_get_memsize(void);
 extern void __init it8172_init_ram_resource(unsigned long memsize);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index 8574924..02bd39a 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-obj-y	 	:= int-handler.o irq.o jazzdma.o reset.o setup.o
+obj-y	 	:= irq.o jazzdma.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
deleted file mode 100644
index dc752c6..0000000
--- a/arch/mips/jazz/int-handler.S
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
- *
- * Jazz family specific interrupt stuff
- *
- * To do: On Jazz machines we remap some non-ISA interrupts to ISA
- *        interrupts.  These interrupts should use their own vectors.
- *        Squeeze the last cycles out of the handlers.  Only a dead
- *        cycle is a good cycle.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
- */
-		.set	noreorder
-
-		NESTED(jazz_handle_int, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-		beqz	t0,3f
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow - use binary search
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-2:		lw	t0,(t1)
-		jr	t0
-		nop				# delay slot
-		END(jazz_handle_int)
-
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-		PANIC("Unimplemented sw0 handler")
-
-ll_sw1:		li	s1,~IE_SW1
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-		PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:	li	s1,~IE_IRQ0
-		PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:	lbu	t0,JAZZ_IO_IRQ_SOURCE
-#if PTRSIZE == 8	/* True 64 bit kernel */
-		dsll	t0,1
-#endif
-		.set	reorder
-		LONG_L	t0,local_vector(t0)
-		jr	t0
-		.set	noreorder
-
-/*
- * The braindead PICA hardware gives us no way to distinguish if we really
- * received interrupt 7 from the (E)ISA bus or if we just received an
- * interrupt with no findable cause.  This sometimes happens with braindead
- * cards.  Oh well - for all the Jazz boxes slots are more or less just
- * whistles and bells and we're aware of the problem.
- */
-ll_isa_irq:	lw	a0, JAZZ_EISA_IRQ_ACK
-
-		jal	do_IRQ
-		 move	a1,sp
-
-		j	ret_from_irq
-		nop
-
-/*
- * Hmm...  This is not just a plain PC clone so the question is
- * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistent memory?)
- */
-ll_isa_nmi:	li	s1,~IE_IRQ3
-		PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ - remapped to be more similar to an IBM compatible.
- *
- * The timer interrupt is handled specially to ensure that the jiffies
- * variable is updated at all times.  Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them.  If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
- */
-ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
-		li	s1,~IE_IRQ4
-
-		li	a0, JAZZ_TIMER_IRQ
-		jal	do_IRQ
-		 move	a1,sp
-
-		mfc0	t0,CP0_STATUS		# disable interrupts again
-		ori	t0,1
-		xori	t0,1
-		mtc0	t0,CP0_STATUS
-
-		j	ret_from_irq
-		 nop
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:	j	ret_from_irq
-		 mtc0	zero,CP0_COMPARE
-
-#if 0
-/*
- * Call the handler for the interrupt
- * (Currently unused)
- */
-call_real:	/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-		mtc0	t2,CP0_STATUS
-		nor	s1,zero,s1
-		jal	do_IRQ
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-		j	ret_from_irq
-#endif
-
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_local_dma		# Local DMA
-		PTR	ll_local_dev		# Local devices
-		PTR	ll_isa_irq		# ISA IRQ
-		PTR	ll_isa_nmi		# ISA NMI
-		PTR	ll_timer		# Timer
-ll_vectors:	PTR	ll_count		# Count/Compare IRQ
-
-		/*
-		 * Interrupt handlers for local devices.
-		 */
-		.text
-		.set	reorder
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ
- */
-loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
-		li	a0,JAZZ_PARALLEL_IRQ
-		b	loc_call
-
-/*
- * Floppy IRQ
- */
-loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
-		li	a0,JAZZ_FLOPPY_IRQ
-		b	loc_call
-
-/*
- * Sound IRQ
- */
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler
- */
-loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
-		li	a0,JAZZ_ETHERNET_IRQ
-		b	loc_call
-
-/*
- * SCSI interrupt handler
- */
-loc_scsi:	li	s1,~JAZZ_IE_SCSI
-		li	a0,JAZZ_SCSI_IRQ
-		b	loc_call
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:	li	s1,~JAZZ_IE_KEYBOARD
-		li	a0,JAZZ_KEYBOARD_IRQ
-		b	loc_call
-
-/*
- * Mouse interrupt handler
- */
-loc_mouse:	li	s1,~JAZZ_IE_MOUSE
-		li	a0,JAZZ_MOUSE_IRQ
-		b	loc_call
-
-/*
- * Serial port 1 IRQ
- */
-loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
-		li	a0,JAZZ_SERIAL1_IRQ
-		b	loc_call
-
-/*
- * Serial port 2 IRQ
- */
-loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
-		li	a0,JAZZ_SERIAL2_IRQ
-		b	loc_call
-
-/*
- * Call the interrupt handler for an interrupt generated by a
- * local device.
- */
-loc_call:	/*
-		 * Temporarily disable interrupt source
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		and	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-
-		nor	s1,zero,s1
-		jal	do_IRQ
-
-		/*
-		 * Reenable interrupt
-		 */
-		lhu	t2,JAZZ_IO_IRQ_ENABLE
-		or	t2,s1
-		sh	t2,JAZZ_IO_IRQ_ENABLE
-
-		j	ret_from_irq
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3:		j	spurious_interrupt
-
-/*
- * Vectors for interrupts generated by local devices
- */
-		.data
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index b309b1b..becc9ac 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -15,8 +15,6 @@
 #include <asm/io.h>
 #include <asm/jazz.h>
 
-extern asmlinkage void jazz_handle_int(void);
-
 static DEFINE_SPINLOCK(r4030_lock);
 
 static void enable_r4030_irq(unsigned int irq)
@@ -90,10 +88,82 @@
  */
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, jazz_handle_int);
-
 	init_i8259_irqs();			/* Integrated i8259  */
 	init_r4030_ints();
 
 	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 }
+
+static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+{
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
+	do_IRQ(irq, regs);
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
+}
+
+static void ll_local_dev(struct pt_regs *regs)
+{
+	switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
+	case 0:
+		panic("Unimplemented loc_no_irq handler");
+		break;
+	case 4:
+		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+		break;
+	case 8:
+		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+		break;
+	case 12:
+		panic("Unimplemented loc_sound handler");
+		break;
+	case 16:
+		panic("Unimplemented loc_video handler");
+		break;
+	case 20:
+		loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+		break;
+	case 24:
+		loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+		break;
+	case 28:
+		loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+		break;
+	case 32:
+		loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+		break;
+	case 36:
+		loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+		break;
+	case 40:
+		loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+		break;
+	}
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & IE_IRQ5)
+		write_c0_compare(0);
+	else if (pending & IE_IRQ4) {
+		r4030_read_reg32(JAZZ_TIMER_REGISTER);
+		do_IRQ(JAZZ_TIMER_IRQ, regs);
+	} else if (pending & IE_IRQ3)
+		panic("Unimplemented ISA NMI handler");
+	else if (pending & IE_IRQ2)
+		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+	else if (pending & IE_IRQ1) {
+		ll_local_dev(regs);
+	} else if (unlikely(pending & IE_IRQ0))
+		panic("Unimplemented local_dma handler");
+	else if (pending & IE_SW1) {
+		clear_c0_cause(IE_SW1);
+		panic("Unimplemented sw1 handler");
+	} else if (pending & IE_SW0) {
+		clear_c0_cause(IE_SW0);
+		panic("Unimplemented sw0 handler");
+	}
+}
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index a6bd3f4..e656134 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -60,15 +60,15 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&rtc_lock, flags);
-	CMOS_WRITE(RTC_READ, RTC_CONTROL);
-	second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-	minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
-	hour = BCD2BIN(CMOS_READ(RTC_HOURS));
-	day = BCD2BIN(CMOS_READ(RTC_DATE));
-	month = BCD2BIN(CMOS_READ(RTC_MONTH));
-	year = BCD2BIN(CMOS_READ(RTC_YEAR));
-	century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
-	CMOS_WRITE(0, RTC_CONTROL);
+	rtc_write(RTC_READ, RTC_CONTROL);
+	second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+	minute = BCD2BIN(rtc_read(RTC_MINUTES));
+	hour = BCD2BIN(rtc_read(RTC_HOURS));
+	day = BCD2BIN(rtc_read(RTC_DATE));
+	month = BCD2BIN(rtc_read(RTC_MONTH));
+	year = BCD2BIN(rtc_read(RTC_YEAR));
+	century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
+	rtc_write(0, RTC_CONTROL);
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	year += century * 100;
@@ -87,16 +87,16 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&rtc_lock, flags);
-	CMOS_WRITE(RTC_READ, RTC_CONTROL);
-	cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-	cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
-	cmos_hour = (u8)CMOS_READ(RTC_HOURS);
-	cmos_day = (u8)CMOS_READ(RTC_DATE);
-	cmos_month = (u8)CMOS_READ(RTC_MONTH);
-	cmos_year = (u8)CMOS_READ(RTC_YEAR);
-	cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK;
+	rtc_write(RTC_READ, RTC_CONTROL);
+	cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+	cmos_minute = (u8)rtc_read(RTC_MINUTES);
+	cmos_hour = (u8)rtc_read(RTC_HOURS);
+	cmos_day = (u8)rtc_read(RTC_DATE);
+	cmos_month = (u8)rtc_read(RTC_MONTH);
+	cmos_year = (u8)rtc_read(RTC_YEAR);
+	cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
 
-	CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+	rtc_write(RTC_WRITE, RTC_CONTROL);
 
 	/* convert */
 	to_tm(t, &tm);
@@ -104,18 +104,18 @@
 	/* check each field one by one */
 	year = BIN2BCD(tm.tm_year - EPOCH);
 	if (year != cmos_year) {
-		CMOS_WRITE(year,RTC_YEAR);
+		rtc_write(year,RTC_YEAR);
 	}
 
 	month = BIN2BCD(tm.tm_mon);
 	if (month != (cmos_month & 0x1f)) {
-		CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
+		rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
 	}
 
 	day = BIN2BCD(tm.tm_mday);
 	if (day != cmos_day) {
 
-		CMOS_WRITE(day, RTC_DATE);
+		rtc_write(day, RTC_DATE);
 	}
 
 	if (cmos_hour & 0x40) {
@@ -130,20 +130,20 @@
 		/* 24 hour format */
 		hour = BIN2BCD(tm.tm_hour) & 0x3f;
 	}
-	if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS);
+	if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
 
 	minute = BIN2BCD(tm.tm_min);
 	if (minute !=  cmos_minute) {
-		CMOS_WRITE(minute, RTC_MINUTES);
+		rtc_write(minute, RTC_MINUTES);
 	}
 
 	second = BIN2BCD(tm.tm_sec);
 	if (second !=  cmos_second) {
-		CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS);
+		rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
 	}
 
 	/* RTC_CENTURY and RTC_CONTROL share same address... */
-	CMOS_WRITE(cmos_century, RTC_CONTROL);
+	rtc_write(cmos_century, RTC_CONTROL);
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
@@ -163,9 +163,9 @@
 	rtc_mips_set_time = rtc_ds1742_set_time;
 
 	/* clear oscillator stop bit */
-	CMOS_WRITE(RTC_READ, RTC_CONTROL);
-	cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-	CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
-	CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */
-	CMOS_WRITE(0, RTC_CONTROL);
+	rtc_write(RTC_READ, RTC_CONTROL);
+	cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+	rtc_write(RTC_WRITE, RTC_CONTROL);
+	rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
+	rtc_write(0, RTC_CONTROL);
 }
diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile
index 75bf418..baf5077 100644
--- a/arch/mips/jmr3927/rbhma3100/Makefile
+++ b/arch/mips/jmr3927/rbhma3100/Makefile
@@ -2,7 +2,7 @@
 # Makefile for TOSHIBA JMR-TX3927 board
 #
 
-obj-y	 			+= init.o int-handler.o irq.o setup.o
+obj-y	 			+= init.o irq.o setup.o
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
 
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
deleted file mode 100644
index f85bbf4..0000000
--- a/arch/mips/jmr3927/rbhma3100/int-handler.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * Based on arch/mips/tsdb/kernel/int-handler.S
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/jmr3927/jmr3927.h>
-
-	/* A lot of complication here is taken away because:
-	 *
-	 * 1) We handle one interrupt and return, sitting in a loop
-	 *    and moving across all the pending IRQ bits in the cause
-	 *    register is _NOT_ the answer, the common case is one
-	 *    pending IRQ so optimize in that direction.
-	 *
-	 * 2) We need not check against bits in the status register
-	 *    IRQ mask, that would make this routine slow as hell.
-	 *
-	 * 3) Linux only thinks in terms of all IRQs on or all IRQs
-	 *    off, nothing in between like BSD spl() brain-damage.
-	 *
-	 */
-
-/* Flush write buffer (needed?)
- * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
- * register of LBU to flush immediately.
- */
-#define FLUSH_WB(tmp)	\
-	la	tmp, JMR3927_IOC_REV_ADDR; \
-	lbu	tmp, (tmp); \
-	move	tmp, zero;
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(jmr3927_IRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	jal	jmr3927_irc_irqdispatch
-	 move	a0, sp
-	FLUSH_WB(t0)
-	j	ret_from_irq
-	 nop
-	END(jmr3927_IRQ)
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
index 2810727..11304d1 100644
--- a/arch/mips/jmr3927/rbhma3100/irq.c
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -77,8 +77,6 @@
 }
 #endif
 
-extern asmlinkage void jmr3927_IRQ(void);
-
 #define irc_dlevel	0
 #define irc_elevel	1
 
@@ -262,7 +260,7 @@
 	       regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
 }
 
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	int irq;
 
@@ -398,8 +396,6 @@
 
 	jmr3927_irq_init(NR_ISA_IRQS);
 
-	set_except_vector(0, jmr3927_IRQ);
-
 	/* setup irq space */
 	add_tb_irq_space(&jmr3927_isac_irqspace);
 	add_tb_irq_space(&jmr3927_ioc_irqspace);
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 309d54c..34e8a25 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -34,8 +34,11 @@
 
 obj-$(CONFIG_SMP)		+= smp.o
 
-obj-$(CONFIG_MIPS_MT_SMP)	+= smp_mt.o
+obj-$(CONFIG_MIPS_MT)		+= mips-mt.o
+obj-$(CONFIG_MIPS_MT_SMTC)	+= smtc.o smtc-asm.o smtc-proc.o
+obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 
+obj-$(CONFIG_MIPS_APSP_KSPD)	+= kspd.o
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
 obj-$(CONFIG_MIPS_VPE_APSP_API)	+= rtlx.o
 
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ca6b03c..92b28b6 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -69,6 +69,9 @@
 	offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
 	offset("#define PT_STATUS ", struct pt_regs, cp0_status);
 	offset("#define PT_CAUSE  ", struct pt_regs, cp0_cause);
+#ifdef CONFIG_MIPS_MT_SMTC
+	offset("#define PT_TCSTATUS  ", struct pt_regs, cp0_tcstatus);
+#endif /* CONFIG_MIPS_MT_SMTC */
 	size("#define PT_SIZE   ", struct pt_regs);
 	linefeed;
 }
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 374de83..b6232d9 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -184,7 +184,7 @@
 		bit = (insn.i_format.rt >> 2);
 		bit += (bit != 0);
 		bit += 23;
-		switch (insn.i_format.rt) {
+		switch (insn.i_format.rt & 3) {
 		case 0:	/* bc1f */
 		case 2:	/* bc1fl */
 			if (~fcr31 & (1 << bit))
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 83c87fe..d101d2f 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -17,6 +17,9 @@
 #include <asm/isadep.h>
 #include <asm/thread_info.h>
 #include <asm/war.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
 
 #ifdef CONFIG_PREEMPT
 	.macro	preempt_stop
@@ -75,6 +78,37 @@
 	bnez	t0, syscall_exit_work
 
 FEXPORT(restore_all)			# restore full frame
+#ifdef CONFIG_MIPS_MT_SMTC
+/* Detect and execute deferred IPI "interrupts" */
+	move	a0,sp
+	jal	deferred_smtc_ipi
+/* Re-arm any temporarily masked interrupts not explicitly "acked" */
+	mfc0	v0, CP0_TCSTATUS
+	ori	v1, v0, TCSTATUS_IXMT
+	mtc0	v1, CP0_TCSTATUS
+	andi	v0, TCSTATUS_IXMT
+	ehb
+	mfc0	t0, CP0_TCCONTEXT
+	DMT	9				# dmt t1
+	jal	mips_ihb
+	mfc0	t2, CP0_STATUS
+	andi	t3, t0, 0xff00
+	or	t2, t2, t3
+	mtc0	t2, CP0_STATUS
+	ehb
+	andi	t1, t1, VPECONTROL_TE
+	beqz	t1, 1f
+	EMT
+1:
+	mfc0	v1, CP0_TCSTATUS
+	/* We set IXMT above, XOR should cler it here */
+	xori	v1, v1, TCSTATUS_IXMT
+	or	v1, v0, v1
+	mtc0	v1, CP0_TCSTATUS
+	ehb
+	xor	t0, t0, t3
+	mtc0	t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC */
 	.set	noat
 	RESTORE_TEMP
 	RESTORE_AT
@@ -120,28 +154,17 @@
 	jal	do_syscall_trace
 	b	resume_userspace
 
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+
 /*
- * Common spurious interrupt handler.
+ * MIPS32R2 Instruction Hazard Barrier - must be called
+ *
+ * For C code use the inline version named instruction_hazard().
  */
-LEAF(spurious_interrupt)
-	/*
-	 * Someone tried to fool us by sending an interrupt but we
-	 * couldn't find a cause for it.
-	 */
-	PTR_LA	t1, irq_err_count
-#ifdef CONFIG_SMP
-1:	ll      t0, (t1)
-	addiu   t0, 1
-	sc      t0, (t1)
-#if R10000_LLSC_WAR
-	beqzl	t0, 1b
-#else
-	beqz	t0, 1b
-#endif
-#else
-	lw      t0, (t1)
-	addiu   t0, 1
-	sw      t0, (t1)
-#endif
-	j	ret_from_irq
-	END(spurious_interrupt)
+LEAF(mips_ihb)
+	.set	mips32r2
+	jr.hb	ra
+	nop
+	END(mips_ihb)
+
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 235ad9f..10f28fb 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -283,11 +283,33 @@
  */
 
 3:
+#ifdef CONFIG_MIPS_MT_SMTC
+		/* Read-modify write of Status must be atomic */
+		mfc0	t2, CP0_TCSTATUS
+		ori	t1, t2, TCSTATUS_IXMT
+		mtc0	t1, CP0_TCSTATUS
+		andi	t2, t2, TCSTATUS_IXMT
+		ehb
+		DMT	9				# dmt	t1
+		jal	mips_ihb
+		nop
+#endif /* CONFIG_MIPS_MT_SMTC */
 		mfc0	t0, CP0_STATUS
 		ori	t0, 0x1f
 		xori	t0, 0x1f
 		mtc0	t0, CP0_STATUS
-
+#ifdef CONFIG_MIPS_MT_SMTC
+        	andi    t1, t1, VPECONTROL_TE
+        	beqz    t1, 9f
+		nop
+        	EMT					# emt
+9:
+		mfc0	t1, CP0_TCSTATUS
+		xori	t1, t1, TCSTATUS_IXMT
+		or	t1, t1, t2
+		mtc0	t1, CP0_TCSTATUS
+		ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
 		LONG_L	v0, GDB_FR_STATUS(sp)
 		LONG_L	v1, GDB_FR_EPC(sp)
 		mtc0	v0, CP0_STATUS
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index d4f88e0..6ecbdc1 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -140,6 +140,7 @@
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/inst.h>
+#include <asm/smp.h>
 
 /*
  * external low-level support routines
@@ -669,6 +670,64 @@
 	local_irq_restore(flags);
 }
 
+/*
+ * GDB stub needs to call kgdb_wait on all processor with interrupts
+ * disabled, so it uses it's own special variant.
+ */
+static int kgdb_smp_call_kgdb_wait(void)
+{
+#ifdef CONFIG_SMP
+	struct call_data_struct data;
+	int i, cpus = num_online_cpus() - 1;
+	int cpu = smp_processor_id();
+
+	/*
+	 * Can die spectacularly if this CPU isn't yet marked online
+	 */
+	BUG_ON(!cpu_online(cpu));
+
+	if (!cpus)
+		return 0;
+
+	if (spin_is_locked(&smp_call_lock)) {
+		/*
+		 * Some other processor is trying to make us do something
+		 * but we're not going to respond... give up
+		 */
+		return -1;
+		}
+
+	/*
+	 * We will continue here, accepting the fact that
+	 * the kernel may deadlock if another CPU attempts
+	 * to call smp_call_function now...
+	 */
+
+	data.func = kgdb_wait;
+	data.info = NULL;
+	atomic_set(&data.started, 0);
+	data.wait = 0;
+
+	spin_lock(&smp_call_lock);
+	call_data = &data;
+	mb();
+
+	/* Send a message to all other CPUs and wait for them to respond */
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_online(i) && i != cpu)
+			core_send_ipi(i, SMP_CALL_FUNCTION);
+
+	/* Wait for response */
+	/* FIXME: lock-up detection, backtrace on lock-up */
+	while (atomic_read(&data.started) != cpus)
+		barrier();
+
+	call_data = NULL;
+	spin_unlock(&smp_call_lock);
+#endif
+
+	return 0;
+}
 
 /*
  * This function does all command processing for interfacing to gdb.  It
@@ -718,7 +777,7 @@
 	/*
 	 * force other cpus to enter kgdb
 	 */
-	smp_call_function(kgdb_wait, NULL, 0, 0);
+	kgdb_smp_call_kgdb_wait();
 
 	/*
 	 * If we're in breakpoint() increment the PC
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 13f22d1..ff7af36 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/cacheops.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
@@ -122,6 +123,20 @@
 	.set	pop
 	END(except_vec3_r4000)
 
+	__FINIT
+
+	.align  5
+NESTED(handle_int, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+
+	PTR_LA	ra, ret_from_irq
+	move	a0, sp
+	j	plat_irq_dispatch
+	END(handle_int)
+
+	__INIT
+
 /*
  * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
  * This is a dedicated interrupt exception vector which reduces the
@@ -157,6 +172,15 @@
 	SAVE_AT
 	.set	push
 	.set	noreorder
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * To keep from blindly blocking *all* interrupts
+	 * during service by SMTC kernel, we also want to
+	 * pass the IM value to be cleared.
+	 */
+EXPORT(except_vec_vi_mori)
+	ori	a0, $0, 0
+#endif /* CONFIG_MIPS_MT_SMTC */
 EXPORT(except_vec_vi_lui)
 	lui	v0, 0		/* Patched */
 	j	except_vec_vi_handler
@@ -173,6 +197,25 @@
 NESTED(except_vec_vi_handler, 0, sp)
 	SAVE_TEMP
 	SAVE_STATIC
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC has an interesting problem that interrupts are level-triggered,
+	 * and the CLI macro will clear EXL, potentially causing a duplicate
+	 * interrupt service invocation. So we need to clear the associated
+	 * IM bit of Status prior to doing CLI, and restore it after the
+	 * service routine has been invoked - we must assume that the
+	 * service routine will have cleared the state, and any active
+	 * level represents a new or otherwised unserviced event...
+	 */
+	mfc0	t1, CP0_STATUS
+	and	t0, a0, t1
+	mfc0	t2, CP0_TCCONTEXT
+	or	t0, t0, t2
+	mtc0	t0, CP0_TCCONTEXT
+	xor	t1, t1, t0
+	mtc0	t1, CP0_STATUS
+	ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
 	CLI
 	move	a0, sp
 	jalr	v0
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 2e9122a..bdf6f6e 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -18,6 +18,7 @@
 #include <linux/threads.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
 #include <asm/mipsregs.h>
@@ -82,12 +83,33 @@
 	 */
 	.macro	setup_c0_status set clr
 	.set	push
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * For SMTC, we need to set privilege and disable interrupts only for
+	 * the current TC, using the TCStatus register.
+	 */
+	mfc0	t0, CP0_TCSTATUS
+	/* Fortunately CU 0 is in the same place in both registers */
+	/* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+	li	t1, ST0_CU0 | 0x08001c00
+	or	t0, t1
+	/* Clear TKSU, leave IXMT */
+	xori	t0, 0x00001800
+	mtc0	t0, CP0_TCSTATUS
+	ehb
+	/* We need to leave the global IE bit set, but clear EXL...*/
+	mfc0	t0, CP0_STATUS
+	or	t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
+	xor	t0, ST0_EXL | ST0_ERL | \clr
+	mtc0	t0, CP0_STATUS
+#else
 	mfc0	t0, CP0_STATUS
 	or	t0, ST0_CU0|\set|0x1f|\clr
 	xor	t0, 0x1f|\clr
 	mtc0	t0, CP0_STATUS
 	.set	noreorder
 	sll	zero,3				# ehb
+#endif
 	.set	pop
 	.endm
 
@@ -134,6 +156,24 @@
 
 	ARC64_TWIDDLE_PC
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * In SMTC kernel, "CLI" is thread-specific, in TCStatus.
+	 * We still need to enable interrupts globally in Status,
+	 * and clear EXL/ERL.
+	 *
+	 * TCContext is used to track interrupt levels under
+	 * service in SMTC kernel. Clear for boot TC before
+	 * allowing any interrupts.
+	 */
+	mtc0	zero, CP0_TCCONTEXT
+
+	mfc0	t0, CP0_STATUS
+	ori	t0, t0, 0xff1f
+	xori	t0, t0, 0x001e
+	mtc0	t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 	PTR_LA		t0, __bss_start		# clear .bss
 	LONG_S		zero, (t0)
 	PTR_LA		t1, __bss_stop - LONGSIZE
@@ -166,8 +206,25 @@
  * function after setting up the stack and gp registers.
  */
 NESTED(smp_bootstrap, 16, sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * Read-modify-writes of Status must be atomic, and this
+	 * is one case where CLI is invoked without EXL being
+	 * necessarily set. The CLI and setup_c0_status will
+	 * in fact be redundant for all but the first TC of
+	 * each VPE being booted.
+	 */
+	DMT	10	# dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
+	jal	mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
 	setup_c0_status_sec
 	smp_slave_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+	andi	t2, t2, VPECONTROL_TE
+	beqz	t2, 2f
+	EMT		# emt
+2:
+#endif /* CONFIG_MIPS_MT_SMTC */
 	j	start_secondary
 	END(smp_bootstrap)
 #endif /* CONFIG_SMP */
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index b974ac9..2125ba5 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -187,6 +187,10 @@
 		outb(cached_21,0x21);
 		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
 	}
+#ifdef CONFIG_MIPS_MT_SMTC
+        if (irq_hwmask[irq] & ST0_IM)
+        	set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 	return;
 
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 3f653c7..97ebdc7 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -76,6 +76,11 @@
 	mask_msc_irq(irq);
 	if (!cpu_has_veic)
 		MSCIC_WRITE(MSC01_IC_EOI, 0);
+#ifdef CONFIG_MIPS_MT_SMTC
+	/* This actually needs to be a call into platform code */
+	if (irq_hwmask[irq] & ST0_IM)
+		set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -92,6 +97,10 @@
 		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
 		MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
 	}
+#ifdef CONFIG_MIPS_MT_SMTC
+	if (irq_hwmask[irq] & ST0_IM)
+		set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 3dd76b3..3dce742 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -38,6 +38,15 @@
 
 atomic_t irq_err_count;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+unsigned long irq_hwmask[NR_IRQS];
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 #undef do_IRQ
 
 /*
@@ -49,6 +58,7 @@
 {
 	irq_enter();
 
+	__DO_IRQ_SMTC_HOOK();
 	__do_IRQ(irq, regs);
 
 	irq_exit();
@@ -101,6 +111,11 @@
 	return 0;
 }
 
+asmlinkage void spurious_interrupt(struct pt_regs *regs)
+{
+	atomic_inc(&irq_err_count);
+}
+
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
 extern void set_debug_traps(void);
@@ -124,6 +139,9 @@
 		irq_desc[i].depth   = 1;
 		irq_desc[i].handler = &no_irq_type;
 		spin_lock_init(&irq_desc[i].lock);
+#ifdef CONFIG_MIPS_MT_SMTC
+		irq_hwmask[i] = 0;
+#endif /* CONFIG_MIPS_MT_SMTC */
 	}
 
 	arch_init_irq();
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
new file mode 100644
index 0000000..f06a144
--- /dev/null
+++ b/arch/mips/kernel/kspd.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+#include <asm/kspd.h>
+
+static struct workqueue_struct *workqueue = NULL;
+static struct work_struct work;
+
+extern unsigned long cpu_khz;
+
+struct mtsp_syscall {
+	int cmd;
+	unsigned char abi;
+	unsigned char size;
+};
+
+struct mtsp_syscall_ret {
+	int retval;
+	int errno;
+};
+
+struct mtsp_syscall_generic {
+	int arg0;
+	int arg1;
+	int arg2;
+	int arg3;
+	int arg4;
+	int arg5;
+	int arg6;
+};
+
+static struct list_head kspd_notifylist;
+static int sp_stopping = 0;
+
+/* these should match with those in the SDE kit */
+#define MTSP_SYSCALL_BASE	0
+#define MTSP_SYSCALL_EXIT	(MTSP_SYSCALL_BASE + 0)
+#define MTSP_SYSCALL_OPEN	(MTSP_SYSCALL_BASE + 1)
+#define MTSP_SYSCALL_READ	(MTSP_SYSCALL_BASE + 2)
+#define MTSP_SYSCALL_WRITE	(MTSP_SYSCALL_BASE + 3)
+#define MTSP_SYSCALL_CLOSE	(MTSP_SYSCALL_BASE + 4)
+#define MTSP_SYSCALL_LSEEK32	(MTSP_SYSCALL_BASE + 5)
+#define MTSP_SYSCALL_ISATTY	(MTSP_SYSCALL_BASE + 6)
+#define MTSP_SYSCALL_GETTIME	(MTSP_SYSCALL_BASE + 7)
+#define MTSP_SYSCALL_PIPEFREQ	(MTSP_SYSCALL_BASE + 8)
+#define MTSP_SYSCALL_GETTOD	(MTSP_SYSCALL_BASE + 9)
+
+#define MTSP_O_RDONLY		0x0000
+#define MTSP_O_WRONLY		0x0001
+#define MTSP_O_RDWR		0x0002
+#define MTSP_O_NONBLOCK		0x0004
+#define MTSP_O_APPEND		0x0008
+#define MTSP_O_SHLOCK		0x0010
+#define MTSP_O_EXLOCK		0x0020
+#define MTSP_O_ASYNC		0x0040
+#define MTSP_O_FSYNC		O_SYNC
+#define MTSP_O_NOFOLLOW		0x0100
+#define MTSP_O_SYNC		0x0080
+#define MTSP_O_CREAT		0x0200
+#define MTSP_O_TRUNC		0x0400
+#define MTSP_O_EXCL		0x0800
+#define MTSP_O_BINARY		0x8000
+
+#define SP_VPE 1
+
+struct apsp_table  {
+	int sp;
+	int ap;
+};
+
+/* we might want to do the mode flags too */
+struct apsp_table open_flags_table[] = {
+	{ MTSP_O_RDWR, O_RDWR },
+	{ MTSP_O_WRONLY, O_WRONLY },
+	{ MTSP_O_CREAT, O_CREAT },
+	{ MTSP_O_TRUNC, O_TRUNC },
+	{ MTSP_O_NONBLOCK, O_NONBLOCK },
+	{ MTSP_O_APPEND, O_APPEND },
+	{ MTSP_O_NOFOLLOW, O_NOFOLLOW }
+};
+
+struct apsp_table syscall_command_table[] = {
+	{ MTSP_SYSCALL_OPEN, __NR_open },
+	{ MTSP_SYSCALL_CLOSE, __NR_close },
+	{ MTSP_SYSCALL_READ, __NR_read },
+	{ MTSP_SYSCALL_WRITE, __NR_write },
+	{ MTSP_SYSCALL_LSEEK32, __NR_lseek }
+};
+
+static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3)
+{
+	register long int _num  __asm__ ("$2") = num;
+	register long int _arg0  __asm__ ("$4") = arg0;
+	register long int _arg1  __asm__ ("$5") = arg1;
+	register long int _arg2  __asm__ ("$6") = arg2;
+	register long int _arg3  __asm__ ("$7") = arg3;
+
+	mm_segment_t old_fs;
+
+	old_fs = get_fs();
+ 	set_fs(KERNEL_DS);
+
+  	__asm__ __volatile__ (
+ 	"	syscall					\n"
+ 	: "=r" (_num), "=r" (_arg3)
+ 	: "r" (_num), "r" (_arg0), "r" (_arg1), "r" (_arg2), "r" (_arg3));
+
+	set_fs(old_fs);
+
+	/* $a3 is error flag */
+	if (_arg3)
+		return -_num;
+
+	return _num;
+}
+
+static int translate_syscall_command(int cmd)
+{
+	int i;
+	int ret = -1;
+
+	for (i = 0; i < ARRAY_SIZE(syscall_command_table); i++) {
+		if ((cmd == syscall_command_table[i].sp))
+			return syscall_command_table[i].ap;
+	}
+
+	return ret;
+}
+
+static unsigned int translate_open_flags(int flags)
+{
+	int i;
+	unsigned int ret = 0;
+
+	for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table));
+	     i++) {
+		if( (flags & open_flags_table[i].sp) ) {
+			ret |= open_flags_table[i].ap;
+		}
+	}
+
+	return ret;
+}
+
+
+static void sp_setfsuidgid( uid_t uid, gid_t gid)
+{
+	current->fsuid = uid;
+	current->fsgid = gid;
+
+	key_fsuid_changed(current);
+	key_fsgid_changed(current);
+}
+
+/*
+ * Expects a request to be on the sysio channel. Reads it.  Decides whether
+ * its a linux syscall and runs it, or whatever.  Puts the return code back
+ * into the request and sends the whole thing back.
+ */
+void sp_work_handle_request(void)
+{
+	struct mtsp_syscall sc;
+	struct mtsp_syscall_generic generic;
+	struct mtsp_syscall_ret ret;
+	struct kspd_notifications *n;
+	struct timeval tv;
+	struct timezone tz;
+	int cmd;
+
+	char *vcwd;
+	mm_segment_t old_fs;
+	int size;
+
+	ret.retval = -1;
+
+	if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
+		printk(KERN_ERR "Expected request but nothing to read\n");
+		return;
+	}
+
+	size = sc.size;
+
+	if (size) {
+		if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
+			printk(KERN_ERR "Expected request but nothing to read\n");
+			return;
+		}
+	}
+
+	/* Run the syscall at the priviledge of the user who loaded the
+	   SP program */
+
+	if (vpe_getuid(SP_VPE))
+		sp_setfsuidgid( vpe_getuid(SP_VPE), vpe_getgid(SP_VPE));
+
+	switch (sc.cmd) {
+	/* needs the flags argument translating from SDE kit to
+	   linux */
+ 	case MTSP_SYSCALL_PIPEFREQ:
+ 		ret.retval = cpu_khz * 1000;
+ 		ret.errno = 0;
+ 		break;
+
+ 	case MTSP_SYSCALL_GETTOD:
+ 		memset(&tz, 0, sizeof(tz));
+ 		if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
+ 		                             (int)&tz, 0,0)) == 0)
+		ret.retval = tv.tv_sec;
+
+		ret.errno = errno;
+		break;
+
+ 	case MTSP_SYSCALL_EXIT:
+		list_for_each_entry(n, &kspd_notifylist, list)
+ 			n->kspd_sp_exit(SP_VPE);
+		sp_stopping = 1;
+
+		printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
+		       generic.arg0);
+ 		break;
+
+ 	case MTSP_SYSCALL_OPEN:
+ 		generic.arg1 = translate_open_flags(generic.arg1);
+
+ 		vcwd = vpe_getcwd(SP_VPE);
+
+ 		/* change to the cwd of the process that loaded the SP program */
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		sys_chdir(vcwd);
+		set_fs(old_fs);
+
+ 		sc.cmd = __NR_open;
+
+		/* fall through */
+
+  	default:
+ 		if ((sc.cmd >= __NR_Linux) &&
+		    (sc.cmd <= (__NR_Linux +  __NR_Linux_syscalls)) )
+			cmd = sc.cmd;
+		else
+			cmd = translate_syscall_command(sc.cmd);
+
+		if (cmd >= 0) {
+			ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1,
+			                        generic.arg2, generic.arg3);
+			ret.errno = errno;
+		} else
+ 			printk(KERN_WARNING
+			       "KSPD: Unknown SP syscall number %d\n", sc.cmd);
+		break;
+ 	} /* switch */
+
+	if (vpe_getuid(SP_VPE))
+		sp_setfsuidgid( 0, 0);
+
+	if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
+	    < sizeof(struct mtsp_syscall_ret))
+		printk("KSPD: sp_work_handle_request failed to send to SP\n");
+}
+
+static void sp_cleanup(void)
+{
+	struct files_struct *files = current->files;
+	int i, j;
+	struct fdtable *fdt;
+
+	j = 0;
+
+	/*
+	 * It is safe to dereference the fd table without RCU or
+	 * ->file_lock
+	 */
+	fdt = files_fdtable(files);
+	for (;;) {
+		unsigned long set;
+		i = j * __NFDBITS;
+		if (i >= fdt->max_fdset || i >= fdt->max_fds)
+			break;
+		set = fdt->open_fds->fds_bits[j++];
+		while (set) {
+			if (set & 1) {
+				struct file * file = xchg(&fdt->fd[i], NULL);
+				if (file)
+					filp_close(file, files);
+			}
+			i++;
+			set >>= 1;
+		}
+	}
+}
+
+static int channel_open = 0;
+
+/* the work handler */
+static void sp_work(void *data)
+{
+	if (!channel_open) {
+		if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
+			printk("KSPD: unable to open sp channel\n");
+			sp_stopping = 1;
+		} else {
+			channel_open++;
+			printk(KERN_DEBUG "KSPD: SP channel opened\n");
+		}
+	} else {
+		/* wait for some data, allow it to sleep */
+		rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
+
+		/* Check we haven't been woken because we are stopping */
+		if (!sp_stopping)
+			sp_work_handle_request();
+	}
+
+	if (!sp_stopping)
+		queue_work(workqueue, &work);
+	else
+		sp_cleanup();
+}
+
+static void startwork(int vpe)
+{
+	sp_stopping = channel_open = 0;
+
+	if (workqueue == NULL) {
+		if ((workqueue = create_singlethread_workqueue("kspd")) == NULL) {
+			printk(KERN_ERR "unable to start kspd\n");
+			return;
+		}
+
+		INIT_WORK(&work, sp_work, NULL);
+		queue_work(workqueue, &work);
+	} else
+		queue_work(workqueue, &work);
+
+}
+
+static void stopwork(int vpe)
+{
+	sp_stopping = 1;
+
+	printk(KERN_DEBUG "KSPD: SP stopping\n");
+}
+
+void kspd_notify(struct kspd_notifications *notify)
+{
+	list_add(&notify->list, &kspd_notifylist);
+}
+
+static struct vpe_notifications notify;
+static int kspd_module_init(void)
+{
+	INIT_LIST_HEAD(&kspd_notifylist);
+
+	notify.start = startwork;
+	notify.stop = stopwork;
+	vpe_notify(SP_VPE, &notify);
+
+	return 0;
+}
+
+static void kspd_module_exit(void)
+{
+
+}
+
+module_init(kspd_module_init);
+module_exit(kspd_module_exit);
+
+MODULE_DESCRIPTION("MIPS KSPD");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 3f40c37..a7d2bb3 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -356,73 +356,13 @@
 asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
 			       size_t count, u32 unused, u64 a4, u64 a5)
 {
-	ssize_t ret;
-	struct file * file;
-	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
-	loff_t pos;
-
-	ret = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto bad_file;
-	if (!(file->f_mode & FMODE_READ))
-		goto out;
-	pos = merge_64(a4, a5);
-	ret = rw_verify_area(READ, file, &pos, count);
-	if (ret < 0)
-		goto out;
-	ret = -EINVAL;
-	if (!file->f_op || !(read = file->f_op->read))
-		goto out;
-	if (pos < 0)
-		goto out;
-	ret = -ESPIPE;
-	if (!(file->f_mode & FMODE_PREAD))
-		goto out;
-	ret = read(file, buf, count, &pos);
-	if (ret > 0)
-		dnotify_parent(file->f_dentry, DN_ACCESS);
-out:
-	fput(file);
-bad_file:
-	return ret;
+	return sys_pread64(fd, buf, count, merge_64(a4, a5));
 }
 
 asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
 			        size_t count, u32 unused, u64 a4, u64 a5)
 {
-	ssize_t ret;
-	struct file * file;
-	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
-	loff_t pos;
-
-	ret = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto bad_file;
-	if (!(file->f_mode & FMODE_WRITE))
-		goto out;
-	pos = merge_64(a4, a5);
-	ret = rw_verify_area(WRITE, file, &pos, count);
-	if (ret < 0)
-		goto out;
-	ret = -EINVAL;
-	if (!file->f_op || !(write = file->f_op->write))
-		goto out;
-	if (pos < 0)
-		goto out;
-
-	ret = -ESPIPE;
-	if (!(file->f_mode & FMODE_PWRITE))
-		goto out;
-
-	ret = write(file, buf, count, &pos);
-	if (ret > 0)
-		dnotify_parent(file->f_dentry, DN_MODIFY);
-out:
-	fput(file);
-bad_file:
-	return ret;
+	return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
 }
 
 asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
@@ -1182,6 +1122,16 @@
 	return sys_readahead(fd, merge_64(a2, a3), count);
 }
 
+asmlinkage long sys32_sync_file_range(int fd, int __pad,
+	unsigned long a2, unsigned long a3,
+	unsigned long a4, unsigned long a5,
+	int flags)
+{
+	return sys_sync_file_range(fd,
+			merge_64(a2, a3), merge_64(a4, a5),
+			flags);
+}
+
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(unsigned int))
 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
new file mode 100644
index 0000000..02237a6
--- /dev/null
+++ b/arch/mips/kernel/mips-mt.c
@@ -0,0 +1,449 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsmtregs.h>
+#include <asm/r4kcache.h>
+#include <asm/cacheflush.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+
+cpumask_t mt_fpu_cpumask;
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline task_t *find_process_by_pid(pid_t pid)
+{
+	return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	cpumask_t new_mask;
+	cpumask_t effective_mask;
+	int retval;
+	task_t *p;
+
+	if (len < sizeof(new_mask))
+		return -EINVAL;
+
+	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+		return -EFAULT;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	p = find_process_by_pid(pid);
+	if (!p) {
+		read_unlock(&tasklist_lock);
+		unlock_cpu_hotplug();
+		return -ESRCH;
+	}
+
+	/*
+	 * It is not safe to call set_cpus_allowed with the
+	 * tasklist_lock held.  We will bump the task_struct's
+	 * usage count and drop tasklist_lock before invoking
+	 * set_cpus_allowed.
+	 */
+	get_task_struct(p);
+
+	retval = -EPERM;
+	if ((current->euid != p->euid) && (current->euid != p->uid) &&
+			!capable(CAP_SYS_NICE)) {
+		read_unlock(&tasklist_lock);
+		goto out_unlock;
+	}
+
+	/* Record new user-specified CPU set for future reference */
+	p->thread.user_cpus_allowed = new_mask;
+
+	/* Unlock the task list */
+	read_unlock(&tasklist_lock);
+
+	/* Compute new global allowed CPU set if necessary */
+	if( (p->thread.mflags & MF_FPUBOUND)
+	&& cpus_intersects(new_mask, mt_fpu_cpumask)) {
+		cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+		retval = set_cpus_allowed(p, effective_mask);
+	} else {
+		p->thread.mflags &= ~MF_FPUBOUND;
+		retval = set_cpus_allowed(p, new_mask);
+	}
+
+
+out_unlock:
+	put_task_struct(p);
+	unlock_cpu_hotplug();
+	return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	unsigned int real_len;
+	cpumask_t mask;
+	int retval;
+	task_t *p;
+
+	real_len = sizeof(mask);
+	if (len < real_len)
+		return -EINVAL;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	retval = -ESRCH;
+	p = find_process_by_pid(pid);
+	if (!p)
+		goto out_unlock;
+
+	retval = 0;
+
+	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+	read_unlock(&tasklist_lock);
+	unlock_cpu_hotplug();
+	if (retval)
+		return retval;
+	if (copy_to_user(user_mask_ptr, &mask, real_len))
+		return -EFAULT;
+	return real_len;
+}
+
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+/*
+ * Dump new MIPS MT state for the core. Does not leave TCs halted.
+ * Takes an argument which taken to be a pre-call MVPControl value.
+ */
+
+void mips_mt_regdump(unsigned long mvpctl)
+{
+	unsigned long flags;
+	unsigned long vpflags;
+	unsigned long mvpconf0;
+	int nvpe;
+	int ntc;
+	int i;
+	int tc;
+	unsigned long haltval;
+	unsigned long tcstatval;
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_soft_dump(void);
+#endif /* CONFIG_MIPT_MT_SMTC */
+
+	local_irq_save(flags);
+	vpflags = dvpe();
+	printk("=== MIPS MT State Dump ===\n");
+	printk("-- Global State --\n");
+	printk("   MVPControl Passed: %08lx\n", mvpctl);
+	printk("   MVPControl Read: %08lx\n", vpflags);
+	printk("   MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0()));
+	nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+	ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+	printk("-- per-VPE State --\n");
+	for(i = 0; i < nvpe; i++) {
+	    for(tc = 0; tc < ntc; tc++) {
+			settc(tc);
+		if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+		    printk("  VPE %d\n", i);
+		    printk("   VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
+		    printk("   VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
+		    printk("   VPE%d.Status : %08lx\n",
+				i, read_vpe_c0_status());
+		    printk("   VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
+		    printk("   VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
+		    printk("   VPE%d.Config7 : %08lx\n",
+				i, read_vpe_c0_config7());
+		    break; /* Next VPE */
+		}
+	    }
+	}
+	printk("-- per-TC State --\n");
+	for(tc = 0; tc < ntc; tc++) {
+		settc(tc);
+		if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+			/* Are we dumping ourself?  */
+			haltval = 0; /* Then we're not halted, and mustn't be */
+			tcstatval = flags; /* And pre-dump TCStatus is flags */
+			printk("  TC %d (current TC with VPE EPC above)\n", tc);
+		} else {
+			haltval = read_tc_c0_tchalt();
+			write_tc_c0_tchalt(1);
+			tcstatval = read_tc_c0_tcstatus();
+			printk("  TC %d\n", tc);
+		}
+		printk("   TCStatus : %08lx\n", tcstatval);
+		printk("   TCBind : %08lx\n", read_tc_c0_tcbind());
+		printk("   TCRestart : %08lx\n", read_tc_c0_tcrestart());
+		printk("   TCHalt : %08lx\n", haltval);
+		printk("   TCContext : %08lx\n", read_tc_c0_tccontext());
+		if (!haltval)
+			write_tc_c0_tchalt(0);
+	}
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_soft_dump();
+#endif /* CONFIG_MIPT_MT_SMTC */
+	printk("===========================\n");
+	evpe(vpflags);
+	local_irq_restore(flags);
+}
+
+static int mt_opt_norps = 0;
+static int mt_opt_rpsctl = -1;
+static int mt_opt_nblsu = -1;
+static int mt_opt_forceconfig7 = 0;
+static int mt_opt_config7 = -1;
+
+static int __init rps_disable(char *s)
+{
+	mt_opt_norps = 1;
+	return 1;
+}
+__setup("norps", rps_disable);
+
+static int __init rpsctl_set(char *str)
+{
+	get_option(&str, &mt_opt_rpsctl);
+	return 1;
+}
+__setup("rpsctl=", rpsctl_set);
+
+static int __init nblsu_set(char *str)
+{
+	get_option(&str, &mt_opt_nblsu);
+	return 1;
+}
+__setup("nblsu=", nblsu_set);
+
+static int __init config7_set(char *str)
+{
+	get_option(&str, &mt_opt_config7);
+	mt_opt_forceconfig7 = 1;
+	return 1;
+}
+__setup("config7=", config7_set);
+
+/* Experimental cache flush control parameters that should go away some day */
+int mt_protiflush = 0;
+int mt_protdflush = 0;
+int mt_n_iflushes = 1;
+int mt_n_dflushes = 1;
+
+static int __init set_protiflush(char *s)
+{
+	mt_protiflush = 1;
+	return 1;
+}
+__setup("protiflush", set_protiflush);
+
+static int __init set_protdflush(char *s)
+{
+	mt_protdflush = 1;
+	return 1;
+}
+__setup("protdflush", set_protdflush);
+
+static int __init niflush(char *s)
+{
+	get_option(&s, &mt_n_iflushes);
+	return 1;
+}
+__setup("niflush=", niflush);
+
+static int __init ndflush(char *s)
+{
+	get_option(&s, &mt_n_dflushes);
+	return 1;
+}
+__setup("ndflush=", ndflush);
+#ifdef CONFIG_MIPS_MT_FPAFF
+static int fpaff_threshold = -1;
+
+static int __init fpaff_thresh(char *str)
+{
+	get_option(&str, &fpaff_threshold);
+	return 1;
+}
+
+__setup("fpaff=", fpaff_thresh);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+static unsigned int itc_base = 0;
+
+static int __init set_itc_base(char *str)
+{
+	get_option(&str, &itc_base);
+	return 1;
+}
+
+__setup("itcbase=", set_itc_base);
+
+void mips_mt_set_cpuoptions(void)
+{
+	unsigned int oconfig7 = read_c0_config7();
+	unsigned int nconfig7 = oconfig7;
+
+	if (mt_opt_norps) {
+		printk("\"norps\" option deprectated: use \"rpsctl=\"\n");
+	}
+	if (mt_opt_rpsctl >= 0) {
+		printk("34K return prediction stack override set to %d.\n",
+			mt_opt_rpsctl);
+		if (mt_opt_rpsctl)
+			nconfig7 |= (1 << 2);
+		else
+			nconfig7 &= ~(1 << 2);
+	}
+	if (mt_opt_nblsu >= 0) {
+		printk("34K ALU/LSU sync override set to %d.\n", mt_opt_nblsu);
+		if (mt_opt_nblsu)
+			nconfig7 |= (1 << 5);
+		else
+			nconfig7 &= ~(1 << 5);
+	}
+	if (mt_opt_forceconfig7) {
+		printk("CP0.Config7 forced to 0x%08x.\n", mt_opt_config7);
+		nconfig7 = mt_opt_config7;
+	}
+	if (oconfig7 != nconfig7) {
+		__asm__ __volatile("sync");
+		write_c0_config7(nconfig7);
+		ehb ();
+		printk("Config7: 0x%08x\n", read_c0_config7());
+	}
+
+	/* Report Cache management debug options */
+	if (mt_protiflush)
+		printk("I-cache flushes single-threaded\n");
+	if (mt_protdflush)
+		printk("D-cache flushes single-threaded\n");
+	if (mt_n_iflushes != 1)
+		printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes);
+	if (mt_n_dflushes != 1)
+		printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/* FPU Use Factor empirically derived from experiments on 34K */
+#define FPUSEFACTOR 333
+
+	if (fpaff_threshold >= 0) {
+		mt_fpemul_threshold = fpaff_threshold;
+	} else {
+		mt_fpemul_threshold =
+			(FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+	}
+	printk("FPU Affinity set after %ld emulations\n",
+			mt_fpemul_threshold);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+	if (itc_base != 0) {
+		/*
+		 * Configure ITC mapping.  This code is very
+		 * specific to the 34K core family, which uses
+		 * a special mode bit ("ITC") in the ErrCtl
+		 * register to enable access to ITC control
+		 * registers via cache "tag" operations.
+		 */
+		unsigned long ectlval;
+		unsigned long itcblkgrn;
+
+		/* ErrCtl register is known as "ecc" to Linux */
+		ectlval = read_c0_ecc();
+		write_c0_ecc(ectlval | (0x1 << 26));
+		ehb();
+#define INDEX_0 (0x80000000)
+#define INDEX_8 (0x80000008)
+		/* Read "cache tag" for Dcache pseudo-index 8 */
+		cache_op(Index_Load_Tag_D, INDEX_8);
+		ehb();
+		itcblkgrn = read_c0_dtaglo();
+		itcblkgrn &= 0xfffe0000;
+		/* Set for 128 byte pitch of ITC cells */
+		itcblkgrn |= 0x00000c00;
+		/* Stage in Tag register */
+		write_c0_dtaglo(itcblkgrn);
+		ehb();
+		/* Write out to ITU with CACHE op */
+		cache_op(Index_Store_Tag_D, INDEX_8);
+		/* Now set base address, and turn ITC on with 0x1 bit */
+		write_c0_dtaglo((itc_base & 0xfffffc00) | 0x1 );
+		ehb();
+		/* Write out to ITU with CACHE op */
+		cache_op(Index_Store_Tag_D, INDEX_0);
+		write_c0_ecc(ectlval);
+		ehb();
+		printk("Mapped %ld ITC cells starting at 0x%08x\n",
+			((itcblkgrn & 0x7fe00000) >> 20), itc_base);
+	}
+}
+
+/*
+ * Function to protect cache flushes from concurrent execution
+ * depends on MP software model chosen.
+ */
+
+void mt_cflush_lockdown(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_cflush_lockdown(void);
+
+	smtc_cflush_lockdown();
+#endif /* CONFIG_MIPS_MT_SMTC */
+	/* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
+
+void mt_cflush_release(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	void smtc_cflush_release(void);
+
+	smtc_cflush_release();
+#endif /* CONFIG_MIPS_MT_SMTC */
+	/* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 86e42c6..0a71a4c 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -28,22 +28,9 @@
 /*
  * String functions
  */
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-#ifdef CONFIG_64BIT
-EXPORT_SYMBOL(strncmp);
-#endif
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(kernel_thread);
 
@@ -62,6 +49,3 @@
 EXPORT_SYMBOL(csum_partial);
 
 EXPORT_SYMBOL(invalid_pte_table);
-#ifdef CONFIG_GENERIC_IRQ_PROBE
-EXPORT_SYMBOL(probe_irq_mask);
-#endif
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index c66db5e..199a06e 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -41,6 +41,10 @@
 #include <asm/elf.h>
 #include <asm/isadep.h>
 #include <asm/inst.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+extern void smtc_idle_loop_hook(void);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 /*
  * The idle thread. There's no useful work to be done, so just try to conserve
@@ -51,9 +55,13 @@
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
-		while (!need_resched())
+		while (!need_resched()) {
+#ifdef CONFIG_MIPS_MT_SMTC
+			smtc_idle_loop_hook();
+#endif /* CONFIG_MIPS_MT_SMTC */
 			if (cpu_wait)
 				(*cpu_wait)();
+		}
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();
@@ -177,6 +185,17 @@
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/*
+	 * FPU affinity support is cleaner if we track the
+	 * user-visible CPU affinity from the very beginning.
+	 * The generic cpus_allowed mask will already have
+	 * been copied from the parent before copy_thread
+	 * is invoked.
+	 */
+	p->thread.user_cpus_allowed = p->cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
 	if (clone_flags & CLONE_SETTLS)
 		ti->tp_value = regs->regs[7];
 
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f838b36..f3106d0 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -248,10 +248,20 @@
 			break;
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+			unsigned int irqflags;
+			unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 			if (!cpu_has_fpu)
 				break;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+			/* Read-modify-write of Status must be atomic */
+			local_irq_save(irqflags);
+			mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
@@ -266,6 +276,10 @@
 				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 				write_c0_status(flags);
 			}
+#ifdef CONFIG_MIPS_MT_SMTC
+			emt(mtflags);
+			local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
 			preempt_enable();
 			break;
 		}
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 0d5cf97..8704dc0 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -173,12 +173,22 @@
 			break;
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+			unsigned int irqflags;
+			unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 			if (!cpu_has_fpu) {
 				tmp = 0;
 				break;
 			}
 
+#ifdef CONFIG_MIPS_MT_SMTC
+			/* Read-modify-write of Status must be atomic */
+			local_irq_save(irqflags);
+			mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
@@ -193,6 +203,10 @@
 				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
 				write_c0_status(flags);
 			}
+#ifdef CONFIG_MIPS_MT_SMTC
+			emt(mtflags);
+			local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
 			preempt_enable();
 			break;
 		}
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index d2afbd1..0b1b54a 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -88,7 +88,18 @@
 
 	PTR_ADDIU	t0, $28, _THREAD_SIZE - 32
 	set_saved_sp	t0, t1, t2
-
+#ifdef CONFIG_MIPS_MT_SMTC
+	/* Read-modify-writes of Status must be atomic on a VPE */
+	mfc0	t2, CP0_TCSTATUS
+	ori	t1, t2, TCSTATUS_IXMT
+	mtc0	t1, CP0_TCSTATUS
+	andi	t2, t2, TCSTATUS_IXMT
+	ehb
+	DMT	8				# dmt	t0
+	move	t1,ra
+	jal	mips_ihb
+	move	ra,t1
+#endif /* CONFIG_MIPS_MT_SMTC */
 	mfc0	t1, CP0_STATUS		/* Do we really need this? */
 	li	a3, 0xff01
 	and	t1, a3
@@ -97,6 +108,18 @@
 	and	a2, a3
 	or	a2, t1
 	mtc0	a2, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+	ehb
+	andi	t0, t0, VPECONTROL_TE
+	beqz	t0, 1f
+	emt
+1:
+	mfc0	t1, CP0_TCSTATUS
+	xori	t1, t1, TCSTATUS_IXMT
+	or	t1, t1, t2
+	mtc0	t1, CP0_TCSTATUS
+	ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
 	move	v0, a0
 	jr	ra
 	END(resume)
@@ -131,10 +154,19 @@
 #define FPU_DEFAULT  0x00000000
 
 LEAF(_init_fpu)
+#ifdef CONFIG_MIPS_MT_SMTC
+	/* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
+	mfc0	t0, CP0_TCSTATUS
+	/* Bit position is the same for Status, TCStatus */
+	li	t1, ST0_CU1
+	or	t0, t1
+	mtc0	t0, CP0_TCSTATUS
+#else /* Normal MIPS CU1 enable */
 	mfc0	t0, CP0_STATUS
 	li	t1, ST0_CU1
 	or	t0, t1
 	mtc0	t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
 	fpu_enable_hazard
 
 	li	t1, FPU_DEFAULT
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 986a9cf..caf777f 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -21,45 +21,44 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-
 #include <asm/mipsmtregs.h>
-#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/vpe.h>
 #include <asm/rtlx.h>
-#include <asm/uaccess.h>
 
 #define RTLX_TARG_VPE 1
 
 static struct rtlx_info *rtlx;
 static int major;
 static char module_name[] = "rtlx";
-static struct irqaction irq;
-static int irq_num;
-
-static inline int spacefree(int read, int write, int size)
-{
-	if (read == write) {
-		/*
-		 * never fill the buffer completely, so indexes are always
-		 * equal if empty and only empty, or !equal if data available
-		 */
-		return size - 1;
-	}
-
-	return ((read + size - write) % size) - 1;
-}
 
 static struct chan_waitqueues {
 	wait_queue_head_t rt_queue;
 	wait_queue_head_t lx_queue;
+	int in_open;
 } channel_wqs[RTLX_CHANNELS];
 
+static struct irqaction irq;
+static int irq_num;
+static struct vpe_notifications notify;
+static int sp_stopping = 0;
+
 extern void *vpe_get_shared(int index);
 
 static void rtlx_dispatch(struct pt_regs *regs)
@@ -67,174 +66,298 @@
 	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
 }
 
+
+/* Interrupt handler may be called before rtlx_init has otherwise had
+   a chance to run.
+*/
 static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int i;
 
 	for (i = 0; i < RTLX_CHANNELS; i++) {
-		struct rtlx_channel *chan = &rtlx->channel[i];
-
-		if (chan->lx_read != chan->lx_write)
-			wake_up_interruptible(&channel_wqs[i].lx_queue);
+			wake_up(&channel_wqs[i].lx_queue);
+			wake_up(&channel_wqs[i].rt_queue);
 	}
 
 	return IRQ_HANDLED;
 }
 
-/* call when we have the address of the shared structure from the SP side. */
-static int rtlx_init(struct rtlx_info *rtlxi)
+static __attribute_used__ void dump_rtlx(void)
 {
 	int i;
 
+	printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
+
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		struct rtlx_channel *chan = &rtlx->channel[i];
+
+		printk(" rt_state %d lx_state %d buffer_size %d\n",
+		       chan->rt_state, chan->lx_state, chan->buffer_size);
+
+		printk(" rt_read %d rt_write %d\n",
+		       chan->rt_read, chan->rt_write);
+
+		printk(" lx_read %d lx_write %d\n",
+		       chan->lx_read, chan->lx_write);
+
+		printk(" rt_buffer <%s>\n", chan->rt_buffer);
+		printk(" lx_buffer <%s>\n", chan->lx_buffer);
+	}
+}
+
+/* call when we have the address of the shared structure from the SP side. */
+static int rtlx_init(struct rtlx_info *rtlxi)
+{
 	if (rtlxi->id != RTLX_ID) {
-		printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
+		printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id);
 		return -ENOEXEC;
 	}
 
-	/* initialise the wait queues */
-	for (i = 0; i < RTLX_CHANNELS; i++) {
-		init_waitqueue_head(&channel_wqs[i].rt_queue);
-		init_waitqueue_head(&channel_wqs[i].lx_queue);
-	}
-
-	/* set up for interrupt handling */
-	memset(&irq, 0, sizeof(struct irqaction));
-
-	if (cpu_has_vint)
-		set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
-
-	irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
-	irq.handler = rtlx_interrupt;
-	irq.flags = SA_INTERRUPT;
-	irq.name = "RTLX";
-	irq.dev_id = rtlx;
-	setup_irq(irq_num, &irq);
-
 	rtlx = rtlxi;
 
 	return 0;
 }
 
-/* only allow one open process at a time to open each channel */
-static int rtlx_open(struct inode *inode, struct file *filp)
+/* notifications */
+static void starting(int vpe)
 {
-	int minor, ret;
-	struct rtlx_channel *chan;
+	int i;
+	sp_stopping = 0;
 
-	/* assume only 1 device at the mo. */
-	minor = MINOR(inode->i_rdev);
+	/* force a reload of rtlx */
+	rtlx=NULL;
+
+	/* wake up any sleeping rtlx_open's */
+	for (i = 0; i < RTLX_CHANNELS; i++)
+		wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+static void stopping(int vpe)
+{
+	int i;
+
+	sp_stopping = 1;
+	for (i = 0; i < RTLX_CHANNELS; i++)
+		wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+
+int rtlx_open(int index, int can_sleep)
+{
+	int ret;
+	struct rtlx_channel *chan;
+	volatile struct rtlx_info **p;
+
+	if (index >= RTLX_CHANNELS) {
+		printk(KERN_DEBUG "rtlx_open index out of range\n");
+		return -ENOSYS;
+	}
+
+	if (channel_wqs[index].in_open) {
+		printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+		return -EBUSY;
+	}
+
+	channel_wqs[index].in_open++;
 
 	if (rtlx == NULL) {
-		struct rtlx_info **p;
 		if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
-			printk(KERN_ERR "vpe_get_shared is NULL. "
-			       "Has an SP program been loaded?\n");
-			return -EFAULT;
+			if (can_sleep) {
+				DECLARE_WAITQUEUE(wait, current);
+
+				/* go to sleep */
+				add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+				set_current_state(TASK_INTERRUPTIBLE);
+				while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
+					schedule();
+					set_current_state(TASK_INTERRUPTIBLE);
+				}
+
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+				/* back running */
+			} else {
+				printk( KERN_DEBUG "No SP program loaded, and device "
+					"opened with O_NONBLOCK\n");
+				channel_wqs[index].in_open = 0;
+				return -ENOSYS;
+			}
 		}
 
 		if (*p == NULL) {
-			printk(KERN_ERR "vpe_shared %p %p\n", p, *p);
-			return -EFAULT;
+			if (can_sleep) {
+				DECLARE_WAITQUEUE(wait, current);
+
+				/* go to sleep */
+				add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+				set_current_state(TASK_INTERRUPTIBLE);
+				while (*p == NULL) {
+					schedule();
+
+					/* reset task state to interruptable otherwise
+					   we'll whizz round here like a very fast loopy
+					   thing. schedule() appears to return with state
+					   set to TASK_RUNNING.
+
+					   If the loaded SP program, for whatever reason,
+					   doesn't set up the shared structure *p will never
+					   become true. So whoever connected to either /dev/rt?
+					   or if it was kspd, will then take up rather a lot of
+					   processor cycles.
+					*/
+
+					set_current_state(TASK_INTERRUPTIBLE);
+				}
+
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+				/* back running */
+			}
+			else {
+				printk(" *vpe_get_shared is NULL. "
+				       "Has an SP program been loaded?\n");
+				channel_wqs[index].in_open = 0;
+				return -ENOSYS;
+			}
 		}
 
-		if ((ret = rtlx_init(*p)) < 0)
-			return ret;
+		if ((unsigned int)*p < KSEG0) {
+			printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
+			       "maybe an error code %d\n", (int)*p);
+ 			channel_wqs[index].in_open = 0;
+			return -ENOSYS;
+		}
+
+ 		if ((ret = rtlx_init(*p)) < 0) {
+ 			channel_wqs[index].in_open = 0;
+  			return ret;
+ 		}
 	}
 
-	chan = &rtlx->channel[minor];
+	chan = &rtlx->channel[index];
 
-	if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state))
-		return -EBUSY;
+ 	if (chan->lx_state == RTLX_STATE_OPENED) {
+ 		channel_wqs[index].in_open = 0;
+  		return -EBUSY;
+ 	}
 
+  	chan->lx_state = RTLX_STATE_OPENED;
+ 	channel_wqs[index].in_open = 0;
 	return 0;
 }
 
-static int rtlx_release(struct inode *inode, struct file *filp)
+int rtlx_release(int index)
 {
-	int minor = MINOR(inode->i_rdev);
-
-	clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state);
-	smp_mb__after_clear_bit();
-
+	rtlx->channel[index].lx_state = RTLX_STATE_UNUSED;
 	return 0;
 }
 
-static unsigned int rtlx_poll(struct file *file, poll_table * wait)
+unsigned int rtlx_read_poll(int index, int can_sleep)
 {
-	int minor;
-	unsigned int mask = 0;
-	struct rtlx_channel *chan;
+ 	struct rtlx_channel *chan;
 
-	minor = MINOR(file->f_dentry->d_inode->i_rdev);
-	chan = &rtlx->channel[minor];
+ 	if (rtlx == NULL)
+ 		return 0;
 
-	poll_wait(file, &channel_wqs[minor].rt_queue, wait);
-	poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+ 	chan = &rtlx->channel[index];
 
 	/* data available to read? */
-	if (chan->lx_read != chan->lx_write)
-		mask |= POLLIN | POLLRDNORM;
+	if (chan->lx_read == chan->lx_write) {
+		if (can_sleep) {
+			DECLARE_WAITQUEUE(wait, current);
 
-	/* space to write */
-	if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
-		mask |= POLLOUT | POLLWRNORM;
+			/* go to sleep */
+			add_wait_queue(&channel_wqs[index].lx_queue, &wait);
 
-	return mask;
+			set_current_state(TASK_INTERRUPTIBLE);
+			while (chan->lx_read == chan->lx_write) {
+				schedule();
+
+				set_current_state(TASK_INTERRUPTIBLE);
+
+				if (sp_stopping) {
+					set_current_state(TASK_RUNNING);
+					remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+					return 0;
+				}
+			}
+
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+			/* back running */
+		}
+		else
+			return 0;
+	}
+
+	return (chan->lx_write + chan->buffer_size - chan->lx_read)
+	       % chan->buffer_size;
 }
 
-static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
-			 loff_t * ppos)
+static inline int write_spacefree(int read, int write, int size)
 {
-	unsigned long failed;
-	size_t fl = 0L;
-	int minor;
-	struct rtlx_channel *lx;
-	DECLARE_WAITQUEUE(wait, current);
-
-	minor = MINOR(file->f_dentry->d_inode->i_rdev);
-	lx = &rtlx->channel[minor];
-
-	/* data available? */
-	if (lx->lx_write == lx->lx_read) {
-		if (file->f_flags & O_NONBLOCK)
-			return 0;	/* -EAGAIN makes cat whinge */
-
-		/* go to sleep */
-		add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		while (lx->lx_write == lx->lx_read)
-			schedule();
-
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&channel_wqs[minor].lx_queue, &wait);
-
-		/* back running */
+	if (read == write) {
+		/*
+		 * Never fill the buffer completely, so indexes are always
+		 * equal if empty and only empty, or !equal if data available
+		 */
+		return size - 1;
 	}
 
+	return ((read + size - write) % size) - 1;
+}
+
+unsigned int rtlx_write_poll(int index)
+{
+	struct rtlx_channel *chan = &rtlx->channel[index];
+	return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
+}
+
+static inline void copy_to(void *dst, void *src, size_t count, int user)
+{
+	if (user)
+		copy_to_user(dst, src, count);
+	else
+		memcpy(dst, src, count);
+}
+
+static inline void copy_from(void *dst, void *src, size_t count, int user)
+{
+	if (user)
+		copy_from_user(dst, src, count);
+	else
+		memcpy(dst, src, count);
+}
+
+ssize_t rtlx_read(int index, void *buff, size_t count, int user)
+{
+	size_t fl = 0L;
+	struct rtlx_channel *lx;
+
+	if (rtlx == NULL)
+		return -ENOSYS;
+
+	lx = &rtlx->channel[index];
+
 	/* find out how much in total */
 	count = min(count,
-		    (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+		     (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read)
+		     % lx->buffer_size);
 
 	/* then how much from the read pointer onwards */
-	fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
+	fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
 
-	failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
-	if (failed) {
-		count = fl - failed;
-		goto out;
-	}
+	copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user);
 
 	/* and if there is anything left at the beginning of the buffer */
-	if (count - fl) {
-		failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
-		if (failed) {
-			count -= failed;
-			goto out;
-		}
-	}
+	if ( count - fl )
+		copy_to (buff + fl, lx->lx_buffer, count - fl, user);
 
-out:
 	/* update the index */
 	lx->lx_read += count;
 	lx->lx_read %= lx->buffer_size;
@@ -242,20 +365,100 @@
 	return count;
 }
 
-static ssize_t rtlx_write(struct file *file, const char __user * buffer,
-			  size_t count, loff_t * ppos)
+ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
 {
-	unsigned long failed;
-	int minor;
 	struct rtlx_channel *rt;
 	size_t fl;
+
+	if (rtlx == NULL)
+		return(-ENOSYS);
+
+	rt = &rtlx->channel[index];
+
+	/* total number of bytes to copy */
+	count = min(count,
+		    (size_t)write_spacefree(rt->rt_read, rt->rt_write,
+					    rt->buffer_size));
+
+	/* first bit from write pointer to the end of the buffer, or count */
+	fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+	copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
+
+	/* if there's any left copy to the beginning of the buffer */
+	if( count - fl )
+		copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
+
+	rt->rt_write += count;
+	rt->rt_write %= rt->buffer_size;
+
+	return(count);
+}
+
+
+static int file_open(struct inode *inode, struct file *filp)
+{
+	int minor = iminor(inode);
+
+	return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
+}
+
+static int file_release(struct inode *inode, struct file *filp)
+{
+	int minor = iminor(inode);
+
+	return rtlx_release(minor);
+}
+
+static unsigned int file_poll(struct file *file, poll_table * wait)
+{
+	int minor;
+	unsigned int mask = 0;
+
+	minor = iminor(file->f_dentry->d_inode);
+
+	poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+	poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+	if (rtlx == NULL)
+		return 0;
+
+	/* data available to read? */
+	if (rtlx_read_poll(minor, 0))
+		mask |= POLLIN | POLLRDNORM;
+
+	/* space to write */
+	if (rtlx_write_poll(minor))
+		mask |= POLLOUT | POLLWRNORM;
+
+	return mask;
+}
+
+static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+			 loff_t * ppos)
+{
+	int minor = iminor(file->f_dentry->d_inode);
+
+	/* data available? */
+	if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+		return 0;	// -EAGAIN makes cat whinge
+	}
+
+	return rtlx_read(minor, buffer, count, 1);
+}
+
+static ssize_t file_write(struct file *file, const char __user * buffer,
+			  size_t count, loff_t * ppos)
+{
+	int minor;
+	struct rtlx_channel *rt;
 	DECLARE_WAITQUEUE(wait, current);
 
-	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	minor = iminor(file->f_dentry->d_inode);
 	rt = &rtlx->channel[minor];
 
 	/* any space left... */
-	if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
+	if (!rtlx_write_poll(minor)) {
 
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
@@ -263,61 +466,64 @@
 		add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
 
-		while (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size))
+		while (!rtlx_write_poll(minor))
 			schedule();
 
 		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
 	}
 
-	/* total number of bytes to copy */
-	count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
-
-	/* first bit from write pointer to the end of the buffer, or count */
-	fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
-
-	failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
-	if (failed) {
-		count = fl - failed;
-		goto out;
-	}
-
-	/* if there's any left copy to the beginning of the buffer */
-	if (count - fl) {
-		failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
-		if (failed) {
-			count -= failed;
-			goto out;
-		}
-	}
-
-out:
-	rt->rt_write += count;
-	rt->rt_write %= rt->buffer_size;
-
-	return count;
+	return rtlx_write(minor, (void *)buffer, count, 1);
 }
 
 static struct file_operations rtlx_fops = {
-	.owner		= THIS_MODULE,
-	.open		= rtlx_open,
-	.release	= rtlx_release,
-	.write		= rtlx_write,
-	.read		= rtlx_read,
-	.poll		= rtlx_poll
+	.owner =   THIS_MODULE,
+	.open =    file_open,
+	.release = file_release,
+	.write =   file_write,
+	.read =    file_read,
+	.poll =    file_poll
 };
 
+static struct irqaction rtlx_irq = {
+	.handler	= rtlx_interrupt,
+	.flags		= SA_INTERRUPT,
+	.name		= "RTLX",
+};
+
+static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+
 static char register_chrdev_failed[] __initdata =
 	KERN_ERR "rtlx_module_init: unable to register device\n";
 
-static int __init rtlx_module_init(void)
+static int rtlx_module_init(void)
 {
+	int i;
+
 	major = register_chrdev(0, module_name, &rtlx_fops);
 	if (major < 0) {
 		printk(register_chrdev_failed);
 		return major;
 	}
 
+	/* initialise the wait queues */
+	for (i = 0; i < RTLX_CHANNELS; i++) {
+		init_waitqueue_head(&channel_wqs[i].rt_queue);
+		init_waitqueue_head(&channel_wqs[i].lx_queue);
+		channel_wqs[i].in_open = 0;
+	}
+
+	/* set up notifiers */
+	notify.start = starting;
+	notify.stop = stopping;
+	vpe_notify(RTLX_TARG_VPE, &notify);
+
+	if (cpu_has_vint)
+		set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+
+	rtlx_irq.dev_id = rtlx;
+	setup_irq(rtlx_irq_num, &rtlx_irq);
+
 	return 0;
 }
 
@@ -330,5 +536,5 @@
 module_exit(rtlx_module_exit);
 
 MODULE_DESCRIPTION("MIPS RTLX");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc.");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
 MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 2f2dc54..a0ac0e5 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -569,8 +569,19 @@
 	sys	sys_tkill		2
 	sys	sys_sendfile64		5
 	sys	sys_futex		6
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/*
+	 * For FPU affinity scheduling on MIPS MT processors, we need to
+	 * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+	 * in kernel/sched.c.  Considered only temporary we only support these
+	 * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
+	 */
+	sys	mipsmt_sys_sched_setaffinity	3
+	sys	mipsmt_sys_sched_getaffinity	3
+#else
 	sys	sys_sched_setaffinity	3
 	sys	sys_sched_getaffinity	3	/* 4240 */
+#endif /* CONFIG_MIPS_MT_FPAFF */
 	sys	sys_io_setup		2
 	sys	sys_io_destroy		1
 	sys	sys_io_getevents	5
@@ -634,6 +645,8 @@
 	sys	sys_pselect6		6
 	sys	sys_ppoll		5
 	sys	sys_unshare		1
+	sys	sys_splice		4
+	sys	sys_sync_file_range	7	/* 4305 */
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 98bf25d..9ba7508 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -460,3 +460,5 @@
 	PTR	sys_pselect6			/* 5260 */
 	PTR	sys_ppoll
 	PTR	sys_unshare
+	PTR	sys_splice
+	PTR	sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 05a2c05..942aca2 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -386,3 +386,5 @@
 	PTR	sys_pselect6
 	PTR	sys_ppoll			/* 6265 */
 	PTR	sys_unshare
+	PTR	sys_splice
+	PTR	sys_sync_file_range
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 19c4ca4..b53a920 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -508,4 +508,6 @@
 	PTR	sys_pselect6
 	PTR	sys_ppoll
 	PTR	sys_unshare
+	PTR	sys_splice
+	PTR	sys32_sync_file_range		/* 4305 */
 	.size	sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index dcbfd27..bcf1b10 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -529,7 +529,10 @@
 
 int __init fpu_disable(char *s)
 {
-	cpu_data[0].options &= ~MIPS_CPU_FPU;
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		cpu_data[i].options &= ~MIPS_CPU_FPU;
 
 	return 1;
 }
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp-mt.c
similarity index 88%
rename from arch/mips/kernel/smp_mt.c
rename to arch/mips/kernel/smp-mt.c
index 993b8bf..5777090 100644
--- a/arch/mips/kernel/smp_mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -1,8 +1,4 @@
 /*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  Elizabeth Clarke (beth@mips.com)
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -16,6 +12,10 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * Copyright (C) 2004, 05, 06 MIPS Technologies, Inc.
+ *    Elizabeth Clarke (beth@mips.com)
+ *    Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 
 #include <asm/atomic.h>
+#include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -33,8 +34,8 @@
 #include <asm/time.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
-#include <asm/cacheflush.h>
-#include <asm/mips-boards/maltaint.h>
+#include <asm/mips_mt.h>
+#include <asm/mips-boards/maltaint.h>  /* This is f*cking wrong */
 
 #define MIPS_CPU_IPI_RESCHED_IRQ 0
 #define MIPS_CPU_IPI_CALL_IRQ 1
@@ -66,6 +67,7 @@
 	if (!cpu_has_mipsmt)
 		return;
 
+	/* Enable VPC */
 	set_c0_mvpcontrol(MVPCONTROL_VPC);
 
 	back_to_back_c0_hazard();
@@ -106,12 +108,12 @@
 
 static void ipi_resched_dispatch (struct pt_regs *regs)
 {
-	do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ, regs);
 }
 
 static void ipi_call_dispatch (struct pt_regs *regs)
 {
-	do_IRQ(MIPS_CPU_IPI_CALL_IRQ, regs);
+	do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ, regs);
 }
 
 irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -148,6 +150,11 @@
 	unsigned long val;
 	int i, num;
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/* If we have an FPU, enroll ourselves in the FPU-full mask */
+	if (cpu_has_fpu)
+		cpu_set(0, mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
 	if (!cpu_has_mipsmt)
 		return;
 
@@ -155,6 +162,8 @@
 	dvpe();
 	dmt();
 
+	mips_mt_set_cpuoptions();
+
 	/* Put MVPE's into 'configuration state' */
 	set_c0_mvpcontrol(MVPCONTROL_VPC);
 
@@ -189,11 +198,13 @@
 
 			if (i != 0) {
 				write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
-				write_vpe_c0_cause(read_vpe_c0_cause() & ~CAUSEF_IP);
 
 				/* set config to be the same as vpe0, particularly kseg0 coherency alg */
 				write_vpe_c0_config( read_c0_config());
 
+				/* make sure there are no software interrupts pending */
+				write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+
 				/* Propagate Config7 */
 				write_vpe_c0_config7(read_c0_config7());
 			}
@@ -233,16 +244,16 @@
 	/* We'll wait until starting the secondaries before starting MVPE */
 
 	printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
 
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
 	/* set up ipi interrupts */
 	if (cpu_has_vint) {
 		set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
 		set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
 	}
-}
 
-void __init plat_prepare_cpus(unsigned int max_cpus)
-{
 	cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
 	cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
 
@@ -287,7 +298,8 @@
 	/* global pointer */
 	write_tc_gpr_gp((unsigned long)gp);
 
-	flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1));
+	flush_icache_range((unsigned long)gp,
+	                   (unsigned long)(gp + sizeof(struct thread_info)));
 
 	/* finally out of configuration and into chaos */
 	clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -305,6 +317,12 @@
 {
 	write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/* If we have an FPU, enroll ourselves in the FPU-full mask */
+	if (cpu_has_fpu)
+		cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
 	local_irq_enable();
 }
 
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 78d171b..d42f358 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -38,6 +38,10 @@
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 cpumask_t phys_cpu_present_map;		/* Bitmask of available CPUs */
 volatile cpumask_t cpu_callin_map;	/* Bitmask of started secondaries */
 cpumask_t cpu_online_map;		/* Bitmask of currently online CPUs */
@@ -85,6 +89,10 @@
 {
 	unsigned int cpu;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	/* Only do cpu_probe for first TC of CPU */
+	if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
+#endif /* CONFIG_MIPS_MT_SMTC */
 	cpu_probe();
 	cpu_report();
 	per_cpu_trap_init();
@@ -179,11 +187,13 @@
 	if (wait)
 		while (atomic_read(&data.finished) != cpus)
 			barrier();
+	call_data = NULL;
 	spin_unlock(&smp_call_lock);
 
 	return 0;
 }
 
+
 void smp_call_function_interrupt(void)
 {
 	void (*func) (void *info) = call_data->func;
@@ -446,5 +456,3 @@
 
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_one);
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(synchronize_irq);
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
new file mode 100644
index 0000000..c9d6519
--- /dev/null
+++ b/arch/mips/kernel/smtc-asm.S
@@ -0,0 +1,130 @@
+/*
+ * Assembly Language Functions for MIPS MT SMTC support
+ */
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
+
+#include <asm/regdef.h>
+#include <asm/asmmacro.h>
+#include <asm/stackframe.h>
+#include <asm/stackframe.h>
+
+/*
+ * "Software Interrupt" linkage.
+ *
+ * This is invoked when an "Interrupt" is sent from one TC to another,
+ * where the TC to be interrupted is halted, has it's Restart address
+ * and Status values saved by the "remote control" thread, then modified
+ * to cause execution to begin here, in kenel mode. This code then
+ * disguises the TC state as that of an exception and transfers
+ * control to the general exception or vectored interrupt handler.
+ */
+	.set noreorder
+
+/*
+The __smtc_ipi_vector would use k0 and k1 as temporaries and
+1) Set EXL (this is per-VPE, so this can't be done by proxy!)
+2) Restore the K/CU and IXMT bits to the pre "exception" state
+   (EXL means no interrupts and access to the kernel map).
+3) Set EPC to be the saved value of TCRestart.
+4) Jump to the exception handler entry point passed by the sender.
+
+CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
+*/
+
+/*
+ * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
+ * state of pre-halt thread, then save everything and call
+ * thought some function pointer to imaginary_exception, which
+ * will parse a register value or memory message queue to
+ * deliver things like interprocessor interrupts. On return
+ * from that function, jump to the global ret_from_irq code
+ * to invoke the scheduler and return as appropriate.
+ */
+
+#define PT_PADSLOT4 (PT_R0-8)
+#define PT_PADSLOT5 (PT_R0-4)
+
+	.text
+	.align 5
+FEXPORT(__smtc_ipi_vector)
+	.set	noat
+	/* Disable thread scheduling to make Status update atomic */
+	DMT	27					# dmt	k1
+	ehb
+	/* Set EXL */
+	mfc0	k0,CP0_STATUS
+	ori	k0,k0,ST0_EXL
+	mtc0	k0,CP0_STATUS
+	ehb
+	/* Thread scheduling now inhibited by EXL. Restore TE state. */
+	andi	k1,k1,VPECONTROL_TE
+	beqz	k1,1f
+	emt
+1:
+	/*
+	 * The IPI sender has put some information on the anticipated
+	 * kernel stack frame.  If we were in user mode, this will be
+	 * built above the saved kernel SP.  If we were already in the
+	 * kernel, it will be built above the current CPU SP.
+	 *
+	 * Were we in kernel mode, as indicated by CU0?
+	 */
+	sll	k1,k0,3
+	.set noreorder
+	bltz	k1,2f
+	move	k1,sp
+	.set reorder
+	/*
+	 * If previously in user mode, set CU0 and use kernel stack.
+	 */
+	li	k1,ST0_CU0
+	or	k1,k1,k0
+	mtc0	k1,CP0_STATUS
+	ehb
+	get_saved_sp
+	/* Interrupting TC will have pre-set values in slots in the new frame */
+2:	subu	k1,k1,PT_SIZE
+	/* Load TCStatus Value */
+	lw	k0,PT_TCSTATUS(k1)
+	/* Write it to TCStatus to restore CU/KSU/IXMT state */
+	mtc0	k0,$2,1
+	ehb
+	lw	k0,PT_EPC(k1)
+	mtc0	k0,CP0_EPC
+	/* Save all will redundantly recompute the SP, but use it for now */
+	SAVE_ALL
+	CLI
+	move	a0,sp
+	/* Function to be invoked passed stack pad slot 5 */
+	lw	t0,PT_PADSLOT5(sp)
+	/* Argument from sender passed in stack pad slot 4 */
+	lw	a1,PT_PADSLOT4(sp)
+	jalr	t0
+	nop
+	j	ret_from_irq
+	nop
+
+/*
+ * Called from idle loop to provoke processing of queued IPIs
+ * First IPI message in queue passed as argument.
+ */
+
+LEAF(self_ipi)
+	/* Before anything else, block interrupts */
+	mfc0	t0,CP0_TCSTATUS
+	ori	t1,t0,TCSTATUS_IXMT
+	mtc0	t1,CP0_TCSTATUS
+	ehb
+	/* We know we're in kernel mode, so prepare stack frame */
+	subu	t1,sp,PT_SIZE
+	sw	ra,PT_EPC(t1)
+	sw	a0,PT_PADSLOT4(t1)
+	la	t2,ipi_decode
+	sw	t2,PT_PADSLOT5(t1)
+	/* Save pre-disable value of TCStatus */
+	sw	t0,PT_TCSTATUS(t1)
+	j	__smtc_ipi_vector
+	nop
+END(self_ipi)
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
new file mode 100644
index 0000000..6f37099
--- /dev/null
+++ b/arch/mips/kernel/smtc-proc.c
@@ -0,0 +1,93 @@
+/*
+ * /proc hooks for SMTC kernel
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <linux/proc_fs.h>
+
+#include <asm/smtc_proc.h>
+
+/*
+ * /proc diagnostic and statistics hooks
+ */
+
+/*
+ * Statistics gathered
+ */
+unsigned long selfipis[NR_CPUS];
+
+struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+static struct proc_dir_entry *smtc_stats;
+
+atomic_t smtc_fpu_recoveries;
+
+static int proc_read_smtc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+	int totalen = 0;
+	int len;
+	int i;
+	extern unsigned long ebase;
+
+	len = sprintf(page, "SMTC Status Word: 0x%08x\n", smtc_status);
+	totalen += len;
+	page += len;
+	len = sprintf(page, "Config7: 0x%08x\n", read_c0_config7());
+	totalen += len;
+	page += len;
+	len = sprintf(page, "EBASE: 0x%08lx\n", ebase);
+	totalen += len;
+	page += len;
+	len = sprintf(page, "Counter Interrupts taken per CPU (TC)\n");
+	totalen += len;
+	page += len;
+	for (i=0; i < NR_CPUS; i++) {
+		len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+		totalen += len;
+		page += len;
+	}
+	len = sprintf(page, "Self-IPIs by CPU:\n");
+	totalen += len;
+	page += len;
+	for(i = 0; i < NR_CPUS; i++) {
+		len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+		totalen += len;
+		page += len;
+	}
+	len = sprintf(page, "%d Recoveries of \"stolen\" FPU\n",
+	              atomic_read(&smtc_fpu_recoveries));
+	totalen += len;
+	page += len;
+
+	return totalen;
+}
+
+void init_smtc_stats(void)
+{
+	int i;
+
+	for (i=0; i<NR_CPUS; i++) {
+		smtc_cpu_stats[i].timerints = 0;
+		smtc_cpu_stats[i].selfipis = 0;
+	}
+
+	atomic_set(&smtc_fpu_recoveries, 0);
+
+	smtc_stats = create_proc_read_entry("smtc", 0444, NULL,
+	                                    proc_read_smtc, NULL);
+}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
new file mode 100644
index 0000000..2e8e52c
--- /dev/null
+++ b/arch/mips/kernel/smtc.c
@@ -0,0 +1,1322 @@
+/* Copyright (C) 2004 Mips Technologies, Inc */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/hazards.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/smtc.h>
+#include <asm/smtc_ipi.h>
+#include <asm/smtc_proc.h>
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
+ */
+
+/*
+ * MIPSCPU_INT_BASE is identically defined in both
+ * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
+ * but as yet there's no properly organized include structure that
+ * will ensure that the right *int.h file will be included for a
+ * given platform build.
+ */
+
+#define MIPSCPU_INT_BASE	16
+
+#define MIPS_CPU_IPI_IRQ	1
+
+#define LOCK_MT_PRA() \
+	local_irq_save(flags); \
+	mtflags = dmt()
+
+#define UNLOCK_MT_PRA() \
+	emt(mtflags); \
+	local_irq_restore(flags)
+
+#define LOCK_CORE_PRA() \
+	local_irq_save(flags); \
+	mtflags = dvpe()
+
+#define UNLOCK_CORE_PRA() \
+	evpe(mtflags); \
+	local_irq_restore(flags)
+
+/*
+ * Data structures purely associated with SMTC parallelism
+ */
+
+
+/*
+ * Table for tracking ASIDs whose lifetime is prolonged.
+ */
+
+asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+/*
+ * Clock interrupt "latch" buffers, per "CPU"
+ */
+
+unsigned int ipi_timer_latch[NR_CPUS];
+
+/*
+ * Number of InterProcessor Interupt (IPI) message buffers to allocate
+ */
+
+#define IPIBUF_PER_CPU 4
+
+struct smtc_ipi_q IPIQ[NR_CPUS];
+struct smtc_ipi_q freeIPIq;
+
+
+/* Forward declarations */
+
+void ipi_decode(struct pt_regs *, struct smtc_ipi *);
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+void setup_cross_vpe_interrupts(void);
+void init_smtc_stats(void);
+
+/* Global SMTC Status */
+
+unsigned int smtc_status = 0;
+
+/* Boot command line configuration overrides */
+
+static int vpelimit = 0;
+static int tclimit = 0;
+static int ipibuffers = 0;
+static int nostlb = 0;
+static int asidmask = 0;
+unsigned long smtc_asid_mask = 0xff;
+
+static int __init maxvpes(char *str)
+{
+	get_option(&str, &vpelimit);
+	return 1;
+}
+
+static int __init maxtcs(char *str)
+{
+	get_option(&str, &tclimit);
+	return 1;
+}
+
+static int __init ipibufs(char *str)
+{
+	get_option(&str, &ipibuffers);
+	return 1;
+}
+
+static int __init stlb_disable(char *s)
+{
+	nostlb = 1;
+	return 1;
+}
+
+static int __init asidmask_set(char *str)
+{
+	get_option(&str, &asidmask);
+	switch(asidmask) {
+	case 0x1:
+	case 0x3:
+	case 0x7:
+	case 0xf:
+	case 0x1f:
+	case 0x3f:
+	case 0x7f:
+	case 0xff:
+		smtc_asid_mask = (unsigned long)asidmask;
+		break;
+	default:
+		printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);
+	}
+	return 1;
+}
+
+__setup("maxvpes=", maxvpes);
+__setup("maxtcs=", maxtcs);
+__setup("ipibufs=", ipibufs);
+__setup("nostlb", stlb_disable);
+__setup("asidmask=", asidmask_set);
+
+/* Enable additional debug checks before going into CPU idle loop */
+#define SMTC_IDLE_HOOK_DEBUG
+
+#ifdef SMTC_IDLE_HOOK_DEBUG
+
+static int hang_trig = 0;
+
+static int __init hangtrig_enable(char *s)
+{
+	hang_trig = 1;
+	return 1;
+}
+
+
+__setup("hangtrig", hangtrig_enable);
+
+#define DEFAULT_BLOCKED_IPI_LIMIT 32
+
+static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;
+
+static int __init tintq(char *str)
+{
+	get_option(&str, &timerq_limit);
+	return 1;
+}
+
+__setup("tintq=", tintq);
+
+int imstuckcount[2][8];
+/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
+int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}};
+int tcnoprog[NR_CPUS];
+static atomic_t idle_hook_initialized = {0};
+static int clock_hang_reported[NR_CPUS];
+
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
+
+void __init sanitize_tlb_entries(void)
+{
+	printk("Deprecated sanitize_tlb_entries() invoked\n");
+}
+
+
+/*
+ * Configure shared TLB - VPC configuration bit must be set by caller
+ */
+
+void smtc_configure_tlb(void)
+{
+	int i,tlbsiz,vpes;
+	unsigned long mvpconf0;
+	unsigned long config1val;
+
+	/* Set up ASID preservation table */
+	for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {
+	    for(i = 0; i < MAX_SMTC_ASIDS; i++) {
+		smtc_live_asid[vpes][i] = 0;
+	    }
+	}
+	mvpconf0 = read_c0_mvpconf0();
+
+	if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)
+			>> MVPCONF0_PVPE_SHIFT) + 1) > 1) {
+	    /* If we have multiple VPEs, try to share the TLB */
+	    if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {
+		/*
+		 * If TLB sizing is programmable, shared TLB
+		 * size is the total available complement.
+		 * Otherwise, we have to take the sum of all
+		 * static VPE TLB entries.
+		 */
+		if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)
+				>> MVPCONF0_PTLBE_SHIFT)) == 0) {
+		    /*
+		     * If there's more than one VPE, there had better
+		     * be more than one TC, because we need one to bind
+		     * to each VPE in turn to be able to read
+		     * its configuration state!
+		     */
+		    settc(1);
+		    /* Stop the TC from doing anything foolish */
+		    write_tc_c0_tchalt(TCHALT_H);
+		    mips_ihb();
+		    /* No need to un-Halt - that happens later anyway */
+		    for (i=0; i < vpes; i++) {
+		    	write_tc_c0_tcbind(i);
+			/*
+			 * To be 100% sure we're really getting the right
+			 * information, we exit the configuration state
+			 * and do an IHB after each rebinding.
+			 */
+			write_c0_mvpcontrol(
+				read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+			mips_ihb();
+			/*
+			 * Only count if the MMU Type indicated is TLB
+			 */
+			if(((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
+				config1val = read_vpe_c0_config1();
+				tlbsiz += ((config1val >> 25) & 0x3f) + 1;
+			}
+
+			/* Put core back in configuration state */
+			write_c0_mvpcontrol(
+				read_c0_mvpcontrol() | MVPCONTROL_VPC );
+			mips_ihb();
+		    }
+		}
+		write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+
+		/*
+		 * Setup kernel data structures to use software total,
+		 * rather than read the per-VPE Config1 value. The values
+		 * for "CPU 0" gets copied to all the other CPUs as part
+		 * of their initialization in smtc_cpu_setup().
+		 */
+
+		tlbsiz = tlbsiz & 0x3f;	/* MIPS32 limits TLB indices to 64 */
+		cpu_data[0].tlbsize = tlbsiz;
+		smtc_status |= SMTC_TLB_SHARED;
+
+		printk("TLB of %d entry pairs shared by %d VPEs\n",
+			tlbsiz, vpes);
+	    } else {
+		printk("WARNING: TLB Not Sharable on SMTC Boot!\n");
+	    }
+	}
+}
+
+
+/*
+ * Incrementally build the CPU map out of constituent MIPS MT cores,
+ * using the specified available VPEs and TCs.  Plaform code needs
+ * to ensure that each MIPS MT core invokes this routine on reset,
+ * one at a time(!).
+ *
+ * This version of the build_cpu_map and prepare_cpus routines assumes
+ * that *all* TCs of a MIPS MT core will be used for Linux, and that
+ * they will be spread across *all* available VPEs (to minimise the
+ * loss of efficiency due to exception service serialization).
+ * An improved version would pick up configuration information and
+ * possibly leave some TCs/VPEs as "slave" processors.
+ *
+ * Use c0_MVPConf0 to find out how many TCs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ */
+
+int __init mipsmt_build_cpu_map(int start_cpu_slot)
+{
+	int i, ntcs;
+
+	/*
+	 * The CPU map isn't actually used for anything at this point,
+	 * so it's not clear what else we should do apart from set
+	 * everything up so that "logical" = "physical".
+	 */
+	ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+	for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
+		cpu_set(i, phys_cpu_present_map);
+		__cpu_number_map[i] = i;
+		__cpu_logical_map[i] = i;
+	}
+	/* Initialize map of CPUs with FPUs */
+	cpus_clear(mt_fpu_cpumask);
+
+	/* One of those TC's is the one booting, and not a secondary... */
+	printk("%i available secondary CPU TC(s)\n", i - 1);
+
+	return i;
+}
+
+/*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+ * secondaries.
+ *
+ * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
+ * as possible across the available VPEs.
+ */
+
+static void smtc_tc_setup(int vpe, int tc, int cpu)
+{
+	settc(tc);
+	write_tc_c0_tchalt(TCHALT_H);
+	mips_ihb();
+	write_tc_c0_tcstatus((read_tc_c0_tcstatus()
+			& ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
+			| TCSTATUS_A);
+	write_tc_c0_tccontext(0);
+	/* Bind tc to vpe */
+	write_tc_c0_tcbind(vpe);
+	/* In general, all TCs should have the same cpu_data indications */
+	memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
+	/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
+	if (cpu_data[0].cputype == CPU_34K)
+		cpu_data[cpu].options &= ~MIPS_CPU_FPU;
+	cpu_data[cpu].vpe_id = vpe;
+	cpu_data[cpu].tc_id = tc;
+}
+
+
+void mipsmt_prepare_cpus(void)
+{
+	int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+	unsigned long flags;
+	unsigned long val;
+	int nipi;
+	struct smtc_ipi *pipi;
+
+	/* disable interrupts so we can disable MT */
+	local_irq_save(flags);
+	/* disable MT so we can configure */
+	dvpe();
+	dmt();
+
+	freeIPIq.lock = SPIN_LOCK_UNLOCKED;
+
+	/*
+	 * We probably don't have as many VPEs as we do SMP "CPUs",
+	 * but it's possible - and in any case we'll never use more!
+	 */
+	for (i=0; i<NR_CPUS; i++) {
+		IPIQ[i].head = IPIQ[i].tail = NULL;
+		IPIQ[i].lock = SPIN_LOCK_UNLOCKED;
+		IPIQ[i].depth = 0;
+		ipi_timer_latch[i] = 0;
+	}
+
+	/* cpu_data index starts at zero */
+	cpu = 0;
+	cpu_data[cpu].vpe_id = 0;
+	cpu_data[cpu].tc_id = 0;
+	cpu++;
+
+	/* Report on boot-time options */
+	mips_mt_set_cpuoptions ();
+	if (vpelimit > 0)
+		printk("Limit of %d VPEs set\n", vpelimit);
+	if (tclimit > 0)
+		printk("Limit of %d TCs set\n", tclimit);
+	if (nostlb) {
+		printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");
+	}
+	if (asidmask)
+		printk("ASID mask value override to 0x%x\n", asidmask);
+
+	/* Temporary */
+#ifdef SMTC_IDLE_HOOK_DEBUG
+	if (hang_trig)
+		printk("Logic Analyser Trigger on suspected TC hang\n");
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+	/* Put MVPE's into 'configuration state' */
+	write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
+
+	val = read_c0_mvpconf0();
+	nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+	if (vpelimit > 0 && nvpe > vpelimit)
+		nvpe = vpelimit;
+	ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+	if (ntc > NR_CPUS)
+		ntc = NR_CPUS;
+	if (tclimit > 0 && ntc > tclimit)
+		ntc = tclimit;
+	tcpervpe = ntc / nvpe;
+	slop = ntc % nvpe;	/* Residual TCs, < NVPE */
+
+	/* Set up shared TLB */
+	smtc_configure_tlb();
+
+	for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
+		/*
+		 * Set the MVP bits.
+		 */
+		settc(tc);
+		write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+		if (vpe != 0)
+			printk(", ");
+		printk("VPE %d: TC", vpe);
+		for (i = 0; i < tcpervpe; i++) {
+			/*
+			 * TC 0 is bound to VPE 0 at reset,
+			 * and is presumably executing this
+			 * code.  Leave it alone!
+			 */
+			if (tc != 0) {
+				smtc_tc_setup(vpe,tc, cpu);
+				cpu++;
+			}
+			printk(" %d", tc);
+			tc++;
+		}
+		if (slop) {
+			if (tc != 0) {
+				smtc_tc_setup(vpe,tc, cpu);
+				cpu++;
+			}
+			printk(" %d", tc);
+			tc++;
+			slop--;
+		}
+		if (vpe != 0) {
+			/*
+			 * Clear any stale software interrupts from VPE's Cause
+			 */
+			write_vpe_c0_cause(0);
+
+			/*
+			 * Clear ERL/EXL of VPEs other than 0
+			 * and set restricted interrupt enable/mask.
+			 */
+			write_vpe_c0_status((read_vpe_c0_status()
+				& ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM))
+				| (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7
+				| ST0_IE));
+			/*
+			 * set config to be the same as vpe0,
+			 *  particularly kseg0 coherency alg
+			 */
+			write_vpe_c0_config(read_c0_config());
+			/* Clear any pending timer interrupt */
+			write_vpe_c0_compare(0);
+			/* Propagate Config7 */
+			write_vpe_c0_config7(read_c0_config7());
+		}
+		/* enable multi-threading within VPE */
+		write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
+		/* enable the VPE */
+		write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+	}
+
+	/*
+	 * Pull any physically present but unused TCs out of circulation.
+	 */
+	while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
+		cpu_clear(tc, phys_cpu_present_map);
+		cpu_clear(tc, cpu_present_map);
+		tc++;
+	}
+
+	/* release config state */
+	write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+
+	printk("\n");
+
+	/* Set up coprocessor affinity CPU mask(s) */
+
+	for (tc = 0; tc < ntc; tc++) {
+		if(cpu_data[tc].options & MIPS_CPU_FPU)
+			cpu_set(tc, mt_fpu_cpumask);
+	}
+
+	/* set up ipi interrupts... */
+
+	/* If we have multiple VPEs running, set up the cross-VPE interrupt */
+
+	if (nvpe > 1)
+		setup_cross_vpe_interrupts();
+
+	/* Set up queue of free IPI "messages". */
+	nipi = NR_CPUS * IPIBUF_PER_CPU;
+	if (ipibuffers > 0)
+		nipi = ipibuffers;
+
+	pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL);
+	if (pipi == NULL)
+		panic("kmalloc of IPI message buffers failed\n");
+	else
+		printk("IPI buffer pool of %d buffers\n", nipi);
+	for (i = 0; i < nipi; i++) {
+		smtc_ipi_nq(&freeIPIq, pipi);
+		pipi++;
+	}
+
+	/* Arm multithreading and enable other VPEs - but all TCs are Halted */
+	emt(EMT_ENABLE);
+	evpe(EVPE_ENABLE);
+	local_irq_restore(flags);
+	/* Initialize SMTC /proc statistics/diagnostics */
+	init_smtc_stats();
+}
+
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ * smp_bootstrap is the place to resume from
+ * __KSTK_TOS(idle) is apparently the stack pointer
+ * (unsigned long)idle->thread_info the gp
+ *
+ */
+void smtc_boot_secondary(int cpu, struct task_struct *idle)
+{
+	extern u32 kernelsp[NR_CPUS];
+	long flags;
+	int mtflags;
+
+	LOCK_MT_PRA();
+	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+		dvpe();
+	}
+	settc(cpu_data[cpu].tc_id);
+
+	/* pc */
+	write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+	/* stack pointer */
+	kernelsp[cpu] = __KSTK_TOS(idle);
+	write_tc_gpr_sp(__KSTK_TOS(idle));
+
+	/* global pointer */
+	write_tc_gpr_gp((unsigned long)idle->thread_info);
+
+	smtc_status |= SMTC_MTC_ACTIVE;
+	write_tc_c0_tchalt(0);
+	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+		evpe(EVPE_ENABLE);
+	}
+	UNLOCK_MT_PRA();
+}
+
+void smtc_init_secondary(void)
+{
+	/*
+	 * Start timer on secondary VPEs if necessary.
+	 * mips_timer_setup should already have been invoked by init/main
+	 * on "boot" TC.  Like per_cpu_trap_init() hack, this assumes that
+	 * SMTC init code assigns TCs consdecutively and in ascending order
+	 * to across available VPEs.
+	 */
+	if(((read_c0_tcbind() & TCBIND_CURTC) != 0)
+	&& ((read_c0_tcbind() & TCBIND_CURVPE)
+	    != cpu_data[smp_processor_id() - 1].vpe_id)){
+		write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+	}
+
+	local_irq_enable();
+}
+
+void smtc_smp_finish(void)
+{
+	printk("TC %d going on-line as CPU %d\n",
+		cpu_data[smp_processor_id()].tc_id, smp_processor_id());
+}
+
+void smtc_cpus_done(void)
+{
+}
+
+/*
+ * Support for SMTC-optimized driver IRQ registration
+ */
+
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+
+int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+			unsigned long hwmask)
+{
+	irq_hwmask[irq] = hwmask;
+
+	return setup_irq(irq, new);
+}
+
+/*
+ * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
+ * Within a VPE one TC can interrupt another by different approaches.
+ * The easiest to get right would probably be to make all TCs except
+ * the target IXMT and set a software interrupt, but an IXMT-based
+ * scheme requires that a handler must run before a new IPI could
+ * be sent, which would break the "broadcast" loops in MIPS MT.
+ * A more gonzo approach within a VPE is to halt the TC, extract
+ * its Restart, Status, and a couple of GPRs, and program the Restart
+ * address to emulate an interrupt.
+ *
+ * Within a VPE, one can be confident that the target TC isn't in
+ * a critical EXL state when halted, since the write to the Halt
+ * register could not have issued on the writing thread if the
+ * halting thread had EXL set. So k0 and k1 of the target TC
+ * can be used by the injection code.  Across VPEs, one can't
+ * be certain that the target TC isn't in a critical exception
+ * state. So we try a two-step process of sending a software
+ * interrupt to the target VPE, which either handles the event
+ * itself (if it was the target) or injects the event within
+ * the VPE.
+ */
+
+void smtc_ipi_qdump(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS ;i++) {
+		printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+			i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
+			IPIQ[i].depth);
+	}
+}
+
+/*
+ * The standard atomic.h primitives don't quite do what we want
+ * here: We need an atomic add-and-return-previous-value (which
+ * could be done with atomic_add_return and a decrement) and an
+ * atomic set/zero-and-return-previous-value (which can't really
+ * be done with the atomic.h primitives). And since this is
+ * MIPS MT, we can assume that we have LL/SC.
+ */
+static __inline__ int atomic_postincrement(unsigned int *pv)
+{
+	unsigned long result;
+
+	unsigned long temp;
+
+	__asm__ __volatile__(
+	"1:	ll	%0, %2					\n"
+	"	addu	%1, %0, 1				\n"
+	"	sc	%1, %2					\n"
+	"	beqz	%1, 1b					\n"
+	"	sync						\n"
+	: "=&r" (result), "=&r" (temp), "=m" (*pv)
+	: "m" (*pv)
+	: "memory");
+
+	return result;
+}
+
+/* No longer used in IPI dispatch, but retained for future recycling */
+
+static __inline__ int atomic_postclear(unsigned int *pv)
+{
+	unsigned long result;
+
+	unsigned long temp;
+
+	__asm__ __volatile__(
+	"1:	ll	%0, %2					\n"
+	"	or	%1, $0, $0				\n"
+	"	sc	%1, %2					\n"
+	"	beqz	%1, 1b					\n"
+	"	sync						\n"
+	: "=&r" (result), "=&r" (temp), "=m" (*pv)
+	: "m" (*pv)
+	: "memory");
+
+	return result;
+}
+
+
+void smtc_send_ipi(int cpu, int type, unsigned int action)
+{
+	int tcstatus;
+	struct smtc_ipi *pipi;
+	long flags;
+	int mtflags;
+
+	if (cpu == smp_processor_id()) {
+		printk("Cannot Send IPI to self!\n");
+		return;
+	}
+	/* Set up a descriptor, to be delivered either promptly or queued */
+	pipi = smtc_ipi_dq(&freeIPIq);
+	if (pipi == NULL) {
+		bust_spinlocks(1);
+		mips_mt_regdump(dvpe());
+		panic("IPI Msg. Buffers Depleted\n");
+	}
+	pipi->type = type;
+	pipi->arg = (void *)action;
+	pipi->dest = cpu;
+	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+		/* If not on same VPE, enqueue and send cross-VPE interupt */
+		smtc_ipi_nq(&IPIQ[cpu], pipi);
+		LOCK_CORE_PRA();
+		settc(cpu_data[cpu].tc_id);
+		write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1);
+		UNLOCK_CORE_PRA();
+	} else {
+		/*
+		 * Not sufficient to do a LOCK_MT_PRA (dmt) here,
+		 * since ASID shootdown on the other VPE may
+		 * collide with this operation.
+		 */
+		LOCK_CORE_PRA();
+		settc(cpu_data[cpu].tc_id);
+		/* Halt the targeted TC */
+		write_tc_c0_tchalt(TCHALT_H);
+		mips_ihb();
+
+		/*
+	 	 * Inspect TCStatus - if IXMT is set, we have to queue
+		 * a message. Otherwise, we set up the "interrupt"
+		 * of the other TC
+	 	 */
+		tcstatus = read_tc_c0_tcstatus();
+
+		if ((tcstatus & TCSTATUS_IXMT) != 0) {
+			/*
+			 * Spin-waiting here can deadlock,
+			 * so we queue the message for the target TC.
+			 */
+			write_tc_c0_tchalt(0);
+			UNLOCK_CORE_PRA();
+			/* Try to reduce redundant timer interrupt messages */
+			if(type == SMTC_CLOCK_TICK) {
+			    if(atomic_postincrement(&ipi_timer_latch[cpu])!=0) {
+				smtc_ipi_nq(&freeIPIq, pipi);
+				return;
+			    }
+			}
+			smtc_ipi_nq(&IPIQ[cpu], pipi);
+		} else {
+			post_direct_ipi(cpu, pipi);
+			write_tc_c0_tchalt(0);
+			UNLOCK_CORE_PRA();
+		}
+	}
+}
+
+/*
+ * Send IPI message to Halted TC, TargTC/TargVPE already having been set
+ */
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+{
+	struct pt_regs *kstack;
+	unsigned long tcstatus;
+	unsigned long tcrestart;
+	extern u32 kernelsp[NR_CPUS];
+	extern void __smtc_ipi_vector(void);
+
+	/* Extract Status, EPC from halted TC */
+	tcstatus = read_tc_c0_tcstatus();
+	tcrestart = read_tc_c0_tcrestart();
+	/* If TCRestart indicates a WAIT instruction, advance the PC */
+	if ((tcrestart & 0x80000000)
+	    && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) {
+		tcrestart += 4;
+	}
+	/*
+	 * Save on TC's future kernel stack
+	 *
+	 * CU bit of Status is indicator that TC was
+	 * already running on a kernel stack...
+	 */
+	if(tcstatus & ST0_CU0)  {
+		/* Note that this "- 1" is pointer arithmetic */
+		kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1;
+	} else {
+		kstack = ((struct pt_regs *)kernelsp[cpu]) - 1;
+	}
+
+	kstack->cp0_epc = (long)tcrestart;
+	/* Save TCStatus */
+	kstack->cp0_tcstatus = tcstatus;
+	/* Pass token of operation to be performed kernel stack pad area */
+	kstack->pad0[4] = (unsigned long)pipi;
+	/* Pass address of function to be called likewise */
+	kstack->pad0[5] = (unsigned long)&ipi_decode;
+	/* Set interrupt exempt and kernel mode */
+	tcstatus |= TCSTATUS_IXMT;
+	tcstatus &= ~TCSTATUS_TKSU;
+	write_tc_c0_tcstatus(tcstatus);
+	ehb();
+	/* Set TC Restart address to be SMTC IPI vector */
+	write_tc_c0_tcrestart(__smtc_ipi_vector);
+}
+
+void ipi_resched_interrupt(struct pt_regs *regs)
+{
+	/* Return from interrupt should be enough to cause scheduler check */
+}
+
+
+void ipi_call_interrupt(struct pt_regs *regs)
+{
+	/* Invoke generic function invocation code in smp.c */
+	smp_call_function_interrupt();
+}
+
+void ipi_decode(struct pt_regs *regs, struct smtc_ipi *pipi)
+{
+	void *arg_copy = pipi->arg;
+	int type_copy = pipi->type;
+	int dest_copy = pipi->dest;
+
+	smtc_ipi_nq(&freeIPIq, pipi);
+	switch (type_copy) {
+		case SMTC_CLOCK_TICK:
+			/* Invoke Clock "Interrupt" */
+			ipi_timer_latch[dest_copy] = 0;
+#ifdef SMTC_IDLE_HOOK_DEBUG
+			clock_hang_reported[dest_copy] = 0;
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+			local_timer_interrupt(0, NULL, regs);
+			break;
+		case LINUX_SMP_IPI:
+			switch ((int)arg_copy) {
+			case SMP_RESCHEDULE_YOURSELF:
+				ipi_resched_interrupt(regs);
+				break;
+			case SMP_CALL_FUNCTION:
+				ipi_call_interrupt(regs);
+				break;
+			default:
+				printk("Impossible SMTC IPI Argument 0x%x\n",
+					(int)arg_copy);
+				break;
+			}
+			break;
+		default:
+			printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
+			break;
+	}
+}
+
+void deferred_smtc_ipi(struct pt_regs *regs)
+{
+	struct smtc_ipi *pipi;
+	unsigned long flags;
+/* DEBUG */
+	int q = smp_processor_id();
+
+	/*
+	 * Test is not atomic, but much faster than a dequeue,
+	 * and the vast majority of invocations will have a null queue.
+	 */
+	if(IPIQ[q].head != NULL) {
+		while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
+			/* ipi_decode() should be called with interrupts off */
+			local_irq_save(flags);
+			ipi_decode(regs, pipi);
+			local_irq_restore(flags);
+		}
+	}
+}
+
+/*
+ * Send clock tick to all TCs except the one executing the funtion
+ */
+
+void smtc_timer_broadcast(int vpe)
+{
+	int cpu;
+	int myTC = cpu_data[smp_processor_id()].tc_id;
+	int myVPE = cpu_data[smp_processor_id()].vpe_id;
+
+	smtc_cpu_stats[smp_processor_id()].timerints++;
+
+	for_each_online_cpu(cpu) {
+		if (cpu_data[cpu].vpe_id == myVPE &&
+		    cpu_data[cpu].tc_id != myTC)
+			smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+	}
+}
+
+/*
+ * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
+ * set via cross-VPE MTTR manipulation of the Cause register. It would be
+ * in some regards preferable to have external logic for "doorbell" hardware
+ * interrupts.
+ */
+
+static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+
+static irqreturn_t ipi_interrupt(int irq, void *dev_idm, struct pt_regs *regs)
+{
+	int my_vpe = cpu_data[smp_processor_id()].vpe_id;
+	int my_tc = cpu_data[smp_processor_id()].tc_id;
+	int cpu;
+	struct smtc_ipi *pipi;
+	unsigned long tcstatus;
+	int sent;
+	long flags;
+	unsigned int mtflags;
+	unsigned int vpflags;
+
+	/*
+	 * So long as cross-VPE interrupts are done via
+	 * MFTR/MTTR read-modify-writes of Cause, we need
+	 * to stop other VPEs whenever the local VPE does
+	 * anything similar.
+	 */
+	local_irq_save(flags);
+	vpflags = dvpe();
+	clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ);
+	set_c0_status(0x100 << MIPS_CPU_IPI_IRQ);
+	irq_enable_hazard();
+	evpe(vpflags);
+	local_irq_restore(flags);
+
+	/*
+	 * Cross-VPE Interrupt handler: Try to directly deliver IPIs
+	 * queued for TCs on this VPE other than the current one.
+	 * Return-from-interrupt should cause us to drain the queue
+	 * for the current TC, so we ought not to have to do it explicitly here.
+	 */
+
+	for_each_online_cpu(cpu) {
+		if (cpu_data[cpu].vpe_id != my_vpe)
+			continue;
+
+		pipi = smtc_ipi_dq(&IPIQ[cpu]);
+		if (pipi != NULL) {
+			if (cpu_data[cpu].tc_id != my_tc) {
+				sent = 0;
+				LOCK_MT_PRA();
+				settc(cpu_data[cpu].tc_id);
+				write_tc_c0_tchalt(TCHALT_H);
+				mips_ihb();
+				tcstatus = read_tc_c0_tcstatus();
+				if ((tcstatus & TCSTATUS_IXMT) == 0) {
+					post_direct_ipi(cpu, pipi);
+					sent = 1;
+				}
+				write_tc_c0_tchalt(0);
+				UNLOCK_MT_PRA();
+				if (!sent) {
+					smtc_ipi_req(&IPIQ[cpu], pipi);
+				}
+			} else {
+				/*
+				 * ipi_decode() should be called
+				 * with interrupts off
+				 */
+				local_irq_save(flags);
+				ipi_decode(regs, pipi);
+				local_irq_restore(flags);
+			}
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void ipi_irq_dispatch(struct pt_regs *regs)
+{
+	do_IRQ(cpu_ipi_irq, regs);
+}
+
+static struct irqaction irq_ipi;
+
+void setup_cross_vpe_interrupts(void)
+{
+	if (!cpu_has_vint)
+		panic("SMTC Kernel requires Vectored Interupt support");
+
+	set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
+
+	irq_ipi.handler = ipi_interrupt;
+	irq_ipi.flags = SA_INTERRUPT;
+	irq_ipi.name = "SMTC_IPI";
+
+	setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
+
+	irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+}
+
+/*
+ * SMTC-specific hacks invoked from elsewhere in the kernel.
+ */
+
+void smtc_idle_loop_hook(void)
+{
+#ifdef SMTC_IDLE_HOOK_DEBUG
+	int im;
+	int flags;
+	int mtflags;
+	int bit;
+	int vpe;
+	int tc;
+	int hook_ntcs;
+	/*
+	 * printk within DMT-protected regions can deadlock,
+	 * so buffer diagnostic messages for later output.
+	 */
+	char *pdb_msg;
+	char id_ho_db_msg[768]; /* worst-case use should be less than 700 */
+
+	if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */
+		if (atomic_add_return(1, &idle_hook_initialized) == 1) {
+			int mvpconf0;
+			/* Tedious stuff to just do once */
+			mvpconf0 = read_c0_mvpconf0();
+			hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+			if (hook_ntcs > NR_CPUS)
+				hook_ntcs = NR_CPUS;
+			for (tc = 0; tc < hook_ntcs; tc++) {
+				tcnoprog[tc] = 0;
+				clock_hang_reported[tc] = 0;
+	    		}
+			for (vpe = 0; vpe < 2; vpe++)
+				for (im = 0; im < 8; im++)
+					imstuckcount[vpe][im] = 0;
+			printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs);
+			atomic_set(&idle_hook_initialized, 1000);
+		} else {
+			/* Someone else is initializing in parallel - let 'em finish */
+			while (atomic_read(&idle_hook_initialized) < 1000)
+				;
+		}
+	}
+
+	/* Have we stupidly left IXMT set somewhere? */
+	if (read_c0_tcstatus() & 0x400) {
+		write_c0_tcstatus(read_c0_tcstatus() & ~0x400);
+		ehb();
+		printk("Dangling IXMT in cpu_idle()\n");
+	}
+
+	/* Have we stupidly left an IM bit turned off? */
+#define IM_LIMIT 2000
+	local_irq_save(flags);
+	mtflags = dmt();
+	pdb_msg = &id_ho_db_msg[0];
+	im = read_c0_status();
+	vpe = cpu_data[smp_processor_id()].vpe_id;
+	for (bit = 0; bit < 8; bit++) {
+		/*
+		 * In current prototype, I/O interrupts
+		 * are masked for VPE > 0
+		 */
+		if (vpemask[vpe][bit]) {
+			if (!(im & (0x100 << bit)))
+				imstuckcount[vpe][bit]++;
+			else
+				imstuckcount[vpe][bit] = 0;
+			if (imstuckcount[vpe][bit] > IM_LIMIT) {
+				set_c0_status(0x100 << bit);
+				ehb();
+				imstuckcount[vpe][bit] = 0;
+				pdb_msg += sprintf(pdb_msg,
+					"Dangling IM %d fixed for VPE %d\n", bit,
+					vpe);
+			}
+		}
+	}
+
+	/*
+	 * Now that we limit outstanding timer IPIs, check for hung TC
+	 */
+	for (tc = 0; tc < NR_CPUS; tc++) {
+		/* Don't check ourself - we'll dequeue IPIs just below */
+		if ((tc != smp_processor_id()) &&
+		    ipi_timer_latch[tc] > timerq_limit) {
+		    if (clock_hang_reported[tc] == 0) {
+			pdb_msg += sprintf(pdb_msg,
+				"TC %d looks hung with timer latch at %d\n",
+				tc, ipi_timer_latch[tc]);
+			clock_hang_reported[tc]++;
+			}
+		}
+	}
+	emt(mtflags);
+	local_irq_restore(flags);
+	if (pdb_msg != &id_ho_db_msg[0])
+		printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+	/*
+	 * To the extent that we've ever turned interrupts off,
+	 * we may have accumulated deferred IPIs.  This is subtle.
+	 * If we use the smtc_ipi_qdepth() macro, we'll get an
+	 * exact number - but we'll also disable interrupts
+	 * and create a window of failure where a new IPI gets
+	 * queued after we test the depth but before we re-enable
+	 * interrupts. So long as IXMT never gets set, however,
+	 * we should be OK:  If we pick up something and dispatch
+	 * it here, that's great. If we see nothing, but concurrent
+	 * with this operation, another TC sends us an IPI, IXMT
+	 * is clear, and we'll handle it as a real pseudo-interrupt
+	 * and not a pseudo-pseudo interrupt.
+	 */
+	if (IPIQ[smp_processor_id()].depth > 0) {
+		struct smtc_ipi *pipi;
+		extern void self_ipi(struct smtc_ipi *);
+
+		if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
+			self_ipi(pipi);
+			smtc_cpu_stats[smp_processor_id()].selfipis++;
+		}
+	}
+}
+
+void smtc_soft_dump(void)
+{
+	int i;
+
+	printk("Counter Interrupts taken per CPU (TC)\n");
+	for (i=0; i < NR_CPUS; i++) {
+		printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+	}
+	printk("Self-IPI invocations:\n");
+	for (i=0; i < NR_CPUS; i++) {
+		printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+	}
+	smtc_ipi_qdump();
+	printk("Timer IPI Backlogs:\n");
+	for (i=0; i < NR_CPUS; i++) {
+		printk("%d: %d\n", i, ipi_timer_latch[i]);
+	}
+	printk("%d Recoveries of \"stolen\" FPU\n",
+	       atomic_read(&smtc_fpu_recoveries));
+}
+
+
+/*
+ * TLB management routines special to SMTC
+ */
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
+{
+	unsigned long flags, mtflags, tcstat, prevhalt, asid;
+	int tlb, i;
+
+	/*
+	 * It would be nice to be able to use a spinlock here,
+	 * but this is invoked from within TLB flush routines
+	 * that protect themselves with DVPE, so if a lock is
+         * held by another TC, it'll never be freed.
+	 *
+	 * DVPE/DMT must not be done with interrupts enabled,
+	 * so even so most callers will already have disabled
+	 * them, let's be really careful...
+	 */
+
+	local_irq_save(flags);
+	if (smtc_status & SMTC_TLB_SHARED) {
+		mtflags = dvpe();
+		tlb = 0;
+	} else {
+		mtflags = dmt();
+		tlb = cpu_data[cpu].vpe_id;
+	}
+	asid = asid_cache(cpu);
+
+	do {
+		if (!((asid += ASID_INC) & ASID_MASK) ) {
+			if (cpu_has_vtag_icache)
+				flush_icache_all();
+			/* Traverse all online CPUs (hack requires contigous range) */
+			for (i = 0; i < num_online_cpus(); i++) {
+				/*
+				 * We don't need to worry about our own CPU, nor those of
+				 * CPUs who don't share our TLB.
+				 */
+				if ((i != smp_processor_id()) &&
+				    ((smtc_status & SMTC_TLB_SHARED) ||
+				     (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) {
+					settc(cpu_data[i].tc_id);
+					prevhalt = read_tc_c0_tchalt() & TCHALT_H;
+					if (!prevhalt) {
+						write_tc_c0_tchalt(TCHALT_H);
+						mips_ihb();
+					}
+					tcstat = read_tc_c0_tcstatus();
+					smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
+					if (!prevhalt)
+						write_tc_c0_tchalt(0);
+				}
+			}
+			if (!asid)		/* fix version if needed */
+				asid = ASID_FIRST_VERSION;
+			local_flush_tlb_all();	/* start new asid cycle */
+		}
+	} while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
+
+	/*
+	 * SMTC shares the TLB within VPEs and possibly across all VPEs.
+	 */
+	for (i = 0; i < num_online_cpus(); i++) {
+		if ((smtc_status & SMTC_TLB_SHARED) ||
+		    (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+			cpu_context(i, mm) = asid_cache(i) = asid;
+	}
+
+	if (smtc_status & SMTC_TLB_SHARED)
+		evpe(mtflags);
+	else
+		emt(mtflags);
+	local_irq_restore(flags);
+}
+
+/*
+ * Invoked from macros defined in mmu_context.h
+ * which must already have disabled interrupts
+ * and done a DVPE or DMT as appropriate.
+ */
+
+void smtc_flush_tlb_asid(unsigned long asid)
+{
+	int entry;
+	unsigned long ehi;
+
+	entry = read_c0_wired();
+
+	/* Traverse all non-wired entries */
+	while (entry < current_cpu_data.tlbsize) {
+		write_c0_index(entry);
+		ehb();
+		tlb_read();
+		ehb();
+		ehi = read_c0_entryhi();
+		if((ehi & ASID_MASK) == asid) {
+		    /*
+		     * Invalidate only entries with specified ASID,
+		     * makiing sure all entries differ.
+		     */
+		    write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+		    write_c0_entrylo0(0);
+		    write_c0_entrylo1(0);
+		    mtc0_tlbw_hazard();
+		    tlb_write_indexed();
+		}
+		entry++;
+	}
+	write_c0_index(PARKED_INDEX);
+	tlbw_use_hazard();
+}
+
+/*
+ * Support for single-threading cache flush operations.
+ */
+
+int halt_state_save[NR_CPUS];
+
+/*
+ * To really, really be sure that nothing is being done
+ * by other TCs, halt them all.  This code assumes that
+ * a DVPE has already been done, so while their Halted
+ * state is theoretically architecturally unstable, in
+ * practice, it's not going to change while we're looking
+ * at it.
+ */
+
+void smtc_cflush_lockdown(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		if (cpu != smp_processor_id()) {
+			settc(cpu_data[cpu].tc_id);
+			halt_state_save[cpu] = read_tc_c0_tchalt();
+			write_tc_c0_tchalt(TCHALT_H);
+		}
+	}
+	mips_ihb();
+}
+
+/* It would be cheating to change the cpu_online states during a flush! */
+
+void smtc_cflush_release(void)
+{
+	int cpu;
+
+	/*
+	 * Start with a hazard barrier to ensure
+	 * that all CACHE ops have played through.
+	 */
+	mips_ihb();
+
+	for_each_online_cpu(cpu) {
+		if (cpu != smp_processor_id()) {
+			settc(cpu_data[cpu].tc_id);
+			write_tc_c0_tchalt(halt_state_save[cpu]);
+		}
+	}
+	mips_ihb();
+}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 5e51a2d..13ff4da 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -116,8 +116,7 @@
 	write_c0_compare(expirelo);
 
 	/* Check to see if we have missed any timer interrupts.  */
-	count = read_c0_count();
-	if ((count - expirelo) < 0x7fffffff) {
+	while (((count = read_c0_count()) - expirelo) < 0x7fffffff) {
 		/* missed_timer_count++; */
 		expirelo = count + cycles_per_jiffy;
 		write_c0_compare(expirelo);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index bed0eb6..4901f0a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -42,6 +42,7 @@
 #include <asm/watch.h>
 #include <asm/types.h>
 
+extern asmlinkage void handle_int(void);
 extern asmlinkage void handle_tlbm(void);
 extern asmlinkage void handle_tlbl(void);
 extern asmlinkage void handle_tlbs(void);
@@ -279,9 +280,16 @@
 NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
 {
 	static int die_counter;
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long dvpret = dvpe();
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+#ifdef CONFIG_MIPS_MT_SMTC
+	mips_mt_regdump(dvpret);
+#endif /* CONFIG_MIPS_MT_SMTC */
 	printk("%s[#%d]:\n", str, ++die_counter);
 	show_registers(regs);
 	spin_unlock_irq(&die_lock);
@@ -750,12 +758,43 @@
 						&current->thread.fpu.soft);
 			if (sig)
 				force_sig(sig, current);
+#ifdef CONFIG_MIPS_MT_FPAFF
+			else {
+			/*
+			 * MIPS MT processors may have fewer FPU contexts
+			 * than CPU threads. If we've emulated more than
+			 * some threshold number of instructions, force
+			 * migration to a "CPU" that has FP support.
+			 */
+			 if(mt_fpemul_threshold > 0
+			 && ((current->thread.emulated_fp++
+			    > mt_fpemul_threshold))) {
+			  /*
+			   * If there's no FPU present, or if the
+			   * application has already restricted
+			   * the allowed set to exclude any CPUs
+			   * with FPUs, we'll skip the procedure.
+			   */
+			  if (cpus_intersects(current->cpus_allowed,
+			  			mt_fpu_cpumask)) {
+			    cpumask_t tmask;
+
+			    cpus_and(tmask,
+					current->thread.user_cpus_allowed,
+					mt_fpu_cpumask);
+			    set_cpus_allowed(current, tmask);
+			    current->thread.mflags |= MF_FPUBOUND;
+			  }
+			 }
+			}
+#endif /* CONFIG_MIPS_MT_FPAFF */
 		}
 
 		return;
 
 	case 2:
 	case 3:
+		die_if_kernel("do_cpu invoked from kernel context!", regs);
 		break;
 	}
 
@@ -793,6 +832,36 @@
 
 asmlinkage void do_mt(struct pt_regs *regs)
 {
+	int subcode;
+
+	die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+	subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
+			>> VPECONTROL_EXCPT_SHIFT;
+	switch (subcode) {
+	case 0:
+		printk(KERN_ERR "Thread Underflow\n");
+		break;
+	case 1:
+		printk(KERN_ERR "Thread Overflow\n");
+		break;
+	case 2:
+		printk(KERN_ERR "Invalid YIELD Qualifier\n");
+		break;
+	case 3:
+		printk(KERN_ERR "Gating Storage Exception\n");
+		break;
+	case 4:
+		printk(KERN_ERR "YIELD Scheduler Exception\n");
+		break;
+	case 5:
+		printk(KERN_ERR "Gating Storage Schedulier Exception\n");
+		break;
+	default:
+		printk(KERN_ERR "*** UNKNOWN THREAD EXCEPTION %d ***\n",
+			subcode);
+		break;
+	}
 	die_if_kernel("MIPS MT Thread exception in kernel", regs);
 
 	force_sig(SIGILL, current);
@@ -928,7 +997,15 @@
  */
 void nmi_exception_handler(struct pt_regs *regs)
 {
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long dvpret = dvpe();
+	bust_spinlocks(1);
 	printk("NMI taken!!!!\n");
+	mips_mt_regdump(dvpret);
+#else
+	bust_spinlocks(1);
+	printk("NMI taken!!!!\n");
+#endif /* CONFIG_MIPS_MT_SMTC */
 	die("NMI", regs);
 	while(1) ;
 }
@@ -960,27 +1037,29 @@
 
 #ifdef CONFIG_CPU_MIPSR2
 /*
- * Shadow register allocation
+ * MIPSR2 shadow register set allocation
  * FIXME: SMP...
  */
 
-/* MIPSR2 shadow register sets */
-struct shadow_registers {
-	spinlock_t sr_lock;	/*  */
-	int sr_supported;	/* Number of shadow register sets supported */
-	int sr_allocated;	/* Bitmap of allocated shadow registers */
+static struct shadow_registers {
+	/*
+	 * Number of shadow register sets supported
+	 */
+	unsigned long sr_supported;
+	/*
+	 * Bitmap of allocated shadow registers
+	 */
+	unsigned long sr_allocated;
 } shadow_registers;
 
-void mips_srs_init(void)
+static void mips_srs_init(void)
 {
 #ifdef CONFIG_CPU_MIPSR2_SRS
 	shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
-	printk ("%d MIPSR2 register sets available\n", shadow_registers.sr_supported);
-#else
-	shadow_registers.sr_supported = 1;
+	printk(KERN_INFO "%d MIPSR2 register sets available\n",
+	       shadow_registers.sr_supported);
 #endif
 	shadow_registers.sr_allocated = 1;	/* Set 0 used by kernel */
-	spin_lock_init(&shadow_registers.sr_lock);
 }
 
 int mips_srs_max(void)
@@ -988,38 +1067,30 @@
 	return shadow_registers.sr_supported;
 }
 
-int mips_srs_alloc (void)
+int mips_srs_alloc(void)
 {
 	struct shadow_registers *sr = &shadow_registers;
-	unsigned long flags;
 	int set;
 
-	spin_lock_irqsave(&sr->sr_lock, flags);
+again:
+	set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
+	if (set >= sr->sr_supported)
+		return -1;
 
-	for (set = 0; set < sr->sr_supported; set++) {
-		if ((sr->sr_allocated & (1 << set)) == 0) {
-			sr->sr_allocated |= 1 << set;
-			spin_unlock_irqrestore(&sr->sr_lock, flags);
-			return set;
-		}
-	}
+	if (test_and_set_bit(set, &sr->sr_allocated))
+		goto again;
 
-	/* None available */
-	spin_unlock_irqrestore(&sr->sr_lock, flags);
-	return -1;
+	return set;
 }
 
-void mips_srs_free (int set)
+void mips_srs_free(int set)
 {
 	struct shadow_registers *sr = &shadow_registers;
-	unsigned long flags;
 
-	spin_lock_irqsave(&sr->sr_lock, flags);
-	sr->sr_allocated &= ~(1 << set);
-	spin_unlock_irqrestore(&sr->sr_lock, flags);
+	clear_bit(set, &sr->sr_allocated);
 }
 
-void *set_vi_srs_handler (int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, void *addr, int srs)
 {
 	unsigned long handler;
 	unsigned long old_handler = vi_handlers[n];
@@ -1032,8 +1103,7 @@
 	if (addr == NULL) {
 		handler = (unsigned long) do_default_vi;
 		srs = 0;
-	}
-	else
+	} else
 		handler = (unsigned long) addr;
 	vi_handlers[n] = (unsigned long) addr;
 
@@ -1045,8 +1115,7 @@
 	if (cpu_has_veic) {
 		if (board_bind_eic_interrupt)
 			board_bind_eic_interrupt (n, srs);
-	}
-	else if (cpu_has_vint) {
+	} else if (cpu_has_vint) {
 		/* SRSMap is only defined if shadow sets are implemented */
 		if (mips_srs_max() > 1)
 			change_c0_srsmap (0xf << n*4, srs << n*4);
@@ -1060,6 +1129,15 @@
 
 		extern char except_vec_vi, except_vec_vi_lui;
 		extern char except_vec_vi_ori, except_vec_vi_end;
+#ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * We need to provide the SMTC vectored interrupt handler
+		 * not only with the address of the handler, but with the
+		 * Status.IM bit to be masked before going there.
+		 */
+		extern char except_vec_vi_mori;
+		const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+#endif /* CONFIG_MIPS_MT_SMTC */
 		const int handler_len = &except_vec_vi_end - &except_vec_vi;
 		const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
 		const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
@@ -1073,6 +1151,12 @@
 		}
 
 		memcpy (b, &except_vec_vi, handler_len);
+#ifdef CONFIG_MIPS_MT_SMTC
+		if (n > 7)
+			printk("Vector index %d exceeds SMTC maximum\n", n);
+		w = (u32 *)(b + mori_offset);
+		*w = (*w & 0xffff0000) | (0x100 << n);
+#endif /* CONFIG_MIPS_MT_SMTC */
 		w = (u32 *)(b + lui_offset);
 		*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
 		w = (u32 *)(b + ori_offset);
@@ -1095,9 +1179,9 @@
 	return (void *)old_handler;
 }
 
-void *set_vi_handler (int n, void *addr)
+void *set_vi_handler(int n, void *addr)
 {
-	return set_vi_srs_handler (n, addr, 0);
+	return set_vi_srs_handler(n, addr, 0);
 }
 #endif
 
@@ -1113,8 +1197,29 @@
 extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
 extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
 
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext *sc)
+{
+	return cpu_has_fpu
+	       ? _save_fp_context(sc)
+	       : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext *sc)
+{
+	return cpu_has_fpu
+	       ? _restore_fp_context(sc)
+	       : fpu_emulator_restore_context(sc);
+}
+#endif
+
 static inline void signal_init(void)
 {
+#ifdef CONFIG_SMP
+	/* For now just do the cpu_has_fpu check when the functions are invoked */
+	save_fp_context = smp_save_fp_context;
+	restore_fp_context = smp_restore_fp_context;
+#else
 	if (cpu_has_fpu) {
 		save_fp_context = _save_fp_context;
 		restore_fp_context = _restore_fp_context;
@@ -1122,6 +1227,7 @@
 		save_fp_context = fpu_emulator_save_context;
 		restore_fp_context = fpu_emulator_restore_context;
 	}
+#endif
 }
 
 #ifdef CONFIG_MIPS32_COMPAT
@@ -1158,6 +1264,20 @@
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned int status_set = ST0_CU0;
+#ifdef CONFIG_MIPS_MT_SMTC
+	int secondaryTC = 0;
+	int bootTC = (cpu == 0);
+
+	/*
+	 * Only do per_cpu_trap_init() for first TC of Each VPE.
+	 * Note that this hack assumes that the SMTC init code
+	 * assigns TCs consecutively and in ascending order.
+	 */
+
+	if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
+	    ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
+		secondaryTC = 1;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	/*
 	 * Disable coprocessors and select 32-bit or 64-bit addressing
@@ -1180,6 +1300,10 @@
 	write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
 #endif
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	if (!secondaryTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 	/*
 	 * Interrupt handling.
 	 */
@@ -1196,6 +1320,9 @@
 		} else
 			set_c0_cause(CAUSEF_IV);
 	}
+#ifdef CONFIG_MIPS_MT_SMTC
+	}
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 	TLBMISS_HANDLER_SETUP();
@@ -1205,8 +1332,14 @@
 	BUG_ON(current->mm);
 	enter_lazy_tlb(&init_mm, current);
 
-	cpu_cache_init();
-	tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+	if (bootTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+		cpu_cache_init();
+		tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+	}
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /* Install CPU exception handler */
@@ -1278,7 +1411,7 @@
 	if (cpu_has_veic || cpu_has_vint) {
 		int nvec = cpu_has_veic ? 64 : 8;
 		for (i = 0; i < nvec; i++)
-			set_vi_handler (i, NULL);
+			set_vi_handler(i, NULL);
 	}
 	else if (cpu_has_divec)
 		set_handler(0x200, &except_vec4, 0x8);
@@ -1297,6 +1430,7 @@
 	if (board_be_init)
 		board_be_init();
 
+	set_except_vector(0, handle_int);
 	set_except_vector(1, handle_tlbm);
 	set_except_vector(2, handle_tlbl);
 	set_except_vector(3, handle_tlbs);
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 2ad0ced..14fa00e 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -2,7 +2,7 @@
 #include <asm/asm-offsets.h>
 #include <asm-generic/vmlinux.lds.h>
 
-#undef mips		/* CPP really sucks for this job  */
+#undef mips
 #define mips mips
 OUTPUT_ARCH(mips)
 ENTRY(kernel_entry)
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index ae83b75..85d7df7 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -13,7 +13,6 @@
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
  */
 
 /*
@@ -27,11 +26,8 @@
  *
  * To load and run, simply cat a SP 'program file' to /dev/vpe1.
  * i.e cat spapp >/dev/vpe1.
- *
- * You'll need to have the following device files.
- * mknod /dev/vpe0 c 63 0
- * mknod /dev/vpe1 c 63 1
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -55,6 +51,8 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/vpe.h>
+#include <asm/kspd.h>
 
 typedef void *vpe_handle;
 
@@ -68,6 +66,11 @@
 static char module_name[] = "vpe";
 static int major;
 
+#ifdef CONFIG_MIPS_APSP_KSPD
+ static struct kspd_notifications kspd_events;
+static int kspd_events_reqd = 0;
+#endif
+
 /* grab the likely amount of memory we will need. */
 #ifdef CONFIG_MIPS_VPE_LOADER_TOM
 #define P_SIZE (2 * 1024 * 1024)
@@ -76,7 +79,10 @@
 #define P_SIZE (256 * 1024)
 #endif
 
+extern unsigned long physical_memsize;
+
 #define MAX_VPES 16
+#define VPE_PATH_MAX 256
 
 enum vpe_state {
 	VPE_STATE_UNUSED = 0,
@@ -102,6 +108,8 @@
 	unsigned long len;
 	char *pbuffer;
 	unsigned long plen;
+	unsigned int uid, gid;
+	char cwd[VPE_PATH_MAX];
 
 	unsigned long __start;
 
@@ -113,6 +121,9 @@
 
 	/* shared symbol address */
 	void *shared_ptr;
+
+	/* the list of who wants to know when something major happens */
+	struct list_head notify;
 };
 
 struct tc {
@@ -138,7 +149,7 @@
 } vpecontrol;
 
 static void release_progmem(void *ptr);
-static void dump_vpe(struct vpe * v);
+/* static __attribute_used__ void dump_vpe(struct vpe * v); */
 extern void save_gp_address(unsigned int secbase, unsigned int rel);
 
 /* get the vpe associated with this minor */
@@ -146,12 +157,14 @@
 {
 	struct vpe *v;
 
+	if (!cpu_has_mipsmt)
+		return NULL;
+
 	list_for_each_entry(v, &vpecontrol.vpe_list, list) {
 		if (v->minor == minor)
 			return v;
 	}
 
-	printk(KERN_DEBUG "VPE: get_vpe minor %d not found\n", minor);
 	return NULL;
 }
 
@@ -165,8 +178,6 @@
 			return t;
 	}
 
-	printk(KERN_DEBUG "VPE: get_tc index %d not found\n", index);
-
 	return NULL;
 }
 
@@ -179,8 +190,6 @@
 			return t;
 	}
 
-	printk(KERN_DEBUG "VPE: All TC's are in use\n");
-
 	return NULL;
 }
 
@@ -190,13 +199,13 @@
 	struct vpe *v;
 
 	if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
 		return NULL;
 	}
 
 	INIT_LIST_HEAD(&v->tc);
 	list_add_tail(&v->list, &vpecontrol.vpe_list);
 
+	INIT_LIST_HEAD(&v->notify);
 	v->minor = minor;
 	return v;
 }
@@ -207,7 +216,6 @@
 	struct tc *t;
 
 	if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "VPE: alloc_tc no mem\n");
 		return NULL;
 	}
 
@@ -236,20 +244,16 @@
 	printk("config3 0x%lx MT %ld\n", val,
 	       (val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
 
-	val = read_c0_mvpconf0();
-	printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
-	       (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
-	       val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
-
 	val = read_c0_mvpcontrol();
 	printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
 	       (val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
 	       (val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
 	       (val & MVPCONTROL_EVP));
 
-	val = read_c0_vpeconf0();
-	printk("VPEConf0 0x%lx MVP %ld\n", val,
-	       (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+	val = read_c0_mvpconf0();
+	printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
+	       (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
+	       val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
 }
 
 /* Find some VPE program space  */
@@ -354,9 +358,9 @@
 	}
 
 	if( (rel > 32768) || (rel < -32768) ) {
-		printk(KERN_ERR
-		       "apply_r_mips_gprel16: relative address out of range 0x%x %d\n",
-		       rel, rel);
+		printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: "
+		       "relative address 0x%x out of range of gp register\n",
+		       rel);
 		return -ENOEXEC;
 	}
 
@@ -374,8 +378,8 @@
 	rel -= 1;		// and one instruction less due to the branch delay slot.
 
 	if( (rel > 32768) || (rel < -32768) ) {
-		printk(KERN_ERR
-		       "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+		printk(KERN_DEBUG "VPE loader: "
+ 		       "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
 		return -ENOEXEC;
 	}
 
@@ -396,7 +400,8 @@
 			   Elf32_Addr v)
 {
 	if (v % 4) {
-		printk(KERN_ERR "module %s: dangerous relocation mod4\n", me->name);
+		printk(KERN_DEBUG "VPE loader: apply_r_mips_26 "
+		       " unaligned relocation\n");
 		return -ENOEXEC;
 	}
 
@@ -459,12 +464,13 @@
 			/*
 			 * The value for the HI16 had best be the same.
 			 */
-			if (v != l->value) {
-				printk("%d != %d\n", v, l->value);
-				goto out_danger;
+ 			if (v != l->value) {
+				printk(KERN_DEBUG "VPE loader: "
+				       "apply_r_mips_lo16/hi16: 	"
+				       "inconsistent value information\n");
+				return -ENOEXEC;
 			}
 
-
 			/*
 			 * Do the HI16 relocation.  Note that we actually don't
 			 * need to know anything about the LO16 itself, except
@@ -500,11 +506,6 @@
 	*location = insnlo;
 
 	return 0;
-
-out_danger:
-	printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
-	return -ENOEXEC;
 }
 
 static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -518,6 +519,15 @@
 	[R_MIPS_PC16] = apply_r_mips_pc16
 };
 
+static char *rstrs[] = {
+    	[R_MIPS_NONE]	= "MIPS_NONE",
+	[R_MIPS_32]	= "MIPS_32",
+	[R_MIPS_26]	= "MIPS_26",
+	[R_MIPS_HI16]	= "MIPS_HI16",
+	[R_MIPS_LO16]	= "MIPS_LO16",
+	[R_MIPS_GPREL16] = "MIPS_GPREL16",
+	[R_MIPS_PC16] = "MIPS_PC16"
+};
 
 int apply_relocations(Elf32_Shdr *sechdrs,
 		      const char *strtab,
@@ -552,15 +562,13 @@
 
 		res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
 		if( res ) {
-			printk(KERN_DEBUG
-			       "relocation error 0x%x sym refer <%s> value 0x%x "
-			       "type 0x%x r_info 0x%x\n",
-			       (unsigned int)location, strtab + sym->st_name, v,
-			       r_info, ELF32_R_TYPE(r_info));
-		}
-
-		if (res)
+			char *r = rstrs[ELF32_R_TYPE(r_info)];
+		    	printk(KERN_WARNING "VPE loader: .text+0x%x "
+			       "relocation type %s for symbol \"%s\" failed\n",
+			       rel[i].r_offset, r ? r : "UNKNOWN",
+			       strtab + sym->st_name);
 			return res;
+		}
 	}
 
 	return 0;
@@ -576,7 +584,7 @@
 
 
 /* Change all symbols so that sh_value encodes the pointer directly. */
-static int simplify_symbols(Elf_Shdr * sechdrs,
+static void simplify_symbols(Elf_Shdr * sechdrs,
 			    unsigned int symindex,
 			    const char *strtab,
 			    const char *secstrings,
@@ -585,18 +593,21 @@
 	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
 	unsigned long secbase, bssbase = 0;
 	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
-	int ret = 0, size;
+	int size;
 
 	/* find the .bss section for COMMON symbols */
 	for (i = 0; i < nsecs; i++) {
-		if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0)
+		if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0) {
 			bssbase = sechdrs[i].sh_addr;
+			break;
+		}
 	}
 
 	for (i = 1; i < n; i++) {
 		switch (sym[i].st_shndx) {
 		case SHN_COMMON:
-			/* Allocate space for the symbol in the .bss section. st_value is currently size.
+			/* Allocate space for the symbol in the .bss section.
+			   st_value is currently size.
 			   We want it to have the address of the symbol. */
 
 			size = sym[i].st_value;
@@ -614,11 +625,9 @@
 			break;
 
 		case SHN_MIPS_SCOMMON:
-
-			printk(KERN_DEBUG
-			       "simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
-			       strtab + sym[i].st_name, sym[i].st_shndx);
-
+			printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON"
+			       "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,
+			       sym[i].st_shndx);
 			// .sbss section
 			break;
 
@@ -632,10 +641,7 @@
 			sym[i].st_value += secbase;
 			break;
 		}
-
 	}
-
-	return ret;
 }
 
 #ifdef DEBUG_ELFLOADER
@@ -655,9 +661,26 @@
 
 static void dump_tc(struct tc *t)
 {
-	printk(KERN_WARNING "VPE: TC index %d TCStatus 0x%lx halt 0x%lx\n",
-	       t->index, read_tc_c0_tcstatus(), read_tc_c0_tchalt());
-	printk(KERN_WARNING "VPE: tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+  	unsigned long val;
+
+  	settc(t->index);
+ 	printk(KERN_DEBUG "VPE loader: TC index %d targtc %ld "
+ 	       "TCStatus 0x%lx halt 0x%lx\n",
+  	       t->index, read_c0_vpecontrol() & VPECONTROL_TARGTC,
+  	       read_tc_c0_tcstatus(), read_tc_c0_tchalt());
+
+ 	printk(KERN_DEBUG " tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+ 	printk(KERN_DEBUG " tcbind 0x%lx\n", read_tc_c0_tcbind());
+
+  	val = read_c0_vpeconf0();
+ 	printk(KERN_DEBUG " VPEConf0 0x%lx MVP %ld\n", val,
+  	       (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+
+ 	printk(KERN_DEBUG " c0 status 0x%lx\n", read_vpe_c0_status());
+ 	printk(KERN_DEBUG " c0 cause 0x%lx\n", read_vpe_c0_cause());
+
+ 	printk(KERN_DEBUG " c0 badvaddr 0x%lx\n", read_vpe_c0_badvaddr());
+ 	printk(KERN_DEBUG " c0 epc 0x%lx\n", read_vpe_c0_epc());
 }
 
 static void dump_tclist(void)
@@ -672,96 +695,108 @@
 /* We are prepared so configure and start the VPE... */
 int vpe_run(struct vpe * v)
 {
-	unsigned long val;
+	struct vpe_notifications *n;
+	unsigned long val, dmt_flag;
 	struct tc *t;
 
 	/* check we are the Master VPE */
 	val = read_c0_vpeconf0();
 	if (!(val & VPECONF0_MVP)) {
 		printk(KERN_WARNING
-		       "VPE: only Master VPE's are allowed to configure MT\n");
+		       "VPE loader: only Master VPE's are allowed to configure MT\n");
 		return -1;
 	}
 
 	/* disable MT (using dvpe) */
 	dvpe();
 
+	if (!list_empty(&v->tc)) {
+                if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+                        printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+                               t->index);
+                        return -ENOEXEC;
+                }
+        } else {
+                printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+                       v->minor);
+                return -ENOEXEC;
+        }
+
 	/* Put MVPE's into 'configuration state' */
 	set_c0_mvpcontrol(MVPCONTROL_VPC);
 
-	if (!list_empty(&v->tc)) {
-		if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
-			printk(KERN_WARNING "VPE: TC %d is already in use.\n",
-			       t->index);
-			return -ENOEXEC;
-		}
-	} else {
-		printk(KERN_WARNING "VPE: No TC's associated with VPE %d\n",
-		       v->minor);
-		return -ENOEXEC;
-	}
-
 	settc(t->index);
 
-	val = read_vpe_c0_vpeconf0();
-
 	/* should check it is halted, and not activated */
 	if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
-		printk(KERN_WARNING "VPE: TC %d is already doing something!\n",
+		printk(KERN_WARNING "VPE loader: TC %d is already doing something!\n",
 		       t->index);
-
 		dump_tclist();
 		return -ENOEXEC;
 	}
 
+	/*
+	 * Disable multi-threaded execution whilst we activate, clear the
+	 * halt bit and bound the tc to the other VPE...
+	 */
+	dmt_flag = dmt();
+
 	/* Write the address we want it to start running from in the TCPC register. */
 	write_tc_c0_tcrestart((unsigned long)v->__start);
-
-	/* write the sivc_info address to tccontext */
 	write_tc_c0_tccontext((unsigned long)0);
-
-	/* Set up the XTC bit in vpeconf0 to point at our tc */
-	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (t->index << VPECONF0_XTC_SHIFT));
-
-	/* mark the TC as activated, not interrupt exempt and not dynamically allocatable */
+	/*
+	 * Mark the TC as activated, not interrupt exempt and not dynamically
+	 * allocatable
+	 */
 	val = read_tc_c0_tcstatus();
 	val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
 	write_tc_c0_tcstatus(val);
 
 	write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
 
-	/* set up VPE1 */
-	write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);	// no multiple TC's
-	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);	// enable this VPE
-
 	/*
 	 * The sde-kit passes 'memsize' to __start in $a3, so set something
-	 * here...
-	 * Or set $a3 (register 7) to zero and define DFLT_STACK_SIZE and
+	 * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
 	 * DFLT_HEAP_SIZE when you compile your program
 	 */
+ 	mttgpr(7, physical_memsize);
 
-	mttgpr(7, 0);
 
-	/* set config to be the same as vpe0, particularly kseg0 coherency alg */
-	write_vpe_c0_config(read_c0_config());
+	/* set up VPE1 */
+	/*
+	 * bind the TC to VPE 1 as late as possible so we only have the final
+	 * VPE registers to set up, and so an EJTAG probe can trigger on it
+	 */
+ 	write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
+
+        /* Set up the XTC bit in vpeconf0 to point at our tc */
+        write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+                               | (t->index << VPECONF0_XTC_SHIFT));
+
+        /* enable this VPE */
+        write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
 	/* clear out any left overs from a previous program */
+	write_vpe_c0_status(0);
 	write_vpe_c0_cause(0);
 
 	/* take system out of configuration state */
 	clear_c0_mvpcontrol(MVPCONTROL_VPC);
 
-	/* clear interrupts enabled IE, ERL, EXL, and KSU from c0 status */
-	write_vpe_c0_status(read_vpe_c0_status() & ~(ST0_ERL | ST0_KSU | ST0_IE | ST0_EXL));
+	/* now safe to re-enable multi-threading */
+	emt(dmt_flag);
 
 	/* set it running */
 	evpe(EVPE_ENABLE);
 
+	list_for_each_entry(n, &v->notify, list) {
+		n->start(v->minor);
+	}
+
 	return 0;
 }
 
-static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
 				      unsigned int symindex, const char *strtab,
 				      struct module *mod)
 {
@@ -778,26 +813,28 @@
 		}
 	}
 
+	if ( (v->__start == 0) || (v->shared_ptr == NULL))
+		return -1;
+
 	return 0;
 }
 
 /*
- * Allocates a VPE with some program code space(the load address), copies
- * the contents of the program (p)buffer performing relocatations/etc,
- * free's it when finished.
-*/
+ * Allocates a VPE with some program code space(the load address), copies the
+ * contents of the program (p)buffer performing relocatations/etc, free's it
+ * when finished.
+ */
 int vpe_elfload(struct vpe * v)
 {
 	Elf_Ehdr *hdr;
 	Elf_Shdr *sechdrs;
 	long err = 0;
 	char *secstrings, *strtab = NULL;
-	unsigned int len, i, symindex = 0, strindex = 0;
-
+	unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
 	struct module mod;	// so we can re-use the relocations code
 
 	memset(&mod, 0, sizeof(struct module));
-	strcpy(mod.name, "VPE dummy prog module");
+	strcpy(mod.name, "VPE loader");
 
 	hdr = (Elf_Ehdr *) v->pbuffer;
 	len = v->plen;
@@ -805,16 +842,22 @@
 	/* Sanity checks against insmoding binaries or wrong arch,
 	   weird elf version */
 	if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
-	    || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+	    || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
+	    || !elf_check_arch(hdr)
 	    || hdr->e_shentsize != sizeof(*sechdrs)) {
 		printk(KERN_WARNING
-		       "VPE program, wrong arch or weird elf version\n");
+		       "VPE loader: program wrong arch or weird elf version\n");
 
 		return -ENOEXEC;
 	}
 
+	if (hdr->e_type == ET_REL)
+		relocate = 1;
+
 	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
-		printk(KERN_ERR "VPE program length %u truncated\n", len);
+		printk(KERN_ERR "VPE loader: program length %u truncated\n",
+		       len);
+
 		return -ENOEXEC;
 	}
 
@@ -826,82 +869,126 @@
 	/* And these should exist, but gcc whinges if we don't init them */
 	symindex = strindex = 0;
 
-	for (i = 1; i < hdr->e_shnum; i++) {
+	if (relocate) {
+		for (i = 1; i < hdr->e_shnum; i++) {
+			if (sechdrs[i].sh_type != SHT_NOBITS
+			    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
+				printk(KERN_ERR "VPE program length %u truncated\n",
+				       len);
+				return -ENOEXEC;
+			}
 
-		if (sechdrs[i].sh_type != SHT_NOBITS
-		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
-			printk(KERN_ERR "VPE program length %u truncated\n",
-			       len);
-			return -ENOEXEC;
+			/* Mark all sections sh_addr with their address in the
+			   temporary image. */
+			sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+
+			/* Internal symbols and strings. */
+			if (sechdrs[i].sh_type == SHT_SYMTAB) {
+				symindex = i;
+				strindex = sechdrs[i].sh_link;
+				strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+			}
 		}
-
-		/* Mark all sections sh_addr with their address in the
-		   temporary image. */
-		sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
-
-		/* Internal symbols and strings. */
-		if (sechdrs[i].sh_type == SHT_SYMTAB) {
-			symindex = i;
-			strindex = sechdrs[i].sh_link;
-			strtab = (char *)hdr + sechdrs[strindex].sh_offset;
-		}
+		layout_sections(&mod, hdr, sechdrs, secstrings);
 	}
 
-	layout_sections(&mod, hdr, sechdrs, secstrings);
-
 	v->load_addr = alloc_progmem(mod.core_size);
 	memset(v->load_addr, 0, mod.core_size);
 
-	printk("VPE elf_loader: loading to %p\n", v->load_addr);
+	printk("VPE loader: loading to %p\n", v->load_addr);
 
-	for (i = 0; i < hdr->e_shnum; i++) {
-		void *dest;
+	if (relocate) {
+		for (i = 0; i < hdr->e_shnum; i++) {
+			void *dest;
 
-		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
-			continue;
+			if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+				continue;
 
-		dest = v->load_addr + sechdrs[i].sh_entsize;
+			dest = v->load_addr + sechdrs[i].sh_entsize;
 
-		if (sechdrs[i].sh_type != SHT_NOBITS)
-			memcpy(dest, (void *)sechdrs[i].sh_addr,
-			       sechdrs[i].sh_size);
-		/* Update sh_addr to point to copy in image. */
-		sechdrs[i].sh_addr = (unsigned long)dest;
-	}
+			if (sechdrs[i].sh_type != SHT_NOBITS)
+				memcpy(dest, (void *)sechdrs[i].sh_addr,
+				       sechdrs[i].sh_size);
+			/* Update sh_addr to point to copy in image. */
+			sechdrs[i].sh_addr = (unsigned long)dest;
 
-	/* Fix up syms, so that st_value is a pointer to location. */
-	err =
-		simplify_symbols(sechdrs, symindex, strtab, secstrings,
-				 hdr->e_shnum, &mod);
-	if (err < 0) {
-		printk(KERN_WARNING "VPE: unable to simplify symbols\n");
-		goto cleanup;
-	}
+			printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
+			       secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
+		}
 
-	/* Now do relocations. */
-	for (i = 1; i < hdr->e_shnum; i++) {
-		const char *strtab = (char *)sechdrs[strindex].sh_addr;
-		unsigned int info = sechdrs[i].sh_info;
+ 		/* Fix up syms, so that st_value is a pointer to location. */
+ 		simplify_symbols(sechdrs, symindex, strtab, secstrings,
+ 				 hdr->e_shnum, &mod);
 
-		/* Not a valid relocation section? */
-		if (info >= hdr->e_shnum)
-			continue;
+ 		/* Now do relocations. */
+ 		for (i = 1; i < hdr->e_shnum; i++) {
+ 			const char *strtab = (char *)sechdrs[strindex].sh_addr;
+ 			unsigned int info = sechdrs[i].sh_info;
 
-		/* Don't bother with non-allocated sections */
-		if (!(sechdrs[info].sh_flags & SHF_ALLOC))
-			continue;
+ 			/* Not a valid relocation section? */
+ 			if (info >= hdr->e_shnum)
+ 				continue;
 
-		if (sechdrs[i].sh_type == SHT_REL)
-			err =
-				apply_relocations(sechdrs, strtab, symindex, i, &mod);
-		else if (sechdrs[i].sh_type == SHT_RELA)
-			err = apply_relocate_add(sechdrs, strtab, symindex, i,
-						 &mod);
-		if (err < 0) {
-			printk(KERN_WARNING
-			       "vpe_elfload: error in relocations err %ld\n",
-			       err);
-			goto cleanup;
+ 			/* Don't bother with non-allocated sections */
+ 			if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+ 				continue;
+
+ 			if (sechdrs[i].sh_type == SHT_REL)
+ 				err = apply_relocations(sechdrs, strtab, symindex, i,
+ 							&mod);
+ 			else if (sechdrs[i].sh_type == SHT_RELA)
+ 				err = apply_relocate_add(sechdrs, strtab, symindex, i,
+ 							 &mod);
+ 			if (err < 0)
+ 				return err;
+
+  		}
+  	} else {
+  		for (i = 0; i < hdr->e_shnum; i++) {
+
+ 			/* Internal symbols and strings. */
+ 			if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ 				symindex = i;
+ 				strindex = sechdrs[i].sh_link;
+ 				strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+
+ 				/* mark the symtab's address for when we try to find the
+ 				   magic symbols */
+ 				sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+ 			}
+
+ 			/* filter sections we dont want in the final image */
+ 			if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
+ 			    (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
+ 				printk( KERN_DEBUG " ignoring section, "
+ 					"name %s type %x address 0x%x \n",
+ 					secstrings + sechdrs[i].sh_name,
+ 					sechdrs[i].sh_type, sechdrs[i].sh_addr);
+ 				continue;
+ 			}
+
+  			if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
+ 				printk( KERN_WARNING "VPE loader: "
+ 					"fully linked image has invalid section, "
+ 					"name %s type %x address 0x%x, before load "
+ 					"address of 0x%x\n",
+ 					secstrings + sechdrs[i].sh_name,
+ 					sechdrs[i].sh_type, sechdrs[i].sh_addr,
+ 					(unsigned int)v->load_addr);
+  				return -ENOEXEC;
+  			}
+
+ 			printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "
+			       "size 0x%x0 from x%p\n",
+			       secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,
+			       sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
+
+  			if (sechdrs[i].sh_type != SHT_NOBITS)
+				memcpy((void *)sechdrs[i].sh_addr,
+				       (char *)hdr + sechdrs[i].sh_offset,
+ 				       sechdrs[i].sh_size);
+			else
+				memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);
 		}
 	}
 
@@ -910,71 +997,104 @@
 			   (unsigned long)v->load_addr + v->len);
 
 	if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+		if (v->__start == 0) {
+			printk(KERN_WARNING "VPE loader: program does not contain "
+			       "a __start symbol\n");
+			return -ENOEXEC;
+		}
 
-		printk(KERN_WARNING
-		       "VPE: program doesn't contain __start or vpe_shared symbols\n");
-		err = -ENOEXEC;
+		if (v->shared_ptr == NULL)
+			printk(KERN_WARNING "VPE loader: "
+			       "program does not contain vpe_shared symbol.\n"
+			       " Unable to use AMVP (AP/SP) facilities.\n");
 	}
 
 	printk(" elf loaded\n");
-
-cleanup:
-	return err;
+	return 0;
 }
 
-static void dump_vpe(struct vpe * v)
+__attribute_used__ void dump_vpe(struct vpe * v)
 {
 	struct tc *t;
 
+	settc(v->minor);
+
 	printk(KERN_DEBUG "VPEControl 0x%lx\n", read_vpe_c0_vpecontrol());
 	printk(KERN_DEBUG "VPEConf0 0x%lx\n", read_vpe_c0_vpeconf0());
 
-	list_for_each_entry(t, &vpecontrol.tc_list, list) {
+	list_for_each_entry(t, &vpecontrol.tc_list, list)
 		dump_tc(t);
-	}
 }
 
-/* checks for VPE is unused and gets ready to load program	 */
+static void cleanup_tc(struct tc *tc)
+{
+	int tmp;
+
+	/* Put MVPE's into 'configuration state' */
+	set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+	settc(tc->index);
+	tmp = read_tc_c0_tcstatus();
+
+	/* mark not allocated and not dynamically allocatable */
+	tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+	tmp |= TCSTATUS_IXMT;	/* interrupt exempt */
+	write_tc_c0_tcstatus(tmp);
+
+	write_tc_c0_tchalt(TCHALT_H);
+
+	/* bind it to anything other than VPE1 */
+	write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
+
+	clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+static int getcwd(char *buff, int size)
+{
+	mm_segment_t old_fs;
+	int ret;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	ret = sys_getcwd(buff,size);
+
+	set_fs(old_fs);
+
+	return ret;
+}
+
+/* checks VPE is unused and gets ready to load program  */
 static int vpe_open(struct inode *inode, struct file *filp)
 {
-	int minor;
+	int minor, ret;
 	struct vpe *v;
+	struct vpe_notifications *not;
 
 	/* assume only 1 device at the mo. */
-	if ((minor = MINOR(inode->i_rdev)) != 1) {
-		printk(KERN_WARNING "VPE: only vpe1 is supported\n");
+	if ((minor = iminor(inode)) != 1) {
+		printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
 		return -ENODEV;
 	}
 
 	if ((v = get_vpe(minor)) == NULL) {
-		printk(KERN_WARNING "VPE: unable to get vpe\n");
+		printk(KERN_WARNING "VPE loader: unable to get vpe\n");
 		return -ENODEV;
 	}
 
 	if (v->state != VPE_STATE_UNUSED) {
-		unsigned long tmp;
-		struct tc *t;
-
-		printk(KERN_WARNING "VPE: device %d already in use\n", minor);
-
 		dvpe();
-		dump_vpe(v);
 
-		printk(KERN_WARNING "VPE: re-initialising %d\n", minor);
+		printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
+
+		dump_tc(get_tc(minor));
+
+		list_for_each_entry(not, &v->notify, list) {
+			not->stop(minor);
+		}
 
 		release_progmem(v->load_addr);
-
-		t = get_tc(minor);
-		settc(minor);
-		tmp = read_tc_c0_tcstatus();
-
-		/* mark not allocated and not dynamically allocatable */
-		tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
-		tmp |= TCSTATUS_IXMT;	/* interrupt exempt */
-		write_tc_c0_tcstatus(tmp);
-
-		write_tc_c0_tchalt(TCHALT_H);
-
+		cleanup_tc(get_tc(minor));
 	}
 
 	// allocate it so when we get write ops we know it's expected.
@@ -986,6 +1106,24 @@
 	v->load_addr = NULL;
 	v->len = 0;
 
+	v->uid = filp->f_uid;
+	v->gid = filp->f_gid;
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+	/* get kspd to tell us when a syscall_exit happens */
+	if (!kspd_events_reqd) {
+		kspd_notify(&kspd_events);
+		kspd_events_reqd++;
+	}
+#endif
+
+	v->cwd[0] = 0;
+	ret = getcwd(v->cwd, VPE_PATH_MAX);
+	if (ret < 0)
+		printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret);
+
+	v->shared_ptr = NULL;
+	v->__start = 0;
 	return 0;
 }
 
@@ -995,7 +1133,7 @@
 	struct vpe *v;
 	Elf_Ehdr *hdr;
 
-	minor = MINOR(inode->i_rdev);
+	minor = iminor(inode);
 	if ((v = get_vpe(minor)) == NULL)
 		return -ENODEV;
 
@@ -1006,14 +1144,22 @@
 		if (vpe_elfload(v) >= 0)
 			vpe_run(v);
 		else {
-			printk(KERN_WARNING "VPE: ELF load failed.\n");
+ 			printk(KERN_WARNING "VPE loader: ELF load failed.\n");
 			ret = -ENOEXEC;
 		}
 	} else {
-		printk(KERN_WARNING "VPE: only elf files are supported\n");
+ 		printk(KERN_WARNING "VPE loader: only elf files are supported\n");
 		ret = -ENOEXEC;
 	}
 
+	/* It's good to be able to run the SP and if it chokes have a look at
+	   the /dev/rt?. But if we reset the pointer to the shared struct we
+	   loose what has happened. So perhaps if garbage is sent to the vpe
+	   device, use it as a trigger for the reset. Hopefully a nice
+	   executable will be along shortly. */
+	if (ret < 0)
+		v->shared_ptr = NULL;
+
 	// cleanup any temp buffers
 	if (v->pbuffer)
 		vfree(v->pbuffer);
@@ -1028,26 +1174,24 @@
 	size_t ret = count;
 	struct vpe *v;
 
-	minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	minor = iminor(file->f_dentry->d_inode);
 	if ((v = get_vpe(minor)) == NULL)
 		return -ENODEV;
 
 	if (v->pbuffer == NULL) {
-		printk(KERN_ERR "vpe_write: no pbuffer\n");
+		printk(KERN_ERR "VPE loader: no buffer for program\n");
 		return -ENOMEM;
 	}
 
 	if ((count + v->len) > v->plen) {
 		printk(KERN_WARNING
-		       "VPE Loader: elf size too big. Perhaps strip uneeded symbols\n");
+		       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
 		return -ENOMEM;
 	}
 
 	count -= copy_from_user(v->pbuffer + v->len, buffer, count);
-	if (!count) {
-		printk("vpe_write: copy_to_user failed\n");
+	if (!count)
 		return -EFAULT;
-	}
 
 	v->len += count;
 	return ret;
@@ -1149,16 +1293,70 @@
 {
 	struct vpe *v;
 
-	if ((v = get_vpe(index)) == NULL) {
-		printk(KERN_WARNING "vpe: invalid vpe index %d\n", index);
+	if ((v = get_vpe(index)) == NULL)
 		return NULL;
-	}
 
 	return v->shared_ptr;
 }
 
 EXPORT_SYMBOL(vpe_get_shared);
 
+int vpe_getuid(int index)
+{
+	struct vpe *v;
+
+	if ((v = get_vpe(index)) == NULL)
+		return -1;
+
+	return v->uid;
+}
+
+EXPORT_SYMBOL(vpe_getuid);
+
+int vpe_getgid(int index)
+{
+	struct vpe *v;
+
+	if ((v = get_vpe(index)) == NULL)
+		return -1;
+
+	return v->gid;
+}
+
+EXPORT_SYMBOL(vpe_getgid);
+
+int vpe_notify(int index, struct vpe_notifications *notify)
+{
+	struct vpe *v;
+
+	if ((v = get_vpe(index)) == NULL)
+		return -1;
+
+	list_add(&notify->list, &v->notify);
+	return 0;
+}
+
+EXPORT_SYMBOL(vpe_notify);
+
+char *vpe_getcwd(int index)
+{
+	struct vpe *v;
+
+	if ((v = get_vpe(index)) == NULL)
+		return NULL;
+
+	return v->cwd;
+}
+
+EXPORT_SYMBOL(vpe_getcwd);
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+static void kspd_sp_exit( int sp_id)
+{
+	cleanup_tc(get_tc(sp_id));
+}
+#endif
+
 static int __init vpe_module_init(void)
 {
 	struct vpe *v = NULL;
@@ -1201,7 +1399,8 @@
 				return -ENODEV;
 			}
 
-			list_add(&t->tc, &v->tc);	/* add the tc to the list of this vpe's tc's. */
+			/* add the tc to the list of this vpe's tc's. */
+			list_add(&t->tc, &v->tc);
 
 			/* deactivate all but vpe0 */
 			if (i != 0) {
@@ -1222,10 +1421,12 @@
 						     ~(ST0_IM | ST0_IE | ST0_KSU))
 						    | ST0_CU0);
 
-				/* set config to be the same as vpe0, particularly kseg0 coherency alg */
+				/*
+				 * Set config to be the same as vpe0,
+				 * particularly kseg0 coherency alg
+				 */
 				write_vpe_c0_config(read_c0_config());
 			}
-
 		}
 
 		/* TC's */
@@ -1234,23 +1435,28 @@
 		if (i != 0) {
 			unsigned long tmp;
 
-			/* tc 0 will of course be running.... */
-			if (i == 0)
-				t->state = TC_STATE_RUNNING;
-
 			settc(i);
 
-			/* bind a TC to each VPE, May as well put all excess TC's
-			   on the last VPE */
-			if (i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1))
-				write_tc_c0_tcbind(read_tc_c0_tcbind() |
-						   ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
-			else
-				write_tc_c0_tcbind(read_tc_c0_tcbind() | i);
+			/* Any TC that is bound to VPE0 gets left as is - in case
+			   we are running SMTC on VPE0. A TC that is bound to any
+			   other VPE gets bound to VPE0, ideally I'd like to make
+			   it homeless but it doesn't appear to let me bind a TC
+			   to a non-existent VPE. Which is perfectly reasonable.
+
+			   The (un)bound state is visible to an EJTAG probe so may
+			   notify GDB...
+			*/
+
+			if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) {
+				/* tc is bound >vpe0 */
+				write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
+
+				t->pvpe = get_vpe(0);	/* set the parent vpe */
+			}
 
 			tmp = read_tc_c0_tcstatus();
 
-			/* mark not allocated and not dynamically allocatable */
+			/* mark not activated and not dynamically allocatable */
 			tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
 			tmp |= TCSTATUS_IXMT;	/* interrupt exempt */
 			write_tc_c0_tcstatus(tmp);
@@ -1262,6 +1468,9 @@
 	/* release config state */
 	clear_c0_mvpcontrol(MVPCONTROL_VPC);
 
+#ifdef CONFIG_MIPS_APSP_KSPD
+	kspd_events.kspd_sp_exit = kspd_sp_exit;
+#endif
 	return 0;
 }
 
@@ -1281,5 +1490,5 @@
 module_init(vpe_module_init);
 module_exit(vpe_module_exit);
 MODULE_DESCRIPTION("MIPS VPE Loader");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
 MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
index 0d5aec4..99f5046 100644
--- a/arch/mips/lasat/Makefile
+++ b/arch/mips/lasat/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y	 			+= reset.o setup.o prom.o lasat_board.o \
-				   at93c.o interrupt.o lasatIRQ.o
+				   at93c.o interrupt.o
 
 obj-$(CONFIG_LASAT_SYSCTL)	+= sysctl.o
 obj-$(CONFIG_DS1603)		+= ds1603.o
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
index 852a419..2d3472b 100644
--- a/arch/mips/lasat/interrupt.c
+++ b/arch/mips/lasat/interrupt.c
@@ -27,14 +27,13 @@
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/lasat/lasatint.h>
+#include <asm/time.h>
 #include <asm/gdb-stub.h>
 
 static volatile int *lasat_int_status = NULL;
 static volatile int *lasat_int_mask = NULL;
 static volatile int lasat_int_mask_shift;
 
-extern asmlinkage void lasatIRQ(void);
-
 void disable_lasat_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
@@ -109,11 +108,17 @@
 	return int_status;
 }
 
-void lasat_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned long int_status;
+	unsigned int cause = read_c0_cause();
 	int irq;
 
+	if (cause & CAUSEF_IP7) {	/* R4000 count / compare IRQ */
+		ll_timer_interrupt(7, regs);
+		return;
+	}
+
 	int_status = get_int_status();
 
 	/* if int_status == 0, then the interrupt has already been cleared */
@@ -147,9 +152,6 @@
 		panic("arch_init_irq: mips_machtype incorrect");
 	}
 
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, lasatIRQ);
-
 	for (i = 0; i <= LASATINT_END; i++) {
 		irq_desc[i].status	= IRQ_DISABLED;
 		irq_desc[i].action	= 0;
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
deleted file mode 100644
index 2a2b0d0..0000000
--- a/arch/mips/lasat/lasatIRQ.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Interrupt exception dispatch code.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set	noreorder
-	.align	5
-	NESTED(lasatIRQ, PT_SIZE, sp)
-	.set	noat
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
-
-	/* Wheee, a timer interrupt. */
-	li	a0, 7
-	jal	ll_timer_interrupt
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-1:
-	/* Wheee, combined hardware level zero interrupt. */
-	jal	lasat_hw0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	/*
-	 * Here by mistake?  This is possible, what can happen is that by the
-	 * time we take the exception the IRQ pin goes low, so just leave if
-	 * this is the case.
-	 */
-	move	a1,s0
-	mfc0	a1, CP0_EPC
-
-	j	ret_from_irq
-	 nop
-	END(lasatIRQ)
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index bc0ebc6..db53950 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -39,8 +39,6 @@
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
-extern asmlinkage void mipsIRQ(void);
-
 #if 0
 #define DEBUG_INT(x...) printk(x)
 #else
@@ -98,7 +96,7 @@
 	return b;
 }
 
-void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
 {
 	unsigned long int_status;
 	int irq;
@@ -116,6 +114,91 @@
 	do_IRQ(irq, regs);
 }
 
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the Atlas board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq == MIPSCPU_INT_ATLAS)
+		atlas_hw0_irqdispatch(regs);
+	else if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	int i;
@@ -128,9 +211,6 @@
 	 */
 	atlas_hw0_icregs->intrsten = 0xffffffff;
 
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, mipsIRQ);
-
 	for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
 		irq_desc[i].status	= IRQ_DISABLED;
 		irq_desc[i].action	= 0;
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
index b21bc68..be47c1c 100644
--- a/arch/mips/mips-boards/generic/Makefile
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -18,8 +18,8 @@
 # Makefile for the MIPS boards generic routines under Linux.
 #
 
-obj-y				:= mipsIRQ.o reset.o display.o init.o memory.o \
-				   printf.o cmdline.o time.o
+obj-y				:= reset.o display.o init.o memory.o printf.o \
+				   cmdline.o time.o
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_KGDB)		+= gdb_hook.o
 
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
index 91a2ccb..6a1854d 100644
--- a/arch/mips/mips-boards/generic/gdb_hook.c
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -25,7 +25,7 @@
 #include <asm/serial.h>
 #include <asm/io.h>
 
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
+static struct serial_state rs_table[] = {
 	SERIAL_PORT_DFNS	/* Defined in serial.h */
 };
 
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index eab5a70..df4e947 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -220,7 +220,6 @@
 				generic_putDebugChar (*s++);
 		}
 
-		kgdb_enabled = 1;
 		/* Breakpoint is invoked after interrupts are initialised */
 	}
 }
@@ -338,6 +337,7 @@
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
 	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_24K:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 		_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
 
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index 32c9210..bc4d093 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,10 +22,12 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/pfn.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 
 #include <asm/mips-boards/prom.h>
 
@@ -46,9 +48,6 @@
 };
 #endif
 
-/* References to section boundaries */
-extern char _end;
-
 struct prom_pmemblock * __init prom_getmdesc(void)
 {
 	char *memsize_str;
@@ -106,10 +105,10 @@
 
 	mdesc[3].type = yamon_dontuse;
 	mdesc[3].base = 0x00100000;
-	mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
+	mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base;
 
 	mdesc[4].type = yamon_free;
-	mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
+	mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
 	mdesc[4].size = memsize - mdesc[4].base;
 
 	return &mdesc[0];
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
deleted file mode 100644
index ddd5c73..0000000
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlasint.h>
-#define CASCADE_IRQ		MIPSCPU_INT_ATLAS
-#define CASCADE_DISPATCH	atlas_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/maltaint.h>
-#define CASCADE_IRQ		MIPSCPU_INT_I8259A
-#define CASCADE_DISPATCH	malta_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/seadint.h>
-#endif
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
- *             3        Hardware (ignored)
- *             4        Hardware (ignored)
- *             5        Hardware (ignored)
- *             6        Hardware (ignored)
- *             7        R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- *       wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(mipsIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-
-	mfc0	s0, CP0_CAUSE		# get irq bits
-	mfc0	s1, CP0_STATUS		# get irq mask
-	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
-	and	s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-	.set	mips32
-	clz	a0, s0
-	.set	mips0
-	negu	a0
-	addu	a0, 31-CAUSEB_IP
-	bltz	a0, spurious
-#else
-	beqz	s0, spurious
-	 li	a0, 7
-
-	and	t0, s0, 0xf000
-	sltiu	t0, t0, 1
-	sll	t0, 2
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0xc000
-	sltiu	t0, t0, 1
-	sll	t0, 1
-	subu	a0, t0
-	sll	s0, t0
-
-	and	t0, s0, 0x8000
-	sltiu	t0, t0, 1
-	# sll	t0, 0
-	subu	a0, t0
-	# sll	s0, t0
-#endif
-
-#ifdef CASCADE_IRQ
-	 li	a1, CASCADE_IRQ
-	bne	a0, a1, 1f
-	 addu	a0, MIPSCPU_INT_BASE
-
-	jal	CASCADE_DISPATCH
-	 move	 a0, sp
-
-	j	ret_from_irq
-	 nop
-1:
-#else
-	 addu	a0, MIPSCPU_INT_BASE
-#endif
-
-	jal	do_IRQ
-	 move	a1, sp
-
-	j	ret_from_irq
-	 nop
-
-
-spurious:
-	j	spurious_interrupt
-	 nop
-	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index 1f6f9df..9337f6c 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -198,6 +198,7 @@
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
 	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_24K:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 		/* Set up resource ranges from the controller's registers.  */
 		MSC_READ(MSC01_PCI_SC2PMBASL, start);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 93f3bf2..a9f6124 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -30,6 +30,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/irq.h>
@@ -50,16 +51,23 @@
 static char display_string[] = "        LINUX ON ATLAS       ";
 #endif
 #if defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MIPS_MT_SMTC)
+static char display_string[] = "       SMTC LINUX ON MALTA       ";
+#else
 static char display_string[] = "        LINUX ON MALTA       ";
+#endif /* CONFIG_MIPS_MT_SMTC */
 #endif
 #if defined(CONFIG_MIPS_SEAD)
 static char display_string[] = "        LINUX ON SEAD       ";
 #endif
-static unsigned int display_count = 0;
+static unsigned int display_count;
 #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
 
-static unsigned int timer_tick_count=0;
+#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
+
+static unsigned int timer_tick_count;
 static int mips_cpu_timer_irq;
+extern void smtc_timer_broadcast(int);
 
 static inline void scroll_display_message(void)
 {
@@ -75,15 +83,55 @@
 	do_IRQ (mips_cpu_timer_irq, regs);
 }
 
+/*
+ * Redeclare until I get around mopping the timer code insanity on MIPS.
+ */
 extern int null_perf_irq(struct pt_regs *regs);
 
 extern int (*perf_irq)(struct pt_regs *regs);
 
 irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	int r2 = cpu_has_mips_r2;
 	int cpu = smp_processor_id();
+	int r2 = cpu_has_mips_r2;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+        /*
+	 *  In an SMTC system, one Count/Compare set exists per VPE.
+	 *  Which TC within a VPE gets the interrupt is essentially
+	 *  random - we only know that it shouldn't be one with
+	 *  IXMT set. Whichever TC gets the interrupt needs to
+	 *  send special interprocessor interrupts to the other
+	 *  TCs to make sure that they schedule, etc.
+	 *
+	 *  That code is specific to the SMTC kernel, not to
+	 *  the a particular platform, so it's invoked from
+	 *  the general MIPS timer_interrupt routine.
+	 */
+
+	/*
+	 * DVPE is necessary so long as cross-VPE interrupts
+	 * are done via read-modify-write of Cause register.
+	 */
+	int vpflags = dvpe();
+	write_c0_compare (read_c0_count() - 1);
+	clear_c0_cause(CPUCTR_IMASKBIT);
+	evpe(vpflags);
+
+	if (cpu_data[cpu].vpe_id == 0) {
+		timer_interrupt(irq, dev_id, regs);
+		scroll_display_message();
+	} else
+		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+
+	if (cpu != 0)
+		/*
+		 * Other CPUs should do profiling and process accounting
+		 */
+		local_timer_interrupt(irq, dev_id, regs);
+
+#else /* CONFIG_MIPS_MT_SMTC */
 	if (cpu == 0) {
 		/*
 		 * CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@
 		 * More support needs to be added to kernel/time for
 		 * counter/timer interrupts on multiple CPU's
 		 */
-		write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+		write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+
 		/*
-		 * other CPUs should do profiling and process accounting
+		 * Other CPUs should do profiling and process accounting
 		 */
-		local_timer_interrupt (irq, dev_id, regs);
+		local_timer_interrupt(irq, dev_id, regs);
 	}
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 out:
 	return IRQ_HANDLED;
@@ -126,7 +176,7 @@
 	unsigned int prid = read_c0_prid() & 0xffff00;
 	unsigned int count;
 
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
 	/*
 	 * The SEAD board doesn't have a real time clock, so we can't
 	 * really calculate the timer frequency
@@ -211,7 +261,11 @@
 
 	/* we are using the cpu counter for timer interrupts */
 	irq->handler = mips_timer_interrupt;	/* we use our own handler */
+#ifdef CONFIG_MIPS_MT_SMTC
+	setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+#else
 	setup_irq(mips_cpu_timer_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #ifdef CONFIG_SMP
 	/* irq_desc(riptor) is a global resource, when the interrupt overlaps
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index fd4c143..77ee5c6 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -20,3 +20,4 @@
 #
 
 obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_SMP) += malta_smp.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index d06dc5ad..7cc0ba4 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -40,7 +40,6 @@
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/msc01_ic.h>
 
-extern asmlinkage void mipsIRQ(void);
 extern void mips_timer_interrupt(void);
 
 static DEFINE_SPINLOCK(mips_irq_lock);
@@ -58,6 +57,7 @@
 	case MIPS_REVISION_CORID_CORE_MSC:
 	case MIPS_REVISION_CORID_CORE_FPGA2:
 	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_24K:
 	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 	        MSC_READ(MSC01_PCI_IACK, irq);
 		irq &= 0xff;
@@ -114,13 +114,14 @@
 	return irq;
 }
 
-void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(struct pt_regs *regs)
 {
 	int irq;
 
 	irq = get_int();
-	if (irq < 0)
+	if (irq < 0) {
 		return;  /* interrupt has already been cleared */
+	}
 
 	do_IRQ(MALTA_INT_BASE+irq, regs);
 }
@@ -143,6 +144,7 @@
         case MIPS_REVISION_CORID_CORE_MSC:
         case MIPS_REVISION_CORID_CORE_FPGA2:
         case MIPS_REVISION_CORID_CORE_FPGA3:
+        case MIPS_REVISION_CORID_CORE_24K:
         case MIPS_REVISION_CORID_CORE_EMUL_MSC:
                 ll_msc_irq(regs);
                 break;
@@ -182,6 +184,92 @@
         die("CoreHi interrupt", regs);
 }
 
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the Malta board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq == MIPSCPU_INT_I8259A)
+		malta_hw0_irqdispatch(regs);
+	else if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 static struct irqaction i8259irq = {
 	.handler = no_action,
 	.name = "XT-PIC cascade"
@@ -214,7 +302,6 @@
 
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, mipsIRQ);
 	init_i8259_irqs();
 
 	if (!cpu_has_veic)
@@ -224,6 +311,7 @@
         case MIPS_REVISION_CORID_CORE_MSC:
         case MIPS_REVISION_CORID_CORE_FPGA2:
         case MIPS_REVISION_CORID_CORE_FPGA3:
+        case MIPS_REVISION_CORID_CORE_24K:
         case MIPS_REVISION_CORID_CORE_EMUL_MSC:
 		if (cpu_has_veic)
 			init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
@@ -240,12 +328,17 @@
 	else if (cpu_has_vint) {
 		set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
 		set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+		setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
+			(0x100 << MIPSCPU_INT_I8259A));
+		setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
+			&corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
+#else /* Not SMTC */
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+#endif /* CONFIG_MIPS_MT_SMTC */
 	}
 	else {
-		set_except_vector(0, mipsIRQ);
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
 		setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
 	}
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
new file mode 100644
index 0000000..6c6c8ee
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_smp.c
@@ -0,0 +1,128 @@
+/*
+ * Malta Platform-specific hooks for SMP operation
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+	int nextslot;
+
+	/*
+	 * As of November, 2004, MIPSsim only simulates one core
+	 * at a time.  However, that core may be a MIPS MT core
+	 * with multiple virtual processors and thread contexts.
+	 */
+
+	if (read_c0_config3() & (1<<2)) {
+		nextslot = mipsmt_build_cpu_map(1);
+	}
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+        void smtc_init_secondary(void);
+	int myvpe;
+
+	/* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
+	myvpe = read_c0_tcbind() & TCBIND_CURVPE;
+	if (myvpe != 0) {
+		/* Ideally, this should be done only once per VPE, but... */
+		clear_c0_status(STATUSF_IP2);
+		set_c0_status(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP3
+				| STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6
+				| STATUSF_IP7);
+	}
+
+        smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ *
+ * As noted above, we can assume a single CPU for now
+ * but it may be multithreaded.
+ */
+
+void plat_smp_setup(void)
+{
+	if (read_c0_config3() & (1<<2))
+		mipsmt_build_cpu_map(0);
+}
+
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
+	if (read_c0_config3() & (1<<2))
+		mipsmt_prepare_cpus();
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+}
+
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index 90fda0d..9168d93 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -24,16 +24,94 @@
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
 #include <asm/system.h>
 
 #include <asm/mips-boards/seadint.h>
 
-extern asmlinkage void mipsIRQ(void);
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+/*
+ * IRQs on the SEAD board look basically are combined together on hardware
+ * interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        UART0 (hw0)
+ *             3        UART1 (hw1)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq >= 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
 	mips_cpu_irq_init(MIPSCPU_INT_BASE);
-
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, mipsIRQ);
 }
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
deleted file mode 100644
index fef9fbd..0000000
--- a/arch/mips/mips-boards/sim/cmdline.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Kernel command line creation using the prom monitor (YAMON) argc/argv.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-
-extern int prom_argc;
-extern int *_prom_argv;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension.
- */
-#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
-
-char arcs_cmdline[CL_SIZE];
-
-char * __init prom_getcmdline(void)
-{
-	return &(arcs_cmdline[0]);
-}
-
-
-void  __init prom_init_cmdline(void)
-{
-	char *cp;
-	int actr;
-
-	actr = 1; /* Always ignore argv[0] */
-
-	cp = &(arcs_cmdline[0]);
-	while(actr < prom_argc) {
-	        strcpy(cp, prom_argv(actr));
-		cp += strlen(prom_argv(actr));
-		*cp++ = ' ';
-		actr++;
-	}
-	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-		--cp;
-	*cp = '\0';
-}
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
index 9df37c6..c63021a 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -26,8 +26,10 @@
 	return arcs_cmdline;
 }
 
-
 void  __init prom_init_cmdline(void)
 {
-    /* nothing to do */
+	char *cp;
+	cp = arcs_cmdline;
+	/* Get boot line from environment? */
+	*cp = '\0';
 }
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index a4d0a2c..2c15c8e 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -25,17 +25,71 @@
 
 extern void mips_cpu_irq_init(int);
 
-extern asmlinkage void simIRQ(void);
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
 
-asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	//t0 = t0 << 2;
+	a0 = a0 - t0;
+	//s0 = s0 << t0;
+
+	return a0;
+#endif
+}
+
+static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
 {
 	do_IRQ(2, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	/* Now safe to set the exception vector. */
-	set_except_vector(0, simIRQ);
-
 	mips_cpu_irq_init(MIPSCPU_INT_BASE);
 }
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
index da52297..d16cf38 100644
--- a/arch/mips/mips-boards/sim/sim_irq.S
+++ b/arch/mips/mips-boards/sim/sim_irq.S
@@ -94,6 +94,8 @@
 
 
 spurious:
-	j	spurious_interrupt
+	jal	spurious_interrupt
+	 nop
+	j	ret_from_irq
 	 nop
 	END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
index e57f737..f7ce769 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -18,9 +18,11 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/pfn.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 
 #include <asm/mips-boards/prom.h>
 
@@ -39,9 +41,6 @@
 };
 #endif
 
-/* References to section boundaries */
-extern char _end;
-
 struct prom_pmemblock * __init prom_getmdesc(void)
 {
 	unsigned int memsize;
@@ -61,10 +60,10 @@
 
 	mdesc[2].type = simmem_reserved;
 	mdesc[2].base = 0x00100000;
-	mdesc[2].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[2].base;
+	mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
 
 	mdesc[3].type = simmem_free;
-	mdesc[3].base = CPHYSADDR(PAGE_ALIGN(&_end));
+	mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
 	mdesc[3].size = memsize - mdesc[3].base;
 
 	return &mdesc[0];
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
index a9f0c2b..b7084e7 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -44,8 +44,6 @@
 void core_send_ipi(int cpu, unsigned int action)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-	void smtc_send_ipi(int, int, unsigned int);
-
 	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
 #endif /* CONFIG_MIPS_MT_SMTC */
 /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
@@ -59,15 +57,8 @@
 void __init prom_build_cpu_map(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-	extern int mipsmt_build_cpu_map(int startslot);
 	int nextslot;
 
-	cpus_clear(phys_cpu_present_map);
-
-	/* Register the boot CPU */
-
-	smp_prepare_boot_cpu();
-
 	/*
 	 * As of November, 2004, MIPSsim only simulates one core
 	 * at a time.  However, that core may be a MIPS MT core
@@ -87,8 +78,6 @@
 void prom_boot_secondary(int cpu, struct task_struct *idle)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-	extern void smtc_boot_secondary(int cpu, struct task_struct *t);
-
 	smtc_boot_secondary(cpu, idle);
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
@@ -113,7 +102,6 @@
 void prom_prepare_cpus(unsigned int max_cpus)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-	void mipsmt_prepare_cpus(int c);
 	/*
 	 * As noted above, we can assume a single CPU for now
 	 * but it may be multithreaded.
@@ -132,8 +120,6 @@
 void prom_smp_finish(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-	void smtc_smp_finish(void);
-
 	smtc_smp_finish();
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 9dd1352..bb041a2 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -260,6 +260,10 @@
 {
 }
 
+static void local_r3k_flush_data_cache_page(unsigned long addr)
+{
+}
+
 static void r3k_flush_data_cache_page(unsigned long addr)
 {
 }
@@ -335,6 +339,7 @@
 	flush_icache_range = r3k_flush_icache_range;
 
 	flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+	local_flush_data_cache_page = local_r3k_flush_data_cache_page;
 	flush_data_cache_page = r3k_flush_data_cache_page;
 
 	_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 32b7f6a..4182e11 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -154,7 +154,8 @@
 
 static inline void tx49_blast_icache32_page_indexed(unsigned long page)
 {
-	unsigned long start = page;
+	unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+	unsigned long start = INDEX_BASE + (page & indexmask);
 	unsigned long end = start + PAGE_SIZE;
 	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
 	unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -749,12 +750,12 @@
 		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
 		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
 		c->icache.ways = 2;
-		c->icache.waybit = ffs(icache_size/2) - 1;
+		c->icache.waybit = __ffs(icache_size/2);
 
 		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 2;
-		c->dcache.waybit= ffs(dcache_size/2) - 1;
+		c->dcache.waybit= __ffs(dcache_size/2);
 
 		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
@@ -837,12 +838,12 @@
 		icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
 		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
 		c->icache.ways = 2;
-		c->icache.waybit = ffs(icache_size/2) - 1;
+		c->icache.waybit = __ffs(icache_size/2);
 
 		dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 2;
-		c->dcache.waybit = ffs(dcache_size/2) - 1;
+		c->dcache.waybit = __ffs(dcache_size/2);
 
 		c->options |= MIPS_CPU_CACHE_CDEX_P;
 		break;
@@ -873,12 +874,12 @@
 		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
 		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
 		c->icache.ways = 4;
-		c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+		c->icache.waybit = __ffs(icache_size / c->icache.ways);
 
 		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
 		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
 		c->dcache.ways = 4;
-		c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+		c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
 
 #if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
 		c->options |= MIPS_CPU_CACHE_CDEX_P;
@@ -906,7 +907,7 @@
 		icache_size = c->icache.sets *
 		              c->icache.ways *
 		              c->icache.linesz;
-		c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+		c->icache.waybit = __ffs(icache_size/c->icache.ways);
 
 		if (config & 0x8)		/* VI bit */
 			c->icache.flags |= MIPS_CACHE_VTAG;
@@ -926,7 +927,7 @@
 		dcache_size = c->dcache.sets *
 		              c->dcache.ways *
 		              c->dcache.linesz;
-		c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+		c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
 
 		c->options |= MIPS_CPU_PREFETCH;
 		break;
@@ -1198,6 +1199,7 @@
 
 	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;
 	flush_icache_all	= r4k_flush_icache_all;
+	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;
 	flush_data_cache_page	= r4k_flush_data_cache_page;
 	flush_icache_range	= r4k_flush_icache_range;
 
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2f08b53..f9b1294 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -528,6 +528,7 @@
 	flush_cache_page = sb1_flush_cache_page;
 
 	flush_cache_sigtramp = sb1_flush_cache_sigtramp;
+	local_flush_data_cache_page = (void *) sb1_nop;
 	flush_data_cache_page = (void *) sb1_nop;
 
 	/* Full flush */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index fe232e3..5dfc9b1 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -216,6 +216,11 @@
 		tx39_blast_icache_page_indexed(page);
 }
 
+static void local_tx39_flush_data_cache_page(void * addr)
+{
+	tx39_blast_dcache_page(addr);
+}
+
 static void tx39_flush_data_cache_page(unsigned long addr)
 {
 	tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@
 		flush_icache_range	= (void *) tx39h_flush_icache_all;
 
 		flush_cache_sigtramp	= (void *) tx39h_flush_icache_all;
+		local_flush_data_cache_page	= (void *) tx39h_flush_icache_all;
 		flush_data_cache_page	= (void *) tx39h_flush_icache_all;
 
 		_dma_cache_wback_inv	= tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@
 		flush_icache_range = tx39_flush_icache_range;
 
 		flush_cache_sigtramp = tx39_flush_cache_sigtramp;
+		local_flush_data_cache_page = local_tx39_flush_data_cache_page;
 		flush_data_cache_page = tx39_flush_data_cache_page;
 
 		_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 591c22b..83a5629 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -30,6 +30,7 @@
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
+void (*local_flush_data_cache_page)(void * addr);
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 2d9624f..e3a6172 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -157,7 +157,6 @@
 	 * Oops. The kernel tried to access some bad page. We'll have to
 	 * terminate things with extreme prejudice.
 	 */
-
 	bust_spinlocks(1);
 
 	printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
@@ -188,11 +187,20 @@
 	/* Kernel mode? Handle exceptions or die */
 	if (!user_mode(regs))
 		goto no_context;
-
+	else
 	/*
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
 	 */
+#if 0
+		printk("do_page_fault() #3: sending SIGBUS to %s for "
+		       "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
+		       tsk->comm,
+		       write ? "write access to" : "read access from",
+		       field, address,
+		       field, (unsigned long) regs->cp0_epc,
+		       field, (unsigned long) regs->regs[31]);
+#endif
 	tsk->thread.cp0_badvaddr = address;
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
@@ -201,7 +209,6 @@
 	force_sig_info(SIGBUS, &info, tsk);
 
 	return;
-
 vmalloc_fault:
 	{
 		/*
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 1f7b37b..0c54437 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -83,6 +83,7 @@
 	preempt_check_resched();
 }
 
+#ifndef CONFIG_LIMITED_DMA
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
@@ -101,6 +102,7 @@
 
 	return (void*) vaddr;
 }
+#endif /* CONFIG_LIMITED_DMA */
 
 struct page *__kmap_atomic_to_page(void *ptr)
 {
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index ad89c44..c22308b 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -276,6 +276,20 @@
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+	unsigned long addr;
+
+	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		memset((void *)addr, 0xcc, PAGE_SIZE);
+		free_page(addr);
+		totalram_pages++;
+	}
+	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
@@ -284,16 +298,7 @@
 	start = (unsigned long)phys_to_virt(CPHYSADDR(start));
 	end = (unsigned long)phys_to_virt(CPHYSADDR(end));
 #endif
-	if (start < end)
-		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
-		       (end - start) >> 10);
-
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-	}
+	free_init_pages("initrd memory", start, end);
 }
 #endif
 
@@ -301,24 +306,17 @@
 
 void free_initmem(void)
 {
-	unsigned long addr, page, freed;
+	unsigned long start, end, freed;
 
 	freed = prom_free_prom_memory();
+	if (freed)
+		printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
 
-	addr = (unsigned long) &__init_begin;
-	while (addr < (unsigned long) &__init_end) {
+	start = (unsigned long)(&__init_begin);
+	end = (unsigned long)(&__init_end);
 #ifdef CONFIG_64BIT
-		page = PAGE_OFFSET | CPHYSADDR(addr);
-#else
-		page = addr;
+	start = PAGE_OFFSET | CPHYSADDR(start);
+	end = PAGE_OFFSET | CPHYSADDR(end);
 #endif
-		ClearPageReserved(virt_to_page(page));
-		init_page_count(virt_to_page(page));
-		free_page(page);
-		totalram_pages++;
-		freed += PAGE_SIZE;
-		addr += PAGE_SIZE;
-	}
-	printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
-	       freed >> 10);
+	free_init_pages("unused kernel memory", start, end);
 }
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 3b6cc9b..31ec730 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -138,7 +138,7 @@
 
 	c->scache.linesz = sc_lsize;
 	c->scache.ways = 4;
-	c->scache.waybit= ffs(scache_size / c->scache.ways) - 1;
+	c->scache.waybit= __ffs(scache_size / c->scache.ways);
 	c->scache.waysize = scache_size / c->scache.ways;
 	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
 	printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index a865f239..9dca099 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -32,13 +32,35 @@
 				     "nop; nop; nop; nop; nop; nop;\n\t" \
 				     ".set reorder\n\t")
 
+/* Atomicity and interruptability */
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#include <asm/smtc.h>
+#include <asm/mipsmtregs.h>
+
+#define ENTER_CRITICAL(flags) \
+	{ \
+	unsigned int mvpflags; \
+	local_irq_save(flags);\
+	mvpflags = dvpe()
+#define EXIT_CRITICAL(flags) \
+	evpe(mvpflags); \
+	local_irq_restore(flags); \
+	}
+#else
+
+#define ENTER_CRITICAL(flags) local_irq_save(flags)
+#define EXIT_CRITICAL(flags) local_irq_restore(flags)
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 void local_flush_tlb_all(void)
 {
 	unsigned long flags;
 	unsigned long old_ctx;
 	int entry;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
 	write_c0_entrylo0(0);
@@ -57,7 +79,7 @@
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 
 /* All entries common to a mm share an asid.  To effectively flush
@@ -87,6 +109,7 @@
 		unsigned long flags;
 		int size;
 
+		ENTER_CRITICAL(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		size = (size + 1) >> 1;
 		local_irq_save(flags);
@@ -120,7 +143,7 @@
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
-		local_irq_restore(flags);
+		EXIT_CRITICAL(flags);
 	}
 }
 
@@ -129,9 +152,9 @@
 	unsigned long flags;
 	int size;
 
+	ENTER_CRITICAL(flags);
 	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 	size = (size + 1) >> 1;
-	local_irq_save(flags);
 	if (size <= current_cpu_data.tlbsize / 2) {
 		int pid = read_c0_entryhi();
 
@@ -162,7 +185,7 @@
 	} else {
 		local_flush_tlb_all();
 	}
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -175,7 +198,7 @@
 
 		newpid = cpu_asid(cpu, vma->vm_mm);
 		page &= (PAGE_MASK << 1);
-		local_irq_save(flags);
+		ENTER_CRITICAL(flags);
 		oldpid = read_c0_entryhi();
 		write_c0_entryhi(page | newpid);
 		mtc0_tlbw_hazard();
@@ -194,7 +217,7 @@
 
 	finish:
 		write_c0_entryhi(oldpid);
-		local_irq_restore(flags);
+		EXIT_CRITICAL(flags);
 	}
 }
 
@@ -207,7 +230,7 @@
 	unsigned long flags;
 	int oldpid, idx;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 	oldpid = read_c0_entryhi();
 	page &= (PAGE_MASK << 1);
 	write_c0_entryhi(page);
@@ -226,7 +249,7 @@
 	}
 	write_c0_entryhi(oldpid);
 
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 
 /*
@@ -249,7 +272,7 @@
 	if (current->active_mm != vma->vm_mm)
 		return;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 
 	pid = read_c0_entryhi() & ASID_MASK;
 	address &= (PAGE_MASK << 1);
@@ -277,7 +300,7 @@
 	else
 		tlb_write_indexed();
 	tlbw_use_hazard();
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 
 #if 0
@@ -291,7 +314,7 @@
 	pte_t *ptep;
 	int idx;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 	address &= (PAGE_MASK << 1);
 	asid = read_c0_entryhi() & ASID_MASK;
 	write_c0_entryhi(address | asid);
@@ -310,7 +333,7 @@
 	else
 		tlb_write_indexed();
 	tlbw_use_hazard();
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 #endif
 
@@ -322,7 +345,7 @@
 	unsigned long old_pagemask;
 	unsigned long old_ctx;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
 	old_pagemask = read_c0_pagemask();
@@ -342,7 +365,7 @@
 	BARRIER;
 	write_c0_pagemask(old_pagemask);
 	local_flush_tlb_all();
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 }
 
 /*
@@ -362,7 +385,7 @@
 	unsigned long old_pagemask;
 	unsigned long old_ctx;
 
-	local_irq_save(flags);
+	ENTER_CRITICAL(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
 	old_pagemask = read_c0_pagemask();
@@ -386,10 +409,11 @@
 	write_c0_entryhi(old_ctx);
 	write_c0_pagemask(old_pagemask);
 out:
-	local_irq_restore(flags);
+	EXIT_CRITICAL(flags);
 	return ret;
 }
 
+extern void __init sanitize_tlb_entries(void);
 static void __init probe_tlb(unsigned long config)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -402,6 +426,14 @@
 	 */
 	if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
 		return;
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * If TLB is shared in SMTC system, total size already
+	 * has been calculated and written into cpu_data tlbsize
+	 */
+	if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED)
+		return;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	reg = read_c0_config1();
 	if (!((config >> 7) & 3))
@@ -410,6 +442,15 @@
 	c->tlbsize = ((reg >> 25) & 0x3f) + 1;
 }
 
+static int __initdata ntlb = 0;
+static int __init set_ntlb(char *str)
+{
+	get_option(&str, &ntlb);
+	return 1;
+}
+
+__setup("ntlb=", set_ntlb);
+
 void __init tlb_init(void)
 {
 	unsigned int config = read_c0_config();
@@ -432,5 +473,15 @@
 
 	/* Did I tell you that ARC SUCKS?  */
 
+	if (ntlb) {
+		if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
+			int wired = current_cpu_data.tlbsize - ntlb;
+			write_c0_wired(wired);
+			write_c0_index(wired-1);
+			printk ("Restricting TLB to %d entries\n", ntlb);
+		} else
+			printk("Ignoring invalid argument ntlb=%d\n", ntlb);
+	}
+
 	build_tlb_refill_handler();
 }
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 599b3c2..053dbac 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -7,6 +7,16 @@
  *
  * Copyright (C) 2004,2005 by Thiemo Seufer
  * Copyright (C) 2005  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ *
+ * ... and the days got worse and worse and now you see
+ * I've gone completly out of my mind.
+ *
+ * They're coming to take me a away haha
+ * they're coming to take me a away hoho hihi haha
+ * to the funny farm where code is beautiful all the time ...
+ *
+ * (Condolences to Napoleon XIV)
  */
 
 #include <stdarg.h>
@@ -68,6 +78,7 @@
 	BIMM = 0x040,
 	JIMM = 0x080,
 	FUNC = 0x100,
+	SET = 0x200
 };
 
 #define OP_MASK		0x2f
@@ -86,6 +97,8 @@
 #define JIMM_SH		0
 #define FUNC_MASK	0x2f
 #define FUNC_SH		0
+#define SET_MASK	0x7
+#define SET_SH		0
 
 enum opcode {
 	insn_invalid,
@@ -129,8 +142,8 @@
 	{ insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
 	{ insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
 	{ insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
-	{ insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD },
-	{ insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD },
+	{ insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
+	{ insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
 	{ insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
 	{ insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
 	{ insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
@@ -145,8 +158,8 @@
 	{ insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
 	{ insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
 	{ insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
-	{ insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
-	{ insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+	{ insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
+	{ insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
 	{ insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
 	{ insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
 	{ insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -242,6 +255,14 @@
 	return arg & FUNC_MASK;
 }
 
+static __init u32 build_set(u32 arg)
+{
+	if (arg & ~SET_MASK)
+		printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+	return arg & SET_MASK;
+}
+
 /*
  * The order of opcode arguments is implicitly left to right,
  * starting with RS and ending with FUNC or IMM.
@@ -273,6 +294,7 @@
 	if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
 	if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
 	if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
+	if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
 	va_end(ap);
 
 	**buf = op;
@@ -358,8 +380,8 @@
 I_u1s2(_bltz);
 I_u1s2(_bltzl);
 I_u1u2s3(_bne);
-I_u1u2(_dmfc0);
-I_u1u2(_dmtc0);
+I_u1u2u3(_dmfc0);
+I_u1u2u3(_dmtc0);
 I_u2u1s3(_daddiu);
 I_u3u1u2(_daddu);
 I_u2u1u3(_dsll);
@@ -376,8 +398,8 @@
 I_u2s3u1(_lld);
 I_u1s2(_lui);
 I_u2s3u1(_lw);
-I_u1u2(_mfc0);
-I_u1u2(_mtc0);
+I_u1u2u3(_mfc0);
+I_u1u2u3(_mtc0);
 I_u2u1u3(_ori);
 I_0(_rfe);
 I_u2s3u1(_sc);
@@ -451,8 +473,8 @@
 # define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
 # define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
 # define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
 # define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
 # define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
 # define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
@@ -464,8 +486,8 @@
 # define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
 # define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
 # define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
 # define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
 # define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
 # define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
@@ -670,14 +692,15 @@
 #define K1		27
 
 /* Some CP0 registers */
-#define C0_INDEX	0
-#define C0_ENTRYLO0	2
-#define C0_ENTRYLO1	3
-#define C0_CONTEXT	4
-#define C0_BADVADDR	8
-#define C0_ENTRYHI	10
-#define C0_EPC		14
-#define C0_XCONTEXT	20
+#define C0_INDEX	0, 0
+#define C0_ENTRYLO0	2, 0
+#define C0_TCBIND	2, 2
+#define C0_ENTRYLO1	3, 0
+#define C0_CONTEXT	4, 0
+#define C0_BADVADDR	8, 0
+#define C0_ENTRYHI	10, 0
+#define C0_EPC		14, 0
+#define C0_XCONTEXT	20, 0
 
 #ifdef CONFIG_64BIT
 # define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
@@ -742,7 +765,7 @@
 	}
 #endif
 
-	memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+	memcpy((void *)ebase, tlb_handler, 0x80);
 }
 
 /*
@@ -951,12 +974,20 @@
 	/* No i_nop needed here, since the next insn doesn't touch TMP. */
 
 #ifdef CONFIG_SMP
+# ifdef  CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC uses TCBind value as "CPU" index
+	 */
+	i_mfc0(p, ptr, C0_TCBIND);
+	i_dsrl(p, ptr, ptr, 19);
+# else
 	/*
 	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
 	 * stored in CONTEXT.
 	 */
 	i_dmfc0(p, ptr, C0_CONTEXT);
 	i_dsrl(p, ptr, ptr, 23);
+#endif
 	i_LA_mostly(p, tmp, pgdc);
 	i_daddu(p, ptr, ptr, tmp);
 	i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1014,9 +1045,21 @@
 
 	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
+#ifdef  CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC uses TCBind value as "CPU" index
+	 */
+	i_mfc0(p, ptr, C0_TCBIND);
+	i_LA_mostly(p, tmp, pgdc);
+	i_srl(p, ptr, ptr, 19);
+#else
+	/*
+	 * smp_processor_id() << 3 is stored in CONTEXT.
+         */
 	i_mfc0(p, ptr, C0_CONTEXT);
 	i_LA_mostly(p, tmp, pgdc);
 	i_srl(p, ptr, ptr, 23);
+#endif
 	i_addu(p, ptr, tmp, ptr);
 #else
 	i_LA_mostly(p, ptr, pgdc);
@@ -1247,7 +1290,7 @@
 	}
 #endif
 
-	memcpy((void *)CAC_BASE, final_handler, 0x100);
+	memcpy((void *)ebase, final_handler, 0x100);
 }
 
 /*
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
index 20bbd3e..67372f3 100644
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
 obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
deleted file mode 100644
index 55bc789..0000000
--- a/arch/mips/momentum/jaguar_atx/int-handler.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work:
- *   Copyright 2001 MontaVista Software Inc.
- *   Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Jaguar-ATX board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-		.align	5
-		NESTED(jaguar_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt */
-		bnez	t1, ll_sw0_irq
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt */
-		bnez	t1, ll_sw1_irq
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pcixa_irq
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_pcixb_irq
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_pcia_irq
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_pcib_irq
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_uart_irq
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-		nop
-		nop
-
-		/* now look at extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		sll	t2, t1, 8
-
-		and	t0, t2
-		srl	t0, t0, 16
-
-		andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_mv64340_decode_irq
-
-		nop
-		nop
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(jaguar_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_pcixa_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcixb_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcia_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pcib_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	ll_timer_interrupt
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
index 15588f9..ec4032b 100644
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -10,7 +10,7 @@
  *   Copyright 2001 MontaVista Software Inc.
  *   Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  *
- *   Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *   Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -38,8 +38,37 @@
 #include <linux/types.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/time.h>
 
-extern asmlinkage void jaguar_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		ll_timer_interrupt(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+		if (pending & STATUSF_IP8)
+			ll_mv64340_irq(regs);
+	}
+}
 
 static struct irqaction cascade_mv64340 = {
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
@@ -53,8 +82,6 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, jaguar_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 91d9637..1379c76 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -381,24 +381,24 @@
 	 * shut down ethernet ports, just to be sure our memory doesn't get
 	 * corrupted by random ethernet traffic.
 	 */
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
-	while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
-	while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
-	         MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
-	         MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2),
-	         MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
+	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
+	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
 
 	/* Turn off the Bit-Error LED */
 	JAGUAR_FPGA_WRITE(0x80, CLR);
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
index aab8fd8..8bcea64 100644
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ b/arch/mips/momentum/ocelot_3/Makefile
@@ -5,4 +5,4 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-obj-y	 += int-handler.o irq.o prom.o reset.o setup.o
+obj-y	 += irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
deleted file mode 100644
index 4522f09..0000000
--- a/arch/mips/momentum/ocelot_3/int-handler.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * First-level interrupt dispatcher for Ocelot-3 board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-3 board
- */
-		.align	5
-		NESTED(ocelot3_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt (IRQ0) */
-		bnez	t1, ll_sw0_irq
-
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt (IRQ1) */
-		bnez	t1, ll_sw1_irq
-
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line (IRQ2) */
-		bnez	t1, ll_pci0slot1_irq
-
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line (IRQ3) */
-		bnez	t1, ll_pci0slot2_irq
-
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line (IRQ4) */
-		bnez	t1, ll_pci1slot1_irq
-
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line (IRQ5) */
-		bnez	t1, ll_pci1slot2_irq
-
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line (IRQ6) */
-		bnez	t1, ll_uart_irq
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer (IRQ7) */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at extended interrupts */
-                mfc0    t0, CP0_CAUSE
-                cfc0    t1, CP0_S1_INTCONTROL
-
-                /* shift the mask 8 bits left to line up the bits */
-                sll     t2, t1, 8
-
-                and     t0, t2
-                srl     t0, t0, 16
-
-                andi    t1, t0, STATUSF_IP8     /* int6 hardware line (IRQ9) */
-                bnez    t1, ll_mv64340_decode_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot3_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0		/* IRQ 1 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1		/* IRQ 2 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci0slot1_irq:
-		li	a0, 2		/* IRQ 3 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci0slot2_irq:
-		li	a0, 3		/* IRQ 4 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci1slot1_irq:
-		li	a0, 4		/* IRQ 5 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pci1slot2_irq:
-		li	a0, 5		/* IRQ 6 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 6		/* IRQ 7 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7		/* IRQ 8 */
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
index 42464db..87c63c3 100644
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -53,8 +53,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot3_handle_int(void);
-
 static struct irqaction cascade_mv64340 = {
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
 };
@@ -67,9 +65,6 @@
 	 */
 	clear_c0_status(ST0_IM | ST0_BEV);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot3_handle_int);
-	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
 	/* set up the cascading interrupts */
@@ -79,3 +74,36 @@
 	set_c0_status(ST0_IM); /* IE in the status register */
 
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)
+			ll_mv64340_irq(regs);
+		else
+			spurious_interrupt(regs);
+	}
+}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index 370e75d..c691952 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -329,22 +329,22 @@
 	/* shut down ethernet ports, just to be sure our memory doesn't get
 	 * corrupted by random ethernet traffic.
 	 */
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
 	do {}
-	  while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
 	do {}
-	  while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
 	do {}
-	  while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
 	do {}
-	  while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
-		 MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
-		 MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
 
 	/* Turn off the Bit-Error LED */
 	OCELOT_FPGA_WRITE(0x80, CLR);
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
index 9124077..94802b4 100644
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ b/arch/mips/momentum/ocelot_c/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-C and -CS boards.
 #
 
-obj-y	 		+= cpci-irq.o int-handler.o irq.o prom.o reset.o \
+obj-y	 		+= cpci-irq.o irq.o prom.o reset.o \
 			   setup.o uart-irq.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
deleted file mode 100644
index 52349d9..0000000
--- a/arch/mips/momentum/ocelot_c/int-handler.S
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Ocelot-CS board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include "ocelot_c_fpga.h"
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t1, t0, STATUSF_IP0	/* sw0 software interrupt */
-		bnez	t1, ll_sw0_irq
-		andi	t1, t0, STATUSF_IP1	/* sw1 software interrupt */
-		bnez	t1, ll_sw1_irq
-		andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_scsi_irq
-		andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_uart_decode_irq
-		andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_pmc_irq
-		andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_decode_irq
-		andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_mv64340_decode_irq
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot_handle_int)
-
-		.align	5
-ll_sw0_irq:
-		li	a0, 0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_sw1_irq:
-		li	a0, 1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-ll_scsi_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_decode_irq:
-		move	a0, sp
-		jal	ll_uart_irq
-		j	ret_from_irq
-
-ll_pmc_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_decode_irq:
-		move	a0, sp
-		jal	ll_cpci_irq
-		j	ret_from_irq
-
-ll_mv64340_decode_irq:
-		move	a0, sp
-		jal	ll_mv64340_irq
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
index a5764bc..86f61ce 100644
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -48,7 +48,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
 extern void uart_irq_init(void);
 extern void cpci_irq_init(void);
 
@@ -60,6 +59,33 @@
 	no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
 };
 
+extern void ll_uart_irq(struct pt_regs *regs);
+extern void ll_cpci_irq(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(1, regs);
+	else if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		ll_uart_irq(regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		ll_cpci_irq(regs);
+	else if (pending & STATUSF_IP6)
+		ll_mv64340_irq(regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else
+		spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	/*
@@ -68,8 +94,6 @@
 	 */
 	clear_c0_status(ST0_IM);
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
 	mips_cpu_irq_init(0);
 
 	/* set up the cascading interrupts */
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
index e5f1cb0..adb5665 100644
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ b/arch/mips/momentum/ocelot_g/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-G board.
 #
 
-obj-y	 		+= int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o gt-irq.o prom.o reset.o setup.o
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
deleted file mode 100644
index 772e8f7..0000000
--- a/arch/mips/momentum/ocelot_g/int-handler.S
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-		.align	5
-		NESTED(ocelot_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		 andi	t1, t0, STATUSF_IP2	/* int0 hardware line */
-		bnez	t1, ll_pri_enet_irq
-		 andi	t1, t0, STATUSF_IP3	/* int1 hardware line */
-		bnez	t1, ll_sec_enet_irq
-		 andi	t1, t0, STATUSF_IP4	/* int2 hardware line */
-		bnez	t1, ll_uart_irq
-		 andi	t1, t0, STATUSF_IP5	/* int3 hardware line */
-		bnez	t1, ll_cpci_irq
-		 andi	t1, t0, STATUSF_IP6	/* int4 hardware line */
-		bnez	t1, ll_galileo_p0_irq
-		 andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-		mfc0	t0, CP0_CAUSE
-		cfc0	t1, CP0_S1_INTCONTROL
-
-		/* shift the mask 8 bits left to line up the bits */
-		 sll	t2, t1, 8
-
-		 and	t0, t2
-		 srl	t0, t0, 16
-
-		 andi	t1, t0, STATUSF_IP8	/* int6 hardware line */
-		bnez	t1, ll_galileo_p1_irq
-		 andi	t1, t0, STATUSF_IP9	/* int7 hardware line */
-		bnez	t1, ll_pmc_irq
-		 andi	t1, t0, STATUSF_IP10	/* int8 hardware line */
-		bnez	t1, ll_cpci_abcd_irq
-		 andi	t1, t0, STATUSF_IP11	/* int9 hardware line */
-		bnez	t1, ll_testpoint_irq
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(ocelot_handle_int)
-
-		.align	5
-ll_pri_enet_irq:
-		li	a0, 2
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_sec_enet_irq:
-		li	a0, 3
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_uart_irq:
-		li	a0, 4
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_irq:
-		li	a0, 5
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_p0_irq:
-		li	a0, 6
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cputimer_irq:
-		li	a0, 7
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_galileo_p1_irq:
-		li	a0, 8
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_pmc_irq:
-		li	a0, 9
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_cpci_abcd_irq:
-		li	a0, 10
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_testpoint_irq:
-		li	a0, 11
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
index 5eb85b1..7a4a419 100644
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -48,7 +48,41 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(6, regs);
+	else if (pending & STATUSF_IP7)
+		do_IRQ(7, regs);
+	else {
+		/*
+		 * Now look at the extended interrupts
+		 */
+		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+		if (pending & STATUSF_IP8)
+			do_IRQ(8, regs);
+		else if (pending & STATUSF_IP9)
+			do_IRQ(9, regs);
+		else if (pending & STATUSF_IP10)
+			do_IRQ(10, regs);
+		else if (pending & STATUSF_IP11)
+			do_IRQ(11, regs);
+		else
+			spurious_interrupt(regs);
+	}
+}
+
 extern void gt64240_irq_init(void);
 
 void __init arch_init_irq(void)
@@ -60,8 +94,6 @@
 	clear_c0_status(ST0_IM);
 	local_irq_disable();
 
-	/* Sets the first-level interrupt dispatcher. */
-	set_except_vector(0, ocelot_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index 935dd85..f2b4862 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -27,7 +27,7 @@
 	model->reg_setup(ctr);
 
 	/* Configure the registers on all cpus.  */
-	on_each_cpu(model->cpu_setup, 0, 0, 1);
+	on_each_cpu(model->cpu_setup, NULL, 0, 1);
 
         return 0;
 }
@@ -114,5 +114,6 @@
 
 void oprofile_arch_exit(void)
 {
-	model->exit();
+	if (model)
+		model->exit();
 }
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
index 6e38f3b..b7c6381 100644
--- a/arch/mips/philips/pnx8550/common/Makefile
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -22,6 +22,6 @@
 # under Linux.
 #
 
-obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
index c500e2d..39ee631 100644
--- a/arch/mips/philips/pnx8550/common/int.c
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -38,8 +38,6 @@
 #include <int.h>
 #include <uart.h>
 
-extern asmlinkage void cp0_irqdispatch(void);
-
 static DEFINE_SPINLOCK(irq_lock);
 
 /* default prio for interrupts */
@@ -55,7 +53,7 @@
 	1			//  70
 };
 
-void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq, struct pt_regs *regs)
 {
 	/* find out which interrupt */
 	irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -68,7 +66,7 @@
 }
 
 
-void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq, struct pt_regs *regs)
 {
 	irq = (0x01c0 & read_c0_config7()) >> 6;
 
@@ -88,6 +86,20 @@
 	}
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP2)
+		do_IRQ(2, regs);
+	else if (pending & STATUSF_IP7) {
+		if (read_c0_config7() & 0x01c0)
+			timer_irqdispatch(7, regs);
+	}
+
+	spurious_interrupt(regs);
+}
+
 static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
 {
 	unsigned long status = read_c0_status();
@@ -223,9 +235,6 @@
 	int i;
 	int configPR;
 
-	/* init of cp0 interrupts */
-	set_except_vector(0, cp0_irqdispatch);
-
 	for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
 		irq_desc[i].handler = &level_irq_type;
 		pnx8550_ack(i);	/* mask the irq just in case  */
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
deleted file mode 100644
index 338bffd..0000000
--- a/arch/mips/philips/pnx8550/common/mipsIRQ.S
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2002 Philips, Inc. All rights.
- * Copyright (c) 2002 Red Hat, Inc. All rights.
- *
- * This software may be freely redistributed under the terms of the
- * GNU General Public License.
- *
- * 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.
- *
- * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
- *
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cp0_irqdispatch
- *
- *    Code to handle in-core interrupt exception.
- */
-
-		.align	5
-		.set	reorder
-		.set	noat
-		NESTED(cp0_irqdispatch, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		mfc0	t0,CP0_CAUSE
-		mfc0	t2,CP0_STATUS
-
-		and	t0,t2
-
-		andi	t1,t0,STATUSF_IP2 /* int0 hardware line */
-		bnez	t1,ll_hw0_irq
-		nop
-
-		andi	t1,t0,STATUSF_IP7 /* int5 hardware line */
-		bnez	t1,ll_timer_irq
-		nop
-
-		/* wrong alarm or masked ... */
-
-		j	spurious_interrupt
-		nop
-		END(cp0_irqdispatch)
-
-		.align	5
-		.set	reorder
-ll_hw0_irq:
-		li	a0,2
-		move	a1,sp
-		jal	hw0_irqdispatch
-		nop
-		j	ret_from_irq
-		nop
-
-		.align	5
-		.set	reorder
-ll_timer_irq:
-		mfc0	t3,CP0_CONFIG,7
-		andi	t4,t3,0x01c0
-		beqz	t4,ll_timer_out
-		nop
-		li	a0,7
-		move	a1,sp
-		jal	timer_irqdispatch
-		nop
-
-ll_timer_out:	j	ret_from_irq
-		nop
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index a592260f..5436b4b 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -18,6 +18,7 @@
 #include <linux/resource.h>
 #include <linux/serial.h>
 #include <linux/serial_ip3106.h>
+#include <linux/platform_device.h>
 
 #include <int.h>
 #include <usb.h>
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
index ae96a71..e931e0d 100644
--- a/arch/mips/pmc-sierra/yosemite/Makefile
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the PMC-Sierra Titan
 #
 
-obj-y    += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+obj-y    += irq.o i2c-yosemite.o prom.o py-console.o setup.o
 
 obj-$(CONFIG_KGDB)		+= dbg_io.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
deleted file mode 100644
index 33b9c40..0000000
--- a/arch/mips/pmc-sierra/yosemite/irq-handler.S
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com
- * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
- *
- * First-level interrupt router for the PMC-Sierra Titan board
- *
- * 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.
- *
- * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
- * line is shared between the PCI slot A and Hypertransport. This is the
- * Processor INTB #0.
- */
-
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-		.align	5
-		NESTED(titan_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-		.set	noreorder
-		la	ra, ret_from_irq
-		mfc0	t0, CP0_CAUSE
-		mfc0	t2, CP0_STATUS
-
-		and	t0, t2
-
-		andi	t2, t0, STATUSF_IP7	/* INTB5 hardware line */
-		bnez	t2, ll_timer_irq	/* Timer */
-		andi	t1, t0, STATUSF_IP2	/* INTB0 hardware line */
-		bnez	t1, ll_pcia_irq		/* 64-bit PCI */
-		andi	t2, t0, STATUSF_IP3	/* INTB1 hardware line */
-		bnez	t2, ll_pcib_irq		/* second 64-bit PCI slot */
-		andi	t1, t0, STATUSF_IP4	/* INTB2 hardware line */
-		bnez	t1, ll_duart_irq	/* UART	*/
-		andi    t2, t0, STATUSF_IP5	/* SMP inter-core interrupts */
-		bnez    t2, ll_smp_irq
-		andi	t1, t0, STATUSF_IP6
-		bnez	t1, ll_ht_irq		/* Hypertransport */
-
-		move	a0, sp
-		j	do_extended_irq
-		END(titan_handle_int)
-
-		.set	reorder
-		.align	5
-
-ll_pcia_irq:
-		li	a0, 2
-		move	a1, sp
-#ifdef CONFIG_HYPERTRANSPORT
-		j	ll_ht_smp_irq_handler
-#else
-		j	do_IRQ
-#endif
-
-ll_pcib_irq:
-		li	a0, 3
-		move	a1, sp
-		j	do_IRQ
-
-ll_duart_irq:
-		li	a0, 4
-		move	a1, sp
-		j	do_IRQ
-
-ll_smp_irq:
-		li	a0, 5
-		move	a1, sp
-#ifdef CONFIG_SMP
-		j	titan_mailbox_irq
-#else
-		j	do_IRQ
-#endif
-
-ll_ht_irq:
-		li	a0, 6
-		move	a1, sp
-		j	ll_ht_smp_irq_handler
-
-ll_timer_irq:
-		li	a0, 7
-		move	a1, sp
-		j	do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
index f4e2897..a1f524f 100644
--- a/arch/mips/pmc-sierra/yosemite/irq.c
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -2,6 +2,8 @@
  * Copyright (C) 2003 PMC-Sierra Inc.
  * Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the  License, or (at your
@@ -55,7 +57,6 @@
 #define HYPERTRANSPORT_INTC     0x7a		/* INTC# */
 #define HYPERTRANSPORT_INTD     0x7b		/* INTD# */
 
-extern asmlinkage void titan_handle_int(void);
 extern void jaguar_mailbox_irq(struct pt_regs *);
 
 /*
@@ -125,6 +126,35 @@
 
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int cause = read_c0_cause();
+	unsigned int status = read_c0_status();
+	unsigned int pending = cause & status;
+
+	if (pending & STATUSF_IP7) {
+		do_IRQ(7, regs);
+	} else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+		ll_ht_smp_irq_handler(2, regs);
+#else
+		do_IRQ(2, regs);
+#endif
+	} else if (pending & STATUSF_IP3) {
+		do_IRQ(3, regs);
+	} else if (pending & STATUSF_IP4) {
+		do_IRQ(4, regs);
+	} else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+		titan_mailbox_irq(regs);
+#else
+		do_IRQ(5, regs);
+#endif
+	} else if (pending & STATUSF_IP6) {
+		do_IRQ(4, regs);
+	}
+}
+
 #ifdef CONFIG_KGDB
 extern void init_second_port(void);
 #endif
@@ -136,7 +166,6 @@
 {
 	clear_c0_status(ST0_IM);
 
-	set_except_vector(0, titan_handle_int);
 	mips_cpu_irq_init(0);
 	rm7k_cpu_irq_init(8);
 	rm9k_cpu_irq_init(12);
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index 6a8e8bc..730f459 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Qemu specific kernel interface routines under Linux.
 #
 
-obj-y		= q-firmware.o q-int.o q-irq.o q-mem.o q-setup.o
+obj-y		= q-firmware.o q-irq.o q-mem.o q-setup.o
 
 obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
deleted file mode 100644
index 6e3dfe5..0000000
--- a/arch/mips/qemu/q-int.S
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Qemu interrupt handler code.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.align	5
-	NESTED(qemu_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	move	a0, sp
-	PTR_LA	ra, ret_from_irq
-	j	do_qemu_int
-	END(qemu_handle_int)
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 2c4e070..3352374 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -9,7 +9,7 @@
 
 extern asmlinkage void qemu_handle_int(void);
 
-asmlinkage void do_qemu_int(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned int pending = read_c0_status() & read_c0_cause();
 
@@ -29,7 +29,6 @@
 
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, qemu_handle_int);
 	mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK;		/* 100MHz */
 
 	init_i8259_irqs();
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index eb0820f..6aa4c0c 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
 	   ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)	+= ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index d16fb43..fc6a7e2 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -37,7 +37,6 @@
 static char lc2msk_to_irqnr[256];
 static char lc3msk_to_irqnr[256];
 
-extern asmlinkage void indyIRQ(void);
 extern int ip22_eisa_init(void);
 
 static void enable_local0_irq(unsigned int irq)
@@ -224,7 +223,7 @@
 	.end		= end_local3_irq,
 };
 
-void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(struct pt_regs *regs)
 {
 	u8 mask = sgint->istat0 & sgint->imask0;
 	u8 mask2;
@@ -242,7 +241,7 @@
 	return;
 }
 
-void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(struct pt_regs *regs)
 {
 	u8 mask = sgint->istat1 & sgint->imask1;
 	u8 mask2;
@@ -262,7 +261,7 @@
 
 extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
 
-void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(struct pt_regs *regs)
 {
 	int irq = SGI_BUSERR_IRQ;
 
@@ -307,6 +306,56 @@
 #define SGI_INTERRUPTS	SGINT_LOCAL3
 #endif
 
+extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
+extern void indy_8254timer_irq(struct pt_regs *regs);
+
+/*
+ * IRQs on the INDY look basically (barring software IRQs which we don't use
+ * at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause();
+
+	/*
+	 * First we check for r4k counter/timer IRQ.
+	 */
+	if (pending & CAUSEF_IP7)
+		indy_r4k_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)
+		indy_local0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		indy_local1_irqdispatch(regs);
+	else if (pending & CAUSEF_IP6)
+		indy_buserror_irq(regs);
+	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+		indy_8254timer_irq(regs);
+}
+
 extern void mips_cpu_irq_init(unsigned int irq_base);
 
 void __init arch_init_irq(void)
@@ -369,8 +418,6 @@
 	sgint->cmeimask0 = 0;
 	sgint->cmeimask1 = 0;
 
-	set_except_vector(0, indyIRQ);
-
 	/* init CPU irqs */
 	mips_cpu_irq_init(SGINT_CPU);
 
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
deleted file mode 100644
index 6ccbd9e..0000000
--- a/arch/mips/sgi-ip22/ip22-irq.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
- *             Guiness.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(indyIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
-
-	/* Wheee, a timer interrupt. */
-	jal	indy_r4k_timer_interrupt
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
-
-	/* Wheee, local level zero interrupt. */
-	jal	indy_local0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
-
-	/* Wheee, local level one interrupt. */
-	jal	indy_local1_irqdispatch
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)	# delay slot
-
-	/* Wheee, an asynchronous bus error... */
-	jal	indy_buserror_irq
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	/* Here by mistake? It is possible, that by the time we take
-	 * the exception the IRQ pin goes low, so just leave if this
-	 * is the case.
-	 */
-	beq	a0, zero, 1f
-	 nop			  	# delay slot
-
-	/* Must be one of the 8254 timers... */
-	jal	indy_8254timer_irq
-	 move	a0, sp			# delay slot
-1:
-	j	ret_from_irq
-	 nop				# delay slot
-	END(indyIRQ)
diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile
index 4ba3407..686ba14 100644
--- a/arch/mips/sgi-ip27/Makefile
+++ b/arch/mips/sgi-ip27/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the IP27 specific kernel interface routines under Linux.
 #
 
-obj-y	:= ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+obj-y	:= ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o \
 	   ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
 	   ip27-timer.o ip27-hubio.o ip27-xtalk.o
 
diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO
index 3210613..19f1512 100644
--- a/arch/mips/sgi-ip27/TODO
+++ b/arch/mips/sgi-ip27/TODO
@@ -9,10 +9,6 @@
 in irix?
 6. Investigate why things do not work without the setup_test() call
 being invoked on all nodes in ip27-memory.c.
-7. Too many CLIs in the locore handlers :
-For the low level handlers set up by set_except_vector(),
-__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
-investigate whether the code should do CLI, STI or KMODE.
 8. Too many do_page_faults invoked - investigate.
 9. start_thread must turn off UX64 ... and define tlb_refill_debug.
 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
deleted file mode 100644
index c304df7..0000000
--- a/arch/mips/sgi-ip27/ip27-irq-glue.S
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.align	5
-NESTED(ip27_irq, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-	mfc0	s0, CP0_CAUSE
-	mfc0	t0, CP0_STATUS
-	and	s0, t0
-	move	a0, sp
-	PTR_LA	ra, ret_from_irq
-
-	/* First check for RT interrupt.  */
-	andi	t0, s0, CAUSEF_IP4
-	bnez	t0, ip4
-	andi	t0, s0, CAUSEF_IP2
-	bnez	t0, ip2
-	andi	t0, s0, CAUSEF_IP3
-	bnez	t0, ip3
-	andi	t0, s0, CAUSEF_IP5
-	bnez	t0, ip5
-	andi	t0, s0, CAUSEF_IP6
-	bnez	t0, ip6
-	j	ra
-
-ip2:	j	ip27_do_irq_mask0	# PI_INT_PEND_0 or CC_PEND_{A|B}
-ip3:	j	ip27_do_irq_mask1	# PI_INT_PEND_1
-ip4:	j	ip27_rt_timer_interrupt
-ip5:	j	ip27_prof_timer
-ip6:	j	ip27_hub_error
-
-	END(ip27_irq)
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 2854ac4..2e643d2 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -130,7 +130,7 @@
  * Kanoj 05.13.00
  */
 
-void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(struct pt_regs *regs)
 {
 	int irq, swlevel;
 	hubreg_t pend0, mask0;
@@ -171,7 +171,7 @@
 	LOCAL_HUB_L(PI_INT_PEND0);
 }
 
-void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(struct pt_regs *regs)
 {
 	int irq, swlevel;
 	hubreg_t pend1, mask1;
@@ -196,12 +196,12 @@
 	LOCAL_HUB_L(PI_INT_PEND1);
 }
 
-void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(struct pt_regs *regs)
 {
 	panic("CPU %d got a profiling interrupt", smp_processor_id());
 }
 
-void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(struct pt_regs *regs)
 {
 	panic("CPU %d got a hub error interrupt", smp_processor_id());
 }
@@ -421,9 +421,26 @@
 	return irq;
 }
 
+extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned long pending = read_c0_cause() & read_c0_status();
+
+	if (pending & CAUSEF_IP4)
+		ip27_rt_timer_interrupt(regs);
+	else if (pending & CAUSEF_IP2)	/* PI_INT_PEND_0 or CC_PEND_{A|B} */
+		ip27_do_irq_mask0(regs);
+	else if (pending & CAUSEF_IP3)	/* PI_INT_PEND_1 */
+		ip27_do_irq_mask1(regs);
+	else if (pending & CAUSEF_IP5)
+		ip27_prof_timer(regs);
+	else if (pending & CAUSEF_IP6)
+		ip27_hub_error(regs);
+}
+
 void __init arch_init_irq(void)
 {
-	set_except_vector(0, ip27_irq);
 }
 
 void install_ipi(void)
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index cddf1ce..36b662e 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -122,7 +122,7 @@
 	    xtime.tv_sec > last_rtc_update + 660 &&
 	    (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
 	    (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-		if (rtc_set_time(xtime.tv_sec) == 0) {
+		if (rtc_mips_set_time(xtime.tv_sec) == 0) {
 			last_rtc_update = xtime.tv_sec;
 		} else {
 			last_rtc_update = xtime.tv_sec - 600;
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 470898f..530bf84 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y	+= ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+obj-y	+= ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
 	   crime.o ip32-memory.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644
index 200924e..0000000
--- a/arch/mips/sgi-ip32/ip32-irq-glue.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Harald Koerfgen
- * Copyright (C) 2001 Keith M Wesolowski
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/addrspace.h>
-
-		.text
-		.set    noreorder
-		.set    noat
-		.align  5
-		NESTED(ip32_handle_int, PT_SIZE, ra)
-		.set    noat
-		SAVE_ALL
-		CLI			# TEST: interrupts should be off
-		.set    at
-		.set    noreorder
-
-		mfc0	s0,CP0_CAUSE
-
-		andi	t1, s0, IE_IRQ0
-		bnez	t1, handle_irq0
-		 andi	t1, s0, IE_IRQ1
-		bnez	t1, handle_irq1
-		 andi	t1, s0, IE_IRQ2
-		bnez	t1, handle_irq2
-		 andi	t1, s0, IE_IRQ3
-		bnez	t1, handle_irq3
-		 andi	t1, s0, IE_IRQ4
-		bnez	t1, handle_irq4
-		 andi	t1, s0, IE_IRQ5
-		bnez	t1, handle_irq5
-		 nop
-
-		/* Either someone has triggered the "software interrupts"
-		 * or we lost an interrupt somehow.  Ignore it.
-		 */
-		j	ret_from_irq
-		 nop
-
-handle_irq0:
-		jal	ip32_irq0
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq1:
-		jal	ip32_irq1
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq2:
-		jal	ip32_irq2
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq3:
-		jal	ip32_irq3
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq4:
-		jal	ip32_irq4
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-handle_irq5:
-		jal	ip32_irq5
-		move	a0, sp
-		j	ret_from_irq
-		 nop
-
-		END(ip32_handle_int)
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
index 2eb22d69..de01c98 100644
--- a/arch/mips/sgi-ip32/ip32-irq.c
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -130,8 +130,6 @@
 struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
 			CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
 
-extern void ip32_handle_int(void);
-
 /*
  * For interrupts wired from a single device to the CPU.  Only the clock
  * uses this it seems, which is IRQ 0 and IP7.
@@ -503,48 +501,67 @@
 
 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
 /* change this to loop over all edge-triggered irqs, exception masked out ones */
-void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(struct pt_regs *regs)
 {
 	uint64_t crime_int;
 	int irq = 0;
 
 	crime_int = crime->istat & crime_mask;
-	irq = ffs(crime_int);
-	crime_int = 1 << (irq - 1);
+	irq = __ffs(crime_int);
+	crime_int = 1 << irq;
 
 	if (crime_int & CRIME_MACEISA_INT_MASK) {
 		unsigned long mace_int = mace->perif.ctrl.istat;
-		irq = ffs(mace_int & maceisa_mask) + 32;
+		irq = __ffs(mace_int & maceisa_mask) + 32;
 	}
+	irq++;
 	DBG("*irq %u*\n", irq);
 	do_IRQ(irq, regs);
 }
 
-void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(struct pt_regs *regs)
 {
 	ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(struct pt_regs *regs)
 {
 	ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause();
+
+	if (likely(pending & IE_IRQ0))
+		ip32_irq0(regs);
+	else if (unlikely(pending & IE_IRQ1))
+		ip32_irq1(regs);
+	else if (unlikely(pending & IE_IRQ2))
+		ip32_irq2(regs);
+	else if (unlikely(pending & IE_IRQ3))
+		ip32_irq3(regs);
+	else if (unlikely(pending & IE_IRQ4))
+		ip32_irq4(regs);
+	else if (likely(pending & IE_IRQ5))
+		ip32_irq5(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	unsigned int irq;
@@ -556,7 +573,6 @@
 	crime->soft_int = 0;
 	mace->perif.ctrl.istat = 0;
 	mace->perif.ctrl.imask = 0;
-	set_except_vector(0, ip32_handle_int);
 
 	for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
 		hw_irq_controller *controller;
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 538d5a5..7b36ff3 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)			+= smp.o
 
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 9cf7d71..e61760b 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -187,9 +187,6 @@
 #endif
 
 
-/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
-extern void bcm1480_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@
 #endif
 	/* Enable necessary IPs, disable the rest */
 	change_c0_status(ST0_IM, imask);
-	set_except_vector(0, bcm1480_irq_handler);
 
 #ifdef CONFIG_KGDB
 	if (kgdb_flag) {
@@ -473,3 +469,76 @@
 }
 
 #endif 	/* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+	int lz;
+
+	__asm__ (
+	"	.set	push						\n"
+	"	.set	mips64						\n"
+	"	dclz	%0, %1						\n"
+	"	.set	pop						\n"
+	: "=r" (lz)
+	: "r" (x));
+
+	return lz;
+}
+
+extern void bcm1480_timer_interrupt(struct pt_regs *regs);
+extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
+extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	/* Set compare to count to silence count/compare timer interrupts */
+	write_c0_compare(read_c0_count());
+#endif
+
+	pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+	if (pending & CAUSEF_IP7)	/* Cpu performance counter interrupt */
+		sbprof_cpu_intr(exception_epc(regs));
+#endif
+
+	if (pending & CAUSEF_IP4)
+		bcm1480_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+	if (pending & CAUSEF_IP3)
+		bcm1480_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+	if (pending & CAUSEF_IP6)
+		bcm1480_kgdb_interrupt(regs);		/* KGDB (uart 1) */
+#endif
+
+	if (pending & CAUSEF_IP2) {
+		unsigned long long mask_h, mask_l;
+		unsigned long base;
+
+		/*
+		 * Default...we've hit an IP[2] interrupt, which means we've
+		 * got to check the 1480 interrupt registers to figure out what
+		 * to do.  Need to detect which CPU we're on, now that
+		 * smp_affinity is supported.
+		 */
+		base = A_BCM1480_IMR_MAPPER(smp_processor_id());
+		mask_h = __raw_readq(
+			IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+		mask_l = __raw_readq(
+			IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+		if (!mask_h) {
+			if (mask_h ^ 1)
+				do_IRQ(63 - dclz(mask_h), regs);
+			else
+				do_IRQ(127 - dclz(mask_l), regs);
+		}
+	}
+}
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
deleted file mode 100644
index 408db88..0000000
--- a/arch/mips/sibyte/bcm1480/irq_handler.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * bcm1480_irq_handler() is the routine that is actually called when an
- * interrupt occurs.  It is installed as the exception vector handler in
- * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that
- * to call the dispatcher, which will take care of actually calling
- * registered handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-	.text
-	.set	push
-	.set	noreorder
-	.set	noat
-	.set	mips64
-	#.set	mips4
-	.align	5
-	NESTED(bcm1480_irq_handler, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-	/* Set compare to count to silence count/compare timer interrupts */
-	mfc0	t1, CP0_COUNT
-	mtc0	t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-	/* Read cause */
-	mfc0	s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-	/* Cpu performance counter interrupt is routed to IP[7] */
-	andi	t1, s0, CAUSEF_IP7
-	beqz	t1, 0f
-	 srl	t1, s0, (CAUSEB_BD-2)	/* Shift BD bit to bit 2 */
-	and	t1, t1, 0x4		/* mask to get just BD bit */
-#ifdef CONFIG_MIPS64
-	dmfc0	a0, CP0_EPC
-	daddu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-#else
-	mfc0	a0, CP0_EPC
-	addu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-#endif
-	jal	sbprof_cpu_intr
-	 nop
-	j	ret_from_irq
-	 nop
-0:
-#endif
-
-	/* Timer interrupt is routed to IP[4] */
-	andi	t1, s0, CAUSEF_IP4
-	beqz	t1, 1f
-	 nop
-	jal	bcm1480_timer_interrupt
-	 move	a0, sp			/* Pass the registers along */
-	j	ret_from_irq
-	 nop				/* delay slot  */
-1:
-
-#ifdef CONFIG_SMP
-	/* Mailbox interrupt is routed to IP[3] */
-	andi	 t1, s0, CAUSEF_IP3
-	beqz	 t1, 2f
-	 nop
-	jal	 bcm1480_mailbox_interrupt
-	 move	 a0, sp
-	j	 ret_from_irq
-	 nop				/* delay slot  */
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-	/* KGDB (uart 1) interrupt is routed to IP[6] */
-	andi	 t1, s0, CAUSEF_IP6
-	beqz	 t1, 3f
-	 nop				/* delay slot  */
-	jal	 bcm1480_kgdb_interrupt
-	 move	 a0, sp
-	j	 ret_from_irq
-	 nop				/* delay slot  */
-3:
-#endif
-
-	and	 t1, s0, CAUSEF_IP2
-	beqz	 t1, 9f
-	 nop
-
-	/*
-	 * Default...we've hit an IP[2] interrupt, which means we've got
-	 * to check the 1480 interrupt registers to figure out what to do
-	 * Need to detect which CPU we're on, now that smp_affinity is
-	 * supported.
-	 */
-	PTR_LA	 v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-	lw	 t1, TI_CPU($28)
-	sll	 t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
-	addu	 v0, v0, t1
-#endif
-
-	/* Read IP[2] status (get both high and low halves of status) */
-	ld	 s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
-	ld	 s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
-
-	move	 s2, zero	/* intr number  */
-	li	 s3, 64
-
-	beqz	 s0, 9f		/* No interrupts.  Return.  */
-	 move	 a1, sp
-
-	xori	 s4, s0, 1	/* if s0 (_H) == 1, it's a low intr, so...  */
-	movz	 s2, s3, s4	/* start the intr number at 64, and  */
-	movz	 s0, s1, s4	/* look at the low status value.  */
-
-	dclz	 s1, s0		/* Find the next interrupt.  */
-	dsubu	 a0, zero, s1
-	daddiu	 a0, a0, 63
-	jal	 do_IRQ
-	 daddu	 a0, a0, s2
-
-9:	j	 ret_from_irq
-	 nop
-
-	.set pop
-	END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a8af846..a2fdbd6 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)			+= smp.o
 obj-$(CONFIG_SIBYTE_TBPROF)		+= bcm1250_tbprof.o
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 589537b..0f6e54d 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -163,10 +163,6 @@
 }
 #endif
 
-
-/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
-extern void sb1250_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_sb1250_irq(unsigned int irq)
@@ -379,7 +375,6 @@
 #endif
 	/* Enable necessary IPs, disable the rest */
 	change_c0_status(ST0_IM, imask);
-	set_except_vector(0, sb1250_irq_handler);
 
 #ifdef CONFIG_KGDB
 	if (kgdb_flag) {
@@ -409,7 +404,7 @@
 #define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 #define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(struct pt_regs *regs)
 {
 	/*
 	 * Clear break-change status (allow some time for the remote
@@ -424,3 +419,74 @@
 }
 
 #endif 	/* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+	int lz;
+
+	__asm__ (
+	"	.set	push						\n"
+	"	.set	mips64						\n"
+	"	dclz	%0, %1						\n"
+	"	.set	pop						\n"
+	: "=r" (lz)
+	: "r" (x));
+
+	return lz;
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+	/* Set compare to count to silence count/compare timer interrupts */
+	write_c0_count(read_c0_count());
+#endif
+
+	/*
+	 * What a pain. We have to be really careful saving the upper 32 bits
+	 * of any * register across function calls if we don't want them
+	 * trashed--since were running in -o32, the calling routing never saves
+	 * the full 64 bits of a register across a function call.  Being the
+	 * interrupt handler, we're guaranteed that interrupts are disabled
+	 * during this code so we don't have to worry about random interrupts
+	 * blasting the high 32 bits.
+	 */
+
+	pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+	if (pending & CAUSEF_IP7) { /* Cpu performance counter interrupt */
+		sbprof_cpu_intr(exception_epc(regs));
+	}
+#endif
+
+	if (pending & CAUSEF_IP4)
+		sb1250_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+	if (pending & CAUSEF_IP3)
+		sb1250_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+	if (pending & CAUSEF_IP6)			/* KGDB (uart 1) */
+		sb1250_kgdb_interrupt(regs);
+#endif
+
+	if (pending & CAUSEF_IP2) {
+		unsigned long long mask;
+
+		/*
+		 * Default...we've hit an IP[2] interrupt, which means we've
+		 * got to check the 1250 interrupt registers to figure out what
+		 * to do.  Need to detect which CPU we're on, now that
+		 ~ smp_affinity is supported.
+		 */
+		mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
+		                              R_IMR_INTERRUPT_STATUS_BASE)));
+		if (mask)
+			do_IRQ(63 - dclz(mask), regs);
+	}
+}
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
deleted file mode 100644
index 60edc8f..0000000
--- a/arch/mips/sibyte/sb1250/irq_handler.S
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*
- * sb1250_handle_int() is the routine that is actually called when an interrupt
- * occurs.  It is installed as the exception vector handler in arch_init_irq()
- * in arch/mips/sibyte/sb1250/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that to
- * call the dispatcher, which will take care of actually calling registered
- * handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-	.text
-	.set	push
-	.set	noreorder
-	.set	noat
-	.set	mips64
-	.align	5
-	NESTED(sb1250_irq_handler, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-	/* Set compare to count to silence count/compare timer interrupts */
-	mfc0	t1, CP0_COUNT
-	mtc0	t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-	/* Read cause */
-	mfc0	s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-	/* Cpu performance counter interrupt is routed to IP[7] */
-	andi	t1, s0, CAUSEF_IP7
-	beqz	t1, 0f
-	 srl	t1, s0, (CAUSEB_BD-2)  /* Shift BD bit to bit 2 */
-	and	t1, t1, 0x4		/* mask to get just BD bit */
-	mfc0	a0, CP0_EPC
-	jal	sbprof_cpu_intr
-	 addu	a0, a0, t1		/* a0 = EPC + (BD ? 4 :	0) */
-	j	ret_from_irq
-	 nop
-0:
-#endif
-
-	/* Timer interrupt is routed to IP[4] */
-	andi	t1, s0, CAUSEF_IP4
-	beqz	t1, 1f
-	 nop
-	jal	sb1250_timer_interrupt
-	 move	a0, sp			/* Pass the registers along */
-	j	ret_from_irq
-	 nop				# delay slot
-1:
-
-#ifdef CONFIG_SMP
-	/* Mailbox interrupt is routed to IP[3] */
-	andi	 t1, s0, CAUSEF_IP3
-	beqz	 t1, 2f
-	 nop
-	jal	 sb1250_mailbox_interrupt
-	 move    a0, sp
-	j	ret_from_irq
-	 nop				# delay slot
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-	/* KGDB (uart 1) interrupt is routed to IP[6] */
-	andi	t1, s0, CAUSEF_IP6
-	beqz	t1, 1f
-	nop                            # delay slot
-	jal	sb1250_kgdb_interrupt
-         move	a0, sp
-	j	ret_from_irq
-	nop                            # delay slot
-1:
-#endif
-
-	and      t1, s0, CAUSEF_IP2
-	beqz     t1, 4f
-	 nop
-
-	/*
-	 * Default...we've hit an IP[2] interrupt, which means we've got to
-	 * check the 1250 interrupt registers to figure out what to do
-	 * Need to detect which CPU we're on, now that smp_affinity is supported.
-	 */
-	PTR_LA	v0, CKSEG1 + A_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-	lw	t1, TI_CPU($28)
-	sll	t1, IMR_REGISTER_SPACING_SHIFT
-	addu	v0, t1
-#endif
-	ld	s0, R_IMR_INTERRUPT_STATUS_BASE(v0)	/* read IP[2] status */
-
-	beqz	s0, 4f		/* No interrupts.  Return */
-	 move	a1, sp
-
-3:	dclz	s1, s0		/* Find the next interrupt */
-	dsubu	a0, zero, s1
-	daddiu	a0, a0, 63
-	jal	 do_IRQ
-	 nop
-
-4:	j        ret_from_irq
-	 nop
-
-	.set pop
-	END(sb1250_irq_handler)
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index 1e5676e..9c7eaa5 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y	 	+= int-handler.o irq.o pcimt_scache.o reset.o setup.o
+obj-y	 	+= irq.o pcimt_scache.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
deleted file mode 100644
index 2cdc09f..0000000
--- a/arch/mips/sni/int-handler.S
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SNI RM200 PCI specific interrupt handler code.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sni.h>
-#include <asm/stackframe.h>
-
-/*
- * The PCI ASIC has the nasty property that it may delay writes if it is busy.
- * As a consequence from writes that have not graduated when we exit from the
- * interrupt handler we might catch a spurious interrupt.  To avoid this we
- * force the PCI ASIC to graduate all writes by executing a read from the
- * PCI bus.
- */
-		.set	noreorder
-		.set	noat
-		.align	5
-		NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/* Blinken light ...  */
-		lb	t0, led_cache
-		addiu	t0, 1
-		sb	t0, led_cache
-		sb	t0, PCIMT_CSLED			# write only register
-		.data
-led_cache:	.byte	0
-		.text
-
-		mfc0	t0, CP0_STATUS
-		mfc0	t1, CP0_CAUSE
-		and	t0, t1
-
-		 andi	t1, t0, 0x0800			# hardware interrupt 1
-		bnez	t1, _hwint1
-		 andi	t1, t0, 0x4000			# hardware interrupt 4
-		bnez	t1, _hwint4
-		 andi	t1, t0, 0x2000			# hardware interrupt 3
-		bnez	t1, _hwint3
-		 andi	t1, t0, 0x1000			# hardware interrupt 2
-		bnez	t1, _hwint2
-		 andi	t1, t0, 0x8000			# hardware interrupt 5
-		bnez	t1, _hwint5
-		 andi	t1, t0, 0x0400			# hardware interrupt 0
-		bnez	t1, _hwint0
-		 nop
-
-		j	restore_all			# spurious interrupt
-		 nop
-
- ##############################################################################
-
-/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
-   button interrupts.  */
-_hwint0:	jal	pciasic_hwint0
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts
- */
-_hwint1:	jal	pciasic_hwint1
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-
-/*
- * This interrupt was used for the com1 console on the first prototypes;
- * it's unsed otherwise
- */
-_hwint2:	jal	pciasic_hwint2
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 3 are the PCI interrupts A - D
- */
-_hwint3:	jal	pciasic_hwint3
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-_hwint4:	jal	pciasic_hwint4
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-/* hwint5 is the r4k count / compare interrupt  */
-_hwint5:	jal	pciasic_hwint5
-		 move	a0, sp
-		j	ret_from_irq
-		 nop
-
-		END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 952038a..7365b48 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -19,8 +19,6 @@
 
 DEFINE_SPINLOCK(pciasic_lock);
 
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
 static void enable_pciasic_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
@@ -71,20 +69,20 @@
  * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
  * button interrupts.  Later ...
  */
-void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(struct pt_regs *regs)
 {
 	panic("Received int0 but no handler yet ...");
 }
 
 /* This interrupt was used for the com1 console on the first prototypes.  */
-void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(struct pt_regs *regs)
 {
 	/* I think this shouldn't happen on production machines.  */
 	panic("hwint2 and no handler yet");
 }
 
 /* hwint5 is the r4k count / compare interrupt  */
-void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(struct pt_regs *regs)
 {
 	panic("hwint5 and no handler yet");
 }
@@ -105,7 +103,7 @@
  *
  * The EISA_INT bit in CSITPEND is high active, all others are low active.
  */
-void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(struct pt_regs *regs)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	unsigned long flags;
@@ -135,7 +133,7 @@
 /*
  * hwint 3 should deal with the PCI A - D interrupts,
  */
-void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(struct pt_regs *regs)
 {
 	u8 pend = *(volatile char *)PCIMT_CSITPEND;
 	int irq;
@@ -150,13 +148,34 @@
 /*
  * hwint 4 is used for only the onboard PCnet 32.
  */
-void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(struct pt_regs *regs)
 {
 	clear_c0_status(IE_IRQ4);
 	do_IRQ(PCIMT_IRQ_ETHERNET, regs);
 	set_c0_status(IE_IRQ4);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+	static unsigned char led_cache;
+
+	*(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
+
+	if (pending & 0x0800)
+		pciasic_hwint1(regs);
+	else if (pending & 0x4000)
+		pciasic_hwint4(regs);
+	else if (pending & 0x2000)
+		pciasic_hwint3(regs);
+	else if (pending & 0x1000)
+		pciasic_hwint2(regs);
+	else if (pending & 0x8000)
+		pciasic_hwint5(regs);
+	else if (pending & 0x0400)
+		pciasic_hwint0(regs);
+}
+
 void __init init_pciasic(void)
 {
 	unsigned long flags;
@@ -176,8 +195,6 @@
 {
 	int i;
 
-	set_except_vector(0, sni_rm200_pci_handle_int);
-
 	init_i8259_irqs();			/* Integrated i8259  */
 	init_pciasic();
 
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile
index 8fa126b..9cb9535 100644
--- a/arch/mips/tx4927/common/Makefile
+++ b/arch/mips/tx4927/common/Makefile
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+obj-y	+= tx4927_prom.o tx4927_setup.o tx4927_irq.o
 
 obj-$(CONFIG_TOSHIBA_FPCIB0)	   += smsc_fdc37m81x.o
 obj-$(CONFIG_KGDB)                 += tx4927_dbgio.o
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
index 5ab2e2b..8ca6801 100644
--- a/arch/mips/tx4927/common/tx4927_irq.c
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -525,8 +525,6 @@
  */
 void __init tx4927_irq_init(void)
 {
-	extern asmlinkage void tx4927_irq_handler(void);
-
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
 
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -535,16 +533,12 @@
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
 	tx4927_irq_pic_init();
 
-	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
-			   "=Calling set_except_vector(tx4927_irq_handler)\n");
-	set_except_vector(0, tx4927_irq_handler);
-
 	TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
 
 	return;
 }
 
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
 {
 	int sw_irq = 0;
 	u32 level2;
@@ -582,3 +576,25 @@
 
 	return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP7)			/* cpu timer */
+		do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+	else if (pending & STATUSF_IP2) {		/* tx4927 pic */
+		unsigned int irq = tx4927_irq_nested();
+
+		if (unlikely(irq == 0)) {
+			spurious_interrupt(regs);
+			return;
+		}
+		do_IRQ(irq, regs);
+	} else if (pending & STATUSF_IP0)		/* user line 0 */
+		do_IRQ(TX4927_IRQ_USER0, regs);
+	else if (pending & STATUSF_IP1)			/* user line 1 */
+		do_IRQ(TX4927_IRQ_USER1, regs);
+	else
+		spurious_interrupt(regs);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
deleted file mode 100644
index dd3ceda..0000000
--- a/arch/mips/tx4927/common/tx4927_irq_handler.S
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
- *
- * Primary interrupt handler for tx4927 based systems
- *
- * Author: MontaVista Software, Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *         source@mvista.com
- *
- * Copyright 2001-2002 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4927/tx4927.h>
-
-		.align	5
-		NESTED(tx4927_irq_handler, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		and	t0, t1
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_ip7
-
-		/* IP6..IP3 multiplexed -- do not use */
-
-		andi	t1, t0, STATUSF_IP2	/* tx4927 pic */
-		bnez	t1, ll_ip2
-
-		andi	t1, t0, STATUSF_IP0	/* user line 0 */
-		bnez	t1, ll_ip0
-
-		andi	t1, t0, STATUSF_IP1	/* user line 1 */
-		bnez	t1, ll_ip1
-
-		.set	reorder
-
-		/* wrong alarm or masked ... */
-		j	spurious_interrupt
-		nop
-		END(tx4927_irq_handler)
-
-		.align	5
-
-
-ll_ip7:
-		li	a0, TX4927_IRQ_CPU_TIMER
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip2:
-		jal	tx4927_irq_nested
-		nop
-		beqz 	v0, goto_spurious_interrupt
-		nop
-		move	a0, v0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-goto_spurious_interrupt:
-	j spurious_interrupt
-	nop
-
-ll_ip1:
-		li	a0, TX4927_IRQ_USER1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip0:
-		li	a0, TX4927_IRQ_USER0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 74c95c5..2033ae7 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
+obj-y	+= prom.o setup.o irq.o rtc_rx5c348.o
 obj-$(CONFIG_KGDB) += dbgio.o
 
diff --git a/arch/mips/tx4938/common/irq.c b/arch/mips/tx4938/common/irq.c
index 4f90d7f..8738051 100644
--- a/arch/mips/tx4938/common/irq.c
+++ b/arch/mips/tx4938/common/irq.c
@@ -392,11 +392,8 @@
 void __init
 tx4938_irq_init(void)
 {
-	extern asmlinkage void tx4938_irq_handler(void);
-
 	tx4938_irq_cp0_init();
 	tx4938_irq_pic_init();
-	set_except_vector(0, tx4938_irq_handler);
 
 	return;
 }
@@ -422,3 +419,21 @@
 	wbflush();
 	return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+	else if (pending & STATUSF_IP2) {
+		int irq = tx4938_irq_nested();
+		if (irq)
+			do_IRQ(irq, regs);
+		else
+			spurious_interrupt(regs);
+	} else if (pending & STATUSF_IP1)
+		do_IRQ(TX4938_IRQ_USER1, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(TX4938_IRQ_USER0, regs);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
deleted file mode 100644
index 1b2f72b..0000000
--- a/arch/mips/tx4938/common/irq_handler.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/mips/tx4938/common/handler.S
- *
- * Primary interrupt handler for tx4938 based systems
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. 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.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4938/rbtx4938.h>
-
-
-		.align	5
-		NESTED(tx4938_irq_handler, PT_SIZE, sp)
-		SAVE_ALL
-		CLI
-		.set	at
-
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		and	t0, t1
-
-		andi	t1, t0, STATUSF_IP7	/* cpu timer */
-		bnez	t1, ll_ip7
-
-		/* IP6..IP3 multiplexed -- do not use */
-
-		andi	t1, t0, STATUSF_IP2	/* tx4938 pic */
-		bnez	t1, ll_ip2
-
-		andi	t1, t0, STATUSF_IP1	/* user line 1 */
-		bnez	t1, ll_ip1
-
-		andi	t1, t0, STATUSF_IP0	/* user line 0 */
-		bnez	t1, ll_ip0
-
-		.set	reorder
-
-		nop
-		END(tx4938_irq_handler)
-
-		.align	5
-
-
-ll_ip7:
-		li	a0, TX4938_IRQ_CPU_TIMER
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-
-ll_ip2:
-		jal	tx4938_irq_nested
-		nop
-		beqz	v0, goto_spurious_interrupt
-		nop
-		move	a0, v0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-goto_spurious_interrupt:
-		j	ret_from_irq
-
-ll_ip1:
-		li	a0, TX4938_IRQ_USER1
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
-
-ll_ip0:
-		li	a0, TX4938_IRQ_USER0
-		move	a1, sp
-		jal	do_IRQ
-		j	ret_from_irq
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index a7add16..055a2cd 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -4,6 +4,8 @@
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ISA
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config IBM_WORKPAD
@@ -12,6 +14,8 @@
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ISA
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config NEC_CMBVR4133
@@ -21,6 +25,9 @@
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select HW_HAS_PCI
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config ROCKHOPPER
 	bool "Support for Rockhopper baseboard"
@@ -34,6 +41,8 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
 	  The TANBAC VR4131 multichip module(TB0225) and
@@ -65,6 +74,8 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config ZAO_CAPCELLA
@@ -73,6 +84,8 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
+	select SYS_HAS_CPU_VR41XX
+	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PCI_VR41XX
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 9096302..aa37397 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,7 +2,7 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y				+= bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
+obj-y				+= bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
 obj-$(CONFIG_VRC4173)		+= vrc4173.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
deleted file mode 100644
index 2b6043f..0000000
--- a/arch/mips/vr41xx/common/int-handler.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * FILE NAME
- *	arch/mips/vr41xx/common/int-handler.S
- *
- * BRIEF MODULE DESCRIPTION
- *	Interrupt dispatcher for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
- *
- * Copyright 2001 MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  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.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4100 series are supported.
- *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *  - Coped with INTASSIGN of NEC VR4133.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-		.text
-		.set	noreorder
-
-		.align	5
-		NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-		.set	noreorder
-
-		/*
-		 * Get the pending interrupts
-		 */
-		mfc0	t0, CP0_CAUSE
-		mfc0	t1, CP0_STATUS
-		andi	t0, 0xff00
-		and	t0, t0, t1
-
-		andi	t1, t0, CAUSEF_IP7	# MIPS timer interrupt
-		bnez	t1, handle_irq
-		li	a0, 7
-
-		andi	t1, t0, 0x7800		# check for Int1-4
-		beqz	t1, 1f
-
-		andi	t1, t0, CAUSEF_IP3	# check for Int1
-		bnez	t1, handle_int
-		li	a0, 3
-
-		andi	t1, t0, CAUSEF_IP4	# check for Int2
-		bnez	t1, handle_int
-		li	a0, 4
-
-		andi	t1, t0, CAUSEF_IP5	# check for Int3
-		bnez	t1, handle_int
-		li	a0, 5
-
-		andi	t1, t0, CAUSEF_IP6	# check for Int4
-		bnez	t1, handle_int
-		li	a0, 6
-
-1:
-		andi	t1, t0, CAUSEF_IP2	# check for Int0
-		bnez	t1, handle_int
-		li	a0, 2
-
-		andi	t1, t0, CAUSEF_IP0	# check for IP0
-		bnez	t1, handle_irq
-		li	a0, 0
-
-		andi	t1, t0, CAUSEF_IP1	# check for IP1
-		bnez	t1, handle_irq
-		li	a0, 1
-
-		j	spurious_interrupt
-		nop
-
-handle_int:
-		jal	irq_dispatch
-		move	a1, sp
-		j	ret_from_irq
-		nop
-
-handle_irq:
-		jal	do_IRQ
-		move	a1, sp
-		j	ret_from_irq
-		END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 61aa264..86796bb 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -59,7 +59,7 @@
 
 EXPORT_SYMBOL_GPL(cascade_irq);
 
-asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
 {
 	irq_cascade_t *cascade;
 	irq_desc_t *desc;
@@ -84,11 +84,32 @@
 		do_IRQ(irq, regs);
 }
 
-extern asmlinkage void vr41xx_handle_interrupt(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7)
+		do_IRQ(7, regs);
+	else if (pending & 0x7800) {
+		if (pending & CAUSEF_IP3)
+			irq_dispatch(3, regs);
+		else if (pending & CAUSEF_IP4)
+			irq_dispatch(4, regs);
+		else if (pending & CAUSEF_IP5)
+			irq_dispatch(5, regs);
+		else if (pending & CAUSEF_IP6)
+			irq_dispatch(6, regs);
+	} else if (pending & CAUSEF_IP2)
+		irq_dispatch(2, regs);
+	else if (pending & CAUSEF_IP0)
+		do_IRQ(0, regs);
+	else if (pending & CAUSEF_IP1)
+		do_IRQ(1, regs);
+	else
+		spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
 	mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-
-	set_except_vector(0, vr41xx_handle_interrupt);
 }
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 2fdf219..910fb3a 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -138,6 +138,37 @@
 	  enable this option otherwise. The 64bit kernel is significantly bigger
 	  and slower than the 32bit one.
 
+choice
+	prompt "Kernel page size"
+	default PARISC_PAGE_SIZE_4KB  if !64BIT
+	default PARISC_PAGE_SIZE_4KB  if 64BIT
+#	default PARISC_PAGE_SIZE_16KB if 64BIT
+
+config PARISC_PAGE_SIZE_4KB
+	bool "4KB"
+	help
+	  This lets you select the page size of the kernel.  For best
+	  performance, a page size of 16KB is recommended.  For best
+	  compatibility with 32bit applications, a page size of 4KB should be
+	  selected (the vast majority of 32bit binaries work perfectly fine
+	  with a larger page size).
+
+	  4KB                For best 32bit compatibility
+	  16KB               For best performance
+	  64KB               For best performance, might give more overhead.
+
+	  If you don't know what to do, choose 4KB.
+
+config PARISC_PAGE_SIZE_16KB
+	bool "16KB (EXPERIMENTAL)"
+	depends on PA8X00 && EXPERIMENTAL
+
+config PARISC_PAGE_SIZE_64KB
+	bool "64KB (EXPERIMENTAL)"
+	depends on PA8X00 && EXPERIMENTAL
+
+endchoice
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -177,6 +208,11 @@
 	def_bool y
 	depends on ARCH_DISCONTIGMEM_ENABLE
 
+config NODES_SHIFT
+	int
+	default "3"
+	depends on NEED_MULTIPLE_NODES
+
 source "kernel/Kconfig.preempt"
 source "kernel/Kconfig.hz"
 source "mm/Kconfig"
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
index 59f7bc3..b38b58e 100644
--- a/arch/parisc/defconfig
+++ b/arch/parisc/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-pa6
-# Sun Mar 26 19:50:07 2006
+# Linux kernel version: 2.6.16-pa10
+# Sun Apr  2 15:26:38 2006
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
@@ -25,7 +25,7 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
@@ -35,7 +35,7 @@
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -57,7 +57,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # Block layer
@@ -79,16 +85,19 @@
 #
 # Processor type and features
 #
-CONFIG_PA7000=y
-# CONFIG_PA7100LC is not set
+# CONFIG_PA7000 is not set
+CONFIG_PA7100LC=y
 # CONFIG_PA7200 is not set
 # CONFIG_PA7300LC is not set
 # CONFIG_PA8X00 is not set
 CONFIG_PA11=y
+CONFIG_PARISC_PAGE_SIZE_4KB=y
+# CONFIG_PARISC_PAGE_SIZE_16KB is not set
+# CONFIG_PARISC_PAGE_SIZE_64KB is not set
 # CONFIG_SMP is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
@@ -108,7 +117,7 @@
 # Bus options (PCI, PCMCIA, EISA, GSC, ISA)
 #
 CONFIG_GSC=y
-CONFIG_HPPB=y
+# CONFIG_HPPB is not set
 CONFIG_IOMMU_CCIO=y
 CONFIG_GSC_LASI=y
 CONFIG_GSC_WAX=y
@@ -126,7 +135,25 @@
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_PCCARD_NONSTATIC=y
 
 #
 # PCI Hotplug Support
@@ -145,7 +172,7 @@
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 
 #
 # Networking
@@ -159,13 +186,15 @@
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
@@ -173,19 +202,20 @@
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
 # CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
 # CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET6_TUNNEL=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
@@ -207,7 +237,8 @@
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
@@ -237,9 +268,9 @@
 #
 # Generic Driver Options
 #
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -256,13 +287,14 @@
 # Parallel port support
 #
 CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
 CONFIG_PARPORT_NOT_PC=y
 CONFIG_PARPORT_GSC=y
-# CONFIG_PARPORT_1284 is not set
+CONFIG_PARPORT_1284=y
 
 #
 # Plug and Play support
@@ -284,7 +316,7 @@
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_SIZE=6144
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -292,7 +324,60 @@
 #
 # ATA/ATAPI/MFM/RLL support
 #
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+CONFIG_BLK_DEV_NS87415=y
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -375,6 +460,15 @@
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
 # Multi-device support (RAID and LVM)
 #
 CONFIG_MD=y
@@ -382,12 +476,17 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=y
 CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
+CONFIG_MD_RAID6=y
 # CONFIG_MD_MULTIPATH is not set
 # CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -411,10 +510,10 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
@@ -430,7 +529,7 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
 CONFIG_LASI_82596=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
@@ -451,6 +550,8 @@
 # CONFIG_WINBOND_840 is not set
 # CONFIG_DM9102 is not set
 # CONFIG_ULI526X is not set
+# CONFIG_PCMCIA_XIRCOM is not set
+# CONFIG_PCMCIA_XIRTULIP is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
@@ -518,14 +619,33 @@
 # Obsolete Wireless cards support (pre-802.11)
 #
 # CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
 
 #
 # Wireless 802.11b ISA/PCI cards support
 #
-# CONFIG_HERMES is not set
+CONFIG_HERMES=y
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
 # CONFIG_ATMEL is not set
 
 #
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=y
+CONFIG_PCMCIA_SPECTRUM=y
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 # CONFIG_PRISM54 is not set
@@ -533,13 +653,34 @@
 CONFIG_NET_WIRELESS=y
 
 #
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+# CONFIG_PCMCIA_PCNET is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_AXNET is not set
+
+#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
@@ -571,14 +712,16 @@
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVDEV is not set
 # CONFIG_INPUT_EVBUG is not set
 
 #
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y
+# CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES is not set
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -586,52 +729,25 @@
 # CONFIG_KEYBOARD_HIL_OLD is not set
 CONFIG_KEYBOARD_HIL=y
 CONFIG_INPUT_MOUSE=y
-# CONFIG_MOUSE_PS2 is not set
-# CONFIG_MOUSE_SERIAL is not set
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_VSXXXAA is not set
 CONFIG_MOUSE_HIL=y
-CONFIG_INPUT_JOYSTICK=y
-# CONFIG_JOYSTICK_ANALOG is not set
-# CONFIG_JOYSTICK_A3D is not set
-# CONFIG_JOYSTICK_ADI is not set
-# CONFIG_JOYSTICK_COBRA is not set
-# CONFIG_JOYSTICK_GF2K is not set
-# CONFIG_JOYSTICK_GRIP is not set
-# CONFIG_JOYSTICK_GRIP_MP is not set
-# CONFIG_JOYSTICK_GUILLEMOT is not set
-# CONFIG_JOYSTICK_INTERACT is not set
-# CONFIG_JOYSTICK_SIDEWINDER is not set
-# CONFIG_JOYSTICK_TMDC is not set
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDJOY is not set
-# CONFIG_JOYSTICK_DB9 is not set
-# CONFIG_JOYSTICK_GAMECON is not set
-# CONFIG_JOYSTICK_TURBOGRAFX is not set
-# CONFIG_JOYSTICK_JOYDUMP is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_GUNZE is not set
-# CONFIG_TOUCHSCREEN_ELO is not set
-# CONFIG_TOUCHSCREEN_MTOUCH is not set
-# CONFIG_TOUCHSCREEN_MK712 is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_UINPUT is not set
-CONFIG_HP_SDC_RTC=y
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Hardware I/O ports
 #
 CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_PARKBD is not set
 CONFIG_SERIO_GSCPS2=y
 CONFIG_HP_SDC=y
 CONFIG_HIL_MLC=y
 # CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
 
@@ -648,7 +764,8 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=13
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=17
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
@@ -666,10 +783,10 @@
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
+CONFIG_PPDEV=m
 # CONFIG_TIPAR is not set
 
 #
@@ -682,7 +799,7 @@
 #
 # CONFIG_WATCHDOG is not set
 CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
+CONFIG_GEN_RTC_X=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -691,6 +808,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -718,10 +842,8 @@
 #
 # Hardware Monitoring support
 #
-CONFIG_HWMON=y
+# CONFIG_HWMON is not set
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
@@ -749,8 +871,8 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -778,8 +900,8 @@
 # Console display driver support
 #
 CONFIG_DUMMY_CONSOLE=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=160
-CONFIG_DUMMY_CONSOLE_ROWS=64
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
 CONFIG_FRAMEBUFFER_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
 CONFIG_STI_CONSOLE=y
@@ -816,13 +938,14 @@
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
 CONFIG_SND_SEQUENCER=y
 # CONFIG_SND_SEQ_DUMMY is not set
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_DYNAMIC_MINORS=y
 CONFIG_SND_SUPPORT_OLD_API=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
@@ -830,6 +953,7 @@
 #
 # Generic devices
 #
+CONFIG_SND_OPL3_LIB=y
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_AC97_BUS=y
 # CONFIG_SND_DUMMY is not set
@@ -842,7 +966,7 @@
 # PCI devices
 #
 CONFIG_SND_AD1889=y
-# CONFIG_SND_AD1889_OPL3 is not set
+CONFIG_SND_AD1889_OPL3=y
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -890,6 +1014,10 @@
 # CONFIG_SND_USB_AUDIO is not set
 
 #
+# PCMCIA devices
+#
+
+#
 # GSC devices
 #
 CONFIG_SND_HARMONY=y
@@ -905,12 +1033,12 @@
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
 
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
@@ -918,14 +1046,12 @@
 #
 # USB Host Controller Drivers
 #
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_SPLIT_ISO is not set
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 
 #
@@ -948,13 +1074,11 @@
 #
 # USB Input Devices
 #
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -1020,8 +1144,8 @@
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
 
 #
 # USB DSL modem support
@@ -1058,7 +1182,7 @@
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1066,7 +1190,7 @@
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
@@ -1081,8 +1205,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
+CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1125,7 +1252,7 @@
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
@@ -1133,10 +1260,16 @@
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1153,50 +1286,50 @@
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
 
 #
 # Profiling support
 #
 CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
 
 #
 # Kernel hacking
@@ -1204,7 +1337,7 @@
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=16
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
@@ -1217,42 +1350,43 @@
 # CONFIG_DEBUG_VM is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
-CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA is not set
 
 #
 # Security options
 #
-# CONFIG_KEYS is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
 
 #
 # Hardware crypto devices
@@ -1261,7 +1395,9 @@
 #
 # Library routines
 #
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index e23c4e1..c11a5bc 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -288,8 +288,11 @@
 	DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
 	DEFINE(ASM_PMD_ENTRY_SIZE, PMD_ENTRY_SIZE);
 	DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
+	DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
 	DEFINE(ASM_PT_INITIAL, PT_INITIAL);
 	DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
+	DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64);
+	DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128);
 	BLANK();
 	DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
 	DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 360b739..c057ad7 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -4,7 +4,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999-2006 Helge Deller <deller@gmx.de> (07-13-1999)
  * Copyright (C) 1999 SuSE GmbH Nuernberg
  * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
  *
@@ -358,5 +358,5 @@
 	if (!parisc_cache_flush_threshold)
 		parisc_cache_flush_threshold = FLUSH_THRESHOLD;
 
-	printk("Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
+	printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus());
 }
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 7c95d76..d9e53cf 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -502,18 +502,20 @@
 	 * all ILP32 processes and all the kernel for machines with
 	 * under 4GB of memory) */
 	.macro		L3_ptep pgd,pte,index,va,fault
+#if PT_NLEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
 	extrd,u		\va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
 	copy		%r0,\pte
-	extrd,u,*=	\va,31,32,%r0
+	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	ldw,s		\index(\pgd),\pgd
-	extrd,u,*=	\va,31,32,%r0
+	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	bb,>=,n		\pgd,_PxD_PRESENT_BIT,\fault
-	extrd,u,*=	\va,31,32,%r0
+	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	shld		\pgd,PxD_VALUE_SHIFT,\index
-	extrd,u,*=	\va,31,32,%r0
+	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	copy		\index,\pgd
-	extrd,u,*<>	\va,31,32,%r0
+	extrd,u,*<>	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	ldo		ASM_PGD_PMD_OFFSET(\pgd),\pgd
+#endif
 	L2_ptep		\pgd,\pte,\index,\va,\fault
 	.endm
 
@@ -563,10 +565,18 @@
 	extrd,u,*= 	\pte,_PAGE_GATEWAY_BIT+32,1,%r0
 	depd		%r0,11,2,\prot	/* If Gateway, Set PL2 to 0 */
 
-	/* Get rid of prot bits and convert to page addr for iitlbt and idtlbt */
+	/* Enforce uncacheable pages.
+	 * This should ONLY be use for MMIO on PA 2.0 machines.
+	 * Memory/DMA is cache coherent on all PA2.0 machines we support
+	 * (that means T-class is NOT supported) and the memory controllers
+	 * on most of those machines only handles cache transactions.
+	 */
+	extrd,u,*=	\pte,_PAGE_NO_CACHE_BIT+32,1,%r0
+	depi		1,12,1,\prot
 
-	depd		%r0,63,PAGE_SHIFT,\pte
-	extrd,s		\pte,(63-PAGE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+	/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
+	extrd,u		\pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte
+	depdi		_PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte
 	.endm
 
 	/* Identical macro to make_insert_tlb above, except it
@@ -584,9 +594,8 @@
 
 	/* Get rid of prot bits and convert to page addr for iitlba */
 
-	depi		0,31,PAGE_SHIFT,\pte
+	depi		_PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte
 	extru		\pte,24,25,\pte
-
 	.endm
 
 	/* This is for ILP32 PA2.0 only.  The TLB insertion needs
@@ -1201,10 +1210,9 @@
 	 */
 
 	/* adjust isr/ior. */
-
-	extrd,u         %r16,63,7,%r1    /* get high bits from isr for ior */
-	depd            %r1,31,7,%r17    /* deposit them into ior */
-	depdi           0,63,7,%r16      /* clear them from isr */
+	extrd,u         %r16,63,SPACEID_SHIFT,%r1	/* get high bits from isr for ior */
+	depd            %r1,31,SPACEID_SHIFT,%r17	/* deposit them into ior */
+	depdi           0,63,SPACEID_SHIFT,%r16		/* clear them from isr */
 #endif
 	STREG           %r16, PT_ISR(%r29)
 	STREG           %r17, PT_IOR(%r29)
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 0b47afc..3e79e62 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -76,16 +76,16 @@
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
 
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 	/* Set pmd in pgd */
 	load32		PA(pmd0),%r5
 	shrd            %r5,PxD_VALUE_SHIFT,%r3	
-        ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3	
+	ldo		(PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
 	stw		%r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
 	ldo		ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
 #else
 	/* 2-level page table, so pmd == pgd */
-        ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
+	ldo		ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
 #endif
 
 	/* Fill in pmd with enough pte directories */
@@ -99,7 +99,7 @@
 	stw		%r3,0(%r4)
 	ldo		(ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
 	addib,>		-1,%r1,1b
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 	ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
 #else
 	ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
@@ -107,13 +107,14 @@
 
 
 	/* Now initialize the PTEs themselves */
-	ldo		_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+	ldo		0+_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+	ldi		(1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
 	load32		PA(pg0),%r1
 
 $pgt_fill_loop:
 	STREGM          %r3,ASM_PTE_ENTRY_SIZE(%r1)
-	ldo		ASM_PAGE_SIZE(%r3),%r3
-	bb,>=		%r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop
+	ldo		(1<<PFN_PTE_SHIFT)(%r3),%r3 /* add one PFN */
+	addib,>		-1,%r11,$pgt_fill_loop
 	nop
 
 	/* Load the return address...er...crash 'n burn */
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index 7e898fd..8384bf9 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -53,17 +53,17 @@
 	__attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
 		{ INIT_THREAD_INFO(init_task) };
 
-#ifdef __LP64__
+#if PT_NLEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
  * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
  * guarantee that global objects will be laid out in memory in the same order 
  * as the order of declaration, so put these in different sections and use
  * the linker script to order them. */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
-
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data.vm0.pmd"), aligned(PAGE_SIZE)));
 #endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte")))  = { {0}, };
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data.vm0.pgd"), aligned(PAGE_SIZE)));
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data.vm0.pte"), aligned(PAGE_SIZE)));
 
 /*
  * Initial task structure.
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 7a4f07e..f600556 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -65,7 +65,7 @@
 	 */
 
 	/* pcxt_ssm_bug	- relied upon translation! PA 2.0 Arch. F-4 and F-5 */
-	rsm	PSW_SM_I, %r19		/* save I-bit state */
+	rsm		PSW_SM_I, %r19		/* save I-bit state */
 	load32		PA(1f), %r1
 	nop
 	nop
@@ -84,8 +84,7 @@
 	rfi
 	nop
 
-1:      ldil		L%PA(cache_info), %r1
-	ldo		R%PA(cache_info)(%r1), %r1
+1:      load32		PA(cache_info), %r1
 
 	/* Flush Instruction Tlb */
 
@@ -212,8 +211,7 @@
 	.entry
 
 	mtsp		%r0, %sr1
-	ldil		L%cache_info, %r1
-	ldo		R%cache_info(%r1), %r1
+	load32		cache_info, %r1
 
 	/* Flush Instruction Cache */
 
@@ -254,8 +252,7 @@
 	.entry
 
 	mtsp		%r0, %sr1
-	ldil		L%cache_info, %r1
-	ldo		R%cache_info(%r1), %r1
+	load32 		cache_info, %r1
 
 	/* Flush Data Cache */
 
@@ -303,7 +300,8 @@
 	 */
 
 	ldd		0(%r25), %r19
-	ldi		32, %r1                 /* PAGE_SIZE/128 == 32 */
+	ldi		ASM_PAGE_SIZE_DIV128, %r1
+
 	ldw		64(%r25), %r0		/* prefetch 1 cacheline ahead */
 	ldw		128(%r25), %r0		/* prefetch 2 */
 
@@ -368,7 +366,7 @@
 	 * use ldd/std on a 32 bit kernel.
 	 */
 	ldw		0(%r25), %r19
-	ldi		64, %r1		/* PAGE_SIZE/64 == 64 */
+	ldi		ASM_PAGE_SIZE_DIV64, %r1
 
 1:
 	ldw		4(%r25), %r20
@@ -461,6 +459,7 @@
 	sub		%r25, %r1, %r23		/* move physical addr into non shadowed reg */
 
 	ldil		L%(TMPALIAS_MAP_START), %r28
+	/* FIXME for different page sizes != 4k */
 #ifdef CONFIG_64BIT
 	extrd,u		%r26,56,32, %r26		/* convert phys addr to tlb insert format */
 	extrd,u		%r23,56,32, %r23		/* convert phys addr to tlb insert format */
@@ -551,6 +550,7 @@
 #ifdef CONFIG_64BIT
 #if (TMPALIAS_MAP_START >= 0x80000000)
 	depdi		0, 31,32, %r28		/* clear any sign extension */
+	/* FIXME: page size dependend */
 #endif
 	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
 	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
@@ -566,10 +566,10 @@
 	pdtlb		0(%r28)
 
 #ifdef CONFIG_64BIT
-	ldi		32, %r1			/* PAGE_SIZE/128 == 32 */
+	ldi		ASM_PAGE_SIZE_DIV128, %r1
 
 	/* PREFETCH (Write) has not (yet) been proven to help here */
-/* #define	PREFETCHW_OP	ldd		256(%0), %r0 */
+	/* #define	PREFETCHW_OP	ldd		256(%0), %r0 */
 
 1:	std		%r0, 0(%r28)
 	std		%r0, 8(%r28)
@@ -591,8 +591,7 @@
 	ldo		128(%r28), %r28
 
 #else	/* ! CONFIG_64BIT */
-
-	ldi		64, %r1			/* PAGE_SIZE/64 == 64 */
+	ldi		ASM_PAGE_SIZE_DIV64, %r1
 
 1:
 	stw		%r0, 0(%r28)
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 47ca5c0..fc107ad 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -31,7 +31,6 @@
 
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strpbrk);
 
 #include <asm/atomic.h>
 EXPORT_SYMBOL(__xchg8);
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index d15a1d5..8b5df98 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -231,6 +231,14 @@
 			(loff_t)high_len << 32 | low_len, advice);
 }
 
+asmlinkage long parisc_sync_file_range(int fd,
+			u32 hi_off, u32 lo_off, u32 hi_nbytes, u32 lo_nbytes,
+			unsigned int flags)
+{
+	return sys_sync_file_range(fd, (loff_t)hi_off << 32 | lo_off,
+			(loff_t)hi_nbytes << 32 | lo_nbytes, flags);
+}
+
 asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag)
 {
 	return -ENOMEM;
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index af88afe..479d9a0 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -55,7 +55,7 @@
 	 * pointers.
 	 */
 
-	.align 4096
+	.align ASM_PAGE_SIZE
 linux_gateway_page:
 
         /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */
@@ -632,7 +632,7 @@
 end_compare_and_swap:
 
 	/* Make sure nothing else is placed on this page */
-	.align 4096
+	.align ASM_PAGE_SIZE
 	.export end_linux_gateway_page
 end_linux_gateway_page:
 
@@ -652,7 +652,7 @@
 
 	.section .rodata,"a"
 
-	.align 4096
+	.align ASM_PAGE_SIZE
 	/* Light-weight-syscall table */
 	/* Start of lws table. */
 	.export lws_table
@@ -662,14 +662,14 @@
 	LWS_ENTRY(compare_and_swap64)	/* 1 - ELF64 Atomic compare and swap */
 	/* End of lws table */
 
-	.align 4096
+	.align ASM_PAGE_SIZE
 	.export sys_call_table
 .Lsys_call_table:
 sys_call_table:
 #include "syscall_table.S"
 
 #ifdef CONFIG_64BIT
-	.align 4096
+	.align ASM_PAGE_SIZE
 	.export sys_call_table64
 .Lsys_call_table64:
 sys_call_table64:
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index bbeeb61..e27b432 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -13,7 +13,7 @@
  *    Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
  *    Copyright (C) 2000-2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
- *
+ *    Copyright (C) 2005-2006 Kyle McMartin <kyle at parisc-linux.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -393,5 +393,11 @@
 	ENTRY_SAME(readlinkat)		/* 285 */
 	ENTRY_SAME(fchmodat)
 	ENTRY_SAME(faccessat)
+	ENTRY_SAME(unshare)
+	ENTRY_COMP(set_robust_list)
+	ENTRY_COMP(get_robust_list)	/* 290 */
+	ENTRY_SAME(splice)
+	ENTRY_OURS(sync_file_range)
+	ENTRY_SAME(tee)
 	/* Nothing yet */
 
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 6d6436a..94dcc03 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -6,6 +6,7 @@
  *    Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
+ *    Copyright (C) 2006 Helge Deller <deller@gmx.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,7 @@
 /* needed for the processor specific cache alignment size */	
 #include <asm/cache.h>
 #include <asm/page.h>
+#include <asm/asm-offsets.h>
 	
 /* ld script to make hppa Linux kernel */
 #ifndef CONFIG_64BIT
@@ -68,7 +70,7 @@
   RODATA
 
   /* writeable */
-  . = ALIGN(4096);		/* Make sure this is page aligned so
+  . = ALIGN(ASM_PAGE_SIZE);	/* Make sure this is page aligned so
   				   that we can properly leave these
 				   as writable */
   data_start = .;
@@ -81,23 +83,17 @@
   __start___unwind = .;         /* unwind info */
   .PARISC.unwind : { *(.PARISC.unwind) }
   __stop___unwind = .;
- 
+
+  /* rarely changed data like cpu maps */
+  . = ALIGN(16);
+  .data.read_mostly : { *(.data.read_mostly) }
+
+  . = ALIGN(L1_CACHE_BYTES);
   .data : {			/* Data */
 	*(.data)
-	*(.data.vm0.pmd)
-	*(.data.vm0.pgd)
-	*(.data.vm0.pte)
 	CONSTRUCTORS
 	}
 
-  . = ALIGN(4096);
-  /* nosave data is really only used for software suspend...it's here
-   * just in case we ever implement it */
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
   . = ALIGN(L1_CACHE_BYTES);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
@@ -105,12 +101,29 @@
   . = ALIGN(16);
   .data.lock_aligned : { *(.data.lock_aligned) }
 
-  /* rarely changed data like cpu maps */
-  . = ALIGN(16);
-  .data.read_mostly : { *(.data.read_mostly) }
+  . = ALIGN(ASM_PAGE_SIZE);
+  /* nosave data is really only used for software suspend...it's here
+   * just in case we ever implement it */
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(ASM_PAGE_SIZE);
+  __nosave_end = .;
 
   _edata = .;			/* End of data section */
 
+  __bss_start = .;		/* BSS */
+  /* page table entries need to be PAGE_SIZE aligned */
+  . = ALIGN(ASM_PAGE_SIZE);
+  .data.vmpages : {
+	*(.data.vm0.pmd)
+	*(.data.vm0.pgd)
+	*(.data.vm0.pte)
+	}
+  .bss : { *(.bss) *(COMMON) }
+  __bss_stop = .;
+
+
+  /* assembler code expects init_task to be 16k aligned */
   . = ALIGN(16384); 		/* init_task */
   .data.init_task : { *(.data.init_task) }
 
@@ -126,6 +139,7 @@
   .dlt : { *(.dlt) }
 #endif
 
+  /* reserve space for interrupt stack by aligning __init* to 16k */
   . = ALIGN(16384);
   __init_begin = .;
   .init.text : { 
@@ -166,7 +180,7 @@
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
   .exit.data : { *(.exit.data) }
-  . = ALIGN(4096);
+  . = ALIGN(ASM_PAGE_SIZE);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
@@ -174,14 +188,10 @@
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(ASM_PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
 	
-  __bss_start = .;		/* BSS */
-  .bss : { *(.bss) *(COMMON) }
-  __bss_stop = .; 
-
   _end = . ;
 
   /* Sections to be discarded */
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 0ad945d..64785e4 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -186,7 +186,7 @@
 		break;
 	      case VM_FAULT_SIGBUS:
 		/*
-		 * We hit a hared mapping outside of the file, or some
+		 * We hit a shared mapping outside of the file, or some
 		 * other thing happened to us that made us unable to
 		 * handle the page fault gracefully.
 		 */
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3796be6..6317125 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -6,6 +6,7 @@
  *    changed by Philipp Rumpf
  *  Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  *  Copyright 2004 Randolph Chung (tausq@debian.org)
+ *  Copyright 2006 Helge Deller (deller@gmx.de)
  *
  */
 
@@ -371,8 +372,8 @@
 
 void free_initmem(void)
 {
-	unsigned long addr;
-	
+	unsigned long addr, init_begin, init_end;
+
 	printk(KERN_INFO "Freeing unused kernel memory: ");
 
 #ifdef CONFIG_DEBUG_KERNEL
@@ -395,8 +396,11 @@
 	local_irq_enable();
 #endif
 	
-	addr = (unsigned long)(&__init_begin);
-	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+	/* align __init_begin and __init_end to page size,
+	   ignoring linker script where we might have tried to save RAM */
+	init_begin = PAGE_ALIGN((unsigned long)(&__init_begin));
+	init_end   = PAGE_ALIGN((unsigned long)(&__init_end));
+	for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
 		free_page(addr);
@@ -407,7 +411,7 @@
 	/* set up a new led state on systems shipped LED State panel */
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
 	
-	printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
+	printk("%luk freed\n", (init_end - init_begin) >> 10);
 }
 
 
@@ -639,11 +643,13 @@
 				 * Map the fault vector writable so we can
 				 * write the HPMC checksum.
 				 */
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 				if (address >= ro_start && address < ro_end
 							&& address != fv_addr
 							&& address != gw_addr)
 				    pte = __mk_pte(address, PAGE_KERNEL_RO);
 				else
+#endif
 				    pte = __mk_pte(address, pgprot);
 
 				if (address >= end_paddr)
@@ -874,8 +880,7 @@
 			flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
 			spin_lock(&sid_lock);
 		}
-		if (free_space_ids == 0)
-			BUG();
+		BUG_ON(free_space_ids == 0);
 	}
 
 	free_space_ids--;
@@ -899,8 +904,7 @@
 
 	spin_lock(&sid_lock);
 
-	if (*dirty_space_offset & (1L << index))
-	    BUG(); /* attempt to free space id twice */
+	BUG_ON(*dirty_space_offset & (1L << index)); /* attempt to free space id twice */
 
 	*dirty_space_offset |= (1L << index);
 	dirty_space_ids++;
@@ -975,7 +979,7 @@
 
 static unsigned long recycle_ndirty;
 static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
-static unsigned int recycle_inuse = 0;
+static unsigned int recycle_inuse;
 
 void flush_tlb_all(void)
 {
@@ -984,9 +988,7 @@
 	do_recycle = 0;
 	spin_lock(&sid_lock);
 	if (dirty_space_ids > RECYCLE_THRESHOLD) {
-	    if (recycle_inuse) {
-		BUG();  /* FIXME: Use a semaphore/wait queue here */
-	    }
+	    BUG_ON(recycle_inuse);  /* FIXME: Use a semaphore/wait queue here */
 	    get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
 	    recycle_inuse++;
 	    do_recycle++;
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 0db1281..2738456 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -2,7 +2,7 @@
  * arch/parisc/mm/ioremap.c
  *
  * (C) Copyright 1995 1996 Linus Torvalds
- * (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ * (C) Copyright 2001-2006 Helge Deller <deller@gmx.de>
  * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
  */
 
@@ -138,6 +138,7 @@
 	if ((phys_addr >= 0x00080000 && end < 0x000fffff) ||
 	    (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
 		phys_addr |= F_EXTEND(0xfc000000);
+		flags |= _PAGE_NO_CACHE;
 	}
 #endif
 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2cdc35c..6729c98 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -366,6 +366,7 @@
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
+	select PPC_970_NAP
 	default y
 
 config PPC_PREP
@@ -383,6 +384,7 @@
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
 	select PPC_UDBG_16550
+	select PPC_970_NAP
 	default n
 	help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -457,6 +459,10 @@
 	bool
 	default n
 
+config PPC_970_NAP
+	bool
+	default n
+
 source "drivers/cpufreq/Kconfig"
 
 config CPU_FREQ_PMAC
@@ -649,6 +655,11 @@
 	depends on PPC64
 	default y if SMP && PPC_PSERIES
 
+config NODES_SHIFT
+	int
+	default "4"
+	depends on NEED_MULTIPLE_NODES
+
 config ARCH_SELECT_MEMORY_MODEL
 	def_bool y
 	depends on PPC64
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6ec84d3..ed5b26a 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -104,6 +104,10 @@
 CFLAGS		+= -mstring
 endif
 
+ifeq ($(CONFIG_6xx),y)
+CFLAGS		+= -mcpu=powerpc
+endif
+
 cpu-as-$(CONFIG_PPC64BRIDGE)	+= -Wa,-mppc64bridge
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 2c3fd20..a456275 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:08 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 13:24:37 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -29,6 +30,7 @@
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 
@@ -53,6 +55,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -67,10 +70,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -82,7 +81,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -91,6 +89,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -185,7 +184,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -227,6 +225,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -238,6 +237,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -261,6 +262,7 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -513,6 +515,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -761,7 +764,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -772,6 +774,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
@@ -813,7 +816,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -832,9 +834,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -862,10 +862,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -874,6 +870,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -883,6 +880,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -901,7 +899,6 @@
 CONFIG_FB_NVIDIA_I2C=y
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -958,9 +955,11 @@
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -977,6 +976,7 @@
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALS4000 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
@@ -1009,6 +1009,7 @@
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -1041,6 +1042,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1068,7 +1070,6 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
 
@@ -1126,15 +1127,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 CONFIG_USB_CATC=m
@@ -1194,6 +1186,7 @@
 CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
 CONFIG_USB_SERIAL_PL2303=m
 # CONFIG_USB_SERIAL_HP4X is not set
 CONFIG_USB_SERIAL_SAFE=m
@@ -1237,17 +1230,23 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
 # File systems
@@ -1319,7 +1318,6 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 1816a46..a95e455 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:19:52 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:46:44 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 
@@ -55,6 +57,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -93,6 +91,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -165,7 +164,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -207,6 +205,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -218,6 +217,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -236,11 +237,14 @@
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 # CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -262,20 +266,19 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+# CONFIG_IP_NF_MATCH_AH is not set
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_MATCH_POLICY=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -479,6 +482,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -702,7 +706,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -751,10 +754,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -779,6 +778,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -796,6 +796,11 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -805,6 +810,11 @@
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -878,7 +888,6 @@
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index daaf038..58e68ce 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Fri Feb 10 17:33:32 2006
+# Linux kernel version: 2.6.17-rc1
+# Wed Apr 19 11:48:00 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -30,6 +31,7 @@
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
 
@@ -55,6 +57,7 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CPUSETS=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
@@ -69,10 +72,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -84,7 +83,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
@@ -93,6 +91,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -188,7 +187,6 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -235,6 +233,7 @@
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -246,6 +245,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -272,6 +273,7 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -519,6 +521,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -750,6 +753,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -767,7 +771,9 @@
 # CONFIG_PRINTER is not set
 # CONFIG_PPDEV is not set
 # CONFIG_TIPAR is not set
+CONFIG_HVC_DRIVER=y
 CONFIG_HVC_CONSOLE=y
+# CONFIG_HVC_RTAS is not set
 CONFIG_HVCS=m
 
 #
@@ -779,7 +785,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -830,7 +835,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -849,9 +853,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -879,10 +881,6 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -891,6 +889,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -900,6 +899,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -919,7 +919,6 @@
 CONFIG_FB_MATROX_G=y
 # CONFIG_FB_MATROX_I2C is not set
 CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -968,6 +967,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1048,15 +1048,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1109,6 +1100,11 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
@@ -1121,12 +1117,13 @@
 # CONFIG_INFINIBAND_SRP is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
-# EDAC - error detection and reporting (RAS)
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
 # File systems
@@ -1202,7 +1199,6 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 0cc0995..803858e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -20,7 +20,7 @@
 				   firmware.o sysfs.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
-obj-$(CONFIG_POWER4)		+= idle_power4.o
+obj-$(CONFIG_PPC_970_NAP)	+= idle_power4.o
 obj-$(CONFIG_PPC_OF)		+= of_device.o prom_parse.o
 procfs-$(CONFIG_PPC64)		:= proc_ppc64.o
 obj-$(CONFIG_PROC_FS)		+= $(procfs-y)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 54b48f3..8f85c5e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -91,6 +91,7 @@
 #endif /* CONFIG_PPC64 */
 
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index b3a9794..8866fd2 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -128,37 +128,36 @@
 	stw	r12,4(r11)
 #endif
 	b	3f
+
 2:	/* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
+	lwz	r9,THREAD_INFO-THREAD(r12)
+	cmplw	r1,r9			/* if r1 <= current->thread_info */
+	ble-	stack_ovf		/* then the kernel stack overflowed */
+5:
 #ifdef CONFIG_6xx
-	mfspr	r11,SPRN_HID0
-	mtcr	r11
-BEGIN_FTR_SECTION
-	bt-	8,4f			/* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
-	bt-	9,4f			/* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+	tophys(r9,r9)			/* check local flags */
+	lwz	r12,TI_LOCAL_FLAGS(r9)
+	mtcrf	0x01,r12
+	bt-	31-TLF_NAPPING,4f
 #endif /* CONFIG_6xx */
 	.globl transfer_to_handler_cont
 transfer_to_handler_cont:
-	lwz	r11,THREAD_INFO-THREAD(r12)
-	cmplw	r1,r11			/* if r1 <= current->thread_info */
-	ble-	stack_ovf		/* then the kernel stack overflowed */
 3:
 	mflr	r9
 	lwz	r11,0(r9)		/* virtual address of handler */
 	lwz	r9,4(r9)		/* where to go when done */
-	FIX_SRR1(r10,r12)
 	mtspr	SPRN_SRR0,r11
 	mtspr	SPRN_SRR1,r10
 	mtlr	r9
 	SYNC
 	RFI				/* jump to handler, enable MMU */
 
-#ifdef CONFIG_6xx	
-4:	b	power_save_6xx_restore
+#ifdef CONFIG_6xx
+4:	rlwinm	r12,r12,0,~_TLF_NAPPING
+	stw	r12,TI_LOCAL_FLAGS(r9)
+	b	power_save_6xx_restore
 #endif
 
 /*
@@ -167,10 +166,10 @@
  */
 stack_ovf:
 	/* sometimes we use a statically-allocated stack, which is OK. */
-	lis	r11,_end@h
-	ori	r11,r11,_end@l
-	cmplw	r1,r11
-	ble	3b			/* r1 <= &_end is OK */
+	lis	r12,_end@h
+	ori	r12,r12,_end@l
+	cmplw	r1,r12
+	ble	5b			/* r1 <= &_end is OK */
 	SAVE_NVGPRS(r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	lis	r1,init_thread_union@ha
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index a5ae04a..b7d1404 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -376,11 +376,28 @@
 	bl	hdlr;					\
 	b	.ret_from_except
 
+/*
+ * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
+ * in the idle task and therefore need the special idle handling.
+ */
+#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr)	\
+	.align	7;					\
+	.globl label##_common;				\
+label##_common:						\
+	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\
+	FINISH_NAP;					\
+	DISABLE_INTS;					\
+	bl	.save_nvgprs;				\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;		\
+	bl	hdlr;					\
+	b	.ret_from_except
+
 #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)	\
 	.align	7;					\
 	.globl label##_common;				\
 label##_common:						\
 	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\
+	FINISH_NAP;					\
 	DISABLE_INTS;					\
 	bl	.ppc64_runlatch_on;			\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;		\
@@ -388,6 +405,25 @@
 	b	.ret_from_except_lite
 
 /*
+ * When the idle code in power4_idle puts the CPU into NAP mode,
+ * it has to do so in a loop, and relies on the external interrupt
+ * and decrementer interrupt entry code to get it out of the loop.
+ * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags
+ * to signal that it is in the loop and needs help to get out.
+ */
+#ifdef CONFIG_PPC_970_NAP
+#define FINISH_NAP				\
+BEGIN_FTR_SECTION				\
+	clrrdi	r11,r1,THREAD_SHIFT;		\
+	ld	r9,TI_LOCAL_FLAGS(r11);		\
+	andi.	r10,r9,_TLF_NAPPING;		\
+	bnel	power4_fixup_nap;		\
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+#else
+#define FINISH_NAP
+#endif
+
+/*
  * Start of pSeries system interrupt routines
  */
 	. = 0x100
@@ -772,6 +808,7 @@
 	.globl machine_check_common
 machine_check_common:
 	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+	FINISH_NAP
 	DISABLE_INTS
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -783,7 +820,7 @@
 	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
 	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
 	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-	STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception)
+	STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
 	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
 #ifdef CONFIG_ALTIVEC
 	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
@@ -1034,6 +1071,7 @@
 	.globl hardware_interrupt_entry
 hardware_interrupt_common:
 	EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
+	FINISH_NAP
 hardware_interrupt_entry:
 	DISABLE_INTS
 	bl	.ppc64_runlatch_on
@@ -1041,6 +1079,15 @@
 	bl	.do_IRQ
 	b	.ret_from_except_lite
 
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+	andc	r9,r9,r10
+	std	r9,TI_LOCAL_FLAGS(r11)
+	ld	r10,_LINK(r1)		/* make idle task do the */
+	std	r10,_NIP(r1)		/* equivalent of a blr */
+	blr
+#endif
+
 	.align	7
 	.globl alignment_common
 alignment_common:
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index e9f321d..d491052 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -50,9 +50,9 @@
 
 	set_thread_flag(TIF_POLLING_NRFLAG);
 	while (1) {
-		ppc64_runlatch_off();
-
 		while (!need_resched() && !cpu_should_die()) {
+			ppc64_runlatch_off();
+
 			if (ppc_md.power_save) {
 				clear_thread_flag(TIF_POLLING_NRFLAG);
 				/*
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 12a4efb..b45fa0e 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -22,8 +22,6 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 
-#undef DEBUG
-
 	.text
 
 /*
@@ -109,12 +107,6 @@
 	dcbf	0,r4
 	dcbf	0,r4
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
-	lis	r6,nap_enter_count@ha
-	lwz	r4,nap_enter_count@l(r6)
-	addi	r4,r4,1
-	stw	r4,nap_enter_count@l(r6)
-#endif	
 2:
 BEGIN_FTR_SECTION
 	/* Go to low speed mode on some 750FX */
@@ -144,48 +136,42 @@
 	DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+	rlwinm	r9,r1,0,0,31-THREAD_SHIFT	/* current thread_info */
+	lwz	r8,TI_LOCAL_FLAGS(r9)	/* set napping bit */
+	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
+	stw	r8,TI_LOCAL_FLAGS(r9)	/* it will return to our caller */
 	mfmsr	r7
 	ori	r7,r7,MSR_EE
 	oris	r7,r7,MSR_POW@h
-	sync
-	isync
+1:	sync
 	mtmsr	r7
 	isync
-	sync
-	blr
-	
+	b	1b
+
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
  * we are called with DR/IR still off and r2 containing physical
- * address of current.
+ * address of current.  R11 points to the exception frame (physical
+ * address).  We have to preserve r10.
  */
 _GLOBAL(power_save_6xx_restore)
-	mfspr	r11,SPRN_HID0
-	rlwinm.	r11,r11,0,10,8	/* Clear NAP & copy NAP bit !state to cr1 EQ */
-	cror	4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
-	rlwinm	r11,r11,0,9,7	/* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-	mtspr	SPRN_HID0, r11
+	lwz	r9,_LINK(r11)		/* interrupted in ppc6xx_idle: */
+	stw	r9,_NIP(r11)		/* make it do a blr */
 
-#ifdef DEBUG
-	beq	cr1,1f
-	lis	r11,(nap_return_count-KERNELBASE)@ha
-	lwz	r9,nap_return_count@l(r11)
-	addi	r9,r9,1
-	stw	r9,nap_return_count@l(r11)
-1:
-#endif
-	
-	rlwinm	r9,r1,0,0,18
-	tophys(r9,r9)
-	lwz	r11,TI_CPU(r9)
+#ifdef CONFIG_SMP
+	mfspr	r12,SPRN_SPRG3
+	lwz	r11,TI_CPU(r12)		/* get cpu number * 4 */
 	slwi	r11,r11,2
+#else
+	li	r11,0
+#endif
 	/* Todo make sure all these are in the same page
-	 * and load r22 (@ha part + CPU offset) only once
+	 * and load r11 (@ha part + CPU offset) only once
 	 */
 BEGIN_FTR_SECTION
-	beq	cr1,1f
+	mfspr	r9,SPRN_HID0
+	andis.	r9,r9,HID0_NAP@h
+	beq	1f
 	addis	r9,r11,(nap_save_msscr0-KERNELBASE)@ha
 	lwz	r9,nap_save_msscr0@l(r9)
 	mtspr	SPRN_MSSCR0, r9
@@ -210,10 +196,3 @@
 
 _GLOBAL(powersave_lowspeed)
 	.long	0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
-	.space	4
-_GLOBAL(nap_return_count)
-	.space	4
-#endif
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 6dad1c0..d85c7c9 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -35,12 +35,16 @@
 	DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+	clrrdi	r9,r1,THREAD_SHIFT	/* current thread_info */
+	ld	r8,TI_LOCAL_FLAGS(r9)	/* set napping bit */
+	ori	r8,r8,_TLF_NAPPING	/* so when we take an exception */
+	std	r8,TI_LOCAL_FLAGS(r9)	/* it will return to our caller */
 	mfmsr	r7
 	ori	r7,r7,MSR_EE
 	oris	r7,r7,MSR_POW@h
-	sync
+1:	sync
 	isync
 	mtmsrd	r7
 	isync
-	sync
-	blr
+	b	1b
+
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d9a7fde..4eba60a 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -61,6 +61,7 @@
 static unsigned long iommu_range_alloc(struct iommu_table *tbl,
                                        unsigned long npages,
                                        unsigned long *handle,
+                                       unsigned long mask,
                                        unsigned int align_order)
 { 
 	unsigned long n, end, i, start;
@@ -97,9 +98,21 @@
 	 */
 	if (start >= limit)
 		start = largealloc ? tbl->it_largehint : tbl->it_hint;
-	
+
  again:
 
+	if (limit + tbl->it_offset > mask) {
+		limit = mask - tbl->it_offset + 1;
+		/* If we're constrained on address range, first try
+		 * at the masked hint to avoid O(n) search complexity,
+		 * but on second pass, start at 0.
+		 */
+		if ((start & mask) >= limit || pass > 0)
+			start = 0;
+		else
+			start &= mask;
+	}
+
 	n = find_next_zero_bit(tbl->it_map, limit, start);
 
 	/* Align allocation */
@@ -150,14 +163,14 @@
 
 static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
 		       unsigned int npages, enum dma_data_direction direction,
-		       unsigned int align_order)
+		       unsigned long mask, unsigned int align_order)
 {
 	unsigned long entry, flags;
 	dma_addr_t ret = DMA_ERROR_CODE;
-	
+
 	spin_lock_irqsave(&(tbl->it_lock), flags);
 
-	entry = iommu_range_alloc(tbl, npages, NULL, align_order);
+	entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
 
 	if (unlikely(entry == DMA_ERROR_CODE)) {
 		spin_unlock_irqrestore(&(tbl->it_lock), flags);
@@ -236,7 +249,7 @@
 
 int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 		struct scatterlist *sglist, int nelems,
-		enum dma_data_direction direction)
+		unsigned long mask, enum dma_data_direction direction)
 {
 	dma_addr_t dma_next = 0, dma_addr;
 	unsigned long flags;
@@ -274,7 +287,7 @@
 		vaddr = (unsigned long)page_address(s->page) + s->offset;
 		npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
 		npages >>= PAGE_SHIFT;
-		entry = iommu_range_alloc(tbl, npages, &handle, 0);
+		entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0);
 
 		DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
 
@@ -479,7 +492,8 @@
  * byte within the page as vaddr.
  */
 dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
-		size_t size, enum dma_data_direction direction)
+		size_t size, unsigned long mask,
+		enum dma_data_direction direction)
 {
 	dma_addr_t dma_handle = DMA_ERROR_CODE;
 	unsigned long uaddr;
@@ -492,7 +506,8 @@
 	npages >>= PAGE_SHIFT;
 
 	if (tbl) {
-		dma_handle = iommu_alloc(tbl, vaddr, npages, direction, 0);
+		dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
+					 mask >> PAGE_SHIFT, 0);
 		if (dma_handle == DMA_ERROR_CODE) {
 			if (printk_ratelimit())  {
 				printk(KERN_INFO "iommu_alloc failed, "
@@ -521,7 +536,7 @@
  * to the dma address (mapping) of the first page.
  */
 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, gfp_t flag)
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
 {
 	void *ret = NULL;
 	dma_addr_t mapping;
@@ -551,7 +566,8 @@
 	memset(ret, 0, size);
 
 	/* Set up tces to cover the allocated range */
-	mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, order);
+	mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL,
+			      mask >> PAGE_SHIFT, order);
 	if (mapping == DMA_ERROR_CODE) {
 		free_pages((unsigned long)ret, order);
 		ret = NULL;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index bb5c950..57d560c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -272,18 +272,26 @@
  * Don't use virtual irqs 0, 1, 2 for devices.
  * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
  * and 2 is the XICS IPI interrupt.
- * We limit virtual irqs to 17 less than NR_IRQS so that when we
- * offset them by 16 (to reserve the first 16 for ISA interrupts)
- * we don't end up with an interrupt number >= NR_IRQS.
+ * We limit virtual irqs to __irq_offet_value less than virt_irq_max so
+ * that when we offset them we don't end up with an interrupt
+ * number >= virt_irq_max.
  */
 #define MIN_VIRT_IRQ	3
-#define MAX_VIRT_IRQ	(NR_IRQS - NUM_ISA_INTERRUPTS - 1)
-#define NR_VIRT_IRQS	(MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
+
+unsigned int virt_irq_max;
+static unsigned int max_virt_irq;
+static unsigned int nr_virt_irqs;
 
 void
 virt_irq_init(void)
 {
 	int i;
+
+	if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
+		virt_irq_max = NR_IRQS - 1;
+	max_virt_irq = virt_irq_max - __irq_offset_value;
+	nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;
+
 	for (i = 0; i < NR_IRQS; i++)
 		virt_irq_to_real_map[i] = UNDEFINED_IRQ;
 }
@@ -308,17 +316,17 @@
 		return real_irq;
 	}
 
-	/* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
+	/* map to a number between MIN_VIRT_IRQ and max_virt_irq */
 	virq = real_irq;
-	if (virq > MAX_VIRT_IRQ)
-		virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+	if (virq > max_virt_irq)
+		virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
 
 	/* search for this number or a free slot */
 	first_virq = virq;
 	while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
 		if (virt_irq_to_real_map[virq] == real_irq)
 			return virq;
-		if (++virq > MAX_VIRT_IRQ)
+		if (++virq > max_virt_irq)
 			virq = MIN_VIRT_IRQ;
 		if (virq == first_virq)
 			goto nospace;	/* oops, no free slots */
@@ -330,8 +338,8 @@
  nospace:
 	if (!warned) {
 		printk(KERN_CRIT "Interrupt table is full\n");
-		printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
-		       "in your kernel sources and rebuild.\n", NR_IRQS);
+		printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
+		       "in your kernel sources and rebuild.\n", virt_irq_max);
 		warned = 1;
 	}
 	return NO_IRQ;
@@ -349,8 +357,8 @@
 
 	virq = real_irq;
 
-	if (virq > MAX_VIRT_IRQ)
-		virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+	if (virq > max_virt_irq)
+		virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
 
 	first_virq = virq;
 
@@ -360,7 +368,7 @@
 
 		virq++;
 
-		if (virq >= MAX_VIRT_IRQ)
+		if (virq >= max_virt_irq)
 			virq = 0;
 
 	} while (first_virq != virq);
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ad7a902..856ef1a 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -88,7 +88,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
 	kprobe_opcode_t insn = *p->ainsn.insn;
 
@@ -101,21 +101,21 @@
 		regs->nip = (unsigned long)p->ainsn.insn;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
 	kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 	kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -141,7 +141,7 @@
 	}
 }
 
-static inline int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
 	int ret = 0;
@@ -334,7 +334,7 @@
 		regs->nip = (unsigned long)p->addr + 4;
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -370,7 +370,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 1b73508..2cbde86 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -37,7 +37,7 @@
 #include <asm/prom.h>
 #include <asm/vdso_datapage.h>
 
-#define MODULE_VERS "1.6"
+#define MODULE_VERS "1.7"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
@@ -149,17 +149,17 @@
 	if (rc == 0)		/* success, return */
 		return;
 /* check for null tag ? */
-	if (rc == H_Hardware)
+	if (rc == H_HARDWARE)
 		printk(KERN_INFO
 		       "plpar-hcall (%s) failed with hardware fault\n", tag);
-	else if (rc == H_Function)
+	else if (rc == H_FUNCTION)
 		printk(KERN_INFO
 		       "plpar-hcall (%s) failed; function not allowed\n", tag);
-	else if (rc == H_Authority)
+	else if (rc == H_AUTHORITY)
 		printk(KERN_INFO
-		       "plpar-hcall (%s) failed; not authorized to this function\n",
-		       tag);
-	else if (rc == H_Parameter)
+		       "plpar-hcall (%s) failed; not authorized to this"
+		       " function\n", tag);
+	else if (rc == H_PARAMETER)
 		printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
 		       tag);
 	else
@@ -209,7 +209,7 @@
 	unsigned long dummy;
 	rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
 
-	if (rc != H_Authority)
+	if (rc != H_AUTHORITY)
 		log_plpar_hcall_return(rc, "H_PIC");
 }
 
@@ -242,7 +242,7 @@
 {
 	int call_status;
 
-	char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+	unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
 	if (!local_buffer) {
 		printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
 		       __FILE__, __FUNCTION__, __LINE__);
@@ -254,7 +254,8 @@
 	call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
 				NULL,
 				SPLPAR_CHARACTERISTICS_TOKEN,
-				__pa(rtas_data_buf));
+				__pa(rtas_data_buf),
+				RTAS_DATA_BUF_SIZE);
 	memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
 	spin_unlock(&rtas_data_buf_lock);
 
@@ -275,7 +276,7 @@
 #ifdef LPARCFG_DEBUG
 		printk(KERN_INFO "success calling get-system-parameter \n");
 #endif
-		splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
+		splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
 		local_buffer += 2;	/* step over strlen value */
 
 		memset(workbuffer, 0, SPLPAR_MAXLENGTH);
@@ -529,13 +530,13 @@
 	retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
 				    *new_weight_ptr);
 
-	if (retval == H_Success || retval == H_Constrained) {
+	if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
 		retval = count;
-	} else if (retval == H_Busy) {
+	} else if (retval == H_BUSY) {
 		retval = -EBUSY;
-	} else if (retval == H_Hardware) {
+	} else if (retval == H_HARDWARE) {
 		retval = -EIO;
-	} else if (retval == H_Parameter) {
+	} else if (retval == H_PARAMETER) {
 		retval = -EINVAL;
 	} else {
 		printk(KERN_WARNING "%s: received unknown hv return code %ld",
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c336f3e..c1d95e1 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -59,6 +59,25 @@
 }
 
 
+static inline unsigned long device_to_mask(struct device *hwdev)
+{
+	struct pci_dev *pdev;
+
+	if (!hwdev) {
+		pdev = ppc64_isabridge_dev;
+		if (!pdev) /* This is the best guess we can do */
+			return 0xfffffffful;
+	} else
+		pdev = to_pci_dev(hwdev);
+
+	if (pdev->dma_mask)
+		return pdev->dma_mask;
+
+	/* Assume devices without mask can take 32 bit addresses */
+	return 0xfffffffful;
+}
+
+
 /* Allocates a contiguous real buffer and creates mappings over it.
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
@@ -67,7 +86,7 @@
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
-			flag);
+			device_to_mask(hwdev), flag);
 }
 
 static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
@@ -85,7 +104,8 @@
 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
+	return iommu_map_single(devnode_table(hwdev), vaddr, size,
+			        device_to_mask(hwdev), direction);
 }
 
 
@@ -100,7 +120,7 @@
 		int nelems, enum dma_data_direction direction)
 {
 	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
-			nelems, direction);
+			nelems, device_to_mask(pdev), direction);
 }
 
 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
@@ -112,7 +132,19 @@
 /* We support DMA to/from any memory page via the iommu */
 static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	return 1;
+	struct iommu_table *tbl = devnode_table(dev);
+
+	if (!tbl || tbl->it_offset > mask) {
+		printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
+		if (tbl)
+			printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
+				mask, tbl->it_offset);
+		else
+			printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+				mask);
+		return 0;
+	} else
+		return 1;
 }
 
 void pci_iommu_init(void)
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dfa5398..4b052ae 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -81,6 +81,7 @@
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4336390..1cb69e8 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -62,7 +62,7 @@
 static int __initdata dt_root_size_cells;
 
 #ifdef CONFIG_PPC64
-static int __initdata iommu_is_off;
+int __initdata iommu_is_off;
 int __initdata iommu_force_on;
 unsigned long tce_alloc_start, tce_alloc_end;
 #endif
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index d66c5e7..7e4d548 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1528,12 +1528,11 @@
 	 *    non-IBM designs !
 	 *  - it has /rtas
 	 */
-	len = prom_getprop(_prom->root, "model",
+	len = prom_getprop(_prom->root, "device_type",
 			   compat, sizeof(compat)-1);
 	if (len <= 0)
 		return PLATFORM_GENERIC;
-	compat[len] = 0;
-	if (strcmp(compat, "chrp"))
+	if (strncmp(compat, RELOC("chrp"), 4))
 		return PLATFORM_GENERIC;
 
 	/* Default to pSeries. We need to know if we are running LPAR */
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 456286c..9c9ad1f 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -258,11 +258,11 @@
 	struct proc_dir_entry *entry;
 
 	if (!machine_is(pseries))
-		return 1;
+		return -ENODEV;
 
 	rtas_node = of_find_node_by_name(NULL, "rtas");
 	if (rtas_node == NULL)
-		return 1;
+		return -ENODEV;
 
 	entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
 	if (entry)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 06636c9..0112318 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -578,18 +578,18 @@
 	 * We use "waiting" to indicate our state.  As long
 	 * as it is >0, we are still trying to all join up.
 	 * If it goes to 0, we have successfully joined up and
-	 * one thread got H_Continue.  If any error happens,
+	 * one thread got H_CONTINUE.  If any error happens,
 	 * we set it to <0.
 	 */
 	local_irq_save(flags);
 	do {
 		rc = plpar_hcall_norets(H_JOIN);
 		smp_rmb();
-	} while (rc == H_Success && data->waiting > 0);
-	if (rc == H_Success)
+	} while (rc == H_SUCCESS && data->waiting > 0);
+	if (rc == H_SUCCESS)
 		goto out;
 
-	if (rc == H_Continue) {
+	if (rc == H_CONTINUE) {
 		data->waiting = 0;
 		data->args->args[data->args->nargs] =
 			rtas_call(ibm_suspend_me_token, 0, 1, NULL);
@@ -597,7 +597,7 @@
 			plpar_hcall_norets(H_PROD,i);
 	} else {
 		data->waiting = -EBUSY;
-		printk(KERN_ERR "Error on H_Join hypervisor call\n");
+		printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
 	}
 
 out:
@@ -624,7 +624,7 @@
 		printk(KERN_ERR "Error doing global join\n");
 
 	/* Prod each CPU.  This won't hurt, and will wake
-	 * anyone we successfully put to sleep with H_Join
+	 * anyone we successfully put to sleep with H_JOIN.
 	 */
 	for_each_possible_cpu(i)
 		plpar_hcall_norets(H_PROD, i);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a72bf5d..69ac257 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -50,7 +50,6 @@
 #include <asm/kgdb.h>
 #endif
 
-extern void platform_init(void);
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
 boot_infos_t *boot_infos;
@@ -138,12 +137,7 @@
 		strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
 #endif /* CONFIG_CMDLINE */
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 	probe_machine();
-#else
-	/* Base init based on machine type. Obsoloete, please kill ! */
-	platform_init();
-#endif
 
 #ifdef CONFIG_6xx
 	if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 59aa92c..13e91c4 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -215,12 +215,10 @@
 	/*
 	 * Initialize stab / SLB management except on iSeries
 	 */
-	if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
-		if (cpu_has_feature(CPU_FTR_SLB))
-			slb_initialize();
-		else
-			stab_initialize(get_paca()->stab_real);
-	}
+	if (cpu_has_feature(CPU_FTR_SLB))
+		slb_initialize();
+	else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+		stab_initialize(get_paca()->stab_real);
 
 	DBG(" <- early_setup()\n");
 }
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 73560ef..ed737ca 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -279,7 +279,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+static int sysfs_cpu_notify(struct notifier_block *self,
 				      unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,7 +297,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata sysfs_cpu_nb = {
+static struct notifier_block sysfs_cpu_nb = {
 	.notifier_call	= sysfs_cpu_notify,
 };
 
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 1ad55f0..0b98eea 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -322,3 +322,11 @@
 COMPAT_SYS(pselect6)
 COMPAT_SYS(ppoll)
 SYSCALL(unshare)
+SYSCALL(splice)
+SYSCALL(tee)
+SYSCALL(vmsplice)
+
+/*
+ * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
+ * as well when appropriate.
+ */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 4cbde21..064a525 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -228,7 +228,7 @@
  */
 static inline int check_io_access(struct pt_regs *regs)
 {
-#ifdef CONFIG_PPC_PMAC
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
 	unsigned long msr = regs->msr;
 	const struct exception_table_entry *entry;
 	unsigned int *nip = (unsigned int *)regs->nip;
@@ -261,7 +261,7 @@
 			return 1;
 		}
 	}
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
 	return 0;
 }
 
@@ -308,8 +308,8 @@
 
 void machine_check_exception(struct pt_regs *regs)
 {
-#ifdef CONFIG_PPC64
 	int recover = 0;
+	unsigned long reason = get_mc_reason(regs);
 
 	/* See if any machine dependent calls */
 	if (ppc_md.machine_check_exception)
@@ -317,8 +317,6 @@
 
 	if (recover)
 		return;
-#else
-	unsigned long reason = get_mc_reason(regs);
 
 	if (user_mode(regs)) {
 		regs->msr |= MSR_RI;
@@ -462,7 +460,6 @@
 	 * additional info, e.g. bus error registers.
 	 */
 	platform_machine_check(regs);
-#endif /* CONFIG_PPC64 */
 
 	if (debugger_fault_handler(regs))
 		return;
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 13c655b..971020c 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -202,7 +202,7 @@
 			  size_t size, enum dma_data_direction direction)
 {
 	return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
-			direction);
+			~0ul, direction);
 }
 
 static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
@@ -216,7 +216,7 @@
 		int nelems, enum dma_data_direction direction)
 {
 	return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
-			nelems, direction);
+			nelems, ~0ul, direction);
 }
 
 static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
@@ -229,7 +229,7 @@
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
-			dma_handle, flag);
+			dma_handle, ~0ul, flag);
 }
 
 static void vio_free_coherent(struct device *dev, size_t size,
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 5aea090..fdbba42 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -177,15 +177,15 @@
 
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
-	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
-	 * erroneous fault occuring in a code path which already holds mmap_sem
+	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+	 * erroneous fault occurring in a code path which already holds mmap_sem
 	 * we will deadlock attempting to validate the fault against the
 	 * address space.  Luckily the kernel only validly references user
 	 * space from well defined areas of code, which are listed in the
 	 * exceptions table.
 	 *
 	 * As the vast majority of faults will be valid we will only perform
-	 * the source reference check when there is a possibilty of a deadlock.
+	 * the source reference check when there is a possibility of a deadlock.
 	 * Attempt to lock the address space, if we cannot we then validate the
 	 * source.  If this is invalid we can skip the address space check,
 	 * thus avoiding the deadlock.
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 7c18b4c..7e789d2 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -158,25 +158,25 @@
 late_initcall(mpc834x_rtc_hookup);
 #endif
 
-void __init platform_init(void)
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc834x_sys_probe(void)
 {
-	/* setup the PowerPC module struct */
-	ppc_md.setup_arch = mpc834x_sys_setup_arch;
-
-	ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
-	ppc_md.get_irq = ipic_get_irq;
-
-	ppc_md.restart = mpc83xx_restart;
-
-	ppc_md.time_init = mpc83xx_time_init;
-	ppc_md.set_rtc_time = NULL;
-	ppc_md.get_rtc_time = NULL;
-	ppc_md.calibrate_decr = generic_calibrate_decr;
-
-	ppc_md.progress = udbg_progress;
-
-	if (ppc_md.progress)
-		ppc_md.progress("mpc834x_sys_init(): exit", 0);
-
-	return;
+	/* We always match for now, eventually we should look at the flat
+	   dev tree to ensure this is the board we are suppose to run on
+	*/
+	return 1;
 }
+
+define_machine(mpc834x_sys) {
+	.name			= "MPC834x SYS",
+	.probe			= mpc834x_sys_probe,
+	.setup_arch		= mpc834x_sys_setup_arch,
+	.init_IRQ		= mpc834x_sys_init_IRQ,
+	.get_irq		= ipic_get_irq,
+	.restart		= mpc83xx_restart,
+	.time_init		= mpc83xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index b7821db..5eeff37 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -220,25 +220,25 @@
 	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 }
 
-void __init platform_init(void)
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_ads_probe(void)
 {
-	ppc_md.setup_arch = mpc85xx_ads_setup_arch;
-	ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
-
-	ppc_md.init_IRQ = mpc85xx_ads_pic_init;
-	ppc_md.get_irq = mpic_get_irq;
-
-	ppc_md.restart = mpc85xx_restart;
-	ppc_md.power_off = NULL;
-	ppc_md.halt = NULL;
-
-	ppc_md.time_init = NULL;
-	ppc_md.set_rtc_time = NULL;
-	ppc_md.get_rtc_time = NULL;
-	ppc_md.calibrate_decr = generic_calibrate_decr;
-
-	ppc_md.progress = udbg_progress;
-
-	if (ppc_md.progress)
-		ppc_md.progress("mpc85xx_ads platform_init(): exit", 0);
+	/* We always match for now, eventually we should look at the flat
+	   dev tree to ensure this is the board we are suppose to run on
+	*/
+	return 1;
 }
+
+define_machine(mpc85xx_ads) {
+	.name			= "MPC85xx ADS",
+	.probe			= mpc85xx_ads_probe,
+	.setup_arch		= mpc85xx_ads_setup_arch,
+	.init_IRQ		= mpc85xx_ads_pic_init,
+	.show_cpuinfo		= mpc85xx_ads_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= mpc85xx_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index 3a4245c..b283380 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -316,17 +316,18 @@
 	[__NR_pselect6]			sys_ni_syscall, /* sys_pselect */
 	[__NR_ppoll]			sys_ni_syscall, /* sys_ppoll */
 	[__NR_unshare]			sys_unshare,
+	[__NR_splice]			sys_splice,
+	[__NR_tee]			sys_tee,
+	[__NR_vmsplice]			sys_vmsplice,
 };
 
 long spu_sys_callback(struct spu_syscall_block *s)
 {
 	long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
 
-	BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls);
-
 	syscall = spu_syscall_table[s->nr_ret];
 
-	if (s->nr_ret >= __NR_syscalls) {
+	if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
 		pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret);
 		return -ENOSYS;
 	}
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index c04e078..483c8b7 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -2,6 +2,7 @@
 #include <linux/ptrace.h>
 
 #include <asm/spu.h>
+#include <asm/unistd.h>
 
 #include "spufs.h"
 
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 97898d5..1726bfe 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -1297,7 +1297,7 @@
 		cycles_t resume_time = get_cycles();
 		cycles_t delta_time = resume_time - csa->suspend_time;
 
-		csa->lscsa->decr.slot[0] = delta_time;
+		csa->lscsa->decr.slot[0] -= delta_time;
 	}
 }
 
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h
index 63f0aee..996c287 100644
--- a/arch/powerpc/platforms/chrp/chrp.h
+++ b/arch/powerpc/platforms/chrp/chrp.h
@@ -9,3 +9,4 @@
 
 extern void chrp_find_bridges(void);
 extern void chrp_event_scan(unsigned long);
+extern void chrp_pcibios_fixup(void);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 8ef279a..ac22487 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -23,6 +23,8 @@
 #include <asm/grackle.h>
 #include <asm/rtas.h>
 
+#include "chrp.h"
+
 /* LongTrail */
 void __iomem *gg2_pci_config_base;
 
@@ -314,6 +316,6 @@
 	}
 
 	/* Do not fixup interrupts from OF tree on pegasos */
-	if (is_pegasos == 0)
-		ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+	if (is_pegasos)
+		ppc_md.pcibios_fixup = NULL;
 }
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 23a2017..18d89f3 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -440,8 +440,6 @@
 
 	if (_chrp_type == _CHRP_Pegasos)
 		ppc_md.get_irq        = i8259_irq;
-	else
-		ppc_md.get_irq        = mpic_get_irq;
 
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	/* see if there is a keyboard in the device tree
@@ -528,26 +526,24 @@
 	/* Assume we have an 8259... */
 	__irq_offset_value = NUM_ISA_INTERRUPTS;
 
-	ppc_md.setup_arch     = chrp_setup_arch;
-	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
-
-	ppc_md.init_IRQ       = chrp_init_IRQ;
-	ppc_md.init           = chrp_init2;
-
-	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
-	ppc_md.restart        = rtas_restart;
-	ppc_md.power_off      = rtas_power_off;
-	ppc_md.halt           = rtas_halt;
-
-	ppc_md.time_init      = chrp_time_init;
-	ppc_md.calibrate_decr = generic_calibrate_decr;
-
-	/* this may get overridden with rtas routines later... */
-	ppc_md.set_rtc_time   = chrp_set_rtc_time;
-	ppc_md.get_rtc_time   = chrp_get_rtc_time;
-
-#ifdef CONFIG_SMP
-	smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
+	return 1;
 }
+
+define_machine(chrp) {
+	.name			= "CHRP",
+	.probe			= chrp_probe,
+	.setup_arch		= chrp_setup_arch,
+	.init			= chrp_init2,
+	.show_cpuinfo		= chrp_show_cpuinfo,
+	.init_IRQ		= chrp_init_IRQ,
+	.get_irq		= mpic_get_irq,
+	.pcibios_fixup		= chrp_pcibios_fixup,
+	.restart		= rtas_restart,
+	.power_off		= rtas_power_off,
+	.halt			= rtas_halt,
+	.time_init		= chrp_time_init,
+	.set_rtc_time		= chrp_set_rtc_time,
+	.get_rtc_time		= chrp_get_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.phys_mem_access_prot	= pci_phys_mem_access_prot,
+};
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 6ce8a40..a6fd9be 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -54,6 +54,7 @@
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/lpar_map.h>
 #include <asm/udbg.h>
+#include <asm/irq.h>
 
 #include "naca.h"
 #include "setup.h"
@@ -684,6 +685,12 @@
 	powerpc_firmware_features |= FW_FEATURE_ISERIES;
 	powerpc_firmware_features |= FW_FEATURE_LPAR;
 
+	/*
+	 * The Hypervisor only allows us up to 256 interrupt
+	 * sources (the irq number is passed in a u8).
+	 */
+	virt_irq_max = 255;
+
 	return 1;
 }
 
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index e14f9ac..df2343e 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -231,6 +231,14 @@
 	return isr;
 }
 
+static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result)
+{
+	kw_write_reg(reg_control, KW_I2C_CTL_STOP);
+	host->state = state_stop;
+	host->result = result;
+}
+
+
 static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
 {
 	u8 ack;
@@ -246,42 +254,36 @@
 	}
 
 	if (isr == 0) {
+		printk(KERN_WARNING "low_i2c: Timeout in i2c transfer"
+		       " on keywest !\n");
 		if (host->state != state_stop) {
-			DBG_LOW("KW: Timeout !\n");
-			host->result = -EIO;
-			goto stop;
+			kw_i2c_do_stop(host, -EIO);
+			return;
 		}
-		if (host->state == state_stop) {
-			ack = kw_read_reg(reg_status);
-			if (ack & KW_I2C_STAT_BUSY)
-				kw_write_reg(reg_status, 0);
-			host->state = state_idle;
-			kw_write_reg(reg_ier, 0x00);
-			if (!host->polled)
-				complete(&host->complete);
-		}
+		ack = kw_read_reg(reg_status);
+		if (ack & KW_I2C_STAT_BUSY)
+			kw_write_reg(reg_status, 0);
+		host->state = state_idle;
+		kw_write_reg(reg_ier, 0x00);
+		if (!host->polled)
+			complete(&host->complete);
 		return;
 	}
 
 	if (isr & KW_I2C_IRQ_ADDR) {
 		ack = kw_read_reg(reg_status);
 		if (host->state != state_addr) {
-			kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
 			WRONG_STATE("KW_I2C_IRQ_ADDR"); 
-			host->result = -EIO;
-			goto stop;
+			kw_i2c_do_stop(host, -EIO);
 		}
 		if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
-			host->result = -ENODEV;
-			DBG_LOW("KW: NAK on address\n");
+			host->result = -ENXIO;
 			host->state = state_stop;
-			return;
+			DBG_LOW("KW: NAK on address\n");
 		} else {
-			if (host->len == 0) {
-				kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
-				goto stop;
-			}
-			if (host->rw) {
+			if (host->len == 0)
+				kw_i2c_do_stop(host, 0);
+			else if (host->rw) {
 				host->state = state_read;
 				if (host->len > 1)
 					kw_write_reg(reg_control,
@@ -308,25 +310,19 @@
 			ack = kw_read_reg(reg_status);
 			if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
 				DBG_LOW("KW: nack on data write\n");
-				host->result = -EIO;
-				goto stop;
+				host->result = -EFBIG;
+				host->state = state_stop;
 			} else if (host->len) {
 				kw_write_reg(reg_data, *(host->data++));
 				host->len--;
-			} else {
-				kw_write_reg(reg_control, KW_I2C_CTL_STOP);
-				host->state = state_stop;
-				host->result = 0;
-			}
-			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
+			} else
+				kw_i2c_do_stop(host, 0);
 		} else {
-			kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
 			WRONG_STATE("KW_I2C_IRQ_DATA"); 
-			if (host->state != state_stop) {
-				host->result = -EIO;
-				goto stop;
-			}
+			if (host->state != state_stop)
+				kw_i2c_do_stop(host, -EIO);
 		}
+		kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
 	}
 
 	if (isr & KW_I2C_IRQ_STOP) {
@@ -340,14 +336,10 @@
 			complete(&host->complete);
 	}
 
+	/* Below should only happen in manual mode which we don't use ... */
 	if (isr & KW_I2C_IRQ_START)
 		kw_write_reg(reg_isr, KW_I2C_IRQ_START);
 
-	return;
- stop:
-	kw_write_reg(reg_control, KW_I2C_CTL_STOP);	
-	host->state = state_stop;
-	return;
 }
 
 /* Interrupt handler */
@@ -544,11 +536,11 @@
 		return NULL;
 	}
 
-	/* Make sure IRA is disabled */
+	/* Make sure IRQ is disabled */
 	kw_write_reg(reg_ier, 0);
 
 	/* Request chip interrupt */
-	if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host))
+	if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host))
 		host->irq = NO_IRQ;
 
 	printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f5d8d15..ea179af 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1097,7 +1097,7 @@
 	 * (iBook second controller)
 	 */
 	if (dev->vendor == PCI_VENDOR_ID_APPLE
-	    && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
+	    && dev->class == PCI_CLASS_SERIAL_USB_OHCI
 	    && !node) {
 		printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
 		       pci_name(dev));
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9b2b1cb..32eaddf 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -865,7 +865,7 @@
  * on the CEC architecture, type of the device, on earlier boot
  * command-line arguments & etc.
  */
-void eeh_add_device_early(struct device_node *dn)
+static void eeh_add_device_early(struct device_node *dn)
 {
 	struct pci_controller *phb;
 	struct eeh_early_enable_info info;
@@ -882,7 +882,6 @@
 	info.buid_lo = BUID_LO(phb->buid);
 	early_enable_eeh(dn, &info);
 }
-EXPORT_SYMBOL_GPL(eeh_add_device_early);
 
 void eeh_add_device_tree_early(struct device_node *dn)
 {
@@ -893,20 +892,6 @@
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
 
-void eeh_add_device_tree_late(struct pci_bus *bus)
-{
-	struct pci_dev *dev;
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
- 		eeh_add_device_late(dev);
- 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- 			struct pci_bus *subbus = dev->subordinate;
- 			if (subbus)
- 				eeh_add_device_tree_late(subbus);
- 		}
-	}
-}
-
 /**
  * eeh_add_device_late - perform EEH initialization for the indicated pci device
  * @dev: pci device for which to set up EEH
@@ -914,7 +899,7 @@
  * This routine must be used to complete EEH initialization for PCI
  * devices that were added after system boot (e.g. hotplug, dlpar).
  */
-void eeh_add_device_late(struct pci_dev *dev)
+static void eeh_add_device_late(struct pci_dev *dev)
 {
 	struct device_node *dn;
 	struct pci_dn *pdn;
@@ -933,16 +918,33 @@
 
 	pci_addr_cache_insert_device (dev);
 }
-EXPORT_SYMBOL_GPL(eeh_add_device_late);
+
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+ 		eeh_add_device_late(dev);
+ 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ 			struct pci_bus *subbus = dev->subordinate;
+ 			if (subbus)
+ 				eeh_add_device_tree_late(subbus);
+ 		}
+	}
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 
 /**
  * eeh_remove_device - undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
  *
- * This routine should be when a device is removed from a running
- * system (e.g. by hotplug or dlpar).
+ * This routine should be called when a device is removed from
+ * a running system (e.g. by hotplug or dlpar).  It unregisters
+ * the PCI device from the EEH subsystem.  I/O errors affecting
+ * this device will no longer be detected after this call; thus,
+ * i/o errors affecting this slot may leave this device unusable.
  */
-void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev)
 {
 	struct device_node *dn;
 	if (!dev || !eeh_subsystem_enabled)
@@ -955,24 +957,22 @@
 	pci_addr_cache_remove_device(dev);
 
 	dn = pci_device_to_OF_node(dev);
-	PCI_DN(dn)->pcidev = NULL;
-	pci_dev_put (dev);
+	if (PCI_DN(dn)->pcidev) {
+		PCI_DN(dn)->pcidev = NULL;
+		pci_dev_put (dev);
+	}
 }
-EXPORT_SYMBOL_GPL(eeh_remove_device);
 
 void eeh_remove_bus_device(struct pci_dev *dev)
 {
+	struct pci_bus *bus = dev->subordinate;
+	struct pci_dev *child, *tmp;
+
 	eeh_remove_device(dev);
-	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		struct pci_bus *bus = dev->subordinate;
-		struct list_head *ln;
-		if (!bus)
-			return; 
-		for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-			struct pci_dev *pdev = pci_dev_b(ln);
-			if (pdev)
-				eeh_remove_bus_device(pdev);
-		}
+
+	if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+			 eeh_remove_bus_device(child);
 	}
 }
 EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index cc2495a..1fba695 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -293,15 +293,16 @@
 	frozen_pdn = PCI_DN(frozen_dn);
 	frozen_pdn->eeh_freeze_count++;
 
-	pci_str = pci_name (frozen_pdn->pcidev);
-	drv_str = pcid_name (frozen_pdn->pcidev);
-	if (!pci_str) {
+	if (frozen_pdn->pcidev) {
+		pci_str = pci_name (frozen_pdn->pcidev);
+		drv_str = pcid_name (frozen_pdn->pcidev);
+	} else {
 		pci_str = pci_name (event->dev);
 		drv_str = pcid_name (event->dev);
 	}
 	
 	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
-		goto hard_fail;
+		goto excess_failures;
 
 	/* If the reset state is a '5' and the time to reset is 0 (infinity)
 	 * or is more then 15 seconds, then mark this as a permanent failure.
@@ -356,7 +357,7 @@
 
 	return;
 	
-hard_fail:
+excess_failures:
 	/*
 	 * About 90% of all real-life EEH failures in the field
 	 * are due to poorly seated PCI cards. Only 10% or so are
@@ -367,7 +368,15 @@
 	   "and has been permanently disabled.  Please try reseating\n"
 	   "this device or replacing it.\n",
 		drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+	goto perm_error;
 
+hard_fail:
+	printk(KERN_ERR
+	   "EEH: Unable to recover from failure of PCI device %s - %s\n"
+	   "Please try reseating this device or replacing it.\n",
+		drv_str, pci_str);
+
+perm_error:
 	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
 
 	/* Notify all devices that they're about to go down. */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 9a9961f..a1bda6f 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -19,7 +19,9 @@
  */
 
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include <asm/eeh_event.h>
 #include <asm/ppc-pci.h>
 
@@ -37,14 +39,18 @@
 static void eeh_thread_launcher(void *);
 DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
 
+/* Serialize reset sequences for a given pci device */
+DEFINE_MUTEX(eeh_event_mutex);
+
 /**
- * eeh_event_handler - dispatch EEH events.  The detection of a frozen
- * slot can occur inside an interrupt, where it can be hard to do
- * anything about it.  The goal of this routine is to pull these
- * detection events out of the context of the interrupt handler, and
- * re-dispatch them for processing at a later time in a normal context.
- *
+ * eeh_event_handler - dispatch EEH events.
  * @dummy - unused
+ *
+ * The detection of a frozen slot can occur inside an interrupt,
+ * where it can be hard to do anything about it.  The goal of this
+ * routine is to pull these detection events out of the context
+ * of the interrupt handler, and re-dispatch them for processing
+ * at a later time in a normal context.
  */
 static int eeh_event_handler(void * dummy)
 {
@@ -64,23 +70,24 @@
 			event = list_entry(eeh_eventlist.next, struct eeh_event, list);
 			list_del(&event->list);
 		}
-		
-		if (event)
-			eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
-
 		spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+
 		if (event == NULL)
 			break;
 
+		/* Serialize processing of EEH events */
+		mutex_lock(&eeh_event_mutex);
+		eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
 		printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
 		       pci_name(event->dev));
 
 		handle_eeh_events(event);
 
 		eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-
 		pci_dev_put(event->dev);
 		kfree(event);
+		mutex_unlock(&eeh_event_mutex);
 	}
 
 	return 0;
@@ -88,7 +95,6 @@
 
 /**
  * eeh_thread_launcher
- *
  * @dummy - unused
  */
 static void eeh_thread_launcher(void *dummy)
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index db7c19f..c9ff547 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -127,3 +127,103 @@
 
 	mtcrf	0xff,r0
 	blr				/* return r3 = status */
+
+/* plpar_hcall_7arg_7ret(unsigned long opcode,		R3
+			 unsigned long arg1,		R4
+			 unsigned long arg2,		R5
+			 unsigned long arg3,		R6
+			 unsigned long arg4,		R7
+			 unsigned long arg5,		R8
+			 unsigned long arg6,		R9
+			 unsigned long arg7,		R10
+			 unsigned long *out1,		112(R1)
+			 unsigned long *out2,		110(R1)
+			 unsigned long *out3,		108(R1)
+			 unsigned long *out4,		106(R1)
+			 unsigned long *out5,		104(R1)
+			 unsigned long *out6,		102(R1)
+			 unsigned long *out7);		100(R1)
+*/
+_GLOBAL(plpar_hcall_7arg_7ret)
+	HMT_MEDIUM
+
+	mfcr	r0
+	stw	r0,8(r1)
+
+	HVSC				/* invoke the hypervisor */
+
+	lwz	r0,8(r1)
+
+	ld	r11,STK_PARM(r11)(r1)	/* Fetch r4 ret arg */
+	std	r4,0(r11)
+	ld	r11,STK_PARM(r12)(r1)	/* Fetch r5 ret arg */
+	std	r5,0(r11)
+	ld	r11,STK_PARM(r13)(r1)	/* Fetch r6 ret arg */
+	std	r6,0(r11)
+	ld	r11,STK_PARM(r14)(r1)	/* Fetch r7 ret arg */
+	std	r7,0(r11)
+	ld	r11,STK_PARM(r15)(r1)	/* Fetch r8 ret arg */
+	std	r8,0(r11)
+	ld	r11,STK_PARM(r16)(r1)	/* Fetch r9 ret arg */
+	std	r9,0(r11)
+	ld	r11,STK_PARM(r17)(r1)	/* Fetch r10 ret arg */
+	std	r10,0(r11)
+
+	mtcrf	0xff,r0
+
+	blr				/* return r3 = status */
+
+/* plpar_hcall_9arg_9ret(unsigned long opcode,		R3
+			 unsigned long arg1,		R4
+			 unsigned long arg2,		R5
+			 unsigned long arg3,		R6
+			 unsigned long arg4,		R7
+			 unsigned long arg5,		R8
+			 unsigned long arg6,		R9
+			 unsigned long arg7,		R10
+			 unsigned long arg8,		112(R1)
+			 unsigned long arg9,		110(R1)
+			 unsigned long *out1,		108(R1)
+			 unsigned long *out2,		106(R1)
+			 unsigned long *out3,		104(R1)
+			 unsigned long *out4,		102(R1)
+			 unsigned long *out5,		100(R1)
+			 unsigned long *out6,		 98(R1)
+			 unsigned long *out7);		 96(R1)
+			 unsigned long *out8,		 94(R1)
+		         unsigned long *out9,            92(R1)
+*/
+_GLOBAL(plpar_hcall_9arg_9ret)
+	HMT_MEDIUM
+
+	mfcr	r0
+	stw	r0,8(r1)
+
+	ld	r11,STK_PARM(r11)(r1)	 /* put arg8 in R11 */
+	ld	r12,STK_PARM(r12)(r1)    /* put arg9 in R12 */
+
+	HVSC				/* invoke the hypervisor */
+
+	ld	r0,STK_PARM(r13)(r1)	/* Fetch r4 ret arg */
+	stdx	r4,r0,r0
+	ld	r0,STK_PARM(r14)(r1)	/* Fetch r5 ret arg */
+	stdx	r5,r0,r0
+	ld	r0,STK_PARM(r15)(r1)	/* Fetch r6 ret arg */
+	stdx	r6,r0,r0
+	ld	r0,STK_PARM(r16)(r1)	/* Fetch r7 ret arg */
+	stdx	r7,r0,r0
+	ld	r0,STK_PARM(r17)(r1)	/* Fetch r8 ret arg */
+	stdx	r8,r0,r0
+	ld	r0,STK_PARM(r18)(r1)	/* Fetch r9 ret arg */
+	stdx	r9,r0,r0
+	ld	r0,STK_PARM(r19)(r1)	/* Fetch r10 ret arg */
+	stdx	r10,r0,r0
+	ld	r0,STK_PARM(r20)(r1)	/* Fetch r11 ret arg */
+	stdx	r11,r0,r0
+	ld	r0,STK_PARM(r21)(r1)	/* Fetch r12 ret arg */
+	stdx	r12,r0,r0
+
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+
+	blr				/* return r3 = status */
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index ba6befd..a72a987 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -41,7 +41,7 @@
 	unsigned long got;
 
 	if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
-		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
+		(unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
 		return got;
 	return 0;
 }
@@ -69,9 +69,9 @@
 
 	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
 				 lbuf[1]);
-	if (ret == H_Success)
+	if (ret == H_SUCCESS)
 		return count;
-	if (ret == H_Busy)
+	if (ret == H_BUSY)
 		return 0;
 	return -EIO;
 }
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 22bfb5c..fcf4b4c 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -43,21 +43,21 @@
 static int hvcs_convert(long to_convert)
 {
 	switch (to_convert) {
-		case H_Success:
+		case H_SUCCESS:
 			return 0;
-		case H_Parameter:
+		case H_PARAMETER:
 			return -EINVAL;
-		case H_Hardware:
+		case H_HARDWARE:
 			return -EIO;
-		case H_Busy:
-		case H_LongBusyOrder1msec:
-		case H_LongBusyOrder10msec:
-		case H_LongBusyOrder100msec:
-		case H_LongBusyOrder1sec:
-		case H_LongBusyOrder10sec:
-		case H_LongBusyOrder100sec:
+		case H_BUSY:
+		case H_LONG_BUSY_ORDER_1_MSEC:
+		case H_LONG_BUSY_ORDER_10_MSEC:
+		case H_LONG_BUSY_ORDER_100_MSEC:
+		case H_LONG_BUSY_ORDER_1_SEC:
+		case H_LONG_BUSY_ORDER_10_SEC:
+		case H_LONG_BUSY_ORDER_100_SEC:
 			return -EBUSY;
-		case H_Function: /* fall through */
+		case H_FUNCTION: /* fall through */
 		default:
 			return -EPERM;
 	}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 8952528..634b7d0 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -54,7 +54,8 @@
 EXPORT_SYMBOL(plpar_hcall_4out);
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-
+EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
+EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
 extern void pSeries_find_serial_port(void);
 
 
@@ -72,7 +73,7 @@
 
 	do {
 		rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
-	} while (rc == H_Busy);
+	} while (rc == H_BUSY);
 }
 
 static long hvsi_udbg_buf_len;
@@ -85,7 +86,7 @@
 
 	if (hvsi_udbg_buf_len == 0) {
 		rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
-		if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+		if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
 			/* bad read or non-data packet */
 			hvsi_udbg_buf_len = 0;
 		} else {
@@ -139,7 +140,7 @@
 	buf[0] = c;
 	do {
 		rc = plpar_put_term_char(vtermno, 1, buf);
-	} while(rc == H_Busy);
+	} while(rc == H_BUSY);
 }
 
 /* Buffered chars getc */
@@ -158,7 +159,7 @@
 		/* get some more chars. */
 		inbuflen = 0;
 		rc = plpar_get_term_char(vtermno, &inbuflen, buf);
-		if (rc != H_Success)
+		if (rc != H_SUCCESS)
 			inbuflen = 0;	/* otherwise inbuflen is garbage */
 	}
 	if (inbuflen <= 0 || inbuflen > 16) {
@@ -304,7 +305,7 @@
 
 	lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
 			      hpte_r, &slot, &dummy0, &dummy1);
-	if (unlikely(lpar_rc == H_PTEG_Full)) {
+	if (unlikely(lpar_rc == H_PTEG_FULL)) {
 		if (!(vflags & HPTE_V_BOLTED))
 			DBG_LOW(" full\n");
 		return -1;
@@ -315,7 +316,7 @@
 	 * will fail. However we must catch the failure in hash_page
 	 * or we will loop forever, so return -2 in this case.
 	 */
-	if (unlikely(lpar_rc != H_Success)) {
+	if (unlikely(lpar_rc != H_SUCCESS)) {
 		if (!(vflags & HPTE_V_BOLTED))
 			DBG_LOW(" lpar err %d\n", lpar_rc);
 		return -2;
@@ -346,9 +347,9 @@
 		/* don't remove a bolted entry */
 		lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
 					   (0x1UL << 4), &dummy1, &dummy2);
-		if (lpar_rc == H_Success)
+		if (lpar_rc == H_SUCCESS)
 			return i;
-		BUG_ON(lpar_rc != H_Not_Found);
+		BUG_ON(lpar_rc != H_NOT_FOUND);
 
 		slot_offset++;
 		slot_offset &= 0x7;
@@ -391,14 +392,14 @@
 
 	lpar_rc = plpar_pte_protect(flags, slot, want_v & HPTE_V_AVPN);
 
-	if (lpar_rc == H_Not_Found) {
+	if (lpar_rc == H_NOT_FOUND) {
 		DBG_LOW("not found !\n");
 		return -1;
 	}
 
 	DBG_LOW("ok\n");
 
-	BUG_ON(lpar_rc != H_Success);
+	BUG_ON(lpar_rc != H_SUCCESS);
 
 	return 0;
 }
@@ -417,7 +418,7 @@
 
 	lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
 
-	BUG_ON(lpar_rc != H_Success);
+	BUG_ON(lpar_rc != H_SUCCESS);
 
 	return dword0;
 }
@@ -468,7 +469,7 @@
 	flags = newpp & 7;
 	lpar_rc = plpar_pte_protect(flags, slot, 0);
 
-	BUG_ON(lpar_rc != H_Success);
+	BUG_ON(lpar_rc != H_SUCCESS);
 }
 
 static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -484,10 +485,10 @@
 	want_v = hpte_encode_v(va, psize);
 	lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v & HPTE_V_AVPN,
 				   &dummy1, &dummy2);
-	if (lpar_rc == H_Not_Found)
+	if (lpar_rc == H_NOT_FOUND)
 		return;
 
-	BUG_ON(lpar_rc != H_Success);
+	BUG_ON(lpar_rc != H_SUCCESS);
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index fcc4d56..e0000ce 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -488,7 +488,7 @@
 	/* No RTAS */
 	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
 		printk(KERN_INFO "rtasd: no event-scan on system\n");
-		return 1;
+		return -ENODEV;
 	}
 
 	entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index b2fbf8b..5eb55ef 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -463,7 +463,7 @@
 	 * very low priority.  The cede enables interrupts, which
 	 * doesn't matter here.
 	 */
-	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending)
+	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
 		cede_processor();
 
 out:
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 866379b..8e53e04 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -258,7 +258,7 @@
 int vio_enable_interrupts(struct vio_dev *dev)
 {
 	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
-	if (rc != H_Success)
+	if (rc != H_SUCCESS)
 		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
 	return rc;
 }
@@ -267,7 +267,7 @@
 int vio_disable_interrupts(struct vio_dev *dev)
 {
 	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
-	if (rc != H_Success)
+	if (rc != H_SUCCESS)
 		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
 	return rc;
 }
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 4864cb3..2d60ea3 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -168,7 +168,7 @@
 	unsigned long return_value;
 
 	lpar_rc = plpar_xirr(&return_value);
-	if (lpar_rc != H_Success)
+	if (lpar_rc != H_SUCCESS)
 		panic(" bad return code xirr - rc = %lx \n", lpar_rc);
 	return (int)return_value;
 }
@@ -179,7 +179,7 @@
 	unsigned long val64 = value & 0xffffffff;
 
 	lpar_rc = plpar_eoi(val64);
-	if (lpar_rc != H_Success)
+	if (lpar_rc != H_SUCCESS)
 		panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
 		      val64);
 }
@@ -189,7 +189,7 @@
 	unsigned long lpar_rc;
 
 	lpar_rc = plpar_cppr(value);
-	if (lpar_rc != H_Success)
+	if (lpar_rc != H_SUCCESS)
 		panic("bad return code cppr - rc = %lx\n", lpar_rc);
 }
 
@@ -198,7 +198,7 @@
 	unsigned long lpar_rc;
 
 	lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value);
-	if (lpar_rc != H_Success)
+	if (lpar_rc != H_SUCCESS)
 		panic("bad return code qirr - rc = %lx\n", lpar_rc);
 }
 
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 61d3174..38087bd 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -49,6 +49,7 @@
 
 #include "dart.h"
 
+extern int iommu_is_off;
 extern int iommu_force_on;
 
 /* Physical base address and size of the DART table */
@@ -329,10 +330,17 @@
 
 void __init alloc_dart_table(void)
 {
-	/* Only reserve DART space if machine has more than 2GB of RAM
+	/* Only reserve DART space if machine has more than 1GB of RAM
 	 * or if requested with iommu=on on cmdline.
+	 *
+	 * 1GB of RAM is picked as limit because some default devices
+	 * (i.e. Airport Extreme) have 30 bit address range limits.
 	 */
-	if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+
+	if (iommu_is_off)
+		return;
+
+	if (!iommu_force_on && lmb_end_of_DRAM() <= 0x40000000ull)
 		return;
 
 	/* 512 pages (2MB) is max DART tablesize. */
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index d4077e6..80c84d5 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -3,7 +3,7 @@
 #
 
 CFLAGS_kbd.o	:= -Idrivers/char
-CFLAGS_vreset.o := -I$(srctree)/arch/ppc/boot/include
+CFLAGS_vreset.o := -Iarch/ppc/boot/include
 
 zlib  := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
 	 
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 77e4dc7..cc7c4ae 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -134,6 +134,7 @@
 	DEFINE(TI_TASK, offsetof(struct thread_info, task));
 	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
 	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, flags));
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5891ecb..1adc914 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -128,29 +128,26 @@
 	stw	r12,4(r11)
 #endif
 	b	3f
+
 2:	/* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
+	lwz	r9,THREAD_INFO-THREAD(r12)
+	cmplw	r1,r9			/* if r1 <= current->thread_info */
+	ble-	stack_ovf		/* then the kernel stack overflowed */
+5:
 #ifdef CONFIG_6xx
-	mfspr	r11,SPRN_HID0
-	mtcr	r11
-BEGIN_FTR_SECTION
-	bt-	8,4f			/* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
-	bt-	9,4f			/* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+	tophys(r9,r9)			/* check local flags */
+	lwz	r12,TI_LOCAL_FLAGS(r9)
+	mtcrf	0x01,r12
+	bt-	31-TLF_NAPPING,4f
 #endif /* CONFIG_6xx */
 	.globl transfer_to_handler_cont
 transfer_to_handler_cont:
-	lwz	r11,THREAD_INFO-THREAD(r12)
-	cmplw	r1,r11			/* if r1 <= current->thread_info */
-	ble-	stack_ovf		/* then the kernel stack overflowed */
 3:
 	mflr	r9
 	lwz	r11,0(r9)		/* virtual address of handler */
 	lwz	r9,4(r9)		/* where to go when done */
-	FIX_SRR1(r10,r12)
 	mtspr	SPRN_SRR0,r11
 	mtspr	SPRN_SRR1,r10
 	mtlr	r9
@@ -158,7 +155,9 @@
 	RFI				/* jump to handler, enable MMU */
 
 #ifdef CONFIG_6xx
-4:	b	power_save_6xx_restore
+4:	rlwinm	r12,r12,0,~_TLF_NAPPING
+	stw	r12,TI_LOCAL_FLAGS(r9)
+	b	power_save_6xx_restore
 #endif
 
 /*
@@ -167,10 +166,10 @@
  */
 stack_ovf:
 	/* sometimes we use a statically-allocated stack, which is OK. */
-	lis	r11,_end@h
-	ori	r11,r11,_end@l
-	cmplw	r1,r11
-	ble	3b			/* r1 <= &_end is OK */
+	lis	r12,_end@h
+	ori	r12,r12,_end@l
+	cmplw	r1,r12
+	ble	5b			/* r1 <= &_end is OK */
 	SAVE_NVGPRS(r11)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	lis	r1,init_thread_union@ha
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 865ba74..b250b1b 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -94,6 +94,7 @@
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcasecmp);
+EXPORT_SYMBOL(strncasecmp);
 EXPORT_SYMBOL(__div64_32);
 
 EXPORT_SYMBOL(csum_partial);
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 60c724e..7662c4e 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -156,12 +156,13 @@
 	while (map->bus_id != NULL) {
 		idx = -1;
 		s = strrchr(dev->bus_id, '.');
-		if (s != NULL)
+		if (s != NULL) {
 			idx = (int)simple_strtol(s + 1, NULL, 10);
-		else
+			len = s - dev->bus_id;
+		} else {
 			s = dev->bus_id;
-
-		len = s - dev->bus_id;
+			len = strlen(dev->bus_id);
+		}
 
 		if (!strncmp(dev->bus_id, map->bus_id, len)) {
 			pdev = container_of(dev, struct platform_device, dev);
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 6c6b197..7bb16fb 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -67,7 +67,6 @@
 endif
 
 CFLAGS		+= -mbackchain -msoft-float $(cflags-y)
-CFLAGS		+= $(call cc-option,-finline-limit=10000)
 CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
 AFLAGS		+= $(aflags-y)
 
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 54d35c1..9a22434 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -652,7 +652,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
 	.notifier_call = appldata_cpu_notify,
 };
 
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f8d0cd5..f4dfc10 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,10 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc2
-# Wed Feb  8 10:44:39 2006
+# Linux kernel version: 2.6.17-rc1
+# Mon Apr  3 14:34:15 2006
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_S390=y
 
@@ -30,8 +31,8 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
@@ -45,10 +46,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -60,7 +57,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -69,7 +65,7 @@
 #
 # Block layer
 #
-# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -91,17 +87,20 @@
 #
 # Processor type and features
 #
-# CONFIG_64BIT is not set
+CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_HOTPLUG_CPU=y
-CONFIG_MATHEMU=y
+CONFIG_DEFAULT_MIGRATION_COST=1000000
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_BINFMT_ELF32=y
 
 #
 # Code generation options
 #
-CONFIG_MARCH_G5=y
-# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_G5 is not set
+CONFIG_MARCH_Z900=y
 # CONFIG_MARCH_Z990 is not set
 CONFIG_PACK_STACK=y
 # CONFIG_SMALL_STACK is not set
@@ -143,7 +142,7 @@
 # CONFIG_APPLDATA_BASE is not set
 CONFIG_NO_IDLE_HZ=y
 CONFIG_NO_IDLE_HZ_INIT=y
-# CONFIG_KEXEC is not set
+CONFIG_KEXEC=y
 
 #
 # Networking
@@ -173,6 +172,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -180,9 +180,11 @@
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
@@ -276,6 +278,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
@@ -340,8 +347,7 @@
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 CONFIG_DASD_DIAG=y
-CONFIG_DASD_EER=m
-# CONFIG_DASD_CMB is not set
+CONFIG_DASD_EER=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -354,6 +360,7 @@
 CONFIG_MD_RAID1=m
 # CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
@@ -404,6 +411,7 @@
 # S/390 tape hardware support
 #
 CONFIG_S390_TAPE_34XX=m
+# CONFIG_S390_TAPE_3590 is not set
 # CONFIG_VMLOGRDR is not set
 # CONFIG_VMCP is not set
 # CONFIG_MONREADER is not set
@@ -529,7 +537,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -619,14 +626,15 @@
 # CONFIG_DETECT_SOFTLOCKUP is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_PREEMPT=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 5291b5f..b4c815d 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -430,7 +430,7 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! on_sig_stack(sp))
+		if (! sas_ss_flags(sp))
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 199da68..ef5b9c4 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1608,3 +1608,45 @@
 sys_unshare_wrapper:
 	llgfr	%r2,%r2			# unsigned long
 	jg	sys_unshare
+
+	.globl compat_sys_set_robust_list_wrapper
+compat_sys_set_robust_list_wrapper:
+	llgtr	%r2,%r2			# struct compat_robust_list_head *
+	llgfr	%r3,%r3			# size_t
+	jg	compat_sys_set_robust_list
+
+	.globl compat_sys_get_robust_list_wrapper
+compat_sys_get_robust_list_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# compat_uptr_t_t *
+	llgtr	%r4,%r4			# compat_size_t *
+	jg	compat_sys_get_robust_list
+
+	.globl sys_splice_wrapper
+sys_splice_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# loff_t *
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# loff_t *
+	llgfr	%r6,%r6			# size_t
+	llgf	%r0,164(%r15)		# unsigned int
+	stg	%r0,160(%r15)
+	jg	sys_splice
+
+	.globl	sys_sync_file_range_wrapper
+sys_sync_file_range_wrapper:
+	lgfr	%r2,%r2			# int
+	sllg	%r3,%r3,32		# get high word of 64bit loff_t
+	or	%r3,%r4			# get low word of 64bit loff_t
+	sllg	%r4,%r5,32		# get high word of 64bit loff_t
+	or	%r4,%r6			# get low word of 64bit loff_t
+	llgf	%r5,164(%r15)		# unsigned int
+	jg	sys_sync_file_range
+
+	.globl	sys_tee_wrapper
+sys_tee_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	llgfr	%r4,%r4			# size_t
+	llgfr	%r5,%r5			# unsigned int
+	jg	sys_tee
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 2f56654..fc2c076 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -312,3 +312,8 @@
 SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
 SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
 SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
+SYSCALL(sys_set_robust_list,sys_set_robust_list,compat_sys_set_robust_list_wrapper)
+SYSCALL(sys_get_robust_list,sys_get_robust_list,compat_sys_get_robust_list_wrapper)
+SYSCALL(sys_splice,sys_splice,sys_splice_wrapper)
+SYSCALL(sys_sync_file_range,sys_sync_file_range,sys_sync_file_range_wrapper)
+SYSCALL(sys_tee,sys_tee,sys_tee_wrapper)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 9289fac..9f34bb5 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -58,9 +58,11 @@
   . = ALIGN(4096);
   .data.page_aligned : { *(.data.idt) }
 
-  . = ALIGN(32);
+  . = ALIGN(256);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
+  . = ALIGN(256);
+  .data.read_mostly : { *(.data.read_mostly) }
   _edata = .;			/* End of data section */
 
   . = ALIGN(8192);		/* init_task */
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index a9566bc..9b11e3e 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -192,6 +192,7 @@
 	diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
 
 	if (diag_cc > 1) {
+		PRINT_WARN ("segment_type: diag returned error %ld\n", vmrc);
 		rc = dcss_diag_translate_rc (vmrc);
 		goto out_free;
 	}
@@ -553,7 +554,7 @@
 	int endpfn = 0;
 	char cmd1[160];
 	char cmd2[80];
-	int i;
+	int i, response;
 
 	if (!MACHINE_IS_VM)
 		return;
@@ -576,8 +577,20 @@
 			segtype_string[seg->range[i].start & 0xff]);
 	}
 	sprintf(cmd2, "SAVESEG %s", name);
-	cpcmd(cmd1, NULL, 0, NULL);
-	cpcmd(cmd2, NULL, 0, NULL);
+	response = 0;
+	cpcmd(cmd1, NULL, 0, &response);
+	if (response) {
+		PRINT_ERR("segment_save: DEFSEG failed with response code %i\n",
+			  response);
+		goto out;
+	}
+	cpcmd(cmd2, NULL, 0, &response);
+	if (response) {
+		PRINT_ERR("segment_save: SAVESEG failed with response code %i\n",
+			  response);
+		goto out;
+	}
+out:
 	spin_unlock(&dcss_lock);
 }
 
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 58583f4..2bcecf4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -527,6 +527,11 @@
 	  See <file:Documentation/sh/register-banks.txt> for further
 	  information on SR.RB and register banking in the kernel in general.
 
+config NODES_SHIFT
+	int
+	default "1"
+	depends on NEED_MULTIPLE_NODES
+
 endmenu
 
 menu "Boot options"
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 1cf94a6..d5d0325 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -37,7 +37,6 @@
 EXPORT_SYMBOL(irq_desc);
 EXPORT_SYMBOL(no_irq_type);
 
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index de29c45..6f3a1c9 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -41,7 +41,6 @@
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
 #ifdef CONFIG_VT
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 2be8121..a93f5da 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -244,7 +244,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&prof_setup_lock, flags);
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		load_profile_irq(i, lvl14_resolution / multiplier);
 		prof_multiplier(i) = multiplier;
 	}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 2c21d79..ec1c968 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -263,7 +263,6 @@
 EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(page_kernel);
 
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 768de64..db8faa7 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -64,18 +64,18 @@
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex
 /*220*/	.long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 /*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
-/*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/	.long sys_select, sys_time, sys_splice, sys_stime, sys_statfs64
 					  /* "We are the Knights of the Forest of Ni!!" */
 /*235*/	.long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/	.long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+/*255*/	.long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/	.long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
 /*285*/	.long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
 /*290*/	.long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
 /*295*/	.long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
diff --git a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile
index f84a9a6..8136987 100644
--- a/arch/sparc/math-emu/Makefile
+++ b/arch/sparc/math-emu/Makefile
@@ -5,4 +5,4 @@
 obj-y    := math.o
 
 EXTRA_AFLAGS := -ansi
-EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w
+EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index d1e2fc5..43a66f5 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -187,13 +187,16 @@
 	bool "512K"
 
 config HUGETLB_PAGE_SIZE_64K
-	depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64K
+	depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64KB
 	bool "64K"
 
 endchoice
 
 endmenu
 
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+
 config ARCH_SPARSEMEM_ENABLE
 	def_bool y
 
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 900fb0b..1317380 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16
-# Sun Mar 26 14:58:11 2006
+# Sun Apr  2 19:31:04 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -180,6 +180,7 @@
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
 CONFIG_INET_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -203,6 +204,7 @@
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_NETFILTER is not set
@@ -308,7 +310,6 @@
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_UB=m
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -449,6 +450,7 @@
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
@@ -741,9 +743,7 @@
 # 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_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -826,6 +826,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+# CONFIG_FB_FIRMWARE_EDID is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -837,7 +838,6 @@
 # CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -923,6 +923,7 @@
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 CONFIG_SND_ALI5451=m
 # CONFIG_SND_ATIIXP is not set
 # CONFIG_SND_ATIIXP_MODEM is not set
@@ -954,6 +955,7 @@
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -1108,6 +1110,11 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -1117,6 +1124,11 @@
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # Misc Linux/SPARC drivers
 #
 CONFIG_SUN_OPENPROMIO=m
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index ffc7309..2e1c824 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -63,7 +63,7 @@
 	flushi(p->addr);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -71,7 +71,7 @@
 	kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -79,7 +79,7 @@
 	kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
@@ -87,7 +87,7 @@
 	kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
 			struct kprobe_ctlblk *kcb)
 {
 	regs->tstate |= TSTATE_PIL;
@@ -273,7 +273,7 @@
 			kcb->kprobe_orig_tstate_pil);
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -300,7 +300,7 @@
 	return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index dfccff2..f97ddeb 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -419,6 +419,7 @@
 	region->start = res->start - zero_res.start;
 	region->end = res->end - zero_res.start;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
 			     struct pci_bus_region *region)
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 9372d4f..9e94db2 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -1092,7 +1092,7 @@
 		}
 	}
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		unsigned long page = get_zeroed_page(GFP_ATOMIC);
 
 		if (!page)
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index eb93e9c..49e6ded 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -244,6 +244,13 @@
 	}
 
 	switch(request) {
+	case PTRACE_PEEKUSR:
+		if (addr != 0)
+			pt_error_return(regs, EIO);
+		else
+			pt_succ_return(regs, 0);
+		goto out_tsk;
+
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
 		unsigned long tmp64;
@@ -602,6 +609,22 @@
 
 	/* PTRACE_DUMPCORE unsupported... */
 
+	case PTRACE_GETEVENTMSG: {
+		int err;
+
+		if (test_thread_flag(TIF_32BIT))
+			err = put_user(child->ptrace_message,
+				       (unsigned int __user *) data);
+		else
+			err = put_user(child->ptrace_message,
+				       (unsigned long __user *) data);
+		if (err)
+			pt_error_return(regs, -err);
+		else
+			pt_succ_return(regs, 0);
+		break;
+	}
+
 	default: {
 		int err = ptrace_request(child, request, addr, data);
 		if (err)
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 7d0e67c..005167f 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -535,7 +535,7 @@
 	while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
 		ncpus_probed++;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
 		if (p) {
 			register_cpu(p, i, NULL);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 7dc28a4..90eaca3 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -745,12 +745,21 @@
 	int wait;
 };
 
-static DEFINE_SPINLOCK(call_lock);
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
 static struct call_data_struct *call_data;
 
 extern unsigned long xcall_call_function;
 
-/*
+/**
+ * smp_call_function(): Run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
  * You must not call this function with disabled interrupts or from a
  * hardware interrupt handler or from a bottom half handler.
  */
@@ -759,7 +768,6 @@
 {
 	struct call_data_struct data;
 	int cpus;
-	long timeout;
 
 	/* Can deadlock when called with interrupts disabled */
 	WARN_ON(irqs_disabled());
@@ -777,31 +785,18 @@
 		goto out_unlock;
 
 	call_data = &data;
+	mb();
 
 	smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
 
-	/* 
-	 * Wait for other cpus to complete function or at
-	 * least snap the call data.
-	 */
-	timeout = 1000000;
-	while (atomic_read(&data.finished) != cpus) {
-		if (--timeout <= 0)
-			goto out_timeout;
-		barrier();
-		udelay(1);
-	}
+	/* Wait for response */
+	while (atomic_read(&data.finished) != cpus)
+		cpu_relax();
 
 out_unlock:
 	spin_unlock(&call_lock);
 
 	return 0;
-
-out_timeout:
-	spin_unlock(&call_lock);
-	printk("XCALL: Remote cpus not responding, ncpus=%d finished=%d\n",
-	       cpus, atomic_read(&data.finished));
-	return 0;
 }
 
 int smp_call_function(void (*func)(void *info), void *info,
@@ -830,9 +825,16 @@
 
 static void tsb_sync(void *info)
 {
+	struct trap_per_cpu *tp = &trap_block[raw_smp_processor_id()];
 	struct mm_struct *mm = info;
 
-	if (current->active_mm == mm)
+	/* It is not valid to test "currrent->active_mm == mm" here.
+	 *
+	 * The value of "current" is not changed atomically with
+	 * switch_mm().  But that's OK, we just need to check the
+	 * current cpu's trap block PGD physical address.
+	 */
+	if (tp->pgd_paddr == __pa(mm->pgd))
 		tsb_context_switch(mm);
 }
 
@@ -1278,7 +1280,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&prof_setup_lock, flags);
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		prof_multiplier(i) = multiplier;
 	current_tick_offset = (timer_tick_offset / multiplier);
 	spin_unlock_irqrestore(&prof_setup_lock, flags);
@@ -1306,12 +1308,12 @@
 		}
 	}
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		if (tlb_type == hypervisor) {
 			int j;
 
 			/* XXX get this mapping from machine description */
-			for_each_cpu(j) {
+			for_each_possible_cpu(j) {
 				if ((j >> 2) == (i >> 2))
 					cpu_set(j, cpu_sibling_map[i]);
 			}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index f5e8db1..62d8a99 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -276,7 +276,6 @@
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(__strlen_user);
 EXPORT_SYMBOL(__strnlen_user);
-EXPORT_SYMBOL(strpbrk);
 
 #ifdef CONFIG_SOLARIS_EMUL_MODULE
 EXPORT_SYMBOL(linux_sparc_syscall);
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index c4a1cef..f9b7576 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -136,6 +136,9 @@
 SIGN1(sys32_getsockname, sys_getsockname, %o0)
 SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
 SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
+SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
+SIGN2(sys32_tee, sys_tee, %o0, %o1)
 
 	.globl		sys32_mmap2
 sys32_mmap2:
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 2e906ba..31030bf 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1069,3 +1069,11 @@
 	return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
 				  buf, len);
 }
+
+long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
+{
+	return sys_sync_file_range(fd,
+				   (off_high << 32) | off_low,
+				   (nb_high << 32) | nb_low,
+				   flags);
+}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 3b250f2..62672cd 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -66,17 +66,17 @@
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys32_ioprio_get, compat_sys_adjtimex
 /*220*/	.word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
 	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/	.word sys32_select, compat_sys_time, sys_nis_syscall, compat_sys_stime, compat_sys_statfs64
+/*230*/	.word sys32_select, compat_sys_time, sys32_splice, compat_sys_stime, compat_sys_statfs64
 	.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
 /*240*/	.word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
 	.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/	.word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
-	.word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+	.word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/	.word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
 	.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
 /*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
 	.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
@@ -135,17 +135,17 @@
 	.word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
 /*220*/	.word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-/*230*/	.word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64
+/*230*/	.word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64
 	.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/	.word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-	.word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+	.word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/	.word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*280*/	.word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat
 	.word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64
 /*285*/	.word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
 	.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index ff090bb..2793a5d 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1130,9 +1130,9 @@
 	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
 	       afsr, afar,
 	       (afsr & CHAFSR_TL1) ? 1 : 0);
-	printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
+	printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n",
 	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
-	       regs->tpc, regs->tnpc, regs->tstate);
+	       regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
 	printk("%s" "ERROR(%d): M_SYND(%lx),  E_SYND(%lx)%s%s\n",
 	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
 	       (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 0db2f7d..6e002aa 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -327,8 +327,12 @@
 		insn = get_fault_insn(regs, 0);
 		if (!insn)
 			goto continue_fault;
+		/* All loads, stores and atomics have bits 30 and 31 both set
+		 * in the instruction.  Bit 21 is set in all stores, but we
+		 * have to avoid prefetches which also have bit 21 set.
+		 */
 		if ((insn & 0xc0200000) == 0xc0200000 &&
-		    (insn & 0x1780000) != 0x1680000) {
+		    (insn & 0x01780000) != 0x01680000) {
 			/* Don't bother updating thread struct value,
 			 * because update_mmu_cache only cares which tlb
 			 * the access came from.
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 074620d..fbbbebb 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -198,6 +198,13 @@
 	pmd_t *pmd;
 	pte_t *pte = NULL;
 
+	/* We must align the address, because our caller will run
+	 * set_huge_pte_at() on whatever we return, which writes out
+	 * all of the sub-ptes for the hugepage range.  So we have
+	 * to give it the first such sub-pte.
+	 */
+	addr &= HPAGE_MASK;
+
 	pgd = pgd_offset(mm, addr);
 	pud = pud_alloc(mm, pgd, addr);
 	if (pud) {
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 24790be..a508e7a 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -159,6 +159,7 @@
 $(SYMLINK_HEADERS):
 	@echo '  SYMLINK $@'
 ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p $(objtree)/include/asm-um
 	$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
 else
 	$(Q)cd $(TOPDIR)/$(dir $@) ; \
@@ -168,7 +169,7 @@
 include/asm-um/arch:
 	@echo '  SYMLINK $@'
 ifneq ($(KBUILD_SRC),)
-	$(Q)mkdir -p include/asm-um
+	$(Q)mkdir -p $(objtree)/include/asm-um
 	$(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
 else
 	$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index 04e3958..dc36b22 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -46,7 +46,7 @@
 extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
 			   void *arg, __u32 *version_out,
 			   char **backing_file_out, time_t *mtime_out,
-			   __u64 *size_out, int *sectorsize_out,
+			   unsigned long long *size_out, int *sectorsize_out,
 			   __u32 *align_out, int *bitmap_offset_out);
 
 extern int write_cow_header(char *cow_file, int fd, char *backing_file,
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index 94de4ea..7a5b4af 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -28,7 +28,7 @@
 	return(os_seek_file(fd, offset));
 }
 
-static inline int cow_file_size(char *file, __u64 *size_out)
+static inline int cow_file_size(char *file, unsigned long long *size_out)
 {
 	return(os_file_size(file, size_out));
 }
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 61951b7..6ab852b 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -17,30 +17,34 @@
 
 #define PATH_LEN_V1 256
 
-struct cow_header_v1 {
-	int magic;
-	int version;
-	char backing_file[PATH_LEN_V1];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
+typedef __u32 time32_t;
 
-#define PATH_LEN_V2 MAXPATHLEN
+struct cow_header_v1 {
+	__s32 magic;
+	__s32 version;
+	char backing_file[PATH_LEN_V1];
+	time32_t mtime;
+	__u64 size;
+	__s32 sectorsize;
+} __attribute__((packed));
+
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
+ * case other systems have different values for MAXPATHLEN.
+ *
+ * The same must hold for V2 - we want file format compatibility, not anything
+ * else.
+ */
+#define PATH_LEN_V3 4096
+#define PATH_LEN_V2 PATH_LEN_V3
 
 struct cow_header_v2 {
 	__u32 magic;
 	__u32 version;
 	char backing_file[PATH_LEN_V2];
-	time_t mtime;
+	time32_t mtime;
 	__u64 size;
-	int sectorsize;
-};
-
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
- * case other systems have different values for MAXPATHLEN
- */
-#define PATH_LEN_V3 4096
+	__s32 sectorsize;
+} __attribute__((packed));
 
 /* Changes from V2 -
  *	PATH_LEN_V3 as described above
@@ -66,6 +70,15 @@
  *	Fixed (finally!) the rounding bug
  */
 
+/* Until Dec2005, __attribute__((packed)) was left out from the below
+ * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
+ * align size to 8-byte alignment.  This shifted all fields above (no padding
+ * was present on 32-bit, no other padding was added).
+ *
+ * However, this _can be detected_: it means that cow_format (always 0 until
+ * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise
+ * impossible to find 4 zeros. -bb */
+
 struct cow_header_v3 {
 	__u32 magic;
 	__u32 version;
@@ -75,7 +88,19 @@
 	__u32 alignment;
 	__u32 cow_format;
 	char backing_file[PATH_LEN_V3];
-};
+} __attribute__((packed));
+
+/* This is the broken layout used by some 64-bit binaries. */
+struct cow_header_v3_broken {
+	__u32 magic;
+	__u32 version;
+	__s64 mtime;
+	__u64 size;
+	__u32 sectorsize;
+	__u32 alignment;
+	__u32 cow_format;
+	char backing_file[PATH_LEN_V3];
+} __attribute__((packed));
 
 /* COW format definitions - for now, we have only the usual COW bitmap */
 #define COW_BITMAP 0
@@ -84,6 +109,7 @@
 	struct cow_header_v1 v1;
 	struct cow_header_v2 v2;
 	struct cow_header_v3 v3;
+	struct cow_header_v3_broken v3_b;
 };
 
 #define COW_MAGIC 0x4f4f4f4d  /* MOOO */
@@ -184,8 +210,9 @@
 
 	err = -EINVAL;
 	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+		/* Below, %zd is for a size_t value */
 		cow_printf("Backing file name \"%s\" is too long - names are "
-			   "limited to %d characters\n", backing_file,
+			   "limited to %zd characters\n", backing_file,
 			   sizeof(header->backing_file) - 1);
 		goto out_free;
 	}
@@ -300,7 +327,8 @@
 		*align_out = *sectorsize_out;
 		file = header->v2.backing_file;
 	}
-	else if(version == 3){
+	/* This is very subtle - see above at union cow_header definition */
+	else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){
 		if(n < sizeof(header->v3)){
 			cow_printf("read_cow_header - failed to read V3 "
 				   "header\n");
@@ -310,9 +338,43 @@
 		*size_out = ntohll(header->v3.size);
 		*sectorsize_out = ntohl(header->v3.sectorsize);
 		*align_out = ntohl(header->v3.alignment);
+		if (*align_out == 0) {
+			cow_printf("read_cow_header - invalid COW header, "
+				   "align == 0\n");
+		}
 		*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
 		file = header->v3.backing_file;
 	}
+	else if(version == 3){
+		cow_printf("read_cow_header - broken V3 file with"
+			   " 64-bit layout - recovering content.\n");
+
+		if(n < sizeof(header->v3_b)){
+			cow_printf("read_cow_header - failed to read V3 "
+				   "header\n");
+			goto out;
+		}
+
+		/* this was used until Dec2005 - 64bits are needed to represent
+		 * 2038+. I.e. we can safely do this truncating cast.
+		 *
+		 * Additionally, we must use ntohl() instead of ntohll(), since
+		 * the program used to use the former (tested - I got mtime
+		 * mismatch "0 vs whatever").
+		 *
+		 * Ever heard about bug-to-bug-compatibility ? ;-) */
+		*mtime_out = (time32_t) ntohl(header->v3_b.mtime);
+
+		*size_out = ntohll(header->v3_b.size);
+		*sectorsize_out = ntohl(header->v3_b.sectorsize);
+		*align_out = ntohl(header->v3_b.alignment);
+		if (*align_out == 0) {
+			cow_printf("read_cow_header - invalid COW header, "
+				   "align == 0\n");
+		}
+		*bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out);
+		file = header->v3_b.backing_file;
+	}
 	else {
 		cow_printf("read_cow_header - invalid COW version\n");
 		goto out;
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 28e3760..6d7173f 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -62,7 +62,7 @@
 	unsigned long flags;
 
 	while(!list_empty(&mc_requests)){
-		local_save_flags(flags);
+		local_irq_save(flags);
 		req = list_entry(mc_requests.next, struct mconsole_entry,
 				 list);
 		list_del(&req->list);
@@ -87,7 +87,7 @@
 		if(req.cmd->context == MCONSOLE_INTR)
 			(*req.cmd->handler)(&req);
 		else {
-			new = kmalloc(sizeof(*new), GFP_ATOMIC);
+			new = kmalloc(sizeof(*new), GFP_NOWAIT);
 			if(new == NULL)
 				mconsole_reply(&req, "Out of memory", 1, 0);
 			else {
@@ -415,7 +415,6 @@
 
 			unplugged = page_address(page);
 			if(unplug_index == UNPLUGGED_PER_PAGE){
-				INIT_LIST_HEAD(&unplugged->list);
 				list_add(&unplugged->list, &unplugged_pages);
 				unplug_index = 0;
 			}
@@ -616,7 +615,7 @@
 		return;
 
 	while(1){
-		n = min((size_t)len, ARRAY_SIZE(console_buf) - console_index);
+		n = min((size_t) len, ARRAY_SIZE(console_buf) - console_index);
 		strncpy(&console_buf[console_index], string, n);
 		console_index += n;
 		string += n;
@@ -655,7 +654,6 @@
 	struct mconsole_entry entry;
 	unsigned long flags;
 
-	INIT_LIST_HEAD(&entry.list);
 	entry.request = *req;
 	list_add(&entry.list, &clients);
 	spin_lock_irqsave(&console_lock, flags);
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 0e2f061..0a7786e 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -182,7 +182,9 @@
 	pe_data.stdout = fds[1];
 	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
 
-	read_output(fds[0], output, output_len);
+	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
+		read_output(fds[0], output, output_len);
+
 	os_close_file(fds[0]);
 	os_close_file(fds[1]);
 
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index b94c661..33c5f6e 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -104,7 +104,7 @@
 	}
 
 	if(err == 0) {
-		printk("slirp_close: process %d has not exited\n");
+		printk("slirp_close: process %d has not exited\n", pri->pid);
 		return;
 	}
 
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 4255713..efa3d33 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -117,10 +117,6 @@
 extern void machine_halt(void);
 extern int is_syscall(unsigned long addr);
 
-extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
-
-extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
-
 extern void free_irq(unsigned int, void *);
 extern int cpu(void);
 
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
index 018b381..8e70530 100644
--- a/arch/um/include/longjmp.h
+++ b/arch/um/include/longjmp.h
@@ -4,11 +4,11 @@
 #include <setjmp.h>
 #include "os.h"
 
-#define UML_SIGLONGJMP(buf, val) do { \
+#define UML_LONGJMP(buf, val) do { \
 	longjmp(*buf, val);	\
 } while(0)
 
-#define UML_SIGSETJMP(buf, enable) ({ \
+#define UML_SETJMP(buf, enable) ({ \
 	int n; \
 	enable = get_signals(); \
 	n = setjmp(*buf); \
diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h
index 82f96c5..2c13de3 100644
--- a/arch/um/include/sysdep-i386/kernel-offsets.h
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,6 +1,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/elf.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
 void foo(void)
 {
 	OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
 	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index 5ce93ab..939cc47 100644
--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -4,6 +4,7 @@
 #include <linux/time.h>
 #include <linux/elf.h>
 #include <asm/page.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -18,6 +19,7 @@
 
 void foo(void)
 {
+	DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
 	OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
diff --git a/arch/um/include/tt/tt.h b/arch/um/include/tt/tt.h
index 8085219..acb8356 100644
--- a/arch/um/include/tt/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -19,7 +19,8 @@
 extern int do_proc_op(void *t, int proc_id);
 extern int tracer(int (*init_proc)(void *), void *sp);
 extern void attach_process(int pid);
-extern void tracer_panic(char *format, ...);
+extern void tracer_panic(char *format, ...)
+	__attribute__ ((format (printf, 1, 2)));
 extern void set_init_pid(int pid);
 extern int set_user_mode(void *task);
 extern void set_tracing(void *t, int tracing);
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 91b0ac4..39f8c88 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -6,8 +6,10 @@
 #ifndef __USER_H__
 #define __USER_H__
 
-extern void panic(const char *fmt, ...);
-extern int printk(const char *fmt, ...);
+extern void panic(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
+extern int printk(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
 extern void schedule(void);
 extern void *um_kmalloc(int size);
 extern void *um_kmalloc_atomic(int size);
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index fe0c29b..802d784 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -55,7 +55,8 @@
 extern void *um_kmalloc(int size);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void do_exec(int old_pid, int new_pid);
-extern void tracer_panic(char *msg, ...);
+extern void tracer_panic(char *msg, ...)
+	__attribute__ ((format (printf, 1, 2)));
 extern int detach(int pid, int sig);
 extern int attach(int pid);
 extern void kill_child_dead(int pid);
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 7713e7a..432cf0b 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -39,7 +39,6 @@
 EXPORT_SYMBOL(mode_tt);
 EXPORT_SYMBOL(handle_page_fault);
 EXPORT_SYMBOL(find_iomem);
-EXPORT_SYMBOL(end_iomem);
 
 #ifdef CONFIG_MODE_TT
 EXPORT_SYMBOL(strncpy_from_user_tt);
@@ -89,12 +88,10 @@
 EXPORT_SYMBOL(do_gettimeofday);
 EXPORT_SYMBOL(do_settimeofday);
 
-/* This is here because UML expands open to sys_open, not to a system
+/* This is here because UML expands lseek to sys_lseek, not to a system
  * call instruction.
  */
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_wait4);
 
 #ifdef CONFIG_SMP
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 901b85e..8f49507 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -40,7 +40,7 @@
 			int fd)
 {
 	struct addr_change change;
-	void *output;
+	char *output;
 	int n;
 
 	change.what = op;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6490a4f..6987d1d 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -43,7 +43,7 @@
 		(*data->pre_exec)(data->pre_data);
 	execvp(argv[0], argv);
 	errval = errno;
-	printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+	printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
 	os_write_file(data->fd, &errval, sizeof(errval));
 	kill(os_getpid(), SIGKILL);
 	return(0);
@@ -92,15 +92,15 @@
 	close(fds[1]);
 	fds[1] = -1;
 
-	/*Read the errno value from the child.*/
+	/* Read the errno value from the child, if the exec failed, or get 0 if
+	 * the exec succeeded because the pipe fd was set as close-on-exec. */
 	n = os_read_file(fds[0], &ret, sizeof(ret));
-	if(n < 0){
+	if (n < 0) {
 		printk("run_helper : read on pipe failed, ret = %d\n", -n);
 		ret = n;
 		kill(pid, SIGKILL);
 		CATCH_EINTR(waitpid(pid, NULL, 0));
-	}
-	else if(n != 0){
+	} else if(n != 0){
 		CATCH_EINTR(n = waitpid(pid, NULL, 0));
 		ret = -errno;
 	} else {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 6ab372d..c6432e7 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/statfs.h>
 #include "kern_util.h"
 #include "user.h"
 #include "user_util.h"
@@ -19,6 +20,7 @@
 
 #include <sys/param.h>
 
+static char *default_tmpdir = "/tmp";
 static char *tempdir = NULL;
 
 static void __init find_tempdir(void)
@@ -34,7 +36,7 @@
 			break;
 	}
 	if((dir == NULL) || (*dir == '\0'))
-		dir = "/tmp";
+		dir = default_tmpdir;
 
 	tempdir = malloc(strlen(dir) + 2);
 	if(tempdir == NULL){
@@ -46,6 +48,96 @@
 	strcat(tempdir, "/");
 }
 
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file.  This will
+ * read the file as needed.  If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+	int n;
+	char *ptr;
+
+	while((ptr = strchr(buf, c)) == NULL){
+		n = read(fd, buf, size - 1);
+		if(n == 0)
+			return 0;
+		else if(n < 0)
+			return -errno;
+
+		buf[n] = '\0';
+	}
+
+	ptr++;
+	memmove(buf, ptr, strlen(ptr) + 1);
+	return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts.  statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems.  Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+	int fd, found;
+	char buf[128] = { '\0' };
+
+	if(checked_tmpdir)
+		return;
+
+	checked_tmpdir = 1;
+
+	printf("Checking for tmpfs mount on /dev/shm...");
+
+	fd = open("/proc/mounts", O_RDONLY);
+	if(fd < 0){
+		printf("failed to open /proc/mounts, errno = %d\n", errno);
+		return;
+	}
+
+	while(1){
+		found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+		if(found != 1)
+			break;
+
+		if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+			goto found;
+
+		found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+		if(found != 1)
+			break;
+	}
+
+err:
+	if(found == 0)
+		printf("nothing mounted on /dev/shm\n");
+	else if(found < 0)
+		printf("read returned errno %d\n", -found);
+
+	return;
+
+found:
+	found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+	if(found != 1)
+		goto err;
+
+	if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+		printf("not tmpfs\n");
+		return;
+	}
+
+	printf("OK\n");
+	default_tmpdir = "/dev/shm";
+}
+
 /*
  * This proc still used in tt-mode
  * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -53,33 +145,37 @@
  */
 int make_tempfile(const char *template, char **out_tempname, int do_unlink)
 {
-	char tempname[MAXPATHLEN];
+	char *tempname;
 	int fd;
 
+	which_tmpdir();
+	tempname = malloc(MAXPATHLEN);
+
 	find_tempdir();
-	if (*template != '/')
+	if (template[0] != '/')
 		strcpy(tempname, tempdir);
 	else
-		*tempname = 0;
+		tempname[0] = '\0';
 	strcat(tempname, template);
 	fd = mkstemp(tempname);
 	if(fd < 0){
 		fprintf(stderr, "open - cannot create %s: %s\n", tempname,
 			strerror(errno));
-		return -1;
+		goto out;
 	}
 	if(do_unlink && (unlink(tempname) < 0)){
 		perror("unlink");
-		return -1;
+		goto out;
 	}
 	if(out_tempname){
-		*out_tempname = strdup(tempname);
-		if(*out_tempname == NULL){
-			perror("strdup");
-			return -1;
-		}
+		*out_tempname = tempname;
+	} else {
+		free(tempname);
 	}
 	return(fd);
+out:
+	free(tempname);
+	return -1;
 }
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -134,3 +230,26 @@
 	}
 	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 %s...",tempdir);
+	fflush(stdout);
+	if(addr == MAP_FAILED){
+		err = errno;
+		perror("failed");
+		if(err == EPERM)
+			printf("%s must be not mounted noexec\n",tempdir);
+		exit(1);
+	}
+	printf("OK\n");
+	munmap(addr, UM_KERN_PAGE_SIZE);
+
+	close(fd);
+}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 8176b0b..3505f44 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -190,7 +190,7 @@
 }
 
 #ifndef MADV_REMOVE
-#define MADV_REMOVE	0x5		/* remove these pages & resources */
+#define MADV_REMOVE KERNEL_MADV_REMOVE
 #endif
 
 int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@
 	}
 
 	addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
-		      MAP_PRIVATE, fd, 0);
+		      MAP_SHARED, fd, 0);
 	if(addr == MAP_FAILED){
 		printk("Mapping test memory file failed, err = %d\n", -errno);
 		return 0;
@@ -266,11 +266,11 @@
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-	sigjmp_buf buf;
+	jmp_buf buf;
 	int n, enable;
 
 	*jmp_ptr = &buf;
-	n = UML_SIGSETJMP(&buf, enable);
+	n = UML_SETJMP(&buf, enable);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 9ba9429..00e9388 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -304,8 +304,8 @@
 					   .size	= 0,
 					   .used	= 0 });
 out_free:
-	kfree(p);
 	sigio_unlock();
+	kfree(p);
 out_close2:
 	close(l_sigio_private[0]);
 	close(l_sigio_private[1]);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index fbb080c..b3c11cf 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -82,8 +82,8 @@
 	if (offset) {
 		data = (unsigned long *)(mm_idp->stack +
 					 offset - UML_CONFIG_STUB_DATA);
-		printk("do_syscall_stub : ret = %d, offset = %d, "
-		       "data = 0x%x\n", ret, offset, data);
+		printk("do_syscall_stub : ret = %ld, offset = %ld, "
+		       "data = %p\n", ret, offset, data);
 		syscall = (unsigned long *)((unsigned long)data + data[0]);
 		printk("do_syscall_stub: syscall %ld failed, return value = "
 		       "0x%lx, expected return value = 0x%lx\n",
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bbf34cb..0776bc1 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -265,7 +265,7 @@
 		if(err)
 			panic("userspace - could not resume userspace process, "
 			      "pid=%d, ptrace operation = %d, errno = %d\n",
-			      op, errno);
+			      pid, op, errno);
 
 		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
 		if(err < 0)
@@ -369,7 +369,7 @@
 	 */
 	wait_stub_done(pid, -1, "copy_context_skas0");
 	if (child_data->err != UML_CONFIG_STUB_DATA)
-		panic("copy_context_skas0 - stub-child reports error %d\n",
+		panic("copy_context_skas0 - stub-child reports error %ld\n",
 		      child_data->err);
 
 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
@@ -434,7 +434,7 @@
 		void (*handler)(int))
 {
 	unsigned long flags;
-	sigjmp_buf switch_buf, fork_buf;
+	jmp_buf switch_buf, fork_buf;
 	int enable;
 
 	*switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@
 	 */
 	flags = get_signals();
 	block_signals();
-	if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+	if(UML_SETJMP(&fork_buf, enable) == 0)
 		new_thread_proc(stack, handler);
 
 	remove_sigstack();
@@ -466,35 +466,35 @@
 
 void thread_wait(void *sw, void *fb)
 {
-	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+	jmp_buf buf, **switch_buf = sw, *fork_buf;
 	int enable;
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(UML_SIGSETJMP(&buf, enable) == 0)
+	if(UML_SETJMP(&buf, enable) == 0)
 		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
 }
 
 void switch_threads(void *me, void *next)
 {
-	sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
 	int enable;
 
 	*me_ptr = &my_buf;
-	if(UML_SIGSETJMP(&my_buf, enable) == 0)
-		UML_SIGLONGJMP(next_buf, 1);
+	if(UML_SETJMP(&my_buf, enable) == 0)
+		UML_LONGJMP(next_buf, 1);
 }
 
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
 
 /* XXX Make these percpu */
 static void (*cb_proc)(void *arg);
 static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
 
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
-	sigjmp_buf **switch_buf = switch_buf_ptr;
+	jmp_buf **switch_buf = switch_buf_ptr;
 	int n, enable;
 
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@
 		    SIGVTALRM, -1);
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+	n = UML_SETJMP(&initial_jmpbuf, enable);
 	switch(n){
 	case INIT_JMP_NEW_THREAD:
 		new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@
 		break;
 	case INIT_JMP_CALLBACK:
 		(*cb_proc)(cb_arg);
-		UML_SIGLONGJMP(cb_back, 1);
+		UML_LONGJMP(cb_back, 1);
 		break;
 	case INIT_JMP_HALT:
 		kmalloc_ok = 0;
@@ -523,12 +523,12 @@
 	default:
 		panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
 	}
-	UML_SIGLONGJMP(*switch_buf, 1);
+	UML_LONGJMP(*switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
-	sigjmp_buf here;
+	jmp_buf here;
 	int enable;
 
 	cb_proc = proc;
@@ -536,8 +536,8 @@
 	cb_back = &here;
 
 	block_signals();
-	if(UML_SIGSETJMP(&here, enable) == 0)
-		UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+	if(UML_SETJMP(&here, enable) == 0)
+		UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -548,13 +548,13 @@
 void halt_skas(void)
 {
 	block_signals();
-	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
 void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 387e26a..5031485 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,29 +296,7 @@
 	check_sysemu();
 }
 
-extern int create_tmp_file(unsigned long 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);
-}
+extern void check_tmpexec(void);
 
 void os_early_checks(void)
 {
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
index ba21f0e..120abbe 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <linux/unistd.h>
 #include "sysdep/tls.h"
 #include "user_util.h"
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26..90b29ae 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@
 
 void do_longjmp(void *b, int val)
 {
-	sigjmp_buf *buf = b;
+	jmp_buf *buf = b;
 
-	UML_SIGLONGJMP(buf, val);
+	UML_LONGJMP(buf, val);
 }
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66..e523719 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@
 	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
 	int enable;
 
-	sigjmp_buf jbuf;
+	jmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(UML_SIGSETJMP(&jbuf, enable) == 0){
+	if(UML_SETJMP(&jbuf, enable) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 198e591..34bfc1b 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -120,7 +120,8 @@
 
 	dead = 0;
 	fd = open(file, O_RDONLY);
-	if(fd < 0){
+	if(fd < 0) {
+		fd = -errno;
 		if(fd != -ENOENT){
 			printk("not_dead_yet : couldn't open pid file '%s', "
 			       "err = %d\n", file, -fd);
@@ -130,9 +131,13 @@
 
 	err = 0;
 	n = read(fd, pid, sizeof(pid));
-	if(n <= 0){
+	if(n < 0){
 		printk("not_dead_yet : couldn't read pid file '%s', "
-		       "err = %d\n", file, -n);
+		       "err = %d\n", file, errno);
+		goto out_close;
+	} else if(n == 0){
+		printk("not_dead_yet : couldn't read pid file '%s', "
+		       "0-byte read\n", file);
 		goto out_close;
 	}
 
@@ -155,9 +160,9 @@
 
 	return err;
 
- out_close:
+out_close:
 	close(fd);
- out:
+out:
 	return 0;
 }
 
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 8da6ab3..2598158 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -18,14 +18,19 @@
 extern void *memset(void *, int, size_t);
 extern int printf(const char *, ...);
 
+/* If they're not defined, the export is included in lib/string.c.*/
+#ifdef __HAVE_ARCH_STRLEN
 EXPORT_SYMBOL(strlen);
+#endif
+#ifdef __HAVE_ARCH_STRSTR
+EXPORT_SYMBOL(strstr);
+#endif
+
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(printf);
 
-EXPORT_SYMBOL(strstr);
-
 /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
  * However, the modules will use the CRC defined *here*, no matter if it is
  * good; so the versions of these symbols will always match
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e..c47a2a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@
 int setjmp_wrapper(void (*proc)(void *, void *), ...)
 {
 	va_list args;
-	sigjmp_buf buf;
+	jmp_buf buf;
 	int n;
 
 	n = sigsetjmp(buf, 1);
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index b696b45..5e7a9c3 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -9,10 +9,8 @@
 
 $(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \
 	c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
-$(USER_OBJS): cmd_checksrc =
-$(USER_OBJS): quiet_cmd_checksrc =
-$(USER_OBJS): cmd_force_checksrc =
-$(USER_OBJS): quiet_cmd_force_checksrc =
+$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
+	-Dunix -D__unix__ -D__$(SUBARCH)__
 
 
 # The stubs and unmap.o can't try to call mcount or update basic block data
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index db524ab3..2a1eac1 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -15,7 +15,3 @@
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial);
-
-/* delay core functions */
-EXPORT_SYMBOL(__const_udelay);
-EXPORT_SYMBOL(__udelay);
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 9f3bd8e..40aa885 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -57,7 +57,7 @@
 		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
 			  regs[i]) < 0)
 			printk("write_debugregs - ptrace failed on "
-			       "register %d, value = 0x%x, errno = %d\n", i,
+			       "register %d, value = 0x%lx, errno = %d\n", i,
 			       regs[i], errno);
 	}
 }
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index f5d0e1c..0709fc6 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -57,7 +57,7 @@
 	return(0);
 }
 
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate __user *to_fp,
+int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
                          struct pt_regs *regs, unsigned long sp)
 {
   	struct sigcontext sc;
@@ -132,7 +132,7 @@
 	return(err);
 }
 
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
 		       struct sigcontext *from, int fpsize, unsigned long sp)
 {
 	struct _fpstate __user *to_fp;
@@ -147,7 +147,7 @@
 	 * delivery.  The sp passed in is the original, and this needs
 	 * to be restored, so we stick it in separately.
 	 */
-	err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+	err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
 
 	if(from_fp != NULL){
 		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
@@ -167,7 +167,7 @@
 	return(ret);
 }
 
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate __user *fp,
+static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
 			   struct pt_regs *from, unsigned long sp)
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
index a37f672..2355dc1 100644
--- a/arch/um/sys-i386/stub_segv.c
+++ b/arch/um/sys-i386/stub_segv.c
@@ -27,6 +27,6 @@
 	 * the stack in its original form when we do the sigreturn here, by
 	 * hand.
 	 */
-	__asm__("mov %0,%%esp ; movl %1, %%eax ; "
-		"int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+	__asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+			     "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
 }
diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
index a3188e8..71b9796 100644
--- a/arch/um/sys-i386/tls.c
+++ b/arch/um/sys-i386/tls.c
@@ -378,7 +378,7 @@
 	} else
 		printk(KERN_ERR "  Host TLS support NOT detected! "
 				"TLS support inside UML will not work\n");
-	return 1;
+	return 0;
 }
 
 __initcall(__setup_host_supports_tls);
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index e75c4e1..a4c46a8 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -137,7 +137,7 @@
 	 * delivery.  The sp passed in is the original, and this needs
 	 * to be restored, so we stick it in separately.
 	 */
-	err |= copy_to_user(&SC_SP(to), sp, sizeof(sp));
+	err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
 
 	if(from_fp != NULL){
 		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
index a270995..1c96702 100644
--- a/arch/um/sys-x86_64/stub_segv.c
+++ b/arch/um/sys-x86_64/stub_segv.c
@@ -33,7 +33,7 @@
 	struct ucontext *uc;
         int pid;
 
-	__asm__("movq %%rdx, %0" : "=g" (uc) :);
+	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
 	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
 			      &uc->uc_mcontext);
 
@@ -44,8 +44,8 @@
 	 * the signal frame.  So, we use the ucontext pointer, which we know
 	 * already, to get the signal frame pointer, and add 8 to that.
 	 */
-	__asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
-		"g" ((unsigned long) container_of(uc, struct rt_sigframe, 
-						  uc) + 8),
-                "g" (__NR_rt_sigreturn));
+	__asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+                             "g" ((unsigned long)
+                                  container_of(uc, struct rt_sigframe, uc) + 8),
+                             "g" (__NR_rt_sigreturn));
 }
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 8ffc29c..6bcfcfe 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -43,7 +43,6 @@
 EXPORT_SYMBOL (strchr);
 EXPORT_SYMBOL (strlen);
 EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strpbrk);
 EXPORT_SYMBOL (strrchr);
 EXPORT_SYMBOL (strstr);
 EXPORT_SYMBOL (memset);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 4310b4a..408d44a 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -136,6 +136,11 @@
 	default "7" if GENERIC_CPU || MPSC
 	default "6" if MK8
 
+config X86_INTERNODE_CACHE_BYTES
+	int
+	default "4096" if X86_VSMP
+	default X86_L1_CACHE_BYTES if !X86_VSMP
+
 config X86_TSC
 	bool
 	default y
@@ -283,6 +288,11 @@
 	 Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
 	 instead, which also takes priority if both are compiled in.   
 
+config NODES_SHIFT
+	int
+	default "6"
+	depends on NEED_MULTIPLE_NODES
+
 # Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig.
 
 config X86_64_ACPI_NUMA
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 585fd4a..e573e2a 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -24,37 +24,37 @@
 LDFLAGS		:= -m elf_x86_64
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux :=
-
 CHECKFLAGS      += -D__x86_64__ -m64
 
+cflags-y	:=
 cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
 cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
 cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
-CFLAGS += $(cflags-y)
 
-CFLAGS += -m64
-CFLAGS += -mno-red-zone
-CFLAGS += -mcmodel=kernel
-CFLAGS += -pipe
+cflags-y += -m64
+cflags-y += -mno-red-zone
+cflags-y += -mcmodel=kernel
+cflags-y += -pipe
 cflags-$(CONFIG_REORDER) += -ffunction-sections
 # this makes reading assembly source easier, but produces worse code
 # actually it makes the kernel smaller too.
-CFLAGS += -fno-reorder-blocks	
-CFLAGS += -Wno-sign-compare
+cflags-y += -fno-reorder-blocks
+cflags-y += -Wno-sign-compare
 ifneq ($(CONFIG_UNWIND_INFO),y)
-CFLAGS += -fno-asynchronous-unwind-tables
+cflags-y += -fno-asynchronous-unwind-tables
 endif
 ifneq ($(CONFIG_DEBUG_INFO),y)
 # -fweb shrinks the kernel a bit, but the difference is very small
 # it also messes up debugging, so don't use it for now.
-#CFLAGS += $(call cc-option,-fweb)
+#cflags-y += $(call cc-option,-fweb)
 endif
 # -funit-at-a-time shrinks the kernel .text considerably
 # unfortunately it makes reading oopses harder.
-CFLAGS += $(call cc-option,-funit-at-a-time)
+cflags-y += $(call cc-option,-funit-at-a-time)
 # prevent gcc from generating any FP code by mistake
-CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
 
+CFLAGS += $(cflags-y)
 AFLAGS += -m64
 
 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
index 0587477..32327bb 100644
--- a/arch/x86_64/boot/video.S
+++ b/arch/x86_64/boot/video.S
@@ -97,6 +97,7 @@
 #define PARAM_VESAPM_OFF	0x30
 #define PARAM_LFB_PAGES		0x32
 #define PARAM_VESA_ATTRIB	0x34
+#define PARAM_CAPABILITIES	0x36
 
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
@@ -233,6 +234,10 @@
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
 
+# store mode capabilities
+	movl 10(%di), %eax
+	movl %eax, %fs:(PARAM_CAPABILITIES)
+
 # switching the DAC to 8-bit is for <= 8 bpp only
 	movw	%fs:(PARAM_LFB_DEPTH), %ax
 	cmpw	$8, %ax
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 566ecc9..69db0c0 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-git9
-# Sat Mar 25 15:18:40 2006
+# Linux kernel version: 2.6.17-rc1-git11
+# Sun Apr 16 07:22:36 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -9,6 +9,7 @@
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
@@ -55,11 +56,8 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
+CONFIG_DOUBLEFAULT=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -70,7 +68,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
@@ -81,6 +78,7 @@
 #
 CONFIG_LBD=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -105,6 +103,7 @@
 CONFIG_GENERIC_CPU=y
 CONFIG_X86_L1_CACHE_BYTES=128
 CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 # CONFIG_MICROCODE is not set
@@ -116,12 +115,14 @@
 CONFIG_MTRR=y
 CONFIG_SMP=y
 CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
 CONFIG_PREEMPT_BKL=y
 CONFIG_NUMA=y
 CONFIG_K8_NUMA=y
+CONFIG_NODES_SHIFT=6
 CONFIG_X86_64_ACPI_NUMA=y
 CONFIG_NUMA_EMU=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
@@ -138,6 +139,7 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_OUT_OF_LINE_PFN_TO_PAGE=y
 CONFIG_NR_CPUS=32
 CONFIG_HOTPLUG_CPU=y
 CONFIG_HPET_TIMER=y
@@ -289,6 +291,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -300,6 +303,7 @@
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
@@ -542,7 +546,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -704,7 +707,6 @@
 # Wireless LAN (non-hamradio)
 #
 # CONFIG_NET_RADIO is not set
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
 
 #
 # Wan interfaces
@@ -791,7 +793,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -921,6 +923,7 @@
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -932,6 +935,8 @@
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -1041,9 +1046,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1058,15 +1061,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1118,9 +1112,23 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
+# CONFIG_IPATH_CORE is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1128,6 +1136,11 @@
 # CONFIG_EDAC is not set
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 929e6b0..e9263b4 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -27,5 +27,5 @@
 $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
 	$(call if_changed,syscall)
 
-AFLAGS_vsyscall-sysenter.o = -m32
-AFLAGS_vsyscall-syscall.o = -m32
+AFLAGS_vsyscall-sysenter.o = -m32 -Wa,-32
+AFLAGS_vsyscall-syscall.o = -m32 -Wa,-32
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 35b2fac..57fc37e 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -15,6 +15,8 @@
 #include <asm/vsyscall32.h>
 #include <linux/linkage.h>
 
+#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+
 	.macro IA32_ARG_FIXUP noebp=0
 	movl	%edi,%r8d
 	.if \noebp
@@ -109,8 +111,8 @@
 	CFI_REMEMBER_STATE
 	jnz  sysenter_tracesys
 sysenter_do_call:	
-	cmpl	$(IA32_NR_syscalls),%eax
-	jae	ia32_badsys
+	cmpl	$(IA32_NR_syscalls-1),%eax
+	ja	ia32_badsys
 	IA32_ARG_FIXUP 1
 	call	*ia32_sys_call_table(,%rax,8)
 	movq	%rax,RAX-ARGOFFSET(%rsp)
@@ -210,8 +212,8 @@
 	CFI_REMEMBER_STATE
 	jnz   cstar_tracesys
 cstar_do_call:	
-	cmpl $IA32_NR_syscalls,%eax
-	jae  ia32_badsys
+	cmpl $IA32_NR_syscalls-1,%eax
+	ja  ia32_badsys
 	IA32_ARG_FIXUP 1
 	call *ia32_sys_call_table(,%rax,8)
 	movq %rax,RAX-ARGOFFSET(%rsp)
@@ -296,8 +298,8 @@
 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz ia32_tracesys
 ia32_do_syscall:	
-	cmpl $(IA32_NR_syscalls),%eax
-	jae  ia32_badsys
+	cmpl $(IA32_NR_syscalls-1),%eax
+	ja  ia32_badsys
 	IA32_ARG_FIXUP
 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
@@ -685,12 +687,12 @@
 	.quad sys_readlinkat		/* 305 */
 	.quad sys_fchmodat
 	.quad sys_faccessat
-	.quad sys_ni_syscall		/* pselect6 for now */
-	.quad sys_ni_syscall		/* ppoll for now */
+	.quad quiet_ni_syscall		/* pselect6 for now */
+	.quad quiet_ni_syscall		/* ppoll for now */
 	.quad sys_unshare		/* 310 */
 	.quad compat_sys_set_robust_list
 	.quad compat_sys_get_robust_list
+	.quad sys_splice
+	.quad sys_sync_file_range
+	.quad sys_tee
 ia32_syscall_end:		
-	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
-		.quad ni_syscall
-	.endr
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index a098a11..059c883 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -8,7 +8,7 @@
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
 		x8664_ksyms.o i387.o syscall.o vsyscall.o \
 		setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
-		dmi_scan.o pci-dma.o pci-nommu.o
+		pci-dma.o pci-nommu.o
 
 obj-$(CONFIG_X86_MCE)         += mce.o
 obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
@@ -49,5 +49,3 @@
 quirks-y			+= ../../i386/kernel/quirks.o
 i8237-y				+= ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
-dmi_scan-y			+= ../../i386/kernel/dmi_scan.o
-
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index fffd6b0..70b9d21 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -80,7 +80,7 @@
 		printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
 		return 0; 
 	}
-	if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {  
+	if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
 		printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
 		return 0; 
 	} 
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 293cd71..62776c0 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -80,7 +80,12 @@
 	return 0;
 } 
 
-int __init e820_mapped(unsigned long start, unsigned long end, unsigned type) 
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int __meminit
+e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
 { 
 	int i;
 	for (i = 0; i < e820.nr_map; i++) { 
@@ -94,6 +99,35 @@
 	return 0;
 }
 
+/*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+	int i;
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		if (type && ei->type != type)
+			continue;
+		/* is the region (part) in overlap with the current region ?*/
+		if (ei->addr >= end || ei->addr + ei->size <= start)
+			continue;
+
+		/* if the region is at the beginning of <start,end> we move
+		 * start to the end of the region since it's ok until there
+		 */
+		if (ei->addr <= start)
+			start = ei->addr + ei->size;
+		/* if start is now at or beyond end, we're done, full coverage */
+		if (start >= end)
+			return 1; /* we're done */
+	}
+	return 0;
+}
+
 /* 
  * Find a free area in a specific range. 
  */ 
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 8538bfe..c946e4f 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -180,6 +180,10 @@
  *
  * XXX	if we had a free scratch register we could save the RSP into the stack frame
  *      and report it properly in ps. Unfortunately we haven't.
+ *
+ * When user can change the frames always force IRET. That is because
+ * it deals with uncanonical addresses better. SYSRET has trouble
+ * with them due to bugs in both AMD and Intel CPUs.
  */ 			 		
 
 ENTRY(system_call)
@@ -254,7 +258,10 @@
 	xorl %esi,%esi # oldset -> arg2
 	call ptregscall_common
 1:	movl $_TIF_NEED_RESCHED,%edi
-	jmp sysret_check
+	/* Use IRET because user could have changed frame. This
+	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+	cli
+	jmp int_with_check
 	
 badsys:
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
@@ -280,7 +287,8 @@
 	call syscall_trace_leave
 	RESTORE_TOP_OF_STACK %rbx
 	RESTORE_REST
-	jmp ret_from_sys_call
+	/* Use IRET because user could have changed frame */
+	jmp int_ret_from_sys_call
 	CFI_ENDPROC
 		
 /* 
@@ -408,25 +416,9 @@
 	CFI_ADJUST_CFA_OFFSET -8
 	CFI_REGISTER rip, r11
 	SAVE_REST
-	movq %r11, %r15
-	CFI_REGISTER rip, r15
 	FIXUP_TOP_OF_STACK %r11
 	call sys_execve
-	GET_THREAD_INFO(%rcx)
-	bt $TIF_IA32,threadinfo_flags(%rcx)
-	CFI_REMEMBER_STATE
-	jc exec_32bit
 	RESTORE_TOP_OF_STACK %r11
-	movq %r15, %r11
-	CFI_REGISTER rip, r11
-	RESTORE_REST
-	pushq %r11
-	CFI_ADJUST_CFA_OFFSET 8
-	CFI_REL_OFFSET rip, 0
-	ret
-
-exec_32bit:
-	CFI_RESTORE_STATE
 	movq %rax,RAX(%rsp)
 	RESTORE_REST
 	jmp int_ret_from_sys_call
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index accbff3..1eaa5da 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -53,7 +53,7 @@
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t *insn)
+static __always_inline int is_IF_modifier(kprobe_opcode_t *insn)
 {
 	switch (*insn) {
 	case 0xfa:		/* cli */
@@ -84,7 +84,7 @@
  * If it does, return the address of the 32-bit displacement word.
  * If not, return null.
  */
-static inline s32 *is_riprel(u8 *insn)
+static s32 __kprobes *is_riprel(u8 *insn)
 {
 #define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf)		      \
 	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
@@ -229,7 +229,7 @@
 	mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	kcb->prev_kprobe.kp = kprobe_running();
 	kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -237,7 +237,7 @@
 	kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
 	kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -245,7 +245,7 @@
 	kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
 				struct kprobe_ctlblk *kcb)
 {
 	__get_cpu_var(current_kprobe) = p;
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 10b3e34..c69fc43 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -29,6 +29,8 @@
 #define MISC_MCELOG_MINOR 227
 #define NR_BANKS 6
 
+atomic_t mce_entry;
+
 static int mce_dont_init;
 
 /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic,
@@ -172,10 +174,12 @@
 	int i;
 	int panicm_found = 0;
 
+	atomic_inc(&mce_entry);
+
 	if (regs)
 		notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
 	if (!banks)
-		return;
+		goto out2;
 
 	memset(&m, 0, sizeof(struct mce));
 	m.cpu = safe_smp_processor_id();
@@ -266,6 +270,8 @@
  out:
 	/* Last thing done in the machine check exception to clear state. */
 	wrmsrl(MSR_IA32_MCG_STATUS, 0);
+ out2:
+	atomic_dec(&mce_entry);
 }
 
 /*
@@ -623,7 +629,7 @@
 #endif
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
 mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index d3ad7d8..d13b241 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -482,7 +482,7 @@
 #endif
 
 /* get notified when a cpu comes on/off */
-static __cpuinit int threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
 					    unsigned long action, void *hcpu)
 {
 	/* cpu was unsigned int to begin with */
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index d9e4067..4e6357f 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -34,6 +34,7 @@
 #include <asm/proto.h>
 #include <asm/kdebug.h>
 #include <asm/local.h>
+#include <asm/mce.h>
 
 /*
  * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -480,6 +481,12 @@
 		__get_cpu_var(nmi_touch) = 0;
 		touched = 1;
 	}
+#ifdef CONFIG_X86_MCE
+	/* Could check oops_in_progress here too, but it's safer
+	   not too */
+	if (atomic_read(&mce_entry) > 0)
+		touched = 1;
+#endif
 	if (!touched && __get_cpu_var(last_irq_sum) == sum) {
 		/*
 		 * Ayiee, looks like this CPU is stuck ...
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 03c9eee..af035ed 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -48,9 +48,11 @@
 {
 	struct page *page;
 	int node;
+#ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
 		node = pcibus_to_node(to_pci_dev(dev)->bus);
 	else
+#endif
 		node = numa_node_id();
 	page = alloc_pages_node(node, gfp, order);
 	return page ? page_address(page) : NULL;
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index a6c01e1..9d3d76c 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -112,10 +112,6 @@
 static void free_iommu(unsigned long offset, int size)
 { 
 	unsigned long flags;
-	if (size == 1) { 
-		clear_bit(offset, iommu_gart_bitmap); 
-		return;
-	}
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
 	__clear_bit_string(iommu_gart_bitmap, offset, size);
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 70dd8e5..fb903e6 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -575,8 +575,10 @@
 	prev->userrsp = read_pda(oldrsp); 
 	write_pda(oldrsp, next->userrsp); 
 	write_pda(pcurrent, next_p); 
+
 	/* This must be here to ensure both math_state_restore() and
-	   kernel_fpu_begin() work consistently. */
+	   kernel_fpu_begin() work consistently. 
+	   And the AMD workaround requires it to be after DS reload. */
 	unlazy_fpu(prev_p);
 	write_pda(kernelstack,
 		  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
@@ -781,10 +783,16 @@
 	}
 	case ARCH_GET_GS: { 
 		unsigned long base;
+		unsigned gsindex;
 		if (task->thread.gsindex == GS_TLS_SEL)
 			base = read_32bit_tls(task, GS_TLS);
-		else if (doit)
-			rdmsrl(MSR_KERNEL_GS_BASE, base);
+		else if (doit) {
+ 			asm("movl %%gs,%0" : "=r" (gsindex));
+			if (gsindex)
+				rdmsrl(MSR_KERNEL_GS_BASE, base);
+			else
+				base = task->thread.gs;
+		}
 		else
 			base = task->thread.gs;
 		ret = put_user(base, (unsigned long __user *)addr); 
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index d44b2c1..da8e790 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -274,11 +274,6 @@
 				return -EIO;
 			value &= 0xffff;
 			break;
-		case offsetof(struct user_regs_struct, rip):
-			/* Check if the new RIP address is canonical */
-			if (value >= TASK_SIZE_OF(child))
-				return -EIO;
-			break;
 	}
 	put_stack_long(child, regno - sizeof(struct pt_regs), value);
 	return 0;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 0856ad4..759070c 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -353,8 +353,10 @@
 		if (fullarg(from, "enable_timer_pin_1"))
 			disable_timer_pin_1 = -1;
 
-		if (fullarg(from, "nolapic") || fullarg(from, "disableapic"))
+		if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
+			clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
 			disable_apic = 1;
+		}
 
 		if (fullarg(from, "noapic"))
 			skip_ioapic_setup = 1;
@@ -928,6 +930,10 @@
 	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
 
+	/* Enable workaround for FXSAVE leak */
+	if (c->x86 >= 6)
+		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
+
 	r = get_model_name(c);
 	if (!r) { 
 		switch (c->x86) { 
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index ef8bc46..7392570 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -726,7 +726,7 @@
 	unsigned int 		ntimer;
 
 	if (!vxtime.hpet_address)
-        	return -1;
+        	return 0;
 
 	memset(&hd, 0, sizeof (hd));
 
@@ -917,6 +917,8 @@
 		vxtime.hpet_address = 0;
 
 	if (hpet_use_timer) {
+		/* set tick_nsec to use the proper rate for HPET */
+	  	tick_nsec = TICK_NSEC_HPET;
 		cpu_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 #ifdef CONFIG_X86_PM_TIMER
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 6bda322..2700b13 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/nmi.h>
 #include <linux/kprobes.h>
+#include <linux/kexec.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -433,6 +434,8 @@
 	printk(KERN_ALERT "RIP ");
 	printk_address(regs->rip); 
 	printk(" RSP <%016lx>\n", regs->rsp); 
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
 }
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -455,6 +458,8 @@
 	 */
 	printk(str, safe_smp_processor_id());
 	show_registers(regs);
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
 	if (panic_on_timeout || panic_on_oops)
 		panic("nmi watchdog");
 	printk("console shuts up ...\n");
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 39ff070..b81f473 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -65,7 +65,7 @@
   .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
 	*(.data.cacheline_aligned)
   }
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+  . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
   .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
   	*(.data.read_mostly)
   }
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index d78f460..1def21c 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -112,7 +112,6 @@
 #undef memcpy
 #undef memset
 #undef memmove
-#undef strlen
 
 extern void * memset(void *,int,__kernel_size_t);
 extern size_t strlen(const char *);
@@ -121,8 +120,6 @@
 extern void * __memcpy(void *,const void *,__kernel_size_t);
 
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index e5f7f1c..4ba34e9 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -305,7 +305,7 @@
 		if (paddr >= end)
 			break;
 
-		if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
+		if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) {
 			set_pud(pud, __pud(0)); 
 			continue;
 		} 
@@ -507,9 +507,8 @@
 
 /*
  * Memory hotplug specific functions
- * These are only for non-NUMA machines right now.
  */
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 
 void online_page(struct page *page)
 {
@@ -520,6 +519,38 @@
 	num_physpages++;
 }
 
+#ifndef CONFIG_MEMORY_HOTPLUG
+/*
+ * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
+ * just online the pages.
+ */
+int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
+{
+	int err = -EIO;
+	unsigned long pfn;
+	unsigned long total = 0, mem = 0;
+	for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
+		if (pfn_valid(pfn)) {
+			online_page(pfn_to_page(pfn));
+			err = 0;
+			mem++;
+		}
+		total++;
+	}
+	if (!err) {
+		z->spanned_pages += total;
+		z->present_pages += mem;
+		z->zone_pgdat->node_spanned_pages += total;
+		z->zone_pgdat->node_present_pages += mem;
+	}
+	return err;
+}
+#endif
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
 int add_memory(u64 start, u64 size)
 {
 	struct pglist_data *pgdat = NODE_DATA(0);
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 4be82d6..b2fac14 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -100,11 +100,30 @@
 }
 #endif
 
+static void * __init
+early_node_mem(int nodeid, unsigned long start, unsigned long end,
+	      unsigned long size)
+{
+	unsigned long mem = find_e820_area(start, end, size);
+	void *ptr;
+	if (mem != -1L)
+		return __va(mem);
+	ptr = __alloc_bootmem_nopanic(size,
+				SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS));
+	if (ptr == 0) {
+		printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
+			size, nodeid);
+		return NULL;
+	}
+	return ptr;
+}
+
 /* Initialize bootmem allocator for a node */
 void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 { 
 	unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; 
 	unsigned long nodedata_phys;
+	void *bootmap;
 	const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE);
 
 	start = round_up(start, ZONE_ALIGN); 
@@ -114,13 +133,11 @@
 	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
 
-	nodedata_phys = find_e820_area(start, end, pgdat_size); 
-	if (nodedata_phys == -1L) 
-		panic("Cannot find memory pgdat in node %d\n", nodeid);
+	node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size);
+	if (node_data[nodeid] == NULL)
+		return;
+	nodedata_phys = __pa(node_data[nodeid]);
 
-	Dprintk("nodedata_phys %lx\n", nodedata_phys); 
-
-	node_data[nodeid] = phys_to_virt(nodedata_phys);
 	memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
 	NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
 	NODE_DATA(nodeid)->node_start_pfn = start_pfn;
@@ -129,9 +146,15 @@
 	/* Find a place for the bootmem map */
 	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 
 	bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE);
-	bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<<PAGE_SHIFT);
-	if (bootmap_start == -1L) 
-		panic("Not enough continuous space for bootmap on node %d", nodeid); 
+	bootmap = early_node_mem(nodeid, bootmap_start, end,
+					bootmap_pages<<PAGE_SHIFT);
+	if (bootmap == NULL)  {
+		if (nodedata_phys < start || nodedata_phys >= end)
+			free_bootmem((unsigned long)node_data[nodeid],pgdat_size);
+		node_data[nodeid] = NULL;
+		return;
+	}
+	bootmap_start = __pa(bootmap);
 	Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); 
 	
 	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
@@ -142,6 +165,9 @@
 
 	reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); 
 	reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
+#ifdef CONFIG_ACPI_NUMA
+	srat_reserve_add_area(nodeid);
+#endif
 	node_set_online(nodeid);
 } 
 
@@ -162,11 +188,13 @@
 	   memory. */
 	memmapsize = sizeof(struct page) * (end_pfn-start_pfn);
 	limit = end_pfn << PAGE_SHIFT;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
 	NODE_DATA(nodeid)->node_mem_map = 
 		__alloc_bootmem_core(NODE_DATA(nodeid)->bdata, 
 				memmapsize, SMP_CACHE_BYTES, 
 				round_down(limit - memmapsize, PAGE_SIZE), 
 				limit);
+#endif
 
 	size_zones(zones, holes, start_pfn, end_pfn);
 	free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
@@ -335,6 +363,8 @@
 #ifdef CONFIG_ACPI_NUMA
  	if (!strncmp(opt,"noacpi",6))
  		acpi_numa = -1;
+	if (!strncmp(opt,"hotadd=", 7))
+		hotadd_percent = simple_strtoul(opt+7, NULL, 10);
 #endif
 	return 1;
 } 
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 2eb8795..15ae9fc 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -15,15 +15,26 @@
 #include <linux/bitmap.h>
 #include <linux/module.h>
 #include <linux/topology.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
 #include <asm/proto.h>
 #include <asm/numa.h>
 #include <asm/e820.h>
 
+#if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
+	defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
+		&& !defined(CONFIG_MEMORY_HOTPLUG)
+#define RESERVE_HOTADD 1
+#endif
+
 static struct acpi_table_slit *acpi_slit;
 
 static nodemask_t nodes_parsed __initdata;
 static nodemask_t nodes_found __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
+static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
+static int found_add_area __initdata;
+int hotadd_percent __initdata = 10;
 static u8 pxm2node[256] = { [0 ... 255] = 0xff };
 
 /* Too small nodes confuse the VM badly. Usually they result
@@ -71,6 +82,10 @@
 static __init void cutoff_node(int i, unsigned long start, unsigned long end)
 {
 	struct bootnode *nd = &nodes[i];
+
+	if (found_add_area)
+		return;
+
 	if (nd->start < start) {
 		nd->start = start;
 		if (nd->end < nd->start)
@@ -90,6 +105,8 @@
 	acpi_numa = -1;
 	for (i = 0; i < MAX_LOCAL_APIC; i++)
 		apicid_to_node[i] = NUMA_NO_NODE;
+	for (i = 0; i < MAX_NUMNODES; i++)
+		nodes_add[i].start = nodes[i].end = 0;
 }
 
 static __init inline int srat_disabled(void)
@@ -155,11 +172,114 @@
 	       pxm, pa->apic_id, node);
 }
 
+#ifdef RESERVE_HOTADD
+/*
+ * Protect against too large hotadd areas that would fill up memory.
+ */
+static int hotadd_enough_memory(struct bootnode *nd)
+{
+	static unsigned long allocated;
+	static unsigned long last_area_end;
+	unsigned long pages = (nd->end - nd->start) >> PAGE_SHIFT;
+	long mem = pages * sizeof(struct page);
+	unsigned long addr;
+	unsigned long allowed;
+	unsigned long oldpages = pages;
+
+	if (mem < 0)
+		return 0;
+	allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+	allowed = (allowed / 100) * hotadd_percent;
+	if (allocated + mem > allowed) {
+		/* Give them at least part of their hotadd memory upto hotadd_percent
+		   It would be better to spread the limit out
+		   over multiple hotplug areas, but that is too complicated
+		   right now */
+		if (allocated >= allowed)
+			return 0;
+		pages = (allowed - allocated + mem) / sizeof(struct page);
+		mem = pages * sizeof(struct page);
+		nd->end = nd->start + pages*PAGE_SIZE;
+	}
+	/* Not completely fool proof, but a good sanity check */
+	addr = find_e820_area(last_area_end, end_pfn<<PAGE_SHIFT, mem);
+	if (addr == -1UL)
+		return 0;
+	if (pages != oldpages)
+		printk(KERN_NOTICE "SRAT: Hotadd area limited to %lu bytes\n",
+			pages << PAGE_SHIFT);
+	last_area_end = addr + mem;
+	allocated += mem;
+	return 1;
+}
+
+/*
+ * It is fine to add this area to the nodes data it will be used later
+ * This code supports one contigious hot add area per node.
+ */
+static int reserve_hotadd(int node, unsigned long start, unsigned long end)
+{
+	unsigned long s_pfn = start >> PAGE_SHIFT;
+	unsigned long e_pfn = end >> PAGE_SHIFT;
+	int changed = 0;
+	struct bootnode *nd = &nodes_add[node];
+
+	/* I had some trouble with strange memory hotadd regions breaking
+	   the boot. Be very strict here and reject anything unexpected.
+	   If you want working memory hotadd write correct SRATs.
+
+	   The node size check is a basic sanity check to guard against
+	   mistakes */
+	if ((signed long)(end - start) < NODE_MIN_SIZE) {
+		printk(KERN_ERR "SRAT: Hotplug area too small\n");
+		return -1;
+	}
+
+	/* This check might be a bit too strict, but I'm keeping it for now. */
+	if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
+		printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+		return -1;
+	}
+
+	if (!hotadd_enough_memory(&nodes_add[node]))  {
+		printk(KERN_ERR "SRAT: Hotplug area too large\n");
+		return -1;
+	}
+
+	/* Looks good */
+
+ 	found_add_area = 1;
+	if (nd->start == nd->end) {
+ 		nd->start = start;
+ 		nd->end = end;
+		changed = 1;
+ 	} else {
+ 		if (nd->start == end) {
+ 			nd->start = start;
+			changed = 1;
+		}
+ 		if (nd->end == start) {
+ 			nd->end = end;
+			changed = 1;
+		}
+		if (!changed)
+			printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
+ 	}
+
+ 	if ((nd->end >> PAGE_SHIFT) > end_pfn)
+ 		end_pfn = nd->end >> PAGE_SHIFT;
+
+	if (changed)
+	 	printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n", nd->start, nd->end);
+	return 0;
+}
+#endif
+
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
 void __init
 acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
 {
-	struct bootnode *nd;
+	struct bootnode *nd, oldnode;
 	unsigned long start, end;
 	int node, pxm;
 	int i;
@@ -172,6 +292,8 @@
 	}
 	if (ma->flags.enabled == 0)
 		return;
+ 	if (ma->flags.hot_pluggable && hotadd_percent == 0)
+		return;
 	start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32);
 	end = start + (ma->length_lo | ((u64)ma->length_hi << 32));
 	pxm = ma->proximity_domain;
@@ -181,10 +303,6 @@
 		bad_srat();
 		return;
 	}
-	/* It is fine to add this area to the nodes data it will be used later*/
-	if (ma->flags.hot_pluggable == 1)
-		printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
-				start, end);
 	i = conflicting_nodes(start, end);
 	if (i == node) {
 		printk(KERN_WARNING
@@ -199,6 +317,7 @@
 		return;
 	}
 	nd = &nodes[node];
+	oldnode = *nd;
 	if (!node_test_and_set(node, nodes_parsed)) {
 		nd->start = start;
 		nd->end = end;
@@ -208,8 +327,19 @@
 		if (nd->end < end)
 			nd->end = end;
 	}
+
 	printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
 	       nd->start, nd->end);
+
+#ifdef RESERVE_HOTADD
+ 	if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
+		/* Ignore hotadd region. Undo damage */
+		printk(KERN_NOTICE "SRAT: Hotplug region ignored\n");
+		*nd = oldnode;
+		if ((nd->start | nd->end) == 0)
+			node_clear(node, nodes_parsed);
+	}
+#endif
 }
 
 /* Sanity check to catch more bad SRATs (they are amazingly common).
@@ -225,6 +355,9 @@
 		unsigned long e = nodes[i].end >> PAGE_SHIFT;
 		pxmram += e - s;
 		pxmram -= e820_hole_size(s, e);
+		pxmram -= nodes_add[i].end - nodes_add[i].start;
+		if ((long)pxmram < 0)
+			pxmram = 0;
 	}
 
 	e820ram = end_pfn - e820_hole_size(0, end_pfn);
@@ -258,7 +391,7 @@
 
 	/* First clean up the node list */
 	for (i = 0; i < MAX_NUMNODES; i++) {
-		cutoff_node(i, start, end);
+ 		cutoff_node(i, start, end);
 		if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE)
 			unparse_node(i);
 	}
@@ -282,6 +415,12 @@
 	/* Finally register nodes */
 	for_each_node_mask(i, nodes_parsed)
 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+	/* Try again in case setup_node_bootmem missed one due
+	   to missing bootmem */
+	for_each_node_mask(i, nodes_parsed)
+		if (!node_online(i))
+			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+
 	for (i = 0; i < NR_CPUS; i++) { 
 		if (cpu_to_node[i] == NUMA_NO_NODE)
 			continue;
@@ -303,6 +442,25 @@
        return 0;
 }
 
+void __init srat_reserve_add_area(int nodeid)
+{
+	if (found_add_area && nodes_add[nodeid].end) {
+		u64 total_mb;
+
+		printk(KERN_INFO "SRAT: Reserving hot-add memory space "
+				"for node %d at %Lx-%Lx\n",
+			nodeid, nodes_add[nodeid].start, nodes_add[nodeid].end);
+		total_mb = (nodes_add[nodeid].end - nodes_add[nodeid].start)
+					>> PAGE_SHIFT;
+		total_mb *= sizeof(struct page);
+		total_mb >>= 20;
+		printk(KERN_INFO "SRAT: This will cost you %Lu MB of "
+				"pre-allocated memory.\n", (unsigned long long)total_mb);
+		reserve_bootmem_node(NODE_DATA(nodeid), nodes_add[nodeid].start,
+			       nodes_add[nodeid].end - nodes_add[nodeid].start);
+	}
+}
+
 int __node_distance(int a, int b)
 {
 	int index;
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index e616500..a2060e4 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,11 +9,16 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
+#include <asm/e820.h>
+
 #include "pci.h"
 
 #define MMCONFIG_APER_SIZE (256*1024*1024)
+/* Verify the first 16 busses. We assume that systems with more busses
+   get MCFG right. */
+#define MAX_CHECK_BUS 16
 
-static DECLARE_BITMAP(fallback_slots, 32);
+static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
 
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
@@ -55,7 +60,8 @@
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
 	char __iomem *addr;
-	if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots))
+	if (seg == 0 && bus < MAX_CHECK_BUS &&
+		test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
 		return NULL;
 	addr = get_virt(seg, bus);
 	if (!addr)
@@ -69,8 +75,10 @@
 	char __iomem *addr;
 
 	/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
-	if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
+	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+		*value = -1;
 		return -EINVAL;
+	}
 
 	addr = pci_dev_base(seg, bus, devfn);
 	if (!addr)
@@ -129,21 +137,26 @@
    Normally this can be expressed in the MCFG by not listing them
    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
    Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them.
-   We only do this for bus 0/seg 0 */
+   and fallback for them. */
 static __init void unreachable_devices(void)
 {
-	int i;
-	for (i = 0; i < 32; i++) {
-		u32 val1;
-		char __iomem *addr;
+	int i, k;
+	/* Use the max bus number from ACPI here? */
+	for (k = 0; k < MAX_CHECK_BUS; k++) {
+		for (i = 0; i < 32; i++) {
+			u32 val1;
+			char __iomem *addr;
 
-		pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
-		if (val1 == 0xffffffff)
-			continue;
-		addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
-		if (addr == NULL|| readl(addr) != val1) {
-			set_bit(i, fallback_slots);
+			pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
+			if (val1 == 0xffffffff)
+				continue;
+			addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
+			if (addr == NULL|| readl(addr) != val1) {
+				set_bit(i + 32*k, fallback_slots);
+				printk(KERN_NOTICE
+				"PCI: No mmconfig possible on device %x:%x\n",
+					k, i);
+			}
 		}
 	}
 }
@@ -161,6 +174,14 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
+	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			E820_RESERVED)) {
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+		return;
+	}
+
 	/* RED-PEN i386 doesn't do _nocache right now */
 	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
 	if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 152b937..a15b6e3 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -48,7 +48,6 @@
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
diff --git a/block/as-iosched.c b/block/as-iosched.c
index 296708c..e25a5d7 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -1844,9 +1844,10 @@
 	DECLARE_COMPLETION(all_gone);
 	elv_unregister(&iosched_as);
 	ioc_gone = &all_gone;
-	barrier();
+	/* ioc_gone's update must be visible before reading ioc_count */
+	smp_wmb();
 	if (atomic_read(&ioc_count))
-		complete(ioc_gone);
+		wait_for_completion(ioc_gone);
 	synchronize_rcu();
 	kmem_cache_destroy(arq_pool);
 }
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 67d446d..2540dfa 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1472,19 +1472,37 @@
 	return cfqq;
 }
 
+static void
+cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
+{
+	read_lock(&cfq_exit_lock);
+	rb_erase(&cic->rb_node, &ioc->cic_root);
+	read_unlock(&cfq_exit_lock);
+	kmem_cache_free(cfq_ioc_pool, cic);
+	atomic_dec(&ioc_count);
+}
+
 static struct cfq_io_context *
 cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
 {
-	struct rb_node *n = ioc->cic_root.rb_node;
+	struct rb_node *n;
 	struct cfq_io_context *cic;
-	void *key = cfqd;
+	void *k, *key = cfqd;
 
+restart:
+	n = ioc->cic_root.rb_node;
 	while (n) {
 		cic = rb_entry(n, struct cfq_io_context, rb_node);
+		/* ->key must be copied to avoid race with cfq_exit_queue() */
+		k = cic->key;
+		if (unlikely(!k)) {
+			cfq_drop_dead_cic(ioc, cic);
+			goto restart;
+		}
 
-		if (key < cic->key)
+		if (key < k)
 			n = n->rb_left;
-		else if (key > cic->key)
+		else if (key > k)
 			n = n->rb_right;
 		else
 			return cic;
@@ -1497,29 +1515,37 @@
 cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
 	     struct cfq_io_context *cic)
 {
-	struct rb_node **p = &ioc->cic_root.rb_node;
-	struct rb_node *parent = NULL;
+	struct rb_node **p;
+	struct rb_node *parent;
 	struct cfq_io_context *__cic;
-
-	read_lock(&cfq_exit_lock);
+	void *k;
 
 	cic->ioc = ioc;
 	cic->key = cfqd;
 
 	ioc->set_ioprio = cfq_ioc_set_ioprio;
-
+restart:
+	parent = NULL;
+	p = &ioc->cic_root.rb_node;
 	while (*p) {
 		parent = *p;
 		__cic = rb_entry(parent, struct cfq_io_context, rb_node);
+		/* ->key must be copied to avoid race with cfq_exit_queue() */
+		k = __cic->key;
+		if (unlikely(!k)) {
+			cfq_drop_dead_cic(ioc, cic);
+			goto restart;
+		}
 
-		if (cic->key < __cic->key)
+		if (cic->key < k)
 			p = &(*p)->rb_left;
-		else if (cic->key > __cic->key)
+		else if (cic->key > k)
 			p = &(*p)->rb_right;
 		else
 			BUG();
 	}
 
+	read_lock(&cfq_exit_lock);
 	rb_link_node(&cic->rb_node, parent, p);
 	rb_insert_color(&cic->rb_node, &ioc->cic_root);
 	list_add(&cic->queue_list, &cfqd->cic_list);
@@ -2439,9 +2465,10 @@
 	DECLARE_COMPLETION(all_gone);
 	elv_unregister(&iosched_cfq);
 	ioc_gone = &all_gone;
-	barrier();
+	/* ioc_gone's update must be visible before reading ioc_count */
+	smp_wmb();
 	if (atomic_read(&ioc_count))
-		complete(ioc_gone);
+		wait_for_completion(ioc_gone);
 	synchronize_rcu();
 	cfq_slab_kill();
 }
diff --git a/block/elevator.c b/block/elevator.c
index 0d6be03..2982579 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -895,10 +895,8 @@
 EXPORT_SYMBOL(elv_dispatch_sort);
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_requeue_request);
 EXPORT_SYMBOL(elv_next_request);
 EXPORT_SYMBOL(elv_dequeue_request);
 EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elv_completed_request);
 EXPORT_SYMBOL(elevator_exit);
 EXPORT_SYMBOL(elevator_init);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 5b26af8..e5041a0 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1554,7 +1554,7 @@
 	 * don't plug a stopped queue, it must be paired with blk_start_queue()
 	 * which will restart the queueing
 	 */
-	if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+	if (blk_queue_stopped(q))
 		return;
 
 	if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
@@ -1587,7 +1587,7 @@
  */
 void __generic_unplug_device(request_queue_t *q)
 {
-	if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
+	if (unlikely(blk_queue_stopped(q)))
 		return;
 
 	if (!blk_remove_plug(q))
@@ -1740,7 +1740,7 @@
 
 /**
  * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
- * @q:    the request queue to be released
+ * @kobj:    the kobj belonging of the request queue to be released
  *
  * Description:
  *     blk_cleanup_queue is the pair to blk_init_queue() or
@@ -3385,7 +3385,7 @@
 }
 
 
-static struct notifier_block __devinitdata blk_cpu_notifier = {
+static struct notifier_block blk_cpu_notifier = {
 	.notifier_call	= blk_cpu_notify,
 };
 
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 24f7af9..b33eda2 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -350,16 +350,51 @@
 	return ret;
 }
 
+/**
+ * sg_scsi_ioctl  --  handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl
+ * @file:	file this ioctl operates on (optional)
+ * @q:		request queue to send scsi commands down
+ * @disk:	gendisk to operate on (option)
+ * @sic:	userspace structure describing the command to perform
+ *
+ * Send down the scsi command described by @sic to the device below
+ * the request queue @q.  If @file is non-NULL it's used to perform
+ * fine-grained permission checks that allow users to send down
+ * non-destructive SCSI commands.  If the caller has a struct gendisk
+ * available it should be passed in as @disk to allow the low level
+ * driver to use the information contained in it.  A non-NULL @disk
+ * is only allowed if the caller knows that the low level driver doesn't
+ * need it (e.g. in the scsi subsystem).
+ *
+ * Notes:
+ *   -  This interface is deprecated - users should use the SG_IO
+ *      interface instead, as this is a more flexible approach to
+ *      performing SCSI commands on a device.
+ *   -  The SCSI command length is determined by examining the 1st byte
+ *      of the given command. There is no way to override this.
+ *   -  Data transfers are limited to PAGE_SIZE
+ *   -  The length (x + y) must be at least OMAX_SB_LEN bytes long to
+ *      accommodate the sense buffer when an error occurs.
+ *      The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
+ *      old code will not be surprised.
+ *   -  If a Unix error occurs (e.g. ENOMEM) then the user will receive
+ *      a negative return and the Unix error code in 'errno'.
+ *      If the SCSI command succeeds then 0 is returned.
+ *      Positive numbers returned are the compacted SCSI error codes (4
+ *      bytes in one int) where the lowest byte is the SCSI status.
+ */
 #define OMAX_SB_LEN 16          /* For backward compatibility */
-
-static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
-			 struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
+int sg_scsi_ioctl(struct file *file, struct request_queue *q,
+		  struct gendisk *disk, struct scsi_ioctl_command __user *sic)
 {
 	struct request *rq;
 	int err;
 	unsigned int in_len, out_len, bytes, opcode, cmdlen;
 	char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
 
+	if (!sic)
+		return -EINVAL;
+
 	/*
 	 * get in an out lengths, verify they don't exceed a page worth of data
 	 */
@@ -393,45 +428,53 @@
 	if (copy_from_user(rq->cmd, sic->data, cmdlen))
 		goto error;
 
-	if (copy_from_user(buffer, sic->data + cmdlen, in_len))
+	if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
 	err = verify_command(file, rq->cmd);
 	if (err)
 		goto error;
 
+	/* default.  possible overriden later */
+	rq->retries = 5;
+
 	switch (opcode) {
-		case SEND_DIAGNOSTIC:
-		case FORMAT_UNIT:
-			rq->timeout = FORMAT_UNIT_TIMEOUT;
-			break;
-		case START_STOP:
-			rq->timeout = START_STOP_TIMEOUT;
-			break;
-		case MOVE_MEDIUM:
-			rq->timeout = MOVE_MEDIUM_TIMEOUT;
-			break;
-		case READ_ELEMENT_STATUS:
-			rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
-			break;
-		case READ_DEFECT_DATA:
-			rq->timeout = READ_DEFECT_DATA_TIMEOUT;
-			break;
-		default:
-			rq->timeout = BLK_DEFAULT_TIMEOUT;
-			break;
+	case SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+		rq->timeout = FORMAT_UNIT_TIMEOUT;
+		rq->retries = 1;
+		break;
+	case START_STOP:
+		rq->timeout = START_STOP_TIMEOUT;
+		break;
+	case MOVE_MEDIUM:
+		rq->timeout = MOVE_MEDIUM_TIMEOUT;
+		break;
+	case READ_ELEMENT_STATUS:
+		rq->timeout = READ_ELEMENT_STATUS_TIMEOUT;
+		break;
+	case READ_DEFECT_DATA:
+		rq->timeout = READ_DEFECT_DATA_TIMEOUT;
+		rq->retries = 1;
+		break;
+	default:
+		rq->timeout = BLK_DEFAULT_TIMEOUT;
+		break;
+	}
+
+	if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
+		err = DRIVER_ERROR << 24;
+		goto out;
 	}
 
 	memset(sense, 0, sizeof(sense));
 	rq->sense = sense;
 	rq->sense_len = 0;
-
-	rq->data = buffer;
-	rq->data_len = bytes;
 	rq->flags |= REQ_BLOCK_PC;
-	rq->retries = 0;
 
-	blk_execute_rq(q, bd_disk, rq, 0);
+	blk_execute_rq(q, disk, rq, 0);
+
+out:
 	err = rq->errors & 0xff;	/* only 8 bit SCSI status */
 	if (err) {
 		if (rq->sense_len && rq->sense) {
@@ -450,7 +493,7 @@
 	blk_put_request(rq);
 	return err;
 }
-
+EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
 
 /* Send basic block requests */
 static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 5c91d6a..aeb5ab2 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -68,8 +68,6 @@
 
 source "drivers/infiniband/Kconfig"
 
-source "drivers/sn/Kconfig"
-
 source "drivers/edac/Kconfig"
 
 source "drivers/rtc/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 55205c8..447d8e6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -69,6 +69,7 @@
 obj-$(CONFIG_MMC)		+= mmc/
 obj-$(CONFIG_NEW_LEDS)		+= leds/
 obj-$(CONFIG_INFINIBAND)	+= infiniband/
+obj-$(CONFIG_IPATH_CORE)	+= infiniband/
 obj-$(CONFIG_SGI_SN)		+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5cb9630..c24652d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -329,7 +329,7 @@
 config ACPI_HOTPLUG_MEMORY
 	tristate "Memory Hotplug"
 	depends on ACPI
-	depends on MEMORY_HOTPLUG
+	depends on MEMORY_HOTPLUG || X86_64
 	default n
 	help
 	  This driver adds supports for ACPI Memory Hotplug.  This driver
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 48718b7..76656ac 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -188,6 +188,11 @@
 		up(&dev->sem);
 		if (dev->parent)
 			up(&dev->parent->sem);
+
+		if (err > 0) 		/* success */
+			err = count;
+		else if (err == 0)	/* driver didn't accept device */
+			err = -ENODEV;
 	}
 	put_device(dev);
 	put_bus(bus);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index df7fdab..0e71dff 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -562,14 +562,13 @@
 	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 
 	/* notify any interfaces this device is now here */
-	if (parent_class) {
-		down(&parent_class->sem);
-		list_add_tail(&class_dev->node, &parent_class->children);
-		list_for_each_entry(class_intf, &parent_class->interfaces, node)
-			if (class_intf->add)
-				class_intf->add(class_dev, class_intf);
-		up(&parent_class->sem);
+	down(&parent_class->sem);
+	list_add_tail(&class_dev->node, &parent_class->children);
+	list_for_each_entry(class_intf, &parent_class->interfaces, node) {
+		if (class_intf->add)
+			class_intf->add(class_dev, class_intf);
 	}
+	up(&parent_class->sem);
 
  register_done:
 	if (error) {
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 730a9ce..889c711 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -209,7 +209,7 @@
 		sysfs_remove_link(&dev->kobj, "driver");
 		klist_remove(&dev->knode_driver);
 
-		if (dev->bus->remove)
+		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 16c513a..c80c3ae 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -106,7 +106,7 @@
 	other_node = 0;
 	for (i = 0; i < MAX_NR_ZONES; i++) {
 		struct zone *z = &pg->node_zones[i];
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		for_each_online_cpu(cpu) {
 			struct per_cpu_pageset *ps = zone_pcp(z,cpu);
 			numa_hit += ps->numa_hit;
 			numa_miss += ps->numa_miss;
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index bdb6066..662209d 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -10,6 +10,8 @@
 
 #include <linux/vt_kern.h>
 #include <linux/device.h>
+#include <linux/kallsyms.h>
+#include <linux/pm.h>
 #include "../base.h"
 #include "power.h"
 
@@ -58,6 +60,7 @@
 	if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
 		dev_dbg(dev, "suspending\n");
 		error = dev->bus->suspend(dev, state);
+		suspend_report_result(dev->bus->suspend, error);
 	}
 	up(&dev->sem);
 	return error;
@@ -169,3 +172,12 @@
 
 EXPORT_SYMBOL_GPL(device_power_down);
 
+void __suspend_report_result(const char *function, void *fn, int ret)
+{
+	if (ret) {
+		printk(KERN_ERR "%s(): ", function);
+		print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
+		printk("%d\n", ret);
+	}
+}
+EXPORT_SYMBOL_GPL(__suspend_report_result);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 915810f..8c52421 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
+static int topology_cpu_callback(struct notifier_block *nfb,
 		unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1b0fd31..1319d8f 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1180,6 +1180,53 @@
         return 0;
 }
 
+static inline void complete_buffers(struct bio *bio, int status)
+{
+	while (bio) {
+		struct bio *xbh = bio->bi_next;
+		int nr_sectors = bio_sectors(bio);
+
+		bio->bi_next = NULL;
+		blk_finished_io(len);
+		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+		bio = xbh;
+	}
+
+}
+
+static void cciss_softirq_done(struct request *rq)
+{
+	CommandList_struct *cmd = rq->completion_data;
+	ctlr_info_t *h = hba[cmd->ctlr];
+	unsigned long flags;
+	u64bit temp64;
+	int i, ddir;
+
+	if (cmd->Request.Type.Direction == XFER_READ)
+		ddir = PCI_DMA_FROMDEVICE;
+	else
+		ddir = PCI_DMA_TODEVICE;
+
+	/* command did not need to be retried */
+	/* unmap the DMA mapping for all the scatter gather elements */
+	for(i=0; i<cmd->Header.SGList; i++) {
+		temp64.val32.lower = cmd->SG[i].Addr.lower;
+		temp64.val32.upper = cmd->SG[i].Addr.upper;
+		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+	}
+
+	complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+	printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+	spin_lock_irqsave(&h->lock, flags);
+	end_that_request_last(rq, rq->errors);
+	cmd_free(h, cmd,1);
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
 /* 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
@@ -1248,6 +1295,8 @@
 
 		blk_queue_max_sectors(disk->queue, 512);
 
+		blk_queue_softirq_done(disk->queue, cciss_softirq_done);
+
 		disk->queue->queuedata = hba[ctlr];
 
 		blk_queue_hardsect_size(disk->queue,
@@ -2147,20 +2196,6 @@
 		addQ (&(h->cmpQ), c); 
 	}
 }
-
-static inline void complete_buffers(struct bio *bio, int status)
-{
-	while (bio) {
-		struct bio *xbh = bio->bi_next; 
-		int nr_sectors = bio_sectors(bio);
-
-		bio->bi_next = NULL; 
-		blk_finished_io(len);
-		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
-		bio = xbh;
-	}
-
-} 
 /* Assumes that CCISS_LOCK(h->ctlr) is held. */
 /* Zeros out the error record and then resends the command back */
 /* to the controller */
@@ -2178,39 +2213,6 @@
 	start_io(h);
 }
 
-static void cciss_softirq_done(struct request *rq)
-{
-	CommandList_struct *cmd = rq->completion_data;
-	ctlr_info_t *h = hba[cmd->ctlr];
-	unsigned long flags;
-	u64bit temp64;
-	int i, ddir;
-
-	if (cmd->Request.Type.Direction == XFER_READ)
-		ddir = PCI_DMA_FROMDEVICE;
-	else
-		ddir = PCI_DMA_TODEVICE;
-
-	/* command did not need to be retried */
-	/* unmap the DMA mapping for all the scatter gather elements */
-	for(i=0; i<cmd->Header.SGList; i++) {
-		temp64.val32.lower = cmd->SG[i].Addr.lower;
-		temp64.val32.upper = cmd->SG[i].Addr.upper;
-		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
-	}
-
-	complete_buffers(rq->bio, rq->errors);
-
-#ifdef CCISS_DEBUG
-	printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */ 
-
-	spin_lock_irqsave(&h->lock, flags);
-	end_that_request_last(rq, rq->errors);
-	cmd_free(h, cmd,1);
-	spin_unlock_irqrestore(&h->lock, flags);
-}
-
 /* checks the status of the job and calls complete buffers to mark all 
  * buffers for the completed job. Note that this function does not need
  * to hold the hba/queue lock.
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 9888bc1..473a13b 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -65,7 +65,7 @@
 
 
 typedef struct bluecard_info_t {
-	dev_link_t link;
+	struct pcmcia_device *p_dev;
 	dev_node_t node;
 
 	struct hci_dev *hdev;
@@ -85,8 +85,8 @@
 } bluecard_info_t;
 
 
-static void bluecard_config(dev_link_t *link);
-static void bluecard_release(dev_link_t *link);
+static int bluecard_config(struct pcmcia_device *link);
+static void bluecard_release(struct pcmcia_device *link);
 
 static void bluecard_detach(struct pcmcia_device *p_dev);
 
@@ -162,7 +162,7 @@
 static void bluecard_activity_led_timeout(u_long arg)
 {
 	bluecard_info_t *info = (bluecard_info_t *)arg;
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 
 	if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		return;
@@ -179,7 +179,7 @@
 
 static void bluecard_enable_activity_led(bluecard_info_t *info)
 {
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 
 	if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		return;
@@ -235,7 +235,7 @@
 	}
 
 	do {
-		register unsigned int iobase = info->link.io.BasePort1;
+		register unsigned int iobase = info->p_dev->io.BasePort1;
 		register unsigned int offset;
 		register unsigned char command;
 		register unsigned long ready_bit;
@@ -244,7 +244,7 @@
 
 		clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-		if (!(info->link.state & DEV_PRESENT))
+		if (!pcmcia_dev_present(info->p_dev))
 			return;
 
 		if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
@@ -382,7 +382,7 @@
 		return;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
 		bluecard_enable_activity_led(info);
@@ -512,7 +512,7 @@
 	if (!test_bit(CARD_READY, &(info->hw_state)))
 		return IRQ_HANDLED;
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	spin_lock(&(info->lock));
 
@@ -626,7 +626,7 @@
 static int bluecard_hci_open(struct hci_dev *hdev)
 {
 	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 
 	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -646,7 +646,7 @@
 static int bluecard_hci_close(struct hci_dev *hdev)
 {
 	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 
 	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
 		return 0;
@@ -713,7 +713,7 @@
 
 static int bluecard_open(bluecard_info_t *info)
 {
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev;
 	unsigned char id;
 
@@ -831,7 +831,7 @@
 
 static int bluecard_close(bluecard_info_t *info)
 {
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
@@ -856,17 +856,16 @@
 	return 0;
 }
 
-static int bluecard_attach(struct pcmcia_device *p_dev)
+static int bluecard_probe(struct pcmcia_device *link)
 {
 	bluecard_info_t *info;
-	dev_link_t *link;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -878,32 +877,22 @@
 	link->irq.Instance = info;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	bluecard_config(link);
-
-	return 0;
+	return bluecard_config(link);
 }
 
 
-static void bluecard_detach(struct pcmcia_device *p_dev)
+static void bluecard_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	bluecard_info_t *info = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		bluecard_release(link);
-
+	bluecard_release(link);
 	kfree(info);
 }
 
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int i;
 
@@ -918,14 +907,12 @@
 	return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static void bluecard_config(dev_link_t *link)
+static int bluecard_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	bluecard_info_t *info = link->priv;
 	tuple_t tuple;
 	u_short buf[256];
 	cisparse_t parse;
-	config_info_t config;
 	int i, n, last_ret, last_fn;
 
 	tuple.TupleData = (cisdata_t *)buf;
@@ -935,7 +922,7 @@
 
 	/* Get configuration register information */
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, &tuple, &parse);
+	last_ret = first_tuple(link, &tuple, &parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
@@ -943,36 +930,31 @@
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	i = pcmcia_get_configuration_info(handle, &config);
-	link->conf.Vcc = config.Vcc;
-
 	link->conf.ConfigIndex = 0x20;
 	link->io.NumPorts1 = 64;
 	link->io.IOAddrLines = 6;
 
 	for (n = 0; n < 0x400; n += 0x40) {
 		link->io.BasePort1 = n ^ 0x300;
-		i = pcmcia_request_io(link->handle, &link->io);
+		i = pcmcia_request_io(link, &link->io);
 		if (i == CS_SUCCESS)
 			break;
 	}
 
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		goto failed;
 	}
 
@@ -980,57 +962,28 @@
 		goto failed;
 
 	strcpy(info->node.dev_name, info->hdev->name);
-	link->dev = &info->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &info->node;
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
 failed:
 	bluecard_release(link);
+	return -ENODEV;
 }
 
 
-static void bluecard_release(dev_link_t *link)
+static void bluecard_release(struct pcmcia_device *link)
 {
 	bluecard_info_t *info = link->priv;
 
-	if (link->state & DEV_PRESENT)
-		bluecard_close(info);
+	bluecard_close(info);
 
 	del_timer(&(info->timer));
 
-	link->dev = NULL;
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
-}
-
-static int bluecard_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int bluecard_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
+	pcmcia_disable_device(link);
 }
 
 static struct pcmcia_device_id bluecard_ids[] = {
@@ -1046,11 +999,9 @@
 	.drv		= {
 		.name	= "bluecard_cs",
 	},
-	.probe		= bluecard_attach,
+	.probe		= bluecard_probe,
 	.remove		= bluecard_detach,
 	.id_table	= bluecard_ids,
-	.suspend	= bluecard_suspend,
-	.resume		= bluecard_resume,
 };
 
 static int __init init_bluecard_cs(void)
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7e21b1f..b94ac2f 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -72,7 +72,7 @@
 
 
 typedef struct bt3c_info_t {
-	dev_link_t link;
+	struct pcmcia_device *p_dev;
 	dev_node_t node;
 
 	struct hci_dev *hdev;
@@ -88,8 +88,8 @@
 } bt3c_info_t;
 
 
-static void bt3c_config(dev_link_t *link);
-static void bt3c_release(dev_link_t *link);
+static int bt3c_config(struct pcmcia_device *link);
+static void bt3c_release(struct pcmcia_device *link);
 
 static void bt3c_detach(struct pcmcia_device *p_dev);
 
@@ -191,11 +191,11 @@
 		return;
 
 	do {
-		register unsigned int iobase = info->link.io.BasePort1;
+		register unsigned int iobase = info->p_dev->io.BasePort1;
 		register struct sk_buff *skb;
 		register int len;
 
-		if (!(info->link.state & DEV_PRESENT))
+		if (!pcmcia_dev_present(info->p_dev))
 			break;
 
 
@@ -229,7 +229,7 @@
 		return;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	avail = bt3c_read(iobase, 0x7006);
 	//printk("bt3c_cs: receiving %d bytes\n", avail);
@@ -350,7 +350,7 @@
 		return IRQ_NONE;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	spin_lock(&(info->lock));
 
@@ -481,7 +481,7 @@
 	unsigned int iobase, size, addr, fcs, tmp;
 	int i, err = 0;
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	/* Reset */
 	bt3c_io_write(iobase, 0x8040, 0x0404);
@@ -562,7 +562,6 @@
 {
 	const struct firmware *firmware;
 	struct hci_dev *hdev;
-	client_handle_t handle;
 	int err;
 
 	spin_lock_init(&(info->lock));
@@ -594,10 +593,8 @@
 
 	hdev->owner = THIS_MODULE;
 
-	handle = info->link.handle;
-
 	/* Load firmware */
-	err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle));
+	err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
 	if (err < 0) {
 		BT_ERR("Firmware request failed");
 		goto error;
@@ -648,17 +645,16 @@
 	return 0;
 }
 
-static int bt3c_attach(struct pcmcia_device *p_dev)
+static int bt3c_probe(struct pcmcia_device *link)
 {
 	bt3c_info_t *info;
-	dev_link_t *link;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -670,31 +666,21 @@
 	link->irq.Instance = info;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	bt3c_config(link);
-
-	return 0;
+	return bt3c_config(link);
 }
 
 
-static void bt3c_detach(struct pcmcia_device *p_dev)
+static void bt3c_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	bt3c_info_t *info = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		bt3c_release(link);
-
+	bt3c_release(link);
 	kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int i;
 
@@ -705,30 +691,28 @@
 	return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static void bt3c_config(dev_link_t *link)
+static int bt3c_config(struct pcmcia_device *link)
 {
 	static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-	client_handle_t handle = link->handle;
 	bt3c_info_t *info = link->priv;
 	tuple_t tuple;
 	u_short buf[256];
 	cisparse_t parse;
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-	config_info_t config;
 	int i, j, try, last_ret, last_fn;
 
 	tuple.TupleData = (cisdata_t *)buf;
@@ -738,7 +722,7 @@
 
 	/* Get configuration register information */
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, &tuple, &parse);
+	last_ret = first_tuple(link, &tuple, &parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
@@ -746,11 +730,6 @@
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	i = pcmcia_get_configuration_info(handle, &config);
-	link->conf.Vcc = config.Vcc;
-
 	/* First pass: look for a config entry that looks normal. */
 	tuple.TupleData = (cisdata_t *)buf;
 	tuple.TupleOffset = 0;
@@ -759,59 +738,59 @@
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	/* Two tries: without IO aliases, then with aliases */
 	for (try = 0; try < 2; try++) {
-		i = first_tuple(handle, &tuple, &parse);
+		i = first_tuple(link, &tuple, &parse);
 		while (i != CS_NO_MORE_ITEMS) {
 			if (i != CS_SUCCESS)
 				goto next_entry;
 			if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-				link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+				link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 			if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
 				link->conf.ConfigIndex = cf->index;
 				link->io.BasePort1 = cf->io.win[0].base;
 				link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				if (i == CS_SUCCESS)
 					goto found_port;
 			}
 next_entry:
-			i = next_tuple(handle, &tuple, &parse);
+			i = next_tuple(link, &tuple, &parse);
 		}
 	}
 
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(link, &tuple, &parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
 			link->conf.ConfigIndex = cf->index;
 			for (j = 0; j < 5; j++) {
 				link->io.BasePort1 = base[j];
 				link->io.IOAddrLines = base[j] ? 16 : 3;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				if (i == CS_SUCCESS)
 					goto found_port;
 			}
 		}
-		i = next_tuple(handle, &tuple, &parse);
+		i = next_tuple(link, &tuple, &parse);
 	}
 
 found_port:
 	if (i != CS_SUCCESS) {
 		BT_ERR("No usable port range found");
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		goto failed;
 	}
 
@@ -819,55 +798,26 @@
 		goto failed;
 
 	strcpy(info->node.dev_name, info->hdev->name);
-	link->dev = &info->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &info->node;
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
 failed:
 	bt3c_release(link);
+	return -ENODEV;
 }
 
 
-static void bt3c_release(dev_link_t *link)
+static void bt3c_release(struct pcmcia_device *link)
 {
 	bt3c_info_t *info = link->priv;
 
-	if (link->state & DEV_PRESENT)
-		bt3c_close(info);
+	bt3c_close(info);
 
-	link->dev = NULL;
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
-}
-
-static int bt3c_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int bt3c_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
+	pcmcia_disable_device(link);
 }
 
 
@@ -882,11 +832,9 @@
 	.drv		= {
 		.name	= "bt3c_cs",
 	},
-	.probe		= bt3c_attach,
+	.probe		= bt3c_probe,
 	.remove		= bt3c_detach,
 	.id_table	= bt3c_ids,
-	.suspend	= bt3c_suspend,
-	.resume		= bt3c_resume,
 };
 
 static int __init init_bt3c_cs(void)
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 7b4bff4..9ce4c93 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -68,7 +68,7 @@
 
 
 typedef struct btuart_info_t {
-	dev_link_t link;
+	struct pcmcia_device *p_dev;
 	dev_node_t node;
 
 	struct hci_dev *hdev;
@@ -84,8 +84,8 @@
 } btuart_info_t;
 
 
-static void btuart_config(dev_link_t *link);
-static void btuart_release(dev_link_t *link);
+static int btuart_config(struct pcmcia_device *link);
+static void btuart_release(struct pcmcia_device *link);
 
 static void btuart_detach(struct pcmcia_device *p_dev);
 
@@ -146,13 +146,13 @@
 	}
 
 	do {
-		register unsigned int iobase = info->link.io.BasePort1;
+		register unsigned int iobase = info->p_dev->io.BasePort1;
 		register struct sk_buff *skb;
 		register int len;
 
 		clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-		if (!(info->link.state & DEV_PRESENT))
+		if (!pcmcia_dev_present(info->p_dev))
 			return;
 
 		if (!(skb = skb_dequeue(&(info->txq))))
@@ -187,7 +187,7 @@
 		return;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	do {
 		info->hdev->stat.byte_rx++;
@@ -301,7 +301,7 @@
 		return IRQ_NONE;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	spin_lock(&(info->lock));
 
@@ -357,7 +357,7 @@
 		return;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	spin_lock_irqsave(&(info->lock), flags);
 
@@ -481,7 +481,7 @@
 static int btuart_open(btuart_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev;
 
 	spin_lock_init(&(info->lock));
@@ -550,7 +550,7 @@
 static int btuart_close(btuart_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
@@ -576,17 +576,16 @@
 	return 0;
 }
 
-static int btuart_attach(struct pcmcia_device *p_dev)
+static int btuart_probe(struct pcmcia_device *link)
 {
 	btuart_info_t *info;
-	dev_link_t *link;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -598,31 +597,21 @@
 	link->irq.Instance = info;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	btuart_config(link);
-
-	return 0;
+	return btuart_config(link);
 }
 
 
-static void btuart_detach(struct pcmcia_device *p_dev)
+static void btuart_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	btuart_info_t *info = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		btuart_release(link);
-
+	btuart_release(link);
 	kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int i;
 
@@ -633,30 +622,28 @@
 	return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static void btuart_config(dev_link_t *link)
+static int btuart_config(struct pcmcia_device *link)
 {
 	static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-	client_handle_t handle = link->handle;
 	btuart_info_t *info = link->priv;
 	tuple_t tuple;
 	u_short buf[256];
 	cisparse_t parse;
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-	config_info_t config;
 	int i, j, try, last_ret, last_fn;
 
 	tuple.TupleData = (cisdata_t *)buf;
@@ -666,7 +653,7 @@
 
 	/* Get configuration register information */
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, &tuple, &parse);
+	last_ret = first_tuple(link, &tuple, &parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
@@ -674,11 +661,6 @@
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	i = pcmcia_get_configuration_info(handle, &config);
-	link->conf.Vcc = config.Vcc;
-
 	/* First pass: look for a config entry that looks normal. */
 	tuple.TupleData = (cisdata_t *) buf;
 	tuple.TupleOffset = 0;
@@ -687,29 +669,29 @@
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	/* Two tries: without IO aliases, then with aliases */
 	for (try = 0; try < 2; try++) {
-		i = first_tuple(handle, &tuple, &parse);
+		i = first_tuple(link, &tuple, &parse);
 		while (i != CS_NO_MORE_ITEMS) {
 			if (i != CS_SUCCESS)
 				goto next_entry;
 			if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-				link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+				link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 			if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
 				link->conf.ConfigIndex = cf->index;
 				link->io.BasePort1 = cf->io.win[0].base;
 				link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				if (i == CS_SUCCESS)
 					goto found_port;
 			}
 next_entry:
-			i = next_tuple(handle, &tuple, &parse);
+			i = next_tuple(link, &tuple, &parse);
 		}
 	}
 
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(link, &tuple, &parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
 		    && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -717,30 +699,30 @@
 			for (j = 0; j < 5; j++) {
 				link->io.BasePort1 = base[j];
 				link->io.IOAddrLines = base[j] ? 16 : 3;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				if (i == CS_SUCCESS)
 					goto found_port;
 			}
 		}
-		i = next_tuple(handle, &tuple, &parse);
+		i = next_tuple(link, &tuple, &parse);
 	}
 
 found_port:
 	if (i != CS_SUCCESS) {
 		BT_ERR("No usable port range found");
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		goto failed;
 	}
 
@@ -748,58 +730,28 @@
 		goto failed;
 
 	strcpy(info->node.dev_name, info->hdev->name);
-	link->dev = &info->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &info->node;
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
 failed:
 	btuart_release(link);
+	return -ENODEV;
 }
 
 
-static void btuart_release(dev_link_t *link)
+static void btuart_release(struct pcmcia_device *link)
 {
 	btuart_info_t *info = link->priv;
 
-	if (link->state & DEV_PRESENT)
-		btuart_close(info);
+	btuart_close(info);
 
-	link->dev = NULL;
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int btuart_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int btuart_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
-
-
 static struct pcmcia_device_id btuart_ids[] = {
 	/* don't use this driver. Use serial_cs + hci_uart instead */
 	PCMCIA_DEVICE_NULL
@@ -811,11 +763,9 @@
 	.drv		= {
 		.name	= "btuart_cs",
 	},
-	.probe		= btuart_attach,
+	.probe		= btuart_probe,
 	.remove		= btuart_detach,
 	.id_table	= btuart_ids,
-	.suspend	= btuart_suspend,
-	.resume		= btuart_resume,
 };
 
 static int __init init_btuart_cs(void)
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 0449bc4..a71a240 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -68,7 +68,7 @@
 
 
 typedef struct dtl1_info_t {
-	dev_link_t link;
+	struct pcmcia_device *p_dev;
 	dev_node_t node;
 
 	struct hci_dev *hdev;
@@ -87,8 +87,8 @@
 } dtl1_info_t;
 
 
-static void dtl1_config(dev_link_t *link);
-static void dtl1_release(dev_link_t *link);
+static int dtl1_config(struct pcmcia_device *link);
+static void dtl1_release(struct pcmcia_device *link);
 
 static void dtl1_detach(struct pcmcia_device *p_dev);
 
@@ -153,13 +153,13 @@
 	}
 
 	do {
-		register unsigned int iobase = info->link.io.BasePort1;
+		register unsigned int iobase = info->p_dev->io.BasePort1;
 		register struct sk_buff *skb;
 		register int len;
 
 		clear_bit(XMIT_WAKEUP, &(info->tx_state));
 
-		if (!(info->link.state & DEV_PRESENT))
+		if (!pcmcia_dev_present(info->p_dev))
 			return;
 
 		if (!(skb = skb_dequeue(&(info->txq))))
@@ -218,7 +218,7 @@
 		return;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	do {
 		info->hdev->stat.byte_rx++;
@@ -305,7 +305,7 @@
 		return IRQ_NONE;
 	}
 
-	iobase = info->link.io.BasePort1;
+	iobase = info->p_dev->io.BasePort1;
 
 	spin_lock(&(info->lock));
 
@@ -458,7 +458,7 @@
 static int dtl1_open(dtl1_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev;
 
 	spin_lock_init(&(info->lock));
@@ -504,7 +504,7 @@
 	outb(UART_LCR_WLEN8, iobase + UART_LCR);	/* Reset DLAB */
 	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 
-	info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+	info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
 
 	/* Turn on interrupts */
 	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
@@ -529,7 +529,7 @@
 static int dtl1_close(dtl1_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->link.io.BasePort1;
+	unsigned int iobase = info->p_dev->io.BasePort1;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
@@ -555,17 +555,16 @@
 	return 0;
 }
 
-static int dtl1_attach(struct pcmcia_device *p_dev)
+static int dtl1_probe(struct pcmcia_device *link)
 {
 	dtl1_info_t *info;
-	dev_link_t *link;
 
 	/* Create new info device */
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -577,31 +576,22 @@
 	link->irq.Instance = info;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	dtl1_config(link);
-
-	return 0;
+	return dtl1_config(link);
 }
 
 
-static void dtl1_detach(struct pcmcia_device *p_dev)
+static void dtl1_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	dtl1_info_t *info = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		dtl1_release(link);
+	dtl1_release(link);
 
 	kfree(info);
 }
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int i;
 
@@ -612,29 +602,27 @@
 	return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
 		return CS_NO_MORE_ITEMS;
 	return get_tuple(handle, tuple, parse);
 }
 
-static void dtl1_config(dev_link_t *link)
+static int dtl1_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	dtl1_info_t *info = link->priv;
 	tuple_t tuple;
 	u_short buf[256];
 	cisparse_t parse;
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-	config_info_t config;
 	int i, last_ret, last_fn;
 
 	tuple.TupleData = (cisdata_t *)buf;
@@ -644,7 +632,7 @@
 
 	/* Get configuration register information */
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, &tuple, &parse);
+	last_ret = first_tuple(link, &tuple, &parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
@@ -652,11 +640,6 @@
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	i = pcmcia_get_configuration_info(handle, &config);
-	link->conf.Vcc = config.Vcc;
-
 	tuple.TupleData = (cisdata_t *)buf;
 	tuple.TupleOffset = 0;
 	tuple.TupleDataMax = 255;
@@ -665,34 +648,34 @@
 
 	/* Look for a generic full-sized window */
 	link->io.NumPorts1 = 8;
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(link, &tuple, &parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
 			link->conf.ConfigIndex = cf->index;
 			link->io.BasePort1 = cf->io.win[0].base;
 			link->io.NumPorts1 = cf->io.win[0].len;	/*yo */
 			link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-			i = pcmcia_request_io(link->handle, &link->io);
+			i = pcmcia_request_io(link, &link->io);
 			if (i == CS_SUCCESS)
 				break;
 		}
-		i = next_tuple(handle, &tuple, &parse);
+		i = next_tuple(link, &tuple, &parse);
 	}
 
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		goto failed;
 	}
 
@@ -700,55 +683,26 @@
 		goto failed;
 
 	strcpy(info->node.dev_name, info->hdev->name);
-	link->dev = &info->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &info->node;
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
 failed:
 	dtl1_release(link);
+	return -ENODEV;
 }
 
 
-static void dtl1_release(dev_link_t *link)
+static void dtl1_release(struct pcmcia_device *link)
 {
 	dtl1_info_t *info = link->priv;
 
-	if (link->state & DEV_PRESENT)
-		dtl1_close(info);
+	dtl1_close(info);
 
-	link->dev = NULL;
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
-}
-
-static int dtl1_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int dtl1_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
+	pcmcia_disable_device(link);
 }
 
 
@@ -765,11 +719,9 @@
 	.drv		= {
 		.name	= "dtl1_cs",
 	},
-	.probe		= dtl1_attach,
+	.probe		= dtl1_probe,
 	.remove		= dtl1_detach,
 	.id_table	= dtl1_ids,
-	.suspend	= dtl1_suspend,
-	.resume		= dtl1_resume,
 };
 
 static int __init init_dtl1_cs(void)
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index ce4a1ce..ec00489 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -1763,7 +1763,7 @@
 				release_region(azt_port, 4);
 			}
 		}
-		if ((azt_port_auto[i] == 0) || (i == 16)) {
+		if ((i == 16) || (azt_port_auto[i] == 0)) {
 			printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
 			return -EIO;
 		}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 889cad0..4022966 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -805,10 +805,6 @@
 	  Samsung S3C2410. This can provide periodic interrupt rates
 	  from 1Hz to 64Hz for user programs, and wakeup from Alarm.
 
-config RTC_VR41XX
-	tristate "NEC VR4100 series Real Time Clock Support"
-	depends on CPU_VR41XX
-
 config COBALT_LCD
 	bool "Support for Cobalt LCD"
 	depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index a73cb49..f5b01c6 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -67,7 +67,6 @@
 obj-$(CONFIG_SGI_IP27_RTC)	+= ip27-rtc.o
 obj-$(CONFIG_DS1302)		+= ds1302.o
 obj-$(CONFIG_S3C2410_RTC)	+= s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX)	+= vr41xx_rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM)	+= generic_nvram.o
 else
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index fed0a87..86a966b 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -64,6 +64,12 @@
 	{.mask = 0x00000001, .type = 0}
 };
 
+/* This function does the same thing as mask_memory() for this chipset... */
+static inline unsigned long efficeon_mask_memory(unsigned long addr)
+{
+	return addr | 0x00000001;
+}
+
 static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
 {
 	{256, 65536, 0},
@@ -251,7 +257,7 @@
 	last_page = NULL;
 	for (i = 0; i < count; i++) {
 		int index = pg_start + i;
-		unsigned long insert = mem->memory[i];
+		unsigned long insert = efficeon_mask_memory(mem->memory[i]);
 
 		page = (unsigned int *) efficeon_private.l1_table[index >> 10];
 
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 927a5bb..a370e7a 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -142,7 +142,7 @@
 	if (!boardno)
 		boardno = readb(loc + NUMCARD_OWNER_TO_PC);
 
-	if (!boardno && boardno > MAX_BOARD) {
+	if (!boardno || boardno > MAX_BOARD) {
 		printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",
 		       boardno, physloc, MAX_BOARD);
 		return 0;
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 5d72f50..46d6603 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -241,9 +241,10 @@
 static void __exit cs5535_gpio_cleanup(void)
 {
 	dev_t dev_id = MKDEV(major, 0);
+
+	cdev_del(&cs5535_gpio_cdev);
 	unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
-	if (gpio_base != 0)
-		release_region(gpio_base, CS5535_GPIO_SIZE);
+	release_region(gpio_base, CS5535_GPIO_SIZE);
 }
 
 module_init(cs5535_gpio_init);
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index edc72a6..cb76e5c 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -815,8 +815,6 @@
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 extern void *drm_ioremap(unsigned long offset, unsigned long size,
 			 drm_device_t * dev);
-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
-				 drm_device_t * dev);
 extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
 
 extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
@@ -891,7 +889,6 @@
 				/* Buffer management support (drm_bufs.h) */
 extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
 extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
-extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);
 extern int drm_addmap(drm_device_t * dev, unsigned int offset,
 		      unsigned int size, drm_map_type_t type,
 		      drm_map_flags_t flags, drm_local_map_t ** map_ptr);
@@ -1022,11 +1019,13 @@
 	map->handle = drm_ioremap(map->offset, map->size, dev);
 }
 
+#if 0
 static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
 						struct drm_device *dev)
 {
 	map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
 }
+#endif  /*  0  */
 
 static __inline__ void drm_core_ioremapfree(struct drm_map *map,
 					    struct drm_device *dev)
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index fabc930..40bfd9b 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -503,8 +503,6 @@
 	return agp_bind_memory(handle, start);
 }
 
-EXPORT_SYMBOL(drm_agp_bind_memory);
-
 /** Calls agp_unbind_memory() */
 int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
 {
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 8a9cf12..006b06d 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -386,7 +386,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(drm_rmmap_locked);
 
 int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
 {
@@ -398,7 +397,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(drm_rmmap);
 
 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
  * the last close of the device, and this is necessary for cleanup when things
@@ -1053,7 +1051,7 @@
 	return 0;
 }
 
-int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
 {
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_entry_t *entry;
@@ -1212,7 +1210,6 @@
 	atomic_dec(&dev->buf_alloc);
 	return 0;
 }
-EXPORT_SYMBOL(drm_addbufs_fb);
 
 
 /**
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index dc6bbe8..3c0b882 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -75,8 +75,8 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
 
-	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY},
 	[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
 	[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index dddf8de..7e3318e 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -80,6 +80,71 @@
 }
 
 #if __OS_HAS_AGP
+/*
+ * Find the drm_map that covers the range [offset, offset+size).
+ */
+static drm_map_t *drm_lookup_map(unsigned long offset,
+				 unsigned long size, drm_device_t * dev)
+{
+	struct list_head *list;
+	drm_map_list_t *r_list;
+	drm_map_t *map;
+
+	list_for_each(list, &dev->maplist->head) {
+		r_list = (drm_map_list_t *) list;
+		map = r_list->map;
+		if (!map)
+			continue;
+		if (map->offset <= offset
+		    && (offset + size) <= (map->offset + map->size))
+			return map;
+	}
+	return NULL;
+}
+
+static void *agp_remap(unsigned long offset, unsigned long size,
+		       drm_device_t * dev)
+{
+	unsigned long *phys_addr_map, i, num_pages =
+	    PAGE_ALIGN(size) / PAGE_SIZE;
+	struct drm_agp_mem *agpmem;
+	struct page **page_map;
+	void *addr;
+
+	size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+	offset -= dev->hose->mem_space->start;
+#endif
+
+	for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+		if (agpmem->bound <= offset
+		    && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+		    (offset + size))
+			break;
+	if (!agpmem)
+		return NULL;
+
+	/*
+	 * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+	 * the CPU do not get remapped by the GART.  We fix this by using the kernel's
+	 * page-table instead (that's probably faster anyhow...).
+	 */
+	/* note: use vmalloc() because num_pages could be large... */
+	page_map = vmalloc(num_pages * sizeof(struct page *));
+	if (!page_map)
+		return NULL;
+
+	phys_addr_map =
+	    agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+	for (i = 0; i < num_pages; ++i)
+		page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+	addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+	vfree(page_map);
+
+	return addr;
+}
+
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
 {
@@ -103,5 +168,74 @@
 {
 	return drm_agp_unbind_memory(handle);
 }
+
+#else  /*  __OS_HAS_AGP  */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+					unsigned long size, drm_device_t * dev)
+{
+	return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+			      drm_device_t * dev)
+{
+	return NULL;
+}
+
 #endif				/* agp */
+
+void *drm_ioremap(unsigned long offset, unsigned long size,
+				drm_device_t * dev)
+{
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+		drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+		if (map && map->type == _DRM_AGP)
+			return agp_remap(offset, size, dev);
+	}
+	return ioremap(offset, size);
+}
+EXPORT_SYMBOL(drm_ioremap);
+
+#if 0
+void *drm_ioremap_nocache(unsigned long offset,
+					unsigned long size, drm_device_t * dev)
+{
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+		drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+		if (map && map->type == _DRM_AGP)
+			return agp_remap(offset, size, dev);
+	}
+	return ioremap_nocache(offset, size);
+}
+#endif  /*  0  */
+
+void drm_ioremapfree(void *pt, unsigned long size,
+				   drm_device_t * dev)
+{
+	/*
+	 * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
+	 * routines for handling mappings in the AGP space.  Hopefully this can be done in
+	 * a future revision of the interface...
+	 */
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
+	    && ((unsigned long)pt >= VMALLOC_START
+		&& (unsigned long)pt < VMALLOC_END)) {
+		unsigned long offset;
+		drm_map_t *map;
+
+		offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
+		map = drm_lookup_map(offset, size, dev);
+		if (map && map->type == _DRM_AGP) {
+			vunmap(pt);
+			return;
+		}
+	}
+
+	iounmap(pt);
+}
+EXPORT_SYMBOL(drm_ioremapfree);
+
 #endif				/* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index 3732a61..714d9ae 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -57,71 +57,6 @@
 # endif
 #endif
 
-/*
- * Find the drm_map that covers the range [offset, offset+size).
- */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
-					unsigned long size, drm_device_t * dev)
-{
-	struct list_head *list;
-	drm_map_list_t *r_list;
-	drm_map_t *map;
-
-	list_for_each(list, &dev->maplist->head) {
-		r_list = (drm_map_list_t *) list;
-		map = r_list->map;
-		if (!map)
-			continue;
-		if (map->offset <= offset
-		    && (offset + size) <= (map->offset + map->size))
-			return map;
-	}
-	return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
-			      drm_device_t * dev)
-{
-	unsigned long *phys_addr_map, i, num_pages =
-	    PAGE_ALIGN(size) / PAGE_SIZE;
-	struct drm_agp_mem *agpmem;
-	struct page **page_map;
-	void *addr;
-
-	size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
-	offset -= dev->hose->mem_space->start;
-#endif
-
-	for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
-		if (agpmem->bound <= offset
-		    && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
-		    (offset + size))
-			break;
-	if (!agpmem)
-		return NULL;
-
-	/*
-	 * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
-	 * the CPU do not get remapped by the GART.  We fix this by using the kernel's
-	 * page-table instead (that's probably faster anyhow...).
-	 */
-	/* note: use vmalloc() because num_pages could be large... */
-	page_map = vmalloc(num_pages * sizeof(struct page *));
-	if (!page_map)
-		return NULL;
-
-	phys_addr_map =
-	    agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
-	for (i = 0; i < num_pages; ++i)
-		page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
-	addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
-	vfree(page_map);
-
-	return addr;
-}
-
 static inline unsigned long drm_follow_page(void *vaddr)
 {
 	pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
@@ -133,18 +68,6 @@
 
 #else				/* __OS_HAS_AGP */
 
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
-					unsigned long size, drm_device_t * dev)
-{
-	return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
-			      drm_device_t * dev)
-{
-	return NULL;
-}
-
 static inline unsigned long drm_follow_page(void *vaddr)
 {
 	return 0;
@@ -152,51 +75,8 @@
 
 #endif
 
-static inline void *drm_ioremap(unsigned long offset, unsigned long size,
-				drm_device_t * dev)
-{
-	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
-		drm_map_t *map = drm_lookup_map(offset, size, dev);
+void *drm_ioremap(unsigned long offset, unsigned long size,
+				drm_device_t * dev);
 
-		if (map && map->type == _DRM_AGP)
-			return agp_remap(offset, size, dev);
-	}
-	return ioremap(offset, size);
-}
-
-static inline void *drm_ioremap_nocache(unsigned long offset,
-					unsigned long size, drm_device_t * dev)
-{
-	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
-		drm_map_t *map = drm_lookup_map(offset, size, dev);
-
-		if (map && map->type == _DRM_AGP)
-			return agp_remap(offset, size, dev);
-	}
-	return ioremap_nocache(offset, size);
-}
-
-static inline void drm_ioremapfree(void *pt, unsigned long size,
-				   drm_device_t * dev)
-{
-	/*
-	 * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
-	 * routines for handling mappings in the AGP space.  Hopefully this can be done in
-	 * a future revision of the interface...
-	 */
-	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
-	    && ((unsigned long)pt >= VMALLOC_START
-		&& (unsigned long)pt < VMALLOC_END)) {
-		unsigned long offset;
-		drm_map_t *map;
-
-		offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
-		map = drm_lookup_map(offset, size, dev);
-		if (map && map->type == _DRM_AGP) {
-			vunmap(pt);
-			return;
-		}
-	}
-
-	iounmap(pt);
-}
+void drm_ioremapfree(void *pt, unsigned long size,
+				   drm_device_t * dev);
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 7868341..6543b9a 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -229,6 +229,7 @@
 	return pt;
 }
 
+#if 0
 void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
 			    drm_device_t * dev) {
 	void *pt;
@@ -251,6 +252,7 @@
 	spin_unlock(&drm_mem_lock);
 	return pt;
 }
+#endif  /*  0  */
 
 void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
 	int alloc_count;
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
index b28ca9c..86a0f1c 100644
--- a/drivers/char/drm/drm_pci.c
+++ b/drivers/char/drm/drm_pci.c
@@ -37,6 +37,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include "drmP.h"
 
 /**********************************************************************/
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 68073e1..9a842a3 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -229,8 +229,6 @@
 	return ret;
 }
 
-EXPORT_SYMBOL(drm_get_dev);
-
 /**
  * Put a device minor number.
  *
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index b108c7f..26bdf2c 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -723,7 +723,7 @@
 	
 	dev_priv->scratch_ages[header.scratch.reg]++;
 	
-	ref_age_base = *(u32 **)cmdbuf->buf;
+	ref_age_base =  (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
 	
 	cmdbuf->buf += sizeof(u64);
 	cmdbuf->bufsz -= sizeof(u64);
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index 6152415..c33d068 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -196,9 +196,9 @@
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	unsigned int cur_irq_sequence;
-	drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+	drm_via_irq_t *cur_irq;
 	int ret = 0;
-	maskarray_t *masks = dev_priv->irq_masks;
+	maskarray_t *masks;
 	int real_irq;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -221,8 +221,9 @@
 			  __FUNCTION__, irq);
 		return DRM_ERR(EINVAL);
 	}
-	
-	cur_irq += real_irq;
+
+	masks = dev_priv->irq_masks;
+	cur_irq = dev_priv->via_irqs + real_irq;
 
 	if (masks[real_irq][2] && !force_sequence) {
 		DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
@@ -247,11 +248,12 @@
 {
 	drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
 	u32 status;
-	drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+	drm_via_irq_t *cur_irq;
 	int i;
 
 	DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
 	if (dev_priv) {
+		cur_irq = dev_priv->via_irqs;
 
 		dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
 		dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index a229915..87dcaa2 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -490,7 +490,7 @@
 		release_region(dtlk_portlist[i], DTLK_IO_EXTENT);
 	}
 
-	printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+	printk(KERN_INFO "DoubleTalk PC - not found\n");
 	return -ENODEV;
 }
 
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 327b00c..8d97b39 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -904,7 +904,7 @@
 		 * It is possible the vty-server was removed after the irq was
 		 * requested but before we have time to enable interrupts.
 		 */
-		if (vio_enable_interrupts(vdev) == H_Success)
+		if (vio_enable_interrupts(vdev) == H_SUCCESS)
 			return 0;
 		else {
 			printk(KERN_ERR "HVCS: int enable failed for"
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 58dcdee..0030cd8 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -165,7 +165,7 @@
 {
 	unsigned int i;
 
-	if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+	if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
 	       return -1;
 
 	if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0ded046..9f2f8fd 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -941,6 +941,7 @@
 			list_del(&msg->link);
 			list_add_tail(&msg->link, &msgs);
 		}
+		intf->waiting_events_count = 0;
 	}
 
 	/* Hold the events lock while doing this to preserve order. */
@@ -2916,6 +2917,7 @@
 
 		copy_event_into_recv_msg(recv_msg, msg);
 		list_add_tail(&(recv_msg->link), &(intf->waiting_events));
+		intf->waiting_events_count++;
 	} else {
 		/* There's too many things in the queue, discard this
 		   message. */
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index a86c0f2..b36eef0 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2198,11 +2198,11 @@
 	}
 }
 
-static struct ipmi_default_vals
+static __devinitdata struct ipmi_default_vals
 {
 	int type;
 	int port;
-} __devinit ipmi_defaults[] =
+} ipmi_defaults[] =
 {
 	{ .type = SI_KCS, .port = 0xca2 },
 	{ .type = SI_SMIC, .port = 0xca9 },
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 66719f9..1fa9fa15 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,6 +27,7 @@
 #include <linux/crash_dump.h>
 #include <linux/backing-dev.h>
 #include <linux/bootmem.h>
+#include <linux/pipe_fs_i.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -578,6 +579,18 @@
 	return count;
 }
 
+static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf,
+			struct splice_desc *sd)
+{
+	return sd->len;
+}
+
+static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out,
+				 loff_t *ppos, size_t len, unsigned int flags)
+{
+	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
+}
+
 #ifdef CONFIG_MMU
 /*
  * For fun, we are using the MMU for this.
@@ -785,6 +798,7 @@
 	.llseek		= null_lseek,
 	.read		= read_null,
 	.write		= write_null,
+	.splice_write	= splice_write_null,
 };
 
 #if defined(CONFIG_ISA) || !defined(__mc68000__)
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 8666171..d3ba2f8 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -271,7 +271,7 @@
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 	
-			if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) {
+			if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
 				PRINTK_ERROR(KERN_ERR_MWAVE
 						"mwavedd::mwave_ioctl:"
 						" IOCTL_MW_REGISTER_IPC:"
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 5fdf185..02114a0 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -46,7 +46,7 @@
 /* #define ATR_CSUM */
 
 #ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)	(&handle_to_dev(x->link.handle))
+#define reader_to_dev(x)	(&handle_to_dev(x->p_dev->handle))
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do { 				\
@@ -67,7 +67,7 @@
 #define	T_100MSEC	msecs_to_jiffies(100)
 #define	T_500MSEC	msecs_to_jiffies(500)
 
-static void cm4000_release(dev_link_t *link);
+static void cm4000_release(struct pcmcia_device *link);
 
 static int major;		/* major number we get from the kernel */
 
@@ -106,7 +106,7 @@
 #define REG_STOPBITS(x)		(x + 7)
 
 struct cm4000_dev {
-	dev_link_t link;		/* pcmcia link */
+	struct pcmcia_device *p_dev;
 	dev_node_t node;		/* OS node (major,minor) */
 
 	unsigned char atr[MAX_ATR];
@@ -149,14 +149,14 @@
 #define	ZERO_DEV(dev)  						\
 	memset(&dev->atr_csum,0,				\
 		sizeof(struct cm4000_dev) - 			\
-		/*link*/ sizeof(dev_link_t) - 			\
+		/*link*/ sizeof(struct pcmcia_device) - 	\
 		/*node*/ sizeof(dev_node_t) - 			\
 		/*atr*/ MAX_ATR*sizeof(char) - 			\
 		/*rbuf*/ 512*sizeof(char) - 			\
 		/*sbuf*/ 512*sizeof(char) - 			\
 		/*queue*/ 4*sizeof(wait_queue_head_t))
 
-static dev_link_t *dev_table[CM4000_MAX_DEV];
+static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
 static struct class *cmm_class;
 
 /* This table doesn't use spaces after the comma between fields and thus
@@ -454,7 +454,7 @@
 static void set_cardparameter(struct cm4000_dev *dev)
 {
 	int i;
-	ioaddr_t iobase = dev->link.io.BasePort1;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
 	u_int8_t stopbits = 0x02; /* ISO default */
 
 	DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -487,7 +487,7 @@
 	unsigned short num_bytes_read;
 	unsigned char pts_reply[4];
 	ssize_t rc;
-	ioaddr_t iobase = dev->link.io.BasePort1;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
 
 	rc = 0;
 
@@ -699,7 +699,7 @@
 static void monitor_card(unsigned long p)
 {
 	struct cm4000_dev *dev = (struct cm4000_dev *) p;
-	ioaddr_t iobase = dev->link.io.BasePort1;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
 	unsigned short s;
 	struct ptsreq ptsreq;
 	int i, atrc;
@@ -962,7 +962,7 @@
 			loff_t *ppos)
 {
 	struct cm4000_dev *dev = filp->private_data;
-	ioaddr_t iobase = dev->link.io.BasePort1;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
 	ssize_t rc;
 	int i, j, k;
 
@@ -971,7 +971,7 @@
 	if (count == 0)		/* according to manpage */
 		return 0;
 
-	if ((dev->link.state & DEV_PRESENT) == 0 ||	/* socket removed */
+	if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
 	    test_bit(IS_CMM_ABSENT, &dev->flags))
 		return -ENODEV;
 
@@ -1083,7 +1083,7 @@
 			 size_t count, loff_t *ppos)
 {
 	struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
-	ioaddr_t iobase = dev->link.io.BasePort1;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
 	unsigned short s;
 	unsigned char tmp;
 	unsigned char infolen;
@@ -1108,7 +1108,7 @@
 
 	sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
 
-	if ((dev->link.state & DEV_PRESENT) == 0 ||	/* socket removed */
+	if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
 	    test_bit(IS_CMM_ABSENT, &dev->flags))
 		return -ENODEV;
 
@@ -1440,8 +1440,8 @@
 		     unsigned long arg)
 {
 	struct cm4000_dev *dev = filp->private_data;
-	ioaddr_t iobase = dev->link.io.BasePort1;
-	dev_link_t *link;
+	ioaddr_t iobase = dev->p_dev->io.BasePort1;
+	struct pcmcia_device *link;
 	int size;
 	int rc;
 	void __user *argp = (void __user *)arg;
@@ -1458,7 +1458,7 @@
 	       iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 
 	link = dev_table[iminor(inode)];
-	if (!(DEV_OK(link))) {
+	if (!pcmcia_dev_present(link)) {
 		DEBUGP(4, dev, "DEV_OK false\n");
 		return -ENODEV;
 	}
@@ -1660,14 +1660,14 @@
 static int cmm_open(struct inode *inode, struct file *filp)
 {
 	struct cm4000_dev *dev;
-	dev_link_t *link;
+	struct pcmcia_device *link;
 	int rc, minor = iminor(inode);
 
 	if (minor >= CM4000_MAX_DEV)
 		return -ENODEV;
 
 	link = dev_table[minor];
-	if (link == NULL || !(DEV_OK(link)))
+	if (link == NULL || !pcmcia_dev_present(link))
 		return -ENODEV;
 
 	if (link->open)
@@ -1709,7 +1709,7 @@
 static int cmm_close(struct inode *inode, struct file *filp)
 {
 	struct cm4000_dev *dev;
-	dev_link_t *link;
+	struct pcmcia_device *link;
 	int minor = iminor(inode);
 
 	if (minor >= CM4000_MAX_DEV)
@@ -1735,7 +1735,7 @@
 	return 0;
 }
 
-static void cmm_cm4000_release(dev_link_t * link)
+static void cmm_cm4000_release(struct pcmcia_device * link)
 {
 	struct cm4000_dev *dev = link->priv;
 
@@ -1759,13 +1759,11 @@
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
-static void cm4000_config(dev_link_t * link, int devno)
+static int cm4000_config(struct pcmcia_device * link, int devno)
 {
-	client_handle_t handle = link->handle;
 	struct cm4000_dev *dev;
 	tuple_t tuple;
 	cisparse_t parse;
-	config_info_t conf;
 	u_char buf[64];
 	int fail_fn, fail_rc;
 	int rc;
@@ -1777,41 +1775,34 @@
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
 
-	if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+	if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
 		fail_fn = GetFirstTuple;
 		goto cs_failed;
 	}
-	if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+	if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
 		fail_fn = GetTupleData;
 		goto cs_failed;
 	}
 	if ((fail_rc =
-	     pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) {
+	     pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {
 		fail_fn = ParseTuple;
 		goto cs_failed;
 	}
-	if ((fail_rc =
-	     pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) {
-		fail_fn = GetConfigurationInfo;
-		goto cs_failed;
-	}
 
-	link->state |= DEV_CONFIG;
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
-	link->conf.Vcc = conf.Vcc;
 
 	link->io.BasePort2 = 0;
 	link->io.NumPorts2 = 0;
 	link->io.Attributes2 = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	for (rc = pcmcia_get_first_tuple(handle, &tuple);
-	     rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) {
+	for (rc = pcmcia_get_first_tuple(link, &tuple);
+	     rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
 
-		rc = pcmcia_get_tuple_data(handle, &tuple);
+		rc = pcmcia_get_tuple_data(link, &tuple);
 		if (rc != CS_SUCCESS)
 			continue;
-		rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+		rc = pcmcia_parse_tuple(link, &tuple, &parse);
 		if (rc != CS_SUCCESS)
 			continue;
 
@@ -1831,7 +1822,7 @@
 		link->io.IOAddrLines = parse.cftable_entry.io.flags
 		    & CISTPL_IO_LINES_MASK;
 
-		rc = pcmcia_request_io(handle, &link->io);
+		rc = pcmcia_request_io(link, &link->io);
 		if (rc == CS_SUCCESS)
 			break;	/* we are done */
 	}
@@ -1841,7 +1832,7 @@
 	link->conf.IntType = 00000002;
 
 	if ((fail_rc =
-	     pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) {
+	     pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
 		fail_fn = RequestConfiguration;
 		goto cs_release;
 	}
@@ -1851,63 +1842,48 @@
 	dev->node.major = major;
 	dev->node.minor = devno;
 	dev->node.next = NULL;
-	link->dev = &dev->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &dev->node;
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(handle, fail_fn, fail_rc);
+	cs_error(link, fail_fn, fail_rc);
 cs_release:
 	cm4000_release(link);
-
-	link->state &= ~DEV_CONFIG_PENDING;
+	return -ENODEV;
 }
 
-static int cm4000_suspend(struct pcmcia_device *p_dev)
+static int cm4000_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct cm4000_dev *dev;
 
 	dev = link->priv;
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 	stop_monitor(dev);
 
 	return 0;
 }
 
-static int cm4000_resume(struct pcmcia_device *p_dev)
+static int cm4000_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct cm4000_dev *dev;
 
 	dev = link->priv;
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
 	if (link->open)
 		start_monitor(dev);
 
 	return 0;
 }
 
-static void cm4000_release(dev_link_t *link)
+static void cm4000_release(struct pcmcia_device *link)
 {
 	cmm_cm4000_release(link->priv);	/* delay release until device closed */
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
+	pcmcia_disable_device(link);
 }
 
-static int cm4000_attach(struct pcmcia_device *p_dev)
+static int cm4000_probe(struct pcmcia_device *link)
 {
 	struct cm4000_dev *dev;
-	dev_link_t *link;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < CM4000_MAX_DEV; i++)
 		if (dev_table[i] == NULL)
@@ -1923,7 +1899,7 @@
 	if (dev == NULL)
 		return -ENOMEM;
 
-	link = &dev->link;
+	dev->p_dev = link;
 	link->priv = dev;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
@@ -1933,11 +1909,9 @@
 	init_waitqueue_head(&dev->atrq);
 	init_waitqueue_head(&dev->readq);
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	cm4000_config(link, i);
+	ret = cm4000_config(link, i);
+	if (ret)
+		return ret;
 
 	class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
 			    "cmm%d", i);
@@ -1945,9 +1919,8 @@
 	return 0;
 }
 
-static void cm4000_detach(struct pcmcia_device *p_dev)
+static void cm4000_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct cm4000_dev *dev = link->priv;
 	int devno;
 
@@ -1958,11 +1931,9 @@
 	if (devno == CM4000_MAX_DEV)
 		return;
 
-	link->state &= ~DEV_PRESENT;
 	stop_monitor(dev);
 
-	if (link->state & DEV_CONFIG)
- 		cm4000_release(link);
+	cm4000_release(link);
 
 	dev_table[devno] = NULL;
  	kfree(dev);
@@ -1993,7 +1964,7 @@
 	.drv	  = {
 		.name = "cm4000_cs",
 		},
-	.probe    = cm4000_attach,
+	.probe    = cm4000_probe,
 	.remove   = cm4000_detach,
 	.suspend  = cm4000_suspend,
 	.resume   = cm4000_resume,
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 466e33b..29efa64 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
 
 
 #ifdef PCMCIA_DEBUG
-#define reader_to_dev(x)	(&handle_to_dev(x->link.handle))
+#define reader_to_dev(x)	(&handle_to_dev(x->p_dev->handle))
 static int pc_debug = PCMCIA_DEBUG;
 module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do { 				\
@@ -65,7 +65,7 @@
 /* how often to poll for fifo status change */
 #define POLL_PERIOD 				msecs_to_jiffies(10)
 
-static void reader_release(dev_link_t *link);
+static void reader_release(struct pcmcia_device *link);
 
 static int major;
 static struct class *cmx_class;
@@ -74,7 +74,7 @@
 #define		BS_WRITABLE	0x02
 
 struct reader_dev {
-	dev_link_t		link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t		node;
 	wait_queue_head_t	devq;
 	wait_queue_head_t	poll_wait;
@@ -87,7 +87,7 @@
 	struct timer_list 	poll_timer;
 };
 
-static dev_link_t *dev_table[CM_MAX_DEV];
+static struct pcmcia_device *dev_table[CM_MAX_DEV];
 
 #ifndef PCMCIA_DEBUG
 #define	xoutb	outb
@@ -116,7 +116,7 @@
 static void cm4040_do_poll(unsigned long dummy)
 {
 	struct reader_dev *dev = (struct reader_dev *) dummy;
-	unsigned int obs = xinb(dev->link.io.BasePort1
+	unsigned int obs = xinb(dev->p_dev->io.BasePort1
 				+ REG_OFFSET_BUFFER_STATUS);
 
 	if ((obs & BSR_BULK_IN_FULL)) {
@@ -147,7 +147,7 @@
 static int wait_for_bulk_out_ready(struct reader_dev *dev)
 {
 	int i, rc;
-	int iobase = dev->link.io.BasePort1;
+	int iobase = dev->p_dev->io.BasePort1;
 
 	for (i = 0; i < POLL_LOOP_COUNT; i++) {
 		if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -177,7 +177,7 @@
 /* Write to Sync Control Register */
 static int write_sync_reg(unsigned char val, struct reader_dev *dev)
 {
-	int iobase = dev->link.io.BasePort1;
+	int iobase = dev->p_dev->io.BasePort1;
 	int rc;
 
 	rc = wait_for_bulk_out_ready(dev);
@@ -195,7 +195,7 @@
 static int wait_for_bulk_in_ready(struct reader_dev *dev)
 {
 	int i, rc;
-	int iobase = dev->link.io.BasePort1;
+	int iobase = dev->p_dev->io.BasePort1;
 
 	for (i = 0; i < POLL_LOOP_COUNT; i++) {
 		if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -225,7 +225,7 @@
 			size_t count, loff_t *ppos)
 {
 	struct reader_dev *dev = filp->private_data;
-	int iobase = dev->link.io.BasePort1;
+	int iobase = dev->p_dev->io.BasePort1;
 	size_t bytes_to_read;
 	unsigned long i;
 	size_t min_bytes_to_read;
@@ -246,7 +246,7 @@
 		return -EAGAIN;
 	}
 
-	if ((dev->link.state & DEV_PRESENT)==0)
+	if (!pcmcia_dev_present(dev->p_dev))
 		return -ENODEV;
 
 	for (i = 0; i < 5; i++) {
@@ -328,7 +328,7 @@
 			 size_t count, loff_t *ppos)
 {
 	struct reader_dev *dev = filp->private_data;
-	int iobase = dev->link.io.BasePort1;
+	int iobase = dev->p_dev->io.BasePort1;
 	ssize_t rc;
 	int i;
 	unsigned int bytes_to_write;
@@ -351,7 +351,7 @@
 		return -EAGAIN;
 	}
 
-	if ((dev->link.state & DEV_PRESENT) == 0)
+	if (!pcmcia_dev_present(dev->p_dev))
 		return -ENODEV;
 
 	bytes_to_write = count;
@@ -445,14 +445,14 @@
 static int cm4040_open(struct inode *inode, struct file *filp)
 {
 	struct reader_dev *dev;
-	dev_link_t *link;
+	struct pcmcia_device *link;
 	int minor = iminor(inode);
 
 	if (minor >= CM_MAX_DEV)
 		return -ENODEV;
 
 	link = dev_table[minor];
-	if (link == NULL || !(DEV_OK(link)))
+	if (link == NULL || !pcmcia_dev_present(link))
 		return -ENODEV;
 
 	if (link->open)
@@ -478,7 +478,7 @@
 static int cm4040_close(struct inode *inode, struct file *filp)
 {
 	struct reader_dev *dev = filp->private_data;
-	dev_link_t *link;
+	struct pcmcia_device *link;
 	int minor = iminor(inode);
 
 	DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode),
@@ -500,7 +500,7 @@
 	return 0;
 }
 
-static void cm4040_reader_release(dev_link_t *link)
+static void cm4040_reader_release(struct pcmcia_device *link)
 {
 	struct reader_dev *dev = link->priv;
 
@@ -514,60 +514,49 @@
 	return;
 }
 
-static void reader_config(dev_link_t *link, int devno)
+static int reader_config(struct pcmcia_device *link, int devno)
 {
-	client_handle_t handle;
 	struct reader_dev *dev;
 	tuple_t tuple;
 	cisparse_t parse;
-	config_info_t conf;
 	u_char buf[64];
 	int fail_fn, fail_rc;
 	int rc;
 
-	handle = link->handle;
-
 	tuple.DesiredTuple = CISTPL_CONFIG;
 	tuple.Attributes = 0;
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
  	tuple.TupleOffset = 0;
 
-	if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
+	if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
 		fail_fn = GetFirstTuple;
 		goto cs_failed;
 	}
-	if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
+	if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
 		fail_fn = GetTupleData;
 		goto cs_failed;
 	}
-	if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse))
+	if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
 							!= CS_SUCCESS) {
 		fail_fn = ParseTuple;
 		goto cs_failed;
 	}
-	if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
-							!= CS_SUCCESS) {
-		fail_fn = GetConfigurationInfo;
-		goto cs_failed;
-	}
 
-	link->state |= DEV_CONFIG;
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
-	link->conf.Vcc = conf.Vcc;
 
 	link->io.BasePort2 = 0;
 	link->io.NumPorts2 = 0;
 	link->io.Attributes2 = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	for (rc = pcmcia_get_first_tuple(handle, &tuple);
+	for (rc = pcmcia_get_first_tuple(link, &tuple);
 	     rc == CS_SUCCESS;
-	     rc = pcmcia_get_next_tuple(handle, &tuple)) {
-		rc = pcmcia_get_tuple_data(handle, &tuple);
+	     rc = pcmcia_get_next_tuple(link, &tuple)) {
+		rc = pcmcia_get_tuple_data(link, &tuple);
 		if (rc != CS_SUCCESS)
 			continue;
-		rc = pcmcia_parse_tuple(handle, &tuple, &parse);
+		rc = pcmcia_parse_tuple(link, &tuple, &parse);
 		if (rc != CS_SUCCESS)
 			continue;
 
@@ -585,13 +574,13 @@
 			link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 		link->io.IOAddrLines = parse.cftable_entry.io.flags
 						& CISTPL_IO_LINES_MASK;
-		rc = pcmcia_request_io(handle, &link->io);
+		rc = pcmcia_request_io(link, &link->io);
 
-		dev_printk(KERN_INFO, &handle_to_dev(handle), "foo");
+		dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
 		if (rc == CS_SUCCESS)
 			break;
 		else
-			dev_printk(KERN_INFO, &handle_to_dev(handle),
+			dev_printk(KERN_INFO, &handle_to_dev(link),
 				   "pcmcia_request_io failed 0x%x\n", rc);
 	}
 	if (rc != CS_SUCCESS)
@@ -599,10 +588,10 @@
 
 	link->conf.IntType = 00000002;
 
-	if ((fail_rc = pcmcia_request_configuration(handle,&link->conf))
+	if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
 								!=CS_SUCCESS) {
 		fail_fn = RequestConfiguration;
-		dev_printk(KERN_INFO, &handle_to_dev(handle),
+		dev_printk(KERN_INFO, &handle_to_dev(link),
 			   "pcmcia_request_configuration failed 0x%x\n",
 			   fail_rc);
 		goto cs_release;
@@ -612,57 +601,31 @@
 	sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
 	dev->node.major = major;
 	dev->node.minor = devno;
-	dev->node.next = NULL;
-	link->dev = &dev->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	dev->node.next = &dev->node;
 
 	DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
 	      link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
 	DEBUGP(2, dev, "<- reader_config (succ)\n");
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(handle, fail_fn, fail_rc);
+	cs_error(link, fail_fn, fail_rc);
 cs_release:
 	reader_release(link);
-	link->state &= ~DEV_CONFIG_PENDING;
+	return -ENODEV;
 }
 
-static int reader_suspend(struct pcmcia_device *p_dev)
-{
-	dev_link_t *link = dev_to_instance(p_dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int reader_resume(struct pcmcia_device *p_dev)
-{
-	dev_link_t *link = dev_to_instance(p_dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
-
-static void reader_release(dev_link_t *link)
+static void reader_release(struct pcmcia_device *link)
 {
 	cm4040_reader_release(link->priv);
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
+	pcmcia_disable_device(link);
 }
 
-static int reader_attach(struct pcmcia_device *p_dev)
+static int reader_probe(struct pcmcia_device *link)
 {
 	struct reader_dev *dev;
-	dev_link_t *link;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < CM_MAX_DEV; i++) {
 		if (dev_table[i] == NULL)
@@ -679,8 +642,8 @@
 	dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
 	dev->buffer_status = 0;
 
-	link = &dev->link;
 	link->priv = dev;
+	dev->p_dev = link;
 
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
@@ -692,11 +655,9 @@
 	init_timer(&dev->poll_timer);
 	dev->poll_timer.function = &cm4040_do_poll;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	reader_config(link, i);
+	ret = reader_config(link, i);
+	if (ret)
+		return ret;
 
 	class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
 			    "cmx%d", i);
@@ -704,9 +665,8 @@
 	return 0;
 }
 
-static void reader_detach(struct pcmcia_device *p_dev)
+static void reader_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct reader_dev *dev = link->priv;
 	int devno;
 
@@ -718,10 +678,7 @@
 	if (devno == CM_MAX_DEV)
 		return;
 
-	link->state &= ~DEV_PRESENT;
-
-	if (link->state & DEV_CONFIG)
-		reader_release(link);
+	reader_release(link);
 
 	dev_table[devno] = NULL;
 	kfree(dev);
@@ -753,10 +710,8 @@
   	.drv		= {
 		.name	= "cm4040_cs",
 	},
-	.probe		= reader_attach,
+	.probe		= reader_probe,
 	.remove		= reader_detach,
-	.suspend	= reader_suspend,
-	.resume		= reader_resume,
 	.id_table	= cm4040_ids,
 };
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index e6b714b..0721345 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -228,7 +228,7 @@
 	struct	_input_signal_events	input_signal_events;
 
 	/* PCMCIA support */
-	dev_link_t	      link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t	      node;
 	int		      stop;
 
@@ -484,7 +484,7 @@
 
 /* PCMCIA prototypes */
 
-static void mgslpc_config(dev_link_t *link);
+static int mgslpc_config(struct pcmcia_device *link);
 static void mgslpc_release(u_long arg);
 static void mgslpc_detach(struct pcmcia_device *p_dev);
 
@@ -533,14 +533,14 @@
 	}
 }
 
-static int mgslpc_attach(struct pcmcia_device *p_dev)
+static int mgslpc_probe(struct pcmcia_device *link)
 {
     MGSLPC_INFO *info;
-    dev_link_t *link;
-    
+    int ret;
+
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_attach\n");
-	
+
     info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
     if (!info) {
 	    printk("Error can't allocate device instance data\n");
@@ -565,25 +565,22 @@
     info->imrb_value = 0xffff;
     info->pim_value = 0xff;
 
-    link = &info->link;
+    info->p_dev = link;
     link->priv = info;
-    
-    /* Initialize the dev_link_t structure */
+
+    /* Initialize the struct pcmcia_device structure */
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1   = IRQ_LEVEL_ID;
     link->irq.Handler = NULL;
-    
+
     link->conf.Attributes = 0;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    mgslpc_config(link);
+    ret = mgslpc_config(link);
+    if (ret)
+	    return ret;
 
     mgslpc_add_device(info);
 
@@ -596,15 +593,13 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void mgslpc_config(dev_link_t *link)
+static int mgslpc_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     MGSLPC_INFO *info = link->priv;
     tuple_t tuple;
     cisparse_t parse;
     int last_fn, last_ret;
     u_char buf[64];
-    config_info_t conf;
     cistpl_cftable_entry_t dflt = { 0 };
     cistpl_cftable_entry_t *cfg;
     
@@ -617,27 +612,20 @@
     tuple.TupleData = buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
 
     /* get CIS configuration entry */
 
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 
     cfg = &(parse.cftable_entry);
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 
     if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
     if (cfg->index == 0)
@@ -658,11 +646,10 @@
 	    link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
 	    link->io.BasePort1 = io->win[0].base;
 	    link->io.NumPorts1 = io->win[0].len;
-	    CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+	    CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 8;
     link->conf.Present = PRESENT_OPTION;
@@ -670,9 +657,9 @@
     link->irq.Attributes |= IRQ_HANDLE_PRESENT;
     link->irq.Handler     = mgslpc_isr;
     link->irq.Instance    = info;
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     info->io_base = link->io.BasePort1;
     info->irq_level = link->irq.AssignedIRQ;
@@ -680,7 +667,7 @@
     /* add to linked list of devices */
     sprintf(info->node.dev_name, "mgslpc0");
     info->node.major = info->node.minor = 0;
-    link->dev = &info->node;
+    link->dev_node = &info->node;
 
     printk(KERN_INFO "%s: index 0x%02x:",
 	   info->node.dev_name, link->conf.ConfigIndex);
@@ -690,13 +677,12 @@
 	    printk(", io 0x%04x-0x%04x", link->io.BasePort1,
 		   link->io.BasePort1+link->io.NumPorts1-1);
     printk("\n");
-    
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     mgslpc_release((u_long)link);
+    return -ENODEV;
 }
 
 /* Card has been removed.
@@ -705,58 +691,38 @@
  */
 static void mgslpc_release(u_long arg)
 {
-    dev_link_t *link = (dev_link_t *)arg;
+	struct pcmcia_device *link = (struct pcmcia_device *)arg;
 
-    if (debug_level >= DEBUG_LEVEL_INFO)
-	    printk("mgslpc_release(0x%p)\n", link);
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("mgslpc_release(0x%p)\n", link);
 
-    /* Unlink the device chain */
-    link->dev = NULL;
-    link->state &= ~DEV_CONFIG;
-
-    pcmcia_release_configuration(link->handle);
-    if (link->io.NumPorts1)
-	    pcmcia_release_io(link->handle, &link->io);
-    if (link->irq.AssignedIRQ)
-	    pcmcia_release_irq(link->handle, &link->irq);
+	pcmcia_disable_device(link);
 }
 
-static void mgslpc_detach(struct pcmcia_device *p_dev)
+static void mgslpc_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("mgslpc_detach(0x%p)\n", link);
 
-    if (debug_level >= DEBUG_LEVEL_INFO)
-	    printk("mgslpc_detach(0x%p)\n", link);
+	((MGSLPC_INFO *)link->priv)->stop = 1;
+	mgslpc_release((u_long)link);
 
-    if (link->state & DEV_CONFIG) {
-	    ((MGSLPC_INFO *)link->priv)->stop = 1;
-	    mgslpc_release((u_long)link);
-    }
-
-    mgslpc_remove_device((MGSLPC_INFO *)link->priv);
+	mgslpc_remove_device((MGSLPC_INFO *)link->priv);
 }
 
-static int mgslpc_suspend(struct pcmcia_device *dev)
+static int mgslpc_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	MGSLPC_INFO *info = link->priv;
 
-	link->state |= DEV_SUSPEND;
 	info->stop = 1;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 
 	return 0;
 }
 
-static int mgslpc_resume(struct pcmcia_device *dev)
+static int mgslpc_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	MGSLPC_INFO *info = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
 	info->stop = 0;
 
 	return 0;
@@ -1280,7 +1246,7 @@
 	if (!info)
 		return IRQ_NONE;
 		
-	if (!(info->link.state & DEV_CONFIG))
+	if (!(info->p_dev->_locked))
 		return IRQ_HANDLED;
 
 	spin_lock(&info->lock);
@@ -3033,7 +2999,7 @@
 	.drv		= {
 		.name	= "synclink_cs",
 	},
-	.probe		= mgslpc_attach,
+	.probe		= mgslpc_probe,
 	.remove		= mgslpc_detach,
 	.id_table	= mgslpc_ids,
 	.suspend	= mgslpc_suspend,
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 86be04b..58f3512 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1584,7 +1584,6 @@
 
 	return twothirdsMD4Transform(daddr, hash);
 }
-EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
 #endif
 
 #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index b543821..56c8243 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -390,7 +390,8 @@
 			format_module_id(devnamep, geo_module(geoid),
 					 MODULE_FORMAT_BRIEF);
 			devnamep = devname + strlen(devname);
-			sprintf(devnamep, "#%d", geo_slab(geoid));
+			sprintf(devnamep, "^%d#%d", geo_slot(geoid),
+				geo_slab(geoid));
 
 			/* allocate sysctl device data */
 			scd = kzalloc(sizeof (struct sysctl_data_s),
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index f8dd852..a90f5d9 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1341,6 +1341,9 @@
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
 	else
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index eb2eb3e..079db5a 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -515,7 +515,7 @@
 		err = PTR_ERR(tipar_class);
 		goto out_chrdev;
 	}
-	if (parport_register_driver(&tipar_driver) || tp_count == 0) {
+	if (parport_register_driver(&tipar_driver)) {
 		printk(KERN_ERR "tipar: unable to register with parport\n");
 		err = -EIO;
 		goto out_class;
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 2546637..f58ad7f 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -327,7 +327,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL,
 		store_received_ref_clk3a);
 
 
@@ -349,7 +349,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL,
 		store_received_ref_clk3b);
 
 
@@ -371,7 +371,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clk3b_output);
 
 static ssize_t store_enable_clk3a_output(struct device *d,
@@ -392,7 +392,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clk3a_output);
 
 static ssize_t store_enable_clkb1_output(struct device *d,
@@ -413,7 +413,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clkb1_output);
 
 
@@ -435,7 +435,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clka1_output);
 
 static ssize_t store_enable_clkb0_output(struct device *d,
@@ -456,7 +456,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clkb0_output);
 
 static ssize_t store_enable_clka0_output(struct device *d,
@@ -477,7 +477,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
+static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL,
 		store_enable_clka0_output);
 
 static ssize_t store_select_amcb2_transmit_clock(struct device *d,
@@ -519,7 +519,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
 	store_select_amcb2_transmit_clock);
 
 static ssize_t store_select_amcb1_transmit_clock(struct device *d,
@@ -560,7 +560,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL,
 		store_select_amcb1_transmit_clock);
 
 static ssize_t store_select_redundant_clock(struct device *d,
@@ -581,7 +581,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL,
+static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL,
 		store_select_redundant_clock);
 
 static ssize_t store_select_ref_frequency(struct device *d,
@@ -602,7 +602,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL,
+static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL,
 		store_select_ref_frequency);
 
 static ssize_t store_filter_select(struct device *d,
@@ -623,7 +623,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select);
+static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select);
 
 static ssize_t store_hardware_switching_mode(struct device *d,
 		 struct device_attribute *attr, const char *buf, size_t count)
@@ -643,7 +643,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL,
 		store_hardware_switching_mode);
 
 static ssize_t store_hardware_switching(struct device *d,
@@ -664,7 +664,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL,
+static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL,
 		store_hardware_switching);
 
 static ssize_t store_refalign (struct device *d,
@@ -684,7 +684,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign);
+static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign);
 
 static ssize_t store_mode_select (struct device *d,
 		 struct device_attribute *attr, const char *buf, size_t count)
@@ -704,7 +704,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select);
+static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select);
 
 static ssize_t store_reset (struct device *d,
 		 struct device_attribute *attr, const char *buf, size_t count)
@@ -724,7 +724,7 @@
 	return strnlen(buf, count);
 }
 
-static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
+static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset);
 
 static struct attribute *tlclk_sysfs_entries[] = {
 	&dev_attr_current_ref.attr,
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a6873bf..1efde3b 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -20,9 +20,18 @@
 	  Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
 	  and CONFIG_PNPACPI.
 
+config TCG_TIS
+	tristate "TPM Interface Specification 1.2 Interface"
+	depends on TCG_TPM
+	---help---
+	  If you have a TPM security chip that is compliant with the
+	  TCG TIS 1.2 TPM specification say Yes and it will be accessible
+	  from within Linux.  To compile this driver as a module, choose
+	  M here; the module will be called tpm_tis.
+
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
-	depends on TCG_TPM
+	depends on TCG_TPM && PNPACPI
 	---help---
 	  If you have a TPM security chip from National Semicondutor 
 	  say Yes and it will be accessible from within Linux.  To 
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ba4582d..ea3a1e0 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -5,6 +5,7 @@
 ifdef CONFIG_ACPI
 	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
 endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 5a38704..6889e7d 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -32,12 +32,291 @@
 	TPM_MINOR = 224,	/* officially assigned */
 	TPM_BUFSIZE = 2048,
 	TPM_NUM_DEVICES = 256,
-	TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
 };
 
+enum tpm_duration {
+	TPM_SHORT = 0,
+	TPM_MEDIUM = 1,
+	TPM_LONG = 2,
+	TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[TPM_NUM_MASK_ENTRIES];
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result.  The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 15 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,		/* 20 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,		/* 25 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 30 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 35 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 40 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 45 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 50 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 55 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 60 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 65 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 70 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 75 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 80 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 85 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 90 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 95 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 100 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 105 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 110 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 115 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 120 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 125 */
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 130 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 135 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 140 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 145 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 150 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 155 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 160 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 165 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 170 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 175 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 180 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,		/* 185 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 190 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 195 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 200 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 205 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 210 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 215 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 220 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 225 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 230 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 235 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 240 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+};
 
 static void user_reader_timeout(unsigned long ptr)
 {
@@ -46,7 +325,7 @@
 	schedule_work(&chip->work);
 }
 
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
 {
 	struct tpm_chip *chip = ptr;
 
@@ -57,17 +336,43 @@
 }
 
 /*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+					   u32 ordinal)
+{
+	int duration_idx = TPM_UNDEFINED;
+	int duration = 0;
+
+	if (ordinal < TPM_MAX_ORDINAL)
+		duration_idx = tpm_ordinal_duration[ordinal];
+	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+		 TPM_MAX_PROTECTED_ORDINAL)
+		duration_idx =
+		    tpm_protected_ordinal_duration[ordinal &
+						   TPM_PROTECTED_ORDINAL_MASK];
+
+	if (duration_idx != TPM_UNDEFINED)
+		duration = chip->vendor.duration[duration_idx];
+	if (duration <= 0)
+		return 2 * 60 * HZ;
+	else
+		return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
+/*
  * Internal kernel interface to transmit TPM commands
  */
 static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
 			    size_t bufsiz)
 {
 	ssize_t rc;
-	u32 count;
+	u32 count, ordinal;
 	unsigned long stop;
 
 	count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
 	if (count == 0)
 		return -ENODATA;
 	if (count > bufsiz) {
@@ -78,21 +383,23 @@
 
 	down(&chip->tpm_mutex);
 
-	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+	if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
 		dev_err(chip->dev,
 			"tpm_transmit: tpm_send: error %zd\n", rc);
 		goto out;
 	}
 
-	stop = jiffies + 2 * 60 * HZ;
-	do {
-		u8 status = chip->vendor->status(chip);
-		if ((status & chip->vendor->req_complete_mask) ==
-		    chip->vendor->req_complete_val) {
-			goto out_recv;
-		}
+	if (chip->vendor.irq)
+		goto out_recv;
 
-		if ((status == chip->vendor->req_canceled)) {
+	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
+	do {
+		u8 status = chip->vendor.status(chip);
+		if ((status & chip->vendor.req_complete_mask) ==
+		    chip->vendor.req_complete_val)
+			goto out_recv;
+
+		if ((status == chip->vendor.req_canceled)) {
 			dev_err(chip->dev, "Operation Canceled\n");
 			rc = -ECANCELED;
 			goto out;
@@ -102,14 +409,13 @@
 		rmb();
 	} while (time_before(jiffies, stop));
 
-
-	chip->vendor->cancel(chip);
+	chip->vendor.cancel(chip);
 	dev_err(chip->dev, "Operation Timed out\n");
 	rc = -ETIME;
 	goto out;
 
 out_recv:
-	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+	rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
 	if (rc < 0)
 		dev_err(chip->dev,
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -119,17 +425,247 @@
 }
 
 #define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+	TPM_CAP_FLAG = 4,
+	TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+	TPM_CAP_PROP_PCR = 0x1,
+	TPM_CAP_PROP_MANUFACTURER = 0x3,
+	TPM_CAP_FLAG_PERM = 0x8,
+	TPM_CAP_FLAG_VOL = 0x9,
+	TPM_CAP_PROP_OWNER = 0x11,
+	TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+	TPM_CAP_PROP_TIS_DURATION = 0x20,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 22,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 5,
-	0, 0, 0, 4,
-	0, 0, 1, 1
+	0, 0, 0, 0,		/* TPM_CAP_<TYPE> */
+	0, 0, 0, 4,		/* TPM_CAP_SUB_<TYPE> size */
+	0, 0, 1, 0		/* TPM_CAP_SUB_<TYPE> */
 };
 
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+			    char *desc)
+{
+	int err;
+
+	len = tpm_transmit(chip, data, len);
+	if (len <  0)
+		return len;
+	if (len == TPM_ERROR_SIZE) {
+		err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+		dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+		return err;
+	}
+	return 0;
+}
+
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	ssize_t rc;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+	ssize_t rc;
+	u32 timeout;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the timeouts");
+	if (rc)
+		goto duration;
+
+	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	    != 4 * sizeof(u32))
+		goto duration;
+
+	/* Don't overwrite default if value is 0 */
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+	if (timeout)
+		chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+	if (timeout)
+		chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+	if (timeout)
+		chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+	timeout =
+	    be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+	if (timeout)
+		chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the durations");
+	if (rc)
+		return;
+
+	if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+	    != 3 * sizeof(u32))
+		return;
+
+	chip->vendor.duration[TPM_SHORT] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_1_IDX))));
+	chip->vendor.duration[TPM_MEDIUM] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_2_IDX))));
+	chip->vendor.duration[TPM_LONG] =
+	    msecs_to_jiffies(be32_to_cpu
+			     (*((__be32 *) (data +
+					    TPM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+	u8 data[] = {
+		0, 193,			/* TPM_TAG_RQU_COMMAND */
+		0, 0, 0, 10,		/* length */
+		0, 0, 0, 83,		/* TPM_ORD_GetCapability */
+	};
+
+	tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attemtping to determine the permanent state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attemtping to determine the permanent state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+			char *buf)
+{
+	u8 data[sizeof(tpm_cap)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the owner state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+				struct device_attribute * attr, char *buf)
+{
+	u8 data[sizeof(tpm_cap)];
+	ssize_t rc;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the temporary state");
+	if (rc)
+		return 0;
+	return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
 static const u8 pcrread[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 14,		/* length */
@@ -140,8 +676,8 @@
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 data[READ_PCR_RESULT_SIZE];
-	ssize_t len;
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+	ssize_t rc;
 	int i, j, num_pcrs;
 	__be32 index;
 	char *str = buf;
@@ -150,29 +686,24 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	memcpy(data, cap_pcr, sizeof(cap_pcr));
-	if ((len = tpm_transmit(chip, data, sizeof(data)))
-	    < CAP_PCR_RESULT_SIZE) {
-		dev_dbg(chip->dev, "A TPM error (%d) occurred "
-				"attempting to determine the number of PCRS\n",
-			be32_to_cpu(*((__be32 *) (data + 6))));
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the number of PCRS");
+	if (rc)
 		return 0;
-	}
 
 	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
 	for (i = 0; i < num_pcrs; i++) {
 		memcpy(data, pcrread, sizeof(pcrread));
 		index = cpu_to_be32(i);
 		memcpy(data + 10, &index, 4);
-		if ((len = tpm_transmit(chip, data, sizeof(data)))
-		    < READ_PCR_RESULT_SIZE){
-			dev_dbg(chip->dev, "A TPM error (%d) occurred"
-				" attempting to read PCR %d of %d\n",
-				be32_to_cpu(*((__be32 *) (data + 6))),
-				i, num_pcrs);
+		rc = transmit_cmd(chip, data, sizeof(data),
+				"attempting to read a PCR");
+		if (rc)
 			goto out;
-		}
 		str += sprintf(str, "PCR-%02d: ", i);
 		for (j = 0; j < TPM_DIGEST_SIZE; j++)
 			str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +725,7 @@
 		       char *buf)
 {
 	u8 *data;
-	ssize_t len;
+	ssize_t err;
 	int i, rc;
 	char *str = buf;
 
@@ -208,14 +739,10 @@
 
 	memcpy(data, readpubek, sizeof(readpubek));
 
-	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
-	    READ_PUBEK_RESULT_SIZE) {
-		dev_dbg(chip->dev, "A TPM error (%d) occurred "
-				"attempting to read the PUBEK\n",
-			    be32_to_cpu(*((__be32 *) (data + 6))));
-		rc = 0;
+	err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+			"attempting to read the PUBEK");
+	if (err)
 		goto out;
-	}
 
 	/* 
 	   ignore header 10 bytes
@@ -245,36 +772,68 @@
 		if ((i + 1) % 16 == 0)
 			str += sprintf(str, "\n");
 	}
-	rc = str - buf;
 out:
+	rc = str - buf;
 	kfree(data);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_show_pubek);
 
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
 static const u8 cap_version[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 18,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 6,
+	0, 0, 0, 0,
 	0, 0, 0, 0
 };
 
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
-	0, 193,			/* TPM_TAG_RQU_COMMAND */
-	0, 0, 0, 22,		/* length */
-	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
-	0, 0, 0, 5,
-	0, 0, 0, 4,
-	0, 0, 1, 3
-};
-
 ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
-	u8 data[sizeof(cap_manufacturer)];
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
+	ssize_t rc;
+	char *str = buf;
+
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the manufacturer");
+	if (rc)
+		return 0;
+
+	str += sprintf(str, "Manufacturer: 0x%x\n",
+		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+	memcpy(data, cap_version, sizeof(cap_version));
+	data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+	rc = transmit_cmd(chip, data, sizeof(data),
+			"attempting to determine the 1.1 version");
+	if (rc)
+		goto out;
+
+	str += sprintf(str,
+		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
+		       (int) data[14], (int) data[15], (int) data[16],
+		       (int) data[17]);
+
+out:
+	return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_show_caps_1_2(struct device * dev,
+			  struct device_attribute * attr, char *buf)
+{
+	u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)];
 	ssize_t len;
 	char *str = buf;
 
@@ -282,29 +841,40 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+	memcpy(data, tpm_cap, sizeof(tpm_cap));
+	data[TPM_CAP_IDX] = TPM_CAP_PROP;
+	data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
 
-	if ((len = tpm_transmit(chip, data, sizeof(data))) <
-	    CAP_MANUFACTURER_RESULT_SIZE)
-		return len;
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+	    TPM_ERROR_SIZE) {
+		dev_dbg(chip->dev, "A TPM error (%d) occurred "
+			"attempting to determine the manufacturer\n",
+			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+		return 0;
+	}
 
 	str += sprintf(str, "Manufacturer: 0x%x\n",
-		       be32_to_cpu(*((__be32 *) (data + 14))));
+		       be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
 
 	memcpy(data, cap_version, sizeof(cap_version));
+	data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
 
-	if ((len = tpm_transmit(chip, data, sizeof(data))) <
-	    CAP_VER_RESULT_SIZE)
-		return len;
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+	    TPM_ERROR_SIZE) {
+		dev_err(chip->dev, "A TPM error (%d) occurred "
+			"attempting to determine the 1.2 version\n",
+			be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+		goto out;
+	}
+	str += sprintf(str,
+		       "TCG version: %d.%d\nFirmware version: %d.%d\n",
+		       (int) data[16], (int) data[17], (int) data[18],
+		       (int) data[19]);
 
-	str +=
-	    sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
-		    (int) data[14], (int) data[15], (int) data[16],
-		    (int) data[17]);
-
+out:
 	return str - buf;
 }
-EXPORT_SYMBOL_GPL(tpm_show_caps);
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
 
 ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
@@ -313,7 +883,7 @@
 	if (chip == NULL)
 		return 0;
 
-	chip->vendor->cancel(chip);
+	chip->vendor.cancel(chip);
 	return count;
 }
 EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -329,7 +899,7 @@
 	spin_lock(&driver_lock);
 
 	list_for_each_entry(pos, &tpm_chip_list, list) {
-		if (pos->vendor->miscdev.minor == minor) {
+		if (pos->vendor.miscdev.minor == minor) {
 			chip = pos;
 			break;
 		}
@@ -387,7 +957,7 @@
 EXPORT_SYMBOL_GPL(tpm_release);
 
 ssize_t tpm_write(struct file *file, const char __user *buf,
-		  size_t size, loff_t * off)
+		  size_t size, loff_t *off)
 {
 	struct tpm_chip *chip = file->private_data;
 	int in_size = size, out_size;
@@ -419,11 +989,10 @@
 
 	return in_size;
 }
-
 EXPORT_SYMBOL_GPL(tpm_write);
 
-ssize_t tpm_read(struct file * file, char __user *buf,
-		 size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+		 size_t size, loff_t *off)
 {
 	struct tpm_chip *chip = file->private_data;
 	int ret_size;
@@ -462,14 +1031,13 @@
 	spin_unlock(&driver_lock);
 
 	dev_set_drvdata(dev, NULL);
-	misc_deregister(&chip->vendor->miscdev);
-	kfree(chip->vendor->miscdev.name);
+	misc_deregister(&chip->vendor.miscdev);
+	kfree(chip->vendor.miscdev.name);
 
-	sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+	sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
 	tpm_bios_log_teardown(chip->bios_dir);
 
-	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
-		~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+	clear_bit(chip->dev_num, dev_mask);
 
 	kfree(chip);
 
@@ -520,18 +1088,18 @@
  * upon errant exit from this function specific probe function should call
  * pci_disable_device
  */
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
+				       *entry)
 {
 #define DEVNAME_SIZE 7
 
 	char *devname;
 	struct tpm_chip *chip;
-	int i, j;
 
 	/* Driver specific per-device data */
 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
-		return -ENOMEM;
+		return NULL;
 
 	init_MUTEX(&chip->buffer_mutex);
 	init_MUTEX(&chip->tpm_mutex);
@@ -543,45 +1111,37 @@
 	chip->user_read_timer.function = user_reader_timeout;
 	chip->user_read_timer.data = (unsigned long) chip;
 
-	chip->vendor = entry;
+	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
 
-	chip->dev_num = -1;
+	chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
 
-	for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
-		for (j = 0; j < 8 * sizeof(int); j++)
-			if ((dev_mask[i] & (1 << j)) == 0) {
-				chip->dev_num =
-				    i * TPM_NUM_MASK_ENTRIES + j;
-				dev_mask[i] |= 1 << j;
-				goto dev_num_search_complete;
-			}
-
-dev_num_search_complete:
-	if (chip->dev_num < 0) {
+	if (chip->dev_num >= TPM_NUM_DEVICES) {
 		dev_err(dev, "No available tpm device numbers\n");
 		kfree(chip);
-		return -ENODEV;
+		return NULL;
 	} else if (chip->dev_num == 0)
-		chip->vendor->miscdev.minor = TPM_MINOR;
+		chip->vendor.miscdev.minor = TPM_MINOR;
 	else
-		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+		chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+	set_bit(chip->dev_num, dev_mask);
 
 	devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
 	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
-	chip->vendor->miscdev.name = devname;
+	chip->vendor.miscdev.name = devname;
 
-	chip->vendor->miscdev.dev = dev;
+	chip->vendor.miscdev.dev = dev;
 	chip->dev = get_device(dev);
 
-	if (misc_register(&chip->vendor->miscdev)) {
+	if (misc_register(&chip->vendor.miscdev)) {
 		dev_err(chip->dev,
 			"unable to misc_register %s, minor %d\n",
-			chip->vendor->miscdev.name,
-			chip->vendor->miscdev.minor);
+			chip->vendor.miscdev.name,
+			chip->vendor.miscdev.minor);
 		put_device(dev);
+		clear_bit(chip->dev_num, dev_mask);
 		kfree(chip);
-		dev_mask[i] &= !(1 << j);
-		return -ENODEV;
+		return NULL;
 	}
 
 	spin_lock(&driver_lock);
@@ -592,11 +1152,11 @@
 
 	spin_unlock(&driver_lock);
 
-	sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+	sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
 
 	chip->bios_dir = tpm_bios_log_setup(devname);
 
-	return 0;
+	return chip;
 }
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index dec0224..54a4c80 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -42,18 +42,30 @@
 				char *);
 extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
 				char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+				char *);
 extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
 				const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+					 struct device_attribute *attr, char *);
 
 struct tpm_chip;
 
 struct tpm_vendor_specific {
-	u8 req_complete_mask;
-	u8 req_complete_val;
-	u8 req_canceled;
+	const u8 req_complete_mask;
+	const u8 req_complete_val;
+	const u8 req_canceled;
 	void __iomem *iobase;		/* ioremapped address */
 	unsigned long base;		/* TPM base address */
 
+	int irq;
+
 	int region_size;
 	int have_region;
 
@@ -63,6 +75,13 @@
 	u8 (*status) (struct tpm_chip *);
 	struct miscdevice miscdev;
 	struct attribute_group *attr_group;
+	struct list_head list;
+	int locality;
+	unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+	unsigned long duration[3]; /* jiffies */
+
+	wait_queue_head_t read_queue;
+	wait_queue_head_t int_queue;
 };
 
 struct tpm_chip {
@@ -81,13 +100,15 @@
 	struct work_struct work;
 	struct semaphore tpm_mutex;	/* tpm is processing */
 
-	struct tpm_vendor_specific *vendor;
+	struct tpm_vendor_specific vendor;
 
 	struct dentry **bios_dir;
 
 	struct list_head list;
 };
 
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+
 static inline int tpm_read_index(int base, int index)
 {
 	outb(index, base);
@@ -100,8 +121,12 @@
 	outb(value & 0xFF, base+1);
 }
 
-extern int tpm_register_hardware(struct device *,
-				 struct tpm_vendor_specific *);
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+				 const struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
 extern int tpm_release(struct inode *, struct file *);
 extern ssize_t tpm_write(struct file *, const char __user *, size_t,
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index ff36549..58a258c 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -47,12 +47,12 @@
 		return -EIO;
 
 	for (i = 0; i < 6; i++) {
-		status = ioread8(chip->vendor->iobase + 1);
+		status = ioread8(chip->vendor.iobase + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 			dev_err(chip->dev, "error reading header\n");
 			return -EIO;
 		}
-		*buf++ = ioread8(chip->vendor->iobase);
+		*buf++ = ioread8(chip->vendor.iobase);
 	}
 
 	/* size of the data received */
@@ -63,7 +63,7 @@
 		dev_err(chip->dev,
 			"Recv size(%d) less than available space\n", size);
 		for (; i < size; i++) {	/* clear the waiting data anyway */
-			status = ioread8(chip->vendor->iobase + 1);
+			status = ioread8(chip->vendor.iobase + 1);
 			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 				dev_err(chip->dev, "error reading data\n");
 				return -EIO;
@@ -74,16 +74,16 @@
 
 	/* read all the data available */
 	for (; i < size; i++) {
-		status = ioread8(chip->vendor->iobase + 1);
+		status = ioread8(chip->vendor.iobase + 1);
 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
 			dev_err(chip->dev, "error reading data\n");
 			return -EIO;
 		}
-		*buf++ = ioread8(chip->vendor->iobase);
+		*buf++ = ioread8(chip->vendor.iobase);
 	}
 
 	/* make sure data available is gone */
-	status = ioread8(chip->vendor->iobase + 1);
+	status = ioread8(chip->vendor.iobase + 1);
 
 	if (status & ATML_STATUS_DATA_AVAIL) {
 		dev_err(chip->dev, "data available is stuck\n");
@@ -100,7 +100,7 @@
 	dev_dbg(chip->dev, "tpm_atml_send:\n");
 	for (i = 0; i < count; i++) {
 		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
- 		iowrite8(buf[i], chip->vendor->iobase);
+ 		iowrite8(buf[i], chip->vendor.iobase);
 	}
 
 	return count;
@@ -108,12 +108,12 @@
 
 static void tpm_atml_cancel(struct tpm_chip *chip)
 {
-	iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
+	iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
 }
 
 static u8 tpm_atml_status(struct tpm_chip *chip)
 {
-	return ioread8(chip->vendor->iobase + 1);
+	return ioread8(chip->vendor.iobase + 1);
 }
 
 static struct file_operations atmel_ops = {
@@ -140,7 +140,7 @@
 
 static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
 
-static struct tpm_vendor_specific tpm_atmel = {
+static const struct tpm_vendor_specific tpm_atmel = {
 	.recv = tpm_atml_recv,
 	.send = tpm_atml_send,
 	.cancel = tpm_atml_cancel,
@@ -159,10 +159,10 @@
 	struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
 
 	if (chip) {
-		if (chip->vendor->have_region)
-			atmel_release_region(chip->vendor->base,
-					     chip->vendor->region_size);
-		atmel_put_base_addr(chip->vendor);
+		if (chip->vendor.have_region)
+			atmel_release_region(chip->vendor.base,
+					     chip->vendor.region_size);
+		atmel_put_base_addr(chip->vendor.iobase);
 		tpm_remove_hardware(chip->dev);
 		platform_device_unregister(pdev);
 	}
@@ -179,18 +179,22 @@
 static int __init init_atmel(void)
 {
 	int rc = 0;
+	void __iomem *iobase = NULL;
+	int have_region, region_size;
+	unsigned long base;
+	struct  tpm_chip *chip;
 
 	driver_register(&atml_drv);
 
-	if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
+	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
 		rc = -ENODEV;
 		goto err_unreg_drv;
 	}
 
-	tpm_atmel.have_region =
+	have_region =
 	    (atmel_request_region
-	     (tpm_atmel.base, tpm_atmel.region_size,
-	      "tpm_atmel0") == NULL) ? 0 : 1;
+	     (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+
 
 	if (IS_ERR
 	    (pdev =
@@ -199,17 +203,25 @@
 		goto err_rel_reg;
 	}
 
-	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
+		rc = -ENODEV;
 		goto err_unreg_dev;
+	}
+
+	chip->vendor.iobase = iobase;
+	chip->vendor.base = base;
+	chip->vendor.have_region = have_region;
+	chip->vendor.region_size = region_size;
+
 	return 0;
 
 err_unreg_dev:
 	platform_device_unregister(pdev);
 err_rel_reg:
-	atmel_put_base_addr(&tpm_atmel);
-	if (tpm_atmel.have_region)
-		atmel_release_region(tpm_atmel.base,
-				     tpm_atmel.region_size);
+	atmel_put_base_addr(iobase);
+	if (have_region)
+		atmel_release_region(base,
+				     region_size);
 err_unreg_drv:
 	driver_unregister(&atml_drv);
 	return rc;
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h
index d3478aa..2e68eeb 100644
--- a/drivers/char/tpm/tpm_atmel.h
+++ b/drivers/char/tpm/tpm_atmel.h
@@ -28,13 +28,12 @@
 #define atmel_request_region request_mem_region
 #define atmel_release_region release_mem_region
 
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
 {
-	iounmap(vendor->iobase);
+	iounmap(iobase);
 }
 
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
 {
 	struct device_node *dn;
 	unsigned long address, size;
@@ -71,9 +70,9 @@
 	else
 		size = reg[naddrc];
 
-	vendor->base = address;
-	vendor->region_size = size;
-	return ioremap(vendor->base, vendor->region_size);
+	*base = address;
+	*region_size = size;
+	return ioremap(*base, *region_size);
 }
 #else
 #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
@@ -106,14 +105,12 @@
 	return 0;
 }
 
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
 {
 }
 
 /* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
-					 *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
 {
 	int lo, hi;
 
@@ -123,9 +120,9 @@
 	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
 	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
 
-	vendor->base = (hi << 8) | lo;
-	vendor->region_size = 2;
+	*base = (hi << 8) | lo;
+	*region_size = 2;
 
-	return ioport_map(vendor->base, vendor->region_size);
+	return ioport_map(*base, *region_size);
 }
 #endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 537aa45..e45f0d3 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -29,6 +29,11 @@
 #define MAX_TEXT_EVENT		1000	/* Max event string length */
 #define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
 
+enum bios_platform_class {
+	BIOS_CLIENT = 0x00,
+	BIOS_SERVER = 0x01,
+};
+
 struct tpm_bios_log {
 	void *bios_event_log;
 	void *bios_event_log_end;
@@ -36,9 +41,18 @@
 
 struct acpi_tcpa {
 	struct acpi_table_header hdr;
-	u16 reserved;
-	u32 log_max_len __attribute__ ((packed));
-	u32 log_start_addr __attribute__ ((packed));
+	u16 platform_class;
+	union {
+		struct client_hdr {
+			u32 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} client;
+		struct server_hdr {
+			u16 reserved;
+			u64 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} server;
+	};
 };
 
 struct tcpa_event {
@@ -120,6 +134,7 @@
 	"S-CRTM Version",
 	"S-CRTM Contents",
 	"S-CRTM POST Contents",
+	"POST Contents",
 };
 
 /* returns pointer to start of pos. entry of tcg log */
@@ -306,6 +321,7 @@
 	/* 5th: delimiter */
 	seq_putc(m, '\0');
 
+	kfree(eventname);
 	return 0;
 }
 
@@ -353,6 +369,7 @@
 	/* 4th: eventname <= max + \'0' delimiter */
 	seq_printf(m, " %s\n", eventname);
 
+	kfree(eventname);
 	return 0;
 }
 
@@ -376,6 +393,7 @@
 	struct acpi_tcpa *buff;
 	acpi_status status;
 	struct acpi_table_header *virt;
+	u64 len, start;
 
 	if (log->bios_event_log != NULL) {
 		printk(KERN_ERR
@@ -396,27 +414,37 @@
 		return -EIO;
 	}
 
-	if (buff->log_max_len == 0) {
+	switch(buff->platform_class) {
+	case BIOS_SERVER:
+		len = buff->server.log_max_len;
+		start = buff->server.log_start_addr;
+		break;
+	case BIOS_CLIENT:
+	default:
+		len = buff->client.log_max_len;
+		start = buff->client.log_start_addr;
+		break;
+	}
+	if (!len) {
 		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
 		return -EIO;
 	}
 
 	/* malloc EventLog space */
-	log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
 	if (!log->bios_event_log) {
-		printk
-		    ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-		     __func__);
+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+			__func__);
 		return -ENOMEM;
 	}
 
-	log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+	log->bios_event_log_end = log->bios_event_log + len;
 
-	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
+	acpi_os_map_memory(start, len, (void *) &virt);
 
-	memcpy(log->bios_event_log, virt, buff->log_max_len);
+	memcpy(log->bios_event_log, virt, len);
 
-	acpi_os_unmap_memory(virt, buff->log_max_len);
+	acpi_os_unmap_memory(virt, len);
 	return 0;
 }
 
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 24095f6..adfff21 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -15,6 +15,7 @@
  * License.
  */
 
+#include <linux/init.h>
 #include <linux/pnp.h>
 #include "tpm.h"
 
@@ -104,7 +105,7 @@
 
 	if (clear_wrfifo) {
 		for (i = 0; i < 4096; i++) {
-			status = inb(chip->vendor->base + WRFIFO);
+			status = inb(chip->vendor.base + WRFIFO);
 			if (status == 0xff) {
 				if (check == 5)
 					break;
@@ -124,8 +125,8 @@
 	 */
 	i = 0;
 	do {
-		status = inb(chip->vendor->base + RDFIFO);
-		status = inb(chip->vendor->base + STAT);
+		status = inb(chip->vendor.base + RDFIFO);
+		status = inb(chip->vendor.base + STAT);
 		i++;
 		if (i == TPM_MAX_TRIES)
 			return -EIO;
@@ -138,7 +139,7 @@
 	int status;
 	int i;
 	for (i = 0; i < TPM_MAX_TRIES; i++) {
-		status = inb(chip->vendor->base + STAT);
+		status = inb(chip->vendor.base + STAT);
 		/* check the status-register if wait_for_bit is set */
 		if (status & 1 << wait_for_bit)
 			break;
@@ -157,7 +158,7 @@
 static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
 {
 	wait(chip, STAT_XFE);
-	outb(sendbyte, chip->vendor->base + WRFIFO);
+	outb(sendbyte, chip->vendor.base + WRFIFO);
 }
 
     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
@@ -204,7 +205,7 @@
 		ret = wait(chip, STAT_RDA);
 		if (ret)
 			return -EIO;
-		buf[i] = inb(chip->vendor->base + RDFIFO);
+		buf[i] = inb(chip->vendor.base + RDFIFO);
 	}
 
 	if (buf[0] != TPM_VL_VER) {
@@ -219,7 +220,7 @@
 
 		for (i = 0; i < size; i++) {
 			wait(chip, STAT_RDA);
-			buf[i] = inb(chip->vendor->base + RDFIFO);
+			buf[i] = inb(chip->vendor.base + RDFIFO);
 		}
 
 		if ((size == 0x6D00) && (buf[1] == 0x80)) {
@@ -268,7 +269,7 @@
 	u8 count_high, count_low, count_4, count_3, count_2, count_1;
 
 	/* Disabling Reset, LP and IRQC */
-	outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
+	outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
 
 	ret = empty_fifo(chip, 1);
 	if (ret) {
@@ -319,7 +320,7 @@
 
 static u8 tpm_inf_status(struct tpm_chip *chip)
 {
-	return inb(chip->vendor->base + STAT);
+	return inb(chip->vendor.base + STAT);
 }
 
 static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
@@ -346,7 +347,7 @@
 	.release = tpm_release,
 };
 
-static struct tpm_vendor_specific tpm_inf = {
+static const struct tpm_vendor_specific tpm_inf = {
 	.recv = tpm_inf_recv,
 	.send = tpm_inf_send,
 	.cancel = tpm_inf_cancel,
@@ -375,6 +376,7 @@
 	int version[2];
 	int productid[2];
 	char chipname[20];
+	struct tpm_chip *chip;
 
 	/* read IO-ports through PnP */
 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
@@ -395,14 +397,13 @@
 			goto err_last;
 		}
 		/* publish my base address and request region */
-		tpm_inf.base = TPM_INF_BASE;
 		if (request_region
-		    (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+		    (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
 			rc = -EINVAL;
 			goto err_last;
 		}
-		if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
-				"tpm_infineon0") == NULL) {
+		if (request_region
+		    (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
 			rc = -EINVAL;
 			goto err_last;
 		}
@@ -442,9 +443,9 @@
 
 		/* configure TPM with IO-ports */
 		outb(IOLIMH, TPM_INF_ADDR);
-		outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
+		outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
 		outb(IOLIML, TPM_INF_ADDR);
-		outb((tpm_inf.base & 0xff), TPM_INF_DATA);
+		outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
 
 		/* control if IO-ports are set correctly */
 		outb(IOLIMH, TPM_INF_ADDR);
@@ -452,10 +453,10 @@
 		outb(IOLIML, TPM_INF_ADDR);
 		iol = inb(TPM_INF_DATA);
 
-		if ((ioh << 8 | iol) != tpm_inf.base) {
+		if ((ioh << 8 | iol) != TPM_INF_BASE) {
 			dev_err(&dev->dev,
-				"Could not set IO-ports to 0x%lx\n",
-				tpm_inf.base);
+				"Could not set IO-ports to 0x%x\n",
+				TPM_INF_BASE);
 			rc = -EIO;
 			goto err_release_region;
 		}
@@ -466,15 +467,15 @@
 		outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
 
 		/* disable RESET, LP and IRQC */
-		outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
+		outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
 
 		/* Finally, we're done, print some infos */
 		dev_info(&dev->dev, "TPM found: "
 			 "config base 0x%x, "
 			 "io base 0x%x, "
-			 "chip version %02x%02x, "
-			 "vendor id %x%x (Infineon), "
-			 "product id %02x%02x"
+			 "chip version 0x%02x%02x, "
+			 "vendor id 0x%x%x (Infineon), "
+			 "product id 0x%02x%02x"
 			 "%s\n",
 			 TPM_INF_ADDR,
 			 TPM_INF_BASE,
@@ -482,11 +483,10 @@
 			 vendorid[0], vendorid[1],
 			 productid[0], productid[1], chipname);
 
-		rc = tpm_register_hardware(&dev->dev, &tpm_inf);
-		if (rc < 0) {
-			rc = -ENODEV;
+		if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
 			goto err_release_region;
 		}
+		chip->vendor.base = TPM_INF_BASE;
 		return 0;
 	} else {
 		rc = -ENODEV;
@@ -494,7 +494,7 @@
 	}
 
 err_release_region:
-	release_region(tpm_inf.base, TPM_INF_PORT_LEN);
+	release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
 	release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
 
 err_last:
@@ -506,7 +506,8 @@
 	struct tpm_chip *chip = pnp_get_drvdata(dev);
 
 	if (chip) {
-		release_region(chip->vendor->base, TPM_INF_PORT_LEN);
+		release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+		release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
 		tpm_remove_hardware(chip->dev);
 	}
 }
@@ -520,7 +521,7 @@
 	},
 	.id_table = tpm_pnp_tbl,
 	.probe = tpm_inf_pnp_probe,
-	.remove = tpm_inf_pnp_remove,
+	.remove = __devexit_p(tpm_inf_pnp_remove),
 };
 
 static int __init init_inf(void)
@@ -538,5 +539,5 @@
 
 MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.8");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 680a8e3..4c8bc06 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -71,7 +71,7 @@
 	unsigned long stop;
 
 	/* status immediately available check */
-	*data = inb(chip->vendor->base + NSC_STATUS);
+	*data = inb(chip->vendor.base + NSC_STATUS);
 	if ((*data & mask) == val)
 		return 0;
 
@@ -79,7 +79,7 @@
 	stop = jiffies + 10 * HZ;
 	do {
 		msleep(TPM_TIMEOUT);
-		*data = inb(chip->vendor->base + 1);
+		*data = inb(chip->vendor.base + 1);
 		if ((*data & mask) == val)
 			return 0;
 	}
@@ -94,9 +94,9 @@
 	unsigned long stop;
 
 	/* status immediately available check */
-	status = inb(chip->vendor->base + NSC_STATUS);
+	status = inb(chip->vendor.base + NSC_STATUS);
 	if (status & NSC_STATUS_OBF)
-		status = inb(chip->vendor->base + NSC_DATA);
+		status = inb(chip->vendor.base + NSC_DATA);
 	if (status & NSC_STATUS_RDY)
 		return 0;
 
@@ -104,9 +104,9 @@
 	stop = jiffies + 100;
 	do {
 		msleep(TPM_TIMEOUT);
-		status = inb(chip->vendor->base + NSC_STATUS);
+		status = inb(chip->vendor.base + NSC_STATUS);
 		if (status & NSC_STATUS_OBF)
-			status = inb(chip->vendor->base + NSC_DATA);
+			status = inb(chip->vendor.base + NSC_DATA);
 		if (status & NSC_STATUS_RDY)
 			return 0;
 	}
@@ -132,7 +132,7 @@
 		return -EIO;
 	}
 	if ((data =
-	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+	     inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
 		dev_err(chip->dev, "not in normal mode (0x%x)\n",
 			data);
 		return -EIO;
@@ -148,7 +148,7 @@
 		}
 		if (data & NSC_STATUS_F0)
 			break;
-		*p = inb(chip->vendor->base + NSC_DATA);
+		*p = inb(chip->vendor.base + NSC_DATA);
 	}
 
 	if ((data & NSC_STATUS_F0) == 0 &&
@@ -156,7 +156,7 @@
 		dev_err(chip->dev, "F0 not set\n");
 		return -EIO;
 	}
-	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+	if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
 		dev_err(chip->dev,
 			"expected end of command(0x%x)\n", data);
 		return -EIO;
@@ -182,7 +182,7 @@
 	 * fix it. Not sure why this is needed, we followed the flow
 	 * chart in the manual to the letter.
 	 */
-	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
 
 	if (nsc_wait_for_ready(chip) != 0)
 		return -EIO;
@@ -192,7 +192,7 @@
 		return -EIO;
 	}
 
-	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
 	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
 		dev_err(chip->dev, "IBR timeout\n");
 		return -EIO;
@@ -204,26 +204,26 @@
 				"IBF timeout (while writing data)\n");
 			return -EIO;
 		}
-		outb(buf[i], chip->vendor->base + NSC_DATA);
+		outb(buf[i], chip->vendor.base + NSC_DATA);
 	}
 
 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
 		dev_err(chip->dev, "IBF timeout\n");
 		return -EIO;
 	}
-	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
 
 	return count;
 }
 
 static void tpm_nsc_cancel(struct tpm_chip *chip)
 {
-	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
 }
 
 static u8 tpm_nsc_status(struct tpm_chip *chip)
 {
-	return inb(chip->vendor->base + NSC_STATUS);
+	return inb(chip->vendor.base + NSC_STATUS);
 }
 
 static struct file_operations nsc_ops = {
@@ -250,7 +250,7 @@
 
 static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
 
-static struct tpm_vendor_specific tpm_nsc = {
+static const struct tpm_vendor_specific tpm_nsc = {
 	.recv = tpm_nsc_recv,
 	.send = tpm_nsc_send,
 	.cancel = tpm_nsc_cancel,
@@ -268,7 +268,7 @@
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if ( chip ) {
-		release_region(chip->vendor->base, 2);
+		release_region(chip->vendor.base, 2);
 		tpm_remove_hardware(chip->dev);
 	}
 }
@@ -286,7 +286,8 @@
 	int rc = 0;
 	int lo, hi;
 	int nscAddrBase = TPM_ADDR;
-
+	struct tpm_chip *chip;
+	unsigned long base;
 
 	/* verify that it is a National part (SID) */
 	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,7 +301,7 @@
 
 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
 	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
-	tpm_nsc.base = (hi<<8) | lo;
+	base = (hi<<8) | lo;
 
 	/* enable the DPM module */
 	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
@@ -320,13 +321,15 @@
 	if ((rc = platform_device_register(pdev)) < 0)
 		goto err_free_dev;
 
-	if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+	if (request_region(base, 2, "tpm_nsc0") == NULL ) {
 		rc = -EBUSY;
 		goto err_unreg_dev;
 	}
 
-	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
+		rc = -ENODEV;
 		goto err_rel_reg;
+	}
 
 	dev_dbg(&pdev->dev, "NSC TPM detected\n");
 	dev_dbg(&pdev->dev,
@@ -361,10 +364,12 @@
 		 "NSC TPM revision %d\n",
 		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
 
+	chip->vendor.base = base;
+
 	return 0;
 
 err_rel_reg:
-	release_region(tpm_nsc.base, 2);
+	release_region(base, 2);
 err_unreg_dev:
 	platform_device_unregister(pdev);
 err_free_dev:
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
new file mode 100644
index 0000000..b9cae9a
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis.c
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+#define TPM_HEADER_SIZE 10
+
+enum tis_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80000000,
+	TPM_INTF_BURST_COUNT_STATIC = 0x100,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_INT_EDGE_FALLING = 0x040,
+	TPM_INTF_INT_EDGE_RISING = 0x020,
+	TPM_INTF_INT_LEVEL_LOW = 0x010,
+	TPM_INTF_INT_LEVEL_HIGH = 0x008,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_MEM_BASE = 0xFED4000,
+	TIS_MEM_LEN = 0x5000,
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
+#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
+#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
+#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
+#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
+#define	TPM_STS(l)			(0x0018 | ((l) << 12))
+#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
+
+#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
+#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
+
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+	if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality = l;
+
+	return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+	if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+		iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
+			 chip->vendor.iobase + TPM_ACCESS(l));
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+	unsigned long stop;
+	long rc;
+
+	if (check_locality(chip, l) >= 0)
+		return l;
+
+	iowrite8(TPM_ACCESS_REQUEST_USE,
+		 chip->vendor.iobase + TPM_ACCESS(l));
+
+	if (chip->vendor.irq) {
+		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
+						      (check_locality
+						       (chip, l) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return l;
+
+	} else {
+		/* wait for burstcount */
+		stop = jiffies + chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip, l) >= 0)
+				return l;
+			msleep(TPM_TIMEOUT);
+		}
+		while (time_before(jiffies, stop));
+	}
+	return -1;
+}
+
+static u8 tpm_tis_status(struct tpm_chip *chip)
+{
+	return ioread8(chip->vendor.iobase +
+		       TPM_STS(chip->vendor.locality));
+}
+
+static void tpm_tis_ready(struct tpm_chip *chip)
+{
+	/* this causes the current command to be aborted */
+	iowrite8(TPM_STS_COMMAND_READY,
+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+}
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt;
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		burstcnt = ioread8(chip->vendor.iobase +
+				   TPM_STS(chip->vendor.locality) + 1);
+		burstcnt += ioread8(chip->vendor.iobase +
+				    TPM_STS(chip->vendor.locality) +
+				    2) << 8;
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+	return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 wait_queue_head_t *queue)
+{
+	unsigned long stop;
+	long rc;
+	u8 status;
+
+	/* check current status */
+	status = tpm_tis_status(chip);
+	if ((status & mask) == mask)
+		return 0;
+
+	if (chip->vendor.irq) {
+		rc = wait_event_interruptible_timeout(*queue,
+						      ((tpm_tis_status
+							(chip) & mask) ==
+						       mask), timeout);
+		if (rc > 0)
+			return 0;
+	} else {
+		stop = jiffies + timeout;
+		do {
+			msleep(TPM_TIMEOUT);
+			status = tpm_tis_status(chip);
+			if ((status & mask) == mask)
+				return 0;
+		} while (time_before(jiffies, stop));
+	}
+	return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt;
+	while (size < count &&
+	       wait_for_stat(chip,
+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+			     chip->vendor.timeout_c,
+			     &chip->vendor.read_queue)
+	       == 0) {
+		burstcnt = get_burstcount(chip);
+		for (; burstcnt > 0 && size < count; burstcnt--)
+			buf[size++] = ioread8(chip->vendor.iobase +
+					      TPM_DATA_FIFO(chip->vendor.
+							    locality));
+	}
+	return size;
+}
+
+static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* read first 10 bytes, including tag, paramsize, and result */
+	if ((size =
+	     recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+		dev_err(chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+	expected = be32_to_cpu(*(__be32 *) (buf + 2));
+	if (expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	if ((size +=
+	     recv_data(chip, &buf[TPM_HEADER_SIZE],
+		       expected - TPM_HEADER_SIZE)) < expected) {
+		dev_err(chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+		      &chip->vendor.int_queue);
+	status = tpm_tis_status(chip);
+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+		dev_err(chip->dev, "Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status, burstcnt;
+	size_t count = 0;
+	u32 ordinal;
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_ready(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	while (count < len - 1) {
+		burstcnt = get_burstcount(chip);
+		for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+			iowrite8(buf[count], chip->vendor.iobase +
+				 TPM_DATA_FIFO(chip->vendor.locality));
+			count++;
+		}
+
+		wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+			      &chip->vendor.int_queue);
+		status = tpm_tis_status(chip);
+		if ((status & TPM_STS_DATA_EXPECT) == 0) {
+			rc = -EIO;
+			goto out_err;
+		}
+	}
+
+	/* write last byte */
+	iowrite8(buf[count],
+		 chip->vendor.iobase +
+		 TPM_DATA_FIFO(chip->vendor.locality));
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+		      &chip->vendor.int_queue);
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	/* go and do it */
+	iowrite8(TPM_STS_GO,
+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+
+	if (chip->vendor.irq) {
+		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+		if (wait_for_stat
+		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+		     tpm_calc_ordinal_duration(chip, ordinal),
+		     &chip->vendor.read_queue) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+	return len;
+out_err:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+static struct file_operations tis_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+		   NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+	.attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis = {
+	.status = tpm_tis_status,
+	.recv = tpm_tis_recv,
+	.send = tpm_tis_send,
+	.cancel = tpm_tis_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &tis_attr_grp,
+	.miscdev = {
+		    .fops = &tis_ops,},
+};
+
+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+	u32 interrupt;
+
+	interrupt = ioread32(chip->vendor.iobase +
+			     TPM_INT_STATUS(chip->vendor.locality));
+
+	if (interrupt == 0)
+		return IRQ_NONE;
+
+	chip->vendor.irq = irq;
+
+	/* Clear interrupts handled with TPM_EOI */
+	iowrite32(interrupt,
+		  chip->vendor.iobase +
+		  TPM_INT_STATUS(chip->vendor.locality));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+	u32 interrupt;
+	int i;
+
+	interrupt = ioread32(chip->vendor.iobase +
+			     TPM_INT_STATUS(chip->vendor.locality));
+
+	if (interrupt == 0)
+		return IRQ_NONE;
+
+	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+		wake_up_interruptible(&chip->vendor.read_queue);
+	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+		for (i = 0; i < 5; i++)
+			if (check_locality(chip, i) >= 0)
+				break;
+	if (interrupt &
+	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+	     TPM_INTF_CMD_READY_INT))
+		wake_up_interruptible(&chip->vendor.int_queue);
+
+	/* Clear interrupts handled with TPM_EOI */
+	iowrite32(interrupt,
+		  chip->vendor.iobase +
+		  TPM_INT_STATUS(chip->vendor.locality));
+	return IRQ_HANDLED;
+}
+
+static int interrupts = 1;
+module_param(interrupts, bool, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+				      const struct pnp_device_id *pnp_id)
+{
+	u32 vendor, intfcaps, intmask;
+	int rc, i;
+	unsigned long start, len;
+	struct tpm_chip *chip;
+
+	start = pnp_mem_start(pnp_dev, 0);
+	len = pnp_mem_len(pnp_dev, 0);
+
+	if (!start)
+		start = TIS_MEM_BASE;
+	if (!len)
+		len = TIS_MEM_LEN;
+
+	if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
+		return -ENODEV;
+
+	chip->vendor.iobase = ioremap(start, len);
+	if (!chip->vendor.iobase) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+	if ((vendor & 0xFFFF) == 0xFFFF) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	dev_info(&pnp_dev->dev,
+		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
+	/* Figure out the capabilities */
+	intfcaps =
+	    ioread32(chip->vendor.iobase +
+		     TPM_INTF_CAPS(chip->vendor.locality));
+	dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
+		intfcaps);
+	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+		dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
+	if (intfcaps & TPM_INTF_CMD_READY_INT)
+		dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
+	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+		dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
+	if (intfcaps & TPM_INTF_STS_VALID_INT)
+		dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
+	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+		dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
+
+	if (request_locality(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* INTERRUPT Setup */
+	init_waitqueue_head(&chip->vendor.read_queue);
+	init_waitqueue_head(&chip->vendor.int_queue);
+
+	intmask =
+	    ioread32(chip->vendor.iobase +
+		     TPM_INT_ENABLE(chip->vendor.locality));
+
+	intmask |= TPM_INTF_CMD_READY_INT
+	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+	    | TPM_INTF_STS_VALID_INT;
+
+	iowrite32(intmask,
+		  chip->vendor.iobase +
+		  TPM_INT_ENABLE(chip->vendor.locality));
+	if (interrupts) {
+		chip->vendor.irq =
+		    ioread8(chip->vendor.iobase +
+			    TPM_INT_VECTOR(chip->vendor.locality));
+
+		for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+			iowrite8(i, chip->vendor.iobase +
+				    TPM_INT_VECTOR(chip->vendor.locality));
+			if (request_irq
+			    (i, tis_int_probe, SA_SHIRQ,
+			     chip->vendor.miscdev.name, chip) != 0) {
+				dev_info(chip->dev,
+					 "Unable to request irq: %d for probe\n",
+					 i);
+				continue;
+			}
+
+			/* Clear all existing */
+			iowrite32(ioread32
+				  (chip->vendor.iobase +
+				   TPM_INT_STATUS(chip->vendor.locality)),
+				  chip->vendor.iobase +
+				  TPM_INT_STATUS(chip->vendor.locality));
+
+			/* Turn on */
+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+
+			/* Generate Interrupts */
+			tpm_gen_interrupt(chip);
+
+			/* Turn off */
+			iowrite32(intmask,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+			free_irq(i, chip);
+		}
+	}
+	if (chip->vendor.irq) {
+		iowrite8(chip->vendor.irq,
+			 chip->vendor.iobase +
+			 TPM_INT_VECTOR(chip->vendor.locality));
+		if (request_irq
+		    (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
+		     chip->vendor.miscdev.name, chip) != 0) {
+			dev_info(chip->dev,
+				 "Unable to request irq: %d for use\n",
+				 chip->vendor.irq);
+			chip->vendor.irq = 0;
+		} else {
+			/* Clear all existing */
+			iowrite32(ioread32
+				  (chip->vendor.iobase +
+				   TPM_INT_STATUS(chip->vendor.locality)),
+				  chip->vendor.iobase +
+				  TPM_INT_STATUS(chip->vendor.locality));
+
+			/* Turn on */
+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+				  chip->vendor.iobase +
+				  TPM_INT_ENABLE(chip->vendor.locality));
+		}
+	}
+
+	INIT_LIST_HEAD(&chip->vendor.list);
+	spin_lock(&tis_lock);
+	list_add(&chip->vendor.list, &tis_chips);
+	spin_unlock(&tis_lock);
+
+	tpm_get_timeouts(chip);
+	tpm_continue_selftest(chip);
+
+	return 0;
+out_err:
+	if (chip->vendor.iobase)
+		iounmap(chip->vendor.iobase);
+	tpm_remove_hardware(chip->dev);
+	return rc;
+}
+
+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
+{
+	return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+{
+	return tpm_pm_resume(&dev->dev);
+}
+
+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+	{"PNP0C31", 0},		/* TPM */
+	{"ATM1200", 0},		/* Atmel */
+	{"IFX0102", 0},		/* Infineon */
+	{"BCM0101", 0},		/* Broadcom */
+	{"NSC1200", 0},		/* National */
+	/* Add new here */
+	{"", 0},		/* User Specified */
+	{"", 0}			/* Terminator */
+};
+
+static struct pnp_driver tis_pnp_driver = {
+	.name = "tpm_tis",
+	.id_table = tpm_pnp_tbl,
+	.probe = tpm_tis_pnp_init,
+	.suspend = tpm_tis_pnp_suspend,
+	.resume = tpm_tis_pnp_resume,
+};
+
+#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
+		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
+MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
+
+static int __init init_tis(void)
+{
+	return pnp_register_driver(&tis_pnp_driver);
+}
+
+static void __exit cleanup_tis(void)
+{
+	struct tpm_vendor_specific *i, *j;
+	struct tpm_chip *chip;
+	spin_lock(&tis_lock);
+	list_for_each_entry_safe(i, j, &tis_chips, list) {
+		chip = to_tpm_chip(i);
+		iowrite32(~TPM_GLOBAL_INT_ENABLE &
+			  ioread32(chip->vendor.iobase +
+				   TPM_INT_ENABLE(chip->vendor.
+						  locality)),
+			  chip->vendor.iobase +
+			  TPM_INT_ENABLE(chip->vendor.locality));
+		release_locality(chip, chip->vendor.locality, 1);
+		if (chip->vendor.irq)
+			free_irq(chip->vendor.irq, chip);
+		iounmap(i->iobase);
+		list_del(&i->list);
+		tpm_remove_hardware(chip->dev);
+	}
+	spin_unlock(&tis_lock);
+	pnp_unregister_driver(&tis_pnp_driver);
+}
+
+module_init(init_tis);
+module_exit(cleanup_tis);
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 98b126c..f07637a 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -351,10 +351,10 @@
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
 	return size;
 }
-
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
 
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+				size_t size)
 {
 	int copied = 0;
 	do {
@@ -368,17 +368,16 @@
 		tb->used += space;
 		copied += space;
 		chars += space;
-/* 		printk("Flip insert %d.\n", space); */
 	}
 	/* There is a small chance that we need to split the data over
 	   several buffers. If this is the case we must loop */
 	while (unlikely(size > copied));
 	return copied;
 }
-
 EXPORT_SYMBOL(tty_insert_flip_string);
 
-int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size)
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+		const unsigned char *chars, const char *flags, size_t size)
 {
 	int copied = 0;
 	do {
@@ -399,9 +398,20 @@
 	while (unlikely(size > copied));
 	return copied;
 }
-
 EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
 
+void tty_schedule_flip(struct tty_struct *tty)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&tty->buf.lock, flags);
+	if (tty->buf.tail != NULL) {
+		tty->buf.tail->active = 0;
+		tty->buf.tail->commit = tty->buf.tail->used;
+	}
+	spin_unlock_irqrestore(&tty->buf.lock, flags);
+	schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
 
 /*
  *	Prepare a block of space in the buffer for data. Returns the length
@@ -1730,7 +1740,7 @@
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
-	int	devpts_master, devpts;
+	int	devpts;
 	int	idx;
 	char	buf[64];
 	unsigned long flags;
@@ -1747,7 +1757,6 @@
 	pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 		      tty->driver->subtype == PTY_TYPE_MASTER);
 	devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
-	devpts_master = pty_master && devpts;
 	o_tty = tty->link;
 
 #ifdef TTY_PARANOIA_CHECK
@@ -2185,6 +2194,7 @@
 		return 0;
 out1:
 	release_dev(filp);
+	return retval;
 out:
 	down(&allocated_ptys_lock);
 	idr_remove(&allocated_ptys, index);
@@ -2713,7 +2723,11 @@
 		}
 		task_lock(p);
 		if (p->files) {
-			rcu_read_lock();
+			/*
+			 * We don't take a ref to the file, so we must
+			 * hold ->file_lock instead.
+			 */
+			spin_lock(&p->files->file_lock);
 			fdt = files_fdtable(p->files);
 			for (i=0; i < fdt->max_fds; i++) {
 				filp = fcheck_files(p->files, i);
@@ -2724,11 +2738,11 @@
 					printk(KERN_NOTICE "SAK: killed process %d"
 					    " (%s): fd#%d opened to the tty\n",
 					    p->pid, p->comm, i);
-					send_sig(SIGKILL, p, 1);
+					force_sig(SIGKILL, p);
 					break;
 				}
 			}
-			rcu_read_unlock();
+			spin_unlock(&p->files->file_lock);
 		}
 		task_unlock(p);
 	} while_each_thread(g, p);
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
deleted file mode 100644
index b109d9a..0000000
--- a/drivers/char/vr41xx_rtc.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- *  Driver for NEC VR4100 series  Real Time Clock unit.
- *
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mc146818rtc.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/rtc.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-
-#include <asm/div64.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/uaccess.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
-MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL");
-
-#define RTC1_TYPE1_START	0x0b0000c0UL
-#define RTC1_TYPE1_END		0x0b0000dfUL
-#define RTC2_TYPE1_START	0x0b0001c0UL
-#define RTC2_TYPE1_END		0x0b0001dfUL
-
-#define RTC1_TYPE2_START	0x0f000100UL
-#define RTC1_TYPE2_END		0x0f00011fUL
-#define RTC2_TYPE2_START	0x0f000120UL
-#define RTC2_TYPE2_END		0x0f00013fUL
-
-#define RTC1_SIZE		0x20
-#define RTC2_SIZE		0x20
-
-/* RTC 1 registers */
-#define ETIMELREG		0x00
-#define ETIMEMREG		0x02
-#define ETIMEHREG		0x04
-/* RFU */
-#define ECMPLREG		0x08
-#define ECMPMREG		0x0a
-#define ECMPHREG		0x0c
-/* RFU */
-#define RTCL1LREG		0x10
-#define RTCL1HREG		0x12
-#define RTCL1CNTLREG		0x14
-#define RTCL1CNTHREG		0x16
-#define RTCL2LREG		0x18
-#define RTCL2HREG		0x1a
-#define RTCL2CNTLREG		0x1c
-#define RTCL2CNTHREG		0x1e
-
-/* RTC 2 registers */
-#define TCLKLREG		0x00
-#define TCLKHREG		0x02
-#define TCLKCNTLREG		0x04
-#define TCLKCNTHREG		0x06
-/* RFU */
-#define RTCINTREG		0x1e
- #define TCLOCK_INT		0x08
- #define RTCLONG2_INT		0x04
- #define RTCLONG1_INT		0x02
- #define ELAPSEDTIME_INT	0x01
-
-#define RTC_FREQUENCY		32768
-#define MAX_PERIODIC_RATE	6553
-#define MAX_USER_PERIODIC_RATE	64
-
-static void __iomem *rtc1_base;
-static void __iomem *rtc2_base;
-
-#define rtc1_read(offset)		readw(rtc1_base + (offset))
-#define rtc1_write(offset, value)	writew((value), rtc1_base + (offset))
-
-#define rtc2_read(offset)		readw(rtc2_base + (offset))
-#define rtc2_write(offset, value)	writew((value), rtc2_base + (offset))
-
-static unsigned long epoch = 1970;	/* Jan 1 1970 00:00:00 */
-
-static spinlock_t rtc_task_lock;
-static wait_queue_head_t rtc_wait;
-static unsigned long rtc_irq_data;
-static struct fasync_struct *rtc_async_queue;
-static rtc_task_t *rtc_callback;
-static char rtc_name[] = "RTC";
-static unsigned long periodic_frequency;
-static unsigned long periodic_count;
-
-typedef enum {
-	RTC_RELEASE,
-	RTC_OPEN,
-} rtc_status_t;
-
-static rtc_status_t rtc_status;
-
-typedef enum {
-	FUNCTION_RTC_IOCTL,
-	FUNCTION_RTC_CONTROL,
-} rtc_callfrom_t;
-
-struct resource rtc_resource[2] = {
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-};
-
-static inline unsigned long read_elapsed_second(void)
-{
-	unsigned long first_low, first_mid, first_high;
-	unsigned long second_low, second_mid, second_high;
-
-	do {
-		first_low = rtc1_read(ETIMELREG);
-		first_mid = rtc1_read(ETIMEMREG);
-		first_high = rtc1_read(ETIMEHREG);
-		second_low = rtc1_read(ETIMELREG);
-		second_mid = rtc1_read(ETIMEMREG);
-		second_high = rtc1_read(ETIMEHREG);
-	} while (first_low != second_low || first_mid != second_mid ||
-	         first_high != second_high);
-
-	return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
-}
-
-static inline void write_elapsed_second(unsigned long sec)
-{
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
-	rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
-	rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
-
-	spin_unlock_irq(&rtc_lock);
-}
-
-static void set_alarm(struct rtc_time *time)
-{
-	unsigned long alarm_sec;
-
-	alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
-	                   time->tm_hour, time->tm_min, time->tm_sec);
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
-	rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
-	rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
-
-	spin_unlock_irq(&rtc_lock);
-}
-
-static void read_alarm(struct rtc_time *time)
-{
-	unsigned long low, mid, high;
-
-	spin_lock_irq(&rtc_lock);
-
-	low = rtc1_read(ECMPLREG);
-	mid = rtc1_read(ECMPMREG);
-	high = rtc1_read(ECMPHREG);
-
-	spin_unlock_irq(&rtc_lock);
-
-	to_tm((high << 17) | (mid << 1) | (low >> 15), time);
-	time->tm_year -= 1900;
-}
-
-static void read_time(struct rtc_time *time)
-{
-	unsigned long epoch_sec, elapsed_sec;
-
-	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
-	elapsed_sec = read_elapsed_second();
-
-	to_tm(epoch_sec + elapsed_sec, time);
-	time->tm_year -= 1900;
-}
-
-static void set_time(struct rtc_time *time)
-{
-	unsigned long epoch_sec, current_sec;
-
-	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
-	current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
-	                     time->tm_hour, time->tm_min, time->tm_sec);
-
-	write_elapsed_second(current_sec - epoch_sec);
-}
-
-static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long irq_data;
-	int retval = 0;
-
-	if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
-		return -EINVAL;
-
-	add_wait_queue(&rtc_wait, &wait);
-
-	do {
-		__set_current_state(TASK_INTERRUPTIBLE);
-
-		spin_lock_irq(&rtc_lock);
-		irq_data = rtc_irq_data;
-		rtc_irq_data = 0;
-		spin_unlock_irq(&rtc_lock);
-
-		if (irq_data != 0)
-			break;
-
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-	} while (1);
-
-	if (retval == 0) {
-		if (count == sizeof(unsigned int)) {
-			retval = put_user(irq_data, (unsigned int __user *)buf);
-			if (retval == 0)
-				retval = sizeof(unsigned int);
-		} else {
-			retval = put_user(irq_data, (unsigned long __user *)buf);
-			if (retval == 0)
-				retval = sizeof(unsigned long);
-		}
-
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&rtc_wait, &wait);
-
-	return retval;
-}
-
-static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table)
-{
-	poll_wait(file, &rtc_wait, table);
-
-	if (rtc_irq_data != 0)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
-
-static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from)
-{
-	struct rtc_time time;
-	unsigned long count;
-
-	switch (cmd) {
-	case RTC_AIE_ON:
-		enable_irq(ELAPSEDTIME_IRQ);
-		break;
-	case RTC_AIE_OFF:
-		disable_irq(ELAPSEDTIME_IRQ);
-		break;
-	case RTC_PIE_ON:
-		enable_irq(RTCLONG1_IRQ);
-		break;
-	case RTC_PIE_OFF:
-		disable_irq(RTCLONG1_IRQ);
-		break;
-	case RTC_ALM_SET:
-		if (copy_from_user(&time, (struct rtc_time __user *)arg,
-		                   sizeof(struct rtc_time)))
-			return -EFAULT;
-
-		set_alarm(&time);
-		break;
-	case RTC_ALM_READ:
-		memset(&time, 0, sizeof(struct rtc_time));
-		read_alarm(&time);
-		break;
-	case RTC_RD_TIME:
-		memset(&time, 0, sizeof(struct rtc_time));
-		read_time(&time);
-		if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
-			return -EFAULT;
-		break;
-	case RTC_SET_TIME:
-		if (capable(CAP_SYS_TIME) == 0)
-			return -EACCES;
-
-		if (copy_from_user(&time, (struct rtc_time __user *)arg,
-		                   sizeof(struct rtc_time)))
-			return -EFAULT;
-
-		set_time(&time);
-		break;
-	case RTC_IRQP_READ:
-		return put_user(periodic_frequency, (unsigned long __user *)arg);
-		break;
-	case RTC_IRQP_SET:
-		if (arg > MAX_PERIODIC_RATE)
-			return -EINVAL;
-
-		if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE &&
-		    capable(CAP_SYS_RESOURCE) == 0)
-			return -EACCES;
-
-		periodic_frequency = arg;
-
-		count = RTC_FREQUENCY;
-		do_div(count, arg);
-
-		periodic_count = count;
-
-		spin_lock_irq(&rtc_lock);
-
-		rtc1_write(RTCL1LREG, count);
-		rtc1_write(RTCL1HREG, count >> 16);
-
-		spin_unlock_irq(&rtc_lock);
-		break;
-	case RTC_EPOCH_READ:
-		return put_user(epoch, (unsigned long __user *)arg);
-	case RTC_EPOCH_SET:
-		/* Doesn't support before 1900 */
-		if (arg < 1900)
-			return -EINVAL;
-
-		if (capable(CAP_SYS_TIME) == 0)
-			return -EACCES;
-
-		epoch = arg;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                     unsigned long arg)
-{
-	return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
-}
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&rtc_lock);
-
-	if (rtc_status == RTC_OPEN) {
-		spin_unlock_irq(&rtc_lock);
-		return -EBUSY;
-	}
-
-	rtc_status = RTC_OPEN;
-	rtc_irq_data = 0;
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
-	if (file->f_flags & FASYNC)
-		(void)fasync_helper(-1, file, 0, &rtc_async_queue);
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-
-	spin_unlock_irq(&rtc_lock);
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	return 0;
-}
-
-static int rtc_fasync(int fd, struct file *file, int on)
-{
-	return fasync_helper(fd, file, on, &rtc_async_queue);
-}
-
-static struct file_operations rtc_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= rtc_read,
-	.poll		= rtc_poll,
-	.ioctl		= rtc_ioctl,
-	.open		= rtc_open,
-	.release	= rtc_release,
-	.fasync		= rtc_fasync,
-};
-
-static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	spin_lock(&rtc_lock);
-	rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
-
-	rtc_irq_data += 0x100;
-	rtc_irq_data &= ~0xff;
-	rtc_irq_data |= RTC_AF;
-	spin_unlock(&rtc_lock);
-
-	spin_lock(&rtc_lock);
-	if (rtc_callback)
-		rtc_callback->func(rtc_callback->private_data);
-	spin_unlock(&rtc_lock);
-
-	wake_up_interruptible(&rtc_wait);
-
-	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long count = periodic_count;
-
-	spin_lock(&rtc_lock);
-	rtc2_write(RTCINTREG, RTCLONG1_INT);
-
-	rtc1_write(RTCL1LREG, count);
-	rtc1_write(RTCL1HREG, count >> 16);
-
-	rtc_irq_data += 0x100;
-	rtc_irq_data &= ~0xff;
-	rtc_irq_data |= RTC_PF;
-	spin_unlock(&rtc_lock);
-
-	spin_lock(&rtc_task_lock);
-	if (rtc_callback)
-		rtc_callback->func(rtc_callback->private_data);
-	spin_unlock(&rtc_task_lock);
-
-	wake_up_interruptible(&rtc_wait);
-
-	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
-
-	return IRQ_HANDLED;
-}
-
-int rtc_register(rtc_task_t *task)
-{
-	if (task == NULL || task->func == NULL)
-		return -EINVAL;
-
-	spin_lock_irq(&rtc_lock);
-	if (rtc_status == RTC_OPEN) {
-		spin_unlock_irq(&rtc_lock);
-		return -EBUSY;
-	}
-
-	spin_lock(&rtc_task_lock);
-	if (rtc_callback != NULL) {
-		spin_unlock(&rtc_task_lock);
-		spin_unlock_irq(&rtc_task_lock);
-		return -EBUSY;
-	}
-
-	rtc_callback = task;
-	spin_unlock(&rtc_task_lock);
-
-	rtc_status = RTC_OPEN;
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_register);
-
-int rtc_unregister(rtc_task_t *task)
-{
-	spin_lock_irq(&rtc_task_lock);
-	if (task == NULL || rtc_callback != task) {
-		spin_unlock_irq(&rtc_task_lock);
-		return -ENXIO;
-	}
-
-	spin_lock(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-
-	spin_unlock(&rtc_lock);
-
-	rtc_callback = NULL;
-
-	spin_unlock_irq(&rtc_task_lock);
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_unregister);
-
-int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
-{
-	int retval = 0;
-
-	spin_lock_irq(&rtc_task_lock);
-
-	if (rtc_callback != task)
-		retval = -ENXIO;
-	else
-		rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
-
-	spin_unlock_irq(&rtc_task_lock);
-
-	return retval;
-}
-
-EXPORT_SYMBOL_GPL(rtc_control);
-
-static struct miscdevice rtc_miscdevice = {
-	.minor	= RTC_MINOR,
-	.name	= rtc_name,
-	.fops	= &rtc_fops,
-};
-
-static int __devinit rtc_probe(struct platform_device *pdev)
-{
-	unsigned int irq;
-	int retval;
-
-	if (pdev->num_resources != 2)
-		return -EBUSY;
-
-	rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
-	if (rtc1_base == NULL)
-		return -EBUSY;
-
-	rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
-	if (rtc2_base == NULL) {
-		iounmap(rtc1_base);
-		rtc1_base = NULL;
-		return -EBUSY;
-	}
-
-	retval = misc_register(&rtc_miscdevice);
-	if (retval < 0) {
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return retval;
-	}
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-	rtc_irq_data = 0;
-
-	spin_unlock_irq(&rtc_lock);
-
-	init_waitqueue_head(&rtc_wait);
-
-	irq = ELAPSEDTIME_IRQ;
-	retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
-	                     "elapsed_time", NULL);
-	if (retval == 0) {
-		irq = RTCLONG1_IRQ;
-		retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
-		                     "rtclong1", NULL);
-	}
-
-	if (retval < 0) {
-		printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
-		if (irq == RTCLONG1_IRQ)
-			free_irq(ELAPSEDTIME_IRQ, NULL);
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return retval;
-	}
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	spin_lock_init(&rtc_task_lock);
-
-	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
-
-	return 0;
-}
-
-static int __devexit rtc_remove(struct platform_device *dev)
-{
-	int retval;
-
-	retval = misc_deregister(&rtc_miscdevice);
-	if (retval < 0)
-		return retval;
-
-	free_irq(ELAPSEDTIME_IRQ, NULL);
-	free_irq(RTCLONG1_IRQ, NULL);
-	if (rtc1_base != NULL)
-		iounmap(rtc1_base);
-	if (rtc2_base != NULL)
-		iounmap(rtc2_base);
-
-	return 0;
-}
-
-static struct platform_device *rtc_platform_device;
-
-static struct platform_driver rtc_device_driver = {
-	.probe		= rtc_probe,
-	.remove		= __devexit_p(rtc_remove),
-	.driver		= {
-		.name	= rtc_name,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init vr41xx_rtc_init(void)
-{
-	int retval;
-
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		rtc_resource[0].start = RTC1_TYPE1_START;
-		rtc_resource[0].end = RTC1_TYPE1_END;
-		rtc_resource[1].start = RTC2_TYPE1_START;
-		rtc_resource[1].end = RTC2_TYPE1_END;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		rtc_resource[0].start = RTC1_TYPE2_START;
-		rtc_resource[0].end = RTC1_TYPE2_END;
-		rtc_resource[1].start = RTC2_TYPE2_START;
-		rtc_resource[1].end = RTC2_TYPE2_END;
-		break;
-	default:
-		return -ENODEV;
-		break;
-	}
-
-	rtc_platform_device = platform_device_alloc("RTC", -1);
-	if (!rtc_platform_device)
-		return -ENOMEM;
-
-	retval = platform_device_add_resources(rtc_platform_device,
-				rtc_resource, ARRAY_SIZE(rtc_resource));
-
-	if (retval == 0)
-		retval = platform_device_add(rtc_platform_device);
-
-	if (retval < 0) {
-		platform_device_put(rtc_platform_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&rtc_device_driver);
-	if (retval < 0)
-		platform_device_unregister(rtc_platform_device);
-
-	return retval;
-}
-
-static void __exit vr41xx_rtc_exit(void)
-{
-	platform_driver_unregister(&rtc_device_driver);
-	platform_device_unregister(rtc_platform_device);
-}
-
-module_init(vr41xx_rtc_init);
-module_exit(vr41xx_rtc_exit);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 16e99db..d53f664 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -60,6 +60,13 @@
 
 # ARM Architecture
 
+config AT91_WATCHDOG
+	tristate "AT91RM9200 watchdog"
+	depends on WATCHDOG && ARCH_AT91RM9200
+	help
+	  Watchdog timer embedded into AT91RM9200 chips. This will reboot your
+	  system when the timeout is reached.
+
 config 21285_WATCHDOG
 	tristate "DC21285 watchdog"
 	depends on WATCHDOG && FOOTBRIDGE
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index d6f27fd..6ab77b6 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 
 # ARM Architecture
+obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
 obj-$(CONFIG_977_WATCHDOG) += wdt977.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c
new file mode 100644
index 0000000..ac83bc4
--- /dev/null
+++ b/drivers/char/watchdog/at91_wdt.c
@@ -0,0 +1,228 @@
+/*
+ * Watchdog driver for Atmel AT91RM9200 (Thunder)
+ *
+ *  Copyright (C) 2003 SAN People (Pty) Ltd
+ *
+ * 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/config.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+
+#define WDT_DEFAULT_TIME	5	/* 5 seconds */
+#define WDT_MAX_TIME		256	/* 256 seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+
+static unsigned long at91wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline at91_wdt_stop(void)
+{
+	at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline at91_wdt_start(void)
+{
+	at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
+	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/*
+ * Reload the watchdog timer.  (ie, pat the watchdog)
+ */
+static void inline at91_wdt_reload(void)
+{
+	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int at91_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &at91wdt_busy))
+		return -EBUSY;
+
+	at91_wdt_start();
+	return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ *  disabled.
+ */
+static int at91_wdt_close(struct inode *inode, struct file *file)
+{
+	if (!nowayout)
+		at91_wdt_stop();	/* Disable the watchdog when file is closed */
+
+	clear_bit(0, &at91wdt_busy);
+	return 0;
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int at91_wdt_settimeout(int new_time)
+{
+	/*
+	 * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+	 *
+	 * Since WDV is a 16-bit counter, the maximum period is
+	 * 65536 / 0.256 = 256 seconds.
+	 */
+	if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+		return -EINVAL;
+
+	/* Set new watchdog time. It will be used when at91_wdt_start() is called. */
+	wdt_time = new_time;
+	return 0;
+}
+
+static struct watchdog_info at91_wdt_info = {
+	.identity	= "at91 watchdog",
+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int at91_wdt_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int new_value;
+
+	switch(cmd) {
+		case WDIOC_KEEPALIVE:
+			at91_wdt_reload();	/* pat the watchdog */
+			return 0;
+
+		case WDIOC_GETSUPPORT:
+			return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0;
+
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_value, p))
+				return -EFAULT;
+				
+			if (at91_wdt_settimeout(new_value))
+				return -EINVAL;
+
+			/* Enable new time value */
+			at91_wdt_start();
+
+			/* Return current value */
+			return put_user(wdt_time, p);
+
+		case WDIOC_GETTIMEOUT:
+			return put_user(wdt_time, p);
+
+		case WDIOC_GETSTATUS:
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, p);
+
+		case WDIOC_SETOPTIONS:
+			if (get_user(new_value, p))
+				return -EFAULT;
+
+			if (new_value & WDIOS_DISABLECARD)
+				at91_wdt_stop();
+			if (new_value & WDIOS_ENABLECARD)
+				at91_wdt_start();
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+	at91_wdt_reload();		/* pat the watchdog */
+	return len;
+}
+
+/* ......................................................................... */
+
+static struct file_operations at91wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.ioctl		= at91_wdt_ioctl,
+	.open		= at91_wdt_open,
+	.release	= at91_wdt_close,
+	.write		= at91_wdt_write,
+};
+
+static struct miscdevice at91wdt_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &at91wdt_fops,
+};
+
+static int __init at91_wdt_init(void)
+{
+	int res;
+
+	/* Check that the heartbeat value is within range; if not reset to the default */
+	if (at91_wdt_settimeout(wdt_time)) {
+		at91_wdt_settimeout(WDT_DEFAULT_TIME);
+		printk(KERN_INFO "at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time);
+	}
+
+	res = misc_register(&at91wdt_miscdev);
+	if (res)
+		return res;
+
+	printk("AT91 Watchdog Timer enabled (%d seconds, nowayout=%d)\n", wdt_time, nowayout);
+	return 0;
+}
+
+static void __exit at91_wdt_exit(void)
+{
+	misc_deregister(&at91wdt_miscdev);
+}
+
+module_init(at91_wdt_init);
+module_exit(at91_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 8d6b249..6d44ca6 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -66,15 +66,13 @@
 #include <linux/fs.h>		/* For file operations */
 #include <linux/ioport.h>	/* For io-port access */
 #include <linux/spinlock.h>	/* For spin_lock/spin_unlock/... */
-#include <linux/sched.h>	/* TASK_INTERRUPTIBLE, set_current_state() and friends */
-#include <linux/slab.h>		/* For kmalloc */
 
 #include <asm/uaccess.h>	/* For copy_to_user/put_user/... */
 #include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.16"
-#define WATCHDOG_DATE "03 Jan 2006"
+#define WATCHDOG_VERSION "1.17"
+#define WATCHDOG_DATE "12 Feb 2006"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
 #define PFX WATCHDOG_NAME ": "
@@ -96,15 +94,19 @@
  * PCI-PC Watchdog card.
 */
 /* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
-#define WD_WDRST                0x01	/* Previously reset state */
-#define WD_T110                 0x02	/* Temperature overheat sense */
-#define WD_HRTBT                0x04	/* Heartbeat sense */
-#define WD_RLY2                 0x08	/* External relay triggered */
-#define WD_SRLY2                0x80	/* Software external relay triggered */
+#define WD_WDRST		0x01	/* Previously reset state */
+#define WD_T110			0x02	/* Temperature overheat sense */
+#define WD_HRTBT		0x04	/* Heartbeat sense */
+#define WD_RLY2			0x08	/* External relay triggered */
+#define WD_SRLY2		0x80	/* Software external relay triggered */
 /* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
-#define WD_REVC_WTRP            0x01	/* Watchdog Trip status */
-#define WD_REVC_HRBT            0x02	/* Watchdog Heartbeat */
-#define WD_REVC_TTRP            0x04	/* Temperature Trip status */
+#define WD_REVC_WTRP		0x01	/* Watchdog Trip status */
+#define WD_REVC_HRBT		0x02	/* Watchdog Heartbeat */
+#define WD_REVC_TTRP		0x04	/* Temperature Trip status */
+#define WD_REVC_RL2A		0x08	/* Relay 2 activated by on-board processor */
+#define WD_REVC_RL1A		0x10	/* Relay 1 active */
+#define WD_REVC_R2DS		0x40	/* Relay 2 disable */
+#define WD_REVC_RLY2		0x80	/* Relay 2 activated? */
 /* Port 2 : Control Status #2 */
 #define WD_WDIS			0x10	/* Watchdog Disabled */
 #define WD_ENTP			0x20	/* Watchdog Enable Temperature Trip */
@@ -122,9 +124,14 @@
 #define CMD_ISA_VERSION_HUNDRETH	0x03
 #define CMD_ISA_VERSION_MINOR		0x04
 #define CMD_ISA_SWITCH_SETTINGS		0x05
+#define CMD_ISA_RESET_PC		0x06
+#define CMD_ISA_ARM_0			0x07
+#define CMD_ISA_ARM_30			0x08
+#define CMD_ISA_ARM_60			0x09
 #define CMD_ISA_DELAY_TIME_2SECS	0x0A
 #define CMD_ISA_DELAY_TIME_4SECS	0x0B
 #define CMD_ISA_DELAY_TIME_8SECS	0x0C
+#define CMD_ISA_RESET_RELAYS		0x0D
 
 /*
  * We are using an kernel timer to do the pinging of the watchdog
@@ -142,6 +149,7 @@
 static char expect_close;
 static int temp_panic;
 static struct {				/* this is private data for each ISA-PC watchdog card */
+	char fw_ver_str[6];		/* The cards firmware version */
 	int revision;			/* The card's revision */
 	int supports_temp;		/* Wether or not the card has a temperature device */
 	int command_mode;		/* Wether or not the card is in command mode */
@@ -153,6 +161,13 @@
 } pcwd_private;
 
 /* module parameters */
+#define QUIET	0	/* Default */
+#define VERBOSE	1	/* Verbose */
+#define DEBUG	2	/* print fancy stuff too */
+static int debug = QUIET;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)");
+
 #define WATCHDOG_HEARTBEAT 60		/* 60 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;
 module_param(heartbeat, int, 0);
@@ -172,6 +187,10 @@
 	int control_status;
 	int port0, last_port0;	/* Double read for stabilising */
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "sending following data cmd=0x%02x\n",
+			cmd);
+
 	/* The WCMD bit must be 1 and the command is only 4 bits in size */
 	control_status = (cmd & 0x0F) | WD_WCMD;
 	outb_p(control_status, pcwd_private.io_addr + 2);
@@ -188,6 +207,10 @@
 		udelay (250);
 	}
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: port0=0x%02x last_port0=0x%02x\n",
+			cmd, port0, last_port0);
+
 	return port0;
 }
 
@@ -214,6 +237,10 @@
 	spin_unlock(&pcwd_private.io_lock);
 	pcwd_private.command_mode = found;
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "command_mode=%d\n",
+				pcwd_private.command_mode);
+
 	return(found);
 }
 
@@ -226,6 +253,10 @@
 	spin_unlock(&pcwd_private.io_lock);
 
 	pcwd_private.command_mode = 0;
+
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "command_mode=%d\n",
+				pcwd_private.command_mode);
 }
 
 static inline void pcwd_check_temperature_support(void)
@@ -234,27 +265,22 @@
 		pcwd_private.supports_temp = 1;
 }
 
-static inline char *get_firmware(void)
+static inline void pcwd_get_firmware(void)
 {
 	int one, ten, hund, minor;
-	char *ret;
 
-	ret = kmalloc(6, GFP_KERNEL);
-	if(ret == NULL)
-		return NULL;
+	strcpy(pcwd_private.fw_ver_str, "ERROR");
 
 	if (set_command_mode()) {
 		one = send_isa_command(CMD_ISA_VERSION_INTEGER);
 		ten = send_isa_command(CMD_ISA_VERSION_TENTH);
 		hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH);
 		minor = send_isa_command(CMD_ISA_VERSION_MINOR);
-		sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+		sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor);
 	}
-	else
-		sprintf(ret, "ERROR");
-
 	unset_command_mode();
-	return(ret);
+
+	return;
 }
 
 static inline int pcwd_get_option_switches(void)
@@ -272,17 +298,15 @@
 
 static void pcwd_show_card_info(void)
 {
-	char *firmware;
 	int option_switches;
 
 	/* Get some extra info from the hardware (in command/debug/diag mode) */
 	if (pcwd_private.revision == PCWD_REVISION_A)
 		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr);
 	else if (pcwd_private.revision == PCWD_REVISION_C) {
-		firmware = get_firmware();
+		pcwd_get_firmware();
 		printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n",
-			pcwd_private.io_addr, firmware);
-		kfree(firmware);
+			pcwd_private.io_addr, pcwd_private.fw_ver_str);
 		option_switches = pcwd_get_option_switches();
 		printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
 			option_switches,
@@ -362,6 +386,10 @@
 			return -EIO;
 		}
 	}
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "Watchdog started\n");
+
 	return 0;
 }
 
@@ -386,6 +414,10 @@
 			return -EIO;
 		}
 	}
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "Watchdog stopped\n");
+
 	return 0;
 }
 
@@ -393,6 +425,10 @@
 {
 	/* user land ping */
 	pcwd_private.next_heartbeat = jiffies + (heartbeat * HZ);
+
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n");
+
 	return 0;
 }
 
@@ -402,12 +438,17 @@
 		return -EINVAL;
 
 	heartbeat = t;
+
+	if (debug >= VERBOSE)
+		printk(KERN_DEBUG PFX "New heartbeat: %d\n",
+		       heartbeat);
+
 	return 0;
 }
 
 static int pcwd_get_status(int *status)
 {
-	int card_status;
+	int control_status;
 
 	*status=0;
 	spin_lock(&pcwd_private.io_lock);
@@ -415,37 +456,39 @@
 		/* Rev A cards return status information from
 		 * the base register, which is used for the
 		 * temperature in other cards. */
-		card_status = inb(pcwd_private.io_addr);
+		control_status = inb(pcwd_private.io_addr);
 	else {
 		/* Rev C cards return card status in the base
 		 * address + 1 register. And use different bits
 		 * to indicate a card initiated reset, and an
 		 * over-temperature condition. And the reboot
 		 * status can be reset. */
-		card_status = inb(pcwd_private.io_addr + 1);
+		control_status = inb(pcwd_private.io_addr + 1);
 	}
 	spin_unlock(&pcwd_private.io_lock);
 
 	if (pcwd_private.revision == PCWD_REVISION_A) {
-		if (card_status & WD_WDRST)
+		if (control_status & WD_WDRST)
 			*status |= WDIOF_CARDRESET;
 
-		if (card_status & WD_T110) {
+		if (control_status & WD_T110) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
 				printk (KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
+				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
 		}
 	} else {
-		if (card_status & WD_REVC_WTRP)
+		if (control_status & WD_REVC_WTRP)
 			*status |= WDIOF_CARDRESET;
 
-		if (card_status & WD_REVC_TTRP) {
+		if (control_status & WD_REVC_TTRP) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
 				printk (KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
+				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
 		}
 	}
@@ -455,9 +498,25 @@
 
 static int pcwd_clear_status(void)
 {
+	int control_status;
+
 	if (pcwd_private.revision == PCWD_REVISION_C) {
 		spin_lock(&pcwd_private.io_lock);
-		outb_p(0x00, pcwd_private.io_addr + 1); /* clear reset status */
+
+		if (debug >= VERBOSE)
+			printk(KERN_INFO PFX "clearing watchdog trip status\n");
+
+		control_status = inb_p(pcwd_private.io_addr + 1);
+
+		if (debug >= DEBUG) {
+			printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status);
+			printk(KERN_DEBUG PFX "sending: 0x%02x\n",
+				(control_status & WD_REVC_R2DS));
+		}
+
+		/* clear reset status & Keep Relay 2 disable state as it is */
+		outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1);
+
 		spin_unlock(&pcwd_private.io_lock);
 	}
 	return 0;
@@ -481,6 +540,11 @@
 	*temperature = ((inb(pcwd_private.io_addr)) * 9 / 5) + 32;
 	spin_unlock(&pcwd_private.io_lock);
 
+	if (debug >= DEBUG) {
+		printk(KERN_DEBUG PFX "temperature is: %d F\n",
+			*temperature);
+	}
+
 	return 0;
 }
 
@@ -599,6 +663,8 @@
 static int pcwd_open(struct inode *inode, struct file *file)
 {
 	if (!atomic_dec_and_test(&open_allowed) ) {
+		if (debug >= VERBOSE)
+			printk(KERN_ERR PFX "Attempt to open already opened device.\n");
 		atomic_inc( &open_allowed );
 		return -EBUSY;
 	}
@@ -922,7 +988,8 @@
 {
 	if (pcwd_private.io_addr)
 		pcwatchdog_exit();
-	return;
+
+	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(pcwd_init_module);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 2700c5c..3fdfda9 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -705,7 +705,8 @@
 err_out_unregister_reboot:
 	unregister_reboot_notifier(&usb_pcwd_notifier);
 error:
-	usb_pcwd_delete (usb_pcwd);
+	if (usb_pcwd)
+		usb_pcwd_delete(usb_pcwd);
 	usb_pcwd_device = NULL;
 	return retval;
 }
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 60c9be9..2cc71b6 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -99,7 +99,7 @@
 	  Enable this cpufreq governor when you either want to set the
 	  CPU frequency manually or when an userspace program shall
 	  be able to set the CPU dynamically, like on LART 
-	  <http://www.lart.tudelft.nl/>
+	  <http://www.lartmaker.nl/>.
 
 	  For details, take a look at <file:Documentation/cpu-freq/>.
 
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9b6ae7d..29b2fa5 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -319,7 +319,6 @@
 	}
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
 
 
 /* drivers/base/cpu.c */
@@ -346,6 +345,8 @@
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
+static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+
 /**
  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
  */
@@ -364,7 +365,10 @@
 	if (ret != 1)							\
 		return -EINVAL;						\
 									\
-	ret = cpufreq_set_policy(&new_policy);				\
+	mutex_lock(&policy->lock);					\
+	ret = __cpufreq_set_policy(policy, &new_policy);		\
+	policy->user_policy.object = policy->object;			\
+	mutex_unlock(&policy->lock);					\
 									\
 	return ret ? ret : count;					\
 }
@@ -420,7 +424,15 @@
 	if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
 		return -EINVAL;
 
-	ret = cpufreq_set_policy(&new_policy);
+	/* Do not use cpufreq_set_policy here or the user_policy.max
+	   will be wrongly overridden */
+	mutex_lock(&policy->lock);
+	ret = __cpufreq_set_policy(policy, &new_policy);
+
+	policy->user_policy.policy = policy->policy;
+	policy->user_policy.governor = policy->governor;
+	mutex_unlock(&policy->lock);
+
 	return ret ? ret : count;
 }
 
@@ -685,7 +697,7 @@
 		if (!cpu_online(j))
 			continue;
 
-		dprintk("CPU already managed, adding link\n");
+		dprintk("CPU %u already managed, adding link\n", j);
 		cpufreq_cpu_get(cpu);
 		cpu_sys_dev = get_cpu_sysdev(j);
 		sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
@@ -695,9 +707,8 @@
 	policy->governor = NULL; /* to assure that the starting sequence is
 				  * run in cpufreq_set_policy */
 	mutex_unlock(&policy->lock);
-	
+
 	/* set default policy */
-	
 	ret = cpufreq_set_policy(&new_policy);
 	if (ret) {
 		dprintk("setting policy failed\n");
@@ -707,7 +718,7 @@
 	module_put(cpufreq_driver->owner);
 	dprintk("initialization complete\n");
 	cpufreq_debug_enable_ratelimit();
-	
+
 	return 0;
 
 
@@ -1486,7 +1497,7 @@
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
-static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
+static int cpufreq_cpu_callback(struct notifier_block *nfb,
 					unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 037f6bf..e07a354 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -176,8 +176,7 @@
 	ret = sscanf (buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > 100 || input < 0 ||
-			input <= dbs_tuners_ins.down_threshold) {
+	if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
@@ -196,8 +195,7 @@
 	ret = sscanf (buf, "%u", &input);
 
 	mutex_lock(&dbs_mutex);
-	if (ret != 1 || input > 100 || input < 0 ||
-			input >= dbs_tuners_ins.up_threshold) {
+	if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) {
 		mutex_unlock(&dbs_mutex);
 		return -EINVAL;
 	}
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 8542997..98e395f 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,7 +1,8 @@
 #
 # Makefile for the linux kernel.
 #
-obj-$(CONFIG_EDD)             	+= edd.o
+obj-$(CONFIG_DMI)		+= dmi_scan.o
+obj-$(CONFIG_EDD)		+= edd.o
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_EFI_PCDP)		+= pcdp.o
 obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
diff --git a/arch/i386/kernel/dmi_scan.c b/drivers/firmware/dmi_scan.c
similarity index 97%
rename from arch/i386/kernel/dmi_scan.c
rename to drivers/firmware/dmi_scan.c
index 5efceeb..948bd7e 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -27,7 +27,7 @@
 			else
 				printk(KERN_ERR "dmi_string: out of memory.\n");
 		}
- 	}
+	}
 
 	return str;
 }
@@ -41,7 +41,7 @@
 {
 	u8 *buf, *data;
 	int i = 0;
-		
+
 	buf = dmi_ioremap(base, len);
 	if (buf == NULL)
 		return -1;
@@ -49,9 +49,9 @@
 	data = buf;
 
 	/*
- 	 *	Stop when we see all the items the table claimed to have
- 	 *	OR we run off the end of the table (also happens)
- 	 */
+	 *	Stop when we see all the items the table claimed to have
+	 *	OR we run off the end of the table (also happens)
+	 */
 	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
 		struct dmi_header *dm = (struct dmi_header *)data;
 		/*
@@ -75,7 +75,7 @@
 {
 	u8 sum = 0;
 	int a;
-	
+
 	for (a = 0; a < 15; a++)
 		sum += buf[a];
 
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 7636c1a..1659f6c 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -33,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/dmi.h>
-#include <linux/mutex.h>
 #include <asm/io.h>
 
 #define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
@@ -71,10 +70,10 @@
 static int rest_x;
 static int rest_y;
 
-static DEFINE_MUTEX(hdaps_mutex);
+static DECLARE_MUTEX(hdaps_sem);
 
 /*
- * __get_latch - Get the value from a given port.  Callers must hold hdaps_mutex.
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_sem.
  */
 static inline u8 __get_latch(u16 port)
 {
@@ -83,7 +82,7 @@
 
 /*
  * __check_latch - Check a port latch for a given value.  Returns zero if the
- * port contains the given value.  Callers must hold hdaps_mutex.
+ * port contains the given value.  Callers must hold hdaps_sem.
  */
 static inline int __check_latch(u16 port, u8 val)
 {
@@ -94,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_mutex.
+ * returning zero if the value is obtained.  Callers must hold hdaps_sem.
  */
 static int __wait_latch(u16 port, u8 val)
 {
@@ -111,7 +110,7 @@
 
 /*
  * __device_refresh - request a refresh from the accelerometer.  Does not wait
- * for refresh to complete.  Callers must hold hdaps_mutex.
+ * for refresh to complete.  Callers must hold hdaps_sem.
  */
 static void __device_refresh(void)
 {
@@ -125,7 +124,7 @@
 /*
  * __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_mutex.
+ * successful and nonzero on error.  Callers must hold hdaps_sem.
  */
 static int __device_refresh_sync(void)
 {
@@ -135,7 +134,7 @@
 
 /*
  * __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh.  Callers must hold hdaps_mutex.
+ * data, and then initiate an async refresh.  Callers must hold hdaps_sem.
  */
 static inline void __device_complete(void)
 {
@@ -153,7 +152,7 @@
 {
 	int ret;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 
 	/* do a sync refresh -- we need to be sure that we read fresh data */
 	ret = __device_refresh_sync();
@@ -164,7 +163,7 @@
 	__device_complete();
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 	return ret;
 }
 
@@ -199,9 +198,9 @@
 {
 	int ret;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 	ret = __hdaps_read_pair(port1, port2, val1, val2);
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 
 	return ret;
 }
@@ -214,7 +213,7 @@
 {
 	int total, ret = -ENXIO;
 
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 
 	outb(0x13, 0x1610);
 	outb(0x01, 0x161f);
@@ -280,7 +279,7 @@
 	}
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 	return ret;
 }
 
@@ -314,7 +313,7 @@
 };
 
 /*
- * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_mutex.
+ * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_sem.
  */
 static void hdaps_calibrate(void)
 {
@@ -326,7 +325,7 @@
 	int x, y;
 
 	/* Cannot sleep.  Try nonblockingly.  If we fail, try again later. */
-	if (!mutex_trylock(&hdaps_mutex)) {
+	if (down_trylock(&hdaps_sem)) {
 		mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
 		return;
 	}
@@ -341,7 +340,7 @@
 	mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
 
 out:
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 }
 
 
@@ -421,9 +420,9 @@
 				     struct device_attribute *attr,
 				     const char *buf, size_t count)
 {
-	mutex_lock(&hdaps_mutex);
+	down(&hdaps_sem);
 	hdaps_calibrate();
-	mutex_unlock(&hdaps_mutex);
+	up(&hdaps_sem);
 
 	return count;
 }
@@ -510,12 +509,22 @@
 	}						\
 }
 
+#define HDAPS_DMI_MATCH_LENOVO(model)   {               \
+        .ident = "Lenovo " model,                       \
+        .callback = hdaps_dmi_match_invert,             \
+        .matches = {                                    \
+                DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),  \
+                DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
+        }                                               \
+}
+
 static int __init hdaps_init(void)
 {
 	int ret;
 
 	/* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
 	struct dmi_system_id hdaps_whitelist[] = {
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
 		HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
@@ -525,15 +534,17 @@
 		HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
+		HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
+		HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
 		{ .ident = NULL }
 	};
 
 	if (!dmi_check_system(hdaps_whitelist)) {
 		printk(KERN_WARNING "hdaps: supported laptop not found!\n");
-		ret = -ENXIO;
+		ret = -ENODEV;
 		goto out;
 	}
 
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 6865c64..958602e 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1161,7 +1161,7 @@
 	   bank. */
 	if (kind < 0) {
 		if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
-			dev_warn(dev, "Detection failed at step 3\n");
+			dev_dbg(dev, "Detection failed at step 1\n");
 			goto ERROR1;
 		}
 		val1 = w83792d_read_value(client, W83792D_REG_BANK);
@@ -1170,6 +1170,7 @@
 		if (!(val1 & 0x07)) {  /* is Bank0 */
 			if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
 			     ((val1 & 0x80) && (val2 != 0x5c))) {
+				dev_dbg(dev, "Detection failed at step 2\n");
 				goto ERROR1;
 			}
 		}
@@ -1177,7 +1178,7 @@
 		   should match */
 		if (w83792d_read_value(client,
 					W83792D_REG_I2C_ADDR) != address) {
-			dev_warn(dev, "Detection failed at step 5\n");
+			dev_dbg(dev, "Detection failed at step 3\n");
 			goto ERROR1;
 		}
 	}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 089c6f5..d6d4494 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -286,7 +286,10 @@
 	  This driver is a replacement for (and was inspired by) an older
 	  driver named i2c-philips-par.  The new driver supports more devices,
 	  and makes it easier to add support for new devices.
-	  
+
+	  An adapter type parameter is now mandatory.  Please read the file
+	  Documentation/i2c/busses/i2c-parport for details.
+
 	  Another driver exists, named i2c-parport-light, which doesn't depend
 	  on the parport driver.  This is meant for embedded systems. Don't say
 	  Y here if you intend to say Y or M there.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8e0f315..dfca749 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -478,6 +478,11 @@
 		ret = i801_transaction();
 	}
 
+	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
+	   time, so we forcibly disable it after every transaction. */
+	if (hwpec)
+		outb_p(0, SMBAUXCTL);
+
 	if(block)
 		return ret;
 	if(ret)
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index c63025a..e09ebbb 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,9 +121,14 @@
 
 static int __init i2c_parport_init(void)
 {
-	if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+	if (type < 0) {
+		printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+		return -ENODEV;
+	}
+
+	if (type >= ARRAY_SIZE(adapter_parm)) {
 		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
-		type = 0;
+		return -ENODEV;
 	}
 
 	if (base == 0) {
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 7e2e8cd..934bd55 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,9 +241,14 @@
 
 static int __init i2c_parport_init(void)
 {
-	if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+	if (type < 0) {
+		printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+		return -ENODEV;
+	}
+
+	if (type >= ARRAY_SIZE(adapter_parm)) {
 		printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
-		type = 0;
+		return -ENODEV;
 	}
 
 	return parport_register_driver(&i2c_parport_driver);
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index d702e5e..9ddd816 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -90,7 +90,7 @@
 	},
 };
 
-static int type;
+static int type = -1;
 module_param(type, int, 0);
 MODULE_PARM_DESC(type,
 	"Type of adapter:\n"
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3024907..1a73c05 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -43,13 +43,6 @@
 #include <linux/init.h>
 #include <asm/io.h>
 
-/*
-	HISTORY:
-	2003-05-11	1.0.0 	Updated from lm_sensors project for kernel 2.5
-				(was i2c-sis645.c from lm_sensors 2.7.0)
-*/
-#define SIS96x_VERSION "1.0.0"
-
 /* base address register in PCI config space */
 #define SIS96x_BAR 0x04
 
@@ -337,7 +330,6 @@
 
 static int __init i2c_sis96x_init(void)
 {
-	printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION);
 	return pci_register_driver(&sis96x_driver);
 }
 
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 03d09ed..4630f19 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -27,6 +27,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #define DS1374_REG_TOD0		0x00
 #define DS1374_REG_TOD1		0x01
@@ -139,7 +140,7 @@
 	return t1;
 }
 
-static void ds1374_set_tlet(ulong arg)
+static void ds1374_set_work(void *arg)
 {
 	ulong t1, t2;
 	int limit = 10;		/* arbitrary retry limit */
@@ -168,17 +169,18 @@
 
 static ulong new_time;
 
-static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
-				(ulong) & new_time);
+static struct workqueue_struct *ds1374_workqueue;
+
+static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
 
 int ds1374_set_rtc_time(ulong nowtime)
 {
 	new_time = nowtime;
 
 	if (in_interrupt())
-		tasklet_schedule(&ds1374_tasklet);
+		queue_work(ds1374_workqueue, &ds1374_work);
 	else
-		ds1374_set_tlet((ulong) & new_time);
+		ds1374_set_work(&new_time);
 
 	return 0;
 }
@@ -204,6 +206,8 @@
 	client->adapter = adap;
 	client->driver = &ds1374_driver;
 
+	ds1374_workqueue = create_singlethread_workqueue("ds1374");
+
 	if ((rc = i2c_attach_client(client)) != 0) {
 		kfree(client);
 		return rc;
@@ -227,7 +231,7 @@
 
 	if ((rc = i2c_detach_client(client)) == 0) {
 		kfree(i2c_get_clientdata(client));
-		tasklet_kill(&ds1374_tasklet);
+		destroy_workqueue(ds1374_workqueue);
 	}
 	return rc;
 }
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index b5aabe7..99ab4ec 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -25,6 +25,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #include <asm/time.h>
 #include <asm/rtc.h>
@@ -111,7 +112,7 @@
 }
 
 static void
-m41t00_set_tlet(ulong arg)
+m41t00_set(void *arg)
 {
 	struct rtc_time	tm;
 	ulong	nowtime = *(ulong *)arg;
@@ -130,13 +131,13 @@
 	if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
 		|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
 			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
 			< 0))
 
 		dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
@@ -145,9 +146,9 @@
 	return;
 }
 
-static ulong	new_time;
-
-DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+static ulong new_time;
+static struct workqueue_struct *m41t00_wq;
+static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
 
 int
 m41t00_set_rtc_time(ulong nowtime)
@@ -155,9 +156,9 @@
 	new_time = nowtime;
 
 	if (in_interrupt())
-		tasklet_schedule(&m41t00_tasklet);
+		queue_work(m41t00_wq, &m41t00_work);
 	else
-		m41t00_set_tlet((ulong)&new_time);
+		m41t00_set(&new_time);
 
 	return 0;
 }
@@ -189,6 +190,7 @@
 		return rc;
 	}
 
+	m41t00_wq = create_singlethread_workqueue("m41t00");
 	save_client = client;
 	return 0;
 }
@@ -206,7 +208,7 @@
 
 	if ((rc = i2c_detach_client(client)) == 0) {
 		kfree(client);
-		tasklet_kill(&m41t00_tasklet);
+		destroy_workqueue(m41t00_wq);
 	}
 	return rc;
 }
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 6213bd3..4961f1e 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -81,14 +81,14 @@
 };
 
 typedef struct ide_info_t {
-    dev_link_t	link;
+	struct pcmcia_device	*p_dev;
     int		ndev;
     dev_node_t	node;
     int		hd;
 } ide_info_t;
 
-static void ide_release(dev_link_t *);
-static void ide_config(dev_link_t *);
+static void ide_release(struct pcmcia_device *);
+static int ide_config(struct pcmcia_device *);
 
 static void ide_detach(struct pcmcia_device *p_dev);
 
@@ -103,10 +103,9 @@
 
 ======================================================================*/
 
-static int ide_attach(struct pcmcia_device *p_dev)
+static int ide_probe(struct pcmcia_device *link)
 {
     ide_info_t *info;
-    dev_link_t *link;
 
     DEBUG(0, "ide_attach()\n");
 
@@ -114,7 +113,9 @@
     info = kzalloc(sizeof(*info), GFP_KERNEL);
     if (!info)
 	return -ENOMEM;
-    link = &info->link; link->priv = info;
+
+    info->p_dev = link;
+    link->priv = info;
 
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -122,16 +123,9 @@
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    ide_config(link);
-
-    return 0;
+    return ide_config(link);
 } /* ide_attach */
 
 /*======================================================================
@@ -143,14 +137,11 @@
 
 ======================================================================*/
 
-static void ide_detach(struct pcmcia_device *p_dev)
+static void ide_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
     DEBUG(0, "ide_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG)
-	ide_release(link);
+    ide_release(link);
 
     kfree(link->priv);
 } /* ide_detach */
@@ -177,9 +168,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ide_config(dev_link_t *link)
+static int ide_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     ide_info_t *info = link->priv;
     tuple_t tuple;
     struct {
@@ -203,34 +193,30 @@
     tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
     link->conf.ConfigBase = stk->parse.config.base;
     link->conf.Present = stk->parse.config.rmask[0];
 
     tuple.DesiredTuple = CISTPL_MANFID;
-    if (!pcmcia_get_first_tuple(handle, &tuple) &&
-	!pcmcia_get_tuple_data(handle, &tuple) &&
-	!pcmcia_parse_tuple(handle, &tuple, &stk->parse))
+    if (!pcmcia_get_first_tuple(link, &tuple) &&
+	!pcmcia_get_tuple_data(link, &tuple) &&
+	!pcmcia_parse_tuple(link, &tuple, &stk->parse))
 	is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
 		  ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
 		   (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /* Not sure if this is right... look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
-    link->conf.Vcc = stk->conf.Vcc;
+    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
 
     pass = io_base = ctl_base = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-    	if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
-	if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
+    	if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
+	if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
 
 	/* Check for matching Vcc, unless we're desperate */
 	if (!pass) {
@@ -244,10 +230,10 @@
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-	    link->conf.Vpp1 = link->conf.Vpp2 =
+	    link->conf.Vpp =
 		cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-	    link->conf.Vpp1 = link->conf.Vpp2 =
+	    link->conf.Vpp =
 		stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
@@ -261,14 +247,14 @@
 		link->io.NumPorts1 = 8;
 		link->io.BasePort2 = io->win[1].base;
 		link->io.NumPorts2 = (is_kme) ? 2 : 1;
-		if (pcmcia_request_io(link->handle, &link->io) != 0)
+		if (pcmcia_request_io(link, &link->io) != 0)
 			goto next_entry;
 		io_base = link->io.BasePort1;
 		ctl_base = link->io.BasePort2;
 	    } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
 		link->io.NumPorts1 = io->win[0].len;
 		link->io.NumPorts2 = 0;
-		if (pcmcia_request_io(link->handle, &link->io) != 0)
+		if (pcmcia_request_io(link, &link->io) != 0)
 			goto next_entry;
 		io_base = link->io.BasePort1;
 		ctl_base = link->io.BasePort1 + 0x0e;
@@ -281,16 +267,16 @@
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 	    memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
 	if (pass) {
-	    CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
-	} else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
-	    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	    CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+	} else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
+	    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	    memset(&stk->dflt, 0, sizeof(stk->dflt));
 	    pass++;
 	}
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /* disable drive interrupts during IDE probe */
     outb(0x02, ctl_base);
@@ -301,12 +287,12 @@
 
     /* retry registration in case device is still spinning up */
     for (hd = -1, i = 0; i < 10; i++) {
-	hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle);
+	hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
 	if (hd >= 0) break;
 	if (link->io.NumPorts1 == 0x20) {
 	    outb(0x02, ctl_base + 0x10);
 	    hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
-				link->irq.AssignedIRQ, handle);
+				link->irq.AssignedIRQ, link);
 	    if (hd >= 0) {
 		io_base += 0x10;
 		ctl_base += 0x10;
@@ -328,25 +314,23 @@
     info->node.major = ide_major[hd];
     info->node.minor = 0;
     info->hd = hd;
-    link->dev = &info->node;
-    printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
-	   info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
-	   link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
+    link->dev_node = &info->node;
+    printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
+	   info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
 
-    link->state &= ~DEV_CONFIG_PENDING;
     kfree(stk);
-    return;
+    return 0;
 
 err_mem:
     printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
     goto failed;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     kfree(stk);
     ide_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
+    return -ENODEV;
 } /* ide_config */
 
 /*======================================================================
@@ -357,7 +341,7 @@
     
 ======================================================================*/
 
-void ide_release(dev_link_t *link)
+void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
     
@@ -369,37 +353,10 @@
 	ide_unregister(info->hd);
     }
     info->ndev = 0;
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
 
+    pcmcia_disable_device(link);
 } /* ide_release */
 
-static int ide_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int ide_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
 
 /*======================================================================
 
@@ -459,11 +416,9 @@
 	.drv		= {
 		.name	= "ide-cs",
 	},
-	.probe		= ide_attach,
+	.probe		= ide_probe,
 	.remove		= ide_detach,
 	.id_table       = ide_ids,
-	.suspend	= ide_suspend,
-	.resume		= ide_resume,
 };
 
 static int __init init_ide_cs(void)
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index cf84350..8b24b4f 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -731,6 +731,8 @@
 	
 	if(m5229_revision <= 0x20)
 		tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+	else if (m5229_revision == 0xc7)
+		tmpbyte |= 0x03;
 	else
 		tmpbyte |= 0x01;
 
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index df9ee9a..900efd1 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -348,6 +348,7 @@
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 6f8f864..7ce5bf7 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -798,7 +798,6 @@
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
-		.flags		= IDEPCI_FLAG_FORCE_PDC,
 	},{	/* 2 */
 		.name		= "PDC20263",
 		.init_setup	= init_setup_pdc202ata4,
@@ -819,7 +818,6 @@
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.extra		= 48,
-		.flags		= IDEPCI_FLAG_FORCE_PDC,
 	},{	/* 4 */
 		.name		= "PDC20267",
 		.init_setup	= init_setup_pdc202xx,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 7ebf992..462ed30 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -580,7 +580,6 @@
 	int port;
 	int at_least_one_hwif_enabled = 0;
 	ide_hwif_t *hwif, *mate = NULL;
-	static int secondpdc = 0;
 	u8 tmp;
 
 	index->all = 0xf0f0;
@@ -592,21 +591,9 @@
 	for (port = 0; port <= 1; ++port) {
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
 	
-		/* 
-		 * If this is a Promise FakeRaid controller,
-		 * the 2nd controller will be marked as 
-		 * disabled while it is actually there and enabled
-		 * by the bios for raid purposes. 
-		 * Skip the normal "is it enabled" test for those.
-		 */
-		if ((d->flags & IDEPCI_FLAG_FORCE_PDC) &&
-		    (secondpdc++==1) && (port==1))
-			goto controller_ok;
-			
 		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
 		    (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
-controller_ok:
 
 		if (d->channels	<= port)
 			break;
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 2c765ca..f420660 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -496,22 +496,17 @@
 /*
  * This function finds the sbp2_command for a given outstanding SCpnt.
  * Only looks at the inuse list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
+static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
+		struct scsi_id_instance_data *scsi_id, void *SCpnt)
 {
 	struct sbp2_command_info *command;
-	unsigned long flags;
 
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
-	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
-		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
-			if (command->Current_SCpnt == SCpnt) {
-				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
+	if (!list_empty(&scsi_id->sbp2_command_orb_inuse))
+		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list)
+			if (command->Current_SCpnt == SCpnt)
 				return command;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return NULL;
 }
 
@@ -580,17 +575,15 @@
 
 /*
  * This function moves a command to the completed orb list.
+ * Must be called with scsi_id->sbp2_command_orb_lock held.
  */
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
-					    struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(
+		struct scsi_id_instance_data *scsi_id,
+		struct sbp2_command_info *command)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	list_del(&command->list);
 	sbp2util_free_command_dma(command);
 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
 /*
@@ -2148,7 +2141,9 @@
 		 * Matched status with command, now grab scsi command pointers and check status
 		 */
 		SCpnt = command->Current_SCpnt;
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		sbp2util_mark_command_completed(scsi_id, command);
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		if (SCpnt) {
 
@@ -2484,6 +2479,7 @@
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct sbp2_command_info *command;
+	unsigned long flags;
 
 	SBP2_ERR("aborting sbp2 command");
 	scsi_print_command(SCpnt);
@@ -2494,6 +2490,7 @@
 		 * Right now, just return any matching command structures
 		 * to the free pool.
 		 */
+		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 		if (command) {
 			SBP2_DEBUG("Found command to abort");
@@ -2511,6 +2508,7 @@
 				command->Current_done(command->Current_SCpnt);
 			}
 		}
+		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 		/*
 		 * Initiate a fetch agent reset.
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index bdf0891..afc612b 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -30,6 +30,7 @@
 	  <http://www.openib.org>.
 
 source "drivers/infiniband/hw/mthca/Kconfig"
+source "drivers/infiniband/hw/ipath/Kconfig"
 
 source "drivers/infiniband/ulp/ipoib/Kconfig"
 
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index a43fb34..eea2732 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_INFINIBAND)		+= core/
 obj-$(CONFIG_INFINIBAND_MTHCA)		+= hw/mthca/
+obj-$(CONFIG_IPATH_CORE)		+= hw/ipath/
 obj-$(CONFIG_INFINIBAND_IPOIB)		+= ulp/ipoib/
 obj-$(CONFIG_INFINIBAND_SRP)		+= ulp/srp/
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index c57a387..50364c0 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -302,7 +302,7 @@
 		kmalloc(sizeof *device->cache.pkey_cache *
 			(end_port(device) - start_port(device) + 1), GFP_KERNEL);
 	device->cache.gid_cache =
-		kmalloc(sizeof *device->cache.pkey_cache *
+		kmalloc(sizeof *device->cache.gid_cache *
 			(end_port(device) - start_port(device) + 1), GFP_KERNEL);
 
 	if (!device->cache.pkey_cache || !device->cache.gid_cache) {
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index ba54c85..469b692 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -228,10 +228,7 @@
 				goto error1;
 		}
 		/* Make sure class supplied is consistent with RMPP */
-		if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
-			if (!rmpp_version)
-				goto error1;
-		} else {
+		if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
 			if (rmpp_version)
 				goto error1;
 		}
@@ -2311,6 +2308,7 @@
 		local = list_entry(mad_agent_priv->local_list.next,
 				   struct ib_mad_local_private,
 				   completion_list);
+		list_del(&local->completion_list);
 		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 		if (local->mad_priv) {
 			recv_mad_agent = local->recv_mad_agent;
@@ -2362,7 +2360,6 @@
 						   &mad_send_wc);
 
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
-		list_del(&local->completion_list);
 		atomic_dec(&mad_agent_priv->refcount);
 		if (!recv)
 			kmem_cache_free(ib_mad_cache, local->mad_priv);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index cae0845..b78e7dc 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -45,6 +45,40 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
 
+int ib_rate_to_mult(enum ib_rate rate)
+{
+	switch (rate) {
+	case IB_RATE_2_5_GBPS: return  1;
+	case IB_RATE_5_GBPS:   return  2;
+	case IB_RATE_10_GBPS:  return  4;
+	case IB_RATE_20_GBPS:  return  8;
+	case IB_RATE_30_GBPS:  return 12;
+	case IB_RATE_40_GBPS:  return 16;
+	case IB_RATE_60_GBPS:  return 24;
+	case IB_RATE_80_GBPS:  return 32;
+	case IB_RATE_120_GBPS: return 48;
+	default:	       return -1;
+	}
+}
+EXPORT_SYMBOL(ib_rate_to_mult);
+
+enum ib_rate mult_to_ib_rate(int mult)
+{
+	switch (mult) {
+	case 1:  return IB_RATE_2_5_GBPS;
+	case 2:  return IB_RATE_5_GBPS;
+	case 4:  return IB_RATE_10_GBPS;
+	case 8:  return IB_RATE_20_GBPS;
+	case 12: return IB_RATE_30_GBPS;
+	case 16: return IB_RATE_40_GBPS;
+	case 24: return IB_RATE_60_GBPS;
+	case 32: return IB_RATE_80_GBPS;
+	case 48: return IB_RATE_120_GBPS;
+	default: return IB_RATE_PORT_CURRENT;
+	}
+}
+EXPORT_SYMBOL(mult_to_ib_rate);
+
 /* Protection domains */
 
 struct ib_pd *ib_alloc_pd(struct ib_device *device)
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
new file mode 100644
index 0000000..9ea67c4
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Kconfig
@@ -0,0 +1,16 @@
+config IPATH_CORE
+	tristate "PathScale InfiniPath Driver"
+	depends on 64BIT && PCI_MSI && NET
+	---help---
+	This is a low-level driver for PathScale InfiniPath host channel
+	adapters (HCAs) based on the HT-400 and PE-800 chips.
+
+config INFINIBAND_IPATH
+	tristate "PathScale InfiniPath Verbs Driver"
+	depends on IPATH_CORE && INFINIBAND
+	---help---
+	This is a driver that provides InfiniBand verbs support for
+	PathScale InfiniPath host channel adapters (HCAs).  This
+	allows these devices to be used with both kernel upper level
+	protocols such as IP-over-InfiniBand as well as with userspace
+	applications (in conjunction with InfiniBand userspace access).
diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile
new file mode 100644
index 0000000..b4d084a
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/Makefile
@@ -0,0 +1,36 @@
+EXTRA_CFLAGS += -DIPATH_IDSTR='"PathScale kernel.org driver"' \
+	-DIPATH_KERN_TYPE=0
+
+obj-$(CONFIG_IPATH_CORE) += ipath_core.o
+obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
+
+ipath_core-y := \
+	ipath_diag.o \
+	ipath_driver.o \
+	ipath_eeprom.o \
+	ipath_file_ops.o \
+	ipath_fs.o \
+	ipath_ht400.o \
+	ipath_init_chip.o \
+	ipath_intr.o \
+	ipath_layer.o \
+	ipath_pe800.o \
+	ipath_stats.o \
+	ipath_sysfs.o \
+	ipath_user_pages.o
+
+ipath_core-$(CONFIG_X86_64) += ipath_wc_x86_64.o
+
+ib_ipath-y := \
+	ipath_cq.o \
+	ipath_keys.o \
+	ipath_mad.o \
+	ipath_mr.o \
+	ipath_qp.o \
+	ipath_rc.o \
+	ipath_ruc.o \
+	ipath_srq.o \
+	ipath_uc.o \
+	ipath_ud.o \
+	ipath_verbs.o \
+	ipath_verbs_mcast.o
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
new file mode 100644
index 0000000..48a5524
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_COMMON_H
+#define _IPATH_COMMON_H
+
+/*
+ * This file contains defines, structures, etc. that are used
+ * to communicate between kernel and user code.
+ */
+
+/* This is the IEEE-assigned OUI for PathScale, Inc. */
+#define IPATH_SRC_OUI_1 0x00
+#define IPATH_SRC_OUI_2 0x11
+#define IPATH_SRC_OUI_3 0x75
+
+/* version of protocol header (known to chip also). In the long run,
+ * we should be able to generate and accept a range of version numbers;
+ * for now we only accept one, and it's compiled in.
+ */
+#define IPS_PROTO_VERSION 2
+
+/*
+ * These are compile time constants that you may want to enable or disable
+ * if you are trying to debug problems with code or performance.
+ * IPATH_VERBOSE_TRACING define as 1 if you want additional tracing in
+ * fastpath code
+ * IPATH_TRACE_REGWRITES define as 1 if you want register writes to be
+ * traced in faspath code
+ * _IPATH_TRACING define as 0 if you want to remove all tracing in a
+ * compilation unit
+ * _IPATH_DEBUGGING define as 0 if you want to remove debug prints
+ */
+
+/*
+ * The value in the BTH QP field that InfiniPath uses to differentiate
+ * an infinipath protocol IB packet vs standard IB transport
+ */
+#define IPATH_KD_QP 0x656b79
+
+/*
+ * valid states passed to ipath_set_linkstate() user call
+ */
+#define IPATH_IB_LINKDOWN		0
+#define IPATH_IB_LINKARM		1
+#define IPATH_IB_LINKACTIVE		2
+#define IPATH_IB_LINKINIT		3
+#define IPATH_IB_LINKDOWN_SLEEP		4
+#define IPATH_IB_LINKDOWN_DISABLE	5
+
+/*
+ * stats maintained by the driver.  For now, at least, this is global
+ * to all minor devices.
+ */
+struct infinipath_stats {
+	/* number of interrupts taken */
+	__u64 sps_ints;
+	/* number of interrupts for errors */
+	__u64 sps_errints;
+	/* number of errors from chip (not incl. packet errors or CRC) */
+	__u64 sps_errs;
+	/* number of packet errors from chip other than CRC */
+	__u64 sps_pkterrs;
+	/* number of packets with CRC errors (ICRC and VCRC) */
+	__u64 sps_crcerrs;
+	/* number of hardware errors reported (parity, etc.) */
+	__u64 sps_hwerrs;
+	/* number of times IB link changed state unexpectedly */
+	__u64 sps_iblink;
+	/* no longer used; left for compatibility */
+	__u64 sps_unused3;
+	/* number of kernel (port0) packets received */
+	__u64 sps_port0pkts;
+	/* number of "ethernet" packets sent by driver */
+	__u64 sps_ether_spkts;
+	/* number of "ethernet" packets received by driver */
+	__u64 sps_ether_rpkts;
+	/* number of SMA packets sent by driver */
+	__u64 sps_sma_spkts;
+	/* number of SMA packets received by driver */
+	__u64 sps_sma_rpkts;
+	/* number of times all ports rcvhdrq was full and packet dropped */
+	__u64 sps_hdrqfull;
+	/* number of times all ports egrtid was full and packet dropped */
+	__u64 sps_etidfull;
+	/*
+	 * number of times we tried to send from driver, but no pio buffers
+	 * avail
+	 */
+	__u64 sps_nopiobufs;
+	/* number of ports currently open */
+	__u64 sps_ports;
+	/* list of pkeys (other than default) accepted (0 means not set) */
+	__u16 sps_pkeys[4];
+	/* lids for up to 4 infinipaths, indexed by infinipath # */
+	__u16 sps_lid[4];
+	/* number of user ports per chip (not IB ports) */
+	__u32 sps_nports;
+	/* not our interrupt, or already handled */
+	__u32 sps_nullintr;
+	/* max number of packets handled per receive call */
+	__u32 sps_maxpkts_call;
+	/* avg number of packets handled per receive call */
+	__u32 sps_avgpkts_call;
+	/* total number of pages locked */
+	__u64 sps_pagelocks;
+	/* total number of pages unlocked */
+	__u64 sps_pageunlocks;
+	/*
+	 * Number of packets dropped in kernel other than errors (ether
+	 * packets if ipath not configured, sma/mad, etc.)
+	 */
+	__u64 sps_krdrops;
+	/* mlids for up to 4 infinipaths, indexed by infinipath # */
+	__u16 sps_mlid[4];
+	/* pad for future growth */
+	__u64 __sps_pad[45];
+};
+
+/*
+ * These are the status bits readable (in ascii form, 64bit value)
+ * from the "status" sysfs file.
+ */
+#define IPATH_STATUS_INITTED       0x1	/* basic initialization done */
+#define IPATH_STATUS_DISABLED      0x2	/* hardware disabled */
+/* Device has been disabled via admin request */
+#define IPATH_STATUS_ADMIN_DISABLED    0x4
+#define IPATH_STATUS_OIB_SMA       0x8	/* ipath_mad kernel SMA running */
+#define IPATH_STATUS_SMA          0x10	/* user SMA running */
+/* Chip has been found and initted */
+#define IPATH_STATUS_CHIP_PRESENT 0x20
+/* IB link is at ACTIVE, usable for data traffic */
+#define IPATH_STATUS_IB_READY     0x40
+/* link is configured, LID, MTU, etc. have been set */
+#define IPATH_STATUS_IB_CONF      0x80
+/* no link established, probably no cable */
+#define IPATH_STATUS_IB_NOCABLE  0x100
+/* A Fatal hardware error has occurred. */
+#define IPATH_STATUS_HWERROR     0x200
+
+/*
+ * The list of usermode accessible registers.  Also see Reg_* later in file.
+ */
+typedef enum _ipath_ureg {
+	/* (RO)  DMA RcvHdr to be used next. */
+	ur_rcvhdrtail = 0,
+	/* (RW)  RcvHdr entry to be processed next by host. */
+	ur_rcvhdrhead = 1,
+	/* (RO)  Index of next Eager index to use. */
+	ur_rcvegrindextail = 2,
+	/* (RW)  Eager TID to be processed next */
+	ur_rcvegrindexhead = 3,
+	/* For internal use only; max register number. */
+	_IPATH_UregMax
+} ipath_ureg;
+
+/* bit values for spi_runtime_flags */
+#define IPATH_RUNTIME_HT	0x1
+#define IPATH_RUNTIME_PCIE	0x2
+#define IPATH_RUNTIME_FORCE_WC_ORDER	0x4
+#define IPATH_RUNTIME_RCVHDR_COPY	0x8
+
+/*
+ * This structure is returned by ipath_userinit() immediately after
+ * open to get implementation-specific info, and info specific to this
+ * instance.
+ *
+ * This struct must have explict pad fields where type sizes
+ * may result in different alignments between 32 and 64 bit
+ * programs, since the 64 bit * bit kernel requires the user code
+ * to have matching offsets
+ */
+struct ipath_base_info {
+	/* version of hardware, for feature checking. */
+	__u32 spi_hw_version;
+	/* version of software, for feature checking. */
+	__u32 spi_sw_version;
+	/* InfiniPath port assigned, goes into sent packets */
+	__u32 spi_port;
+	/*
+	 * IB MTU, packets IB data must be less than this.
+	 * The MTU is in bytes, and will be a multiple of 4 bytes.
+	 */
+	__u32 spi_mtu;
+	/*
+	 * Size of a PIO buffer.  Any given packet's total size must be less
+	 * than this (in words).  Included is the starting control word, so
+	 * if 513 is returned, then total pkt size is 512 words or less.
+	 */
+	__u32 spi_piosize;
+	/* size of the TID cache in infinipath, in entries */
+	__u32 spi_tidcnt;
+	/* size of the TID Eager list in infinipath, in entries */
+	__u32 spi_tidegrcnt;
+	/* size of a single receive header queue entry. */
+	__u32 spi_rcvhdrent_size;
+	/*
+	 * Count of receive header queue entries allocated.
+	 * This may be less than the spu_rcvhdrcnt passed in!.
+	 */
+	__u32 spi_rcvhdr_cnt;
+
+	/* per-chip and other runtime features bitmap (IPATH_RUNTIME_*) */
+	__u32 spi_runtime_flags;
+
+	/* address where receive buffer queue is mapped into */
+	__u64 spi_rcvhdr_base;
+
+	/* user program. */
+
+	/* base address of eager TID receive buffers. */
+	__u64 spi_rcv_egrbufs;
+
+	/* Allocated by initialization code, not by protocol. */
+
+	/*
+	 * Size of each TID buffer in host memory, starting at
+	 * spi_rcv_egrbufs.  The buffers are virtually contiguous.
+	 */
+	__u32 spi_rcv_egrbufsize;
+	/*
+	 * The special QP (queue pair) value that identifies an infinipath
+	 * protocol packet from standard IB packets.  More, probably much
+	 * more, to be added.
+	 */
+	__u32 spi_qpair;
+
+	/*
+	 * User register base for init code, not to be used directly by
+	 * protocol or applications.
+	 */
+	__u64 __spi_uregbase;
+	/*
+	 * Maximum buffer size in bytes that can be used in a single TID
+	 * entry (assuming the buffer is aligned to this boundary).  This is
+	 * the minimum of what the hardware and software support Guaranteed
+	 * to be a power of 2.
+	 */
+	__u32 spi_tid_maxsize;
+	/*
+	 * alignment of each pio send buffer (byte count
+	 * to add to spi_piobufbase to get to second buffer)
+	 */
+	__u32 spi_pioalign;
+	/*
+	 * The index of the first pio buffer available to this process;
+	 * needed to do lookup in spi_pioavailaddr; not added to
+	 * spi_piobufbase.
+	 */
+	__u32 spi_pioindex;
+	 /* number of buffers mapped for this process */
+	__u32 spi_piocnt;
+
+	/*
+	 * Base address of writeonly pio buffers for this process.
+	 * Each buffer has spi_piosize words, and is aligned on spi_pioalign
+	 * boundaries.  spi_piocnt buffers are mapped from this address
+	 */
+	__u64 spi_piobufbase;
+
+	/*
+	 * Base address of readonly memory copy of the pioavail registers.
+	 * There are 2 bits for each buffer.
+	 */
+	__u64 spi_pioavailaddr;
+
+	/*
+	 * Address where driver updates a copy of the interface and driver
+	 * status (IPATH_STATUS_*) as a 64 bit value.  It's followed by a
+	 * string indicating hardware error, if there was one.
+	 */
+	__u64 spi_status;
+
+	/* number of chip ports available to user processes */
+	__u32 spi_nports;
+	/* unit number of chip we are using */
+	__u32 spi_unit;
+	/* num bufs in each contiguous set */
+	__u32 spi_rcv_egrperchunk;
+	/* size in bytes of each contiguous set */
+	__u32 spi_rcv_egrchunksize;
+	/* total size of mmap to cover full rcvegrbuffers */
+	__u32 spi_rcv_egrbuftotlen;
+} __attribute__ ((aligned(8)));
+
+
+/*
+ * This version number is given to the driver by the user code during
+ * initialization in the spu_userversion field of ipath_user_info, so
+ * the driver can check for compatibility with user code.
+ *
+ * The major version changes when data structures
+ * change in an incompatible way.  The driver must be the same or higher
+ * for initialization to succeed.  In some cases, a higher version
+ * driver will not interoperate with older software, and initialization
+ * will return an error.
+ */
+#define IPATH_USER_SWMAJOR 1
+
+/*
+ * Minor version differences are always compatible
+ * a within a major version, however if if user software is larger
+ * than driver software, some new features and/or structure fields
+ * may not be implemented; the user code must deal with this if it
+ * cares, or it must abort after initialization reports the difference
+ */
+#define IPATH_USER_SWMINOR 2
+
+#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
+
+#define IPATH_KERN_TYPE 0
+
+/*
+ * Similarly, this is the kernel version going back to the user.  It's
+ * slightly different, in that we want to tell if the driver was built as
+ * part of a PathScale release, or from the driver from OpenIB, kernel.org,
+ * or a standard distribution, for support reasons.  The high bit is 0 for
+ * non-PathScale, and 1 for PathScale-built/supplied.
+ *
+ * It's returned by the driver to the user code during initialization in the
+ * spi_sw_version field of ipath_base_info, so the user code can in turn
+ * check for compatibility with the kernel.
+*/
+#define IPATH_KERN_SWVERSION ((IPATH_KERN_TYPE<<31) | IPATH_USER_SWVERSION)
+
+/*
+ * This structure is passed to ipath_userinit() to tell the driver where
+ * user code buffers are, sizes, etc.   The offsets and sizes of the
+ * fields must remain unchanged, for binary compatibility.  It can
+ * be extended, if userversion is changed so user code can tell, if needed
+ */
+struct ipath_user_info {
+	/*
+	 * version of user software, to detect compatibility issues.
+	 * Should be set to IPATH_USER_SWVERSION.
+	 */
+	__u32 spu_userversion;
+
+	/* desired number of receive header queue entries */
+	__u32 spu_rcvhdrcnt;
+
+	/* size of struct base_info to write to */
+	__u32 spu_base_info_size;
+
+	/*
+	 * number of words in KD protocol header
+	 * This tells InfiniPath how many words to copy to rcvhdrq.  If 0,
+	 * kernel uses a default.  Once set, attempts to set any other value
+	 * are an error (EAGAIN) until driver is reloaded.
+	 */
+	__u32 spu_rcvhdrsize;
+
+	/*
+	 * cache line aligned (64 byte) user address to
+	 * which the rcvhdrtail register will be written by infinipath
+	 * whenever it changes, so that no chip registers are read in
+	 * the performance path.
+	 */
+	__u64 spu_rcvhdraddr;
+
+	/*
+	 * address of struct base_info to write to
+	 */
+	__u64 spu_base_info;
+
+} __attribute__ ((aligned(8)));
+
+/* User commands. */
+
+#define IPATH_CMD_MIN		16
+
+#define IPATH_CMD_USER_INIT	16	/* set up userspace */
+#define IPATH_CMD_PORT_INFO	17	/* find out what resources we got */
+#define IPATH_CMD_RECV_CTRL	18	/* control receipt of packets */
+#define IPATH_CMD_TID_UPDATE	19	/* update expected TID entries */
+#define IPATH_CMD_TID_FREE	20	/* free expected TID entries */
+#define IPATH_CMD_SET_PART_KEY	21	/* add partition key */
+
+#define IPATH_CMD_MAX		21
+
+struct ipath_port_info {
+	__u32 num_active;	/* number of active units */
+	__u32 unit;		/* unit (chip) assigned to caller */
+	__u32 port;		/* port on unit assigned to caller */
+};
+
+struct ipath_tid_info {
+	__u32 tidcnt;
+	/* make structure same size in 32 and 64 bit */
+	__u32 tid__unused;
+	/* virtual address of first page in transfer */
+	__u64 tidvaddr;
+	/* pointer (same size 32/64 bit) to __u16 tid array */
+	__u64 tidlist;
+
+	/*
+	 * pointer (same size 32/64 bit) to bitmap of TIDs used
+	 * for this call; checked for being large enough at open
+	 */
+	__u64 tidmap;
+};
+
+struct ipath_cmd {
+	__u32 type;			/* command type */
+	union {
+		struct ipath_tid_info tid_info;
+		struct ipath_user_info user_info;
+		/* address in userspace of struct ipath_port_info to
+		   write result to */
+		__u64 port_info;
+		/* enable/disable receipt of packets */
+		__u32 recv_ctrl;
+		/* partition key to set */
+		__u16 part_key;
+	} cmd;
+};
+
+struct ipath_iovec {
+	/* Pointer to data, but same size 32 and 64 bit */
+	__u64 iov_base;
+
+	/*
+	 * Length of data; don't need 64 bits, but want
+	 * ipath_sendpkt to remain same size as before 32 bit changes, so...
+	 */
+	__u64 iov_len;
+};
+
+/*
+ * Describes a single packet for send.  Each packet can have one or more
+ * buffers, but the total length (exclusive of IB headers) must be less
+ * than the MTU, and if using the PIO method, entire packet length,
+ * including IB headers, must be less than the ipath_piosize value (words).
+ * Use of this necessitates including sys/uio.h
+ */
+struct __ipath_sendpkt {
+	__u32 sps_flags;	/* flags for packet (TBD) */
+	__u32 sps_cnt;		/* number of entries to use in sps_iov */
+	/* array of iov's describing packet. TEMPORARY */
+	struct ipath_iovec sps_iov[4];
+};
+
+/* Passed into SMA special file's ->read and ->write methods. */
+struct ipath_sma_pkt
+{
+	__u32 unit;	/* unit on which to send packet */
+	__u64 data;	/* address of payload in userspace */
+	__u32 len;	/* length of payload */
+};
+
+/*
+ * Data layout in I2C flash (for GUID, etc.)
+ * All fields are little-endian binary unless otherwise stated
+ */
+#define IPATH_FLASH_VERSION 1
+struct ipath_flash {
+	/* flash layout version (IPATH_FLASH_VERSION) */
+	__u8 if_fversion;
+	/* checksum protecting if_length bytes */
+	__u8 if_csum;
+	/*
+	 * valid length (in use, protected by if_csum), including
+	 * if_fversion and if_sum themselves)
+	 */
+	__u8 if_length;
+	/* the GUID, in network order */
+	__u8 if_guid[8];
+	/* number of GUIDs to use, starting from if_guid */
+	__u8 if_numguid;
+	/* the board serial number, in ASCII */
+	char if_serial[12];
+	/* board mfg date (YYYYMMDD ASCII) */
+	char if_mfgdate[8];
+	/* last board rework/test date (YYYYMMDD ASCII) */
+	char if_testdate[8];
+	/* logging of error counts, TBD */
+	__u8 if_errcntp[4];
+	/* powered on hours, updated at driver unload */
+	__u8 if_powerhour[2];
+	/* ASCII free-form comment field */
+	char if_comment[32];
+	/* 78 bytes used, min flash size is 128 bytes */
+	__u8 if_future[50];
+};
+
+/*
+ * These are the counters implemented in the chip, and are listed in order.
+ * The InterCaps naming is taken straight from the chip spec.
+ */
+struct infinipath_counters {
+	__u64 LBIntCnt;
+	__u64 LBFlowStallCnt;
+	__u64 Reserved1;
+	__u64 TxUnsupVLErrCnt;
+	__u64 TxDataPktCnt;
+	__u64 TxFlowPktCnt;
+	__u64 TxDwordCnt;
+	__u64 TxLenErrCnt;
+	__u64 TxMaxMinLenErrCnt;
+	__u64 TxUnderrunCnt;
+	__u64 TxFlowStallCnt;
+	__u64 TxDroppedPktCnt;
+	__u64 RxDroppedPktCnt;
+	__u64 RxDataPktCnt;
+	__u64 RxFlowPktCnt;
+	__u64 RxDwordCnt;
+	__u64 RxLenErrCnt;
+	__u64 RxMaxMinLenErrCnt;
+	__u64 RxICRCErrCnt;
+	__u64 RxVCRCErrCnt;
+	__u64 RxFlowCtrlErrCnt;
+	__u64 RxBadFormatCnt;
+	__u64 RxLinkProblemCnt;
+	__u64 RxEBPCnt;
+	__u64 RxLPCRCErrCnt;
+	__u64 RxBufOvflCnt;
+	__u64 RxTIDFullErrCnt;
+	__u64 RxTIDValidErrCnt;
+	__u64 RxPKeyMismatchCnt;
+	__u64 RxP0HdrEgrOvflCnt;
+	__u64 RxP1HdrEgrOvflCnt;
+	__u64 RxP2HdrEgrOvflCnt;
+	__u64 RxP3HdrEgrOvflCnt;
+	__u64 RxP4HdrEgrOvflCnt;
+	__u64 RxP5HdrEgrOvflCnt;
+	__u64 RxP6HdrEgrOvflCnt;
+	__u64 RxP7HdrEgrOvflCnt;
+	__u64 RxP8HdrEgrOvflCnt;
+	__u64 Reserved6;
+	__u64 Reserved7;
+	__u64 IBStatusChangeCnt;
+	__u64 IBLinkErrRecoveryCnt;
+	__u64 IBLinkDownedCnt;
+	__u64 IBSymbolErrCnt;
+};
+
+/*
+ * The next set of defines are for packet headers, and chip register
+ * and memory bits that are visible to and/or used by user-mode software
+ * The other bits that are used only by the driver or diags are in
+ * ipath_registers.h
+ */
+
+/* RcvHdrFlags bits */
+#define INFINIPATH_RHF_LENGTH_MASK 0x7FF
+#define INFINIPATH_RHF_LENGTH_SHIFT 0
+#define INFINIPATH_RHF_RCVTYPE_MASK 0x7
+#define INFINIPATH_RHF_RCVTYPE_SHIFT 11
+#define INFINIPATH_RHF_EGRINDEX_MASK 0x7FF
+#define INFINIPATH_RHF_EGRINDEX_SHIFT 16
+#define INFINIPATH_RHF_H_ICRCERR   0x80000000
+#define INFINIPATH_RHF_H_VCRCERR   0x40000000
+#define INFINIPATH_RHF_H_PARITYERR 0x20000000
+#define INFINIPATH_RHF_H_LENERR    0x10000000
+#define INFINIPATH_RHF_H_MTUERR    0x08000000
+#define INFINIPATH_RHF_H_IHDRERR   0x04000000
+#define INFINIPATH_RHF_H_TIDERR    0x02000000
+#define INFINIPATH_RHF_H_MKERR     0x01000000
+#define INFINIPATH_RHF_H_IBERR     0x00800000
+#define INFINIPATH_RHF_L_SWA       0x00008000
+#define INFINIPATH_RHF_L_SWB       0x00004000
+
+/* infinipath header fields */
+#define INFINIPATH_I_VERS_MASK 0xF
+#define INFINIPATH_I_VERS_SHIFT 28
+#define INFINIPATH_I_PORT_MASK 0xF
+#define INFINIPATH_I_PORT_SHIFT 24
+#define INFINIPATH_I_TID_MASK 0x7FF
+#define INFINIPATH_I_TID_SHIFT 13
+#define INFINIPATH_I_OFFSET_MASK 0x1FFF
+#define INFINIPATH_I_OFFSET_SHIFT 0
+
+/* K_PktFlags bits */
+#define INFINIPATH_KPF_INTR 0x1
+
+/* SendPIO per-buffer control */
+#define INFINIPATH_SP_LENGTHP1_MASK 0x3FF
+#define INFINIPATH_SP_LENGTHP1_SHIFT 0
+#define INFINIPATH_SP_INTR    0x80000000
+#define INFINIPATH_SP_TEST    0x40000000
+#define INFINIPATH_SP_TESTEBP 0x20000000
+
+/* SendPIOAvail bits */
+#define INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT 1
+#define INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT 0
+
+#endif				/* _IPATH_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
new file mode 100644
index 0000000..7ece113
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_cq_enter - add a new entry to the completion queue
+ * @cq: completion queue
+ * @entry: work completion entry to add
+ * @sig: true if @entry is a solicitated entry
+ *
+ * This may be called with one of the qp->s_lock or qp->r_rq.lock held.
+ */
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
+{
+	unsigned long flags;
+	u32 next;
+
+	spin_lock_irqsave(&cq->lock, flags);
+
+	if (cq->head == cq->ibcq.cqe)
+		next = 0;
+	else
+		next = cq->head + 1;
+	if (unlikely(next == cq->tail)) {
+		spin_unlock_irqrestore(&cq->lock, flags);
+		if (cq->ibcq.event_handler) {
+			struct ib_event ev;
+
+			ev.device = cq->ibcq.device;
+			ev.element.cq = &cq->ibcq;
+			ev.event = IB_EVENT_CQ_ERR;
+			cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
+		}
+		return;
+	}
+	cq->queue[cq->head] = *entry;
+	cq->head = next;
+
+	if (cq->notify == IB_CQ_NEXT_COMP ||
+	    (cq->notify == IB_CQ_SOLICITED && solicited)) {
+		cq->notify = IB_CQ_NONE;
+		cq->triggered++;
+		/*
+		 * This will cause send_complete() to be called in
+		 * another thread.
+		 */
+		tasklet_hi_schedule(&cq->comptask);
+	}
+
+	spin_unlock_irqrestore(&cq->lock, flags);
+
+	if (entry->status != IB_WC_SUCCESS)
+		to_idev(cq->ibcq.device)->n_wqe_errs++;
+}
+
+/**
+ * ipath_poll_cq - poll for work completion entries
+ * @ibcq: the completion queue to poll
+ * @num_entries: the maximum number of entries to return
+ * @entry: pointer to array where work completions are placed
+ *
+ * Returns the number of completion entries polled.
+ *
+ * This may be called from interrupt context.  Also called by ib_poll_cq()
+ * in the generic verbs code.
+ */
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
+{
+	struct ipath_cq *cq = to_icq(ibcq);
+	unsigned long flags;
+	int npolled;
+
+	spin_lock_irqsave(&cq->lock, flags);
+
+	for (npolled = 0; npolled < num_entries; ++npolled, ++entry) {
+		if (cq->tail == cq->head)
+			break;
+		*entry = cq->queue[cq->tail];
+		if (cq->tail == cq->ibcq.cqe)
+			cq->tail = 0;
+		else
+			cq->tail++;
+	}
+
+	spin_unlock_irqrestore(&cq->lock, flags);
+
+	return npolled;
+}
+
+static void send_complete(unsigned long data)
+{
+	struct ipath_cq *cq = (struct ipath_cq *)data;
+
+	/*
+	 * The completion handler will most likely rearm the notification
+	 * and poll for all pending entries.  If a new completion entry
+	 * is added while we are in this routine, tasklet_hi_schedule()
+	 * won't call us again until we return so we check triggered to
+	 * see if we need to call the handler again.
+	 */
+	for (;;) {
+		u8 triggered = cq->triggered;
+
+		cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+
+		if (cq->triggered == triggered)
+			return;
+	}
+}
+
+/**
+ * ipath_create_cq - create a completion queue
+ * @ibdev: the device this completion queue is attached to
+ * @entries: the minimum size of the completion queue
+ * @context: unused by the InfiniPath driver
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns a pointer to the completion queue or negative errno values
+ * for failure.
+ *
+ * Called by ib_create_cq() in the generic verbs code.
+ */
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+			      struct ib_ucontext *context,
+			      struct ib_udata *udata)
+{
+	struct ipath_cq *cq;
+	struct ib_wc *wc;
+	struct ib_cq *ret;
+
+	/*
+	 * Need to use vmalloc() if we want to support large #s of
+	 * entries.
+	 */
+	cq = kmalloc(sizeof(*cq), GFP_KERNEL);
+	if (!cq) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	/*
+	 * Need to use vmalloc() if we want to support large #s of entries.
+	 */
+	wc = vmalloc(sizeof(*wc) * (entries + 1));
+	if (!wc) {
+		kfree(cq);
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+	/*
+	 * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe.
+	 * The number of entries should be >= the number requested or return
+	 * an error.
+	 */
+	cq->ibcq.cqe = entries;
+	cq->notify = IB_CQ_NONE;
+	cq->triggered = 0;
+	spin_lock_init(&cq->lock);
+	tasklet_init(&cq->comptask, send_complete, (unsigned long)cq);
+	cq->head = 0;
+	cq->tail = 0;
+	cq->queue = wc;
+
+	ret = &cq->ibcq;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_destroy_cq - destroy a completion queue
+ * @ibcq: the completion queue to destroy.
+ *
+ * Returns 0 for success.
+ *
+ * Called by ib_destroy_cq() in the generic verbs code.
+ */
+int ipath_destroy_cq(struct ib_cq *ibcq)
+{
+	struct ipath_cq *cq = to_icq(ibcq);
+
+	tasklet_kill(&cq->comptask);
+	vfree(cq->queue);
+	kfree(cq);
+
+	return 0;
+}
+
+/**
+ * ipath_req_notify_cq - change the notification type for a completion queue
+ * @ibcq: the completion queue
+ * @notify: the type of notification to request
+ *
+ * Returns 0 for success.
+ *
+ * This may be called from interrupt context.  Also called by
+ * ib_req_notify_cq() in the generic verbs code.
+ */
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+	struct ipath_cq *cq = to_icq(ibcq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cq->lock, flags);
+	/*
+	 * Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow
+	 * any other transitions.
+	 */
+	if (cq->notify != IB_CQ_NEXT_COMP)
+		cq->notify = notify;
+	spin_unlock_irqrestore(&cq->lock, flags);
+	return 0;
+}
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
+{
+	struct ipath_cq *cq = to_icq(ibcq);
+	struct ib_wc *wc, *old_wc;
+	u32 n;
+	int ret;
+
+	/*
+	 * Need to use vmalloc() if we want to support large #s of entries.
+	 */
+	wc = vmalloc(sizeof(*wc) * (cqe + 1));
+	if (!wc) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	spin_lock_irq(&cq->lock);
+	if (cq->head < cq->tail)
+		n = cq->ibcq.cqe + 1 + cq->head - cq->tail;
+	else
+		n = cq->head - cq->tail;
+	if (unlikely((u32)cqe < n)) {
+		spin_unlock_irq(&cq->lock);
+		vfree(wc);
+		ret = -EOVERFLOW;
+		goto bail;
+	}
+	for (n = 0; cq->tail != cq->head; n++) {
+		wc[n] = cq->queue[cq->tail];
+		if (cq->tail == cq->ibcq.cqe)
+			cq->tail = 0;
+		else
+			cq->tail++;
+	}
+	cq->ibcq.cqe = cqe;
+	cq->head = n;
+	cq->tail = 0;
+	old_wc = cq->queue;
+	cq->queue = wc;
+	spin_unlock_irq(&cq->lock);
+
+	vfree(old_wc);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
new file mode 100644
index 0000000..593e289
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_DEBUG_H
+#define _IPATH_DEBUG_H
+
+#ifndef _IPATH_DEBUGGING	/* debugging enabled or not */
+#define _IPATH_DEBUGGING 1
+#endif
+
+#if _IPATH_DEBUGGING
+
+/*
+ * Mask values for debugging.  The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or disable
+ * dynamically.  This can be set at modprobe time also:
+ *      modprobe infinipath.ko infinipath_debug=7
+ */
+
+#define __IPATH_INFO        0x1	/* generic low verbosity stuff */
+#define __IPATH_DBG         0x2	/* generic debug */
+#define __IPATH_TRSAMPLE    0x8	/* generate trace buffer sample entries */
+/* leave some low verbosity spots open */
+#define __IPATH_VERBDBG     0x40	/* very verbose debug */
+#define __IPATH_PKTDBG      0x80	/* print packet data */
+/* print process startup (init)/exit messages */
+#define __IPATH_PROCDBG     0x100
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG       0x200
+#define __IPATH_USER_SEND   0x1000	/* use user mode send */
+#define __IPATH_KERNEL_SEND 0x2000	/* use kernel mode send */
+#define __IPATH_EPKTDBG     0x4000	/* print ethernet packet data */
+#define __IPATH_SMADBG      0x8000	/* sma packet debug */
+#define __IPATH_IPATHDBG    0x10000	/* Ethernet (IPATH) general debug on */
+#define __IPATH_IPATHWARN   0x20000	/* Ethernet (IPATH) warnings on */
+#define __IPATH_IPATHERR    0x40000	/* Ethernet (IPATH) errors on */
+#define __IPATH_IPATHPD     0x80000	/* Ethernet (IPATH) packet dump on */
+#define __IPATH_IPATHTABLE  0x100000	/* Ethernet (IPATH) table dump on */
+
+#else				/* _IPATH_DEBUGGING */
+
+/*
+ * define all of these even with debugging off, for the few places that do
+ * if(infinipath_debug & _IPATH_xyzzy), but in a way that will make the
+ * compiler eliminate the code
+ */
+
+#define __IPATH_INFO      0x0	/* generic low verbosity stuff */
+#define __IPATH_DBG       0x0	/* generic debug */
+#define __IPATH_TRSAMPLE  0x0	/* generate trace buffer sample entries */
+#define __IPATH_VERBDBG   0x0	/* very verbose debug */
+#define __IPATH_PKTDBG    0x0	/* print packet data */
+#define __IPATH_PROCDBG   0x0	/* print process startup (init)/exit messages */
+/* print mmap/nopage stuff, not using VDBG any more */
+#define __IPATH_MMDBG     0x0
+#define __IPATH_EPKTDBG   0x0	/* print ethernet packet data */
+#define __IPATH_SMADBG    0x0   /* print process startup (init)/exit messages */#define __IPATH_IPATHDBG  0x0	/* Ethernet (IPATH) table dump on */
+#define __IPATH_IPATHWARN 0x0	/* Ethernet (IPATH) warnings on   */
+#define __IPATH_IPATHERR  0x0	/* Ethernet (IPATH) errors on   */
+#define __IPATH_IPATHPD   0x0	/* Ethernet (IPATH) packet dump on   */
+#define __IPATH_IPATHTABLE 0x0	/* Ethernet (IPATH) packet dump on   */
+
+#endif				/* _IPATH_DEBUGGING */
+
+#define __IPATH_VERBOSEDBG __IPATH_VERBDBG
+
+#endif				/* _IPATH_DEBUG_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
new file mode 100644
index 0000000..7d3fb69
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains support for diagnostic functions.  It is accessed by
+ * opening the ipath_diag device, normally minor number 129.  Diagnostic use
+ * of the InfiniPath chip may render the chip or board unusable until the
+ * driver is unloaded, or in some cases, until the system is rebooted.
+ *
+ * Accesses to the chip through this interface are not similar to going
+ * through the /sys/bus/pci resource mmap interface.
+ */
+
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#include "ipath_common.h"
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+int ipath_diag_inuse;
+static int diag_set_link;
+
+static int ipath_diag_open(struct inode *in, struct file *fp);
+static int ipath_diag_release(struct inode *in, struct file *fp);
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+			       size_t count, loff_t *off);
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+				size_t count, loff_t *off);
+
+static struct file_operations diag_file_ops = {
+	.owner = THIS_MODULE,
+	.write = ipath_diag_write,
+	.read = ipath_diag_read,
+	.open = ipath_diag_open,
+	.release = ipath_diag_release
+};
+
+static struct cdev *diag_cdev;
+static struct class_device *diag_class_dev;
+
+int ipath_diag_init(void)
+{
+	return ipath_cdev_init(IPATH_DIAG_MINOR, "ipath_diag",
+			       &diag_file_ops, &diag_cdev, &diag_class_dev);
+}
+
+void ipath_diag_cleanup(void)
+{
+	ipath_cdev_cleanup(&diag_cdev, &diag_class_dev);
+}
+
+/**
+ * ipath_read_umem64 - read a 64-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy (multiple of 32 bits)
+ *
+ * This function also localizes all chip memory accesses.
+ * The copy should be written such that we read full cacheline packets
+ * from the chip.  This is usually used for a single qword
+ *
+ * NOTE:  This assumes the chip address is 64-bit aligned.
+ */
+static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
+			     const void __iomem *caddr, size_t count)
+{
+	const u64 __iomem *reg_addr = caddr;
+	const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+	int ret;
+
+	/* not very efficient, but it works for now */
+	if (reg_addr < dd->ipath_kregbase ||
+	    reg_end > dd->ipath_kregend) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	while (reg_addr < reg_end) {
+		u64 data = readq(reg_addr);
+		if (copy_to_user(uaddr, &data, sizeof(u64))) {
+			ret = -EFAULT;
+			goto bail;
+		}
+		reg_addr++;
+		uaddr++;
+	}
+	ret = 0;
+bail:
+	return ret;
+}
+
+/**
+ * ipath_write_umem64 - write a 64-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: the number of bytes to copy (multiple of 32 bits)
+ *
+ * This is usually used for a single qword
+ * NOTE:  This assumes the chip address is 64-bit aligned.
+ */
+
+static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
+			      const void __user *uaddr, size_t count)
+{
+	u64 __iomem *reg_addr = caddr;
+	const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
+	int ret;
+
+	/* not very efficient, but it works for now */
+	if (reg_addr < dd->ipath_kregbase ||
+	    reg_end > dd->ipath_kregend) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	while (reg_addr < reg_end) {
+		u64 data;
+		if (copy_from_user(&data, uaddr, sizeof(data))) {
+			ret = -EFAULT;
+			goto bail;
+		}
+		writeq(data, reg_addr);
+
+		reg_addr++;
+		uaddr++;
+	}
+	ret = 0;
+bail:
+	return ret;
+}
+
+/**
+ * ipath_read_umem32 - read a 32-bit quantity from the chip into user space
+ * @dd: the infinipath device
+ * @uaddr: the location to store the data in user memory
+ * @caddr: the source chip address (full pointer, not offset)
+ * @count: number of bytes to copy
+ *
+ * read 32 bit values, not 64 bit; for memories that only
+ * support 32 bit reads; usually a single dword.
+ */
+static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr,
+			     const void __iomem *caddr, size_t count)
+{
+	const u32 __iomem *reg_addr = caddr;
+	const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+	int ret;
+
+	if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+	    reg_end > (u32 __iomem *) dd->ipath_kregend) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	/* not very efficient, but it works for now */
+	while (reg_addr < reg_end) {
+		u32 data = readl(reg_addr);
+		if (copy_to_user(uaddr, &data, sizeof(data))) {
+			ret = -EFAULT;
+			goto bail;
+		}
+
+		reg_addr++;
+		uaddr++;
+	}
+	ret = 0;
+bail:
+	return ret;
+}
+
+/**
+ * ipath_write_umem32 - write a 32-bit quantity to the chip from user space
+ * @dd: the infinipath device
+ * @caddr: the destination chip address (full pointer, not offset)
+ * @uaddr: the source of the data in user memory
+ * @count: number of bytes to copy
+ *
+ * write 32 bit values, not 64 bit; for memories that only
+ * support 32 bit write; usually a single dword.
+ */
+
+static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr,
+			      const void __user *uaddr, size_t count)
+{
+	u32 __iomem *reg_addr = caddr;
+	const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
+	int ret;
+
+	if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
+	    reg_end > (u32 __iomem *) dd->ipath_kregend) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	while (reg_addr < reg_end) {
+		u32 data;
+		if (copy_from_user(&data, uaddr, sizeof(data))) {
+			ret = -EFAULT;
+			goto bail;
+		}
+		writel(data, reg_addr);
+
+		reg_addr++;
+		uaddr++;
+	}
+	ret = 0;
+bail:
+	return ret;
+}
+
+static int ipath_diag_open(struct inode *in, struct file *fp)
+{
+	struct ipath_devdata *dd;
+	int unit = 0; /* XXX this is bogus */
+	unsigned long flags;
+	int ret;
+
+	dd = ipath_lookup(unit);
+
+	mutex_lock(&ipath_mutex);
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	if (ipath_diag_inuse) {
+		ret = -EBUSY;
+		goto bail;
+	}
+
+	list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+		/*
+		 * we need at least one infinipath device to be present
+		 * (don't use INITTED, because we want to be able to open
+		 * even if device is in freeze mode, which cleared INITTED).
+		 * There is a small amount of risk to this, which is why we
+		 * also verify kregbase is set.
+		 */
+
+		if (!(dd->ipath_flags & IPATH_PRESENT) ||
+		    !dd->ipath_kregbase)
+			continue;
+
+		ipath_diag_inuse = 1;
+		diag_set_link = 0;
+		ret = 0;
+		goto bail;
+	}
+
+	ret = -ENODEV;
+
+bail:
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+	mutex_unlock(&ipath_mutex);
+
+	/* Only expose a way to reset the device if we
+	   make it into diag mode. */
+	if (ret == 0)
+		ipath_expose_reset(&dd->pcidev->dev);
+
+	return ret;
+}
+
+static int ipath_diag_release(struct inode *i, struct file *f)
+{
+	mutex_lock(&ipath_mutex);
+	ipath_diag_inuse = 0;
+	mutex_unlock(&ipath_mutex);
+	return 0;
+}
+
+static ssize_t ipath_diag_read(struct file *fp, char __user *data,
+			       size_t count, loff_t *off)
+{
+	int unit = 0; /* XXX provide for reads on other units some day */
+	struct ipath_devdata *dd;
+	void __iomem *kreg_base;
+	ssize_t ret;
+
+	dd = ipath_lookup(unit);
+	if (!dd) {
+		ret = -ENODEV;
+		goto bail;
+	}
+
+	kreg_base = dd->ipath_kregbase;
+
+	if (count == 0)
+		ret = 0;
+	else if ((count % 4) || (*off % 4))
+		/* address or length is not 32-bit aligned, hence invalid */
+		ret = -EINVAL;
+	else if ((count % 8) || (*off % 8))
+		/* address or length not 64-bit aligned; do 32-bit reads */
+		ret = ipath_read_umem32(dd, data, kreg_base + *off, count);
+	else
+		ret = ipath_read_umem64(dd, data, kreg_base + *off, count);
+
+	if (ret >= 0) {
+		*off += count;
+		ret = count;
+	}
+
+bail:
+	return ret;
+}
+
+static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
+				size_t count, loff_t *off)
+{
+	int unit = 0; /* XXX this is bogus */
+	struct ipath_devdata *dd;
+	void __iomem *kreg_base;
+	ssize_t ret;
+
+	dd = ipath_lookup(unit);
+	if (!dd) {
+		ret = -ENODEV;
+		goto bail;
+	}
+	kreg_base = dd->ipath_kregbase;
+
+	if (count == 0)
+		ret = 0;
+	else if ((count % 4) || (*off % 4))
+		/* address or length is not 32-bit aligned, hence invalid */
+		ret = -EINVAL;
+	else if ((count % 8) || (*off % 8))
+		/* address or length not 64-bit aligned; do 32-bit writes */
+		ret = ipath_write_umem32(dd, kreg_base + *off, data, count);
+	else
+		ret = ipath_write_umem64(dd, kreg_base + *off, data, count);
+
+	if (ret >= 0) {
+		*off += count;
+		ret = count;
+	}
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
new file mode 100644
index 0000000..e7617c3
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -0,0 +1,1983 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static void ipath_update_pio_bufs(struct ipath_devdata *);
+
+const char *ipath_get_unit_name(int unit)
+{
+	static char iname[16];
+	snprintf(iname, sizeof iname, "infinipath%u", unit);
+	return iname;
+}
+
+EXPORT_SYMBOL_GPL(ipath_get_unit_name);
+
+#define DRIVER_LOAD_MSG "PathScale " IPATH_DRV_NAME " loaded: "
+#define PFX IPATH_DRV_NAME ": "
+
+/*
+ * The size has to be longer than this string, so we can append
+ * board/chip information to it in the init code.
+ */
+const char ipath_core_version[] = IPATH_IDSTR "\n";
+
+static struct idr unit_table;
+DEFINE_SPINLOCK(ipath_devs_lock);
+LIST_HEAD(ipath_dev_list);
+
+wait_queue_head_t ipath_sma_state_wait;
+
+unsigned ipath_debug = __IPATH_INFO;
+
+module_param_named(debug, ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "mask for debug prints");
+EXPORT_SYMBOL_GPL(ipath_debug);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const char *ipath_ibcstatus_str[] = {
+	"Disabled",
+	"LinkUp",
+	"PollActive",
+	"PollQuiet",
+	"SleepDelay",
+	"SleepQuiet",
+	"LState6",		/* unused */
+	"LState7",		/* unused */
+	"CfgDebounce",
+	"CfgRcvfCfg",
+	"CfgWaitRmt",
+	"CfgIdle",
+	"RecovRetrain",
+	"LState0xD",		/* unused */
+	"RecovWaitRmt",
+	"RecovIdle",
+};
+
+/*
+ * These variables are initialized in the chip-specific files
+ * but are defined here.
+ */
+u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+u64 ipath_gpio_sda, ipath_gpio_scl;
+u64 infinipath_i_bitsextant;
+ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+static void __devexit ipath_remove_one(struct pci_dev *);
+static int __devinit ipath_init_one(struct pci_dev *,
+				    const struct pci_device_id *);
+
+/* Only needed for registration, nothing else needs this info */
+#define PCI_VENDOR_ID_PATHSCALE 0x1fc1
+#define PCI_DEVICE_ID_INFINIPATH_HT 0xd
+#define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
+
+static const struct pci_device_id ipath_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE,
+		    PCI_DEVICE_ID_INFINIPATH_HT)},
+	{PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE,
+		    PCI_DEVICE_ID_INFINIPATH_PE800)},
+};
+
+MODULE_DEVICE_TABLE(pci, ipath_pci_tbl);
+
+static struct pci_driver ipath_driver = {
+	.name = IPATH_DRV_NAME,
+	.probe = ipath_init_one,
+	.remove = __devexit_p(ipath_remove_one),
+	.id_table = ipath_pci_tbl,
+};
+
+/*
+ * This is where port 0's rcvhdrtail register is written back; we also
+ * want nothing else sharing the cache line, so make it a cache line
+ * in size.  Used for all units.
+ */
+volatile __le64 *ipath_port0_rcvhdrtail;
+dma_addr_t ipath_port0_rcvhdrtail_dma;
+static int port0_rcvhdrtail_refs;
+
+static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
+			     u32 *bar0, u32 *bar1)
+{
+	int ret;
+
+	ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
+	if (ret)
+		ipath_dev_err(dd, "failed to read bar0 before enable: "
+			      "error %d\n", -ret);
+
+	ret = pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, bar1);
+	if (ret)
+		ipath_dev_err(dd, "failed to read bar1 before enable: "
+			      "error %d\n", -ret);
+
+	ipath_dbg("Read bar0 %x bar1 %x\n", *bar0, *bar1);
+}
+
+static void ipath_free_devdata(struct pci_dev *pdev,
+			       struct ipath_devdata *dd)
+{
+	unsigned long flags;
+
+	pci_set_drvdata(pdev, NULL);
+
+	if (dd->ipath_unit != -1) {
+		spin_lock_irqsave(&ipath_devs_lock, flags);
+		idr_remove(&unit_table, dd->ipath_unit);
+		list_del(&dd->ipath_list);
+		spin_unlock_irqrestore(&ipath_devs_lock, flags);
+	}
+	dma_free_coherent(&pdev->dev, sizeof(*dd), dd, dd->ipath_dma_addr);
+}
+
+static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
+{
+	unsigned long flags;
+	struct ipath_devdata *dd;
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+		dd = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	dd = dma_alloc_coherent(&pdev->dev, sizeof(*dd), &dma_addr,
+				GFP_KERNEL);
+
+	if (!dd) {
+		dd = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	dd->ipath_dma_addr = dma_addr;
+	dd->ipath_unit = -1;
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	ret = idr_get_new(&unit_table, dd, &dd->ipath_unit);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Could not allocate unit ID: error %d\n", -ret);
+		ipath_free_devdata(pdev, dd);
+		dd = ERR_PTR(ret);
+		goto bail_unlock;
+	}
+
+	dd->pcidev = pdev;
+	pci_set_drvdata(pdev, dd);
+
+	list_add(&dd->ipath_list, &ipath_dev_list);
+
+bail_unlock:
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+	return dd;
+}
+
+static inline struct ipath_devdata *__ipath_lookup(int unit)
+{
+	return idr_find(&unit_table, unit);
+}
+
+struct ipath_devdata *ipath_lookup(int unit)
+{
+	struct ipath_devdata *dd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+	dd = __ipath_lookup(unit);
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	return dd;
+}
+
+int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp)
+{
+	int nunits, npresent, nup;
+	struct ipath_devdata *dd;
+	unsigned long flags;
+	u32 maxports;
+
+	nunits = npresent = nup = maxports = 0;
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+		nunits++;
+		if ((dd->ipath_flags & IPATH_PRESENT) && dd->ipath_kregbase)
+			npresent++;
+		if (dd->ipath_lid &&
+		    !(dd->ipath_flags & (IPATH_DISABLED | IPATH_LINKDOWN
+					 | IPATH_LINKUNK)))
+			nup++;
+		if (dd->ipath_cfgports > maxports)
+			maxports = dd->ipath_cfgports;
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	if (npresentp)
+		*npresentp = npresent;
+	if (nupp)
+		*nupp = nup;
+	if (maxportsp)
+		*maxportsp = maxports;
+
+	return nunits;
+}
+
+static int init_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+	int ret;
+
+	mutex_lock(&ipath_mutex);
+
+	if (!ipath_port0_rcvhdrtail) {
+		ipath_port0_rcvhdrtail =
+			dma_alloc_coherent(&pdev->dev,
+					   IPATH_PORT0_RCVHDRTAIL_SIZE,
+					   &ipath_port0_rcvhdrtail_dma,
+					   GFP_KERNEL);
+
+		if (!ipath_port0_rcvhdrtail) {
+			ret = -ENOMEM;
+			goto bail;
+		}
+	}
+	port0_rcvhdrtail_refs++;
+	ret = 0;
+
+bail:
+	mutex_unlock(&ipath_mutex);
+
+	return ret;
+}
+
+static void cleanup_port0_rcvhdrtail(struct pci_dev *pdev)
+{
+	mutex_lock(&ipath_mutex);
+
+	if (!--port0_rcvhdrtail_refs) {
+		dma_free_coherent(&pdev->dev, IPATH_PORT0_RCVHDRTAIL_SIZE,
+				  (void *) ipath_port0_rcvhdrtail,
+				  ipath_port0_rcvhdrtail_dma);
+		ipath_port0_rcvhdrtail = NULL;
+	}
+
+	mutex_unlock(&ipath_mutex);
+}
+
+/*
+ * These next two routines are placeholders in case we don't have per-arch
+ * code for controlling write combining.  If explicit control of write
+ * combining is not available, performance will probably be awful.
+ */
+
+int __attribute__((weak)) ipath_enable_wc(struct ipath_devdata *dd)
+{
+	return -EOPNOTSUPP;
+}
+
+void __attribute__((weak)) ipath_disable_wc(struct ipath_devdata *dd)
+{
+}
+
+static int __devinit ipath_init_one(struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
+{
+	int ret, len, j;
+	struct ipath_devdata *dd;
+	unsigned long long addr;
+	u32 bar0 = 0, bar1 = 0;
+	u8 rev;
+
+	ret = init_port0_rcvhdrtail(pdev);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Could not allocate port0_rcvhdrtail: error %d\n",
+		       -ret);
+		goto bail;
+	}
+
+	dd = ipath_alloc_devdata(pdev);
+	if (IS_ERR(dd)) {
+		ret = PTR_ERR(dd);
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Could not allocate devdata: error %d\n", -ret);
+		goto bail_rcvhdrtail;
+	}
+
+	ipath_cdbg(VERBOSE, "initializing unit #%u\n", dd->ipath_unit);
+
+	read_bars(dd, pdev, &bar0, &bar1);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		/* This can happen iff:
+		 *
+		 * We did a chip reset, and then failed to reprogram the
+		 * BAR, or the chip reset due to an internal error.  We then
+		 * unloaded the driver and reloaded it.
+		 *
+		 * Both reset cases set the BAR back to initial state.  For
+		 * the latter case, the AER sticky error bit at offset 0x718
+		 * should be set, but the Linux kernel doesn't yet know
+		 * about that, it appears.  If the original BAR was retained
+		 * in the kernel data structures, this may be OK.
+		 */
+		ipath_dev_err(dd, "enable unit %d failed: error %d\n",
+			      dd->ipath_unit, -ret);
+		goto bail_devdata;
+	}
+	addr = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %x, vend %x/%x "
+		   "driver_data %lx\n", addr, len, pdev->irq, ent->vendor,
+		   ent->device, ent->driver_data);
+
+	read_bars(dd, pdev, &bar0, &bar1);
+
+	if (!bar1 && !(bar0 & ~0xf)) {
+		if (addr) {
+			dev_info(&pdev->dev, "BAR is 0 (probable RESET), "
+				 "rewriting as %llx\n", addr);
+			ret = pci_write_config_dword(
+				pdev, PCI_BASE_ADDRESS_0, addr);
+			if (ret) {
+				ipath_dev_err(dd, "rewrite of BAR0 "
+					      "failed: err %d\n", -ret);
+				goto bail_disable;
+			}
+			ret = pci_write_config_dword(
+				pdev, PCI_BASE_ADDRESS_1, addr >> 32);
+			if (ret) {
+				ipath_dev_err(dd, "rewrite of BAR1 "
+					      "failed: err %d\n", -ret);
+				goto bail_disable;
+			}
+		} else {
+			ipath_dev_err(dd, "BAR is 0 (probable RESET), "
+				      "not usable until reboot\n");
+			ret = -ENODEV;
+			goto bail_disable;
+		}
+	}
+
+	ret = pci_request_regions(pdev, IPATH_DRV_NAME);
+	if (ret) {
+		dev_info(&pdev->dev, "pci_request_regions unit %u fails: "
+			 "err %d\n", dd->ipath_unit, -ret);
+		goto bail_disable;
+	}
+
+	ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	if (ret) {
+		dev_info(&pdev->dev, "pci_set_dma_mask unit %u "
+			 "fails: %d\n", dd->ipath_unit, ret);
+		goto bail_regions;
+	}
+
+	pci_set_master(pdev);
+
+	/*
+	 * Save BARs to rewrite after device reset.  Save all 64 bits of
+	 * BAR, just in case.
+	 */
+	dd->ipath_pcibar0 = addr;
+	dd->ipath_pcibar1 = addr >> 32;
+	dd->ipath_deviceid = ent->device;	/* save for later use */
+	dd->ipath_vendorid = ent->vendor;
+
+	/* setup the chip-specific functions, as early as possible. */
+	switch (ent->device) {
+	case PCI_DEVICE_ID_INFINIPATH_HT:
+		ipath_init_ht400_funcs(dd);
+		break;
+	case PCI_DEVICE_ID_INFINIPATH_PE800:
+		ipath_init_pe800_funcs(dd);
+		break;
+	default:
+		ipath_dev_err(dd, "Found unknown PathScale deviceid 0x%x, "
+			      "failing\n", ent->device);
+		return -ENODEV;
+	}
+
+	for (j = 0; j < 6; j++) {
+		if (!pdev->resource[j].start)
+			continue;
+		ipath_cdbg(VERBOSE, "BAR %d start %lx, end %lx, len %lx\n",
+			   j, pdev->resource[j].start,
+			   pdev->resource[j].end,
+			   pci_resource_len(pdev, j));
+	}
+
+	if (!addr) {
+		ipath_dev_err(dd, "No valid address in BAR 0!\n");
+		ret = -ENODEV;
+		goto bail_regions;
+	}
+
+	dd->ipath_deviceid = ent->device;	/* save for later use */
+	dd->ipath_vendorid = ent->vendor;
+
+	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+	if (ret) {
+		ipath_dev_err(dd, "Failed to read PCI revision ID unit "
+			      "%u: err %d\n", dd->ipath_unit, -ret);
+		goto bail_regions;	/* shouldn't ever happen */
+	}
+	dd->ipath_pcirev = rev;
+
+	dd->ipath_kregbase = ioremap_nocache(addr, len);
+
+	if (!dd->ipath_kregbase) {
+		ipath_dbg("Unable to map io addr %llx to kvirt, failing\n",
+			  addr);
+		ret = -ENOMEM;
+		goto bail_iounmap;
+	}
+	dd->ipath_kregend = (u64 __iomem *)
+		((void __iomem *)dd->ipath_kregbase + len);
+	dd->ipath_physaddr = addr;	/* used for io_remap, etc. */
+	/* for user mmap */
+	dd->ipath_kregvirt = (u64 __iomem *) phys_to_virt(addr);
+	ipath_cdbg(VERBOSE, "mapped io addr %llx to kregbase %p "
+		   "kregvirt %p\n", addr, dd->ipath_kregbase,
+		   dd->ipath_kregvirt);
+
+	/*
+	 * clear ipath_flags here instead of in ipath_init_chip as it is set
+	 * by ipath_setup_htconfig.
+	 */
+	dd->ipath_flags = 0;
+
+	if (dd->ipath_f_bus(dd, pdev))
+		ipath_dev_err(dd, "Failed to setup config space; "
+			      "continuing anyway\n");
+
+	/*
+	 * set up our interrupt handler; SA_SHIRQ probably not needed,
+	 * since MSI interrupts shouldn't be shared but won't  hurt for now.
+	 * check 0 irq after we return from chip-specific bus setup, since
+	 * that can affect this due to setup
+	 */
+	if (!pdev->irq)
+		ipath_dev_err(dd, "irq is 0, BIOS error?  Interrupts won't "
+			      "work\n");
+	else {
+		ret = request_irq(pdev->irq, ipath_intr, SA_SHIRQ,
+				  IPATH_DRV_NAME, dd);
+		if (ret) {
+			ipath_dev_err(dd, "Couldn't setup irq handler, "
+				      "irq=%u: %d\n", pdev->irq, ret);
+			goto bail_iounmap;
+		}
+	}
+
+	ret = ipath_init_chip(dd, 0);	/* do the chip-specific init */
+	if (ret)
+		goto bail_iounmap;
+
+	ret = ipath_enable_wc(dd);
+
+	if (ret) {
+		ipath_dev_err(dd, "Write combining not enabled "
+			      "(err %d): performance may be poor\n",
+			      -ret);
+		ret = 0;
+	}
+
+	ipath_device_create_group(&pdev->dev, dd);
+	ipathfs_add_device(dd);
+	ipath_user_add(dd);
+	ipath_layer_add(dd);
+
+	goto bail;
+
+bail_iounmap:
+	iounmap((volatile void __iomem *) dd->ipath_kregbase);
+
+bail_regions:
+	pci_release_regions(pdev);
+
+bail_disable:
+	pci_disable_device(pdev);
+
+bail_devdata:
+	ipath_free_devdata(pdev, dd);
+
+bail_rcvhdrtail:
+	cleanup_port0_rcvhdrtail(pdev);
+
+bail:
+	return ret;
+}
+
+static void __devexit ipath_remove_one(struct pci_dev *pdev)
+{
+	struct ipath_devdata *dd;
+
+	ipath_cdbg(VERBOSE, "removing, pdev=%p\n", pdev);
+	if (!pdev)
+		return;
+
+	dd = pci_get_drvdata(pdev);
+	ipath_layer_del(dd);
+	ipath_user_del(dd);
+	ipathfs_remove_device(dd);
+	ipath_device_remove_group(&pdev->dev, dd);
+	ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, "
+		   "unit %u\n", dd, (u32) dd->ipath_unit);
+	if (dd->ipath_kregbase) {
+		ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n",
+			   dd->ipath_kregbase);
+		iounmap((volatile void __iomem *) dd->ipath_kregbase);
+		dd->ipath_kregbase = NULL;
+	}
+	pci_release_regions(pdev);
+	ipath_cdbg(VERBOSE, "calling pci_disable_device\n");
+	pci_disable_device(pdev);
+
+	ipath_free_devdata(pdev, dd);
+	cleanup_port0_rcvhdrtail(pdev);
+}
+
+/* general driver use */
+DEFINE_MUTEX(ipath_mutex);
+
+static DEFINE_SPINLOCK(ipath_pioavail_lock);
+
+/**
+ * ipath_disarm_piobufs - cancel a range of PIO buffers
+ * @dd: the infinipath device
+ * @first: the first PIO buffer to cancel
+ * @cnt: the number of PIO buffers to cancel
+ *
+ * cancel a range of PIO buffers, used when they might be armed, but
+ * not triggered.  Used at init to ensure buffer state, and also user
+ * process close, in case it died while writing to a PIO buffer
+ * Also after errors.
+ */
+void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+			  unsigned cnt)
+{
+	unsigned i, last = first + cnt;
+	u64 sendctrl, sendorig;
+
+	ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
+	sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+	for (i = first; i < last; i++) {
+		sendctrl = sendorig |
+			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+				 sendctrl);
+	}
+
+	/*
+	 * Write it again with current value, in case ipath_sendctrl changed
+	 * while we were looping; no critical bits that would require
+	 * locking.
+	 *
+	 * Write a 0, and then the original value, reading scratch in
+	 * between.  This seems to avoid a chip timing race that causes
+	 * pioavail updates to memory to stop.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 0);
+	sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 dd->ipath_sendctrl);
+}
+
+/**
+ * ipath_wait_linkstate - wait for an IB link state change to occur
+ * @dd: the infinipath device
+ * @state: the state to wait for
+ * @msecs: the number of milliseconds to wait
+ *
+ * wait up to msecs milliseconds for IB link state change to occur for
+ * now, take the easy polling route.  Currently used only by
+ * ipath_layer_set_linkstate.  Returns 0 if state reached, otherwise
+ * -ETIMEDOUT state can have multiple states set, for any of several
+ * transitions.
+ */
+int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
+{
+	dd->ipath_sma_state_wanted = state;
+	wait_event_interruptible_timeout(ipath_sma_state_wait,
+					 (dd->ipath_flags & state),
+					 msecs_to_jiffies(msecs));
+	dd->ipath_sma_state_wanted = 0;
+
+	if (!(dd->ipath_flags & state)) {
+		u64 val;
+		ipath_cdbg(SMA, "Didn't reach linkstate %s within %u ms\n",
+			   /* test INIT ahead of DOWN, both can be set */
+			   (state & IPATH_LINKINIT) ? "INIT" :
+			   ((state & IPATH_LINKDOWN) ? "DOWN" :
+			    ((state & IPATH_LINKARMED) ? "ARM" : "ACTIVE")),
+			   msecs);
+		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+		ipath_cdbg(VERBOSE, "ibcc=%llx ibcstatus=%llx (%s)\n",
+			   (unsigned long long) ipath_read_kreg64(
+				   dd, dd->ipath_kregs->kr_ibcctrl),
+			   (unsigned long long) val,
+			   ipath_ibcstatus_str[val & 0xf]);
+	}
+	return (dd->ipath_flags & state) ? 0 : -ETIMEDOUT;
+}
+
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err)
+{
+	*buf = '\0';
+	if (err & INFINIPATH_E_RHDRLEN)
+		strlcat(buf, "rhdrlen ", blen);
+	if (err & INFINIPATH_E_RBADTID)
+		strlcat(buf, "rbadtid ", blen);
+	if (err & INFINIPATH_E_RBADVERSION)
+		strlcat(buf, "rbadversion ", blen);
+	if (err & INFINIPATH_E_RHDR)
+		strlcat(buf, "rhdr ", blen);
+	if (err & INFINIPATH_E_RLONGPKTLEN)
+		strlcat(buf, "rlongpktlen ", blen);
+	if (err & INFINIPATH_E_RSHORTPKTLEN)
+		strlcat(buf, "rshortpktlen ", blen);
+	if (err & INFINIPATH_E_RMAXPKTLEN)
+		strlcat(buf, "rmaxpktlen ", blen);
+	if (err & INFINIPATH_E_RMINPKTLEN)
+		strlcat(buf, "rminpktlen ", blen);
+	if (err & INFINIPATH_E_RFORMATERR)
+		strlcat(buf, "rformaterr ", blen);
+	if (err & INFINIPATH_E_RUNSUPVL)
+		strlcat(buf, "runsupvl ", blen);
+	if (err & INFINIPATH_E_RUNEXPCHAR)
+		strlcat(buf, "runexpchar ", blen);
+	if (err & INFINIPATH_E_RIBFLOW)
+		strlcat(buf, "ribflow ", blen);
+	if (err & INFINIPATH_E_REBP)
+		strlcat(buf, "EBP ", blen);
+	if (err & INFINIPATH_E_SUNDERRUN)
+		strlcat(buf, "sunderrun ", blen);
+	if (err & INFINIPATH_E_SPIOARMLAUNCH)
+		strlcat(buf, "spioarmlaunch ", blen);
+	if (err & INFINIPATH_E_SUNEXPERRPKTNUM)
+		strlcat(buf, "sunexperrpktnum ", blen);
+	if (err & INFINIPATH_E_SDROPPEDDATAPKT)
+		strlcat(buf, "sdroppeddatapkt ", blen);
+	if (err & INFINIPATH_E_SDROPPEDSMPPKT)
+		strlcat(buf, "sdroppedsmppkt ", blen);
+	if (err & INFINIPATH_E_SMAXPKTLEN)
+		strlcat(buf, "smaxpktlen ", blen);
+	if (err & INFINIPATH_E_SMINPKTLEN)
+		strlcat(buf, "sminpktlen ", blen);
+	if (err & INFINIPATH_E_SUNSUPVL)
+		strlcat(buf, "sunsupVL ", blen);
+	if (err & INFINIPATH_E_SPKTLEN)
+		strlcat(buf, "spktlen ", blen);
+	if (err & INFINIPATH_E_INVALIDADDR)
+		strlcat(buf, "invalidaddr ", blen);
+	if (err & INFINIPATH_E_RICRC)
+		strlcat(buf, "CRC ", blen);
+	if (err & INFINIPATH_E_RVCRC)
+		strlcat(buf, "VCRC ", blen);
+	if (err & INFINIPATH_E_RRCVEGRFULL)
+		strlcat(buf, "rcvegrfull ", blen);
+	if (err & INFINIPATH_E_RRCVHDRFULL)
+		strlcat(buf, "rcvhdrfull ", blen);
+	if (err & INFINIPATH_E_IBSTATUSCHANGED)
+		strlcat(buf, "ibcstatuschg ", blen);
+	if (err & INFINIPATH_E_RIBLOSTLINK)
+		strlcat(buf, "riblostlink ", blen);
+	if (err & INFINIPATH_E_HARDWARE)
+		strlcat(buf, "hardware ", blen);
+	if (err & INFINIPATH_E_RESET)
+		strlcat(buf, "reset ", blen);
+}
+
+/**
+ * get_rhf_errstring - decode RHF errors
+ * @err: the err number
+ * @msg: the output buffer
+ * @len: the length of the output buffer
+ *
+ * only used one place now, may want more later
+ */
+static void get_rhf_errstring(u32 err, char *msg, size_t len)
+{
+	/* if no errors, and so don't need to check what's first */
+	*msg = '\0';
+
+	if (err & INFINIPATH_RHF_H_ICRCERR)
+		strlcat(msg, "icrcerr ", len);
+	if (err & INFINIPATH_RHF_H_VCRCERR)
+		strlcat(msg, "vcrcerr ", len);
+	if (err & INFINIPATH_RHF_H_PARITYERR)
+		strlcat(msg, "parityerr ", len);
+	if (err & INFINIPATH_RHF_H_LENERR)
+		strlcat(msg, "lenerr ", len);
+	if (err & INFINIPATH_RHF_H_MTUERR)
+		strlcat(msg, "mtuerr ", len);
+	if (err & INFINIPATH_RHF_H_IHDRERR)
+		/* infinipath hdr checksum error */
+		strlcat(msg, "ipathhdrerr ", len);
+	if (err & INFINIPATH_RHF_H_TIDERR)
+		strlcat(msg, "tiderr ", len);
+	if (err & INFINIPATH_RHF_H_MKERR)
+		/* bad port, offset, etc. */
+		strlcat(msg, "invalid ipathhdr ", len);
+	if (err & INFINIPATH_RHF_H_IBERR)
+		strlcat(msg, "iberr ", len);
+	if (err & INFINIPATH_RHF_L_SWA)
+		strlcat(msg, "swA ", len);
+	if (err & INFINIPATH_RHF_L_SWB)
+		strlcat(msg, "swB ", len);
+}
+
+/**
+ * ipath_get_egrbuf - get an eager buffer
+ * @dd: the infinipath device
+ * @bufnum: the eager buffer to get
+ * @err: unused
+ *
+ * must only be called if ipath_pd[port] is known to be allocated
+ */
+static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
+				     int err)
+{
+	return dd->ipath_port0_skbs ?
+		(void *)dd->ipath_port0_skbs[bufnum]->data : NULL;
+}
+
+/**
+ * ipath_alloc_skb - allocate an skb and buffer with possible constraints
+ * @dd: the infinipath device
+ * @gfp_mask: the sk_buff SFP mask
+ */
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
+				gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+	u32 len;
+
+	/*
+	 * Only fully supported way to handle this is to allocate lots
+	 * extra, align as needed, and then do skb_reserve().  That wastes
+	 * a lot of memory...  I'll have to hack this into infinipath_copy
+	 * also.
+	 */
+
+	/*
+	 * We need 4 extra bytes for unaligned transfer copying
+	 */
+	if (dd->ipath_flags & IPATH_4BYTE_TID) {
+		/* we need a 4KB multiple alignment, and there is no way
+		 * to do it except to allocate extra and then skb_reserve
+		 * enough to bring it up to the right alignment.
+		 */
+		len = dd->ipath_ibmaxlen + 4 + (1 << 11) - 1;
+	}
+	else
+		len = dd->ipath_ibmaxlen + 4;
+	skb = __dev_alloc_skb(len, gfp_mask);
+	if (!skb) {
+		ipath_dev_err(dd, "Failed to allocate skbuff, length %u\n",
+			      len);
+		goto bail;
+	}
+	if (dd->ipath_flags & IPATH_4BYTE_TID) {
+		u32 una = ((1 << 11) - 1) & (unsigned long)(skb->data + 4);
+		if (una)
+			skb_reserve(skb, 4 + (1 << 11) - una);
+		else
+			skb_reserve(skb, 4);
+	} else
+		skb_reserve(skb, 4);
+
+bail:
+	return skb;
+}
+
+/**
+ * ipath_rcv_layer - receive a packet for the layered (ethernet) driver
+ * @dd: the infinipath device
+ * @etail: the sk_buff number
+ * @tlen: the total packet length
+ * @hdr: the ethernet header
+ *
+ * Separate routine for better overall optimization
+ */
+static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail,
+			    u32 tlen, struct ether_header *hdr)
+{
+	u32 elen;
+	u8 pad, *bthbytes;
+	struct sk_buff *skb, *nskb;
+
+	if (dd->ipath_port0_skbs && hdr->sub_opcode == OPCODE_ENCAP) {
+		/*
+		 * Allocate a new sk_buff to replace the one we give
+		 * to the network stack.
+		 */
+		nskb = ipath_alloc_skb(dd, GFP_ATOMIC);
+		if (!nskb) {
+			/* count OK packets that we drop */
+			ipath_stats.sps_krdrops++;
+			return;
+		}
+
+		bthbytes = (u8 *) hdr->bth;
+		pad = (bthbytes[1] >> 4) & 3;
+		/* +CRC32 */
+		elen = tlen - (sizeof(*hdr) + pad + sizeof(u32));
+
+		skb = dd->ipath_port0_skbs[etail];
+		dd->ipath_port0_skbs[etail] = nskb;
+		skb_put(skb, elen);
+
+		dd->ipath_f_put_tid(dd, etail + (u64 __iomem *)
+				    ((char __iomem *) dd->ipath_kregbase
+				     + dd->ipath_rcvegrbase), 0,
+				    virt_to_phys(nskb->data));
+
+		__ipath_layer_rcv(dd, hdr, skb);
+
+		/* another ether packet received */
+		ipath_stats.sps_ether_rpkts++;
+	}
+	else if (hdr->sub_opcode == OPCODE_LID_ARP)
+		__ipath_layer_rcv_lid(dd, hdr);
+}
+
+/*
+ * ipath_kreceive - receive a packet
+ * @dd: the infinipath device
+ *
+ * called from interrupt handler for errors or receive interrupt
+ */
+void ipath_kreceive(struct ipath_devdata *dd)
+{
+	u64 *rc;
+	void *ebuf;
+	const u32 rsize = dd->ipath_rcvhdrentsize;	/* words */
+	const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize;	/* words */
+	u32 etail = -1, l, hdrqtail;
+	struct ips_message_header *hdr;
+	u32 eflags, i, etype, tlen, pkttot = 0;
+	static u64 totcalls;	/* stats, may eventually remove */
+	char emsg[128];
+
+	if (!dd->ipath_hdrqtailptr) {
+		ipath_dev_err(dd,
+			      "hdrqtailptr not set, can't do receives\n");
+		goto bail;
+	}
+
+	/* There is already a thread processing this queue. */
+	if (test_and_set_bit(0, &dd->ipath_rcv_pending))
+		goto bail;
+
+	if (dd->ipath_port0head ==
+	    (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+		goto done;
+
+gotmore:
+	/*
+	 * read only once at start.  If in flood situation, this helps
+	 * performance slightly.  If more arrive while we are processing,
+	 * we'll come back here and do them
+	 */
+	hdrqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
+
+	for (i = 0, l = dd->ipath_port0head; l != hdrqtail; i++) {
+		u32 qp;
+		u8 *bthbytes;
+
+		rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
+		hdr = (struct ips_message_header *)&rc[1];
+		/*
+		 * could make a network order version of IPATH_KD_QP, and
+		 * do the obvious shift before masking to speed this up.
+		 */
+		qp = ntohl(hdr->bth[1]) & 0xffffff;
+		bthbytes = (u8 *) hdr->bth;
+
+		eflags = ips_get_hdr_err_flags((__le32 *) rc);
+		etype = ips_get_rcv_type((__le32 *) rc);
+		/* total length */
+		tlen = ips_get_length_in_bytes((__le32 *) rc);
+		ebuf = NULL;
+		if (etype != RCVHQ_RCV_TYPE_EXPECTED) {
+			/*
+			 * it turns out that the chips uses an eager buffer
+			 * for all non-expected packets, whether it "needs"
+			 * one or not.  So always get the index, but don't
+			 * set ebuf (so we try to copy data) unless the
+			 * length requires it.
+			 */
+			etail = ips_get_index((__le32 *) rc);
+			if (tlen > sizeof(*hdr) ||
+			    etype == RCVHQ_RCV_TYPE_NON_KD)
+				ebuf = ipath_get_egrbuf(dd, etail, 0);
+		}
+
+		/*
+		 * both tiderr and ipathhdrerr are set for all plain IB
+		 * packets; only ipathhdrerr should be set.
+		 */
+
+		if (etype != RCVHQ_RCV_TYPE_NON_KD && etype !=
+		    RCVHQ_RCV_TYPE_ERROR && ips_get_ipath_ver(
+			    hdr->iph.ver_port_tid_offset) !=
+		    IPS_PROTO_VERSION) {
+			ipath_cdbg(PKT, "Bad InfiniPath protocol version "
+				   "%x\n", etype);
+		}
+
+		if (eflags & ~(INFINIPATH_RHF_H_TIDERR |
+			       INFINIPATH_RHF_H_IHDRERR)) {
+			get_rhf_errstring(eflags, emsg, sizeof emsg);
+			ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u "
+				   "tlen=%x opcode=%x egridx=%x: %s\n",
+				   eflags, l, etype, tlen, bthbytes[0],
+				   ips_get_index((__le32 *) rc), emsg);
+		} else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
+				int ret = __ipath_verbs_rcv(dd, rc + 1,
+							    ebuf, tlen);
+				if (ret == -ENODEV)
+					ipath_cdbg(VERBOSE,
+						   "received IB packet, "
+						   "not SMA (QP=%x)\n", qp);
+		} else if (etype == RCVHQ_RCV_TYPE_EAGER) {
+			if (qp == IPATH_KD_QP &&
+			    bthbytes[0] == ipath_layer_rcv_opcode &&
+			    ebuf)
+				ipath_rcv_layer(dd, etail, tlen,
+						(struct ether_header *)hdr);
+			else
+				ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
+					   "qp=%x), len %x; ignored\n",
+					   etype, bthbytes[0], qp, tlen);
+		}
+		else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
+			ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
+				  be32_to_cpu(hdr->bth[0]) & 0xff);
+		else if (eflags & (INFINIPATH_RHF_H_TIDERR |
+				   INFINIPATH_RHF_H_IHDRERR)) {
+			/*
+			 * This is a type 3 packet, only the LRH is in the
+			 * rcvhdrq, the rest of the header is in the eager
+			 * buffer.
+			 */
+			u8 opcode;
+			if (ebuf) {
+				bthbytes = (u8 *) ebuf;
+				opcode = *bthbytes;
+			}
+			else
+				opcode = 0;
+			get_rhf_errstring(eflags, emsg, sizeof emsg);
+			ipath_dbg("Err %x (%s), opcode %x, egrbuf %x, "
+				  "len %x\n", eflags, emsg, opcode, etail,
+				  tlen);
+		} else {
+			/*
+			 * error packet, type of error	unknown.
+			 * Probably type 3, but we don't know, so don't
+			 * even try to print the opcode, etc.
+			 */
+			ipath_dbg("Error Pkt, but no eflags! egrbuf %x, "
+				  "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; "
+				  "hdr %llx %llx %llx %llx %llx\n",
+				  etail, tlen, (unsigned long) rc, l,
+				  (unsigned long long) rc[0],
+				  (unsigned long long) rc[1],
+				  (unsigned long long) rc[2],
+				  (unsigned long long) rc[3],
+				  (unsigned long long) rc[4],
+				  (unsigned long long) rc[5]);
+		}
+		l += rsize;
+		if (l >= maxcnt)
+			l = 0;
+		/*
+		 * update for each packet, to help prevent overflows if we
+		 * have lots of packets.
+		 */
+		(void)ipath_write_ureg(dd, ur_rcvhdrhead,
+				       dd->ipath_rhdrhead_intr_off | l, 0);
+		if (etype != RCVHQ_RCV_TYPE_EXPECTED)
+			(void)ipath_write_ureg(dd, ur_rcvegrindexhead,
+					       etail, 0);
+	}
+
+	pkttot += i;
+
+	dd->ipath_port0head = l;
+
+	if (hdrqtail != (u32)le64_to_cpu(*dd->ipath_hdrqtailptr))
+		/* more arrived while we handled first batch */
+		goto gotmore;
+
+	if (pkttot > ipath_stats.sps_maxpkts_call)
+		ipath_stats.sps_maxpkts_call = pkttot;
+	ipath_stats.sps_port0pkts += pkttot;
+	ipath_stats.sps_avgpkts_call =
+		ipath_stats.sps_port0pkts / ++totcalls;
+
+done:
+	clear_bit(0, &dd->ipath_rcv_pending);
+	smp_mb__after_clear_bit();
+
+bail:;
+}
+
+/**
+ * ipath_update_pio_bufs - update shadow copy of the PIO availability map
+ * @dd: the infinipath device
+ *
+ * called whenever our local copy indicates we have run out of send buffers
+ * NOTE: This can be called from interrupt context by some code
+ * and from non-interrupt context by ipath_getpiobuf().
+ */
+
+static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+{
+	unsigned long flags;
+	int i;
+	const unsigned piobregs = (unsigned)dd->ipath_pioavregs;
+
+	/* If the generation (check) bits have changed, then we update the
+	 * busy bit for the corresponding PIO buffer.  This algorithm will
+	 * modify positions to the value they already have in some cases
+	 * (i.e., no change), but it's faster than changing only the bits
+	 * that have changed.
+	 *
+	 * We would like to do this atomicly, to avoid spinlocks in the
+	 * critical send path, but that's not really possible, given the
+	 * type of changes, and that this routine could be called on
+	 * multiple cpu's simultaneously, so we lock in this routine only,
+	 * to avoid conflicting updates; all we change is the shadow, and
+	 * it's a single 64 bit memory location, so by definition the update
+	 * is atomic in terms of what other cpu's can see in testing the
+	 * bits.  The spin_lock overhead isn't too bad, since it only
+	 * happens when all buffers are in use, so only cpu overhead, not
+	 * latency or bandwidth is affected.
+	 */
+#define _IPATH_ALL_CHECKBITS 0x5555555555555555ULL
+	if (!dd->ipath_pioavailregs_dma) {
+		ipath_dbg("Update shadow pioavail, but regs_dma NULL!\n");
+		return;
+	}
+	if (ipath_debug & __IPATH_VERBDBG) {
+		/* only if packet debug and verbose */
+		volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+		unsigned long *shadow = dd->ipath_pioavailshadow;
+
+		ipath_cdbg(PKT, "Refill avail, dma0=%llx shad0=%lx, "
+			   "d1=%llx s1=%lx, d2=%llx s2=%lx, d3=%llx "
+			   "s3=%lx\n",
+			   (unsigned long long) le64_to_cpu(dma[0]),
+			   shadow[0],
+			   (unsigned long long) le64_to_cpu(dma[1]),
+			   shadow[1],
+			   (unsigned long long) le64_to_cpu(dma[2]),
+			   shadow[2],
+			   (unsigned long long) le64_to_cpu(dma[3]),
+			   shadow[3]);
+		if (piobregs > 4)
+			ipath_cdbg(
+				PKT, "2nd group, dma4=%llx shad4=%lx, "
+				"d5=%llx s5=%lx, d6=%llx s6=%lx, "
+				"d7=%llx s7=%lx\n",
+				(unsigned long long) le64_to_cpu(dma[4]),
+				shadow[4],
+				(unsigned long long) le64_to_cpu(dma[5]),
+				shadow[5],
+				(unsigned long long) le64_to_cpu(dma[6]),
+				shadow[6],
+				(unsigned long long) le64_to_cpu(dma[7]),
+				shadow[7]);
+	}
+	spin_lock_irqsave(&ipath_pioavail_lock, flags);
+	for (i = 0; i < piobregs; i++) {
+		u64 pchbusy, pchg, piov, pnew;
+		/*
+		 * Chip Errata: bug 6641; even and odd qwords>3 are swapped
+		 */
+		if (i > 3) {
+			if (i & 1)
+				piov = le64_to_cpu(
+					dd->ipath_pioavailregs_dma[i - 1]);
+			else
+				piov = le64_to_cpu(
+					dd->ipath_pioavailregs_dma[i + 1]);
+		} else
+			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+		pchg = _IPATH_ALL_CHECKBITS &
+			~(dd->ipath_pioavailshadow[i] ^ piov);
+		pchbusy = pchg << INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT;
+		if (pchg && (pchbusy & dd->ipath_pioavailshadow[i])) {
+			pnew = dd->ipath_pioavailshadow[i] & ~pchbusy;
+			pnew |= piov & pchbusy;
+			dd->ipath_pioavailshadow[i] = pnew;
+		}
+	}
+	spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+}
+
+/**
+ * ipath_setrcvhdrsize - set the receive header size
+ * @dd: the infinipath device
+ * @rhdrsize: the receive header size
+ *
+ * called from user init code, and also layered driver init
+ */
+int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize)
+{
+	int ret = 0;
+
+	if (dd->ipath_flags & IPATH_RCVHDRSZ_SET) {
+		if (dd->ipath_rcvhdrsize != rhdrsize) {
+			dev_info(&dd->pcidev->dev,
+				 "Error: can't set protocol header "
+				 "size %u, already %u\n",
+				 rhdrsize, dd->ipath_rcvhdrsize);
+			ret = -EAGAIN;
+		} else
+			ipath_cdbg(VERBOSE, "Reuse same protocol header "
+				   "size %u\n", dd->ipath_rcvhdrsize);
+	} else if (rhdrsize > (dd->ipath_rcvhdrentsize -
+			       (sizeof(u64) / sizeof(u32)))) {
+		ipath_dbg("Error: can't set protocol header size %u "
+			  "(> max %u)\n", rhdrsize,
+			  dd->ipath_rcvhdrentsize -
+			  (u32) (sizeof(u64) / sizeof(u32)));
+		ret = -EOVERFLOW;
+	} else {
+		dd->ipath_flags |= IPATH_RCVHDRSZ_SET;
+		dd->ipath_rcvhdrsize = rhdrsize;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+				 dd->ipath_rcvhdrsize);
+		ipath_cdbg(VERBOSE, "Set protocol header size to %u\n",
+			   dd->ipath_rcvhdrsize);
+	}
+	return ret;
+}
+
+/**
+ * ipath_getpiobuf - find an available pio buffer
+ * @dd: the infinipath device
+ * @pbufnum: the buffer number is placed here
+ *
+ * do appropriate marking as busy, etc.
+ * returns buffer number if one found (>=0), negative number is error.
+ * Used by ipath_sma_send_pkt and ipath_layer_send
+ */
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
+{
+	int i, j, starti, updated = 0;
+	unsigned piobcnt, iter;
+	unsigned long flags;
+	unsigned long *shadow = dd->ipath_pioavailshadow;
+	u32 __iomem *buf;
+
+	piobcnt = (unsigned)(dd->ipath_piobcnt2k
+			     + dd->ipath_piobcnt4k);
+	starti = dd->ipath_lastport_piobuf;
+	iter = piobcnt - starti;
+	if (dd->ipath_upd_pio_shadow) {
+		/*
+		 * Minor optimization.  If we had no buffers on last call,
+		 * start out by doing the update; continue and do scan even
+		 * if no buffers were updated, to be paranoid
+		 */
+		ipath_update_pio_bufs(dd);
+		/* we scanned here, don't do it at end of scan */
+		updated = 1;
+		i = starti;
+	} else
+		i = dd->ipath_lastpioindex;
+
+rescan:
+	/*
+	 * while test_and_set_bit() is atomic, we do that and then the
+	 * change_bit(), and the pair is not.  See if this is the cause
+	 * of the remaining armlaunch errors.
+	 */
+	spin_lock_irqsave(&ipath_pioavail_lock, flags);
+	for (j = 0; j < iter; j++, i++) {
+		if (i >= piobcnt)
+			i = starti;
+		/*
+		 * To avoid bus lock overhead, we first find a candidate
+		 * buffer, then do the test and set, and continue if that
+		 * fails.
+		 */
+		if (test_bit((2 * i) + 1, shadow) ||
+		    test_and_set_bit((2 * i) + 1, shadow))
+			continue;
+		/* flip generation bit */
+		change_bit(2 * i, shadow);
+		break;
+	}
+	spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
+
+	if (j == iter) {
+		volatile __le64 *dma = dd->ipath_pioavailregs_dma;
+
+		/*
+		 * first time through; shadow exhausted, but may be real
+		 * buffers available, so go see; if any updated, rescan
+		 * (once)
+		 */
+		if (!updated) {
+			ipath_update_pio_bufs(dd);
+			updated = 1;
+			i = starti;
+			goto rescan;
+		}
+		dd->ipath_upd_pio_shadow = 1;
+		/*
+		 * not atomic, but if we lose one once in a while, that's OK
+		 */
+		ipath_stats.sps_nopiobufs++;
+		if (!(++dd->ipath_consec_nopiobuf % 100000)) {
+			ipath_dbg(
+				"%u pio sends with no bufavail; dmacopy: "
+				"%llx %llx %llx %llx; shadow:  "
+				"%lx %lx %lx %lx\n",
+				dd->ipath_consec_nopiobuf,
+				(unsigned long long) le64_to_cpu(dma[0]),
+				(unsigned long long) le64_to_cpu(dma[1]),
+				(unsigned long long) le64_to_cpu(dma[2]),
+				(unsigned long long) le64_to_cpu(dma[3]),
+				shadow[0], shadow[1], shadow[2],
+				shadow[3]);
+			/*
+			 * 4 buffers per byte, 4 registers above, cover rest
+			 * below
+			 */
+			if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
+			    (sizeof(shadow[0]) * 4 * 4))
+				ipath_dbg("2nd group: dmacopy: %llx %llx "
+					  "%llx %llx; shadow: %lx %lx "
+					  "%lx %lx\n",
+					  (unsigned long long)
+					  le64_to_cpu(dma[4]),
+					  (unsigned long long)
+					  le64_to_cpu(dma[5]),
+					  (unsigned long long)
+					  le64_to_cpu(dma[6]),
+					  (unsigned long long)
+					  le64_to_cpu(dma[7]),
+					  shadow[4], shadow[5],
+					  shadow[6], shadow[7]);
+		}
+		buf = NULL;
+		goto bail;
+	}
+
+	if (updated)
+		/*
+		 * ran out of bufs, now some (at least this one we just
+		 * got) are now available, so tell the layered driver.
+		 */
+		__ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+
+	/*
+	 * set next starting place.  Since it's just an optimization,
+	 * it doesn't matter who wins on this, so no locking
+	 */
+	dd->ipath_lastpioindex = i + 1;
+	if (dd->ipath_upd_pio_shadow)
+		dd->ipath_upd_pio_shadow = 0;
+	if (dd->ipath_consec_nopiobuf)
+		dd->ipath_consec_nopiobuf = 0;
+	if (i < dd->ipath_piobcnt2k)
+		buf = (u32 __iomem *) (dd->ipath_pio2kbase +
+				       i * dd->ipath_palign);
+	else
+		buf = (u32 __iomem *)
+			(dd->ipath_pio4kbase +
+			 (i - dd->ipath_piobcnt2k) * dd->ipath_4kalign);
+	ipath_cdbg(VERBOSE, "Return piobuf%u %uk @ %p\n",
+		   i, (i < dd->ipath_piobcnt2k) ? 2 : 4, buf);
+	if (pbufnum)
+		*pbufnum = i;
+
+bail:
+	return buf;
+}
+
+/**
+ * ipath_create_rcvhdrq - create a receive header queue
+ * @dd: the infinipath device
+ * @pd: the port data
+ *
+ * this *must* be physically contiguous memory, and for now,
+ * that limits it to what kmalloc can do.
+ */
+int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+			 struct ipath_portdata *pd)
+{
+	int ret = 0, amt;
+
+	amt = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+		    sizeof(u32), PAGE_SIZE);
+	if (!pd->port_rcvhdrq) {
+		/*
+		 * not using REPEAT isn't viable; at 128KB, we can easily
+		 * fail this.  The problem with REPEAT is we can block here
+		 * "forever".  There isn't an inbetween, unfortunately.  We
+		 * could reduce the risk by never freeing the rcvhdrq except
+		 * at unload, but even then, the first time a port is used,
+		 * we could delay for some time...
+		 */
+		gfp_t gfp_flags = GFP_USER | __GFP_COMP;
+
+		pd->port_rcvhdrq = dma_alloc_coherent(
+			&dd->pcidev->dev, amt, &pd->port_rcvhdrq_phys,
+			gfp_flags);
+
+		if (!pd->port_rcvhdrq) {
+			ipath_dev_err(dd, "attempt to allocate %d bytes "
+				      "for port %u rcvhdrq failed\n",
+				      amt, pd->port_port);
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		pd->port_rcvhdrq_size = amt;
+
+		ipath_cdbg(VERBOSE, "%d pages at %p (phys %lx) size=%lu "
+			   "for port %u rcvhdr Q\n",
+			   amt >> PAGE_SHIFT, pd->port_rcvhdrq,
+			   (unsigned long) pd->port_rcvhdrq_phys,
+			   (unsigned long) pd->port_rcvhdrq_size,
+			   pd->port_port);
+	} else {
+		/*
+		 * clear for security, sanity, and/or debugging, each
+		 * time we reuse
+		 */
+		memset(pd->port_rcvhdrq, 0, amt);
+	}
+
+	/*
+	 * tell chip each time we init it, even if we are re-using previous
+	 * memory (we zero it at process close)
+	 */
+	ipath_cdbg(VERBOSE, "writing port %d rcvhdraddr as %lx\n",
+		   pd->port_port, (unsigned long) pd->port_rcvhdrq_phys);
+	ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+			      pd->port_port, pd->port_rcvhdrq_phys);
+
+	ret = 0;
+bail:
+	return ret;
+}
+
+int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
+			   u64 bits_to_wait_for, u64 * valp)
+{
+	unsigned long timeout;
+	u64 lastval, val;
+	int ret;
+
+	lastval = ipath_read_kreg64(dd, reg_id);
+	/* wait a ridiculously long time */
+	timeout = jiffies + msecs_to_jiffies(5);
+	do {
+		val = ipath_read_kreg64(dd, reg_id);
+		/* set so they have something, even on failures. */
+		*valp = val;
+		if ((val & bits_to_wait_for) == bits_to_wait_for) {
+			ret = 0;
+			break;
+		}
+		if (val != lastval)
+			ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
+				   "waiting for %llx bits\n",
+				   (unsigned long long) lastval,
+				   (unsigned long long) val,
+				   (unsigned long long) bits_to_wait_for);
+		cond_resched();
+		if (time_after(jiffies, timeout)) {
+			ipath_dbg("Didn't get bits %llx in register 0x%x, "
+				  "got %llx\n",
+				  (unsigned long long) bits_to_wait_for,
+				  reg_id, (unsigned long long) *valp);
+			ret = -ENODEV;
+			break;
+		}
+	} while (1);
+
+	return ret;
+}
+
+/**
+ * ipath_waitfor_mdio_cmdready - wait for last command to complete
+ * @dd: the infinipath device
+ *
+ * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
+ * away indicating the last command has completed.  It doesn't return data
+ */
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
+{
+	unsigned long timeout;
+	u64 val;
+	int ret;
+
+	/* wait a ridiculously long time */
+	timeout = jiffies + msecs_to_jiffies(5);
+	do {
+		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
+		if (!(val & IPATH_MDIO_CMDVALID)) {
+			ret = 0;
+			break;
+		}
+		cond_resched();
+		if (time_after(jiffies, timeout)) {
+			ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
+				  (unsigned long long) val);
+			ret = -ENODEV;
+			break;
+		}
+	} while (1);
+
+	return ret;
+}
+
+void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
+{
+	static const char *what[4] = {
+		[0] = "DOWN",
+		[INFINIPATH_IBCC_LINKCMD_INIT] = "INIT",
+		[INFINIPATH_IBCC_LINKCMD_ARMED] = "ARMED",
+		[INFINIPATH_IBCC_LINKCMD_ACTIVE] = "ACTIVE"
+	};
+	ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate "
+		   "is %s\n", dd->ipath_unit,
+		   what[(which >> INFINIPATH_IBCC_LINKCMD_SHIFT) &
+			INFINIPATH_IBCC_LINKCMD_MASK],
+		   ipath_ibcstatus_str[
+			   (ipath_read_kreg64
+			    (dd, dd->ipath_kregs->kr_ibcstatus) >>
+			    INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+			   INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+			 dd->ipath_ibcctrl | which);
+}
+
+/**
+ * ipath_read_kreg64_port - read a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to read
+ * @port: the port containing the register
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+u64 ipath_read_kreg64_port(const struct ipath_devdata *dd, ipath_kreg regno,
+			   unsigned port)
+{
+	u16 where;
+
+	if (port < dd->ipath_portcnt &&
+	    (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+	     regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+		where = regno + port;
+	else
+		where = -1;
+
+	return ipath_read_kreg64(dd, where);
+}
+
+/**
+ * ipath_write_kreg_port - write a device's per-port 64-bit kernel register
+ * @dd: the infinipath device
+ * @regno: the register number to write
+ * @port: the port containing the register
+ * @value: the value to write
+ *
+ * Registers that vary with the chip implementation constants (port)
+ * use this routine.
+ */
+void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
+			  unsigned port, u64 value)
+{
+	u16 where;
+
+	if (port < dd->ipath_portcnt &&
+	    (regno == dd->ipath_kregs->kr_rcvhdraddr ||
+	     regno == dd->ipath_kregs->kr_rcvhdrtailaddr))
+		where = regno + port;
+	else
+		where = -1;
+
+	ipath_write_kreg(dd, where, value);
+}
+
+/**
+ * ipath_shutdown_device - shut down a device
+ * @dd: the infinipath device
+ *
+ * This is called to make the device quiet when we are about to
+ * unload the driver, and also when the device is administratively
+ * disabled.   It does not free any data structures.
+ * Everything it does has to be setup again by ipath_init_chip(dd,1)
+ */
+void ipath_shutdown_device(struct ipath_devdata *dd)
+{
+	u64 val;
+
+	ipath_dbg("Shutting down the device\n");
+
+	dd->ipath_flags |= IPATH_LINKUNK;
+	dd->ipath_flags &= ~(IPATH_INITTED | IPATH_LINKDOWN |
+			     IPATH_LINKINIT | IPATH_LINKARMED |
+			     IPATH_LINKACTIVE);
+	*dd->ipath_statusp &= ~(IPATH_STATUS_IB_CONF |
+				IPATH_STATUS_IB_READY);
+
+	/* mask interrupts, but not errors */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+
+	dd->ipath_rcvctrl = 0;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+	/*
+	 * gracefully stop all sends allowing any in progress to trickle out
+	 * first.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
+	/* flush it */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	/*
+	 * enough for anything that's going to trickle out to have actually
+	 * done so.
+	 */
+	udelay(5);
+
+	/*
+	 * abort any armed or launched PIO buffers that didn't go. (self
+	 * clearing).  Will cause any packet currently being transmitted to
+	 * go out with an EBP, and may also cause a short packet error on
+	 * the receiver.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 INFINIPATH_S_ABORT);
+
+	ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+			    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+
+	/*
+	 * we are shutting down, so tell the layered driver.  We don't do
+	 * this on just a link state change, much like ethernet, a cable
+	 * unplug, etc. doesn't change driver state
+	 */
+	ipath_layer_intr(dd, IPATH_LAYER_INT_IF_DOWN);
+
+	/* disable IBC */
+	dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+			 dd->ipath_control);
+
+	/*
+	 * clear SerdesEnable and turn the leds off; do this here because
+	 * we are unloading, so don't count on interrupts to move along
+	 * Turn the LEDs off explictly for the same reason.
+	 */
+	dd->ipath_f_quiet_serdes(dd);
+	dd->ipath_f_setextled(dd, 0, 0);
+
+	if (dd->ipath_stats_timer_active) {
+		del_timer_sync(&dd->ipath_stats_timer);
+		dd->ipath_stats_timer_active = 0;
+	}
+
+	/*
+	 * clear all interrupts and errors, so that the next time the driver
+	 * is loaded or device is enabled, we know that whatever is set
+	 * happened while we were unloaded
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+			 ~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+}
+
+/**
+ * ipath_free_pddata - free a port's allocated data
+ * @dd: the infinipath device
+ * @port: the port
+ * @freehdrq: free the port data structure if true
+ *
+ * when closing, free up any allocated data for a port, if the
+ * reference count goes to zero
+ * Note: this also optionally frees the portdata itself!
+ * Any changes here have to be matched up with the reinit case
+ * of ipath_init_chip(), which calls this routine on reinit after reset.
+ */
+void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq)
+{
+	struct ipath_portdata *pd = dd->ipath_pd[port];
+
+	if (!pd)
+		return;
+	if (freehdrq)
+		/*
+		 * only clear and free portdata if we are going to also
+		 * release the hdrq, otherwise we leak the hdrq on each
+		 * open/close cycle
+		 */
+		dd->ipath_pd[port] = NULL;
+	if (freehdrq && pd->port_rcvhdrq) {
+		ipath_cdbg(VERBOSE, "free closed port %d rcvhdrq @ %p "
+			   "(size=%lu)\n", pd->port_port, pd->port_rcvhdrq,
+			   (unsigned long) pd->port_rcvhdrq_size);
+		dma_free_coherent(&dd->pcidev->dev, pd->port_rcvhdrq_size,
+				  pd->port_rcvhdrq, pd->port_rcvhdrq_phys);
+		pd->port_rcvhdrq = NULL;
+	}
+	if (port && pd->port_rcvegrbuf) {
+		/* always free this */
+		if (pd->port_rcvegrbuf) {
+			unsigned e;
+
+			for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+				void *base = pd->port_rcvegrbuf[e];
+				size_t size = pd->port_rcvegrbuf_size;
+
+				ipath_cdbg(VERBOSE, "egrbuf free(%p, %lu), "
+					   "chunk %u/%u\n", base,
+					   (unsigned long) size,
+					   e, pd->port_rcvegrbuf_chunks);
+				dma_free_coherent(
+					&dd->pcidev->dev, size, base,
+					pd->port_rcvegrbuf_phys[e]);
+			}
+			vfree(pd->port_rcvegrbuf);
+			pd->port_rcvegrbuf = NULL;
+			vfree(pd->port_rcvegrbuf_phys);
+			pd->port_rcvegrbuf_phys = NULL;
+		}
+		pd->port_rcvegrbuf_chunks = 0;
+	} else if (port == 0 && dd->ipath_port0_skbs) {
+		unsigned e;
+		struct sk_buff **skbs = dd->ipath_port0_skbs;
+
+		dd->ipath_port0_skbs = NULL;
+		ipath_cdbg(VERBOSE, "free closed port %d ipath_port0_skbs "
+			   "@ %p\n", pd->port_port, skbs);
+		for (e = 0; e < dd->ipath_rcvegrcnt; e++)
+			if (skbs[e])
+				dev_kfree_skb(skbs[e]);
+		vfree(skbs);
+	}
+	if (freehdrq) {
+		kfree(pd->port_tid_pg_list);
+		kfree(pd);
+	}
+}
+
+static int __init infinipath_init(void)
+{
+	int ret;
+
+	ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ipath_core_version);
+
+	/*
+	 * These must be called before the driver is registered with
+	 * the PCI subsystem.
+	 */
+	idr_init(&unit_table);
+	if (!idr_pre_get(&unit_table, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	ret = pci_register_driver(&ipath_driver);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Unable to register driver: error %d\n", -ret);
+		goto bail_unit;
+	}
+
+	ret = ipath_driver_create_group(&ipath_driver.driver);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create driver "
+		       "sysfs entries: error %d\n", -ret);
+		goto bail_pci;
+	}
+
+	ret = ipath_init_ipathfs();
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
+		       "ipathfs: error %d\n", -ret);
+		goto bail_group;
+	}
+
+	goto bail;
+
+bail_group:
+	ipath_driver_remove_group(&ipath_driver.driver);
+
+bail_pci:
+	pci_unregister_driver(&ipath_driver);
+
+bail_unit:
+	idr_destroy(&unit_table);
+
+bail:
+	return ret;
+}
+
+static void cleanup_device(struct ipath_devdata *dd)
+{
+	int port;
+
+	ipath_shutdown_device(dd);
+
+	if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) {
+		/* can't do anything more with chip; needs re-init */
+		*dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT;
+		if (dd->ipath_kregbase) {
+			/*
+			 * if we haven't already cleaned up before these are
+			 * to ensure any register reads/writes "fail" until
+			 * re-init
+			 */
+			dd->ipath_kregbase = NULL;
+			dd->ipath_kregvirt = NULL;
+			dd->ipath_uregbase = 0;
+			dd->ipath_sregbase = 0;
+			dd->ipath_cregbase = 0;
+			dd->ipath_kregsize = 0;
+		}
+		ipath_disable_wc(dd);
+	}
+
+	if (dd->ipath_pioavailregs_dma) {
+		dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
+				  (void *) dd->ipath_pioavailregs_dma,
+				  dd->ipath_pioavailregs_phys);
+		dd->ipath_pioavailregs_dma = NULL;
+	}
+
+	if (dd->ipath_pageshadow) {
+		struct page **tmpp = dd->ipath_pageshadow;
+		int i, cnt = 0;
+
+		ipath_cdbg(VERBOSE, "Unlocking any expTID pages still "
+			   "locked\n");
+		for (port = 0; port < dd->ipath_cfgports; port++) {
+			int port_tidbase = port * dd->ipath_rcvtidcnt;
+			int maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+			for (i = port_tidbase; i < maxtid; i++) {
+				if (!tmpp[i])
+					continue;
+				ipath_release_user_pages(&tmpp[i], 1);
+				tmpp[i] = NULL;
+				cnt++;
+			}
+		}
+		if (cnt) {
+			ipath_stats.sps_pageunlocks += cnt;
+			ipath_cdbg(VERBOSE, "There were still %u expTID "
+				   "entries locked\n", cnt);
+		}
+		if (ipath_stats.sps_pagelocks ||
+		    ipath_stats.sps_pageunlocks)
+			ipath_cdbg(VERBOSE, "%llu pages locked, %llu "
+				   "unlocked via ipath_m{un}lock\n",
+				   (unsigned long long)
+				   ipath_stats.sps_pagelocks,
+				   (unsigned long long)
+				   ipath_stats.sps_pageunlocks);
+
+		ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n",
+			   dd->ipath_pageshadow);
+		vfree(dd->ipath_pageshadow);
+		dd->ipath_pageshadow = NULL;
+	}
+
+	/*
+	 * free any resources still in use (usually just kernel ports)
+	 * at unload
+	 */
+	for (port = 0; port < dd->ipath_cfgports; port++)
+		ipath_free_pddata(dd, port, 1);
+	kfree(dd->ipath_pd);
+	/*
+	 * debuggability, in case some cleanup path tries to use it
+	 * after this
+	 */
+	dd->ipath_pd = NULL;
+}
+
+static void __exit infinipath_cleanup(void)
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+
+	ipath_exit_ipathfs();
+
+	ipath_driver_remove_group(&ipath_driver.driver);
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	/*
+	 * turn off rcv, send, and interrupts for all ports, all drivers
+	 * should also hard reset the chip here?
+	 * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs
+	 * for all versions of the driver, if they were allocated
+	 */
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+		if (dd->ipath_kregbase)
+			cleanup_device(dd);
+
+		if (dd->pcidev) {
+			if (dd->pcidev->irq) {
+				ipath_cdbg(VERBOSE,
+					   "unit %u free_irq of irq %x\n",
+					   dd->ipath_unit, dd->pcidev->irq);
+				free_irq(dd->pcidev->irq, dd);
+			} else
+				ipath_dbg("irq is 0, not doing free_irq "
+					  "for unit %u\n", dd->ipath_unit);
+			dd->pcidev = NULL;
+		}
+
+		/*
+		 * we check for NULL here, because it's outside the kregbase
+		 * check, and we need to call it after the free_irq.  Thus
+		 * it's possible that the function pointers were never
+		 * initialized.
+		 */
+		if (dd->ipath_f_cleanup)
+			/* clean up chip-specific stuff */
+			dd->ipath_f_cleanup(dd);
+
+		spin_lock_irqsave(&ipath_devs_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
+	pci_unregister_driver(&ipath_driver);
+
+	idr_destroy(&unit_table);
+}
+
+/**
+ * ipath_reset_device - reset the chip if possible
+ * @unit: the device to reset
+ *
+ * Whether or not reset is successful, we attempt to re-initialize the chip
+ * (that is, much like a driver unload/reload).  We clear the INITTED flag
+ * so that the various entry points will fail until we reinitialize.  For
+ * now, we only allow this if no user ports are open that use chip resources
+ */
+int ipath_reset_device(int unit)
+{
+	int ret, i;
+	struct ipath_devdata *dd = ipath_lookup(unit);
+
+	if (!dd) {
+		ret = -ENODEV;
+		goto bail;
+	}
+
+	dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
+
+	if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
+		dev_info(&dd->pcidev->dev, "Invalid unit number %u or "
+			 "not initialized or not present\n", unit);
+		ret = -ENXIO;
+		goto bail;
+	}
+
+	if (dd->ipath_pd)
+		for (i = 1; i < dd->ipath_portcnt; i++) {
+			if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) {
+				ipath_dbg("unit %u port %d is in use "
+					  "(PID %u cmd %s), can't reset\n",
+					  unit, i,
+					  dd->ipath_pd[i]->port_pid,
+					  dd->ipath_pd[i]->port_comm);
+				ret = -EBUSY;
+				goto bail;
+			}
+		}
+
+	dd->ipath_flags &= ~IPATH_INITTED;
+	ret = dd->ipath_f_reset(dd);
+	if (ret != 1)
+		ipath_dbg("reset was not successful\n");
+	ipath_dbg("Trying to reinitialize unit %u after reset attempt\n",
+		  unit);
+	ret = ipath_init_chip(dd, 1);
+	if (ret)
+		ipath_dev_err(dd, "Reinitialize unit %u after "
+			      "reset failed with %d\n", unit, ret);
+	else
+		dev_info(&dd->pcidev->dev, "Reinitialized unit %u after "
+			 "resetting\n", unit);
+
+bail:
+	return ret;
+}
+
+module_init(infinipath_init);
+module_exit(infinipath_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
new file mode 100644
index 0000000..f11a900e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+
+/*
+ * InfiniPath I2C driver for a serial eeprom.  This is not a generic
+ * I2C interface.  For a start, the device we're using (Atmel AT24C11)
+ * doesn't work like a regular I2C device.  It looks like one
+ * electrically, but not logically.  Normal I2C devices have a single
+ * 7-bit or 10-bit I2C address that they respond to.  Valid 7-bit
+ * addresses range from 0x03 to 0x77.  Addresses 0x00 to 0x02 and 0x78
+ * to 0x7F are special reserved addresses (e.g. 0x00 is the "general
+ * call" address.)  The Atmel device, on the other hand, responds to ALL
+ * 7-bit addresses.  It's designed to be the only device on a given I2C
+ * bus.  A 7-bit address corresponds to the memory address within the
+ * Atmel device itself.
+ *
+ * Also, the timing requirements mean more than simple software
+ * bitbanging, with readbacks from chip to ensure timing (simple udelay
+ * is not enough).
+ *
+ * This all means that accessing the device is specialized enough
+ * that using the standard kernel I2C bitbanging interface would be
+ * impossible.  For example, the core I2C eeprom driver expects to find
+ * a device at one or more of a limited set of addresses only.  It doesn't
+ * allow writing to an eeprom.  It also doesn't provide any means of
+ * accessing eeprom contents from within the kernel, only via sysfs.
+ */
+
+enum i2c_type {
+	i2c_line_scl = 0,
+	i2c_line_sda
+};
+
+enum i2c_state {
+	i2c_line_low = 0,
+	i2c_line_high
+};
+
+#define READ_CMD 1
+#define WRITE_CMD 0
+
+static int eeprom_init;
+
+/*
+ * The gpioval manipulation really should be protected by spinlocks
+ * or be converted to use atomic operations.
+ */
+
+/**
+ * i2c_gpio_set - set a GPIO line
+ * @dd: the infinipath device
+ * @line: the line to set
+ * @new_line_state: the state to set
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error.
+ */
+static int i2c_gpio_set(struct ipath_devdata *dd,
+			enum i2c_type line,
+			enum i2c_state new_line_state)
+{
+	u64 read_val, write_val, mask, *gpioval;
+
+	gpioval = &dd->ipath_gpio_out;
+	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
+	if (line == i2c_line_scl)
+		mask = ipath_gpio_scl;
+	else
+		mask = ipath_gpio_sda;
+
+	if (new_line_state == i2c_line_high)
+		/* tri-state the output rather than force high */
+		write_val = read_val & ~mask;
+	else
+		/* config line to be an output */
+		write_val = read_val | mask;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+	/* set high and verify */
+	if (new_line_state == i2c_line_high)
+		write_val = 0x1UL;
+	else
+		write_val = 0x0UL;
+
+	if (line == i2c_line_scl) {
+		write_val <<= ipath_gpio_scl_num;
+		*gpioval = *gpioval & ~(1UL << ipath_gpio_scl_num);
+		*gpioval |= write_val;
+	} else {
+		write_val <<= ipath_gpio_sda_num;
+		*gpioval = *gpioval & ~(1UL << ipath_gpio_sda_num);
+		*gpioval |= write_val;
+	}
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+
+	return 0;
+}
+
+/**
+ * i2c_gpio_get - get a GPIO line state
+ * @dd: the infinipath device
+ * @line: the line to get
+ * @curr_statep: where to put the line state
+ *
+ * Returns 0 if the line was set to the new state successfully, non-zero
+ * on error.  curr_state is not set on error.
+ */
+static int i2c_gpio_get(struct ipath_devdata *dd,
+			enum i2c_type line,
+			enum i2c_state *curr_statep)
+{
+	u64 read_val, write_val, mask;
+	int ret;
+
+	/* check args */
+	if (curr_statep == NULL) {
+		ret = 1;
+		goto bail;
+	}
+
+	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
+	/* config line to be an input */
+	if (line == i2c_line_scl)
+		mask = ipath_gpio_scl;
+	else
+		mask = ipath_gpio_sda;
+	write_val = read_val & ~mask;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+	read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+	if (read_val & mask)
+		*curr_statep = i2c_line_high;
+	else
+		*curr_statep = i2c_line_low;
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * i2c_wait_for_writes - wait for a write
+ * @dd: the infinipath device
+ *
+ * We use this instead of udelay directly, so we can make sure
+ * that previous register writes have been flushed all the way
+ * to the chip.  Since we are delaying anyway, the cost doesn't
+ * hurt, and makes the bit twiddling more regular
+ */
+static void i2c_wait_for_writes(struct ipath_devdata *dd)
+{
+	(void)ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
+}
+
+static void scl_out(struct ipath_devdata *dd, u8 bit)
+{
+	i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
+
+	i2c_wait_for_writes(dd);
+}
+
+static void sda_out(struct ipath_devdata *dd, u8 bit)
+{
+	i2c_gpio_set(dd, i2c_line_sda, bit ? i2c_line_high : i2c_line_low);
+
+	i2c_wait_for_writes(dd);
+}
+
+static u8 sda_in(struct ipath_devdata *dd, int wait)
+{
+	enum i2c_state bit;
+
+	if (i2c_gpio_get(dd, i2c_line_sda, &bit))
+		ipath_dbg("get bit failed!\n");
+
+	if (wait)
+		i2c_wait_for_writes(dd);
+
+	return bit == i2c_line_high ? 1U : 0;
+}
+
+/**
+ * i2c_ackrcv - see if ack following write is true
+ * @dd: the infinipath device
+ */
+static int i2c_ackrcv(struct ipath_devdata *dd)
+{
+	u8 ack_received;
+
+	/* AT ENTRY SCL = LOW */
+	/* change direction, ignore data */
+	ack_received = sda_in(dd, 1);
+	scl_out(dd, i2c_line_high);
+	ack_received = sda_in(dd, 1) == 0;
+	scl_out(dd, i2c_line_low);
+	return ack_received;
+}
+
+/**
+ * wr_byte - write a byte, one bit at a time
+ * @dd: the infinipath device
+ * @data: the byte to write
+ *
+ * Returns 0 if we got the following ack, otherwise 1
+ */
+static int wr_byte(struct ipath_devdata *dd, u8 data)
+{
+	int bit_cntr;
+	u8 bit;
+
+	for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {
+		bit = (data >> bit_cntr) & 1;
+		sda_out(dd, bit);
+		scl_out(dd, i2c_line_high);
+		scl_out(dd, i2c_line_low);
+	}
+	return (!i2c_ackrcv(dd)) ? 1 : 0;
+}
+
+static void send_ack(struct ipath_devdata *dd)
+{
+	sda_out(dd, i2c_line_low);
+	scl_out(dd, i2c_line_high);
+	scl_out(dd, i2c_line_low);
+	sda_out(dd, i2c_line_high);
+}
+
+/**
+ * i2c_startcmd - transmit the start condition, followed by address/cmd
+ * @dd: the infinipath device
+ * @offset_dir: direction byte
+ *
+ *      (both clock/data high, clock high, data low while clock is high)
+ */
+static int i2c_startcmd(struct ipath_devdata *dd, u8 offset_dir)
+{
+	int res;
+
+	/* issue start sequence */
+	sda_out(dd, i2c_line_high);
+	scl_out(dd, i2c_line_high);
+	sda_out(dd, i2c_line_low);
+	scl_out(dd, i2c_line_low);
+
+	/* issue length and direction byte */
+	res = wr_byte(dd, offset_dir);
+
+	if (res)
+		ipath_cdbg(VERBOSE, "No ack to complete start\n");
+
+	return res;
+}
+
+/**
+ * stop_cmd - transmit the stop condition
+ * @dd: the infinipath device
+ *
+ * (both clock/data low, clock high, data high while clock is high)
+ */
+static void stop_cmd(struct ipath_devdata *dd)
+{
+	scl_out(dd, i2c_line_low);
+	sda_out(dd, i2c_line_low);
+	scl_out(dd, i2c_line_high);
+	sda_out(dd, i2c_line_high);
+	udelay(2);
+}
+
+/**
+ * eeprom_reset - reset I2C communication
+ * @dd: the infinipath device
+ */
+
+static int eeprom_reset(struct ipath_devdata *dd)
+{
+	int clock_cycles_left = 9;
+	u64 *gpioval = &dd->ipath_gpio_out;
+	int ret;
+
+	eeprom_init = 1;
+	*gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+	ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
+		   "is %llx\n", (unsigned long long) *gpioval);
+
+	/*
+	 * This is to get the i2c into a known state, by first going low,
+	 * then tristate sda (and then tristate scl as first thing
+	 * in loop)
+	 */
+	scl_out(dd, i2c_line_low);
+	sda_out(dd, i2c_line_high);
+
+	while (clock_cycles_left--) {
+		scl_out(dd, i2c_line_high);
+
+		if (sda_in(dd, 0)) {
+			sda_out(dd, i2c_line_low);
+			scl_out(dd, i2c_line_low);
+			ret = 0;
+			goto bail;
+		}
+
+		scl_out(dd, i2c_line_low);
+	}
+
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_eeprom_read - receives bytes from the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: address to read from
+ * @buffer: where to store result
+ * @len: number of bytes to receive
+ */
+
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+		      void *buffer, int len)
+{
+	/* compiler complains unless initialized */
+	u8 single_byte = 0;
+	int bit_cntr;
+	int ret;
+
+	if (!eeprom_init)
+		eeprom_reset(dd);
+
+	eeprom_offset = (eeprom_offset << 1) | READ_CMD;
+
+	if (i2c_startcmd(dd, eeprom_offset)) {
+		ipath_dbg("Failed startcmd\n");
+		stop_cmd(dd);
+		ret = 1;
+		goto bail;
+	}
+
+	/*
+	 * eeprom keeps clocking data out as long as we ack, automatically
+	 * incrementing the address.
+	 */
+	while (len-- > 0) {
+		/* get data */
+		single_byte = 0;
+		for (bit_cntr = 8; bit_cntr; bit_cntr--) {
+			u8 bit;
+			scl_out(dd, i2c_line_high);
+			bit = sda_in(dd, 0);
+			single_byte |= bit << (bit_cntr - 1);
+			scl_out(dd, i2c_line_low);
+		}
+
+		/* send ack if not the last byte */
+		if (len)
+			send_ack(dd);
+
+		*((u8 *) buffer) = single_byte;
+		buffer++;
+	}
+
+	stop_cmd(dd);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_eeprom_write - writes data to the eeprom via I2C
+ * @dd: the infinipath device
+ * @eeprom_offset: where to place data
+ * @buffer: data to write
+ * @len: number of bytes to write
+ */
+int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+		       const void *buffer, int len)
+{
+	u8 single_byte;
+	int sub_len;
+	const u8 *bp = buffer;
+	int max_wait_time, i;
+	int ret;
+
+	if (!eeprom_init)
+		eeprom_reset(dd);
+
+	while (len > 0) {
+		if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) {
+			ipath_dbg("Failed to start cmd offset %u\n",
+				  eeprom_offset);
+			goto failed_write;
+		}
+
+		sub_len = min(len, 4);
+		eeprom_offset += sub_len;
+		len -= sub_len;
+
+		for (i = 0; i < sub_len; i++) {
+			if (wr_byte(dd, *bp++)) {
+				ipath_dbg("no ack after byte %u/%u (%u "
+					  "total remain)\n", i, sub_len,
+					  len + sub_len - i);
+				goto failed_write;
+			}
+		}
+
+		stop_cmd(dd);
+
+		/*
+		 * wait for write complete by waiting for a successful
+		 * read (the chip replies with a zero after the write
+		 * cmd completes, and before it writes to the eeprom.
+		 * The startcmd for the read will fail the ack until
+		 * the writes have completed.   We do this inline to avoid
+		 * the debug prints that are in the real read routine
+		 * if the startcmd fails.
+		 */
+		max_wait_time = 100;
+		while (i2c_startcmd(dd, READ_CMD)) {
+			stop_cmd(dd);
+			if (!--max_wait_time) {
+				ipath_dbg("Did not get successful read to "
+					  "complete write\n");
+				goto failed_write;
+			}
+		}
+		/* now read the zero byte */
+		for (i = single_byte = 0; i < 8; i++) {
+			u8 bit;
+			scl_out(dd, i2c_line_high);
+			bit = sda_in(dd, 0);
+			scl_out(dd, i2c_line_low);
+			single_byte <<= 1;
+			single_byte |= bit;
+		}
+		stop_cmd(dd);
+	}
+
+	ret = 0;
+	goto bail;
+
+failed_write:
+	stop_cmd(dd);
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+static u8 flash_csum(struct ipath_flash *ifp, int adjust)
+{
+	u8 *ip = (u8 *) ifp;
+	u8 csum = 0, len;
+
+	for (len = 0; len < ifp->if_length; len++)
+		csum += *ip++;
+	csum -= ifp->if_csum;
+	csum = ~csum;
+	if (adjust)
+		ifp->if_csum = csum;
+
+	return csum;
+}
+
+/**
+ * ipath_get_guid - get the GUID from the i2c device
+ * @dd: the infinipath device
+ *
+ * When we add the multi-chip support, we will probably have to add
+ * the ability to use the number of guids field, and get the guid from
+ * the first chip's flash, to use for all of them.
+ */
+void ipath_get_guid(struct ipath_devdata *dd)
+{
+	void *buf;
+	struct ipath_flash *ifp;
+	__be64 guid;
+	int len;
+	u8 csum, *bguid;
+	int t = dd->ipath_unit;
+	struct ipath_devdata *dd0 = ipath_lookup(0);
+
+	if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
+		u8 *bguid, oguid;
+		dd->ipath_guid = dd0->ipath_guid;
+		bguid = (u8 *) & dd->ipath_guid;
+
+		oguid = bguid[7];
+		bguid[7] += t;
+		if (oguid > bguid[7]) {
+			if (bguid[6] == 0xff) {
+				if (bguid[5] == 0xff) {
+					ipath_dev_err(
+						dd,
+						"Can't set %s GUID from "
+						"base, wraps to OUI!\n",
+						ipath_get_unit_name(t));
+					dd->ipath_guid = 0;
+					goto bail;
+				}
+				bguid[5]++;
+			}
+			bguid[6]++;
+		}
+		dd->ipath_nguid = 1;
+
+		ipath_dbg("nguid %u, so adding %u to device 0 guid, "
+			  "for %llx\n",
+			  dd0->ipath_nguid, t,
+			  (unsigned long long) be64_to_cpu(dd->ipath_guid));
+		goto bail;
+	}
+
+	len = offsetof(struct ipath_flash, if_future);
+	buf = vmalloc(len);
+	if (!buf) {
+		ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+			      "bytes from eeprom for GUID\n", len);
+		goto bail;
+	}
+
+	if (ipath_eeprom_read(dd, 0, buf, len)) {
+		ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
+		goto done;
+	}
+	ifp = (struct ipath_flash *)buf;
+
+	csum = flash_csum(ifp, 0);
+	if (csum != ifp->if_csum) {
+		dev_info(&dd->pcidev->dev, "Bad I2C flash checksum: "
+			 "0x%x, not 0x%x\n", csum, ifp->if_csum);
+		goto done;
+	}
+	if (*(__be64 *) ifp->if_guid == 0ULL ||
+	    *(__be64 *) ifp->if_guid == __constant_cpu_to_be64(-1LL)) {
+		ipath_dev_err(dd, "Invalid GUID %llx from flash; "
+			      "ignoring\n",
+			      *(unsigned long long *) ifp->if_guid);
+		/* don't allow GUID if all 0 or all 1's */
+		goto done;
+	}
+
+	/* complain, but allow it */
+	if (*(u64 *) ifp->if_guid == 0x100007511000000ULL)
+		dev_info(&dd->pcidev->dev, "Warning, GUID %llx is "
+			 "default, probably not correct!\n",
+			 *(unsigned long long *) ifp->if_guid);
+
+	bguid = ifp->if_guid;
+	if (!bguid[0] && !bguid[1] && !bguid[2]) {
+		/* original incorrect GUID format in flash; fix in
+		 * core copy, by shifting up 2 octets; don't need to
+		 * change top octet, since both it and shifted are
+		 * 0.. */
+		bguid[1] = bguid[3];
+		bguid[2] = bguid[4];
+		bguid[3] = bguid[4] = 0;
+		guid = *(__be64 *) ifp->if_guid;
+		ipath_cdbg(VERBOSE, "Old GUID format in flash, top 3 zero, "
+			   "shifting 2 octets\n");
+	} else
+		guid = *(__be64 *) ifp->if_guid;
+	dd->ipath_guid = guid;
+	dd->ipath_nguid = ifp->if_numguid;
+	memcpy(dd->ipath_serial, ifp->if_serial,
+	       sizeof(ifp->if_serial));
+	ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
+		   (unsigned long long) be64_to_cpu(dd->ipath_guid));
+
+done:
+	vfree(buf);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
new file mode 100644
index 0000000..c347191
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -0,0 +1,1910 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/swap.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+static int ipath_open(struct inode *, struct file *);
+static int ipath_close(struct inode *, struct file *);
+static ssize_t ipath_write(struct file *, const char __user *, size_t,
+			   loff_t *);
+static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
+static int ipath_mmap(struct file *, struct vm_area_struct *);
+
+static struct file_operations ipath_file_ops = {
+	.owner = THIS_MODULE,
+	.write = ipath_write,
+	.open = ipath_open,
+	.release = ipath_close,
+	.poll = ipath_poll,
+	.mmap = ipath_mmap
+};
+
+static int ipath_get_base_info(struct ipath_portdata *pd,
+			       void __user *ubase, size_t ubase_size)
+{
+	int ret = 0;
+	struct ipath_base_info *kinfo = NULL;
+	struct ipath_devdata *dd = pd->port_dd;
+
+	if (ubase_size < sizeof(*kinfo)) {
+		ipath_cdbg(PROC,
+			   "Base size %lu, need %lu (version mismatch?)\n",
+			   (unsigned long) ubase_size,
+			   (unsigned long) sizeof(*kinfo));
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	kinfo = kzalloc(sizeof(*kinfo), GFP_KERNEL);
+	if (kinfo == NULL) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	ret = dd->ipath_f_get_base_info(pd, kinfo);
+	if (ret < 0)
+		goto bail;
+
+	kinfo->spi_rcvhdr_cnt = dd->ipath_rcvhdrcnt;
+	kinfo->spi_rcvhdrent_size = dd->ipath_rcvhdrentsize;
+	kinfo->spi_tidegrcnt = dd->ipath_rcvegrcnt;
+	kinfo->spi_rcv_egrbufsize = dd->ipath_rcvegrbufsize;
+	/*
+	 * have to mmap whole thing
+	 */
+	kinfo->spi_rcv_egrbuftotlen =
+		pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size;
+	kinfo->spi_rcv_egrperchunk = pd->port_rcvegrbufs_perchunk;
+	kinfo->spi_rcv_egrchunksize = kinfo->spi_rcv_egrbuftotlen /
+		pd->port_rcvegrbuf_chunks;
+	kinfo->spi_tidcnt = dd->ipath_rcvtidcnt;
+	/*
+	 * for this use, may be ipath_cfgports summed over all chips that
+	 * are are configured and present
+	 */
+	kinfo->spi_nports = dd->ipath_cfgports;
+	/* unit (chip/board) our port is on */
+	kinfo->spi_unit = dd->ipath_unit;
+	/* for now, only a single page */
+	kinfo->spi_tid_maxsize = PAGE_SIZE;
+
+	/*
+	 * Doing this per port, and based on the skip value, etc.  This has
+	 * to be the actual buffer size, since the protocol code treats it
+	 * as an array.
+	 *
+	 * These have to be set to user addresses in the user code via mmap.
+	 * These values are used on return to user code for the mmap target
+	 * addresses only.  For 32 bit, same 44 bit address problem, so use
+	 * the physical address, not virtual.  Before 2.6.11, using the
+	 * page_address() macro worked, but in 2.6.11, even that returns the
+	 * full 64 bit address (upper bits all 1's).  So far, using the
+	 * physical addresses (or chip offsets, for chip mapping) works, but
+	 * no doubt some future kernel release will chang that, and we'll be
+	 * on to yet another method of dealing with this
+	 */
+	kinfo->spi_rcvhdr_base = (u64) pd->port_rcvhdrq_phys;
+	kinfo->spi_rcv_egrbufs = (u64) pd->port_rcvegr_phys;
+	kinfo->spi_pioavailaddr = (u64) dd->ipath_pioavailregs_phys;
+	kinfo->spi_status = (u64) kinfo->spi_pioavailaddr +
+		(void *) dd->ipath_statusp -
+		(void *) dd->ipath_pioavailregs_dma;
+	kinfo->spi_piobufbase = (u64) pd->port_piobufs;
+	kinfo->__spi_uregbase =
+		dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+	kinfo->spi_pioindex = dd->ipath_pbufsport * (pd->port_port - 1);
+	kinfo->spi_piocnt = dd->ipath_pbufsport;
+	kinfo->spi_pioalign = dd->ipath_palign;
+
+	kinfo->spi_qpair = IPATH_KD_QP;
+	kinfo->spi_piosize = dd->ipath_ibmaxlen;
+	kinfo->spi_mtu = dd->ipath_ibmaxlen;	/* maxlen, not ibmtu */
+	kinfo->spi_port = pd->port_port;
+	kinfo->spi_sw_version = IPATH_USER_SWVERSION;
+	kinfo->spi_hw_version = dd->ipath_revision;
+
+	if (copy_to_user(ubase, kinfo, sizeof(*kinfo)))
+		ret = -EFAULT;
+
+bail:
+	kfree(kinfo);
+	return ret;
+}
+
+/**
+ * ipath_tid_update - update a port TID
+ * @pd: the port
+ * @ti: the TID information
+ *
+ * The new implementation as of Oct 2004 is that the driver assigns
+ * the tid and returns it to the caller.   To make it easier to
+ * catch bugs, and to reduce search time, we keep a cursor for
+ * each port, walking the shadow tid array to find one that's not
+ * in use.
+ *
+ * For now, if we can't allocate the full list, we fail, although
+ * in the long run, we'll allocate as many as we can, and the
+ * caller will deal with that by trying the remaining pages later.
+ * That means that when we fail, we have to mark the tids as not in
+ * use again, in our shadow copy.
+ *
+ * It's up to the caller to free the tids when they are done.
+ * We'll unlock the pages as they free them.
+ *
+ * Also, right now we are locking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance.
+ */
+static int ipath_tid_update(struct ipath_portdata *pd,
+			    const struct ipath_tid_info *ti)
+{
+	int ret = 0, ntids;
+	u32 tid, porttid, cnt, i, tidcnt;
+	u16 *tidlist;
+	struct ipath_devdata *dd = pd->port_dd;
+	u64 physaddr;
+	unsigned long vaddr;
+	u64 __iomem *tidbase;
+	unsigned long tidmap[8];
+	struct page **pagep = NULL;
+
+	if (!dd->ipath_pageshadow) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cnt = ti->tidcnt;
+	if (!cnt) {
+		ipath_dbg("After copyin, tidcnt 0, tidlist %llx\n",
+			  (unsigned long long) ti->tidlist);
+		/*
+		 * Should we treat as success?  likely a bug
+		 */
+		ret = -EFAULT;
+		goto done;
+	}
+	tidcnt = dd->ipath_rcvtidcnt;
+	if (cnt >= tidcnt) {
+		/* make sure it all fits in port_tid_pg_list */
+		dev_info(&dd->pcidev->dev, "Process tried to allocate %u "
+			 "TIDs, only trying max (%u)\n", cnt, tidcnt);
+		cnt = tidcnt;
+	}
+	pagep = (struct page **)pd->port_tid_pg_list;
+	tidlist = (u16 *) (&pagep[cnt]);
+
+	memset(tidmap, 0, sizeof(tidmap));
+	tid = pd->port_tidcursor;
+	/* before decrement; chip actual # */
+	porttid = pd->port_port * tidcnt;
+	ntids = tidcnt;
+	tidbase = (u64 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+				   dd->ipath_rcvtidbase +
+				   porttid * sizeof(*tidbase));
+
+	ipath_cdbg(VERBOSE, "Port%u %u tids, cursor %u, tidbase %p\n",
+		   pd->port_port, cnt, tid, tidbase);
+
+	/* virtual address of first page in transfer */
+	vaddr = ti->tidvaddr;
+	if (!access_ok(VERIFY_WRITE, (void __user *) vaddr,
+		       cnt * PAGE_SIZE)) {
+		ipath_dbg("Fail vaddr %p, %u pages, !access_ok\n",
+			  (void *)vaddr, cnt);
+		ret = -EFAULT;
+		goto done;
+	}
+	ret = ipath_get_user_pages(vaddr, cnt, pagep);
+	if (ret) {
+		if (ret == -EBUSY) {
+			ipath_dbg("Failed to lock addr %p, %u pages "
+				  "(already locked)\n",
+				  (void *) vaddr, cnt);
+			/*
+			 * for now, continue, and see what happens but with
+			 * the new implementation, this should never happen,
+			 * unless perhaps the user has mpin'ed the pages
+			 * themselves (something we need to test)
+			 */
+			ret = 0;
+		} else {
+			dev_info(&dd->pcidev->dev,
+				 "Failed to lock addr %p, %u pages: "
+				 "errno %d\n", (void *) vaddr, cnt, -ret);
+			goto done;
+		}
+	}
+	for (i = 0; i < cnt; i++, vaddr += PAGE_SIZE) {
+		for (; ntids--; tid++) {
+			if (tid == tidcnt)
+				tid = 0;
+			if (!dd->ipath_pageshadow[porttid + tid])
+				break;
+		}
+		if (ntids < 0) {
+			/*
+			 * oops, wrapped all the way through their TIDs,
+			 * and didn't have enough free; see comments at
+			 * start of routine
+			 */
+			ipath_dbg("Not enough free TIDs for %u pages "
+				  "(index %d), failing\n", cnt, i);
+			i--;	/* last tidlist[i] not filled in */
+			ret = -ENOMEM;
+			break;
+		}
+		tidlist[i] = tid;
+		ipath_cdbg(VERBOSE, "Updating idx %u to TID %u, "
+			   "vaddr %lx\n", i, tid, vaddr);
+		/* we "know" system pages and TID pages are same size */
+		dd->ipath_pageshadow[porttid + tid] = pagep[i];
+		/*
+		 * don't need atomic or it's overhead
+		 */
+		__set_bit(tid, tidmap);
+		physaddr = page_to_phys(pagep[i]);
+		ipath_stats.sps_pagelocks++;
+		ipath_cdbg(VERBOSE,
+			   "TID %u, vaddr %lx, physaddr %llx pgp %p\n",
+			   tid, vaddr, (unsigned long long) physaddr,
+			   pagep[i]);
+		dd->ipath_f_put_tid(dd, &tidbase[tid], 1, physaddr);
+		/*
+		 * don't check this tid in ipath_portshadow, since we
+		 * just filled it in; start with the next one.
+		 */
+		tid++;
+	}
+
+	if (ret) {
+		u32 limit;
+	cleanup:
+		/* jump here if copy out of updated info failed... */
+		ipath_dbg("After failure (ret=%d), undo %d of %d entries\n",
+			  -ret, i, cnt);
+		/* same code that's in ipath_free_tid() */
+		limit = sizeof(tidmap) * BITS_PER_BYTE;
+		if (limit > tidcnt)
+			/* just in case size changes in future */
+			limit = tidcnt;
+		tid = find_first_bit((const unsigned long *)tidmap, limit);
+		for (; tid < limit; tid++) {
+			if (!test_bit(tid, tidmap))
+				continue;
+			if (dd->ipath_pageshadow[porttid + tid]) {
+				ipath_cdbg(VERBOSE, "Freeing TID %u\n",
+					   tid);
+				dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+						    dd->ipath_tidinvalid);
+				dd->ipath_pageshadow[porttid + tid] = NULL;
+				ipath_stats.sps_pageunlocks++;
+			}
+		}
+		ipath_release_user_pages(pagep, cnt);
+	} else {
+		/*
+		 * Copy the updated array, with ipath_tid's filled in, back
+		 * to user.  Since we did the copy in already, this "should
+		 * never fail" If it does, we have to clean up...
+		 */
+		if (copy_to_user((void __user *)
+				 (unsigned long) ti->tidlist,
+				 tidlist, cnt * sizeof(*tidlist))) {
+			ret = -EFAULT;
+			goto cleanup;
+		}
+		if (copy_to_user((void __user *) (unsigned long) ti->tidmap,
+				 tidmap, sizeof tidmap)) {
+			ret = -EFAULT;
+			goto cleanup;
+		}
+		if (tid == tidcnt)
+			tid = 0;
+		pd->port_tidcursor = tid;
+	}
+
+done:
+	if (ret)
+		ipath_dbg("Failed to map %u TID pages, failing with %d\n",
+			  ti->tidcnt, -ret);
+	return ret;
+}
+
+/**
+ * ipath_tid_free - free a port TID
+ * @pd: the port
+ * @ti: the TID info
+ *
+ * right now we are unlocking one page at a time, but since
+ * the intended use of this routine is for a single group of
+ * virtually contiguous pages, that should change to improve
+ * performance.  We check that the TID is in range for this port
+ * but otherwise don't check validity; if user has an error and
+ * frees the wrong tid, it's only their own data that can thereby
+ * be corrupted.  We do check that the TID was in use, for sanity
+ * We always use our idea of the saved address, not the address that
+ * they pass in to us.
+ */
+
+static int ipath_tid_free(struct ipath_portdata *pd,
+			  const struct ipath_tid_info *ti)
+{
+	int ret = 0;
+	u32 tid, porttid, cnt, limit, tidcnt;
+	struct ipath_devdata *dd = pd->port_dd;
+	u64 __iomem *tidbase;
+	unsigned long tidmap[8];
+
+	if (!dd->ipath_pageshadow) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	if (copy_from_user(tidmap, (void __user *)(unsigned long)ti->tidmap,
+			   sizeof tidmap)) {
+		ret = -EFAULT;
+		goto done;
+	}
+
+	porttid = pd->port_port * dd->ipath_rcvtidcnt;
+	tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+				   dd->ipath_rcvtidbase +
+				   porttid * sizeof(*tidbase));
+
+	tidcnt = dd->ipath_rcvtidcnt;
+	limit = sizeof(tidmap) * BITS_PER_BYTE;
+	if (limit > tidcnt)
+		/* just in case size changes in future */
+		limit = tidcnt;
+	tid = find_first_bit(tidmap, limit);
+	ipath_cdbg(VERBOSE, "Port%u free %u tids; first bit (max=%d) "
+		   "set is %d, porttid %u\n", pd->port_port, ti->tidcnt,
+		   limit, tid, porttid);
+	for (cnt = 0; tid < limit; tid++) {
+		/*
+		 * small optimization; if we detect a run of 3 or so without
+		 * any set, use find_first_bit again.  That's mainly to
+		 * accelerate the case where we wrapped, so we have some at
+		 * the beginning, and some at the end, and a big gap
+		 * in the middle.
+		 */
+		if (!test_bit(tid, tidmap))
+			continue;
+		cnt++;
+		if (dd->ipath_pageshadow[porttid + tid]) {
+			ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
+				   pd->port_pid, tid);
+			dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+					    dd->ipath_tidinvalid);
+			ipath_release_user_pages(
+				&dd->ipath_pageshadow[porttid + tid], 1);
+			dd->ipath_pageshadow[porttid + tid] = NULL;
+			ipath_stats.sps_pageunlocks++;
+		} else
+			ipath_dbg("Unused tid %u, ignoring\n", tid);
+	}
+	if (cnt != ti->tidcnt)
+		ipath_dbg("passed in tidcnt %d, only %d bits set in map\n",
+			  ti->tidcnt, cnt);
+done:
+	if (ret)
+		ipath_dbg("Failed to unmap %u TID pages, failing with %d\n",
+			  ti->tidcnt, -ret);
+	return ret;
+}
+
+/**
+ * ipath_set_part_key - set a partition key
+ * @pd: the port
+ * @key: the key
+ *
+ * We can have up to 4 active at a time (other than the default, which is
+ * always allowed).  This is somewhat tricky, since multiple ports may set
+ * the same key, so we reference count them, and clean up at exit.  All 4
+ * partition keys are packed into a single infinipath register.  It's an
+ * error for a process to set the same pkey multiple times.  We provide no
+ * mechanism to de-allocate a pkey at this time, we may eventually need to
+ * do that.  I've used the atomic operations, and no locking, and only make
+ * a single pass through what's available.  This should be more than
+ * adequate for some time. I'll think about spinlocks or the like if and as
+ * it's necessary.
+ */
+static int ipath_set_part_key(struct ipath_portdata *pd, u16 key)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	int i, any = 0, pidx = -1;
+	u16 lkey = key & 0x7FFF;
+	int ret;
+
+	if (lkey == (IPS_DEFAULT_P_KEY & 0x7FFF)) {
+		/* nothing to do; this key always valid */
+		ret = 0;
+		goto bail;
+	}
+
+	ipath_cdbg(VERBOSE, "p%u try to set pkey %hx, current keys "
+		   "%hx:%x %hx:%x %hx:%x %hx:%x\n",
+		   pd->port_port, key, dd->ipath_pkeys[0],
+		   atomic_read(&dd->ipath_pkeyrefs[0]), dd->ipath_pkeys[1],
+		   atomic_read(&dd->ipath_pkeyrefs[1]), dd->ipath_pkeys[2],
+		   atomic_read(&dd->ipath_pkeyrefs[2]), dd->ipath_pkeys[3],
+		   atomic_read(&dd->ipath_pkeyrefs[3]));
+
+	if (!lkey) {
+		ipath_cdbg(PROC, "p%u tries to set key 0, not allowed\n",
+			   pd->port_port);
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	/*
+	 * Set the full membership bit, because it has to be
+	 * set in the register or the packet, and it seems
+	 * cleaner to set in the register than to force all
+	 * callers to set it. (see bug 4331)
+	 */
+	key |= 0x8000;
+
+	for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+		if (!pd->port_pkeys[i] && pidx == -1)
+			pidx = i;
+		if (pd->port_pkeys[i] == key) {
+			ipath_cdbg(VERBOSE, "p%u tries to set same pkey "
+				   "(%x) more than once\n",
+				   pd->port_port, key);
+			ret = -EEXIST;
+			goto bail;
+		}
+	}
+	if (pidx == -1) {
+		ipath_dbg("All pkeys for port %u already in use, "
+			  "can't set %x\n", pd->port_port, key);
+		ret = -EBUSY;
+		goto bail;
+	}
+	for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+		if (!dd->ipath_pkeys[i]) {
+			any++;
+			continue;
+		}
+		if (dd->ipath_pkeys[i] == key) {
+			atomic_t *pkrefs = &dd->ipath_pkeyrefs[i];
+
+			if (atomic_inc_return(pkrefs) > 1) {
+				pd->port_pkeys[pidx] = key;
+				ipath_cdbg(VERBOSE, "p%u set key %x "
+					   "matches #%d, count now %d\n",
+					   pd->port_port, key, i,
+					   atomic_read(pkrefs));
+				ret = 0;
+				goto bail;
+			} else {
+				/*
+				 * lost race, decrement count, catch below
+				 */
+				atomic_dec(pkrefs);
+				ipath_cdbg(VERBOSE, "Lost race, count was "
+					   "0, after dec, it's %d\n",
+					   atomic_read(pkrefs));
+				any++;
+			}
+		}
+		if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+			/*
+			 * It makes no sense to have both the limited and
+			 * full membership PKEY set at the same time since
+			 * the unlimited one will disable the limited one.
+			 */
+			ret = -EEXIST;
+			goto bail;
+		}
+	}
+	if (!any) {
+		ipath_dbg("port %u, all pkeys already in use, "
+			  "can't set %x\n", pd->port_port, key);
+		ret = -EBUSY;
+		goto bail;
+	}
+	for (any = i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+		if (!dd->ipath_pkeys[i] &&
+		    atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+			u64 pkey;
+
+			/* for ipathstats, etc. */
+			ipath_stats.sps_pkeys[i] = lkey;
+			pd->port_pkeys[pidx] = dd->ipath_pkeys[i] = key;
+			pkey =
+				(u64) dd->ipath_pkeys[0] |
+				((u64) dd->ipath_pkeys[1] << 16) |
+				((u64) dd->ipath_pkeys[2] << 32) |
+				((u64) dd->ipath_pkeys[3] << 48);
+			ipath_cdbg(PROC, "p%u set key %x in #%d, "
+				   "portidx %d, new pkey reg %llx\n",
+				   pd->port_port, key, i, pidx,
+				   (unsigned long long) pkey);
+			ipath_write_kreg(
+				dd, dd->ipath_kregs->kr_partitionkey, pkey);
+
+			ret = 0;
+			goto bail;
+		}
+	}
+	ipath_dbg("port %u, all pkeys already in use 2nd pass, "
+		  "can't set %x\n", pd->port_port, key);
+	ret = -EBUSY;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_manage_rcvq - manage a port's receive queue
+ * @pd: the port
+ * @start_stop: action to carry out
+ *
+ * start_stop == 0 disables receive on the port, for use in queue
+ * overflow conditions.  start_stop==1 re-enables, to be used to
+ * re-init the software copy of the head register
+ */
+static int ipath_manage_rcvq(struct ipath_portdata *pd, int start_stop)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	u64 tval;
+
+	ipath_cdbg(PROC, "%sabling rcv for unit %u port %u\n",
+		   start_stop ? "en" : "dis", dd->ipath_unit,
+		   pd->port_port);
+	/* atomically clear receive enable port. */
+	if (start_stop) {
+		/*
+		 * On enable, force in-memory copy of the tail register to
+		 * 0, so that protocol code doesn't have to worry about
+		 * whether or not the chip has yet updated the in-memory
+		 * copy or not on return from the system call. The chip
+		 * always resets it's tail register back to 0 on a
+		 * transition from disabled to enabled.  This could cause a
+		 * problem if software was broken, and did the enable w/o
+		 * the disable, but eventually the in-memory copy will be
+		 * updated and correct itself, even in the face of software
+		 * bugs.
+		 */
+		*pd->port_rcvhdrtail_kvaddr = 0;
+		set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+			&dd->ipath_rcvctrl);
+	} else
+		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+			  &dd->ipath_rcvctrl);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+	/* now be sure chip saw it before we return */
+	tval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	if (start_stop) {
+		/*
+		 * And try to be sure that tail reg update has happened too.
+		 * This should in theory interlock with the RXE changes to
+		 * the tail register.  Don't assign it to the tail register
+		 * in memory copy, since we could overwrite an update by the
+		 * chip if we did.
+		 */
+		tval = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+	}
+	/* always; new head should be equal to new tail; see above */
+	return 0;
+}
+
+static void ipath_clean_part_key(struct ipath_portdata *pd,
+				 struct ipath_devdata *dd)
+{
+	int i, j, pchanged = 0;
+	u64 oldpkey;
+
+	/* for debugging only */
+	oldpkey = (u64) dd->ipath_pkeys[0] |
+		((u64) dd->ipath_pkeys[1] << 16) |
+		((u64) dd->ipath_pkeys[2] << 32) |
+		((u64) dd->ipath_pkeys[3] << 48);
+
+	for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+		if (!pd->port_pkeys[i])
+			continue;
+		ipath_cdbg(VERBOSE, "look for key[%d] %hx in pkeys\n", i,
+			   pd->port_pkeys[i]);
+		for (j = 0; j < ARRAY_SIZE(dd->ipath_pkeys); j++) {
+			/* check for match independent of the global bit */
+			if ((dd->ipath_pkeys[j] & 0x7fff) !=
+			    (pd->port_pkeys[i] & 0x7fff))
+				continue;
+			if (atomic_dec_and_test(&dd->ipath_pkeyrefs[j])) {
+				ipath_cdbg(VERBOSE, "p%u clear key "
+					   "%x matches #%d\n",
+					   pd->port_port,
+					   pd->port_pkeys[i], j);
+				ipath_stats.sps_pkeys[j] =
+					dd->ipath_pkeys[j] = 0;
+				pchanged++;
+			}
+			else ipath_cdbg(
+				VERBOSE, "p%u key %x matches #%d, "
+				"but ref still %d\n", pd->port_port,
+				pd->port_pkeys[i], j,
+				atomic_read(&dd->ipath_pkeyrefs[j]));
+			break;
+		}
+		pd->port_pkeys[i] = 0;
+	}
+	if (pchanged) {
+		u64 pkey = (u64) dd->ipath_pkeys[0] |
+			((u64) dd->ipath_pkeys[1] << 16) |
+			((u64) dd->ipath_pkeys[2] << 32) |
+			((u64) dd->ipath_pkeys[3] << 48);
+		ipath_cdbg(VERBOSE, "p%u old pkey reg %llx, "
+			   "new pkey reg %llx\n", pd->port_port,
+			   (unsigned long long) oldpkey,
+			   (unsigned long long) pkey);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+				 pkey);
+	}
+}
+
+/**
+ * ipath_create_user_egr - allocate eager TID buffers
+ * @pd: the port to allocate TID buffers for
+ *
+ * This routine is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance
+ * This is the user port version
+ *
+ * Allocate the eager TID buffers and program them into infinipath
+ * They are no longer completely contiguous, we do multiple allocation
+ * calls.
+ */
+static int ipath_create_user_egr(struct ipath_portdata *pd)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	unsigned e, egrcnt, alloced, egrperchunk, chunk, egrsize, egroff;
+	size_t size;
+	int ret;
+
+	egrcnt = dd->ipath_rcvegrcnt;
+	/* TID number offset for this port */
+	egroff = pd->port_port * egrcnt;
+	egrsize = dd->ipath_rcvegrbufsize;
+	ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
+		   "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
+
+	/*
+	 * to avoid wasting a lot of memory, we allocate 32KB chunks of
+	 * physically contiguous memory, advance through it until used up
+	 * and then allocate more.  Of course, we need memory to store those
+	 * extra pointers, now.  Started out with 256KB, but under heavy
+	 * memory pressure (creating large files and then copying them over
+	 * NFS while doing lots of MPI jobs), we hit some allocation
+	 * failures, even though we can sleep...  (2.6.10) Still get
+	 * failures at 64K.  32K is the lowest we can go without waiting
+	 * more memory again.  It seems likely that the coalescing in
+	 * free_pages, etc. still has issues (as it has had previously
+	 * during 2.6.x development).
+	 */
+	size = 0x8000;
+	alloced = ALIGN(egrsize * egrcnt, size);
+	egrperchunk = size / egrsize;
+	chunk = (egrcnt + egrperchunk - 1) / egrperchunk;
+	pd->port_rcvegrbuf_chunks = chunk;
+	pd->port_rcvegrbufs_perchunk = egrperchunk;
+	pd->port_rcvegrbuf_size = size;
+	pd->port_rcvegrbuf = vmalloc(chunk * sizeof(pd->port_rcvegrbuf[0]));
+	if (!pd->port_rcvegrbuf) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+	pd->port_rcvegrbuf_phys =
+		vmalloc(chunk * sizeof(pd->port_rcvegrbuf_phys[0]));
+	if (!pd->port_rcvegrbuf_phys) {
+		ret = -ENOMEM;
+		goto bail_rcvegrbuf;
+	}
+	for (e = 0; e < pd->port_rcvegrbuf_chunks; e++) {
+		/*
+		 * GFP_USER, but without GFP_FS, so buffer cache can be
+		 * coalesced (we hope); otherwise, even at order 4,
+		 * heavy filesystem activity makes these fail
+		 */
+		gfp_t gfp_flags = __GFP_WAIT | __GFP_IO | __GFP_COMP;
+
+		pd->port_rcvegrbuf[e] = dma_alloc_coherent(
+			&dd->pcidev->dev, size, &pd->port_rcvegrbuf_phys[e],
+			gfp_flags);
+
+		if (!pd->port_rcvegrbuf[e]) {
+			ret = -ENOMEM;
+			goto bail_rcvegrbuf_phys;
+		}
+	}
+
+	pd->port_rcvegr_phys = pd->port_rcvegrbuf_phys[0];
+
+	for (e = chunk = 0; chunk < pd->port_rcvegrbuf_chunks; chunk++) {
+		dma_addr_t pa = pd->port_rcvegrbuf_phys[chunk];
+		unsigned i;
+
+		for (i = 0; e < egrcnt && i < egrperchunk; e++, i++) {
+			dd->ipath_f_put_tid(dd, e + egroff +
+					    (u64 __iomem *)
+					    ((char __iomem *)
+					     dd->ipath_kregbase +
+					     dd->ipath_rcvegrbase), 0, pa);
+			pa += egrsize;
+		}
+		cond_resched();	/* don't hog the cpu */
+	}
+
+	ret = 0;
+	goto bail;
+
+bail_rcvegrbuf_phys:
+	for (e = 0; e < pd->port_rcvegrbuf_chunks &&
+		     pd->port_rcvegrbuf[e]; e++)
+		dma_free_coherent(&dd->pcidev->dev, size,
+				  pd->port_rcvegrbuf[e],
+				  pd->port_rcvegrbuf_phys[e]);
+
+	vfree(pd->port_rcvegrbuf_phys);
+	pd->port_rcvegrbuf_phys = NULL;
+bail_rcvegrbuf:
+	vfree(pd->port_rcvegrbuf);
+	pd->port_rcvegrbuf = NULL;
+bail:
+	return ret;
+}
+
+static int ipath_do_user_init(struct ipath_portdata *pd,
+			      const struct ipath_user_info *uinfo)
+{
+	int ret = 0;
+	struct ipath_devdata *dd = pd->port_dd;
+	u64 physaddr, uaddr, off, atmp;
+	struct page *pagep;
+	u32 head32;
+	u64 head;
+
+	/* for now, if major version is different, bail */
+	if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+		dev_info(&dd->pcidev->dev,
+			 "User major version %d not same as driver "
+			 "major %d\n", uinfo->spu_userversion >> 16,
+			 IPATH_USER_SWMAJOR);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR)
+		ipath_dbg("User minor version %d not same as driver "
+			  "minor %d\n", uinfo->spu_userversion & 0xffff,
+			  IPATH_USER_SWMINOR);
+
+	if (uinfo->spu_rcvhdrsize) {
+		ret = ipath_setrcvhdrsize(dd, uinfo->spu_rcvhdrsize);
+		if (ret)
+			goto done;
+	}
+
+	/* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */
+
+	/* set up for the rcvhdr Q tail register writeback to user memory */
+	if (!uinfo->spu_rcvhdraddr ||
+	    !access_ok(VERIFY_WRITE, (u64 __user *) (unsigned long)
+		       uinfo->spu_rcvhdraddr, sizeof(u64))) {
+		ipath_dbg("Port %d rcvhdrtail addr %llx not valid\n",
+			  pd->port_port,
+			  (unsigned long long) uinfo->spu_rcvhdraddr);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	off = offset_in_page(uinfo->spu_rcvhdraddr);
+	uaddr = PAGE_MASK & (unsigned long) uinfo->spu_rcvhdraddr;
+	ret = ipath_get_user_pages_nocopy(uaddr, &pagep);
+	if (ret) {
+		dev_info(&dd->pcidev->dev, "Failed to lookup and lock "
+			 "address %llx for rcvhdrtail: errno %d\n",
+			 (unsigned long long) uinfo->spu_rcvhdraddr, -ret);
+		goto done;
+	}
+	ipath_stats.sps_pagelocks++;
+	pd->port_rcvhdrtail_uaddr = uaddr;
+	pd->port_rcvhdrtail_pagep = pagep;
+	pd->port_rcvhdrtail_kvaddr =
+		page_address(pagep);
+	pd->port_rcvhdrtail_kvaddr += off;
+	physaddr = page_to_phys(pagep) + off;
+	ipath_cdbg(VERBOSE, "port %d user addr %llx hdrtailaddr, %llx "
+		   "physical (off=%llx)\n",
+		   pd->port_port,
+		   (unsigned long long) uinfo->spu_rcvhdraddr,
+		   (unsigned long long) physaddr, (unsigned long long) off);
+	ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+			      pd->port_port, physaddr);
+	atmp = ipath_read_kreg64_port(dd,
+				      dd->ipath_kregs->kr_rcvhdrtailaddr,
+				      pd->port_port);
+	if (physaddr != atmp) {
+		ipath_dev_err(dd,
+			      "Catastrophic software error, "
+			      "RcvHdrTailAddr%u written as %llx, "
+			      "read back as %llx\n", pd->port_port,
+			      (unsigned long long) physaddr,
+			      (unsigned long long) atmp);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* for right now, kernel piobufs are at end, so port 1 is at 0 */
+	pd->port_piobufs = dd->ipath_piobufbase +
+		dd->ipath_pbufsport * (pd->port_port -
+				       1) * dd->ipath_palign;
+	ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
+		   pd->port_port, pd->port_piobufs);
+
+	/*
+	 * Now allocate the rcvhdr Q and eager TIDs; skip the TID
+	 * array for time being.  If pd->port_port > chip-supported,
+	 * we need to do extra stuff here to handle by handling overflow
+	 * through port 0, someday
+	 */
+	ret = ipath_create_rcvhdrq(dd, pd);
+	if (!ret)
+		ret = ipath_create_user_egr(pd);
+	if (ret)
+		goto done;
+	/* enable receives now */
+	/* atomically set enable bit for this port */
+	set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
+		&dd->ipath_rcvctrl);
+
+	/*
+	 * set the head registers for this port to the current values
+	 * of the tail pointers, since we don't know if they were
+	 * updated on last use of the port.
+	 */
+	head32 = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+	head = (u64) head32;
+	ipath_write_ureg(dd, ur_rcvhdrhead, head, pd->port_port);
+	head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
+	ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
+	dd->ipath_lastegrheads[pd->port_port] = -1;
+	dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
+	ipath_cdbg(VERBOSE, "Wrote port%d head %llx, egrhead %x from "
+		   "tail regs\n", pd->port_port,
+		   (unsigned long long) head, head32);
+	pd->port_tidcursor = 0;	/* start at beginning after open */
+	/*
+	 * now enable the port; the tail registers will be written to memory
+	 * by the chip as soon as it sees the write to
+	 * dd->ipath_kregs->kr_rcvctrl.  The update only happens on
+	 * transition from 0 to 1, so clear it first, then set it as part of
+	 * enabling the port.  This will (very briefly) affect any other
+	 * open ports, but it shouldn't be long enough to be an issue.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+done:
+	return ret;
+}
+
+static int mmap_ureg(struct vm_area_struct *vma, struct ipath_devdata *dd,
+		     u64 ureg)
+{
+	unsigned long phys;
+	int ret;
+
+	/* it's the real hardware, so io_remap works */
+
+	if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+		dev_info(&dd->pcidev->dev, "FAIL mmap userreg: reqlen "
+			 "%lx > PAGE\n", vma->vm_end - vma->vm_start);
+		ret = -EFAULT;
+	} else {
+		phys = dd->ipath_physaddr + ureg;
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+		vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+		ret = io_remap_pfn_range(vma, vma->vm_start,
+					 phys >> PAGE_SHIFT,
+					 vma->vm_end - vma->vm_start,
+					 vma->vm_page_prot);
+	}
+	return ret;
+}
+
+static int mmap_piobufs(struct vm_area_struct *vma,
+			struct ipath_devdata *dd,
+			struct ipath_portdata *pd)
+{
+	unsigned long phys;
+	int ret;
+
+	/*
+	 * When we map the PIO buffers, we want to map them as writeonly, no
+	 * read possible.
+	 */
+
+	if ((vma->vm_end - vma->vm_start) >
+	    (dd->ipath_pbufsport * dd->ipath_palign)) {
+		dev_info(&dd->pcidev->dev, "FAIL mmap piobufs: "
+			 "reqlen %lx > PAGE\n",
+			 vma->vm_end - vma->vm_start);
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	phys = dd->ipath_physaddr + pd->port_piobufs;
+	/*
+	 * Do *NOT* mark this as non-cached (PWT bit), or we don't get the
+	 * write combining behavior we want on the PIO buffers!
+	 * vma->vm_page_prot =
+	 *        pgprot_noncached(vma->vm_page_prot);
+	 */
+
+	if (vma->vm_flags & VM_READ) {
+		dev_info(&dd->pcidev->dev,
+			 "Can't map piobufs as readable (flags=%lx)\n",
+			 vma->vm_flags);
+		ret = -EPERM;
+		goto bail;
+	}
+
+	/* don't allow them to later change to readable with mprotect */
+
+	vma->vm_flags &= ~VM_MAYWRITE;
+	vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+
+	ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
+				 vma->vm_end - vma->vm_start,
+				 vma->vm_page_prot);
+bail:
+	return ret;
+}
+
+static int mmap_rcvegrbufs(struct vm_area_struct *vma,
+			   struct ipath_portdata *pd)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	unsigned long start, size;
+	size_t total_size, i;
+	dma_addr_t *phys;
+	int ret;
+
+	if (!pd->port_rcvegrbuf) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	size = pd->port_rcvegrbuf_size;
+	total_size = pd->port_rcvegrbuf_chunks * size;
+	if ((vma->vm_end - vma->vm_start) > total_size) {
+		dev_info(&dd->pcidev->dev, "FAIL on egr bufs: "
+			 "reqlen %lx > actual %lx\n",
+			 vma->vm_end - vma->vm_start,
+			 (unsigned long) total_size);
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	if (vma->vm_flags & VM_WRITE) {
+		dev_info(&dd->pcidev->dev, "Can't map eager buffers as "
+			 "writable (flags=%lx)\n", vma->vm_flags);
+		ret = -EPERM;
+		goto bail;
+	}
+
+	start = vma->vm_start;
+	phys = pd->port_rcvegrbuf_phys;
+
+	/* don't allow them to later change to writeable with mprotect */
+	vma->vm_flags &= ~VM_MAYWRITE;
+
+	for (i = 0; i < pd->port_rcvegrbuf_chunks; i++, start += size) {
+		ret = remap_pfn_range(vma, start, phys[i] >> PAGE_SHIFT,
+				      size, vma->vm_page_prot);
+		if (ret < 0)
+			goto bail;
+	}
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static int mmap_rcvhdrq(struct vm_area_struct *vma,
+			struct ipath_portdata *pd)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	size_t total_size;
+	int ret;
+
+	/*
+	 * kmalloc'ed memory, physically contiguous; this is from
+	 * spi_rcvhdr_base; we allow user to map read-write so they can
+	 * write hdrq entries to allow protocol code to directly poll
+	 * whether a hdrq entry has been written.
+	 */
+	total_size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize *
+			   sizeof(u32), PAGE_SIZE);
+	if ((vma->vm_end - vma->vm_start) > total_size) {
+		dev_info(&dd->pcidev->dev,
+			 "FAIL on rcvhdrq: reqlen %lx > actual %lx\n",
+			 vma->vm_end - vma->vm_start,
+			 (unsigned long) total_size);
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	ret = remap_pfn_range(vma, vma->vm_start,
+			      pd->port_rcvhdrq_phys >> PAGE_SHIFT,
+			      vma->vm_end - vma->vm_start,
+			      vma->vm_page_prot);
+bail:
+	return ret;
+}
+
+static int mmap_pioavailregs(struct vm_area_struct *vma,
+			     struct ipath_portdata *pd)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	int ret;
+
+	/*
+	 * when we map the PIO bufferavail registers, we want to map them as
+	 * readonly, no write possible.
+	 *
+	 * kmalloc'ed memory, physically contiguous, one page only, readonly
+	 */
+
+	if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) {
+		dev_info(&dd->pcidev->dev, "FAIL on pioavailregs_dma: "
+			 "reqlen %lx > actual %lx\n",
+			 vma->vm_end - vma->vm_start,
+			 (unsigned long) PAGE_SIZE);
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	if (vma->vm_flags & VM_WRITE) {
+		dev_info(&dd->pcidev->dev,
+			 "Can't map pioavailregs as writable (flags=%lx)\n",
+			 vma->vm_flags);
+		ret = -EPERM;
+		goto bail;
+	}
+
+	/* don't allow them to later change with mprotect */
+	vma->vm_flags &= ~VM_MAYWRITE;
+
+	ret = remap_pfn_range(vma, vma->vm_start,
+			      dd->ipath_pioavailregs_phys >> PAGE_SHIFT,
+			      PAGE_SIZE, vma->vm_page_prot);
+bail:
+	return ret;
+}
+
+/**
+ * ipath_mmap - mmap various structures into user space
+ * @fp: the file pointer
+ * @vma: the VM area
+ *
+ * We use this to have a shared buffer between the kernel and the user code
+ * for the rcvhdr queue, egr buffers, and the per-port user regs and pio
+ * buffers in the chip.  We have the open and close entries so we can bump
+ * the ref count and keep the driver from being unloaded while still mapped.
+ */
+static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+	struct ipath_portdata *pd;
+	struct ipath_devdata *dd;
+	u64 pgaddr, ureg;
+	int ret;
+
+	pd = port_fp(fp);
+	dd = pd->port_dd;
+	/*
+	 * This is the ipath_do_user_init() code, mapping the shared buffers
+	 * into the user process. The address referred to by vm_pgoff is the
+	 * virtual, not physical, address; we only do one mmap for each
+	 * space mapped.
+	 */
+	pgaddr = vma->vm_pgoff << PAGE_SHIFT;
+
+	/*
+	 * note that ureg does *NOT* have the kregvirt as part of it, to be
+	 * sure that for 32 bit programs, we don't end up trying to map a >
+	 * 44 address.  Has to match ipath_get_base_info() code that sets
+	 * __spi_uregbase
+	 */
+
+	ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
+
+	ipath_cdbg(MM, "ushare: pgaddr %llx vm_start=%lx, vmlen %lx\n",
+		   (unsigned long long) pgaddr, vma->vm_start,
+		   vma->vm_end - vma->vm_start);
+
+	if (pgaddr == ureg)
+		ret = mmap_ureg(vma, dd, ureg);
+	else if (pgaddr == pd->port_piobufs)
+		ret = mmap_piobufs(vma, dd, pd);
+	else if (pgaddr == (u64) pd->port_rcvegr_phys)
+		ret = mmap_rcvegrbufs(vma, pd);
+	else if (pgaddr == (u64) pd->port_rcvhdrq_phys)
+		ret = mmap_rcvhdrq(vma, pd);
+	else if (pgaddr == dd->ipath_pioavailregs_phys)
+		ret = mmap_pioavailregs(vma, pd);
+	else
+		ret = -EINVAL;
+
+	vma->vm_private_data = NULL;
+
+	if (ret < 0)
+		dev_info(&dd->pcidev->dev,
+			 "Failure %d on addr %lx, off %lx\n",
+			 -ret, vma->vm_start, vma->vm_pgoff);
+
+	return ret;
+}
+
+static unsigned int ipath_poll(struct file *fp,
+			       struct poll_table_struct *pt)
+{
+	struct ipath_portdata *pd;
+	u32 head, tail;
+	int bit;
+	struct ipath_devdata *dd;
+
+	pd = port_fp(fp);
+	dd = pd->port_dd;
+
+	bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
+	set_bit(bit, &dd->ipath_rcvctrl);
+
+	/*
+	 * Before blocking, make sure that head is still == tail,
+	 * reading from the chip, so we can be sure the interrupt
+	 * enable has made it to the chip.  If not equal, disable
+	 * interrupt again and return immediately.  This avoids races,
+	 * and the overhead of the chip read doesn't matter much at
+	 * this point, since we are waiting for something anyway.
+	 */
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+	head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
+	tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+
+	if (tail == head) {
+		set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+		poll_wait(fp, &pd->port_wait, pt);
+
+		if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
+			/* timed out, no packets received */
+			clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+			pd->port_rcvwait_to++;
+		}
+	}
+	else {
+		/* it's already happened; don't do wait_event overhead */
+		pd->port_rcvnowait++;
+	}
+
+	clear_bit(bit, &dd->ipath_rcvctrl);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+	return 0;
+}
+
+static int try_alloc_port(struct ipath_devdata *dd, int port,
+			  struct file *fp)
+{
+	int ret;
+
+	if (!dd->ipath_pd[port]) {
+		void *p, *ptmp;
+
+		p = kzalloc(sizeof(struct ipath_portdata), GFP_KERNEL);
+
+		/*
+		 * Allocate memory for use in ipath_tid_update() just once
+		 * at open, not per call.  Reduces cost of expected send
+		 * setup.
+		 */
+		ptmp = kmalloc(dd->ipath_rcvtidcnt * sizeof(u16) +
+			       dd->ipath_rcvtidcnt * sizeof(struct page **),
+			       GFP_KERNEL);
+		if (!p || !ptmp) {
+			ipath_dev_err(dd, "Unable to allocate portdata "
+				      "memory, failing open\n");
+			ret = -ENOMEM;
+			kfree(p);
+			kfree(ptmp);
+			goto bail;
+		}
+		dd->ipath_pd[port] = p;
+		dd->ipath_pd[port]->port_port = port;
+		dd->ipath_pd[port]->port_dd = dd;
+		dd->ipath_pd[port]->port_tid_pg_list = ptmp;
+		init_waitqueue_head(&dd->ipath_pd[port]->port_wait);
+	}
+	if (!dd->ipath_pd[port]->port_cnt) {
+		dd->ipath_pd[port]->port_cnt = 1;
+		fp->private_data = (void *) dd->ipath_pd[port];
+		ipath_cdbg(PROC, "%s[%u] opened unit:port %u:%u\n",
+			   current->comm, current->pid, dd->ipath_unit,
+			   port);
+		dd->ipath_pd[port]->port_pid = current->pid;
+		strncpy(dd->ipath_pd[port]->port_comm, current->comm,
+			sizeof(dd->ipath_pd[port]->port_comm));
+		ipath_stats.sps_ports++;
+		ret = 0;
+		goto bail;
+	}
+	ret = -EBUSY;
+
+bail:
+	return ret;
+}
+
+static inline int usable(struct ipath_devdata *dd)
+{
+	return dd &&
+		(dd->ipath_flags & IPATH_PRESENT) &&
+		dd->ipath_kregbase &&
+		dd->ipath_lid &&
+		!(dd->ipath_flags & (IPATH_LINKDOWN | IPATH_DISABLED
+				     | IPATH_LINKUNK));
+}
+
+static int find_free_port(int unit, struct file *fp)
+{
+	struct ipath_devdata *dd = ipath_lookup(unit);
+	int ret, i;
+
+	if (!dd) {
+		ret = -ENODEV;
+		goto bail;
+	}
+
+	if (!usable(dd)) {
+		ret = -ENETDOWN;
+		goto bail;
+	}
+
+	for (i = 0; i < dd->ipath_cfgports; i++) {
+		ret = try_alloc_port(dd, i, fp);
+		if (ret != -EBUSY)
+			goto bail;
+	}
+	ret = -EBUSY;
+
+bail:
+	return ret;
+}
+
+static int find_best_unit(struct file *fp)
+{
+	int ret = 0, i, prefunit = -1, devmax;
+	int maxofallports, npresent, nup;
+	int ndev;
+
+	(void) ipath_count_units(&npresent, &nup, &maxofallports);
+
+	/*
+	 * This code is present to allow a knowledgeable person to
+	 * specify the layout of processes to processors before opening
+	 * this driver, and then we'll assign the process to the "closest"
+	 * HT-400 to that processor (we assume reasonable connectivity,
+	 * for now).  This code assumes that if affinity has been set
+	 * before this point, that at most one cpu is set; for now this
+	 * is reasonable.  I check for both cpus_empty() and cpus_full(),
+	 * in case some kernel variant sets none of the bits when no
+	 * affinity is set.  2.6.11 and 12 kernels have all present
+	 * cpus set.  Some day we'll have to fix it up further to handle
+	 * a cpu subset.  This algorithm fails for two HT-400's connected
+	 * in tunnel fashion.  Eventually this needs real topology
+	 * information.  There may be some issues with dual core numbering
+	 * as well.  This needs more work prior to release.
+	 */
+	if (!cpus_empty(current->cpus_allowed) &&
+	    !cpus_full(current->cpus_allowed)) {
+		int ncpus = num_online_cpus(), curcpu = -1;
+		for (i = 0; i < ncpus; i++)
+			if (cpu_isset(i, current->cpus_allowed)) {
+				ipath_cdbg(PROC, "%s[%u] affinity set for "
+					   "cpu %d\n", current->comm,
+					   current->pid, i);
+				curcpu = i;
+			}
+		if (curcpu != -1) {
+			if (npresent) {
+				prefunit = curcpu / (ncpus / npresent);
+				ipath_dbg("%s[%u] %d chips, %d cpus, "
+					  "%d cpus/chip, select unit %d\n",
+					  current->comm, current->pid,
+					  npresent, ncpus, ncpus / npresent,
+					  prefunit);
+			}
+		}
+	}
+
+	/*
+	 * user ports start at 1, kernel port is 0
+	 * For now, we do round-robin access across all chips
+	 */
+
+	if (prefunit != -1)
+		devmax = prefunit + 1;
+	else
+		devmax = ipath_count_units(NULL, NULL, NULL);
+recheck:
+	for (i = 1; i < maxofallports; i++) {
+		for (ndev = prefunit != -1 ? prefunit : 0; ndev < devmax;
+		     ndev++) {
+			struct ipath_devdata *dd = ipath_lookup(ndev);
+
+			if (!usable(dd))
+				continue; /* can't use this unit */
+			if (i >= dd->ipath_cfgports)
+				/*
+				 * Maxed out on users of this unit. Try
+				 * next.
+				 */
+				continue;
+			ret = try_alloc_port(dd, i, fp);
+			if (!ret)
+				goto done;
+		}
+	}
+
+	if (npresent) {
+		if (nup == 0) {
+			ret = -ENETDOWN;
+			ipath_dbg("No ports available (none initialized "
+				  "and ready)\n");
+		} else {
+			if (prefunit > 0) {
+				/* if started above 0, retry from 0 */
+				ipath_cdbg(PROC,
+					   "%s[%u] no ports on prefunit "
+					   "%d, clear and re-check\n",
+					   current->comm, current->pid,
+					   prefunit);
+				devmax = ipath_count_units(NULL, NULL,
+							   NULL);
+				prefunit = -1;
+				goto recheck;
+			}
+			ret = -EBUSY;
+			ipath_dbg("No ports available\n");
+		}
+	} else {
+		ret = -ENXIO;
+		ipath_dbg("No boards found\n");
+	}
+
+done:
+	return ret;
+}
+
+static int ipath_open(struct inode *in, struct file *fp)
+{
+	int ret, minor;
+
+	mutex_lock(&ipath_mutex);
+
+	minor = iminor(in);
+	ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n",
+		   (long)in->i_rdev, minor);
+
+	if (minor)
+		ret = find_free_port(minor - 1, fp);
+	else
+		ret = find_best_unit(fp);
+
+	mutex_unlock(&ipath_mutex);
+	return ret;
+}
+
+/**
+ * unlock_exptid - unlock any expected TID entries port still had in use
+ * @pd: port
+ *
+ * We don't actually update the chip here, because we do a bulk update
+ * below, using ipath_f_clear_tids.
+ */
+static void unlock_expected_tids(struct ipath_portdata *pd)
+{
+	struct ipath_devdata *dd = pd->port_dd;
+	int port_tidbase = pd->port_port * dd->ipath_rcvtidcnt;
+	int i, cnt = 0, maxtid = port_tidbase + dd->ipath_rcvtidcnt;
+
+	ipath_cdbg(VERBOSE, "Port %u unlocking any locked expTID pages\n",
+		   pd->port_port);
+	for (i = port_tidbase; i < maxtid; i++) {
+		if (!dd->ipath_pageshadow[i])
+			continue;
+
+		ipath_release_user_pages_on_close(&dd->ipath_pageshadow[i],
+						  1);
+		dd->ipath_pageshadow[i] = NULL;
+		cnt++;
+		ipath_stats.sps_pageunlocks++;
+	}
+	if (cnt)
+		ipath_cdbg(VERBOSE, "Port %u locked %u expTID entries\n",
+			   pd->port_port, cnt);
+
+	if (ipath_stats.sps_pagelocks || ipath_stats.sps_pageunlocks)
+		ipath_cdbg(VERBOSE, "%llu pages locked, %llu unlocked\n",
+			   (unsigned long long) ipath_stats.sps_pagelocks,
+			   (unsigned long long)
+			   ipath_stats.sps_pageunlocks);
+}
+
+static int ipath_close(struct inode *in, struct file *fp)
+{
+	int ret = 0;
+	struct ipath_portdata *pd;
+	struct ipath_devdata *dd;
+	unsigned port;
+
+	ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n",
+		   (long)in->i_rdev, fp->private_data);
+
+	mutex_lock(&ipath_mutex);
+
+	pd = port_fp(fp);
+	port = pd->port_port;
+	fp->private_data = NULL;
+	dd = pd->port_dd;
+
+	if (pd->port_hdrqfull) {
+		ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors "
+			   "during run\n", pd->port_comm, pd->port_pid,
+			   pd->port_hdrqfull);
+		pd->port_hdrqfull = 0;
+	}
+
+	if (pd->port_rcvwait_to || pd->port_piowait_to
+	    || pd->port_rcvnowait || pd->port_pionowait) {
+		ipath_cdbg(VERBOSE, "port%u, %u rcv, %u pio wait timeo; "
+			   "%u rcv %u, pio already\n",
+			   pd->port_port, pd->port_rcvwait_to,
+			   pd->port_piowait_to, pd->port_rcvnowait,
+			   pd->port_pionowait);
+		pd->port_rcvwait_to = pd->port_piowait_to =
+			pd->port_rcvnowait = pd->port_pionowait = 0;
+	}
+	if (pd->port_flag) {
+		ipath_dbg("port %u port_flag still set to 0x%lx\n",
+			  pd->port_port, pd->port_flag);
+		pd->port_flag = 0;
+	}
+
+	if (dd->ipath_kregbase) {
+		if (pd->port_rcvhdrtail_uaddr) {
+			pd->port_rcvhdrtail_uaddr = 0;
+			pd->port_rcvhdrtail_kvaddr = NULL;
+			ipath_release_user_pages_on_close(
+				&pd->port_rcvhdrtail_pagep, 1);
+			pd->port_rcvhdrtail_pagep = NULL;
+			ipath_stats.sps_pageunlocks++;
+		}
+		ipath_write_kreg_port(
+			dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+			port, 0ULL);
+		ipath_write_kreg_port(
+			dd, dd->ipath_kregs->kr_rcvhdraddr,
+			pd->port_port, 0);
+
+		/* clean up the pkeys for this port user */
+		ipath_clean_part_key(pd, dd);
+
+		if (port < dd->ipath_cfgports) {
+			int i = dd->ipath_pbufsport * (port - 1);
+			ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
+
+			/* atomically clear receive enable port. */
+			clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
+				  &dd->ipath_rcvctrl);
+			ipath_write_kreg(
+				dd,
+				dd->ipath_kregs->kr_rcvctrl,
+				dd->ipath_rcvctrl);
+
+			if (dd->ipath_pageshadow)
+				unlock_expected_tids(pd);
+			ipath_stats.sps_ports--;
+			ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
+				   pd->port_comm, pd->port_pid,
+				   dd->ipath_unit, port);
+		}
+	}
+
+	pd->port_cnt = 0;
+	pd->port_pid = 0;
+
+	dd->ipath_f_clear_tids(dd, pd->port_port);
+
+	ipath_free_pddata(dd, pd->port_port, 0);
+
+	mutex_unlock(&ipath_mutex);
+
+	return ret;
+}
+
+static int ipath_port_info(struct ipath_portdata *pd,
+			   struct ipath_port_info __user *uinfo)
+{
+	struct ipath_port_info info;
+	int nup;
+	int ret;
+
+	(void) ipath_count_units(NULL, &nup, NULL);
+	info.num_active = nup;
+	info.unit = pd->port_dd->ipath_unit;
+	info.port = pd->port_port;
+
+	if (copy_to_user(uinfo, &info, sizeof(info))) {
+		ret = -EFAULT;
+		goto bail;
+	}
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static ssize_t ipath_write(struct file *fp, const char __user *data,
+			   size_t count, loff_t *off)
+{
+	const struct ipath_cmd __user *ucmd;
+	struct ipath_portdata *pd;
+	const void __user *src;
+	size_t consumed, copy;
+	struct ipath_cmd cmd;
+	ssize_t ret = 0;
+	void *dest;
+
+	if (count < sizeof(cmd.type)) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	ucmd = (const struct ipath_cmd __user *) data;
+
+	if (copy_from_user(&cmd.type, &ucmd->type, sizeof(cmd.type))) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	consumed = sizeof(cmd.type);
+
+	switch (cmd.type) {
+	case IPATH_CMD_USER_INIT:
+		copy = sizeof(cmd.cmd.user_info);
+		dest = &cmd.cmd.user_info;
+		src = &ucmd->cmd.user_info;
+		break;
+	case IPATH_CMD_RECV_CTRL:
+		copy = sizeof(cmd.cmd.recv_ctrl);
+		dest = &cmd.cmd.recv_ctrl;
+		src = &ucmd->cmd.recv_ctrl;
+		break;
+	case IPATH_CMD_PORT_INFO:
+		copy = sizeof(cmd.cmd.port_info);
+		dest = &cmd.cmd.port_info;
+		src = &ucmd->cmd.port_info;
+		break;
+	case IPATH_CMD_TID_UPDATE:
+	case IPATH_CMD_TID_FREE:
+		copy = sizeof(cmd.cmd.tid_info);
+		dest = &cmd.cmd.tid_info;
+		src = &ucmd->cmd.tid_info;
+		break;
+	case IPATH_CMD_SET_PART_KEY:
+		copy = sizeof(cmd.cmd.part_key);
+		dest = &cmd.cmd.part_key;
+		src = &ucmd->cmd.part_key;
+		break;
+	default:
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if ((count - consumed) < copy) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if (copy_from_user(dest, src, copy)) {
+		ret = -EFAULT;
+		goto bail;
+	}
+
+	consumed += copy;
+	pd = port_fp(fp);
+
+	switch (cmd.type) {
+	case IPATH_CMD_USER_INIT:
+		ret = ipath_do_user_init(pd, &cmd.cmd.user_info);
+		if (ret < 0)
+			goto bail;
+		ret = ipath_get_base_info(
+			pd, (void __user *) (unsigned long)
+			cmd.cmd.user_info.spu_base_info,
+			cmd.cmd.user_info.spu_base_info_size);
+		break;
+	case IPATH_CMD_RECV_CTRL:
+		ret = ipath_manage_rcvq(pd, cmd.cmd.recv_ctrl);
+		break;
+	case IPATH_CMD_PORT_INFO:
+		ret = ipath_port_info(pd,
+				      (struct ipath_port_info __user *)
+				      (unsigned long) cmd.cmd.port_info);
+		break;
+	case IPATH_CMD_TID_UPDATE:
+		ret = ipath_tid_update(pd, &cmd.cmd.tid_info);
+		break;
+	case IPATH_CMD_TID_FREE:
+		ret = ipath_tid_free(pd, &cmd.cmd.tid_info);
+		break;
+	case IPATH_CMD_SET_PART_KEY:
+		ret = ipath_set_part_key(pd, cmd.cmd.part_key);
+		break;
+	}
+
+	if (ret >= 0)
+		ret = consumed;
+
+bail:
+	return ret;
+}
+
+static struct class *ipath_class;
+
+static int init_cdev(int minor, char *name, struct file_operations *fops,
+		     struct cdev **cdevp, struct class_device **class_devp)
+{
+	const dev_t dev = MKDEV(IPATH_MAJOR, minor);
+	struct cdev *cdev = NULL;
+	struct class_device *class_dev = NULL;
+	int ret;
+
+	cdev = cdev_alloc();
+	if (!cdev) {
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Could not allocate cdev for minor %d, %s\n",
+		       minor, name);
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	cdev->owner = THIS_MODULE;
+	cdev->ops = fops;
+	kobject_set_name(&cdev->kobj, name);
+
+	ret = cdev_add(cdev, dev, 1);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME
+		       ": Could not add cdev for minor %d, %s (err %d)\n",
+		       minor, name, -ret);
+		goto err_cdev;
+	}
+
+	class_dev = class_device_create(ipath_class, NULL, dev, NULL, name);
+
+	if (IS_ERR(class_dev)) {
+		ret = PTR_ERR(class_dev);
+		printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+		       "class_dev for minor %d, %s (err %d)\n",
+		       minor, name, -ret);
+		goto err_cdev;
+	}
+
+	goto done;
+
+err_cdev:
+	cdev_del(cdev);
+	cdev = NULL;
+
+done:
+	if (ret >= 0) {
+		*cdevp = cdev;
+		*class_devp = class_dev;
+	} else {
+		*cdevp = NULL;
+		*class_devp = NULL;
+	}
+
+	return ret;
+}
+
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+		    struct cdev **cdevp, struct class_device **class_devp)
+{
+	return init_cdev(minor, name, fops, cdevp, class_devp);
+}
+
+static void cleanup_cdev(struct cdev **cdevp,
+			 struct class_device **class_devp)
+{
+	struct class_device *class_dev = *class_devp;
+
+	if (class_dev) {
+		class_device_unregister(class_dev);
+		*class_devp = NULL;
+	}
+
+	if (*cdevp) {
+		cdev_del(*cdevp);
+		*cdevp = NULL;
+	}
+}
+
+void ipath_cdev_cleanup(struct cdev **cdevp,
+			struct class_device **class_devp)
+{
+	cleanup_cdev(cdevp, class_devp);
+}
+
+static struct cdev *wildcard_cdev;
+static struct class_device *wildcard_class_dev;
+
+static const dev_t dev = MKDEV(IPATH_MAJOR, 0);
+
+static int user_init(void)
+{
+	int ret;
+
+	ret = register_chrdev_region(dev, IPATH_NMINORS, IPATH_DRV_NAME);
+	if (ret < 0) {
+		printk(KERN_ERR IPATH_DRV_NAME ": Could not register "
+		       "chrdev region (err %d)\n", -ret);
+		goto done;
+	}
+
+	ipath_class = class_create(THIS_MODULE, IPATH_DRV_NAME);
+
+	if (IS_ERR(ipath_class)) {
+		ret = PTR_ERR(ipath_class);
+		printk(KERN_ERR IPATH_DRV_NAME ": Could not create "
+		       "device class (err %d)\n", -ret);
+		goto bail;
+	}
+
+	goto done;
+bail:
+	unregister_chrdev_region(dev, IPATH_NMINORS);
+done:
+	return ret;
+}
+
+static void user_cleanup(void)
+{
+	if (ipath_class) {
+		class_destroy(ipath_class);
+		ipath_class = NULL;
+	}
+
+	unregister_chrdev_region(dev, IPATH_NMINORS);
+}
+
+static atomic_t user_count = ATOMIC_INIT(0);
+static atomic_t user_setup = ATOMIC_INIT(0);
+
+int ipath_user_add(struct ipath_devdata *dd)
+{
+	char name[10];
+	int ret;
+
+	if (atomic_inc_return(&user_count) == 1) {
+		ret = user_init();
+		if (ret < 0) {
+			ipath_dev_err(dd, "Unable to set up user support: "
+				      "error %d\n", -ret);
+			goto bail;
+		}
+		ret = ipath_diag_init();
+		if (ret < 0) {
+			ipath_dev_err(dd, "Unable to set up diag support: "
+				      "error %d\n", -ret);
+			goto bail_sma;
+		}
+
+		ret = init_cdev(0, "ipath", &ipath_file_ops, &wildcard_cdev,
+				&wildcard_class_dev);
+		if (ret < 0) {
+			ipath_dev_err(dd, "Could not create wildcard "
+				      "minor: error %d\n", -ret);
+			goto bail_diag;
+		}
+
+		atomic_set(&user_setup, 1);
+	}
+
+	snprintf(name, sizeof(name), "ipath%d", dd->ipath_unit);
+
+	ret = init_cdev(dd->ipath_unit + 1, name, &ipath_file_ops,
+			&dd->cdev, &dd->class_dev);
+	if (ret < 0)
+		ipath_dev_err(dd, "Could not create user minor %d, %s\n",
+			      dd->ipath_unit + 1, name);
+
+	goto bail;
+
+bail_diag:
+	ipath_diag_cleanup();
+bail_sma:
+	user_cleanup();
+bail:
+	return ret;
+}
+
+void ipath_user_del(struct ipath_devdata *dd)
+{
+	cleanup_cdev(&dd->cdev, &dd->class_dev);
+
+	if (atomic_dec_return(&user_count) == 0) {
+		if (atomic_read(&user_setup) == 0)
+			goto bail;
+
+		cleanup_cdev(&wildcard_cdev, &wildcard_class_dev);
+		ipath_diag_cleanup();
+		user_cleanup();
+
+		atomic_set(&user_setup, 0);
+	}
+bail:
+	return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
new file mode 100644
index 0000000..e274120
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/version.h>
+#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/pci.h>
+
+#include "ipath_kernel.h"
+
+#define IPATHFS_MAGIC 0x726a77
+
+static struct super_block *ipath_super;
+
+static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
+			 int mode, struct file_operations *fops,
+			 void *data)
+{
+	int error;
+	struct inode *inode = new_inode(dir->i_sb);
+
+	if (!inode) {
+		error = -EPERM;
+		goto bail;
+	}
+
+	inode->i_mode = mode;
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_blksize = PAGE_CACHE_SIZE;
+	inode->i_blocks = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	inode->u.generic_ip = data;
+	if ((mode & S_IFMT) == S_IFDIR) {
+		inode->i_op = &simple_dir_inode_operations;
+		inode->i_nlink++;
+		dir->i_nlink++;
+	}
+
+	inode->i_fop = fops;
+
+	d_instantiate(dentry, inode);
+	error = 0;
+
+bail:
+	return error;
+}
+
+static int create_file(const char *name, mode_t mode,
+		       struct dentry *parent, struct dentry **dentry,
+		       struct file_operations *fops, void *data)
+{
+	int error;
+
+	*dentry = NULL;
+	mutex_lock(&parent->d_inode->i_mutex);
+	*dentry = lookup_one_len(name, parent, strlen(name));
+	if (!IS_ERR(dentry))
+		error = ipathfs_mknod(parent->d_inode, *dentry,
+				      mode, fops, data);
+	else
+		error = PTR_ERR(dentry);
+	mutex_unlock(&parent->d_inode->i_mutex);
+
+	return error;
+}
+
+static ssize_t atomic_stats_read(struct file *file, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	return simple_read_from_buffer(buf, count, ppos, &ipath_stats,
+				       sizeof ipath_stats);
+}
+
+static struct file_operations atomic_stats_ops = {
+	.read = atomic_stats_read,
+};
+
+#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
+
+static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	u64 counters[NUM_COUNTERS];
+	u16 i;
+	struct ipath_devdata *dd;
+
+	dd = file->f_dentry->d_inode->u.generic_ip;
+
+	for (i = 0; i < NUM_COUNTERS; i++)
+		counters[i] = ipath_snap_cntr(dd, i);
+
+	return simple_read_from_buffer(buf, count, ppos, counters,
+				       sizeof counters);
+}
+
+static struct file_operations atomic_counters_ops = {
+	.read = atomic_counters_read,
+};
+
+static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	u32 nodeinfo[10];
+	struct ipath_devdata *dd;
+	u64 guid;
+
+	dd = file->f_dentry->d_inode->u.generic_ip;
+
+	guid = be64_to_cpu(dd->ipath_guid);
+
+	nodeinfo[0] =			/* BaseVersion is SMA */
+		/* ClassVersion is SMA */
+		(1 << 8)		/* NodeType  */
+		| (1 << 0);		/* NumPorts */
+	nodeinfo[1] = (u32) (guid >> 32);
+	nodeinfo[2] = (u32) (guid & 0xffffffff);
+	/* PortGUID == SystemImageGUID for us */
+	nodeinfo[3] = nodeinfo[1];
+	/* PortGUID == SystemImageGUID for us */
+	nodeinfo[4] = nodeinfo[2];
+	/* PortGUID == NodeGUID for us */
+	nodeinfo[5] = nodeinfo[3];
+	/* PortGUID == NodeGUID for us */
+	nodeinfo[6] = nodeinfo[4];
+	nodeinfo[7] = (4 << 16) /* we support 4 pkeys */
+		| (dd->ipath_deviceid << 0);
+	/* our chip version as 16 bits major, 16 bits minor */
+	nodeinfo[8] = dd->ipath_minrev | (dd->ipath_majrev << 16);
+	nodeinfo[9] = (dd->ipath_unit << 24) | (dd->ipath_vendorid << 0);
+
+	return simple_read_from_buffer(buf, count, ppos, nodeinfo,
+				       sizeof nodeinfo);
+}
+
+static struct file_operations atomic_node_info_ops = {
+	.read = atomic_node_info_read,
+};
+
+static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	u32 portinfo[13];
+	u32 tmp, tmp2;
+	struct ipath_devdata *dd;
+
+	dd = file->f_dentry->d_inode->u.generic_ip;
+
+	/* so we only initialize non-zero fields. */
+	memset(portinfo, 0, sizeof portinfo);
+
+	/*
+	 * Notimpl yet M_Key (64)
+	 * Notimpl yet GID (64)
+	 */
+
+	portinfo[4] = (dd->ipath_lid << 16);
+
+	/*
+	 * Notimpl yet SMLID (should we store this in the driver, in case
+	 * SMA dies?)  CapabilityMask is 0, we don't support any of these
+	 * DiagCode is 0; we don't store any diag info for now Notimpl yet
+	 * M_KeyLeasePeriod (we don't support M_Key)
+	 */
+
+	/* LocalPortNum is whichever port number they ask for */
+	portinfo[7] = (dd->ipath_unit << 24)
+		/* LinkWidthEnabled */
+		| (2 << 16)
+		/* LinkWidthSupported (really 2, but not IB valid) */
+		| (3 << 8)
+		/* LinkWidthActive */
+		| (2 << 0);
+	tmp = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+	tmp2 = 5;
+	if (tmp == IPATH_IBSTATE_INIT)
+		tmp = 2;
+	else if (tmp == IPATH_IBSTATE_ARM)
+		tmp = 3;
+	else if (tmp == IPATH_IBSTATE_ACTIVE)
+		tmp = 4;
+	else {
+		tmp = 0;	/* down */
+		tmp2 = tmp & 0xf;
+	}
+
+	portinfo[8] = (1 << 28)	/* LinkSpeedSupported */
+		| (tmp << 24)	/* PortState */
+		| (tmp2 << 20)	/* PortPhysicalState */
+		| (2 << 16)
+
+		/* LinkDownDefaultState */
+		/* M_KeyProtectBits == 0 */
+		/* NotImpl yet LMC == 0 (we can support all values) */
+		| (1 << 4)	/* LinkSpeedActive */
+		| (1 << 0);	/* LinkSpeedEnabled */
+	switch (dd->ipath_ibmtu) {
+	case 4096:
+		tmp = 5;
+		break;
+	case 2048:
+		tmp = 4;
+		break;
+	case 1024:
+		tmp = 3;
+		break;
+	case 512:
+		tmp = 2;
+		break;
+	case 256:
+		tmp = 1;
+		break;
+	default:		/* oops, something is wrong */
+		ipath_dbg("Problem, ipath_ibmtu 0x%x not a valid IB MTU, "
+			  "treat as 2048\n", dd->ipath_ibmtu);
+		tmp = 4;
+		break;
+	}
+	portinfo[9] = (tmp << 28)
+		/* NeighborMTU */
+		/* Notimpl MasterSMSL */
+		| (1 << 20)
+
+		/* VLCap */
+		/* Notimpl InitType (actually, an SMA decision) */
+		/* VLHighLimit is 0 (only one VL) */
+		; /* VLArbitrationHighCap is 0 (only one VL) */
+	portinfo[10] = 	/* VLArbitrationLowCap is 0 (only one VL) */
+		/* InitTypeReply is SMA decision */
+		(5 << 16)	/* MTUCap 4096 */
+		| (7 << 13)	/* VLStallCount */
+		| (0x1f << 8)	/* HOQLife */
+		| (1 << 4)
+
+		/* OperationalVLs 0 */
+		/* PartitionEnforcementInbound */
+		/* PartitionEnforcementOutbound not enforced */
+		/* FilterRawinbound not enforced */
+		;		/* FilterRawOutbound not enforced */
+	/* M_KeyViolations are not counted by hardware, SMA can count */
+	tmp = ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+	/* P_KeyViolations are counted by hardware. */
+	portinfo[11] = ((tmp & 0xffff) << 0);
+	portinfo[12] =
+		/* Q_KeyViolations are not counted by hardware */
+		(1 << 8)
+
+		/* GUIDCap */
+		/* SubnetTimeOut handled by SMA */
+		/* RespTimeValue handled by SMA */
+		;
+	/* LocalPhyErrors are programmed to max */
+	portinfo[12] |= (0xf << 20)
+		| (0xf << 16)   /* OverRunErrors are programmed to max */
+		;
+
+	return simple_read_from_buffer(buf, count, ppos, portinfo,
+				       sizeof portinfo);
+}
+
+static struct file_operations atomic_port_info_ops = {
+	.read = atomic_port_info_read,
+};
+
+static ssize_t flash_read(struct file *file, char __user *buf,
+			  size_t count, loff_t *ppos)
+{
+	struct ipath_devdata *dd;
+	ssize_t ret;
+	loff_t pos;
+	char *tmp;
+
+	pos = *ppos;
+
+	if ( pos < 0) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if (pos >= sizeof(struct ipath_flash)) {
+		ret = 0;
+		goto bail;
+	}
+
+	if (count > sizeof(struct ipath_flash) - pos)
+		count = sizeof(struct ipath_flash) - pos;
+
+	tmp = kmalloc(count, GFP_KERNEL);
+	if (!tmp) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	dd = file->f_dentry->d_inode->u.generic_ip;
+	if (ipath_eeprom_read(dd, pos, tmp, count)) {
+		ipath_dev_err(dd, "failed to read from flash\n");
+		ret = -ENXIO;
+		goto bail_tmp;
+	}
+
+	if (copy_to_user(buf, tmp, count)) {
+		ret = -EFAULT;
+		goto bail_tmp;
+	}
+
+	*ppos = pos + count;
+	ret = count;
+
+bail_tmp:
+	kfree(tmp);
+
+bail:
+	return ret;
+}
+
+static ssize_t flash_write(struct file *file, const char __user *buf,
+			   size_t count, loff_t *ppos)
+{
+	struct ipath_devdata *dd;
+	ssize_t ret;
+	loff_t pos;
+	char *tmp;
+
+	pos = *ppos;
+
+	if ( pos < 0) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if (pos >= sizeof(struct ipath_flash)) {
+		ret = 0;
+		goto bail;
+	}
+
+	if (count > sizeof(struct ipath_flash) - pos)
+		count = sizeof(struct ipath_flash) - pos;
+
+	tmp = kmalloc(count, GFP_KERNEL);
+	if (!tmp) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	if (copy_from_user(tmp, buf, count)) {
+		ret = -EFAULT;
+		goto bail_tmp;
+	}
+
+	dd = file->f_dentry->d_inode->u.generic_ip;
+	if (ipath_eeprom_write(dd, pos, tmp, count)) {
+		ret = -ENXIO;
+		ipath_dev_err(dd, "failed to write to flash\n");
+		goto bail_tmp;
+	}
+
+	*ppos = pos + count;
+	ret = count;
+
+bail_tmp:
+	kfree(tmp);
+
+bail:
+	return ret;
+}
+
+static struct file_operations flash_ops = {
+	.read = flash_read,
+	.write = flash_write,
+};
+
+static int create_device_files(struct super_block *sb,
+			       struct ipath_devdata *dd)
+{
+	struct dentry *dir, *tmp;
+	char unit[10];
+	int ret;
+
+	snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+	ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
+			  (struct file_operations *) &simple_dir_operations,
+			  dd);
+	if (ret) {
+		printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
+		goto bail;
+	}
+
+	ret = create_file("atomic_counters", S_IFREG|S_IRUGO, dir, &tmp,
+			  &atomic_counters_ops, dd);
+	if (ret) {
+		printk(KERN_ERR "create_file(%s/atomic_counters) "
+		       "failed: %d\n", unit, ret);
+		goto bail;
+	}
+
+	ret = create_file("node_info", S_IFREG|S_IRUGO, dir, &tmp,
+			  &atomic_node_info_ops, dd);
+	if (ret) {
+		printk(KERN_ERR "create_file(%s/node_info) "
+		       "failed: %d\n", unit, ret);
+		goto bail;
+	}
+
+	ret = create_file("port_info", S_IFREG|S_IRUGO, dir, &tmp,
+			  &atomic_port_info_ops, dd);
+	if (ret) {
+		printk(KERN_ERR "create_file(%s/port_info) "
+		       "failed: %d\n", unit, ret);
+		goto bail;
+	}
+
+	ret = create_file("flash", S_IFREG|S_IWUSR|S_IRUGO, dir, &tmp,
+			  &flash_ops, dd);
+	if (ret) {
+		printk(KERN_ERR "create_file(%s/flash) "
+		       "failed: %d\n", unit, ret);
+		goto bail;
+	}
+
+bail:
+	return ret;
+}
+
+static void remove_file(struct dentry *parent, char *name)
+{
+	struct dentry *tmp;
+
+	tmp = lookup_one_len(name, parent, strlen(name));
+
+	spin_lock(&dcache_lock);
+	spin_lock(&tmp->d_lock);
+	if (!(d_unhashed(tmp) && tmp->d_inode)) {
+		dget_locked(tmp);
+		__d_drop(tmp);
+		spin_unlock(&tmp->d_lock);
+		spin_unlock(&dcache_lock);
+		simple_unlink(parent->d_inode, tmp);
+	} else {
+		spin_unlock(&tmp->d_lock);
+		spin_unlock(&dcache_lock);
+	}
+}
+
+static int remove_device_files(struct super_block *sb,
+			       struct ipath_devdata *dd)
+{
+	struct dentry *dir, *root;
+	char unit[10];
+	int ret;
+
+	root = dget(sb->s_root);
+	mutex_lock(&root->d_inode->i_mutex);
+	snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+	dir = lookup_one_len(unit, root, strlen(unit));
+
+	if (IS_ERR(dir)) {
+		ret = PTR_ERR(dir);
+		printk(KERN_ERR "Lookup of %s failed\n", unit);
+		goto bail;
+	}
+
+	remove_file(dir, "flash");
+	remove_file(dir, "port_info");
+	remove_file(dir, "node_info");
+	remove_file(dir, "atomic_counters");
+	d_delete(dir);
+	ret = simple_rmdir(root->d_inode, dir);
+
+bail:
+	mutex_unlock(&root->d_inode->i_mutex);
+	dput(root);
+	return ret;
+}
+
+static int ipathfs_fill_super(struct super_block *sb, void *data,
+			      int silent)
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+	int ret;
+
+	static struct tree_descr files[] = {
+		[1] = {"atomic_stats", &atomic_stats_ops, S_IRUGO},
+		{""},
+	};
+
+	ret = simple_fill_super(sb, IPATHFS_MAGIC, files);
+	if (ret) {
+		printk(KERN_ERR "simple_fill_super failed: %d\n", ret);
+		goto bail;
+	}
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		spin_unlock_irqrestore(&ipath_devs_lock, flags);
+		ret = create_device_files(sb, dd);
+		if (ret) {
+			deactivate_super(sb);
+			goto bail;
+		}
+		spin_lock_irqsave(&ipath_devs_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+bail:
+	return ret;
+}
+
+static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type,
+				        int flags, const char *dev_name,
+					void *data)
+{
+	ipath_super = get_sb_single(fs_type, flags, data,
+				    ipathfs_fill_super);
+	return ipath_super;
+}
+
+static void ipathfs_kill_super(struct super_block *s)
+{
+	kill_litter_super(s);
+	ipath_super = NULL;
+}
+
+int ipathfs_add_device(struct ipath_devdata *dd)
+{
+	int ret;
+
+	if (ipath_super == NULL) {
+		ret = 0;
+		goto bail;
+	}
+
+	ret = create_device_files(ipath_super, dd);
+
+bail:
+	return ret;
+}
+
+int ipathfs_remove_device(struct ipath_devdata *dd)
+{
+	int ret;
+
+	if (ipath_super == NULL) {
+		ret = 0;
+		goto bail;
+	}
+
+	ret = remove_device_files(ipath_super, dd);
+
+bail:
+	return ret;
+}
+
+static struct file_system_type ipathfs_fs_type = {
+	.owner =	THIS_MODULE,
+	.name =		"ipathfs",
+	.get_sb =	ipathfs_get_sb,
+	.kill_sb =	ipathfs_kill_super,
+};
+
+int __init ipath_init_ipathfs(void)
+{
+	return register_filesystem(&ipathfs_fs_type);
+}
+
+void __exit ipath_exit_ipathfs(void)
+{
+	unregister_filesystem(&ipathfs_fs_type);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c
new file mode 100644
index 0000000..4652435
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ht400.c
@@ -0,0 +1,1586 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file contains all of the code that is specific to the InfiniPath
+ * HT-400 chip.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This lists the InfiniPath HT400 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ *
+ * The names are in InterCap form because they're taken straight from
+ * the chip specification.  Since they're only used in this file, they
+ * don't pollute the rest of the source.
+*/
+
+struct _infinipath_do_not_use_kernel_regs {
+	unsigned long long Revision;
+	unsigned long long Control;
+	unsigned long long PageAlign;
+	unsigned long long PortCnt;
+	unsigned long long DebugPortSelect;
+	unsigned long long DebugPort;
+	unsigned long long SendRegBase;
+	unsigned long long UserRegBase;
+	unsigned long long CounterRegBase;
+	unsigned long long Scratch;
+	unsigned long long ReservedMisc1;
+	unsigned long long InterruptConfig;
+	unsigned long long IntBlocked;
+	unsigned long long IntMask;
+	unsigned long long IntStatus;
+	unsigned long long IntClear;
+	unsigned long long ErrorMask;
+	unsigned long long ErrorStatus;
+	unsigned long long ErrorClear;
+	unsigned long long HwErrMask;
+	unsigned long long HwErrStatus;
+	unsigned long long HwErrClear;
+	unsigned long long HwDiagCtrl;
+	unsigned long long MDIO;
+	unsigned long long IBCStatus;
+	unsigned long long IBCCtrl;
+	unsigned long long ExtStatus;
+	unsigned long long ExtCtrl;
+	unsigned long long GPIOOut;
+	unsigned long long GPIOMask;
+	unsigned long long GPIOStatus;
+	unsigned long long GPIOClear;
+	unsigned long long RcvCtrl;
+	unsigned long long RcvBTHQP;
+	unsigned long long RcvHdrSize;
+	unsigned long long RcvHdrCnt;
+	unsigned long long RcvHdrEntSize;
+	unsigned long long RcvTIDBase;
+	unsigned long long RcvTIDCnt;
+	unsigned long long RcvEgrBase;
+	unsigned long long RcvEgrCnt;
+	unsigned long long RcvBufBase;
+	unsigned long long RcvBufSize;
+	unsigned long long RxIntMemBase;
+	unsigned long long RxIntMemSize;
+	unsigned long long RcvPartitionKey;
+	unsigned long long ReservedRcv[10];
+	unsigned long long SendCtrl;
+	unsigned long long SendPIOBufBase;
+	unsigned long long SendPIOSize;
+	unsigned long long SendPIOBufCnt;
+	unsigned long long SendPIOAvailAddr;
+	unsigned long long TxIntMemBase;
+	unsigned long long TxIntMemSize;
+	unsigned long long ReservedSend[9];
+	unsigned long long SendBufferError;
+	unsigned long long SendBufferErrorCONT1;
+	unsigned long long SendBufferErrorCONT2;
+	unsigned long long SendBufferErrorCONT3;
+	unsigned long long ReservedSBE[4];
+	unsigned long long RcvHdrAddr0;
+	unsigned long long RcvHdrAddr1;
+	unsigned long long RcvHdrAddr2;
+	unsigned long long RcvHdrAddr3;
+	unsigned long long RcvHdrAddr4;
+	unsigned long long RcvHdrAddr5;
+	unsigned long long RcvHdrAddr6;
+	unsigned long long RcvHdrAddr7;
+	unsigned long long RcvHdrAddr8;
+	unsigned long long ReservedRHA[7];
+	unsigned long long RcvHdrTailAddr0;
+	unsigned long long RcvHdrTailAddr1;
+	unsigned long long RcvHdrTailAddr2;
+	unsigned long long RcvHdrTailAddr3;
+	unsigned long long RcvHdrTailAddr4;
+	unsigned long long RcvHdrTailAddr5;
+	unsigned long long RcvHdrTailAddr6;
+	unsigned long long RcvHdrTailAddr7;
+	unsigned long long RcvHdrTailAddr8;
+	unsigned long long ReservedRHTA[7];
+	unsigned long long Sync;	/* Software only */
+	unsigned long long Dump;	/* Software only */
+	unsigned long long SimVer;	/* Software only */
+	unsigned long long ReservedSW[5];
+	unsigned long long SerdesConfig0;
+	unsigned long long SerdesConfig1;
+	unsigned long long SerdesStatus;
+	unsigned long long XGXSConfig;
+	unsigned long long ReservedSW2[4];
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+    struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_ht_kregs = {
+	.kr_control = IPATH_KREG_OFFSET(Control),
+	.kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+	.kr_debugport = IPATH_KREG_OFFSET(DebugPort),
+	.kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+	.kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+	.kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+	.kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+	.kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+	.kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+	.kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+	.kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+	.kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+	.kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+	.kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+	.kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+	.kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+	.kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+	.kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+	.kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+	.kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+	.kr_intclear = IPATH_KREG_OFFSET(IntClear),
+	.kr_interruptconfig = IPATH_KREG_OFFSET(InterruptConfig),
+	.kr_intmask = IPATH_KREG_OFFSET(IntMask),
+	.kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+	.kr_mdio = IPATH_KREG_OFFSET(MDIO),
+	.kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+	.kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+	.kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+	.kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+	.kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+	.kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+	.kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+	.kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+	.kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+	.kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+	.kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+	.kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+	.kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+	.kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+	.kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+	.kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+	.kr_revision = IPATH_KREG_OFFSET(Revision),
+	.kr_scratch = IPATH_KREG_OFFSET(Scratch),
+	.kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+	.kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+	.kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+	.kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+	.kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+	.kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+	.kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+	.kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+	.kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+	.kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+	.kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+	.kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+	.kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+	.kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+	/*
+	 * These should not be used directly via ipath_read_kreg64(),
+	 * use them with ipath_read_kreg64_port(),
+	 */
+	.kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+	.kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0)
+};
+
+static const struct ipath_cregs ipath_ht_cregs = {
+	.cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+	.cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+	.cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+	.cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+	.cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+	.cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+	.cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+	.cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+	.cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+	.cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+	.cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+	.cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+	/* calc from Reg_CounterRegBase + offset */
+	.cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+	.cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+	.cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+	.cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+	.cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+	.cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+	.cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+	.cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+	.cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+	.cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+	.cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+	.cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+	.cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+	.cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+	.cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+	.cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+	.cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+	.cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+	.cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+	.cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+	.cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1FF
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1FF
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_HTCMEMPARITYERR_MASK 0x3FFFFFULL
+#define INFINIPATH_HWE_HTCLNKABYTE0CRCERR   0x0000000000800000ULL
+#define INFINIPATH_HWE_HTCLNKABYTE1CRCERR   0x0000000001000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE0CRCERR   0x0000000002000000ULL
+#define INFINIPATH_HWE_HTCLNKBBYTE1CRCERR   0x0000000004000000ULL
+#define INFINIPATH_HWE_HTCMISCERR4          0x0000000008000000ULL
+#define INFINIPATH_HWE_HTCMISCERR5          0x0000000010000000ULL
+#define INFINIPATH_HWE_HTCMISCERR6          0x0000000020000000ULL
+#define INFINIPATH_HWE_HTCMISCERR7          0x0000000040000000ULL
+#define INFINIPATH_HWE_HTCBUSTREQPARITYERR  0x0000000080000000ULL
+#define INFINIPATH_HWE_HTCBUSTRESPPARITYERR 0x0000000100000000ULL
+#define INFINIPATH_HWE_HTCBUSIREQPARITYERR  0x0000000200000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP       0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP       0x0100000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_FBSLIP        0x0200000000000000ULL
+#define INFINIPATH_HWE_HTBPLL_RFSLIP        0x0400000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_FBSLIP        0x0800000000000000ULL
+#define INFINIPATH_HWE_HTAPLL_RFSLIP        0x1000000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED      0x2000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST     0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_CORRECT     0x0000000000008000
+
+/*
+ * masks and bits that are different in different chips, or present only
+ * in one
+ */
+static const ipath_err_t infinipath_hwe_htcmemparityerr_mask =
+    INFINIPATH_HWE_HTCMEMPARITYERR_MASK;
+static const ipath_err_t infinipath_hwe_htcmemparityerr_shift =
+    INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT;
+
+static const ipath_err_t infinipath_hwe_htclnkabyte0crcerr =
+    INFINIPATH_HWE_HTCLNKABYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkabyte1crcerr =
+    INFINIPATH_HWE_HTCLNKABYTE1CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte0crcerr =
+    INFINIPATH_HWE_HTCLNKBBYTE0CRCERR;
+static const ipath_err_t infinipath_hwe_htclnkbbyte1crcerr =
+    INFINIPATH_HWE_HTCLNKBBYTE1CRCERR;
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA \
+	(1ULL << (_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL \
+	(1ULL << (_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/* keep the code below somewhat more readonable; not used elsewhere */
+#define _IPATH_HTLINK0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr |	\
+				infinipath_hwe_htclnkabyte1crcerr)
+#define _IPATH_HTLINK1_CRCBITS (infinipath_hwe_htclnkbbyte0crcerr |	\
+				infinipath_hwe_htclnkbbyte1crcerr)
+#define _IPATH_HTLANE0_CRCBITS (infinipath_hwe_htclnkabyte0crcerr |	\
+				infinipath_hwe_htclnkbbyte0crcerr)
+#define _IPATH_HTLANE1_CRCBITS (infinipath_hwe_htclnkabyte1crcerr |	\
+				infinipath_hwe_htclnkbbyte1crcerr)
+
+static void hwerr_crcbits(struct ipath_devdata *dd, ipath_err_t hwerrs,
+			  char *msg, size_t msgl)
+{
+	char bitsmsg[64];
+	ipath_err_t crcbits = hwerrs &
+		(_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS);
+	/* don't check if 8bit HT */
+	if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+		crcbits &= ~infinipath_hwe_htclnkabyte1crcerr;
+	/* don't check if 8bit HT */
+	if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+		crcbits &= ~infinipath_hwe_htclnkbbyte1crcerr;
+	/*
+	 * we'll want to ignore link errors on link that is
+	 * not in use, if any.  For now, complain about both
+	 */
+	if (crcbits) {
+		u16 ctrl0, ctrl1;
+		snprintf(bitsmsg, sizeof bitsmsg,
+			 "[HT%s lane %s CRC (%llx); ignore till reload]",
+			 !(crcbits & _IPATH_HTLINK1_CRCBITS) ?
+			 "0 (A)" : (!(crcbits & _IPATH_HTLINK0_CRCBITS)
+				    ? "1 (B)" : "0+1 (A+B)"),
+			 !(crcbits & _IPATH_HTLANE1_CRCBITS) ? "0"
+			 : (!(crcbits & _IPATH_HTLANE0_CRCBITS) ? "1" :
+			    "0+1"), (unsigned long long) crcbits);
+		strlcat(msg, bitsmsg, msgl);
+
+		/*
+		 * print extra info for debugging.  slave/primary
+		 * config word 4, 8 (link control 0, 1)
+		 */
+
+		if (pci_read_config_word(dd->pcidev,
+					 dd->ipath_ht_slave_off + 0x4,
+					 &ctrl0))
+			dev_info(&dd->pcidev->dev, "Couldn't read "
+				 "linkctrl0 of slave/primary "
+				 "config block\n");
+		else if (!(ctrl0 & 1 << 6))
+			/* not if EOC bit set */
+			ipath_dbg("HT linkctrl0 0x%x%s%s\n", ctrl0,
+				  ((ctrl0 >> 8) & 7) ? " CRC" : "",
+				  ((ctrl0 >> 4) & 1) ? "linkfail" :
+				  "");
+		if (pci_read_config_word(dd->pcidev,
+					 dd->ipath_ht_slave_off + 0x8,
+					 &ctrl1))
+			dev_info(&dd->pcidev->dev, "Couldn't read "
+				 "linkctrl1 of slave/primary "
+				 "config block\n");
+		else if (!(ctrl1 & 1 << 6))
+			/* not if EOC bit set */
+			ipath_dbg("HT linkctrl1 0x%x%s%s\n", ctrl1,
+				  ((ctrl1 >> 8) & 7) ? " CRC" : "",
+				  ((ctrl1 >> 4) & 1) ? "linkfail" :
+				  "");
+
+		/* disable until driver reloaded */
+		dd->ipath_hwerrmask &= ~crcbits;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+		ipath_dbg("HT crc errs: %s\n", msg);
+	} else
+		ipath_dbg("ignoring HT crc errors 0x%llx, "
+			  "not in use\n", (unsigned long long)
+			  (hwerrs & (_IPATH_HTLINK0_CRCBITS |
+				     _IPATH_HTLINK1_CRCBITS)));
+}
+
+/**
+ * ipath_ht_handle_hwerrors - display hardware errors
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid
+ * excessive stack use.  Most hardware errors are catastrophic, but for
+ * right now, we'll print them and continue.
+ * We reuse the same message buffer as ipath_handle_errors() to avoid
+ * excessive stack usage.
+ */
+static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+				     size_t msgl)
+{
+	ipath_err_t hwerrs;
+	u32 bits, ctrl;
+	int isfatal = 0;
+	char bitsmsg[64];
+
+	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+
+	if (!hwerrs) {
+		ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+		/*
+		 * better than printing cofusing messages
+		 * This seems to be related to clearing the crc error, or
+		 * the pll error during init.
+		 */
+		goto bail;
+	} else if (hwerrs == -1LL) {
+		ipath_dev_err(dd, "Read of hardware error status failed "
+			      "(all bits set); ignoring\n");
+		goto bail;
+	}
+	ipath_stats.sps_hwerrs++;
+
+	/* Always clear the error status register, except MEMBISTFAIL,
+	 * regardless of whether we continue or stop using the chip.
+	 * We want that set so we know it failed, even across driver reload.
+	 * We'll still ignore it in the hwerrmask.  We do this partly for
+	 * diagnostics, but also for support */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+			 hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+	hwerrs &= dd->ipath_hwerrmask;
+
+	/*
+	 * make sure we get this much out, unless told to be quiet,
+	 * or it's occurred within the last 5 seconds
+	 */
+	if ((hwerrs & ~dd->ipath_lasthwerror) ||
+	    (ipath_debug & __IPATH_VERBDBG))
+		dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+			 "(cleared)\n", (unsigned long long) hwerrs);
+	dd->ipath_lasthwerror |= hwerrs;
+
+	if (hwerrs & ~infinipath_hwe_bitsextant)
+		ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+			      "%llx set\n", (unsigned long long)
+			      (hwerrs & ~infinipath_hwe_bitsextant));
+
+	ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+	if (ctrl & INFINIPATH_C_FREEZEMODE) {
+		if (hwerrs) {
+			/*
+			 * if any set that we aren't ignoring; only
+			 * make the complaint once, in case it's stuck
+			 * or recurring, and we get here multiple
+			 * times.
+			 */
+			if (dd->ipath_flags & IPATH_INITTED) {
+				ipath_dev_err(dd, "Fatal Error (freeze "
+					      "mode), no longer usable\n");
+				isfatal = 1;
+			}
+			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+			/* mark as having had error */
+			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+			/*
+			 * mark as not usable, at a minimum until driver
+			 * is reloaded, probably until reboot, since no
+			 * other reset is possible.
+			 */
+			dd->ipath_flags &= ~IPATH_INITTED;
+		} else {
+			ipath_dbg("Clearing freezemode on ignored hardware "
+				  "error\n");
+			ctrl &= ~INFINIPATH_C_FREEZEMODE;
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+					 ctrl);
+		}
+	}
+
+	*msg = '\0';
+
+	/*
+	 * may someday want to decode into which bits are which
+	 * functional area for parity errors, etc.
+	 */
+	if (hwerrs & (infinipath_hwe_htcmemparityerr_mask
+		      << INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_HTCMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg, "[HTC Parity Errs %x] ",
+			 bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+		      << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+			 bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+		      << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+			 bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+		strlcat(msg, "[IB2IPATH Parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+		strlcat(msg, "[IPATH2IB Parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_HTCBUSIREQPARITYERR)
+		strlcat(msg, "[HTC Ireq Parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_HTCBUSTREQPARITYERR)
+		strlcat(msg, "[HTC Treq Parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_HTCBUSTRESPPARITYERR)
+		strlcat(msg, "[HTC Tresp Parity]", msgl);
+
+	if (hwerrs & (_IPATH_HTLINK0_CRCBITS | _IPATH_HTLINK1_CRCBITS))
+		hwerr_crcbits(dd, hwerrs, msg, msgl);
+
+	if (hwerrs & INFINIPATH_HWE_HTCMISCERR5)
+		strlcat(msg, "[HT core Misc5]", msgl);
+	if (hwerrs & INFINIPATH_HWE_HTCMISCERR6)
+		strlcat(msg, "[HT core Misc6]", msgl);
+	if (hwerrs & INFINIPATH_HWE_HTCMISCERR7)
+		strlcat(msg, "[HT core Misc7]", msgl);
+	if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+		strlcat(msg, "[Memory BIST test failed, HT-400 unusable]",
+			msgl);
+		/* ignore from now on, so disable until driver reloaded */
+		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |	\
+			 INFINIPATH_HWE_COREPLL_RFSLIP |	\
+			 INFINIPATH_HWE_HTBPLL_FBSLIP |		\
+			 INFINIPATH_HWE_HTBPLL_RFSLIP |		\
+			 INFINIPATH_HWE_HTAPLL_FBSLIP |		\
+			 INFINIPATH_HWE_HTAPLL_RFSLIP)
+
+	if (hwerrs & _IPATH_PLL_FAIL) {
+		snprintf(bitsmsg, sizeof bitsmsg,
+			 "[PLL failed (%llx), HT-400 unusable]",
+			 (unsigned long long) (hwerrs & _IPATH_PLL_FAIL));
+		strlcat(msg, bitsmsg, msgl);
+		/* ignore from now on, so disable until driver reloaded */
+		dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+
+	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+		/*
+		 * If it occurs, it is left masked since the eternal
+		 * interface is unused
+		 */
+		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+
+	if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+		strlcat(msg, "[Rx Dsync]", msgl);
+	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+		strlcat(msg, "[SerDes PLL]", msgl);
+
+	ipath_dev_err(dd, "%s hardware error\n", msg);
+	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)
+		/*
+		 * for status file; if no trailing brace is copied,
+		 * we'll know it was truncated.
+		 */
+		snprintf(dd->ipath_freezemsg,
+			 dd->ipath_freezelen, "{%s}", msg);
+
+bail:;
+}
+
+/**
+ * ipath_ht_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * fill in the board name, based on the board revision register
+ */
+static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+			      size_t namelen)
+{
+	char *n = NULL;
+	u8 boardrev = dd->ipath_boardrev;
+	int ret;
+
+	switch (boardrev) {
+	case 4:		/* Ponderosa is one of the bringup boards */
+		n = "Ponderosa";
+		break;
+	case 5:		/* HT-460 original production board */
+		n = "InfiniPath_HT-460";
+		break;
+	case 6:
+		n = "OEM_Board_3";
+		break;
+	case 7:
+		/* HT-460 small form factor production board */
+		n = "InfiniPath_HT-465";
+		break;
+	case 8:
+		n = "LS/X-1";
+		break;
+	case 9:		/* Comstock bringup test board */
+		n = "Comstock";
+		break;
+	case 10:
+		n = "OEM_Board_2";
+		break;
+	case 11:
+		n = "InfiniPath_HT-470";
+		break;
+	case 12:
+		n = "OEM_Board_4";
+		break;
+	default:		/* don't know, just print the number */
+		ipath_dev_err(dd, "Don't yet know about board "
+			      "with ID %u\n", boardrev);
+		snprintf(name, namelen, "Unknown_InfiniPath_HT-4xx_%u",
+			 boardrev);
+		break;
+	}
+	if (n)
+		snprintf(name, namelen, "%s", n);
+
+	if (dd->ipath_majrev != 3 || dd->ipath_minrev != 2) {
+		/*
+		 * This version of the driver only supports the HT-400
+		 * Rev 3.2
+		 */
+		ipath_dev_err(dd,
+			      "Unsupported HT-400 revision %u.%u!\n",
+			      dd->ipath_majrev, dd->ipath_minrev);
+		ret = 1;
+		goto bail;
+	}
+	/*
+	 * pkt/word counters are 32 bit, and therefore wrap fast enough
+	 * that we snapshot them from a timer, and maintain 64 bit shadow
+	 * copies
+	 */
+	dd->ipath_flags |= IPATH_32BITCOUNTERS;
+	if (dd->ipath_htspeed != 800)
+		ipath_dev_err(dd,
+			      "Incorrectly configured for HT @ %uMHz\n",
+			      dd->ipath_htspeed);
+	if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||
+	    dd->ipath_boardrev == 6)
+		dd->ipath_flags |= IPATH_GPIO_INTR;
+	else
+		dd->ipath_flags |= IPATH_POLL_RX_INTR;
+	if (dd->ipath_boardrev == 8) {	/* LS/X-1 */
+		u64 val;
+		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+		if (val & INFINIPATH_EXTS_SERDESSEL) {
+			/*
+			 * hardware disabled
+			 *
+			 * This means that the chip is hardware disabled,
+			 * and will not be able to bring up the link,
+			 * in any case.  We special case this and abort
+			 * early, to avoid later messages.  We also set
+			 * the DISABLED status bit
+			 */
+			ipath_dbg("Unit %u is hardware-disabled\n",
+				  dd->ipath_unit);
+			*dd->ipath_statusp |= IPATH_STATUS_DISABLED;
+			/* this value is handled differently */
+			ret = 2;
+			goto bail;
+		}
+	}
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static void ipath_check_htlink(struct ipath_devdata *dd)
+{
+	u8 linkerr, link_off, i;
+
+	for (i = 0; i < 2; i++) {
+		link_off = dd->ipath_ht_slave_off + i * 4 + 0xd;
+		if (pci_read_config_byte(dd->pcidev, link_off, &linkerr))
+			dev_info(&dd->pcidev->dev, "Couldn't read "
+				 "linkerror%d of HT slave/primary block\n",
+				 i);
+		else if (linkerr & 0xf0) {
+			ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+				   "clearing\n", linkerr >> 4, i);
+			/*
+			 * writing the linkerr bits that are set should
+			 * clear them
+			 */
+			if (pci_write_config_byte(dd->pcidev, link_off,
+						  linkerr))
+				ipath_dbg("Failed write to clear HT "
+					  "linkerror%d\n", i);
+			if (pci_read_config_byte(dd->pcidev, link_off,
+						 &linkerr))
+				dev_info(&dd->pcidev->dev,
+					 "Couldn't reread linkerror%d of "
+					 "HT slave/primary block\n", i);
+			else if (linkerr & 0xf0)
+				dev_info(&dd->pcidev->dev,
+					 "HT linkerror%d bits 0x%x "
+					 "couldn't be cleared\n",
+					 i, linkerr >> 4);
+		}
+	}
+}
+
+static int ipath_setup_ht_reset(struct ipath_devdata *dd)
+{
+	ipath_dbg("No reset possible for HT-400\n");
+	return 0;
+}
+
+#define HT_CAPABILITY_ID   0x08	/* HT capabilities not defined in kernel */
+#define HT_INTR_DISC_CONFIG  0x80	/* HT interrupt and discovery cap */
+#define HT_INTR_REG_INDEX    2	/* intconfig requires indirect accesses */
+
+/*
+ * Bits 13-15 of command==0 is slave/primary block.  Clear any HT CRC
+ * errors.  We only bother to do this at load time, because it's OK if
+ * it happened before we were loaded (first time after boot/reset),
+ * but any time after that, it's fatal anyway.  Also need to not check
+ * for for upper byte errors if we are in 8 bit mode, so figure out
+ * our width.  For now, at least, also complain if it's 8 bit.
+ */
+static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev,
+			     int pos, u8 cap_type)
+{
+	u8 linkwidth = 0, linkerr, link_a_b_off, link_off;
+	u16 linkctrl = 0;
+	int i;
+
+	dd->ipath_ht_slave_off = pos;
+	/* command word, master_host bit */
+	/* master host || slave */
+	if ((cap_type >> 2) & 1)
+		link_a_b_off = 4;
+	else
+		link_a_b_off = 0;
+	ipath_cdbg(VERBOSE, "HT%u (Link %c) connected to processor\n",
+		   link_a_b_off ? 1 : 0,
+		   link_a_b_off ? 'B' : 'A');
+
+	link_a_b_off += pos;
+
+	/*
+	 * check both link control registers; clear both HT CRC sets if
+	 * necessary.
+	 */
+	for (i = 0; i < 2; i++) {
+		link_off = pos + i * 4 + 0x4;
+		if (pci_read_config_word(pdev, link_off, &linkctrl))
+			ipath_dev_err(dd, "Couldn't read HT link control%d "
+				      "register\n", i);
+		else if (linkctrl & (0xf << 8)) {
+			ipath_cdbg(VERBOSE, "Clear linkctrl%d CRC Error "
+				   "bits %x\n", i, linkctrl & (0xf << 8));
+			/*
+			 * now write them back to clear the error.
+			 */
+			pci_write_config_byte(pdev, link_off,
+					      linkctrl & (0xf << 8));
+		}
+	}
+
+	/*
+	 * As with HT CRC bits, same for protocol errors that might occur
+	 * during boot.
+	 */
+	for (i = 0; i < 2; i++) {
+		link_off = pos + i * 4 + 0xd;
+		if (pci_read_config_byte(pdev, link_off, &linkerr))
+			dev_info(&pdev->dev, "Couldn't read linkerror%d "
+				 "of HT slave/primary block\n", i);
+		else if (linkerr & 0xf0) {
+			ipath_cdbg(VERBOSE, "HT linkerr%d bits 0x%x set, "
+				   "clearing\n", linkerr >> 4, i);
+			/*
+			 * writing the linkerr bits that are set will clear
+			 * them
+			 */
+			if (pci_write_config_byte
+			    (pdev, link_off, linkerr))
+				ipath_dbg("Failed write to clear HT "
+					  "linkerror%d\n", i);
+			if (pci_read_config_byte(pdev, link_off, &linkerr))
+				dev_info(&pdev->dev, "Couldn't reread "
+					 "linkerror%d of HT slave/primary "
+					 "block\n", i);
+			else if (linkerr & 0xf0)
+				dev_info(&pdev->dev, "HT linkerror%d bits "
+					 "0x%x couldn't be cleared\n",
+					 i, linkerr >> 4);
+		}
+	}
+
+	/*
+	 * this is just for our link to the host, not devices connected
+	 * through tunnel.
+	 */
+
+	if (pci_read_config_byte(pdev, link_a_b_off + 7, &linkwidth))
+		ipath_dev_err(dd, "Couldn't read HT link width "
+			      "config register\n");
+	else {
+		u32 width;
+		switch (linkwidth & 7) {
+		case 5:
+			width = 4;
+			break;
+		case 4:
+			width = 2;
+			break;
+		case 3:
+			width = 32;
+			break;
+		case 1:
+			width = 16;
+			break;
+		case 0:
+		default:	/* if wrong, assume 8 bit */
+			width = 8;
+			break;
+		}
+
+		dd->ipath_htwidth = width;
+
+		if (linkwidth != 0x11) {
+			ipath_dev_err(dd, "Not configured for 16 bit HT "
+				      "(%x)\n", linkwidth);
+			if (!(linkwidth & 0xf)) {
+				ipath_dbg("Will ignore HT lane1 errors\n");
+				dd->ipath_flags |= IPATH_8BIT_IN_HT0;
+			}
+		}
+	}
+
+	/*
+	 * this is just for our link to the host, not devices connected
+	 * through tunnel.
+	 */
+	if (pci_read_config_byte(pdev, link_a_b_off + 0xd, &linkwidth))
+		ipath_dev_err(dd, "Couldn't read HT link frequency "
+			      "config register\n");
+	else {
+		u32 speed;
+		switch (linkwidth & 0xf) {
+		case 6:
+			speed = 1000;
+			break;
+		case 5:
+			speed = 800;
+			break;
+		case 4:
+			speed = 600;
+			break;
+		case 3:
+			speed = 500;
+			break;
+		case 2:
+			speed = 400;
+			break;
+		case 1:
+			speed = 300;
+			break;
+		default:
+			/*
+			 * assume reserved and vendor-specific are 200...
+			 */
+		case 0:
+			speed = 200;
+			break;
+		}
+		dd->ipath_htspeed = speed;
+	}
+}
+
+static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev,
+			    int pos)
+{
+	u32 int_handler_addr_lower;
+	u32 int_handler_addr_upper;
+	u64 ihandler;
+	u32 intvec;
+
+	/* use indirection register to get the intr handler */
+	pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10);
+	pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower);
+	pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11);
+	pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper);
+
+	ihandler = (u64) int_handler_addr_lower |
+		((u64) int_handler_addr_upper << 32);
+
+	/*
+	 * kernels with CONFIG_PCI_MSI set the vector in the irq field of
+	 * struct pci_device, so we use that to program the HT-400 internal
+	 * interrupt register (not config space) with that value. The BIOS
+	 * must still have done the basic MSI setup.
+	 */
+	intvec = pdev->irq;
+	/*
+	 * clear any vector bits there; normally not set but we'll overload
+	 * this for some debug purposes (setting the HTC debug register
+	 * value from software, rather than GPIOs), so it might be set on a
+	 * driver reload.
+	 */
+	ihandler &= ~0xff0000;
+	/* x86 vector goes in intrinfo[23:16] */
+	ihandler |= intvec << 16;
+	ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, "
+		   "interruptconfig %llx\n", int_handler_addr_lower,
+		   int_handler_addr_upper, intvec,
+		   (unsigned long long) ihandler);
+
+	/* can't program yet, so save for interrupt setup */
+	dd->ipath_intconfig = ihandler;
+	/* keep going, so we find link control stuff also */
+
+	return ihandler != 0;
+}
+
+/**
+ * ipath_setup_ht_config - setup the interruptconfig register
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * setup the interruptconfig register from the HT config info.
+ * Also clear CRC errors in HT linkcontrol, if necessary.
+ * This is done only for the real hardware.  It is done before
+ * chip address space is initted, so can't touch infinipath registers
+ */
+static int ipath_setup_ht_config(struct ipath_devdata *dd,
+				 struct pci_dev *pdev)
+{
+	int pos, ret = 0;
+	int ihandler = 0;
+
+	/*
+	 * Read the capability info to find the interrupt info, and also
+	 * handle clearing CRC errors in linkctrl register if necessary.  We
+	 * do this early, before we ever enable errors or hardware errors,
+	 * mostly to avoid causing the chip to enter freeze mode.
+	 */
+	pos = pci_find_capability(pdev, HT_CAPABILITY_ID);
+	if (!pos) {
+		ipath_dev_err(dd, "Couldn't find HyperTransport "
+			      "capability; no interrupts\n");
+		ret = -ENODEV;
+		goto bail;
+	}
+	do {
+		u8 cap_type;
+
+		/* the HT capability type byte is 3 bytes after the
+		 * capability byte.
+		 */
+		if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
+			dev_info(&pdev->dev, "Couldn't read config "
+				 "command @ %d\n", pos);
+			continue;
+		}
+		if (!(cap_type & 0xE0))
+			slave_or_pri_blk(dd, pdev, pos, cap_type);
+		else if (cap_type == HT_INTR_DISC_CONFIG)
+			ihandler = set_int_handler(dd, pdev, pos);
+	} while ((pos = pci_find_next_capability(pdev, pos,
+						 HT_CAPABILITY_ID)));
+
+	if (!ihandler) {
+		ipath_dev_err(dd, "Couldn't find interrupt handler in "
+			      "config space\n");
+		ret = -ENODEV;
+	}
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_setup_ht_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * Called during driver unload.
+ * This is currently a nop for the HT-400, not for all chips
+ */
+static void ipath_setup_ht_cleanup(struct ipath_devdata *dd)
+{
+}
+
+/**
+ * ipath_setup_ht_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+ *
+ * Set the state of the two external LEDs, to indicate physical and
+ * logical state of IB link.   For this chip (at least with recommended
+ * board pinouts), LED1 is Green (physical state), and LED2 is Yellow
+ * (logical state)
+ *
+ * Note:  We try to match the Mellanox HCA LED behavior as best
+ * we can.  Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate.  That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
+				     u64 lst, u64 ltst)
+{
+	u64 extctl;
+
+	/* the diags use the LED to indicate diag info, so we leave
+	 * the external LED alone when the diags are running */
+	if (ipath_diag_inuse)
+		return;
+
+	/*
+	 * start by setting both LED control bits to off, then turn
+	 * on the appropriate bit(s).
+	 */
+	if (dd->ipath_boardrev == 8) { /* LS/X-1 uses different pins */
+		/*
+		 * major difference is that INFINIPATH_EXTC_LEDGBLERR_OFF
+		 * is inverted,  because it is normally used to indicate
+		 * a hardware fault at reset, if there were errors
+		 */
+		extctl = (dd->ipath_extctrl & ~INFINIPATH_EXTC_LEDGBLOK_ON)
+			| INFINIPATH_EXTC_LEDGBLERR_OFF;
+		if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+			extctl &= ~INFINIPATH_EXTC_LEDGBLERR_OFF;
+		if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+			extctl |= INFINIPATH_EXTC_LEDGBLOK_ON;
+	}
+	else {
+		extctl = dd->ipath_extctrl &
+			~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+			  INFINIPATH_EXTC_LED2PRIPORT_ON);
+		if (ltst == INFINIPATH_IBCS_LT_STATE_LINKUP)
+			extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+		if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+			extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+	}
+	dd->ipath_extctrl = extctl;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+static void ipath_init_ht_variables(void)
+{
+	ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+	ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+	ipath_gpio_sda = IPATH_GPIO_SDA;
+	ipath_gpio_scl = IPATH_GPIO_SCL;
+
+	infinipath_i_bitsextant =
+		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+		(INFINIPATH_I_RCVAVAIL_MASK <<
+		 INFINIPATH_I_RCVAVAIL_SHIFT) |
+		INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+		INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+
+	infinipath_e_bitsextant =
+		INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+		INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+		INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+		INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+		INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+		INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+		INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+		INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+		INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+		INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+		INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+		INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+		INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+		INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+		INFINIPATH_E_HARDWARE;
+
+	infinipath_hwe_bitsextant =
+		(INFINIPATH_HWE_HTCMEMPARITYERR_MASK <<
+		 INFINIPATH_HWE_HTCMEMPARITYERR_SHIFT) |
+		(INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+		 INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) |
+		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+		 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+		INFINIPATH_HWE_HTCLNKABYTE0CRCERR |
+		INFINIPATH_HWE_HTCLNKABYTE1CRCERR |
+		INFINIPATH_HWE_HTCLNKBBYTE0CRCERR |
+		INFINIPATH_HWE_HTCLNKBBYTE1CRCERR |
+		INFINIPATH_HWE_HTCMISCERR4 |
+		INFINIPATH_HWE_HTCMISCERR5 | INFINIPATH_HWE_HTCMISCERR6 |
+		INFINIPATH_HWE_HTCMISCERR7 |
+		INFINIPATH_HWE_HTCBUSTREQPARITYERR |
+		INFINIPATH_HWE_HTCBUSTRESPPARITYERR |
+		INFINIPATH_HWE_HTCBUSIREQPARITYERR |
+		INFINIPATH_HWE_RXDSYNCMEMPARITYERR |
+		INFINIPATH_HWE_MEMBISTFAILED |
+		INFINIPATH_HWE_COREPLL_FBSLIP |
+		INFINIPATH_HWE_COREPLL_RFSLIP |
+		INFINIPATH_HWE_HTBPLL_FBSLIP |
+		INFINIPATH_HWE_HTBPLL_RFSLIP |
+		INFINIPATH_HWE_HTAPLL_FBSLIP |
+		INFINIPATH_HWE_HTAPLL_RFSLIP |
+		INFINIPATH_HWE_SERDESPLLFAILED |
+		INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+		INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+
+	infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+	infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/**
+ * ipath_ht_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
+{
+	ipath_err_t val;
+	u64 extsval;
+
+	extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+	if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+		ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+	ipath_check_htlink(dd);
+
+	/* barring bugs, all hwerrors become interrupts, which can */
+	val = -1LL;
+	/* don't look at crc lane1 if 8 bit */
+	if (dd->ipath_flags & IPATH_8BIT_IN_HT0)
+		val &= ~infinipath_hwe_htclnkabyte1crcerr;
+	/* don't look at crc lane1 if 8 bit */
+	if (dd->ipath_flags & IPATH_8BIT_IN_HT1)
+		val &= ~infinipath_hwe_htclnkbbyte1crcerr;
+
+	/*
+	 * disable RXDSYNCMEMPARITY because external serdes is unused,
+	 * and therefore the logic will never be used or initialized,
+	 * and uninitialized state will normally result in this error
+	 * being asserted.  Similarly for the external serdess pll
+	 * lock signal.
+	 */
+	val &= ~(INFINIPATH_HWE_SERDESPLLFAILED |
+		 INFINIPATH_HWE_RXDSYNCMEMPARITYERR);
+
+	/*
+	 * Disable MISCERR4 because of an inversion in the HT core
+	 * logic checking for errors that cause this bit to be set.
+	 * The errata can also cause the protocol error bit to be set
+	 * in the HT config space linkerror register(s).
+	 */
+	val &= ~INFINIPATH_HWE_HTCMISCERR4;
+
+	/*
+	 * PLL ignored because MDIO interface has a logic problem
+	 * for reads, on Comstock and Ponderosa.  BRINGUP
+	 */
+	if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
+		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+	dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_ht_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
+{
+	u64 val, config1;
+	int ret = 0, change = 0;
+
+	ipath_dbg("Trying to bringup serdes\n");
+
+	if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+	    INFINIPATH_HWE_SERDESPLLFAILED)
+	{
+		ipath_dbg("At start, serdes PLL failed bit set in "
+			  "hwerrstatus, clearing and continuing\n");
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+				 INFINIPATH_HWE_SERDESPLLFAILED);
+	}
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+	config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+	ipath_cdbg(VERBOSE, "Initial serdes status is config0=%llx "
+		   "config1=%llx, sstatus=%llx xgxs %llx\n",
+		   (unsigned long long) val, (unsigned long long) config1,
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+	/* force reset on */
+	val |= INFINIPATH_SERDC0_RESET_PLL
+		/* | INFINIPATH_SERDC0_RESET_MASK */
+		;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+	udelay(15);		/* need pll reset set at least for a bit */
+
+	if (val & INFINIPATH_SERDC0_RESET_PLL) {
+		u64 val2 = val &= ~INFINIPATH_SERDC0_RESET_PLL;
+		/* set lane resets, and tx idle, during pll reset */
+		val2 |= INFINIPATH_SERDC0_RESET_MASK |
+			INFINIPATH_SERDC0_TXIDLE;
+		ipath_cdbg(VERBOSE, "Clearing serdes PLL reset (writing "
+			   "%llx)\n", (unsigned long long) val2);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+				 val2);
+		/*
+		 * be sure chip saw it
+		 */
+		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+		/*
+		 * need pll reset clear at least 11 usec before lane
+		 * resets cleared; give it a few more
+		 */
+		udelay(15);
+		val = val2;	/* for check below */
+	}
+
+	if (val & (INFINIPATH_SERDC0_RESET_PLL |
+		   INFINIPATH_SERDC0_RESET_MASK |
+		   INFINIPATH_SERDC0_TXIDLE)) {
+		val &= ~(INFINIPATH_SERDC0_RESET_PLL |
+			 INFINIPATH_SERDC0_RESET_MASK |
+			 INFINIPATH_SERDC0_TXIDLE);
+		/* clear them */
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0,
+				 val);
+	}
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+		val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+			 INFINIPATH_XGXS_MDIOADDR_SHIFT);
+		/*
+		 * we use address 3
+		 */
+		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+		change = 1;
+	}
+	if (val & INFINIPATH_XGXS_RESET) {
+		/* normally true after boot */
+		val &= ~INFINIPATH_XGXS_RESET;
+		change = 1;
+	}
+	if (change)
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+	/* clear current and de-emphasis bits */
+	config1 &= ~0x0ffffffff00ULL;
+	/* set current to 20ma */
+	config1 |= 0x00000000000ULL;
+	/* set de-emphasis to -5.68dB */
+	config1 |= 0x0cccc000000ULL;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+	ipath_cdbg(VERBOSE, "After setup: serdes status is config0=%llx "
+		   "config1=%llx, sstatus=%llx xgxs %llx\n",
+		   (unsigned long long) val, (unsigned long long) config1,
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+	if (!ipath_waitfor_mdio_cmdready(dd)) {
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
+				 ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+						IPATH_MDIO_CTRL_XGXS_REG_8,
+						0));
+		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+					   IPATH_MDIO_DATAVALID, &val))
+			ipath_dbg("Never got MDIO data for XGXS status "
+				  "read\n");
+		else
+			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+				   "'bank' 31 %x\n", (u32) val);
+	} else
+		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+	return ret;		/* for now, say we always succeeded */
+}
+
+/**
+ * ipath_ht_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * driver is being unloaded
+ */
+static void ipath_ht_quiet_serdes(struct ipath_devdata *dd)
+{
+	u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+	val |= INFINIPATH_SERDC0_TXIDLE;
+	ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+		  (unsigned long long) val);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+static int ipath_ht_intconfig(struct ipath_devdata *dd)
+{
+	int ret;
+
+	if (!dd->ipath_intconfig) {
+		ipath_dev_err(dd, "No interrupts enabled, couldn't setup "
+			      "interrupt address\n");
+		ret = 1;
+		goto bail;
+	}
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig,
+			 dd->ipath_intconfig);	/* interrupt address */
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_pe_put_tid - write a TID in chip
+ * @dd: the infinipath device
+ * @tidptr: pointer to the expected TID (in chip) to udpate
+ * @tidtype: 0 for eager, 1 for expected
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_ht_put_tid(struct ipath_devdata *dd,
+			     u64 __iomem *tidptr, u32 type,
+			     unsigned long pa)
+{
+	if (pa != dd->ipath_tidinvalid) {
+		if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) {
+			dev_info(&dd->pcidev->dev,
+				 "physaddr %lx has more than "
+				 "40 bits, using only 40!!!\n", pa);
+			pa &= INFINIPATH_RT_ADDR_MASK;
+		}
+		if (type == 0)
+			pa |= dd->ipath_tidtemplate;
+		else {
+			/* in words (fixed, full page).  */
+			u64 lenvalid = PAGE_SIZE >> 2;
+			lenvalid <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+			pa |= lenvalid | INFINIPATH_RT_VALID;
+		}
+	}
+	if (dd->ipath_kregbase)
+		writeq(pa, tidptr);
+}
+
+/**
+ * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * Used from ipath_close(), and at chip initialization.
+ */
+static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+	u64 __iomem *tidbase;
+	int i;
+
+	if (!dd->ipath_kregbase)
+		return;
+
+	ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+	/*
+	 * need to invalidate all of the expected TID entries for this
+	 * port, so we don't have valid entries that might somehow get
+	 * used (early in next use of this port, or through some bug)
+	 */
+	tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+				   dd->ipath_rcvtidbase +
+				   port * dd->ipath_rcvtidcnt *
+				   sizeof(*tidbase));
+	for (i = 0; i < dd->ipath_rcvtidcnt; i++)
+		ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid);
+
+	tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
+				   dd->ipath_rcvegrbase +
+				   port * dd->ipath_rcvegrcnt *
+				   sizeof(*tidbase));
+
+	for (i = 0; i < dd->ipath_rcvegrcnt; i++)
+		ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+}
+
+/**
+ * ipath_ht_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_ht_tidtemplate(struct ipath_devdata *dd)
+{
+	dd->ipath_tidtemplate = dd->ipath_ibmaxlen >> 2;
+	dd->ipath_tidtemplate <<= INFINIPATH_RT_BUFSIZE_SHIFT;
+	dd->ipath_tidtemplate |= INFINIPATH_RT_VALID;
+
+	/*
+	 * work around chip errata bug 7358, by marking invalid tids
+	 * as having max length
+	 */
+	dd->ipath_tidinvalid = (-1LL & INFINIPATH_RT_BUFSIZE_MASK) <<
+		INFINIPATH_RT_BUFSIZE_SHIFT;
+}
+
+static int ipath_ht_early_init(struct ipath_devdata *dd)
+{
+	u32 __iomem *piobuf;
+	u32 pioincr, val32, egrsize;
+	int i;
+
+	/*
+	 * one cache line; long IB headers will spill over into received
+	 * buffer
+	 */
+	dd->ipath_rcvhdrentsize = 16;
+	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+	/*
+	 * For HT-400, we allocate a somewhat overly large eager buffer,
+	 * such that we can guarantee that we can receive the largest
+	 * packet that we can send out.  To truly support a 4KB MTU,
+	 * we need to bump this to a large value.  To date, other than
+	 * testing, we have never encountered an HCA that can really
+	 * send 4KB MTU packets, so we do not handle that (we'll get
+	 * errors interrupts if we ever see one).
+	 */
+	dd->ipath_rcvegrbufsize = dd->ipath_piosize2k;
+	egrsize = dd->ipath_rcvegrbufsize;
+
+	/*
+	 * the min() check here is currently a nop, but it may not
+	 * always be, depending on just how we do ipath_rcvegrbufsize
+	 */
+	dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+				 dd->ipath_rcvegrbufsize);
+	dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+	ipath_ht_tidtemplate(dd);
+
+	/*
+	 * zero all the TID entries at startup.  We do this for sanity,
+	 * in case of a previous driver crash of some kind, and also
+	 * because the chip powers up with these memories in an unknown
+	 * state.  Use portcnt, not cfgports, since this is for the
+	 * full chip, not for current (possibly different) configuration
+	 * value.
+	 * Chip Errata bug 6447
+	 */
+	for (val32 = 0; val32 < dd->ipath_portcnt; val32++)
+		ipath_ht_clear_tids(dd, val32);
+
+	/*
+	 * write the pbc of each buffer, to be sure it's initialized, then
+	 * cancel all the buffers, and also abort any packets that might
+	 * have been in flight for some reason (the latter is for driver
+	 * unload/reload, but isn't a bad idea at first init).	PIO send
+	 * isn't enabled at this point, so there is no danger of sending
+	 * these out on the wire.
+	 * Chip Errata bug 6610
+	 */
+	piobuf = (u32 __iomem *) (((char __iomem *)(dd->ipath_kregbase)) +
+				  dd->ipath_piobufbase);
+	pioincr = dd->ipath_palign / sizeof(*piobuf);
+	for (i = 0; i < dd->ipath_piobcnt2k; i++) {
+		/*
+		 * reasonable word count, just to init pbc
+		 */
+		writel(16, piobuf);
+		piobuf += pioincr;
+	}
+	/*
+	 * self-clearing
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 INFINIPATH_S_ABORT);
+	return 0;
+}
+
+/**
+ * ipath_init_ht_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+	struct ipath_base_info *kinfo = kbase;
+
+	kinfo->spi_runtime_flags |= IPATH_RUNTIME_HT |
+		IPATH_RUNTIME_RCVHDR_COPY;
+
+	return 0;
+}
+
+/**
+ * ipath_init_ht400_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_ht400_funcs(struct ipath_devdata *dd)
+{
+	dd->ipath_f_intrsetup = ipath_ht_intconfig;
+	dd->ipath_f_bus = ipath_setup_ht_config;
+	dd->ipath_f_reset = ipath_setup_ht_reset;
+	dd->ipath_f_get_boardname = ipath_ht_boardname;
+	dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+	dd->ipath_f_init_hwerrors = ipath_ht_init_hwerrors;
+	dd->ipath_f_early_init = ipath_ht_early_init;
+	dd->ipath_f_handle_hwerrors = ipath_ht_handle_hwerrors;
+	dd->ipath_f_quiet_serdes = ipath_ht_quiet_serdes;
+	dd->ipath_f_bringup_serdes = ipath_ht_bringup_serdes;
+	dd->ipath_f_clear_tids = ipath_ht_clear_tids;
+	dd->ipath_f_put_tid = ipath_ht_put_tid;
+	dd->ipath_f_cleanup = ipath_setup_ht_cleanup;
+	dd->ipath_f_setextled = ipath_setup_ht_setextled;
+	dd->ipath_f_get_base_info = ipath_ht_get_base_info;
+
+	/*
+	 * initialize chip-specific variables
+	 */
+	dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
+
+	/*
+	 * setup the register offsets, since they are different for each
+	 * chip
+	 */
+	dd->ipath_kregs = &ipath_ht_kregs;
+	dd->ipath_cregs = &ipath_ht_cregs;
+
+	/*
+	 * do very early init that is needed before ipath_f_bus is
+	 * called
+	 */
+	ipath_init_ht_variables();
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
new file mode 100644
index 0000000..2823ff9
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -0,0 +1,951 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+
+/*
+ * min buffers we want to have per port, after driver
+ */
+#define IPATH_MIN_USER_PORT_BUFCNT 8
+
+/*
+ * Number of ports we are configured to use (to allow for more pio
+ * buffers per port, etc.)  Zero means use chip value.
+ */
+static ushort ipath_cfgports;
+
+module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO);
+MODULE_PARM_DESC(cfgports, "Set max number of ports to use");
+
+/*
+ * Number of buffers reserved for driver (layered drivers and SMA
+ * send).  Reserved at end of buffer list.
+ */
+static ushort ipath_kpiobufs = 32;
+
+static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp);
+
+module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint,
+		  &ipath_kpiobufs, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
+
+/**
+ * create_port0_egr - allocate the eager TID buffers
+ * @dd: the infinipath device
+ *
+ * This code is now quite different for user and kernel, because
+ * the kernel uses skb's, for the accelerated network performance.
+ * This is the kernel (port0) version.
+ *
+ * Allocate the eager TID buffers and program them into infinipath.
+ * We use the network layer alloc_skb() allocator to allocate the
+ * memory, and either use the buffers as is for things like SMA
+ * packets, or pass the buffers up to the ipath layered driver and
+ * thence the network layer, replacing them as we do so (see
+ * ipath_rcv_layer()).
+ */
+static int create_port0_egr(struct ipath_devdata *dd)
+{
+	unsigned e, egrcnt;
+	struct sk_buff **skbs;
+	int ret;
+
+	egrcnt = dd->ipath_rcvegrcnt;
+
+	skbs = vmalloc(sizeof(*dd->ipath_port0_skbs) * egrcnt);
+	if (skbs == NULL) {
+		ipath_dev_err(dd, "allocation error for eager TID "
+			      "skb array\n");
+		ret = -ENOMEM;
+		goto bail;
+	}
+	for (e = 0; e < egrcnt; e++) {
+		/*
+		 * This is a bit tricky in that we allocate extra
+		 * space for 2 bytes of the 14 byte ethernet header.
+		 * These two bytes are passed in the ipath header so
+		 * the rest of the data is word aligned.  We allocate
+		 * 4 bytes so that the data buffer stays word aligned.
+		 * See ipath_kreceive() for more details.
+		 */
+		skbs[e] = ipath_alloc_skb(dd, GFP_KERNEL);
+		if (!skbs[e]) {
+			ipath_dev_err(dd, "SKB allocation error for "
+				      "eager TID %u\n", e);
+			while (e != 0)
+				dev_kfree_skb(skbs[--e]);
+			ret = -ENOMEM;
+			goto bail;
+		}
+	}
+	/*
+	 * After loop above, so we can test non-NULL to see if ready
+	 * to use at receive, etc.
+	 */
+	dd->ipath_port0_skbs = skbs;
+
+	for (e = 0; e < egrcnt; e++) {
+		unsigned long phys =
+			virt_to_phys(dd->ipath_port0_skbs[e]->data);
+		dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
+				    ((char __iomem *) dd->ipath_kregbase +
+				     dd->ipath_rcvegrbase), 0, phys);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static int bringup_link(struct ipath_devdata *dd)
+{
+	u64 val, ibc;
+	int ret = 0;
+
+	/* hold IBC in reset */
+	dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+			 dd->ipath_control);
+
+	/*
+	 * Note that prior to try 14 or 15 of IB, the credit scaling
+	 * wasn't working, because it was swapped for writes with the
+	 * 1 bit default linkstate field
+	 */
+
+	/* ignore pbc and align word */
+	val = dd->ipath_piosize2k - 2 * sizeof(u32);
+	/*
+	 * for ICRC, which we only send in diag test pkt mode, and we
+	 * don't need to worry about that for mtu
+	 */
+	val += 1;
+	/*
+	 * Set the IBC maxpktlength to the size of our pio buffers the
+	 * maxpktlength is in words.  This is *not* the IB data MTU.
+	 */
+	ibc = (val / sizeof(u32)) << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+	/* in KB */
+	ibc |= 0x5ULL << INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT;
+	/*
+	 * How often flowctrl sent.  More or less in usecs; balance against
+	 * watermark value, so that in theory senders always get a flow
+	 * control update in time to not let the IB link go idle.
+	 */
+	ibc |= 0x3ULL << INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT;
+	/* max error tolerance */
+	ibc |= 0xfULL << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+	/* use "real" buffer space for */
+	ibc |= 4ULL << INFINIPATH_IBCC_CREDITSCALE_SHIFT;
+	/* IB credit flow control. */
+	ibc |= 0xfULL << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+	/* initially come up waiting for TS1, without sending anything. */
+	dd->ipath_ibcctrl = ibc;
+	/*
+	 * Want to start out with both LINKCMD and LINKINITCMD in NOP
+	 * (0 and 0).  Don't put linkinitcmd in ipath_ibcctrl, want that
+	 * to stay a NOP
+	 */
+	ibc |= INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+		INFINIPATH_IBCC_LINKINITCMD_SHIFT;
+	ipath_cdbg(VERBOSE, "Writing 0x%llx to ibcctrl\n",
+		   (unsigned long long) ibc);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, ibc);
+
+	// be sure chip saw it
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+	ret = dd->ipath_f_bringup_serdes(dd);
+
+	if (ret)
+		dev_info(&dd->pcidev->dev, "Could not initialize SerDes, "
+			 "not usable\n");
+	else {
+		/* enable IBC */
+		dd->ipath_control |= INFINIPATH_C_LINKENABLE;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+				 dd->ipath_control);
+	}
+
+	return ret;
+}
+
+static int init_chip_first(struct ipath_devdata *dd,
+			   struct ipath_portdata **pdp)
+{
+	struct ipath_portdata *pd = NULL;
+	int ret = 0;
+	u64 val;
+
+	/*
+	 * skip cfgports stuff because we are not allocating memory,
+	 * and we don't want problems if the portcnt changed due to
+	 * cfgports.  We do still check and report a difference, if
+	 * not same (should be impossible).
+	 */
+	dd->ipath_portcnt =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+	if (!ipath_cfgports)
+		dd->ipath_cfgports = dd->ipath_portcnt;
+	else if (ipath_cfgports <= dd->ipath_portcnt) {
+		dd->ipath_cfgports = ipath_cfgports;
+		ipath_dbg("Configured to use %u ports out of %u in chip\n",
+			  dd->ipath_cfgports, dd->ipath_portcnt);
+	} else {
+		dd->ipath_cfgports = dd->ipath_portcnt;
+		ipath_dbg("Tried to configured to use %u ports; chip "
+			  "only supports %u\n", ipath_cfgports,
+			  dd->ipath_portcnt);
+	}
+	dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports,
+			       GFP_KERNEL);
+
+	if (!dd->ipath_pd) {
+		ipath_dev_err(dd, "Unable to allocate portdata array, "
+			      "failing\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
+					 * dd->ipath_cfgports,
+					 GFP_KERNEL);
+	dd->ipath_lastrcvhdrqtails =
+		kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
+			* dd->ipath_cfgports, GFP_KERNEL);
+
+	if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
+		ipath_dev_err(dd, "Unable to allocate head arrays, "
+			      "failing\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL);
+
+	if (!dd->ipath_pd[0]) {
+		ipath_dev_err(dd, "Unable to allocate portdata for port "
+			      "0, failing\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	pd = dd->ipath_pd[0];
+	pd->port_dd = dd;
+	pd->port_port = 0;
+	pd->port_cnt = 1;
+	/* The port 0 pkey table is used by the layer interface. */
+	pd->port_pkeys[0] = IPS_DEFAULT_P_KEY;
+	dd->ipath_rcvtidcnt =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+	dd->ipath_rcvtidbase =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+	dd->ipath_rcvegrcnt =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+	dd->ipath_rcvegrbase =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+	dd->ipath_palign =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
+	dd->ipath_piobufbase =
+		ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufbase);
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
+	dd->ipath_piosize2k = val & ~0U;
+	dd->ipath_piosize4k = val >> 32;
+	dd->ipath_ibmtu = 4096;	/* default to largest legal MTU */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
+	dd->ipath_piobcnt2k = val & ~0U;
+	dd->ipath_piobcnt4k = val >> 32;
+	dd->ipath_pio2kbase =
+		(u32 __iomem *) (((char __iomem *) dd->ipath_kregbase) +
+				 (dd->ipath_piobufbase & 0xffffffff));
+	if (dd->ipath_piobcnt4k) {
+		dd->ipath_pio4kbase = (u32 __iomem *)
+			(((char __iomem *) dd->ipath_kregbase) +
+			 (dd->ipath_piobufbase >> 32));
+		/*
+		 * 4K buffers take 2 pages; we use roundup just to be
+		 * paranoid; we calculate it once here, rather than on
+		 * ever buf allocate
+		 */
+		dd->ipath_4kalign = ALIGN(dd->ipath_piosize4k,
+					  dd->ipath_palign);
+		ipath_dbg("%u 2k(%x) piobufs @ %p, %u 4k(%x) @ %p "
+			  "(%x aligned)\n",
+			  dd->ipath_piobcnt2k, dd->ipath_piosize2k,
+			  dd->ipath_pio2kbase, dd->ipath_piobcnt4k,
+			  dd->ipath_piosize4k, dd->ipath_pio4kbase,
+			  dd->ipath_4kalign);
+	}
+	else ipath_dbg("%u 2k piobufs @ %p\n",
+		       dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+
+	spin_lock_init(&dd->ipath_tid_lock);
+
+done:
+	*pdp = pd;
+	return ret;
+}
+
+/**
+ * init_chip_reset - re-initialize after a reset, or enable
+ * @dd: the infinipath device
+ * @pdp: output for port data
+ *
+ * sanity check at least some of the values after reset, and
+ * ensure no receive or transmit (explictly, in case reset
+ * failed
+ */
+static int init_chip_reset(struct ipath_devdata *dd,
+			   struct ipath_portdata **pdp)
+{
+	struct ipath_portdata *pd;
+	u32 rtmp;
+
+	*pdp = pd = dd->ipath_pd[0];
+	/* ensure chip does no sends or receives while we re-initialize */
+	dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
+
+	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+	if (dd->ipath_portcnt != rtmp)
+		dev_info(&dd->pcidev->dev, "portcnt was %u before "
+			 "reset, now %u, using original\n",
+			 dd->ipath_portcnt, rtmp);
+	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt);
+	if (rtmp != dd->ipath_rcvtidcnt)
+		dev_info(&dd->pcidev->dev, "tidcnt was %u before "
+			 "reset, now %u, using original\n",
+			 dd->ipath_rcvtidcnt, rtmp);
+	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidbase);
+	if (rtmp != dd->ipath_rcvtidbase)
+		dev_info(&dd->pcidev->dev, "tidbase was %u before "
+			 "reset, now %u, using original\n",
+			 dd->ipath_rcvtidbase, rtmp);
+	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
+	if (rtmp != dd->ipath_rcvegrcnt)
+		dev_info(&dd->pcidev->dev, "egrcnt was %u before "
+			 "reset, now %u, using original\n",
+			 dd->ipath_rcvegrcnt, rtmp);
+	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrbase);
+	if (rtmp != dd->ipath_rcvegrbase)
+		dev_info(&dd->pcidev->dev, "egrbase was %u before "
+			 "reset, now %u, using original\n",
+			 dd->ipath_rcvegrbase, rtmp);
+
+	return 0;
+}
+
+static int init_pioavailregs(struct ipath_devdata *dd)
+{
+	int ret;
+
+	dd->ipath_pioavailregs_dma = dma_alloc_coherent(
+		&dd->pcidev->dev, PAGE_SIZE, &dd->ipath_pioavailregs_phys,
+		GFP_KERNEL);
+	if (!dd->ipath_pioavailregs_dma) {
+		ipath_dev_err(dd, "failed to allocate PIOavail reg area "
+			      "in memory\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/*
+	 * we really want L2 cache aligned, but for current CPUs of
+	 * interest, they are the same.
+	 */
+	dd->ipath_statusp = (u64 *)
+		((char *)dd->ipath_pioavailregs_dma +
+		 ((2 * L1_CACHE_BYTES +
+		   dd->ipath_pioavregs * sizeof(u64)) & ~L1_CACHE_BYTES));
+	/* copy the current value now that it's really allocated */
+	*dd->ipath_statusp = dd->_ipath_status;
+	/*
+	 * setup buffer to hold freeze msg, accessible to apps,
+	 * following statusp
+	 */
+	dd->ipath_freezemsg = (char *)&dd->ipath_statusp[1];
+	/* and its length */
+	dd->ipath_freezelen = L1_CACHE_BYTES - sizeof(dd->ipath_statusp[0]);
+
+	if (dd->ipath_unit * 64 > (IPATH_PORT0_RCVHDRTAIL_SIZE - 64)) {
+		ipath_dev_err(dd, "unit %u too large for port 0 "
+			      "rcvhdrtail buffer size\n", dd->ipath_unit);
+		ret = -ENODEV;
+	}
+	else
+		ret = 0;
+
+	/* so we can get current tail in ipath_kreceive(), per chip */
+	dd->ipath_hdrqtailptr = &ipath_port0_rcvhdrtail[
+		dd->ipath_unit * (64 / sizeof(*ipath_port0_rcvhdrtail))];
+done:
+	return ret;
+}
+
+/**
+ * init_shadow_tids - allocate the shadow TID array
+ * @dd: the infinipath device
+ *
+ * allocate the shadow TID array, so we can ipath_munlock previous
+ * entries.  It may make more sense to move the pageshadow to the
+ * port data structure, so we only allocate memory for ports actually
+ * in use, since we at 8k per port, now.
+ */
+static void init_shadow_tids(struct ipath_devdata *dd)
+{
+	dd->ipath_pageshadow = (struct page **)
+		vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+			sizeof(struct page *));
+	if (!dd->ipath_pageshadow)
+		ipath_dev_err(dd, "failed to allocate shadow page * "
+			      "array, no expected sends!\n");
+	else
+		memset(dd->ipath_pageshadow, 0,
+		       dd->ipath_cfgports * dd->ipath_rcvtidcnt *
+		       sizeof(struct page *));
+}
+
+static void enable_chip(struct ipath_devdata *dd,
+			struct ipath_portdata *pd, int reinit)
+{
+	u32 val;
+	int i;
+
+	if (!reinit) {
+		init_waitqueue_head(&ipath_sma_state_wait);
+	}
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+	/* Enable PIO send, and update of PIOavail regs to memory. */
+	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+		INFINIPATH_S_PIOBUFAVAILUPD;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 dd->ipath_sendctrl);
+
+	/*
+	 * enable port 0 receive, and receive interrupt.  other ports
+	 * done as user opens and inits them.
+	 */
+	dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
+		(1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
+		(1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+			 dd->ipath_rcvctrl);
+
+	/*
+	 * now ready for use.  this should be cleared whenever we
+	 * detect a reset, or initiate one.
+	 */
+	dd->ipath_flags |= IPATH_INITTED;
+
+	/*
+	 * init our shadow copies of head from tail values, and write
+	 * head values to match.
+	 */
+	val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+	(void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+	dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
+
+	/* Initialize so we interrupt on next packet received */
+	(void)ipath_write_ureg(dd, ur_rcvhdrhead,
+			       dd->ipath_rhdrhead_intr_off |
+			       dd->ipath_port0head, 0);
+
+	/*
+	 * by now pioavail updates to memory should have occurred, so
+	 * copy them into our working/shadow registers; this is in
+	 * case something went wrong with abort, but mostly to get the
+	 * initial values of the generation bit correct.
+	 */
+	for (i = 0; i < dd->ipath_pioavregs; i++) {
+		__le64 val;
+
+		/*
+		 * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+		 */
+		if (i > 3) {
+			if (i & 1)
+				val = dd->ipath_pioavailregs_dma[i - 1];
+			else
+				val = dd->ipath_pioavailregs_dma[i + 1];
+		}
+		else
+			val = dd->ipath_pioavailregs_dma[i];
+		dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
+	}
+	/* can get counters, stats, etc. */
+	dd->ipath_flags |= IPATH_PRESENT;
+}
+
+static int init_housekeeping(struct ipath_devdata *dd,
+			     struct ipath_portdata **pdp, int reinit)
+{
+	char boardn[32];
+	int ret = 0;
+
+	/*
+	 * have to clear shadow copies of registers at init that are
+	 * not otherwise set here, or all kinds of bizarre things
+	 * happen with driver on chip reset
+	 */
+	dd->ipath_rcvhdrsize = 0;
+
+	/*
+	 * Don't clear ipath_flags as 8bit mode was set before
+	 * entering this func. However, we do set the linkstate to
+	 * unknown, so we can watch for a transition.
+	 */
+	dd->ipath_flags |= IPATH_LINKUNK;
+	dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED |
+			     IPATH_LINKDOWN | IPATH_LINKINIT);
+
+	ipath_cdbg(VERBOSE, "Try to read spc chip revision\n");
+	dd->ipath_revision =
+		ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+
+	/*
+	 * set up fundamental info we need to use the chip; we assume
+	 * if the revision reg and these regs are OK, we don't need to
+	 * special case the rest
+	 */
+	dd->ipath_sregbase =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_sendregbase);
+	dd->ipath_cregbase =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_counterregbase);
+	dd->ipath_uregbase =
+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_userregbase);
+	ipath_cdbg(VERBOSE, "ipath_kregbase %p, sendbase %x usrbase %x, "
+		   "cntrbase %x\n", dd->ipath_kregbase, dd->ipath_sregbase,
+		   dd->ipath_uregbase, dd->ipath_cregbase);
+	if ((dd->ipath_revision & 0xffffffff) == 0xffffffff
+	    || (dd->ipath_sregbase & 0xffffffff) == 0xffffffff
+	    || (dd->ipath_cregbase & 0xffffffff) == 0xffffffff
+	    || (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) {
+		ipath_dev_err(dd, "Register read failures from chip, "
+			      "giving up initialization\n");
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/* clear the initial reset flag, in case first driver load */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+			 INFINIPATH_E_RESET);
+
+	if (reinit)
+		ret = init_chip_reset(dd, pdp);
+	else
+		ret = init_chip_first(dd, pdp);
+
+	if (ret)
+		goto done;
+
+	ipath_cdbg(VERBOSE, "Revision %llx (PCI %x), %u ports, %u tids, "
+		   "%u egrtids\n", (unsigned long long) dd->ipath_revision,
+		   dd->ipath_pcirev, dd->ipath_portcnt, dd->ipath_rcvtidcnt,
+		   dd->ipath_rcvegrcnt);
+
+	if (((dd->ipath_revision >> INFINIPATH_R_SOFTWARE_SHIFT) &
+	     INFINIPATH_R_SOFTWARE_MASK) != IPATH_CHIP_SWVERSION) {
+		ipath_dev_err(dd, "Driver only handles version %d, "
+			      "chip swversion is %d (%llx), failng\n",
+			      IPATH_CHIP_SWVERSION,
+			      (int)(dd->ipath_revision >>
+				    INFINIPATH_R_SOFTWARE_SHIFT) &
+			      INFINIPATH_R_SOFTWARE_MASK,
+			      (unsigned long long) dd->ipath_revision);
+		ret = -ENOSYS;
+		goto done;
+	}
+	dd->ipath_majrev = (u8) ((dd->ipath_revision >>
+				  INFINIPATH_R_CHIPREVMAJOR_SHIFT) &
+				 INFINIPATH_R_CHIPREVMAJOR_MASK);
+	dd->ipath_minrev = (u8) ((dd->ipath_revision >>
+				  INFINIPATH_R_CHIPREVMINOR_SHIFT) &
+				 INFINIPATH_R_CHIPREVMINOR_MASK);
+	dd->ipath_boardrev = (u8) ((dd->ipath_revision >>
+				    INFINIPATH_R_BOARDID_SHIFT) &
+				   INFINIPATH_R_BOARDID_MASK);
+
+	ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
+
+	snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
+		 "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+		 "SW Compat %u\n",
+		 IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
+		 (unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
+		 INFINIPATH_R_ARCH_MASK,
+		 dd->ipath_majrev, dd->ipath_minrev, dd->ipath_pcirev,
+		 (unsigned)(dd->ipath_revision >>
+			    INFINIPATH_R_SOFTWARE_SHIFT) &
+		 INFINIPATH_R_SOFTWARE_MASK);
+
+	ipath_dbg("%s", dd->ipath_boardversion);
+
+done:
+	return ret;
+}
+
+
+/**
+ * ipath_init_chip - do the actual initialization sequence on the chip
+ * @dd: the infinipath device
+ * @reinit: reinitializing, so don't allocate new memory
+ *
+ * Do the actual initialization sequence on the chip.  This is done
+ * both from the init routine called from the PCI infrastructure, and
+ * when we reset the chip, or detect that it was reset internally,
+ * or it's administratively re-enabled.
+ *
+ * Memory allocation here and in called routines is only done in
+ * the first case (reinit == 0).  We have to be careful, because even
+ * without memory allocation, we need to re-write all the chip registers
+ * TIDs, etc. after the reset or enable has completed.
+ */
+int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+{
+	int ret = 0, i;
+	u32 val32, kpiobufs;
+	u64 val, atmp;
+	struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+
+	ret = init_housekeeping(dd, &pd, reinit);
+	if (ret)
+		goto done;
+
+	/*
+	 * we ignore most issues after reporting them, but have to specially
+	 * handle hardware-disabled chips.
+	 */
+	if (ret == 2) {
+		/* unique error, known to ipath_init_one */
+		ret = -EPERM;
+		goto done;
+	}
+
+	/*
+	 * We could bump this to allow for full rcvegrcnt + rcvtidcnt,
+	 * but then it no longer nicely fits power of two, and since
+	 * we now use routines that backend onto __get_free_pages, the
+	 * rest would be wasted.
+	 */
+	dd->ipath_rcvhdrcnt = dd->ipath_rcvegrcnt;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrcnt,
+			 dd->ipath_rcvhdrcnt);
+
+	/*
+	 * Set up the shadow copies of the piobufavail registers,
+	 * which we compare against the chip registers for now, and
+	 * the in memory DMA'ed copies of the registers.  This has to
+	 * be done early, before we calculate lastport, etc.
+	 */
+	val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+	/*
+	 * calc number of pioavail registers, and save it; we have 2
+	 * bits per buffer.
+	 */
+	dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
+		/ (sizeof(u64) * BITS_PER_BYTE / 2);
+	if (!ipath_kpiobufs)	/* have to have at least 1, for SMA */
+		kpiobufs = ipath_kpiobufs = 1;
+	else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) <
+		 (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) {
+		dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) "
+			 "for %u ports to have %u each!\n",
+			 dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
+			 dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT);
+		kpiobufs = 1;	/* reserve just the minimum for SMA/ether */
+	} else
+		kpiobufs = ipath_kpiobufs;
+
+	if (kpiobufs >
+	    (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+	     (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) {
+		i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+			(dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT);
+		if (i < 0)
+			i = 0;
+		dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for "
+			 "kernel leaves too few for %d user ports "
+			 "(%d each); using %u\n", kpiobufs,
+			 dd->ipath_cfgports - 1,
+			 IPATH_MIN_USER_PORT_BUFCNT, i);
+		/*
+		 * shouldn't change ipath_kpiobufs, because could be
+		 * different for different devices...
+		 */
+		kpiobufs = i;
+	}
+	dd->ipath_lastport_piobuf =
+		dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs;
+	dd->ipath_pbufsport = dd->ipath_cfgports > 1
+		? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1)
+		: 0;
+	val32 = dd->ipath_lastport_piobuf -
+		(dd->ipath_pbufsport * (dd->ipath_cfgports - 1));
+	if (val32 > 0) {
+		ipath_dbg("allocating %u pbufs/port leaves %u unused, "
+			  "add to kernel\n", dd->ipath_pbufsport, val32);
+		dd->ipath_lastport_piobuf -= val32;
+		ipath_dbg("%u pbufs/port leaves %u unused, add to kernel\n",
+			  dd->ipath_pbufsport, val32);
+	}
+	dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;
+	ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u "
+		   "each for %u user ports\n", kpiobufs,
+		   dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
+		   dd->ipath_pbufsport, dd->ipath_cfgports - 1);
+
+	dd->ipath_f_early_init(dd);
+
+	/* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
+	 * done after early_init */
+	dd->ipath_hdrqlast =
+		dd->ipath_rcvhdrentsize * (dd->ipath_rcvhdrcnt - 1);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrentsize,
+			 dd->ipath_rcvhdrentsize);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvhdrsize,
+			 dd->ipath_rcvhdrsize);
+
+	if (!reinit) {
+		ret = init_pioavailregs(dd);
+		init_shadow_tids(dd);
+		if (ret)
+			goto done;
+	}
+
+	(void)ipath_write_kreg(dd, dd->ipath_kregs->kr_sendpioavailaddr,
+			       dd->ipath_pioavailregs_phys);
+	/*
+	 * this is to detect s/w errors, which the h/w works around by
+	 * ignoring the low 6 bits of address, if it wasn't aligned.
+	 */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpioavailaddr);
+	if (val != dd->ipath_pioavailregs_phys) {
+		ipath_dev_err(dd, "Catastrophic software error, "
+			      "SendPIOAvailAddr written as %lx, "
+			      "read back as %llx\n",
+			      (unsigned long) dd->ipath_pioavailregs_phys,
+			      (unsigned long long) val);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	val = ipath_port0_rcvhdrtail_dma + dd->ipath_unit * 64;
+
+	/* verify that the alignment requirement was met */
+	ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
+			      0, val);
+	atmp = ipath_read_kreg64_port(
+		dd, dd->ipath_kregs->kr_rcvhdrtailaddr, 0);
+	if (val != atmp) {
+		ipath_dev_err(dd, "Catastrophic software error, "
+			      "RcvHdrTailAddr0 written as %llx, "
+			      "read back as %llx from %x\n",
+			      (unsigned long long) val,
+			      (unsigned long long) atmp,
+			      dd->ipath_kregs->kr_rcvhdrtailaddr);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvbthqp, IPATH_KD_QP);
+
+	/*
+	 * make sure we are not in freeze, and PIO send enabled, so
+	 * writes to pbc happen
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask, 0ULL);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+			 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 INFINIPATH_S_PIOENABLE);
+
+	/*
+	 * before error clears, since we expect serdes pll errors during
+	 * this, the first time after reset
+	 */
+	if (bringup_link(dd)) {
+		dev_info(&dd->pcidev->dev, "Failed to bringup IB link\n");
+		ret = -ENETDOWN;
+		goto done;
+	}
+
+	/*
+	 * clear any "expected" hwerrs from reset and/or initialization
+	 * clear any that aren't enabled (at least this once), and then
+	 * set the enable mask
+	 */
+	dd->ipath_f_init_hwerrors(dd);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+			 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+			 dd->ipath_hwerrmask);
+
+	dd->ipath_maskederrs = dd->ipath_ignorederrs;
+	/* clear all */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
+	/* enable errors that are masked, at least this first time. */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+			 ~dd->ipath_maskederrs);
+	/* clear any interrups up to this point (ints still not enabled) */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+	ipath_stats.sps_lid[dd->ipath_unit] = dd->ipath_lid;
+
+	/*
+	 * Set up the port 0 (kernel) rcvhdr q and egr TIDs.  If doing
+	 * re-init, the simplest way to handle this is to free
+	 * existing, and re-allocate.
+	 */
+	if (reinit)
+		ipath_free_pddata(dd, 0, 0);
+	dd->ipath_f_tidtemplate(dd);
+	ret = ipath_create_rcvhdrq(dd, pd);
+	if (!ret)
+		ret = create_port0_egr(dd);
+	if (ret)
+		ipath_dev_err(dd, "failed to allocate port 0 (kernel) "
+			      "rcvhdrq and/or egr bufs\n");
+	else
+		enable_chip(dd, pd, reinit);
+
+	/*
+	 * cause retrigger of pending interrupts ignored during init,
+	 * even if we had errors
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+
+	if(!dd->ipath_stats_timer_active) {
+		/*
+		 * first init, or after an admin disable/enable
+		 * set up stats retrieval timer, even if we had errors
+		 * in last portion of setup
+		 */
+		init_timer(&dd->ipath_stats_timer);
+		dd->ipath_stats_timer.function = ipath_get_faststats;
+		dd->ipath_stats_timer.data = (unsigned long) dd;
+		/* every 5 seconds; */
+		dd->ipath_stats_timer.expires = jiffies + 5 * HZ;
+		/* takes ~16 seconds to overflow at full IB 4x bandwdith */
+		add_timer(&dd->ipath_stats_timer);
+		dd->ipath_stats_timer_active = 1;
+	}
+
+done:
+	if (!ret) {
+		ipath_get_guid(dd);
+		*dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT;
+		if (!dd->ipath_f_intrsetup(dd)) {
+			/* now we can enable all interrupts from the chip */
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+					 -1LL);
+			/* force re-interrupt of any pending interrupts. */
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear,
+					 0ULL);
+			/* chip is usable; mark it as initialized */
+			*dd->ipath_statusp |= IPATH_STATUS_INITTED;
+		} else
+			ipath_dev_err(dd, "No interrupts enabled, couldn't "
+				      "setup interrupt address\n");
+
+		if (dd->ipath_cfgports > ipath_stats.sps_nports)
+			/*
+			 * sps_nports is a global, so, we set it to
+			 * the highest number of ports of any of the
+			 * chips we find; we never decrement it, at
+			 * least for now.  Since this might have changed
+			 * over disable/enable or prior to reset, always
+			 * do the check and potentially adjust.
+			 */
+			ipath_stats.sps_nports = dd->ipath_cfgports;
+	} else
+		ipath_dbg("Failed (%d) to initialize chip\n", ret);
+
+	/* if ret is non-zero, we probably should do some cleanup
+	   here... */
+	return ret;
+}
+
+static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp)
+{
+	struct ipath_devdata *dd;
+	unsigned long flags;
+	unsigned short val;
+	int ret;
+
+	ret = ipath_parse_ushort(str, &val);
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	if (ret < 0)
+		goto bail;
+
+	if (val == 0) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	list_for_each_entry(dd, &ipath_dev_list, ipath_list) {
+		if (dd->ipath_kregbase)
+			continue;
+		if (val > (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k -
+			   (dd->ipath_cfgports *
+			    IPATH_MIN_USER_PORT_BUFCNT)))
+		{
+			ipath_dev_err(
+				dd,
+				"Allocating %d PIO bufs for kernel leaves "
+				"too few for %d user ports (%d each)\n",
+				val, dd->ipath_cfgports - 1,
+				IPATH_MIN_USER_PORT_BUFCNT);
+			ret = -EINVAL;
+			goto bail;
+		}
+		dd->ipath_lastport_piobuf =
+			dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val;
+	}
+
+	ret = 0;
+bail:
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
new file mode 100644
index 0000000..0bcb428
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+#define E_SUM_PKTERRS \
+	(INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \
+	 INFINIPATH_E_RBADVERSION | INFINIPATH_E_RHDR | \
+	 INFINIPATH_E_RLONGPKTLEN | INFINIPATH_E_RSHORTPKTLEN | \
+	 INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RMINPKTLEN | \
+	 INFINIPATH_E_RFORMATERR | INFINIPATH_E_RUNSUPVL | \
+	 INFINIPATH_E_RUNEXPCHAR | INFINIPATH_E_REBP)
+
+#define E_SUM_ERRS \
+	(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM | \
+	 INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+	 INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SUNSUPVL | \
+	 INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SPKTLEN | \
+	 INFINIPATH_E_INVALIDADDR)
+
+static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs)
+{
+	unsigned long sbuf[4];
+	u64 ignore_this_time = 0;
+	u32 piobcnt;
+
+	/* if possible that sendbuffererror could be valid */
+	piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;
+	/* read these before writing errorclear */
+	sbuf[0] = ipath_read_kreg64(
+		dd, dd->ipath_kregs->kr_sendbuffererror);
+	sbuf[1] = ipath_read_kreg64(
+		dd, dd->ipath_kregs->kr_sendbuffererror + 1);
+	if (piobcnt > 128) {
+		sbuf[2] = ipath_read_kreg64(
+			dd, dd->ipath_kregs->kr_sendbuffererror + 2);
+		sbuf[3] = ipath_read_kreg64(
+			dd, dd->ipath_kregs->kr_sendbuffererror + 3);
+	}
+
+	if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
+		int i;
+
+		ipath_cdbg(PKT, "SendbufErrs %lx %lx ", sbuf[0], sbuf[1]);
+		if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128)
+			printk("%lx %lx ", sbuf[2], sbuf[3]);
+		for (i = 0; i < piobcnt; i++) {
+			if (test_bit(i, sbuf)) {
+				u32 __iomem *piobuf;
+				if (i < dd->ipath_piobcnt2k)
+					piobuf = (u32 __iomem *)
+						(dd->ipath_pio2kbase +
+						 i * dd->ipath_palign);
+				else
+					piobuf = (u32 __iomem *)
+						(dd->ipath_pio4kbase +
+						 (i - dd->ipath_piobcnt2k) *
+						 dd->ipath_4kalign);
+
+				ipath_cdbg(PKT,
+					   "PIObuf[%u] @%p pbc is %x; ",
+					   i, piobuf, readl(piobuf));
+
+				ipath_disarm_piobufs(dd, i, 1);
+			}
+		}
+		if (ipath_debug & __IPATH_PKTDBG)
+			printk("\n");
+	}
+	if ((errs & (INFINIPATH_E_SDROPPEDDATAPKT |
+		     INFINIPATH_E_SDROPPEDSMPPKT |
+		     INFINIPATH_E_SMINPKTLEN)) &&
+	    !(dd->ipath_flags & IPATH_LINKACTIVE)) {
+		/*
+		 * This can happen when SMA is trying to bring the link
+		 * up, but the IB link changes state at the "wrong" time.
+		 * The IB logic then complains that the packet isn't
+		 * valid.  We don't want to confuse people, so we just
+		 * don't print them, except at debug
+		 */
+		ipath_dbg("Ignoring pktsend errors %llx, because not "
+			  "yet active\n", (unsigned long long) errs);
+		ignore_this_time = INFINIPATH_E_SDROPPEDDATAPKT |
+			INFINIPATH_E_SDROPPEDSMPPKT |
+			INFINIPATH_E_SMINPKTLEN;
+	}
+
+	return ignore_this_time;
+}
+
+/* return the strings for the most common link states */
+static char *ib_linkstate(u32 linkstate)
+{
+	char *ret;
+
+	switch (linkstate) {
+	case IPATH_IBSTATE_INIT:
+		ret = "Init";
+		break;
+	case IPATH_IBSTATE_ARM:
+		ret = "Arm";
+		break;
+	case IPATH_IBSTATE_ACTIVE:
+		ret = "Active";
+		break;
+	default:
+		ret = "Down";
+	}
+
+	return ret;
+}
+
+static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
+				     ipath_err_t errs, int noprint)
+{
+	u64 val;
+	u32 ltstate, lstate;
+
+	/*
+	 * even if diags are enabled, we want to notice LINKINIT, etc.
+	 * We just don't want to change the LED state, or
+	 * dd->ipath_kregs->kr_ibcctrl
+	 */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+	lstate = val & IPATH_IBSTATE_MASK;
+	if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
+	    lstate == IPATH_IBSTATE_ACTIVE) {
+		/*
+		 * only print at SMA if there is a change, debug if not
+		 * (sometimes we want to know that, usually not).
+		 */
+		if (lstate == ((unsigned) dd->ipath_lastibcstat
+			       & IPATH_IBSTATE_MASK)) {
+			ipath_dbg("Status change intr but no change (%s)\n",
+				  ib_linkstate(lstate));
+		}
+		else
+			ipath_cdbg(SMA, "Unit %u link state %s, last "
+				   "was %s\n", dd->ipath_unit,
+				   ib_linkstate(lstate),
+				   ib_linkstate((unsigned)
+						dd->ipath_lastibcstat
+						& IPATH_IBSTATE_MASK));
+	}
+	else {
+		lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
+		if (lstate == IPATH_IBSTATE_INIT ||
+		    lstate == IPATH_IBSTATE_ARM ||
+		    lstate == IPATH_IBSTATE_ACTIVE)
+			ipath_cdbg(SMA, "Unit %u link state down"
+				   " (state 0x%x), from %s\n",
+				   dd->ipath_unit,
+				   (u32)val & IPATH_IBSTATE_MASK,
+				   ib_linkstate(lstate));
+		else
+			ipath_cdbg(VERBOSE, "Unit %u link state changed "
+				   "to 0x%x from down (%x)\n",
+				   dd->ipath_unit, (u32) val, lstate);
+	}
+	ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+		INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+	lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+		INFINIPATH_IBCS_LINKSTATE_MASK;
+
+	if (ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE ||
+	    ltstate == INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+		u32 last_ltstate;
+
+		/*
+		 * Ignore cycling back and forth from Polling.Active
+		 * to Polling.Quiet while waiting for the other end of
+		 * the link to come up. We will cycle back and forth
+		 * between them if no cable is plugged in,
+		 * the other device is powered off or disabled, etc.
+		 */
+		last_ltstate = (dd->ipath_lastibcstat >>
+				INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT)
+			& INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+		if (last_ltstate == INFINIPATH_IBCS_LT_STATE_POLLACTIVE
+		    || last_ltstate ==
+		    INFINIPATH_IBCS_LT_STATE_POLLQUIET) {
+			if (dd->ipath_ibpollcnt > 40) {
+				dd->ipath_flags |= IPATH_NOCABLE;
+				*dd->ipath_statusp |=
+					IPATH_STATUS_IB_NOCABLE;
+			} else
+				dd->ipath_ibpollcnt++;
+			goto skip_ibchange;
+		}
+	}
+	dd->ipath_ibpollcnt = 0;	/* some state other than 2 or 3 */
+	ipath_stats.sps_iblink++;
+	if (ltstate != INFINIPATH_IBCS_LT_STATE_LINKUP) {
+		dd->ipath_flags |= IPATH_LINKDOWN;
+		dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+				     | IPATH_LINKACTIVE |
+				     IPATH_LINKARMED);
+		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+		if (!noprint) {
+			if (((dd->ipath_lastibcstat >>
+			      INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+			     INFINIPATH_IBCS_LINKSTATE_MASK)
+			    == INFINIPATH_IBCS_L_STATE_ACTIVE)
+				/* if from up to down be more vocal */
+				ipath_cdbg(SMA,
+					   "Unit %u link now down (%s)\n",
+					   dd->ipath_unit,
+					   ipath_ibcstatus_str[ltstate]);
+			else
+				ipath_cdbg(VERBOSE, "Unit %u link is "
+					   "down (%s)\n", dd->ipath_unit,
+					   ipath_ibcstatus_str[ltstate]);
+		}
+
+		dd->ipath_f_setextled(dd, lstate, ltstate);
+	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ACTIVE) {
+		dd->ipath_flags |= IPATH_LINKACTIVE;
+		dd->ipath_flags &=
+			~(IPATH_LINKUNK | IPATH_LINKINIT | IPATH_LINKDOWN |
+			  IPATH_LINKARMED | IPATH_NOCABLE);
+		*dd->ipath_statusp &= ~IPATH_STATUS_IB_NOCABLE;
+		*dd->ipath_statusp |=
+			IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
+		dd->ipath_f_setextled(dd, lstate, ltstate);
+
+		__ipath_layer_intr(dd, IPATH_LAYER_INT_IF_UP);
+	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
+		/*
+		 * set INIT and DOWN.  Down is checked by most of the other
+		 * code, but INIT is useful to know in a few places.
+		 */
+		dd->ipath_flags |= IPATH_LINKINIT | IPATH_LINKDOWN;
+		dd->ipath_flags &=
+			~(IPATH_LINKUNK | IPATH_LINKACTIVE | IPATH_LINKARMED
+			  | IPATH_NOCABLE);
+		*dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+					| IPATH_STATUS_IB_READY);
+		dd->ipath_f_setextled(dd, lstate, ltstate);
+	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_ARM) {
+		dd->ipath_flags |= IPATH_LINKARMED;
+		dd->ipath_flags &=
+			~(IPATH_LINKUNK | IPATH_LINKDOWN | IPATH_LINKINIT |
+			  IPATH_LINKACTIVE | IPATH_NOCABLE);
+		*dd->ipath_statusp &= ~(IPATH_STATUS_IB_NOCABLE
+					| IPATH_STATUS_IB_READY);
+		dd->ipath_f_setextled(dd, lstate, ltstate);
+	} else {
+		if (!noprint)
+			ipath_dbg("IBstatuschange unit %u: %s (%x)\n",
+				  dd->ipath_unit,
+				  ipath_ibcstatus_str[ltstate], ltstate);
+	}
+skip_ibchange:
+	dd->ipath_lastibcstat = val;
+}
+
+static void handle_supp_msgs(struct ipath_devdata *dd,
+			     unsigned supp_msgs, char msg[512])
+{
+	/*
+	 * Print the message unless it's ibc status change only, which
+	 * happens so often we never want to count it.
+	 */
+	if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) {
+		ipath_decode_err(msg, sizeof msg, dd->ipath_lasterror &
+				 ~INFINIPATH_E_IBSTATUSCHANGED);
+		if (dd->ipath_lasterror &
+		    ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+			ipath_dev_err(dd, "Suppressed %u messages for "
+				      "fast-repeating errors (%s) (%llx)\n",
+				      supp_msgs, msg,
+				      (unsigned long long)
+				      dd->ipath_lasterror);
+		else {
+			/*
+			 * rcvegrfull and rcvhdrqfull are "normal", for some
+			 * types of processes (mostly benchmarks) that send
+			 * huge numbers of messages, while not processing
+			 * them. So only complain about these at debug
+			 * level.
+			 */
+			ipath_dbg("Suppressed %u messages for %s\n",
+				  supp_msgs, msg);
+		}
+	}
+}
+
+static unsigned handle_frequent_errors(struct ipath_devdata *dd,
+				       ipath_err_t errs, char msg[512],
+				       int *noprint)
+{
+	unsigned long nc;
+	static unsigned long nextmsg_time;
+	static unsigned nmsgs, supp_msgs;
+
+	/*
+	 * Throttle back "fast" messages to no more than 10 per 5 seconds.
+	 * This isn't perfect, but it's a reasonable heuristic. If we get
+	 * more than 10, give a 6x longer delay.
+	 */
+	nc = jiffies;
+	if (nmsgs > 10) {
+		if (time_before(nc, nextmsg_time)) {
+			*noprint = 1;
+			if (!supp_msgs++)
+				nextmsg_time = nc + HZ * 3;
+		}
+		else if (supp_msgs) {
+			handle_supp_msgs(dd, supp_msgs, msg);
+			supp_msgs = 0;
+			nmsgs = 0;
+		}
+	}
+	else if (!nmsgs++ || time_after(nc, nextmsg_time))
+		nextmsg_time = nc + HZ / 2;
+
+	return supp_msgs;
+}
+
+static void handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+{
+	char msg[512];
+	u64 ignore_this_time = 0;
+	int i;
+	int chkerrpkts = 0, noprint = 0;
+	unsigned supp_msgs;
+
+	supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
+
+	/*
+	 * don't report errors that are masked (includes those always
+	 * ignored)
+	 */
+	errs &= ~dd->ipath_maskederrs;
+
+	/* do these first, they are most important */
+	if (errs & INFINIPATH_E_HARDWARE) {
+		/* reuse same msg buf */
+		dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+	}
+
+	if (!noprint && (errs & ~infinipath_e_bitsextant))
+		ipath_dev_err(dd, "error interrupt with unknown errors "
+			      "%llx set\n", (unsigned long long)
+			      (errs & ~infinipath_e_bitsextant));
+
+	if (errs & E_SUM_ERRS)
+		ignore_this_time = handle_e_sum_errs(dd, errs);
+
+	if (supp_msgs == 250000) {
+		/*
+		 * It's not entirely reasonable assuming that the errors set
+		 * in the last clear period are all responsible for the
+		 * problem, but the alternative is to assume it's the only
+		 * ones on this particular interrupt, which also isn't great
+		 */
+		dd->ipath_maskederrs |= dd->ipath_lasterror | errs;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+				 ~dd->ipath_maskederrs);
+		ipath_decode_err(msg, sizeof msg,
+				 (dd->ipath_maskederrs & ~dd->
+				  ipath_ignorederrs));
+
+		if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+		    ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+			ipath_dev_err(dd, "Disabling error(s) %llx because "
+				      "occuring too frequently (%s)\n",
+				      (unsigned long long)
+				      (dd->ipath_maskederrs &
+				       ~dd->ipath_ignorederrs), msg);
+		else {
+			/*
+			 * rcvegrfull and rcvhdrqfull are "normal",
+			 * for some types of processes (mostly benchmarks)
+			 * that send huge numbers of messages, while not
+			 * processing them.  So only complain about
+			 * these at debug level.
+			 */
+			ipath_dbg("Disabling frequent queue full errors "
+				  "(%s)\n", msg);
+		}
+
+		/*
+		 * Re-enable the masked errors after around 3 minutes.  in
+		 * ipath_get_faststats().  If we have a series of fast
+		 * repeating but different errors, the interval will keep
+		 * stretching out, but that's OK, as that's pretty
+		 * catastrophic.
+		 */
+		dd->ipath_unmasktime = jiffies + HZ * 180;
+	}
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, errs);
+	if (ignore_this_time)
+		errs &= ~ignore_this_time;
+	if (errs & ~dd->ipath_lasterror) {
+		errs &= ~dd->ipath_lasterror;
+		/* never suppress duplicate hwerrors or ibstatuschange */
+		dd->ipath_lasterror |= errs &
+			~(INFINIPATH_E_HARDWARE |
+			  INFINIPATH_E_IBSTATUSCHANGED);
+	}
+	if (!errs)
+		return;
+
+	if (!noprint)
+		/*
+		 * the ones we mask off are handled specially below or above
+		 */
+		ipath_decode_err(msg, sizeof msg,
+				 errs & ~(INFINIPATH_E_IBSTATUSCHANGED |
+					  INFINIPATH_E_RRCVEGRFULL |
+					  INFINIPATH_E_RRCVHDRFULL |
+					  INFINIPATH_E_HARDWARE));
+	else
+		/* so we don't need if (!noprint) at strlcat's below */
+		*msg = 0;
+
+	if (errs & E_SUM_PKTERRS) {
+		ipath_stats.sps_pkterrs++;
+		chkerrpkts = 1;
+	}
+	if (errs & E_SUM_ERRS)
+		ipath_stats.sps_errs++;
+
+	if (errs & (INFINIPATH_E_RICRC | INFINIPATH_E_RVCRC)) {
+		ipath_stats.sps_crcerrs++;
+		chkerrpkts = 1;
+	}
+
+	/*
+	 * We don't want to print these two as they happen, or we can make
+	 * the situation even worse, because it takes so long to print
+	 * messages to serial consoles.  Kernel ports get printed from
+	 * fast_stats, no more than every 5 seconds, user ports get printed
+	 * on close
+	 */
+	if (errs & INFINIPATH_E_RRCVHDRFULL) {
+		int any;
+		u32 hd, tl;
+		ipath_stats.sps_hdrqfull++;
+		for (any = i = 0; i < dd->ipath_cfgports; i++) {
+			struct ipath_portdata *pd = dd->ipath_pd[i];
+			if (i == 0) {
+				hd = dd->ipath_port0head;
+				tl = (u32) le64_to_cpu(
+					*dd->ipath_hdrqtailptr);
+			} else if (pd && pd->port_cnt &&
+				   pd->port_rcvhdrtail_kvaddr) {
+				/*
+				 * don't report same point multiple times,
+				 * except kernel
+				 */
+				tl = (u32) * pd->port_rcvhdrtail_kvaddr;
+				if (tl == dd->ipath_lastrcvhdrqtails[i])
+					continue;
+				hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+						       i);
+			} else
+				continue;
+			if (hd == (tl + 1) ||
+			    (!hd && tl == dd->ipath_hdrqlast)) {
+				dd->ipath_lastrcvhdrqtails[i] = tl;
+				pd->port_hdrqfull++;
+				if (i == 0)
+					chkerrpkts = 1;
+			}
+		}
+	}
+	if (errs & INFINIPATH_E_RRCVEGRFULL) {
+		/*
+		 * since this is of less importance and not likely to
+		 * happen without also getting hdrfull, only count
+		 * occurrences; don't check each port (or even the kernel
+		 * vs user)
+		 */
+		ipath_stats.sps_etidfull++;
+		if (dd->ipath_port0head !=
+		    (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+			chkerrpkts = 1;
+	}
+
+	/*
+	 * do this before IBSTATUSCHANGED, in case both bits set in a single
+	 * interrupt; we want the STATUSCHANGE to "win", so we do our
+	 * internal copy of state machine correctly
+	 */
+	if (errs & INFINIPATH_E_RIBLOSTLINK) {
+		/*
+		 * force through block below
+		 */
+		errs |= INFINIPATH_E_IBSTATUSCHANGED;
+		ipath_stats.sps_iblink++;
+		dd->ipath_flags |= IPATH_LINKDOWN;
+		dd->ipath_flags &= ~(IPATH_LINKUNK | IPATH_LINKINIT
+				     | IPATH_LINKARMED | IPATH_LINKACTIVE);
+		*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+		if (!noprint) {
+			u64 st = ipath_read_kreg64(
+				dd, dd->ipath_kregs->kr_ibcstatus);
+
+			ipath_dbg("Lost link, link now down (%s)\n",
+				  ipath_ibcstatus_str[st & 0xf]);
+		}
+	}
+	if (errs & INFINIPATH_E_IBSTATUSCHANGED)
+		handle_e_ibstatuschanged(dd, errs, noprint);
+
+	if (errs & INFINIPATH_E_RESET) {
+		if (!noprint)
+			ipath_dev_err(dd, "Got reset, requires re-init "
+				      "(unload and reload driver)\n");
+		dd->ipath_flags &= ~IPATH_INITTED;	/* needs re-init */
+		/* mark as having had error */
+		*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+		*dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF;
+	}
+
+	if (!noprint && *msg)
+		ipath_dev_err(dd, "%s error\n", msg);
+	if (dd->ipath_sma_state_wanted & dd->ipath_flags) {
+		ipath_cdbg(VERBOSE, "sma wanted state %x, iflags now %x, "
+			   "waking\n", dd->ipath_sma_state_wanted,
+			   dd->ipath_flags);
+		wake_up_interruptible(&ipath_sma_state_wait);
+	}
+
+	if (chkerrpkts)
+		/* process possible error packets in hdrq */
+		ipath_kreceive(dd);
+}
+
+/* this is separate to allow for better optimization of ipath_intr() */
+
+static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+{
+	/*
+	 * sometimes happen during driver init and unload, don't want
+	 * to process any interrupts at that point
+	 */
+
+	/* this is just a bandaid, not a fix, if something goes badly
+	 * wrong */
+	if (++*unexpectp > 100) {
+		if (++*unexpectp > 105) {
+			/*
+			 * ok, we must be taking somebody else's interrupts,
+			 * due to a messed up mptable and/or PIRQ table, so
+			 * unregister the interrupt.  We've seen this during
+			 * linuxbios development work, and it may happen in
+			 * the future again.
+			 */
+			if (dd->pcidev && dd->pcidev->irq) {
+				ipath_dev_err(dd, "Now %u unexpected "
+					      "interrupts, unregistering "
+					      "interrupt handler\n",
+					      *unexpectp);
+				ipath_dbg("free_irq of irq %x\n",
+					  dd->pcidev->irq);
+				free_irq(dd->pcidev->irq, dd);
+			}
+		}
+		if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
+			ipath_dev_err(dd, "%u unexpected interrupts, "
+				      "disabling interrupts completely\n",
+				      *unexpectp);
+			/*
+			 * disable all interrupts, something is very wrong
+			 */
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask,
+					 0ULL);
+		}
+	} else if (*unexpectp > 1)
+		ipath_dbg("Interrupt when not ready, should not happen, "
+			  "ignoring\n");
+}
+
+static void ipath_bad_regread(struct ipath_devdata *dd)
+{
+	static int allbits;
+
+	/* separate routine, for better optimization of ipath_intr() */
+
+	/*
+	 * We print the message and disable interrupts, in hope of
+	 * having a better chance of debugging the problem.
+	 */
+	ipath_dev_err(dd,
+		      "Read of interrupt status failed (all bits set)\n");
+	if (allbits++) {
+		/* disable all interrupts, something is very wrong */
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_intmask, 0ULL);
+		if (allbits == 2) {
+			ipath_dev_err(dd, "Still bad interrupt status, "
+				      "unregistering interrupt\n");
+			free_irq(dd->pcidev->irq, dd);
+		} else if (allbits > 2) {
+			if ((allbits % 10000) == 0)
+				printk(".");
+		} else
+			ipath_dev_err(dd, "Disabling interrupts, "
+				      "multiple errors\n");
+	}
+}
+
+static void handle_port_pioavail(struct ipath_devdata *dd)
+{
+	u32 i;
+	/*
+	 * start from port 1, since for now port 0  is never using
+	 * wait_event for PIO
+	 */
+	for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
+		struct ipath_portdata *pd = dd->ipath_pd[i];
+
+		if (pd && pd->port_cnt &&
+		    dd->ipath_portpiowait & (1U << i)) {
+			clear_bit(i, &dd->ipath_portpiowait);
+			if (test_bit(IPATH_PORT_WAITING_PIO,
+				     &pd->port_flag)) {
+				clear_bit(IPATH_PORT_WAITING_PIO,
+					  &pd->port_flag);
+				wake_up_interruptible(&pd->port_wait);
+			}
+		}
+	}
+}
+
+static void handle_layer_pioavail(struct ipath_devdata *dd)
+{
+	int ret;
+
+	ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
+	if (ret > 0)
+		goto clear;
+
+	ret = __ipath_verbs_piobufavail(dd);
+	if (ret > 0)
+		goto clear;
+
+	return;
+clear:
+	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 dd->ipath_sendctrl);
+}
+
+static void handle_rcv(struct ipath_devdata *dd, u32 istat)
+{
+	u64 portr;
+	int i;
+	int rcvdint = 0;
+
+	portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+		 infinipath_i_rcvavail_mask)
+		| ((istat >> INFINIPATH_I_RCVURG_SHIFT) &
+		   infinipath_i_rcvurg_mask);
+	for (i = 0; i < dd->ipath_cfgports; i++) {
+		struct ipath_portdata *pd = dd->ipath_pd[i];
+		if (portr & (1 << i) && pd &&
+		    pd->port_cnt) {
+			if (i == 0)
+				ipath_kreceive(dd);
+			else if (test_bit(IPATH_PORT_WAITING_RCV,
+					  &pd->port_flag)) {
+				int rcbit;
+				clear_bit(IPATH_PORT_WAITING_RCV,
+					  &pd->port_flag);
+				rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT;
+				clear_bit(1UL << rcbit, &dd->ipath_rcvctrl);
+				wake_up_interruptible(&pd->port_wait);
+				rcvdint = 1;
+			}
+		}
+	}
+	if (rcvdint) {
+		/* only want to take one interrupt, so turn off the rcv
+		 * interrupt for all the ports that we did the wakeup on
+		 * (but never for kernel port)
+		 */
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+				 dd->ipath_rcvctrl);
+	}
+}
+
+irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
+{
+	struct ipath_devdata *dd = data;
+	u32 istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
+	ipath_err_t estat = 0;
+	static unsigned unexpected = 0;
+	irqreturn_t ret;
+
+	if (unlikely(!istat)) {
+		ipath_stats.sps_nullintr++;
+		ret = IRQ_NONE; /* not our interrupt, or already handled */
+		goto bail;
+	}
+	if (unlikely(istat == -1)) {
+		ipath_bad_regread(dd);
+		/* don't know if it was our interrupt or not */
+		ret = IRQ_NONE;
+		goto bail;
+	}
+
+	ipath_stats.sps_ints++;
+
+	/*
+	 * this needs to be flags&initted, not statusp, so we keep
+	 * taking interrupts even after link goes down, etc.
+	 * Also, we *must* clear the interrupt at some point, or we won't
+	 * take it again, which can be real bad for errors, etc...
+	 */
+
+	if (!(dd->ipath_flags & IPATH_INITTED)) {
+		ipath_bad_intr(dd, &unexpected);
+		ret = IRQ_NONE;
+		goto bail;
+	}
+	if (unexpected)
+		unexpected = 0;
+
+	ipath_cdbg(VERBOSE, "intr stat=0x%x\n", istat);
+
+	if (istat & ~infinipath_i_bitsextant)
+		ipath_dev_err(dd,
+			      "interrupt with unknown interrupts %x set\n",
+			      istat & (u32) ~ infinipath_i_bitsextant);
+
+	if (istat & INFINIPATH_I_ERROR) {
+		ipath_stats.sps_errints++;
+		estat = ipath_read_kreg64(dd,
+					  dd->ipath_kregs->kr_errorstatus);
+		if (!estat)
+			dev_info(&dd->pcidev->dev, "error interrupt (%x), "
+				 "but no error bits set!\n", istat);
+		else if (estat == -1LL)
+			/*
+			 * should we try clearing all, or hope next read
+			 * works?
+			 */
+			ipath_dev_err(dd, "Read of error status failed "
+				      "(all bits set); ignoring\n");
+		else
+			handle_errors(dd, estat);
+	}
+
+	if (istat & INFINIPATH_I_GPIO) {
+		if (unlikely(!(dd->ipath_flags & IPATH_GPIO_INTR))) {
+			u32 gpiostatus;
+			gpiostatus = ipath_read_kreg32(
+				dd, dd->ipath_kregs->kr_gpio_status);
+			ipath_dbg("Unexpected GPIO interrupt bits %x\n",
+				  gpiostatus);
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+					 gpiostatus);
+		}
+		else {
+			/* Clear GPIO status bit 2 */
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_clear,
+					 (u64) (1 << 2));
+
+			/*
+			 * Packets are available in the port 0 rcv queue.
+			 * Eventually this needs to be generalized to check
+			 * IPATH_GPIO_INTR, and the specific GPIO bit, if
+			 * GPIO interrupts are used for anything else.
+			 */
+			ipath_kreceive(dd);
+		}
+	}
+
+	/*
+	 * clear the ones we will deal with on this round
+	 * We clear it early, mostly for receive interrupts, so we
+	 * know the chip will have seen this by the time we process
+	 * the queue, and will re-interrupt if necessary.  The processor
+	 * itself won't take the interrupt again until we return.
+	 */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, istat);
+
+	if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+		clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+				 dd->ipath_sendctrl);
+
+		if (dd->ipath_portpiowait)
+			handle_port_pioavail(dd);
+
+		handle_layer_pioavail(dd);
+	}
+
+	/*
+	 * we check for both transition from empty to non-empty, and urgent
+	 * packets (those with the interrupt bit set in the header)
+	 */
+
+	if (istat & ((infinipath_i_rcvavail_mask <<
+		      INFINIPATH_I_RCVAVAIL_SHIFT)
+		     | (infinipath_i_rcvurg_mask <<
+			INFINIPATH_I_RCVURG_SHIFT)))
+		handle_rcv(dd, istat);
+
+	ret = IRQ_HANDLED;
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
new file mode 100644
index 0000000..0ce5f19
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -0,0 +1,883 @@
+#ifndef _IPATH_KERNEL_H
+#define _IPATH_KERNEL_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This header file is the base header file for infinipath kernel code
+ * ipath_user.h serves a similar purpose for user code.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "ipath_common.h"
+#include "ipath_debug.h"
+#include "ipath_registers.h"
+
+/* only s/w major version of InfiniPath we can handle */
+#define IPATH_CHIP_VERS_MAJ 2U
+
+/* don't care about this except printing */
+#define IPATH_CHIP_VERS_MIN 0U
+
+/* temporary, maybe always */
+extern struct infinipath_stats ipath_stats;
+
+#define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+
+struct ipath_portdata {
+	void **port_rcvegrbuf;
+	dma_addr_t *port_rcvegrbuf_phys;
+	/* rcvhdrq base, needs mmap before useful */
+	void *port_rcvhdrq;
+	/* kernel virtual address where hdrqtail is updated */
+	u64 *port_rcvhdrtail_kvaddr;
+	/* page * used for uaddr */
+	struct page *port_rcvhdrtail_pagep;
+	/*
+	 * temp buffer for expected send setup, allocated at open, instead
+	 * of each setup call
+	 */
+	void *port_tid_pg_list;
+	/* when waiting for rcv or pioavail */
+	wait_queue_head_t port_wait;
+	/*
+	 * rcvegr bufs base, physical, must fit
+	 * in 44 bits so 32 bit programs mmap64 44 bit works)
+	 */
+	dma_addr_t port_rcvegr_phys;
+	/* mmap of hdrq, must fit in 44 bits */
+	dma_addr_t port_rcvhdrq_phys;
+	/*
+	 * the actual user address that we ipath_mlock'ed, so we can
+	 * ipath_munlock it at close
+	 */
+	unsigned long port_rcvhdrtail_uaddr;
+	/*
+	 * number of opens on this instance (0 or 1; ignoring forks, dup,
+	 * etc. for now)
+	 */
+	int port_cnt;
+	/*
+	 * how much space to leave at start of eager TID entries for
+	 * protocol use, on each TID
+	 */
+	/* instead of calculating it */
+	unsigned port_port;
+	/* chip offset of PIO buffers for this port */
+	u32 port_piobufs;
+	/* how many alloc_pages() chunks in port_rcvegrbuf_pages */
+	u32 port_rcvegrbuf_chunks;
+	/* how many egrbufs per chunk */
+	u32 port_rcvegrbufs_perchunk;
+	/* order for port_rcvegrbuf_pages */
+	size_t port_rcvegrbuf_size;
+	/* rcvhdrq size (for freeing) */
+	size_t port_rcvhdrq_size;
+	/* next expected TID to check when looking for free */
+	u32 port_tidcursor;
+	/* next expected TID to check */
+	unsigned long port_flag;
+	/* WAIT_RCV that timed out, no interrupt */
+	u32 port_rcvwait_to;
+	/* WAIT_PIO that timed out, no interrupt */
+	u32 port_piowait_to;
+	/* WAIT_RCV already happened, no wait */
+	u32 port_rcvnowait;
+	/* WAIT_PIO already happened, no wait */
+	u32 port_pionowait;
+	/* total number of rcvhdrqfull errors */
+	u32 port_hdrqfull;
+	/* pid of process using this port */
+	pid_t port_pid;
+	/* same size as task_struct .comm[] */
+	char port_comm[16];
+	/* pkeys set by this use of this port */
+	u16 port_pkeys[4];
+	/* so file ops can get at unit */
+	struct ipath_devdata *port_dd;
+};
+
+struct sk_buff;
+
+/*
+ * control information for layered drivers
+ */
+struct _ipath_layer {
+	void *l_arg;
+};
+
+/* Verbs layer interface */
+struct _verbs_layer {
+	void *l_arg;
+	struct timer_list l_timer;
+};
+
+struct ipath_devdata {
+	struct list_head ipath_list;
+
+	struct ipath_kregs const *ipath_kregs;
+	struct ipath_cregs const *ipath_cregs;
+
+	/* mem-mapped pointer to base of chip regs */
+	u64 __iomem *ipath_kregbase;
+	/* end of mem-mapped chip space; range checking */
+	u64 __iomem *ipath_kregend;
+	/* physical address of chip for io_remap, etc. */
+	unsigned long ipath_physaddr;
+	/* base of memory alloced for ipath_kregbase, for free */
+	u64 *ipath_kregalloc;
+	/*
+	 * version of kregbase that doesn't have high bits set (for 32 bit
+	 * programs, so mmap64 44 bit works)
+	 */
+	u64 __iomem *ipath_kregvirt;
+	/*
+	 * virtual address where port0 rcvhdrqtail updated for this unit.
+	 * only written to by the chip, not the driver.
+	 */
+	volatile __le64 *ipath_hdrqtailptr;
+	dma_addr_t ipath_dma_addr;
+	/* ipath_cfgports pointers */
+	struct ipath_portdata **ipath_pd;
+	/* sk_buffs used by port 0 eager receive queue */
+	struct sk_buff **ipath_port0_skbs;
+	/* kvirt address of 1st 2k pio buffer */
+	void __iomem *ipath_pio2kbase;
+	/* kvirt address of 1st 4k pio buffer */
+	void __iomem *ipath_pio4kbase;
+	/*
+	 * points to area where PIOavail registers will be DMA'ed.
+	 * Has to be on a page of it's own, because the page will be
+	 * mapped into user program space.  This copy is *ONLY* ever
+	 * written by DMA, not by the driver!  Need a copy per device
+	 * when we get to multiple devices
+	 */
+	volatile __le64 *ipath_pioavailregs_dma;
+	/* physical address where updates occur */
+	dma_addr_t ipath_pioavailregs_phys;
+	struct _ipath_layer ipath_layer;
+	/* setup intr */
+	int (*ipath_f_intrsetup)(struct ipath_devdata *);
+	/* setup on-chip bus config */
+	int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
+	/* hard reset chip */
+	int (*ipath_f_reset)(struct ipath_devdata *);
+	int (*ipath_f_get_boardname)(struct ipath_devdata *, char *,
+				     size_t);
+	void (*ipath_f_init_hwerrors)(struct ipath_devdata *);
+	void (*ipath_f_handle_hwerrors)(struct ipath_devdata *, char *,
+					size_t);
+	void (*ipath_f_quiet_serdes)(struct ipath_devdata *);
+	int (*ipath_f_bringup_serdes)(struct ipath_devdata *);
+	int (*ipath_f_early_init)(struct ipath_devdata *);
+	void (*ipath_f_clear_tids)(struct ipath_devdata *, unsigned);
+	void (*ipath_f_put_tid)(struct ipath_devdata *, u64 __iomem*,
+				u32, unsigned long);
+	void (*ipath_f_tidtemplate)(struct ipath_devdata *);
+	void (*ipath_f_cleanup)(struct ipath_devdata *);
+	void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64);
+	/* fill out chip-specific fields */
+	int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
+	struct _verbs_layer verbs_layer;
+	/* total dwords sent (summed from counter) */
+	u64 ipath_sword;
+	/* total dwords rcvd (summed from counter) */
+	u64 ipath_rword;
+	/* total packets sent (summed from counter) */
+	u64 ipath_spkts;
+	/* total packets rcvd (summed from counter) */
+	u64 ipath_rpkts;
+	/* ipath_statusp initially points to this. */
+	u64 _ipath_status;
+	/* GUID for this interface, in network order */
+	__be64 ipath_guid;
+	/*
+	 * aggregrate of error bits reported since last cleared, for
+	 * limiting of error reporting
+	 */
+	ipath_err_t ipath_lasterror;
+	/*
+	 * aggregrate of error bits reported since last cleared, for
+	 * limiting of hwerror reporting
+	 */
+	ipath_err_t ipath_lasthwerror;
+	/*
+	 * errors masked because they occur too fast, also includes errors
+	 * that are always ignored (ipath_ignorederrs)
+	 */
+	ipath_err_t ipath_maskederrs;
+	/* time in jiffies at which to re-enable maskederrs */
+	unsigned long ipath_unmasktime;
+	/*
+	 * errors always ignored (masked), at least for a given
+	 * chip/device, because they are wrong or not useful
+	 */
+	ipath_err_t ipath_ignorederrs;
+	/* count of egrfull errors, combined for all ports */
+	u64 ipath_last_tidfull;
+	/* for ipath_qcheck() */
+	u64 ipath_lastport0rcv_cnt;
+	/* template for writing TIDs  */
+	u64 ipath_tidtemplate;
+	/* value to write to free TIDs */
+	u64 ipath_tidinvalid;
+	/* PE-800 rcv interrupt setup */
+	u64 ipath_rhdrhead_intr_off;
+
+	/* size of memory at ipath_kregbase */
+	u32 ipath_kregsize;
+	/* number of registers used for pioavail */
+	u32 ipath_pioavregs;
+	/* IPATH_POLL, etc. */
+	u32 ipath_flags;
+	/* ipath_flags sma is waiting for */
+	u32 ipath_sma_state_wanted;
+	/* last buffer for user use, first buf for kernel use is this
+	 * index. */
+	u32 ipath_lastport_piobuf;
+	/* is a stats timer active */
+	u32 ipath_stats_timer_active;
+	/* dwords sent read from counter */
+	u32 ipath_lastsword;
+	/* dwords received read from counter */
+	u32 ipath_lastrword;
+	/* sent packets read from counter */
+	u32 ipath_lastspkts;
+	/* received packets read from counter */
+	u32 ipath_lastrpkts;
+	/* pio bufs allocated per port */
+	u32 ipath_pbufsport;
+	/*
+	 * number of ports configured as max; zero is set to number chip
+	 * supports, less gives more pio bufs/port, etc.
+	 */
+	u32 ipath_cfgports;
+	/* port0 rcvhdrq head offset */
+	u32 ipath_port0head;
+	/* count of port 0 hdrqfull errors */
+	u32 ipath_p0_hdrqfull;
+
+	/*
+	 * (*cfgports) used to suppress multiple instances of same
+	 * port staying stuck at same point
+	 */
+	u32 *ipath_lastrcvhdrqtails;
+	/*
+	 * (*cfgports) used to suppress multiple instances of same
+	 * port staying stuck at same point
+	 */
+	u32 *ipath_lastegrheads;
+	/*
+	 * index of last piobuffer we used.  Speeds up searching, by
+	 * starting at this point.  Doesn't matter if multiple cpu's use and
+	 * update, last updater is only write that matters.  Whenever it
+	 * wraps, we update shadow copies.  Need a copy per device when we
+	 * get to multiple devices
+	 */
+	u32 ipath_lastpioindex;
+	/* max length of freezemsg */
+	u32 ipath_freezelen;
+	/*
+	 * consecutive times we wanted a PIO buffer but were unable to
+	 * get one
+	 */
+	u32 ipath_consec_nopiobuf;
+	/*
+	 * hint that we should update ipath_pioavailshadow before
+	 * looking for a PIO buffer
+	 */
+	u32 ipath_upd_pio_shadow;
+	/* so we can rewrite it after a chip reset */
+	u32 ipath_pcibar0;
+	/* so we can rewrite it after a chip reset */
+	u32 ipath_pcibar1;
+	/* sequential tries for SMA send and no bufs */
+	u32 ipath_nosma_bufs;
+	/* duration (seconds) ipath_nosma_bufs set */
+	u32 ipath_nosma_secs;
+
+	/* HT/PCI Vendor ID (here for NodeInfo) */
+	u16 ipath_vendorid;
+	/* HT/PCI Device ID (here for NodeInfo) */
+	u16 ipath_deviceid;
+	/* offset in HT config space of slave/primary interface block */
+	u8 ipath_ht_slave_off;
+	/* for write combining settings */
+	unsigned long ipath_wc_cookie;
+	/* ref count for each pkey */
+	atomic_t ipath_pkeyrefs[4];
+	/* shadow copy of all exptids physaddr; used only by funcsim */
+	u64 *ipath_tidsimshadow;
+	/* shadow copy of struct page *'s for exp tid pages */
+	struct page **ipath_pageshadow;
+	/* lock to workaround chip bug 9437 */
+	spinlock_t ipath_tid_lock;
+
+	/*
+	 * IPATH_STATUS_*,
+	 * this address is mapped readonly into user processes so they can
+	 * get status cheaply, whenever they want.
+	 */
+	u64 *ipath_statusp;
+	/* freeze msg if hw error put chip in freeze */
+	char *ipath_freezemsg;
+	/* pci access data structure */
+	struct pci_dev *pcidev;
+	struct cdev *cdev;
+	struct class_device *class_dev;
+	/* timer used to prevent stats overflow, error throttling, etc. */
+	struct timer_list ipath_stats_timer;
+	/* check for stale messages in rcv queue */
+	/* only allow one intr at a time. */
+	unsigned long ipath_rcv_pending;
+
+	/*
+	 * Shadow copies of registers; size indicates read access size.
+	 * Most of them are readonly, but some are write-only register,
+	 * where we manipulate the bits in the shadow copy, and then write
+	 * the shadow copy to infinipath.
+	 *
+	 * We deliberately make most of these 32 bits, since they have
+	 * restricted range.  For any that we read, we won't to generate 32
+	 * bit accesses, since Opteron will generate 2 separate 32 bit HT
+	 * transactions for a 64 bit read, and we want to avoid unnecessary
+	 * HT transactions.
+	 */
+
+	/* This is the 64 bit group */
+
+	/*
+	 * shadow of pioavail, check to be sure it's large enough at
+	 * init time.
+	 */
+	unsigned long ipath_pioavailshadow[8];
+	/* shadow of kr_gpio_out, for rmw ops */
+	u64 ipath_gpio_out;
+	/* kr_revision shadow */
+	u64 ipath_revision;
+	/*
+	 * shadow of ibcctrl, for interrupt handling of link changes,
+	 * etc.
+	 */
+	u64 ipath_ibcctrl;
+	/*
+	 * last ibcstatus, to suppress "duplicate" status change messages,
+	 * mostly from 2 to 3
+	 */
+	u64 ipath_lastibcstat;
+	/* hwerrmask shadow */
+	ipath_err_t ipath_hwerrmask;
+	/* interrupt config reg shadow */
+	u64 ipath_intconfig;
+	/* kr_sendpiobufbase value */
+	u64 ipath_piobufbase;
+
+	/* these are the "32 bit" regs */
+
+	/*
+	 * number of GUIDs in the flash for this interface; may need some
+	 * rethinking for setting on other ifaces
+	 */
+	u32 ipath_nguid;
+	/*
+	 * the following two are 32-bit bitmasks, but {test,clear,set}_bit
+	 * all expect bit fields to be "unsigned long"
+	 */
+	/* shadow kr_rcvctrl */
+	unsigned long ipath_rcvctrl;
+	/* shadow kr_sendctrl */
+	unsigned long ipath_sendctrl;
+
+	/* value we put in kr_rcvhdrcnt */
+	u32 ipath_rcvhdrcnt;
+	/* value we put in kr_rcvhdrsize */
+	u32 ipath_rcvhdrsize;
+	/* value we put in kr_rcvhdrentsize */
+	u32 ipath_rcvhdrentsize;
+	/* offset of last entry in rcvhdrq */
+	u32 ipath_hdrqlast;
+	/* kr_portcnt value */
+	u32 ipath_portcnt;
+	/* kr_pagealign value */
+	u32 ipath_palign;
+	/* number of "2KB" PIO buffers */
+	u32 ipath_piobcnt2k;
+	/* size in bytes of "2KB" PIO buffers */
+	u32 ipath_piosize2k;
+	/* number of "4KB" PIO buffers */
+	u32 ipath_piobcnt4k;
+	/* size in bytes of "4KB" PIO buffers */
+	u32 ipath_piosize4k;
+	/* kr_rcvegrbase value */
+	u32 ipath_rcvegrbase;
+	/* kr_rcvegrcnt value */
+	u32 ipath_rcvegrcnt;
+	/* kr_rcvtidbase value */
+	u32 ipath_rcvtidbase;
+	/* kr_rcvtidcnt value */
+	u32 ipath_rcvtidcnt;
+	/* kr_sendregbase */
+	u32 ipath_sregbase;
+	/* kr_userregbase */
+	u32 ipath_uregbase;
+	/* kr_counterregbase */
+	u32 ipath_cregbase;
+	/* shadow the control register contents */
+	u32 ipath_control;
+	/* shadow the gpio output contents */
+	u32 ipath_extctrl;
+	/* PCI revision register (HTC rev on FPGA) */
+	u32 ipath_pcirev;
+
+	/* chip address space used by 4k pio buffers */
+	u32 ipath_4kalign;
+	/* The MTU programmed for this unit */
+	u32 ipath_ibmtu;
+	/*
+	 * The max size IB packet, included IB headers that we can send.
+	 * Starts same as ipath_piosize, but is affected when ibmtu is
+	 * changed, or by size of eager buffers
+	 */
+	u32 ipath_ibmaxlen;
+	/*
+	 * ibmaxlen at init time, limited by chip and by receive buffer
+	 * size.  Not changed after init.
+	 */
+	u32 ipath_init_ibmaxlen;
+	/* size of each rcvegrbuffer */
+	u32 ipath_rcvegrbufsize;
+	/* width (2,4,8,16,32) from HT config reg */
+	u32 ipath_htwidth;
+	/* HT speed (200,400,800,1000) from HT config */
+	u32 ipath_htspeed;
+	/* ports waiting for PIOavail intr */
+	unsigned long ipath_portpiowait;
+	/*
+	 * number of sequential ibcstatus change for polling active/quiet
+	 * (i.e., link not coming up).
+	 */
+	u32 ipath_ibpollcnt;
+	/* low and high portions of MSI capability/vector */
+	u32 ipath_msi_lo;
+	/* saved after PCIe init for restore after reset */
+	u32 ipath_msi_hi;
+	/* MSI data (vector) saved for restore */
+	u16 ipath_msi_data;
+	/* MLID programmed for this instance */
+	u16 ipath_mlid;
+	/* LID programmed for this instance */
+	u16 ipath_lid;
+	/* list of pkeys programmed; 0 if not set */
+	u16 ipath_pkeys[4];
+	/* ASCII serial number, from flash */
+	u8 ipath_serial[12];
+	/* human readable board version */
+	u8 ipath_boardversion[80];
+	/* chip major rev, from ipath_revision */
+	u8 ipath_majrev;
+	/* chip minor rev, from ipath_revision */
+	u8 ipath_minrev;
+	/* board rev, from ipath_revision */
+	u8 ipath_boardrev;
+	/* unit # of this chip, if present */
+	int ipath_unit;
+	/* saved for restore after reset */
+	u8 ipath_pci_cacheline;
+	/* LID mask control */
+	u8 ipath_lmc;
+};
+
+extern volatile __le64 *ipath_port0_rcvhdrtail;
+extern dma_addr_t ipath_port0_rcvhdrtail_dma;
+
+#define IPATH_PORT0_RCVHDRTAIL_SIZE PAGE_SIZE
+
+extern struct list_head ipath_dev_list;
+extern spinlock_t ipath_devs_lock;
+extern struct ipath_devdata *ipath_lookup(int unit);
+
+extern u16 ipath_layer_rcv_opcode;
+extern int __ipath_layer_intr(struct ipath_devdata *, u32);
+extern int ipath_layer_intr(struct ipath_devdata *, u32);
+extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
+			     struct sk_buff *);
+extern int __ipath_layer_rcv_lid(struct ipath_devdata *, void *);
+extern int __ipath_verbs_piobufavail(struct ipath_devdata *);
+extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32);
+
+void ipath_layer_add(struct ipath_devdata *);
+void ipath_layer_del(struct ipath_devdata *);
+
+int ipath_init_chip(struct ipath_devdata *, int);
+int ipath_enable_wc(struct ipath_devdata *dd);
+void ipath_disable_wc(struct ipath_devdata *dd);
+int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
+void ipath_shutdown_device(struct ipath_devdata *);
+
+struct file_operations;
+int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+		    struct cdev **cdevp, struct class_device **class_devp);
+void ipath_cdev_cleanup(struct cdev **cdevp,
+			struct class_device **class_devp);
+
+int ipath_diag_init(void);
+void ipath_diag_cleanup(void);
+void ipath_diag_bringup_link(struct ipath_devdata *);
+
+extern wait_queue_head_t ipath_sma_state_wait;
+
+int ipath_user_add(struct ipath_devdata *dd);
+void ipath_user_del(struct ipath_devdata *dd);
+
+struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, gfp_t);
+
+extern int ipath_diag_inuse;
+
+irqreturn_t ipath_intr(int irq, void *devid, struct pt_regs *regs);
+void ipath_decode_err(char *buf, size_t blen, ipath_err_t err);
+#if __IPATH_INFO || __IPATH_DBG
+extern const char *ipath_ibcstatus_str[];
+#endif
+
+/* clean up any per-chip chip-specific stuff */
+void ipath_chip_cleanup(struct ipath_devdata *);
+/* clean up any chip type-specific stuff */
+void ipath_chip_done(void);
+
+/* check to see if we have to force ordering for write combining */
+int ipath_unordered_wc(void);
+
+void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
+			  unsigned cnt);
+
+int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
+void ipath_free_pddata(struct ipath_devdata *, u32, int);
+
+int ipath_parse_ushort(const char *str, unsigned short *valp);
+
+int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
+void ipath_set_ib_lstate(struct ipath_devdata *, int);
+void ipath_kreceive(struct ipath_devdata *);
+int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
+int ipath_reset_device(int);
+void ipath_get_faststats(unsigned long);
+
+/* for use in system calls, where we want to know device type, etc. */
+#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
+
+/*
+ * values for ipath_flags
+ */
+/* The chip is up and initted */
+#define IPATH_INITTED       0x2
+		/* set if any user code has set kr_rcvhdrsize */
+#define IPATH_RCVHDRSZ_SET  0x4
+		/* The chip is present and valid for accesses */
+#define IPATH_PRESENT       0x8
+		/* HT link0 is only 8 bits wide, ignore upper byte crc
+		 * errors, etc. */
+#define IPATH_8BIT_IN_HT0   0x10
+		/* HT link1 is only 8 bits wide, ignore upper byte crc
+		 * errors, etc. */
+#define IPATH_8BIT_IN_HT1   0x20
+		/* The link is down */
+#define IPATH_LINKDOWN      0x40
+		/* The link level is up (0x11) */
+#define IPATH_LINKINIT      0x80
+		/* The link is in the armed (0x21) state */
+#define IPATH_LINKARMED     0x100
+		/* The link is in the active (0x31) state */
+#define IPATH_LINKACTIVE    0x200
+		/* link current state is unknown */
+#define IPATH_LINKUNK       0x400
+		/* no IB cable, or no device on IB cable */
+#define IPATH_NOCABLE       0x4000
+		/* Supports port zero per packet receive interrupts via
+		 * GPIO */
+#define IPATH_GPIO_INTR     0x8000
+		/* uses the coded 4byte TID, not 8 byte */
+#define IPATH_4BYTE_TID     0x10000
+		/* packet/word counters are 32 bit, else those 4 counters
+		 * are 64bit */
+#define IPATH_32BITCOUNTERS 0x20000
+		/* can miss port0 rx interrupts */
+#define IPATH_POLL_RX_INTR  0x40000
+#define IPATH_DISABLED      0x80000 /* administratively disabled */
+
+/* portdata flag bit offsets */
+		/* waiting for a packet to arrive */
+#define IPATH_PORT_WAITING_RCV   2
+		/* waiting for a PIO buffer to be available */
+#define IPATH_PORT_WAITING_PIO   3
+
+/* free up any allocated data at closes */
+void ipath_free_data(struct ipath_portdata *dd);
+int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
+int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
+u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
+/* init PE-800-specific func */
+void ipath_init_pe800_funcs(struct ipath_devdata *);
+/* init HT-400-specific func */
+void ipath_init_ht400_funcs(struct ipath_devdata *);
+void ipath_get_guid(struct ipath_devdata *);
+u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
+
+/*
+ * number of words used for protocol header if not set by ipath_userinit();
+ */
+#define IPATH_DFLT_RCVHDRSIZE 9
+
+#define IPATH_MDIO_CMD_WRITE   1
+#define IPATH_MDIO_CMD_READ    2
+#define IPATH_MDIO_CLD_DIV     25	/* to get 2.5 Mhz mdio clock */
+#define IPATH_MDIO_CMDVALID    0x40000000	/* bit 30 */
+#define IPATH_MDIO_DATAVALID   0x80000000	/* bit 31 */
+#define IPATH_MDIO_CTRL_STD    0x0
+
+static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
+{
+	return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
+		(cmd << 26) |
+		(dev << 21) |
+		(reg << 16) |
+		(data & 0xFFFF);
+}
+
+		/* signal and fifo status, in bank 31 */
+#define IPATH_MDIO_CTRL_XGXS_REG_8  0x8
+		/* controls loopback, redundancy */
+#define IPATH_MDIO_CTRL_8355_REG_1  0x10
+		/* premph, encdec, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_2  0x11
+		/* Kchars, etc. */
+#define IPATH_MDIO_CTRL_8355_REG_6  0x15
+#define IPATH_MDIO_CTRL_8355_REG_9  0x18
+#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
+
+int ipath_get_user_pages(unsigned long, size_t, struct page **);
+int ipath_get_user_pages_nocopy(unsigned long, struct page **);
+void ipath_release_user_pages(struct page **, size_t);
+void ipath_release_user_pages_on_close(struct page **, size_t);
+int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int);
+int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int);
+
+/* these are used for the registers that vary with port */
+void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg,
+			   unsigned, u64);
+u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg,
+			   unsigned);
+
+/*
+ * We could have a single register get/put routine, that takes a group type,
+ * but this is somewhat clearer and cleaner.  It also gives us some error
+ * checking.  64 bit register reads should always work, but are inefficient
+ * on opteron (the northbridge always generates 2 separate HT 32 bit reads),
+ * so we use kreg32 wherever possible.  User register and counter register
+ * reads are always 32 bit reads, so only one form of those routines.
+ */
+
+/*
+ * At the moment, none of the s-registers are writable, so no
+ * ipath_write_sreg(), and none of the c-registers are writable, so no
+ * ipath_write_creg().
+ */
+
+/**
+ * ipath_read_ureg32 - read 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @port: port number
+ *
+ * Return the contents of a register that is virtualized to be per port.
+ * Prints a debug message and returns -1 on errors (not distinguishable from
+ * valid contents at runtime; we may add a separate error variable at some
+ * point).
+ *
+ * This is normally not used by the kernel, but may be for debugging, and
+ * has a different implementation than user mode, which is why it's not in
+ * _common.h.
+ */
+static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
+				    ipath_ureg regno, int port)
+{
+	if (!dd->ipath_kregbase)
+		return 0;
+
+	return readl(regno + (u64 __iomem *)
+		     (dd->ipath_uregbase +
+		      (char __iomem *)dd->ipath_kregbase +
+		      dd->ipath_palign * port));
+}
+
+/**
+ * ipath_write_ureg - write 32-bit virtualized per-port register
+ * @dd: device
+ * @regno: register number
+ * @value: value
+ * @port: port
+ *
+ * Write the contents of a register that is virtualized to be per port.
+ */
+static inline void ipath_write_ureg(const struct ipath_devdata *dd,
+				    ipath_ureg regno, u64 value, int port)
+{
+	u64 __iomem *ubase = (u64 __iomem *)
+		(dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
+		 dd->ipath_palign * port);
+	if (dd->ipath_kregbase)
+		writeq(value, &ubase[regno]);
+}
+
+static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd,
+				    ipath_kreg regno)
+{
+	if (!dd->ipath_kregbase)
+		return -1;
+	return readl((u32 __iomem *) & dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd,
+				    ipath_kreg regno)
+{
+	if (!dd->ipath_kregbase)
+		return -1;
+
+	return readq(&dd->ipath_kregbase[regno]);
+}
+
+static inline void ipath_write_kreg(const struct ipath_devdata *dd,
+				    ipath_kreg regno, u64 value)
+{
+	if (dd->ipath_kregbase)
+		writeq(value, &dd->ipath_kregbase[regno]);
+}
+
+static inline u64 ipath_read_creg(const struct ipath_devdata *dd,
+				  ipath_sreg regno)
+{
+	if (!dd->ipath_kregbase)
+		return 0;
+
+	return readq(regno + (u64 __iomem *)
+		     (dd->ipath_cregbase +
+		      (char __iomem *)dd->ipath_kregbase));
+}
+
+static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
+					 ipath_sreg regno)
+{
+	if (!dd->ipath_kregbase)
+		return 0;
+	return readl(regno + (u64 __iomem *)
+		     (dd->ipath_cregbase +
+		      (char __iomem *)dd->ipath_kregbase));
+}
+
+/*
+ * sysfs interface.
+ */
+
+struct device_driver;
+
+extern const char ipath_core_version[];
+
+int ipath_driver_create_group(struct device_driver *);
+void ipath_driver_remove_group(struct device_driver *);
+
+int ipath_device_create_group(struct device *, struct ipath_devdata *);
+void ipath_device_remove_group(struct device *, struct ipath_devdata *);
+int ipath_expose_reset(struct device *);
+
+int ipath_init_ipathfs(void);
+void ipath_exit_ipathfs(void);
+int ipathfs_add_device(struct ipath_devdata *);
+int ipathfs_remove_device(struct ipath_devdata *);
+
+/*
+ * Flush write combining store buffers (if present) and perform a write
+ * barrier.
+ */
+#if defined(CONFIG_X86_64)
+#define ipath_flush_wc() asm volatile("sfence" ::: "memory")
+#else
+#define ipath_flush_wc() wmb()
+#endif
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+const char *ipath_get_unit_name(int unit);
+
+extern struct mutex ipath_mutex;
+
+#define IPATH_DRV_NAME		"ipath_core"
+#define IPATH_MAJOR		233
+#define IPATH_SMA_MINOR		128
+#define IPATH_DIAG_MINOR	129
+#define IPATH_NMINORS		130
+
+#define ipath_dev_err(dd,fmt,...) \
+	do { \
+		const struct ipath_devdata *__dd = (dd); \
+		if (__dd->pcidev) \
+			dev_err(&__dd->pcidev->dev, "%s: " fmt, \
+				ipath_get_unit_name(__dd->ipath_unit), \
+				##__VA_ARGS__); \
+		else \
+			printk(KERN_ERR IPATH_DRV_NAME ": %s: " fmt, \
+			       ipath_get_unit_name(__dd->ipath_unit), \
+			       ##__VA_ARGS__); \
+	} while (0)
+
+#if _IPATH_DEBUGGING
+
+# define __IPATH_DBG_WHICH(which,fmt,...) \
+	do { \
+		if(unlikely(ipath_debug&(which))) \
+			printk(KERN_DEBUG IPATH_DRV_NAME ": %s: " fmt, \
+			       __func__,##__VA_ARGS__); \
+	} while(0)
+
+# define ipath_dbg(fmt,...) \
+	__IPATH_DBG_WHICH(__IPATH_DBG,fmt,##__VA_ARGS__)
+# define ipath_cdbg(which,fmt,...) \
+	__IPATH_DBG_WHICH(__IPATH_##which##DBG,fmt,##__VA_ARGS__)
+
+#else /* ! _IPATH_DEBUGGING */
+
+# define ipath_dbg(fmt,...)
+# define ipath_cdbg(which,fmt,...)
+
+#endif /* _IPATH_DEBUGGING */
+
+#endif				/* _IPATH_KERNEL_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
new file mode 100644
index 0000000..aa33b0e
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <asm/io.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_alloc_lkey - allocate an lkey
+ * @rkt: lkey table in which to allocate the lkey
+ * @mr: memory region that this lkey protects
+ *
+ * Returns 1 if successful, otherwise returns 0.
+ */
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr)
+{
+	unsigned long flags;
+	u32 r;
+	u32 n;
+	int ret;
+
+	spin_lock_irqsave(&rkt->lock, flags);
+
+	/* Find the next available LKEY */
+	r = n = rkt->next;
+	for (;;) {
+		if (rkt->table[r] == NULL)
+			break;
+		r = (r + 1) & (rkt->max - 1);
+		if (r == n) {
+			spin_unlock_irqrestore(&rkt->lock, flags);
+			_VERBS_INFO("LKEY table full\n");
+			ret = 0;
+			goto bail;
+		}
+	}
+	rkt->next = (r + 1) & (rkt->max - 1);
+	/*
+	 * Make sure lkey is never zero which is reserved to indicate an
+	 * unrestricted LKEY.
+	 */
+	rkt->gen++;
+	mr->lkey = (r << (32 - ib_ipath_lkey_table_size)) |
+		((((1 << (24 - ib_ipath_lkey_table_size)) - 1) & rkt->gen)
+		 << 8);
+	if (mr->lkey == 0) {
+		mr->lkey |= 1 << 8;
+		rkt->gen++;
+	}
+	rkt->table[r] = mr;
+	spin_unlock_irqrestore(&rkt->lock, flags);
+
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_free_lkey - free an lkey
+ * @rkt: table from which to free the lkey
+ * @lkey: lkey id to free
+ */
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey)
+{
+	unsigned long flags;
+	u32 r;
+
+	if (lkey == 0)
+		return;
+	r = lkey >> (32 - ib_ipath_lkey_table_size);
+	spin_lock_irqsave(&rkt->lock, flags);
+	rkt->table[r] = NULL;
+	spin_unlock_irqrestore(&rkt->lock, flags);
+}
+
+/**
+ * ipath_lkey_ok - check IB SGE for validity and initialize
+ * @rkt: table containing lkey to check SGE against
+ * @isge: outgoing internal SGE
+ * @sge: SGE to check
+ * @acc: access flags
+ *
+ * Return 1 if valid and successful, otherwise returns 0.
+ *
+ * Check the IB SGE for validity and initialize our internal version
+ * of it.
+ */
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+		  struct ib_sge *sge, int acc)
+{
+	struct ipath_mregion *mr;
+	size_t off;
+	int ret;
+
+	/*
+	 * We use LKEY == zero to mean a physical kmalloc() address.
+	 * This is a bit of a hack since we rely on dma_map_single()
+	 * being reversible by calling bus_to_virt().
+	 */
+	if (sge->lkey == 0) {
+		isge->mr = NULL;
+		isge->vaddr = bus_to_virt(sge->addr);
+		isge->length = sge->length;
+		isge->sge_length = sge->length;
+		ret = 1;
+		goto bail;
+	}
+	spin_lock(&rkt->lock);
+	mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))];
+	spin_unlock(&rkt->lock);
+	if (unlikely(mr == NULL || mr->lkey != sge->lkey)) {
+		ret = 0;
+		goto bail;
+	}
+
+	off = sge->addr - mr->user_base;
+	if (unlikely(sge->addr < mr->user_base ||
+		     off + sge->length > mr->length ||
+		     (mr->access_flags & acc) != acc)) {
+		ret = 0;
+		goto bail;
+	}
+
+	off += mr->offset;
+	isge->mr = mr;
+	isge->m = 0;
+	isge->n = 0;
+	while (off >= mr->map[isge->m]->segs[isge->n].length) {
+		off -= mr->map[isge->m]->segs[isge->n].length;
+		isge->n++;
+		if (isge->n >= IPATH_SEGSZ) {
+			isge->m++;
+			isge->n = 0;
+		}
+	}
+	isge->vaddr = mr->map[isge->m]->segs[isge->n].vaddr + off;
+	isge->length = mr->map[isge->m]->segs[isge->n].length - off;
+	isge->sge_length = sge->length;
+
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_rkey_ok - check the IB virtual address, length, and RKEY
+ * @dev: infiniband device
+ * @ss: SGE state
+ * @len: length of data
+ * @vaddr: virtual address to place data
+ * @rkey: rkey to check
+ * @acc: access flags
+ *
+ * Return 1 if successful, otherwise 0.
+ *
+ * The QP r_rq.lock should be held.
+ */
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+		  u32 len, u64 vaddr, u32 rkey, int acc)
+{
+	struct ipath_lkey_table *rkt = &dev->lk_table;
+	struct ipath_sge *sge = &ss->sge;
+	struct ipath_mregion *mr;
+	size_t off;
+	int ret;
+
+	spin_lock(&rkt->lock);
+	mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))];
+	spin_unlock(&rkt->lock);
+	if (unlikely(mr == NULL || mr->lkey != rkey)) {
+		ret = 0;
+		goto bail;
+	}
+
+	off = vaddr - mr->iova;
+	if (unlikely(vaddr < mr->iova || off + len > mr->length ||
+		     (mr->access_flags & acc) == 0)) {
+		ret = 0;
+		goto bail;
+	}
+
+	off += mr->offset;
+	sge->mr = mr;
+	sge->m = 0;
+	sge->n = 0;
+	while (off >= mr->map[sge->m]->segs[sge->n].length) {
+		off -= mr->map[sge->m]->segs[sge->n].length;
+		sge->n++;
+		if (sge->n >= IPATH_SEGSZ) {
+			sge->m++;
+			sge->n = 0;
+		}
+	}
+	sge->vaddr = mr->map[sge->m]->segs[sge->n].vaddr + off;
+	sge->length = mr->map[sge->m]->segs[sge->n].length - off;
+	sge->sge_length = len;
+	ss->sg_list = NULL;
+	ss->num_sge = 1;
+
+	ret = 1;
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
new file mode 100644
index 0000000..69ed110
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -0,0 +1,1515 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * These are the routines used by layered drivers, currently just the
+ * layered ethernet driver and verbs layer.
+ */
+
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <asm/byteorder.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/* Acquire before ipath_devs_lock. */
+static DEFINE_MUTEX(ipath_layer_mutex);
+
+u16 ipath_layer_rcv_opcode;
+static int (*layer_intr)(void *, u32);
+static int (*layer_rcv)(void *, void *, struct sk_buff *);
+static int (*layer_rcv_lid)(void *, void *);
+static int (*verbs_piobufavail)(void *);
+static void (*verbs_rcv)(void *, void *, void *, u32);
+static int ipath_verbs_registered;
+
+static void *(*layer_add_one)(int, struct ipath_devdata *);
+static void (*layer_remove_one)(void *);
+static void *(*verbs_add_one)(int, struct ipath_devdata *);
+static void (*verbs_remove_one)(void *);
+static void (*verbs_timer_cb)(void *);
+
+int __ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+	int ret = -ENODEV;
+
+	if (dd->ipath_layer.l_arg && layer_intr)
+		ret = layer_intr(dd->ipath_layer.l_arg, arg);
+
+	return ret;
+}
+
+int ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
+{
+	int ret;
+
+	mutex_lock(&ipath_layer_mutex);
+
+	ret = __ipath_layer_intr(dd, arg);
+
+	mutex_unlock(&ipath_layer_mutex);
+
+	return ret;
+}
+
+int __ipath_layer_rcv(struct ipath_devdata *dd, void *hdr,
+		      struct sk_buff *skb)
+{
+	int ret = -ENODEV;
+
+	if (dd->ipath_layer.l_arg && layer_rcv)
+		ret = layer_rcv(dd->ipath_layer.l_arg, hdr, skb);
+
+	return ret;
+}
+
+int __ipath_layer_rcv_lid(struct ipath_devdata *dd, void *hdr)
+{
+	int ret = -ENODEV;
+
+	if (dd->ipath_layer.l_arg && layer_rcv_lid)
+		ret = layer_rcv_lid(dd->ipath_layer.l_arg, hdr);
+
+	return ret;
+}
+
+int __ipath_verbs_piobufavail(struct ipath_devdata *dd)
+{
+	int ret = -ENODEV;
+
+	if (dd->verbs_layer.l_arg && verbs_piobufavail)
+		ret = verbs_piobufavail(dd->verbs_layer.l_arg);
+
+	return ret;
+}
+
+int __ipath_verbs_rcv(struct ipath_devdata *dd, void *rc, void *ebuf,
+		      u32 tlen)
+{
+	int ret = -ENODEV;
+
+	if (dd->verbs_layer.l_arg && verbs_rcv) {
+		verbs_rcv(dd->verbs_layer.l_arg, rc, ebuf, tlen);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 newstate)
+{
+	u32 lstate;
+	int ret;
+
+	switch (newstate) {
+	case IPATH_IB_LINKDOWN:
+		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
+				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+		/* don't wait */
+		ret = 0;
+		goto bail;
+
+	case IPATH_IB_LINKDOWN_SLEEP:
+		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
+				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+		/* don't wait */
+		ret = 0;
+		goto bail;
+
+	case IPATH_IB_LINKDOWN_DISABLE:
+		ipath_set_ib_lstate(dd,
+				    INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
+				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+		/* don't wait */
+		ret = 0;
+		goto bail;
+
+	case IPATH_IB_LINKINIT:
+		if (dd->ipath_flags & IPATH_LINKINIT) {
+			ret = 0;
+			goto bail;
+		}
+		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
+				    INFINIPATH_IBCC_LINKCMD_SHIFT);
+		lstate = IPATH_LINKINIT;
+		break;
+
+	case IPATH_IB_LINKARM:
+		if (dd->ipath_flags & IPATH_LINKARMED) {
+			ret = 0;
+			goto bail;
+		}
+		if (!(dd->ipath_flags &
+		      (IPATH_LINKINIT | IPATH_LINKACTIVE))) {
+			ret = -EINVAL;
+			goto bail;
+		}
+		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
+				    INFINIPATH_IBCC_LINKCMD_SHIFT);
+		/*
+		 * Since the port can transition to ACTIVE by receiving
+		 * a non VL 15 packet, wait for either state.
+		 */
+		lstate = IPATH_LINKARMED | IPATH_LINKACTIVE;
+		break;
+
+	case IPATH_IB_LINKACTIVE:
+		if (dd->ipath_flags & IPATH_LINKACTIVE) {
+			ret = 0;
+			goto bail;
+		}
+		if (!(dd->ipath_flags & IPATH_LINKARMED)) {
+			ret = -EINVAL;
+			goto bail;
+		}
+		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
+				    INFINIPATH_IBCC_LINKCMD_SHIFT);
+		lstate = IPATH_LINKACTIVE;
+		break;
+
+	default:
+		ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
+		ret = -EINVAL;
+		goto bail;
+	}
+	ret = ipath_wait_linkstate(dd, lstate, 2000);
+
+bail:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkstate);
+
+/**
+ * ipath_layer_set_mtu - set the MTU
+ * @dd: the infinipath device
+ * @arg: the new MTU
+ *
+ * we can handle "any" incoming size, the issue here is whether we
+ * need to restrict our outgoing size.   For now, we don't do any
+ * sanity checking on this, and we don't deal with what happens to
+ * programs that are already running when the size changes.
+ * NOTE: changing the MTU will usually cause the IBC to go back to
+ * link initialize (IPATH_IBSTATE_INIT) state...
+ */
+int ipath_layer_set_mtu(struct ipath_devdata *dd, u16 arg)
+{
+	u32 piosize;
+	int changed = 0;
+	int ret;
+
+	/*
+	 * mtu is IB data payload max.  It's the largest power of 2 less
+	 * than piosize (or even larger, since it only really controls the
+	 * largest we can receive; we can send the max of the mtu and
+	 * piosize).  We check that it's one of the valid IB sizes.
+	 */
+	if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
+	    arg != 4096) {
+		ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
+		ret = -EINVAL;
+		goto bail;
+	}
+	if (dd->ipath_ibmtu == arg) {
+		ret = 0;	/* same as current */
+		goto bail;
+	}
+
+	piosize = dd->ipath_ibmaxlen;
+	dd->ipath_ibmtu = arg;
+
+	if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
+		/* Only if it's not the initial value (or reset to it) */
+		if (piosize != dd->ipath_init_ibmaxlen) {
+			dd->ipath_ibmaxlen = piosize;
+			changed = 1;
+		}
+	} else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) {
+		piosize = arg + IPATH_PIO_MAXIBHDR;
+		ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x "
+			   "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize,
+			   arg);
+		dd->ipath_ibmaxlen = piosize;
+		changed = 1;
+	}
+
+	if (changed) {
+		/*
+		 * set the IBC maxpktlength to the size of our pio
+		 * buffers in words
+		 */
+		u64 ibc = dd->ipath_ibcctrl;
+		ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
+			 INFINIPATH_IBCC_MAXPKTLEN_SHIFT);
+
+		piosize = piosize - 2 * sizeof(u32);	/* ignore pbc */
+		dd->ipath_ibmaxlen = piosize;
+		piosize /= sizeof(u32);	/* in words */
+		/*
+		 * for ICRC, which we only send in diag test pkt mode, and
+		 * we don't need to worry about that for mtu
+		 */
+		piosize += 1;
+
+		ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
+		dd->ipath_ibcctrl = ibc;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+				 dd->ipath_ibcctrl);
+		dd->ipath_f_tidtemplate(dd);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_mtu);
+
+int ipath_set_sps_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
+{
+	ipath_stats.sps_lid[dd->ipath_unit] = arg;
+	dd->ipath_lid = arg;
+	dd->ipath_lmc = lmc;
+
+	mutex_lock(&ipath_layer_mutex);
+
+	if (dd->ipath_layer.l_arg && layer_intr)
+		layer_intr(dd->ipath_layer.l_arg, IPATH_LAYER_INT_LID);
+
+	mutex_unlock(&ipath_layer_mutex);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_set_sps_lid);
+
+int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid)
+{
+	/* XXX - need to inform anyone who cares this just happened. */
+	dd->ipath_guid = guid;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_guid);
+
+__be64 ipath_layer_get_guid(struct ipath_devdata *dd)
+{
+	return dd->ipath_guid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_guid);
+
+u32 ipath_layer_get_nguid(struct ipath_devdata *dd)
+{
+	return dd->ipath_nguid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_nguid);
+
+int ipath_layer_query_device(struct ipath_devdata *dd, u32 * vendor,
+			     u32 * boardrev, u32 * majrev, u32 * minrev)
+{
+	*vendor = dd->ipath_vendorid;
+	*boardrev = dd->ipath_boardrev;
+	*majrev = dd->ipath_majrev;
+	*minrev = dd->ipath_minrev;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_query_device);
+
+u32 ipath_layer_get_flags(struct ipath_devdata *dd)
+{
+	return dd->ipath_flags;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_flags);
+
+struct device *ipath_layer_get_device(struct ipath_devdata *dd)
+{
+	return &dd->pcidev->dev;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_device);
+
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd)
+{
+	return dd->ipath_deviceid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid);
+
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd)
+{
+	return dd->ipath_lastibcstat;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lastibcstat);
+
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd)
+{
+	return dd->ipath_ibmtu;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_ibmtu);
+
+void ipath_layer_add(struct ipath_devdata *dd)
+{
+	mutex_lock(&ipath_layer_mutex);
+
+	if (layer_add_one)
+		dd->ipath_layer.l_arg =
+			layer_add_one(dd->ipath_unit, dd);
+
+	if (verbs_add_one)
+		dd->verbs_layer.l_arg =
+			verbs_add_one(dd->ipath_unit, dd);
+
+	mutex_unlock(&ipath_layer_mutex);
+}
+
+void ipath_layer_del(struct ipath_devdata *dd)
+{
+	mutex_lock(&ipath_layer_mutex);
+
+	if (dd->ipath_layer.l_arg && layer_remove_one) {
+		layer_remove_one(dd->ipath_layer.l_arg);
+		dd->ipath_layer.l_arg = NULL;
+	}
+
+	if (dd->verbs_layer.l_arg && verbs_remove_one) {
+		verbs_remove_one(dd->verbs_layer.l_arg);
+		dd->verbs_layer.l_arg = NULL;
+	}
+
+	mutex_unlock(&ipath_layer_mutex);
+}
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+			 void (*l_remove)(void *),
+			 int (*l_intr)(void *, u32),
+			 int (*l_rcv)(void *, void *, struct sk_buff *),
+			 u16 l_rcv_opcode,
+			 int (*l_rcv_lid)(void *, void *))
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+
+	mutex_lock(&ipath_layer_mutex);
+
+	layer_add_one = l_add;
+	layer_remove_one = l_remove;
+	layer_intr = l_intr;
+	layer_rcv = l_rcv;
+	layer_rcv_lid = l_rcv_lid;
+	ipath_layer_rcv_opcode = l_rcv_opcode;
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		if (!(dd->ipath_flags & IPATH_INITTED))
+			continue;
+
+		if (dd->ipath_layer.l_arg)
+			continue;
+
+		if (!(*dd->ipath_statusp & IPATH_STATUS_SMA))
+			*dd->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+
+		spin_unlock_irqrestore(&ipath_devs_lock, flags);
+		dd->ipath_layer.l_arg = l_add(dd->ipath_unit, dd);
+		spin_lock_irqsave(&ipath_devs_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+	mutex_unlock(&ipath_layer_mutex);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_register);
+
+void ipath_layer_unregister(void)
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+
+	mutex_lock(&ipath_layer_mutex);
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		if (dd->ipath_layer.l_arg && layer_remove_one) {
+			spin_unlock_irqrestore(&ipath_devs_lock, flags);
+			layer_remove_one(dd->ipath_layer.l_arg);
+			spin_lock_irqsave(&ipath_devs_lock, flags);
+			dd->ipath_layer.l_arg = NULL;
+		}
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	layer_add_one = NULL;
+	layer_remove_one = NULL;
+	layer_intr = NULL;
+	layer_rcv = NULL;
+	layer_rcv_lid = NULL;
+
+	mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_unregister);
+
+static void __ipath_verbs_timer(unsigned long arg)
+{
+	struct ipath_devdata *dd = (struct ipath_devdata *) arg;
+
+	/*
+	 * If port 0 receive packet interrupts are not available, or
+	 * can be missed, poll the receive queue
+	 */
+	if (dd->ipath_flags & IPATH_POLL_RX_INTR)
+		ipath_kreceive(dd);
+
+	/* Handle verbs layer timeouts. */
+	if (dd->verbs_layer.l_arg && verbs_timer_cb)
+		verbs_timer_cb(dd->verbs_layer.l_arg);
+
+	mod_timer(&dd->verbs_layer.l_timer, jiffies + 1);
+}
+
+/**
+ * ipath_verbs_register - verbs layer registration
+ * @l_piobufavail: callback for when PIO buffers become available
+ * @l_rcv: callback for receiving a packet
+ * @l_timer_cb: timer callback
+ * @ipath_devdata: device data structure is put here
+ */
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+			 void (*l_remove)(void *arg),
+			 int (*l_piobufavail) (void *arg),
+			 void (*l_rcv) (void *arg, void *rhdr,
+					void *data, u32 tlen),
+			 void (*l_timer_cb) (void *arg))
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+
+	mutex_lock(&ipath_layer_mutex);
+
+	verbs_add_one = l_add;
+	verbs_remove_one = l_remove;
+	verbs_piobufavail = l_piobufavail;
+	verbs_rcv = l_rcv;
+	verbs_timer_cb = l_timer_cb;
+
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		if (!(dd->ipath_flags & IPATH_INITTED))
+			continue;
+
+		if (dd->verbs_layer.l_arg)
+			continue;
+
+		spin_unlock_irqrestore(&ipath_devs_lock, flags);
+		dd->verbs_layer.l_arg = l_add(dd->ipath_unit, dd);
+		spin_lock_irqsave(&ipath_devs_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+	mutex_unlock(&ipath_layer_mutex);
+
+	ipath_verbs_registered = 1;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_register);
+
+void ipath_verbs_unregister(void)
+{
+	struct ipath_devdata *dd, *tmp;
+	unsigned long flags;
+
+	mutex_lock(&ipath_layer_mutex);
+	spin_lock_irqsave(&ipath_devs_lock, flags);
+
+	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+		*dd->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+
+		if (dd->verbs_layer.l_arg && verbs_remove_one) {
+			spin_unlock_irqrestore(&ipath_devs_lock, flags);
+			verbs_remove_one(dd->verbs_layer.l_arg);
+			spin_lock_irqsave(&ipath_devs_lock, flags);
+			dd->verbs_layer.l_arg = NULL;
+		}
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, flags);
+
+	verbs_add_one = NULL;
+	verbs_remove_one = NULL;
+	verbs_piobufavail = NULL;
+	verbs_rcv = NULL;
+	verbs_timer_cb = NULL;
+
+	mutex_unlock(&ipath_layer_mutex);
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_unregister);
+
+int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax)
+{
+	int ret;
+	u32 intval = 0;
+
+	mutex_lock(&ipath_layer_mutex);
+
+	if (!dd->ipath_layer.l_arg) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	ret = ipath_setrcvhdrsize(dd, NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE);
+
+	if (ret < 0)
+		goto bail;
+
+	*pktmax = dd->ipath_ibmaxlen;
+
+	if (*dd->ipath_statusp & IPATH_STATUS_IB_READY)
+		intval |= IPATH_LAYER_INT_IF_UP;
+	if (ipath_stats.sps_lid[dd->ipath_unit])
+		intval |= IPATH_LAYER_INT_LID;
+	if (ipath_stats.sps_mlid[dd->ipath_unit])
+		intval |= IPATH_LAYER_INT_BCAST;
+	/*
+	 * do this on open, in case low level is already up and
+	 * just layered driver was reloaded, etc.
+	 */
+	if (intval)
+		layer_intr(dd->ipath_layer.l_arg, intval);
+
+	ret = 0;
+bail:
+	mutex_unlock(&ipath_layer_mutex);
+
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_open);
+
+u16 ipath_layer_get_lid(struct ipath_devdata *dd)
+{
+	return dd->ipath_lid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_lid);
+
+/**
+ * ipath_layer_get_mac - get the MAC address
+ * @dd: the infinipath device
+ * @mac: the MAC is put here
+ *
+ * This is the EUID-64 OUI octets (top 3), then
+ * skip the next 2 (which should both be zero or 0xff).
+ * The returned MAC is in network order
+ * mac points to at least 6 bytes of buffer
+ * We assume that by the time the LID is set, that the GUID is as valid
+ * as it's ever going to be, rather than adding yet another status bit.
+ */
+
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 * mac)
+{
+	u8 *guid;
+
+	guid = (u8 *) &dd->ipath_guid;
+
+	mac[0] = guid[0];
+	mac[1] = guid[1];
+	mac[2] = guid[2];
+	mac[3] = guid[5];
+	mac[4] = guid[6];
+	mac[5] = guid[7];
+	if ((guid[3] || guid[4]) && !(guid[3] == 0xff && guid[4] == 0xff))
+		ipath_dbg("Warning, guid bytes 3 and 4 not 0 or 0xffff: "
+			  "%x %x\n", guid[3], guid[4]);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_mac);
+
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd)
+{
+	return dd->ipath_mlid;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_bcast);
+
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd)
+{
+	return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_cr_errpkey);
+
+static void update_sge(struct ipath_sge_state *ss, u32 length)
+{
+	struct ipath_sge *sge = &ss->sge;
+
+	sge->vaddr += length;
+	sge->length -= length;
+	sge->sge_length -= length;
+	if (sge->sge_length == 0) {
+		if (--ss->num_sge)
+			*sge = *ss->sg_list++;
+	} else if (sge->length == 0 && sge->mr != NULL) {
+		if (++sge->n >= IPATH_SEGSZ) {
+			if (++sge->m >= sge->mr->mapsz)
+				return;
+			sge->n = 0;
+		}
+		sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr;
+		sge->length = sge->mr->map[sge->m]->segs[sge->n].length;
+	}
+}
+
+#ifdef __LITTLE_ENDIAN
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+	return data >> shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+	return data << shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+	data <<= ((sizeof(u32) - n) * BITS_PER_BYTE);
+	data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+	return data;
+}
+#else
+static inline u32 get_upper_bits(u32 data, u32 shift)
+{
+	return data << shift;
+}
+
+static inline u32 set_upper_bits(u32 data, u32 shift)
+{
+	return data >> shift;
+}
+
+static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off)
+{
+	data >>= ((sizeof(u32) - n) * BITS_PER_BYTE);
+	data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE);
+	return data;
+}
+#endif
+
+static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss,
+		    u32 length)
+{
+	u32 extra = 0;
+	u32 data = 0;
+	u32 last;
+
+	while (1) {
+		u32 len = ss->sge.length;
+		u32 off;
+
+		BUG_ON(len == 0);
+		if (len > length)
+			len = length;
+		if (len > ss->sge.sge_length)
+			len = ss->sge.sge_length;
+		/* If the source address is not aligned, try to align it. */
+		off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1);
+		if (off) {
+			u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr &
+					    ~(sizeof(u32) - 1));
+			u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE);
+			u32 y;
+
+			y = sizeof(u32) - off;
+			if (len > y)
+				len = y;
+			if (len + extra >= sizeof(u32)) {
+				data |= set_upper_bits(v, extra *
+						       BITS_PER_BYTE);
+				len = sizeof(u32) - extra;
+				if (len == length) {
+					last = data;
+					break;
+				}
+				__raw_writel(data, piobuf);
+				piobuf++;
+				extra = 0;
+				data = 0;
+			} else {
+				/* Clear unused upper bytes */
+				data |= clear_upper_bytes(v, len, extra);
+				if (len == length) {
+					last = data;
+					break;
+				}
+				extra += len;
+			}
+		} else if (extra) {
+			/* Source address is aligned. */
+			u32 *addr = (u32 *) ss->sge.vaddr;
+			int shift = extra * BITS_PER_BYTE;
+			int ushift = 32 - shift;
+			u32 l = len;
+
+			while (l >= sizeof(u32)) {
+				u32 v = *addr;
+
+				data |= set_upper_bits(v, shift);
+				__raw_writel(data, piobuf);
+				data = get_upper_bits(v, ushift);
+				piobuf++;
+				addr++;
+				l -= sizeof(u32);
+			}
+			/*
+			 * We still have 'extra' number of bytes leftover.
+			 */
+			if (l) {
+				u32 v = *addr;
+
+				if (l + extra >= sizeof(u32)) {
+					data |= set_upper_bits(v, shift);
+					len -= l + extra - sizeof(u32);
+					if (len == length) {
+						last = data;
+						break;
+					}
+					__raw_writel(data, piobuf);
+					piobuf++;
+					extra = 0;
+					data = 0;
+				} else {
+					/* Clear unused upper bytes */
+					data |= clear_upper_bytes(v, l,
+								  extra);
+					if (len == length) {
+						last = data;
+						break;
+					}
+					extra += l;
+				}
+			} else if (len == length) {
+				last = data;
+				break;
+			}
+		} else if (len == length) {
+			u32 w;
+
+			/*
+			 * Need to round up for the last dword in the
+			 * packet.
+			 */
+			w = (len + 3) >> 2;
+			__iowrite32_copy(piobuf, ss->sge.vaddr, w - 1);
+			piobuf += w - 1;
+			last = ((u32 *) ss->sge.vaddr)[w - 1];
+			break;
+		} else {
+			u32 w = len >> 2;
+
+			__iowrite32_copy(piobuf, ss->sge.vaddr, w);
+			piobuf += w;
+
+			extra = len & (sizeof(u32) - 1);
+			if (extra) {
+				u32 v = ((u32 *) ss->sge.vaddr)[w];
+
+				/* Clear unused upper bytes */
+				data = clear_upper_bytes(v, extra, 0);
+			}
+		}
+		update_sge(ss, len);
+		length -= len;
+	}
+	/* must flush early everything before trigger word */
+	ipath_flush_wc();
+	__raw_writel(last, piobuf);
+	/* be sure trigger word is written */
+	ipath_flush_wc();
+	update_sge(ss, length);
+}
+
+/**
+ * ipath_verbs_send - send a packet from the verbs layer
+ * @dd: the infinipath device
+ * @hdrwords: the number of works in the header
+ * @hdr: the packet header
+ * @len: the length of the packet in bytes
+ * @ss: the SGE to send
+ *
+ * This is like ipath_sma_send_pkt() in that we need to be able to send
+ * packets after the chip is initialized (MADs) but also like
+ * ipath_layer_send_hdr() since its used by the verbs layer.
+ */
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+		     u32 *hdr, u32 len, struct ipath_sge_state *ss)
+{
+	u32 __iomem *piobuf;
+	u32 plen;
+	int ret;
+
+	/* +1 is for the qword padding of pbc */
+	plen = hdrwords + ((len + 3) >> 2) + 1;
+	if (unlikely((plen << 2) > dd->ipath_ibmaxlen)) {
+		ipath_dbg("packet len 0x%x too long, failing\n", plen);
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	/* Get a PIO buffer to use. */
+	piobuf = ipath_getpiobuf(dd, NULL);
+	if (unlikely(piobuf == NULL)) {
+		ret = -EBUSY;
+		goto bail;
+	}
+
+	/*
+	 * Write len to control qword, no flags.
+	 * We have to flush after the PBC for correctness on some cpus
+	 * or WC buffer can be written out of order.
+	 */
+	writeq(plen, piobuf);
+	ipath_flush_wc();
+	piobuf += 2;
+	if (len == 0) {
+		/*
+		 * If there is just the header portion, must flush before
+		 * writing last word of header for correctness, and after
+		 * the last header word (trigger word).
+		 */
+		__iowrite32_copy(piobuf, hdr, hdrwords - 1);
+		ipath_flush_wc();
+		__raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1);
+		ipath_flush_wc();
+		ret = 0;
+		goto bail;
+	}
+
+	__iowrite32_copy(piobuf, hdr, hdrwords);
+	piobuf += hdrwords;
+
+	/* The common case is aligned and contained in one segment. */
+	if (likely(ss->num_sge == 1 && len <= ss->sge.length &&
+		   !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) {
+		u32 w;
+
+		/* Need to round up for the last dword in the packet. */
+		w = (len + 3) >> 2;
+		__iowrite32_copy(piobuf, ss->sge.vaddr, w - 1);
+		/* must flush early everything before trigger word */
+		ipath_flush_wc();
+		__raw_writel(((u32 *) ss->sge.vaddr)[w - 1],
+			     piobuf + w - 1);
+		/* be sure trigger word is written */
+		ipath_flush_wc();
+		update_sge(ss, len);
+		ret = 0;
+		goto bail;
+	}
+	copy_io(piobuf, ss, len);
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_verbs_send);
+
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+				  u64 *rwords, u64 *spkts, u64 *rpkts,
+				  u64 *xmit_wait)
+{
+	int ret;
+
+	if (!(dd->ipath_flags & IPATH_INITTED)) {
+		/* no hardware, freeze, etc. */
+		ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+		ret = -EINVAL;
+		goto bail;
+	}
+	*swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+	*rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+	*spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+	*rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+	*xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_snapshot_counters);
+
+/**
+ * ipath_layer_get_counters - get various chip counters
+ * @dd: the infinipath device
+ * @cntrs: counters are placed here
+ *
+ * Return the counters needed by recv_pma_get_portcounters().
+ */
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+			      struct ipath_layer_counters *cntrs)
+{
+	int ret;
+
+	if (!(dd->ipath_flags & IPATH_INITTED)) {
+		/* no hardware, freeze, etc. */
+		ipath_dbg("unit %u not usable\n", dd->ipath_unit);
+		ret = -EINVAL;
+		goto bail;
+	}
+	cntrs->symbol_error_counter =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt);
+	cntrs->link_error_recovery_counter =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt);
+	cntrs->link_downed_counter =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt);
+	cntrs->port_rcv_errors =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_errrcvflowctrlcnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlinkcnt) +
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt);
+	cntrs->port_rcv_remphys_errors =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt);
+	cntrs->port_xmit_discards =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_unsupvlcnt);
+	cntrs->port_xmit_data =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+	cntrs->port_rcv_data =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+	cntrs->port_xmit_packets =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+	cntrs->port_rcv_packets =
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_counters);
+
+int ipath_layer_want_buffer(struct ipath_devdata *dd)
+{
+	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 dd->ipath_sendctrl);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_want_buffer);
+
+int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr)
+{
+	int ret = 0;
+	u32 __iomem *piobuf;
+	u32 plen, *uhdr;
+	size_t count;
+	__be16 vlsllnh;
+
+	if (!(dd->ipath_flags & IPATH_RCVHDRSZ_SET)) {
+		ipath_dbg("send while not open\n");
+		ret = -EINVAL;
+	} else
+		if ((dd->ipath_flags & (IPATH_LINKUNK | IPATH_LINKDOWN)) ||
+		    dd->ipath_lid == 0) {
+			/*
+			 * lid check is for when sma hasn't yet configured
+			 */
+			ret = -ENETDOWN;
+			ipath_cdbg(VERBOSE, "send while not ready, "
+				   "mylid=%u, flags=0x%x\n",
+				   dd->ipath_lid, dd->ipath_flags);
+		}
+
+	vlsllnh = *((__be16 *) hdr);
+	if (vlsllnh != htons(IPS_LRH_BTH)) {
+		ipath_dbg("Warning: lrh[0] wrong (%x, not %x); "
+			  "not sending\n", be16_to_cpu(vlsllnh),
+			  IPS_LRH_BTH);
+		ret = -EINVAL;
+	}
+	if (ret)
+		goto done;
+
+	/* Get a PIO buffer to use. */
+	piobuf = ipath_getpiobuf(dd, NULL);
+	if (piobuf == NULL) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	plen = (sizeof(*hdr) >> 2); /* actual length */
+	ipath_cdbg(EPKT, "0x%x+1w pio %p\n", plen, piobuf);
+
+	writeq(plen+1, piobuf); /* len (+1 for pad) to pbc, no flags */
+	ipath_flush_wc();
+	piobuf += 2;
+	uhdr = (u32 *)hdr;
+	count = plen-1; /* amount we can copy before trigger word */
+	__iowrite32_copy(piobuf, uhdr, count);
+	ipath_flush_wc();
+	__raw_writel(uhdr[count], piobuf + count);
+	ipath_flush_wc(); /* ensure it's sent, now */
+
+	ipath_stats.sps_ether_spkts++;	/* ether packet sent */
+
+done:
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_send_hdr);
+
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd)
+{
+	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
+
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+			 dd->ipath_sendctrl);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_piointbufavail_int);
+
+int ipath_layer_enable_timer(struct ipath_devdata *dd)
+{
+	/*
+	 * HT-400 has a design flaw where the chip and kernel idea
+	 * of the tail register don't always agree, and therefore we won't
+	 * get an interrupt on the next packet received.
+	 * If the board supports per packet receive interrupts, use it.
+	 * Otherwise, the timer function periodically checks for packets
+	 * to cover this case.
+	 * Either way, the timer is needed for verbs layer related
+	 * processing.
+	 */
+	if (dd->ipath_flags & IPATH_GPIO_INTR) {
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect,
+				 0x2074076542310ULL);
+		/* Enable GPIO bit 2 interrupt */
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask,
+				 (u64) (1 << 2));
+	}
+
+	init_timer(&dd->verbs_layer.l_timer);
+	dd->verbs_layer.l_timer.function = __ipath_verbs_timer;
+	dd->verbs_layer.l_timer.data = (unsigned long)dd;
+	dd->verbs_layer.l_timer.expires = jiffies + 1;
+	add_timer(&dd->verbs_layer.l_timer);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_enable_timer);
+
+int ipath_layer_disable_timer(struct ipath_devdata *dd)
+{
+	/* Disable GPIO bit 2 interrupt */
+	if (dd->ipath_flags & IPATH_GPIO_INTR)
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0);
+
+	del_timer_sync(&dd->verbs_layer.l_timer);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_disable_timer);
+
+/**
+ * ipath_layer_set_verbs_flags - set the verbs layer flags
+ * @dd: the infinipath device
+ * @flags: the flags to set
+ */
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags)
+{
+	struct ipath_devdata *ss;
+	unsigned long lflags;
+
+	spin_lock_irqsave(&ipath_devs_lock, lflags);
+
+	list_for_each_entry(ss, &ipath_dev_list, ipath_list) {
+		if (!(ss->ipath_flags & IPATH_INITTED))
+			continue;
+		if ((flags & IPATH_VERBS_KERNEL_SMA) &&
+		    !(*ss->ipath_statusp & IPATH_STATUS_SMA))
+			*ss->ipath_statusp |= IPATH_STATUS_OIB_SMA;
+		else
+			*ss->ipath_statusp &= ~IPATH_STATUS_OIB_SMA;
+	}
+
+	spin_unlock_irqrestore(&ipath_devs_lock, lflags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_verbs_flags);
+
+/**
+ * ipath_layer_get_npkeys - return the size of the PKEY table for port 0
+ * @dd: the infinipath device
+ */
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd)
+{
+	return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_npkeys);
+
+/**
+ * ipath_layer_get_pkey - return the indexed PKEY from the port 0 PKEY table
+ * @dd: the infinipath device
+ * @index: the PKEY index
+ */
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index)
+{
+	unsigned ret;
+
+	if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys))
+		ret = 0;
+	else
+		ret = dd->ipath_pd[0]->port_pkeys[index];
+
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkey);
+
+/**
+ * ipath_layer_get_pkeys - return the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the pkey table is placed here
+ */
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+	struct ipath_portdata *pd = dd->ipath_pd[0];
+
+	memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys));
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_pkeys);
+
+/**
+ * rm_pkey - decrecment the reference count for the given PKEY
+ * @dd: the infinipath device
+ * @key: the PKEY index
+ *
+ * Return true if this was the last reference and the hardware table entry
+ * needs to be changed.
+ */
+static int rm_pkey(struct ipath_devdata *dd, u16 key)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+		if (dd->ipath_pkeys[i] != key)
+			continue;
+		if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) {
+			dd->ipath_pkeys[i] = 0;
+			ret = 1;
+			goto bail;
+		}
+		break;
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * add_pkey - add the given PKEY to the hardware table
+ * @dd: the infinipath device
+ * @key: the PKEY
+ *
+ * Return an error code if unable to add the entry, zero if no change,
+ * or 1 if the hardware PKEY register needs to be updated.
+ */
+static int add_pkey(struct ipath_devdata *dd, u16 key)
+{
+	int i;
+	u16 lkey = key & 0x7FFF;
+	int any = 0;
+	int ret;
+
+	if (lkey == 0x7FFF) {
+		ret = 0;
+		goto bail;
+	}
+
+	/* Look for an empty slot or a matching PKEY. */
+	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+		if (!dd->ipath_pkeys[i]) {
+			any++;
+			continue;
+		}
+		/* If it matches exactly, try to increment the ref count */
+		if (dd->ipath_pkeys[i] == key) {
+			if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) {
+				ret = 0;
+				goto bail;
+			}
+			/* Lost the race. Look for an empty slot below. */
+			atomic_dec(&dd->ipath_pkeyrefs[i]);
+			any++;
+		}
+		/*
+		 * It makes no sense to have both the limited and unlimited
+		 * PKEY set at the same time since the unlimited one will
+		 * disable the limited one.
+		 */
+		if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
+			ret = -EEXIST;
+			goto bail;
+		}
+	}
+	if (!any) {
+		ret = -EBUSY;
+		goto bail;
+	}
+	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
+		if (!dd->ipath_pkeys[i] &&
+		    atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
+			/* for ipathstats, etc. */
+			ipath_stats.sps_pkeys[i] = lkey;
+			dd->ipath_pkeys[i] = key;
+			ret = 1;
+			goto bail;
+		}
+	}
+	ret = -EBUSY;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_layer_set_pkeys - set the PKEY table for port 0
+ * @dd: the infinipath device
+ * @pkeys: the PKEY table
+ */
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 * pkeys)
+{
+	struct ipath_portdata *pd;
+	int i;
+	int changed = 0;
+
+	pd = dd->ipath_pd[0];
+
+	for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
+		u16 key = pkeys[i];
+		u16 okey = pd->port_pkeys[i];
+
+		if (key == okey)
+			continue;
+		/*
+		 * The value of this PKEY table entry is changing.
+		 * Remove the old entry in the hardware's array of PKEYs.
+		 */
+		if (okey & 0x7FFF)
+			changed |= rm_pkey(dd, okey);
+		if (key & 0x7FFF) {
+			int ret = add_pkey(dd, key);
+
+			if (ret < 0)
+				key = 0;
+			else
+				changed |= ret;
+		}
+		pd->port_pkeys[i] = key;
+	}
+	if (changed) {
+		u64 pkey;
+
+		pkey = (u64) dd->ipath_pkeys[0] |
+			((u64) dd->ipath_pkeys[1] << 16) |
+			((u64) dd->ipath_pkeys[2] << 32) |
+			((u64) dd->ipath_pkeys[3] << 48);
+		ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n",
+			   (unsigned long long) pkey);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
+				 pkey);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_pkeys);
+
+/**
+ * ipath_layer_get_linkdowndefaultstate - get the default linkdown state
+ * @dd: the infinipath device
+ *
+ * Returns zero if the default is POLL, 1 if the default is SLEEP.
+ */
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd)
+{
+	return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE);
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_linkdowndefaultstate);
+
+/**
+ * ipath_layer_set_linkdowndefaultstate - set the default linkdown state
+ * @dd: the infinipath device
+ * @sleep: the new state
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+					 int sleep)
+{
+	if (sleep)
+		dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+	else
+		dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+			 dd->ipath_ibcctrl);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_linkdowndefaultstate);
+
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd)
+{
+	return (dd->ipath_ibcctrl >>
+		INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+		INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_phyerrthreshold);
+
+/**
+ * ipath_layer_set_phyerrthreshold - set the physical error threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n)
+{
+	unsigned v;
+
+	v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
+		INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
+	if (v != n) {
+		dd->ipath_ibcctrl &=
+			~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<
+			  INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT);
+		dd->ipath_ibcctrl |=
+			(u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+				 dd->ipath_ibcctrl);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_phyerrthreshold);
+
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd)
+{
+	return (dd->ipath_ibcctrl >>
+		INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+		INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_get_overrunthreshold);
+
+/**
+ * ipath_layer_set_overrunthreshold - set the overrun threshold
+ * @dd: the infinipath device
+ * @n: the new threshold
+ *
+ * Note that this will only take effect when the link state changes.
+ */
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n)
+{
+	unsigned v;
+
+	v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
+		INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
+	if (v != n) {
+		dd->ipath_ibcctrl &=
+			~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<
+			  INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT);
+		dd->ipath_ibcctrl |=
+			(u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
+				 dd->ipath_ibcctrl);
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ipath_layer_set_overrunthreshold);
+
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+			      size_t namelen)
+{
+	return dd->ipath_f_get_boardname(dd, name, namelen);
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_boardname);
+
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd)
+{
+	return dd->ipath_rcvhdrentsize;
+}
+EXPORT_SYMBOL_GPL(ipath_layer_get_rcvhdrentsize);
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h
new file mode 100644
index 0000000..6fefd15
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_layer.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_LAYER_H
+#define _IPATH_LAYER_H
+
+/*
+ * This header file is for symbols shared between the infinipath driver
+ * and drivers layered upon it (such as ipath).
+ */
+
+struct sk_buff;
+struct ipath_sge_state;
+struct ipath_devdata;
+struct ether_header;
+
+struct ipath_layer_counters {
+	u64 symbol_error_counter;
+	u64 link_error_recovery_counter;
+	u64 link_downed_counter;
+	u64 port_rcv_errors;
+	u64 port_rcv_remphys_errors;
+	u64 port_xmit_discards;
+	u64 port_xmit_data;
+	u64 port_rcv_data;
+	u64 port_xmit_packets;
+	u64 port_rcv_packets;
+};
+
+/*
+ * A segment is a linear region of low physical memory.
+ * XXX Maybe we should use phys addr here and kmap()/kunmap().
+ * Used by the verbs layer.
+ */
+struct ipath_seg {
+	void *vaddr;
+	size_t length;
+};
+
+/* The number of ipath_segs that fit in a page. */
+#define IPATH_SEGSZ     (PAGE_SIZE / sizeof (struct ipath_seg))
+
+struct ipath_segarray {
+	struct ipath_seg segs[IPATH_SEGSZ];
+};
+
+struct ipath_mregion {
+	u64 user_base;		/* User's address for this region */
+	u64 iova;		/* IB start address of this region */
+	size_t length;
+	u32 lkey;
+	u32 offset;		/* offset (bytes) to start of region */
+	int access_flags;
+	u32 max_segs;		/* number of ipath_segs in all the arrays */
+	u32 mapsz;		/* size of the map array */
+	struct ipath_segarray *map[0];	/* the segments */
+};
+
+/*
+ * These keep track of the copy progress within a memory region.
+ * Used by the verbs layer.
+ */
+struct ipath_sge {
+	struct ipath_mregion *mr;
+	void *vaddr;		/* current pointer into the segment */
+	u32 sge_length;		/* length of the SGE */
+	u32 length;		/* remaining length of the segment */
+	u16 m;			/* current index: mr->map[m] */
+	u16 n;			/* current index: mr->map[m]->segs[n] */
+};
+
+struct ipath_sge_state {
+	struct ipath_sge *sg_list;	/* next SGE to be used if any */
+	struct ipath_sge sge;	/* progress state for the current SGE */
+	u8 num_sge;
+};
+
+int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
+			 void (*l_remove)(void *),
+			 int (*l_intr)(void *, u32),
+			 int (*l_rcv)(void *, void *,
+				      struct sk_buff *),
+			 u16 rcv_opcode,
+			 int (*l_rcv_lid)(void *, void *));
+int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *),
+			 void (*l_remove)(void *arg),
+			 int (*l_piobufavail)(void *arg),
+			 void (*l_rcv)(void *arg, void *rhdr,
+				       void *data, u32 tlen),
+			 void (*l_timer_cb)(void *arg));
+void ipath_layer_unregister(void);
+void ipath_verbs_unregister(void);
+int ipath_layer_open(struct ipath_devdata *, u32 * pktmax);
+u16 ipath_layer_get_lid(struct ipath_devdata *dd);
+int ipath_layer_get_mac(struct ipath_devdata *dd, u8 *);
+u16 ipath_layer_get_bcast(struct ipath_devdata *dd);
+u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd);
+int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state);
+int ipath_layer_set_mtu(struct ipath_devdata *, u16);
+int ipath_set_sps_lid(struct ipath_devdata *, u32, u8);
+int ipath_layer_send_hdr(struct ipath_devdata *dd,
+			 struct ether_header *hdr);
+int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords,
+		     u32 * hdr, u32 len, struct ipath_sge_state *ss);
+int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd);
+int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name,
+			      size_t namelen);
+int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords,
+				  u64 *rwords, u64 *spkts, u64 *rpkts,
+				  u64 *xmit_wait);
+int ipath_layer_get_counters(struct ipath_devdata *dd,
+			     struct ipath_layer_counters *cntrs);
+int ipath_layer_want_buffer(struct ipath_devdata *dd);
+int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid);
+__be64 ipath_layer_get_guid(struct ipath_devdata *);
+u32 ipath_layer_get_nguid(struct ipath_devdata *);
+int ipath_layer_query_device(struct ipath_devdata *, u32 * vendor,
+			     u32 * boardrev, u32 * majrev, u32 * minrev);
+u32 ipath_layer_get_flags(struct ipath_devdata *dd);
+struct device *ipath_layer_get_device(struct ipath_devdata *dd);
+u16 ipath_layer_get_deviceid(struct ipath_devdata *dd);
+u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd);
+u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd);
+int ipath_layer_enable_timer(struct ipath_devdata *dd);
+int ipath_layer_disable_timer(struct ipath_devdata *dd);
+int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags);
+unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd);
+unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index);
+int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 *pkeys);
+int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd);
+int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd,
+					 int sleep);
+int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n);
+int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd);
+int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n);
+u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd);
+
+/* ipath_ether interrupt values */
+#define IPATH_LAYER_INT_IF_UP 0x2
+#define IPATH_LAYER_INT_IF_DOWN 0x4
+#define IPATH_LAYER_INT_LID 0x8
+#define IPATH_LAYER_INT_SEND_CONTINUE 0x10
+#define IPATH_LAYER_INT_BCAST 0x40
+
+/* _verbs_layer.l_flags */
+#define IPATH_VERBS_KERNEL_SMA 0x1
+
+extern unsigned ipath_debug; /* debugging bit mask */
+
+#endif				/* _IPATH_LAYER_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
new file mode 100644
index 0000000..f7f8391
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define IB_SMP_UNSUP_VERSION	__constant_htons(0x0004)
+#define IB_SMP_UNSUP_METHOD	__constant_htons(0x0008)
+#define IB_SMP_UNSUP_METH_ATTR	__constant_htons(0x000C)
+#define IB_SMP_INVALID_FIELD	__constant_htons(0x001C)
+
+static int reply(struct ib_smp *smp)
+{
+	/*
+	 * The verbs framework will handle the directed/LID route
+	 * packet changes.
+	 */
+	smp->method = IB_MGMT_METHOD_GET_RESP;
+	if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+		smp->status |= IB_SMP_DIRECTION;
+	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+}
+
+static int recv_subn_get_nodedescription(struct ib_smp *smp,
+					 struct ib_device *ibdev)
+{
+	if (smp->attr_mod)
+		smp->status |= IB_SMP_INVALID_FIELD;
+
+	strncpy(smp->data, ibdev->node_desc, sizeof(smp->data));
+
+	return reply(smp);
+}
+
+struct nodeinfo {
+	u8 base_version;
+	u8 class_version;
+	u8 node_type;
+	u8 num_ports;
+	__be64 sys_guid;
+	__be64 node_guid;
+	__be64 port_guid;
+	__be16 partition_cap;
+	__be16 device_id;
+	__be32 revision;
+	u8 local_port_num;
+	u8 vendor_id[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_nodeinfo(struct ib_smp *smp,
+				  struct ib_device *ibdev, u8 port)
+{
+	struct nodeinfo *nip = (struct nodeinfo *)&smp->data;
+	struct ipath_devdata *dd = to_idev(ibdev)->dd;
+	u32 vendor, boardid, majrev, minrev;
+
+	if (smp->attr_mod)
+		smp->status |= IB_SMP_INVALID_FIELD;
+
+	nip->base_version = 1;
+	nip->class_version = 1;
+	nip->node_type = 1;	/* channel adapter */
+	/*
+	 * XXX The num_ports value will need a layer function to get
+	 * the value if we ever have more than one IB port on a chip.
+	 * We will also need to get the GUID for the port.
+	 */
+	nip->num_ports = ibdev->phys_port_cnt;
+	/* This is already in network order */
+	nip->sys_guid = to_idev(ibdev)->sys_image_guid;
+	nip->node_guid = ipath_layer_get_guid(dd);
+	nip->port_guid = nip->sys_guid;
+	nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd));
+	nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd));
+	ipath_layer_query_device(dd, &vendor, &boardid, &majrev, &minrev);
+	nip->revision = cpu_to_be32((majrev << 16) | minrev);
+	nip->local_port_num = port;
+	nip->vendor_id[0] = 0;
+	nip->vendor_id[1] = vendor >> 8;
+	nip->vendor_id[2] = vendor;
+
+	return reply(smp);
+}
+
+static int recv_subn_get_guidinfo(struct ib_smp *smp,
+				  struct ib_device *ibdev)
+{
+	u32 startgx = 8 * be32_to_cpu(smp->attr_mod);
+	__be64 *p = (__be64 *) smp->data;
+
+	/* 32 blocks of 8 64-bit GUIDs per block */
+
+	memset(smp->data, 0, sizeof(smp->data));
+
+	/*
+	 * We only support one GUID for now.  If this changes, the
+	 * portinfo.guid_cap field needs to be updated too.
+	 */
+	if (startgx == 0)
+		/* The first is a copy of the read-only HW GUID. */
+		*p = ipath_layer_get_guid(to_idev(ibdev)->dd);
+	else
+		smp->status |= IB_SMP_INVALID_FIELD;
+
+	return reply(smp);
+}
+
+struct port_info {
+	__be64 mkey;
+	__be64 gid_prefix;
+	__be16 lid;
+	__be16 sm_lid;
+	__be32 cap_mask;
+	__be16 diag_code;
+	__be16 mkey_lease_period;
+	u8 local_port_num;
+	u8 link_width_enabled;
+	u8 link_width_supported;
+	u8 link_width_active;
+	u8 linkspeed_portstate;			/* 4 bits, 4 bits */
+	u8 portphysstate_linkdown;		/* 4 bits, 4 bits */
+	u8 mkeyprot_resv_lmc;			/* 2 bits, 3, 3 */
+	u8 linkspeedactive_enabled;		/* 4 bits, 4 bits */
+	u8 neighbormtu_mastersmsl;		/* 4 bits, 4 bits */
+	u8 vlcap_inittype;			/* 4 bits, 4 bits */
+	u8 vl_high_limit;
+	u8 vl_arb_high_cap;
+	u8 vl_arb_low_cap;
+	u8 inittypereply_mtucap;		/* 4 bits, 4 bits */
+	u8 vlstallcnt_hoqlife;			/* 3 bits, 5 bits */
+	u8 operationalvl_pei_peo_fpi_fpo;	/* 4 bits, 1, 1, 1, 1 */
+	__be16 mkey_violations;
+	__be16 pkey_violations;
+	__be16 qkey_violations;
+	u8 guid_cap;
+	u8 clientrereg_resv_subnetto;		/* 1 bit, 2 bits, 5 */
+	u8 resv_resptimevalue;			/* 3 bits, 5 bits */
+	u8 localphyerrors_overrunerrors;	/* 4 bits, 4 bits */
+	__be16 max_credit_hint;
+	u8 resv;
+	u8 link_roundtrip_latency[3];
+} __attribute__ ((packed));
+
+static int recv_subn_get_portinfo(struct ib_smp *smp,
+				  struct ib_device *ibdev, u8 port)
+{
+	struct ipath_ibdev *dev;
+	struct port_info *pip = (struct port_info *)smp->data;
+	u16 lid;
+	u8 ibcstat;
+	u8 mtu;
+	int ret;
+
+	if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) {
+		smp->status |= IB_SMP_INVALID_FIELD;
+		ret = reply(smp);
+		goto bail;
+	}
+
+	dev = to_idev(ibdev);
+
+	/* Clear all fields.  Only set the non-zero fields. */
+	memset(smp->data, 0, sizeof(smp->data));
+
+	/* Only return the mkey if the protection field allows it. */
+	if (smp->method == IB_MGMT_METHOD_SET || dev->mkey == smp->mkey ||
+	    (dev->mkeyprot_resv_lmc >> 6) == 0)
+		pip->mkey = dev->mkey;
+	pip->gid_prefix = dev->gid_prefix;
+	lid = ipath_layer_get_lid(dev->dd);
+	pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
+	pip->sm_lid = cpu_to_be16(dev->sm_lid);
+	pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
+	/* pip->diag_code; */
+	pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
+	pip->local_port_num = port;
+	pip->link_width_enabled = dev->link_width_enabled;
+	pip->link_width_supported = 3;	/* 1x or 4x */
+	pip->link_width_active = 2;	/* 4x */
+	pip->linkspeed_portstate = 0x10;	/* 2.5Gbps */
+	ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+	pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1;
+	pip->portphysstate_linkdown =
+		(ipath_cvt_physportstate[ibcstat & 0xf] << 4) |
+		(ipath_layer_get_linkdowndefaultstate(dev->dd) ? 1 : 2);
+	pip->mkeyprot_resv_lmc = dev->mkeyprot_resv_lmc;
+	pip->linkspeedactive_enabled = 0x11;	/* 2.5Gbps, 2.5Gbps */
+	switch (ipath_layer_get_ibmtu(dev->dd)) {
+	case 4096:
+		mtu = IB_MTU_4096;
+		break;
+	case 2048:
+		mtu = IB_MTU_2048;
+		break;
+	case 1024:
+		mtu = IB_MTU_1024;
+		break;
+	case 512:
+		mtu = IB_MTU_512;
+		break;
+	case 256:
+		mtu = IB_MTU_256;
+		break;
+	default:		/* oops, something is wrong */
+		mtu = IB_MTU_2048;
+		break;
+	}
+	pip->neighbormtu_mastersmsl = (mtu << 4) | dev->sm_sl;
+	pip->vlcap_inittype = 0x10;	/* VLCap = VL0, InitType = 0 */
+	pip->vl_high_limit = dev->vl_high_limit;
+	/* pip->vl_arb_high_cap; // only one VL */
+	/* pip->vl_arb_low_cap; // only one VL */
+	/* InitTypeReply = 0 */
+	pip->inittypereply_mtucap = IB_MTU_4096;
+	// HCAs ignore VLStallCount and HOQLife
+	/* pip->vlstallcnt_hoqlife; */
+	pip->operationalvl_pei_peo_fpi_fpo = 0x10;	/* OVLs = 1 */
+	pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
+	/* P_KeyViolations are counted by hardware. */
+	pip->pkey_violations =
+		cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) -
+			     dev->n_pkey_violations) & 0xFFFF);
+	pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
+	/* Only the hardware GUID is supported for now */
+	pip->guid_cap = 1;
+	pip->clientrereg_resv_subnetto = dev->subnet_timeout;
+	/* 32.768 usec. response time (guessing) */
+	pip->resv_resptimevalue = 3;
+	pip->localphyerrors_overrunerrors =
+		(ipath_layer_get_phyerrthreshold(dev->dd) << 4) |
+		ipath_layer_get_overrunthreshold(dev->dd);
+	/* pip->max_credit_hint; */
+	/* pip->link_roundtrip_latency[3]; */
+
+	ret = reply(smp);
+
+bail:
+	return ret;
+}
+
+static int recv_subn_get_pkeytable(struct ib_smp *smp,
+				   struct ib_device *ibdev)
+{
+	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+	u16 *p = (u16 *) smp->data;
+	__be16 *q = (__be16 *) smp->data;
+
+	/* 64 blocks of 32 16-bit P_Key entries */
+
+	memset(smp->data, 0, sizeof(smp->data));
+	if (startpx == 0) {
+		struct ipath_ibdev *dev = to_idev(ibdev);
+		unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+		ipath_layer_get_pkeys(dev->dd, p);
+
+		for (i = 0; i < n; i++)
+			q[i] = cpu_to_be16(p[i]);
+	} else
+		smp->status |= IB_SMP_INVALID_FIELD;
+
+	return reply(smp);
+}
+
+static int recv_subn_set_guidinfo(struct ib_smp *smp,
+				  struct ib_device *ibdev)
+{
+	/* The only GUID we support is the first read-only entry. */
+	return recv_subn_get_guidinfo(smp, ibdev);
+}
+
+/**
+ * recv_subn_set_portinfo - set port information
+ * @smp: the incoming SM packet
+ * @ibdev: the infiniband device
+ * @port: the port on the device
+ *
+ * Set Portinfo (see ch. 14.2.5.6).
+ */
+static int recv_subn_set_portinfo(struct ib_smp *smp,
+				  struct ib_device *ibdev, u8 port)
+{
+	struct port_info *pip = (struct port_info *)smp->data;
+	struct ib_event event;
+	struct ipath_ibdev *dev;
+	u32 flags;
+	char clientrereg = 0;
+	u16 lid, smlid;
+	u8 lwe;
+	u8 lse;
+	u8 state;
+	u16 lstate;
+	u32 mtu;
+	int ret;
+
+	if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt)
+		goto err;
+
+	dev = to_idev(ibdev);
+	event.device = ibdev;
+	event.element.port_num = port;
+
+	dev->mkey = pip->mkey;
+	dev->gid_prefix = pip->gid_prefix;
+	dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period);
+
+	lid = be16_to_cpu(pip->lid);
+	if (lid != ipath_layer_get_lid(dev->dd)) {
+		/* Must be a valid unicast LID address. */
+		if (lid == 0 || lid >= IPS_MULTICAST_LID_BASE)
+			goto err;
+		ipath_set_sps_lid(dev->dd, lid, pip->mkeyprot_resv_lmc & 7);
+		event.event = IB_EVENT_LID_CHANGE;
+		ib_dispatch_event(&event);
+	}
+
+	smlid = be16_to_cpu(pip->sm_lid);
+	if (smlid != dev->sm_lid) {
+		/* Must be a valid unicast LID address. */
+		if (smlid == 0 || smlid >= IPS_MULTICAST_LID_BASE)
+			goto err;
+		dev->sm_lid = smlid;
+		event.event = IB_EVENT_SM_CHANGE;
+		ib_dispatch_event(&event);
+	}
+
+	/* Only 4x supported but allow 1x or 4x to be set (see 14.2.6.6). */
+	lwe = pip->link_width_enabled;
+	if ((lwe >= 4 && lwe <= 8) || (lwe >= 0xC && lwe <= 0xFE))
+		goto err;
+	if (lwe == 0xFF)
+		dev->link_width_enabled = 3;	/* 1x or 4x */
+	else if (lwe)
+		dev->link_width_enabled = lwe;
+
+	/* Only 2.5 Gbs supported. */
+	lse = pip->linkspeedactive_enabled & 0xF;
+	if (lse >= 2 && lse <= 0xE)
+		goto err;
+
+	/* Set link down default state. */
+	switch (pip->portphysstate_linkdown & 0xF) {
+	case 0: /* NOP */
+		break;
+	case 1: /* SLEEP */
+		if (ipath_layer_set_linkdowndefaultstate(dev->dd, 1))
+			goto err;
+		break;
+	case 2: /* POLL */
+		if (ipath_layer_set_linkdowndefaultstate(dev->dd, 0))
+			goto err;
+		break;
+	default:
+		goto err;
+	}
+
+	dev->mkeyprot_resv_lmc = pip->mkeyprot_resv_lmc;
+	dev->vl_high_limit = pip->vl_high_limit;
+
+	switch ((pip->neighbormtu_mastersmsl >> 4) & 0xF) {
+	case IB_MTU_256:
+		mtu = 256;
+		break;
+	case IB_MTU_512:
+		mtu = 512;
+		break;
+	case IB_MTU_1024:
+		mtu = 1024;
+		break;
+	case IB_MTU_2048:
+		mtu = 2048;
+		break;
+	case IB_MTU_4096:
+		mtu = 4096;
+		break;
+	default:
+		/* XXX We have already partially updated our state! */
+		goto err;
+	}
+	ipath_layer_set_mtu(dev->dd, mtu);
+
+	dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF;
+
+	/* We only support VL0 */
+	if (((pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF) > 1)
+		goto err;
+
+	if (pip->mkey_violations == 0)
+		dev->mkey_violations = 0;
+
+	/*
+	 * Hardware counter can't be reset so snapshot and subtract
+	 * later.
+	 */
+	if (pip->pkey_violations == 0)
+		dev->n_pkey_violations =
+			ipath_layer_get_cr_errpkey(dev->dd);
+
+	if (pip->qkey_violations == 0)
+		dev->qkey_violations = 0;
+
+	if (ipath_layer_set_phyerrthreshold(
+		    dev->dd,
+		    (pip->localphyerrors_overrunerrors >> 4) & 0xF))
+		goto err;
+
+	if (ipath_layer_set_overrunthreshold(
+		    dev->dd,
+		    (pip->localphyerrors_overrunerrors & 0xF)))
+		goto err;
+
+	dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
+
+	if (pip->clientrereg_resv_subnetto & 0x80) {
+		clientrereg = 1;
+		event.event = IB_EVENT_LID_CHANGE;
+		ib_dispatch_event(&event);
+	}
+
+	/*
+	 * Do the port state change now that the other link parameters
+	 * have been set.
+	 * Changing the port physical state only makes sense if the link
+	 * is down or is being set to down.
+	 */
+	state = pip->linkspeed_portstate & 0xF;
+	flags = ipath_layer_get_flags(dev->dd);
+	lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
+	if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
+		goto err;
+
+	/*
+	 * Only state changes of DOWN, ARM, and ACTIVE are valid
+	 * and must be in the correct state to take effect (see 7.2.6).
+	 */
+	switch (state) {
+	case IB_PORT_NOP:
+		if (lstate == 0)
+			break;
+		/* FALLTHROUGH */
+	case IB_PORT_DOWN:
+		if (lstate == 0)
+			if (ipath_layer_get_linkdowndefaultstate(dev->dd))
+				lstate = IPATH_IB_LINKDOWN_SLEEP;
+			else
+				lstate = IPATH_IB_LINKDOWN;
+		else if (lstate == 1)
+			lstate = IPATH_IB_LINKDOWN_SLEEP;
+		else if (lstate == 2)
+			lstate = IPATH_IB_LINKDOWN;
+		else if (lstate == 3)
+			lstate = IPATH_IB_LINKDOWN_DISABLE;
+		else
+			goto err;
+		ipath_layer_set_linkstate(dev->dd, lstate);
+		if (flags & IPATH_LINKACTIVE) {
+			event.event = IB_EVENT_PORT_ERR;
+			ib_dispatch_event(&event);
+		}
+		break;
+	case IB_PORT_ARMED:
+		if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE)))
+			break;
+		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKARM);
+		if (flags & IPATH_LINKACTIVE) {
+			event.event = IB_EVENT_PORT_ERR;
+			ib_dispatch_event(&event);
+		}
+		break;
+	case IB_PORT_ACTIVE:
+		if (!(flags & IPATH_LINKARMED))
+			break;
+		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE);
+		event.event = IB_EVENT_PORT_ACTIVE;
+		ib_dispatch_event(&event);
+		break;
+	default:
+		/* XXX We have already partially updated our state! */
+		goto err;
+	}
+
+	ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+	if (clientrereg)
+		pip->clientrereg_resv_subnetto |= 0x80;
+
+	goto done;
+
+err:
+	smp->status |= IB_SMP_INVALID_FIELD;
+	ret = recv_subn_get_portinfo(smp, ibdev, port);
+
+done:
+	return ret;
+}
+
+static int recv_subn_set_pkeytable(struct ib_smp *smp,
+				   struct ib_device *ibdev)
+{
+	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
+	__be16 *p = (__be16 *) smp->data;
+	u16 *q = (u16 *) smp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	unsigned i, n = ipath_layer_get_npkeys(dev->dd);
+
+	for (i = 0; i < n; i++)
+		q[i] = be16_to_cpu(p[i]);
+
+	if (startpx != 0 ||
+	    ipath_layer_set_pkeys(dev->dd, q) != 0)
+		smp->status |= IB_SMP_INVALID_FIELD;
+
+	return recv_subn_get_pkeytable(smp, ibdev);
+}
+
+#define IB_PMA_CLASS_PORT_INFO		__constant_htons(0x0001)
+#define IB_PMA_PORT_SAMPLES_CONTROL	__constant_htons(0x0010)
+#define IB_PMA_PORT_SAMPLES_RESULT	__constant_htons(0x0011)
+#define IB_PMA_PORT_COUNTERS		__constant_htons(0x0012)
+#define IB_PMA_PORT_COUNTERS_EXT	__constant_htons(0x001D)
+#define IB_PMA_PORT_SAMPLES_RESULT_EXT	__constant_htons(0x001E)
+
+struct ib_perf {
+	u8 base_version;
+	u8 mgmt_class;
+	u8 class_version;
+	u8 method;
+	__be16 status;
+	__be16 unused;
+	__be64 tid;
+	__be16 attr_id;
+	__be16 resv;
+	__be32 attr_mod;
+	u8 reserved[40];
+	u8 data[192];
+} __attribute__ ((packed));
+
+struct ib_pma_classportinfo {
+	u8 base_version;
+	u8 class_version;
+	__be16 cap_mask;
+	u8 reserved[3];
+	u8 resp_time_value;	/* only lower 5 bits */
+	union ib_gid redirect_gid;
+	__be32 redirect_tc_sl_fl;	/* 8, 4, 20 bits respectively */
+	__be16 redirect_lid;
+	__be16 redirect_pkey;
+	__be32 redirect_qp;	/* only lower 24 bits */
+	__be32 redirect_qkey;
+	union ib_gid trap_gid;
+	__be32 trap_tc_sl_fl;	/* 8, 4, 20 bits respectively */
+	__be16 trap_lid;
+	__be16 trap_pkey;
+	__be32 trap_hl_qp;	/* 8, 24 bits respectively */
+	__be32 trap_qkey;
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplescontrol {
+	u8 opcode;
+	u8 port_select;
+	u8 tick;
+	u8 counter_width;	/* only lower 3 bits */
+	__be32 counter_mask0_9;	/* 2, 10 * 3, bits */
+	__be16 counter_mask10_14;	/* 1, 5 * 3, bits */
+	u8 sample_mechanisms;
+	u8 sample_status;	/* only lower 2 bits */
+	__be64 option_mask;
+	__be64 vendor_mask;
+	__be32 sample_start;
+	__be32 sample_interval;
+	__be16 tag;
+	__be16 counter_select[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult {
+	__be16 tag;
+	__be16 sample_status;	/* only lower 2 bits */
+	__be32 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portsamplesresult_ext {
+	__be16 tag;
+	__be16 sample_status;	/* only lower 2 bits */
+	__be32 extended_width;	/* only upper 2 bits */
+	__be64 counter[15];
+} __attribute__ ((packed));
+
+struct ib_pma_portcounters {
+	u8 reserved;
+	u8 port_select;
+	__be16 counter_select;
+	__be16 symbol_error_counter;
+	u8 link_error_recovery_counter;
+	u8 link_downed_counter;
+	__be16 port_rcv_errors;
+	__be16 port_rcv_remphys_errors;
+	__be16 port_rcv_switch_relay_errors;
+	__be16 port_xmit_discards;
+	u8 port_xmit_constraint_errors;
+	u8 port_rcv_constraint_errors;
+	u8 reserved1;
+	u8 lli_ebor_errors;	/* 4, 4, bits */
+	__be16 reserved2;
+	__be16 vl15_dropped;
+	__be32 port_xmit_data;
+	__be32 port_rcv_data;
+	__be32 port_xmit_packets;
+	__be32 port_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SEL_SYMBOL_ERROR			__constant_htons(0x0001)
+#define IB_PMA_SEL_LINK_ERROR_RECOVERY		__constant_htons(0x0002)
+#define IB_PMA_SEL_LINK_DOWNED			__constant_htons(0x0004)
+#define IB_PMA_SEL_PORT_RCV_ERRORS		__constant_htons(0x0008)
+#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS	__constant_htons(0x0010)
+#define IB_PMA_SEL_PORT_XMIT_DISCARDS		__constant_htons(0x0040)
+#define IB_PMA_SEL_PORT_XMIT_DATA		__constant_htons(0x1000)
+#define IB_PMA_SEL_PORT_RCV_DATA		__constant_htons(0x2000)
+#define IB_PMA_SEL_PORT_XMIT_PACKETS		__constant_htons(0x4000)
+#define IB_PMA_SEL_PORT_RCV_PACKETS		__constant_htons(0x8000)
+
+struct ib_pma_portcounters_ext {
+	u8 reserved;
+	u8 port_select;
+	__be16 counter_select;
+	__be32 reserved1;
+	__be64 port_xmit_data;
+	__be64 port_rcv_data;
+	__be64 port_xmit_packets;
+	__be64 port_rcv_packets;
+	__be64 port_unicast_xmit_packets;
+	__be64 port_unicast_rcv_packets;
+	__be64 port_multicast_xmit_packets;
+	__be64 port_multicast_rcv_packets;
+} __attribute__ ((packed));
+
+#define IB_PMA_SELX_PORT_XMIT_DATA		__constant_htons(0x0001)
+#define IB_PMA_SELX_PORT_RCV_DATA		__constant_htons(0x0002)
+#define IB_PMA_SELX_PORT_XMIT_PACKETS		__constant_htons(0x0004)
+#define IB_PMA_SELX_PORT_RCV_PACKETS		__constant_htons(0x0008)
+#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS	__constant_htons(0x0010)
+#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS	__constant_htons(0x0020)
+#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS	__constant_htons(0x0040)
+#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS	__constant_htons(0x0080)
+
+static int recv_pma_get_classportinfo(struct ib_perf *pmp)
+{
+	struct ib_pma_classportinfo *p =
+		(struct ib_pma_classportinfo *)pmp->data;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+
+	if (pmp->attr_mod != 0)
+		pmp->status |= IB_SMP_INVALID_FIELD;
+
+	/* Indicate AllPortSelect is valid (only one port anyway) */
+	p->cap_mask = __constant_cpu_to_be16(1 << 8);
+	p->base_version = 1;
+	p->class_version = 1;
+	/*
+	 * Expected response time is 4.096 usec. * 2^18 == 1.073741824
+	 * sec.
+	 */
+	p->resp_time_value = 18;
+
+	return reply((struct ib_smp *) pmp);
+}
+
+/*
+ * The PortSamplesControl.CounterMasks field is an array of 3 bit fields
+ * which specify the N'th counter's capabilities. See ch. 16.1.3.2.
+ * We support 5 counters which only count the mandatory quantities.
+ */
+#define COUNTER_MASK(q, n) (q << ((9 - n) * 3))
+#define COUNTER_MASK0_9 \
+	__constant_cpu_to_be32(COUNTER_MASK(1, 0) | \
+			       COUNTER_MASK(1, 1) | \
+			       COUNTER_MASK(1, 2) | \
+			       COUNTER_MASK(1, 3) | \
+			       COUNTER_MASK(1, 4))
+
+static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+					   struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portsamplescontrol *p =
+		(struct ib_pma_portsamplescontrol *)pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	unsigned long flags;
+	u8 port_select = p->port_select;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+
+	p->port_select = port_select;
+	if (pmp->attr_mod != 0 ||
+	    (port_select != port && port_select != 0xFF))
+		pmp->status |= IB_SMP_INVALID_FIELD;
+	/*
+	 * Ticks are 10x the link transfer period which for 2.5Gbs is 4
+	 * nsec.  0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec.  Sample
+	 * intervals are counted in ticks.  Since we use Linux timers, that
+	 * count in jiffies, we can't sample for less than 1000 ticks if HZ
+	 * == 1000 (4000 ticks if HZ is 250).
+	 */
+	/* XXX This is WRONG. */
+	p->tick = 250;		/* 1 usec. */
+	p->counter_width = 4;	/* 32 bit counters */
+	p->counter_mask0_9 = COUNTER_MASK0_9;
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	p->sample_status = dev->pma_sample_status;
+	p->sample_start = cpu_to_be32(dev->pma_sample_start);
+	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
+	p->tag = cpu_to_be16(dev->pma_tag);
+	p->counter_select[0] = dev->pma_counter_select[0];
+	p->counter_select[1] = dev->pma_counter_select[1];
+	p->counter_select[2] = dev->pma_counter_select[2];
+	p->counter_select[3] = dev->pma_counter_select[3];
+	p->counter_select[4] = dev->pma_counter_select[4];
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+	return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+					   struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portsamplescontrol *p =
+		(struct ib_pma_portsamplescontrol *)pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	unsigned long flags;
+	u32 start;
+	int ret;
+
+	if (pmp->attr_mod != 0 ||
+	    (p->port_select != port && p->port_select != 0xFF)) {
+		pmp->status |= IB_SMP_INVALID_FIELD;
+		ret = reply((struct ib_smp *) pmp);
+		goto bail;
+	}
+
+	start = be32_to_cpu(p->sample_start);
+	if (start != 0) {
+		spin_lock_irqsave(&dev->pending_lock, flags);
+		if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
+			dev->pma_sample_status =
+				IB_PMA_SAMPLE_STATUS_STARTED;
+			dev->pma_sample_start = start;
+			dev->pma_sample_interval =
+				be32_to_cpu(p->sample_interval);
+			dev->pma_tag = be16_to_cpu(p->tag);
+			if (p->counter_select[0])
+				dev->pma_counter_select[0] =
+					p->counter_select[0];
+			if (p->counter_select[1])
+				dev->pma_counter_select[1] =
+					p->counter_select[1];
+			if (p->counter_select[2])
+				dev->pma_counter_select[2] =
+					p->counter_select[2];
+			if (p->counter_select[3])
+				dev->pma_counter_select[3] =
+					p->counter_select[3];
+			if (p->counter_select[4])
+				dev->pma_counter_select[4] =
+					p->counter_select[4];
+		}
+		spin_unlock_irqrestore(&dev->pending_lock, flags);
+	}
+	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
+
+bail:
+	return ret;
+}
+
+static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
+{
+	u64 ret;
+
+	switch (sel) {
+	case IB_PMA_PORT_XMIT_DATA:
+		ret = dev->ipath_sword;
+		break;
+	case IB_PMA_PORT_RCV_DATA:
+		ret = dev->ipath_rword;
+		break;
+	case IB_PMA_PORT_XMIT_PKTS:
+		ret = dev->ipath_spkts;
+		break;
+	case IB_PMA_PORT_RCV_PKTS:
+		ret = dev->ipath_rpkts;
+		break;
+	case IB_PMA_PORT_XMIT_WAIT:
+		ret = dev->ipath_xmit_wait;
+		break;
+	default:
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+					  struct ib_device *ibdev)
+{
+	struct ib_pma_portsamplesresult *p =
+		(struct ib_pma_portsamplesresult *)pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int i;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+	p->tag = cpu_to_be16(dev->pma_tag);
+	p->sample_status = cpu_to_be16(dev->pma_sample_status);
+	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+		p->counter[i] = cpu_to_be32(
+			get_counter(dev, dev->pma_counter_select[i]));
+
+	return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+					      struct ib_device *ibdev)
+{
+	struct ib_pma_portsamplesresult_ext *p =
+		(struct ib_pma_portsamplesresult_ext *)pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int i;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+	p->tag = cpu_to_be16(dev->pma_tag);
+	p->sample_status = cpu_to_be16(dev->pma_sample_status);
+	/* 64 bits */
+	p->extended_width = __constant_cpu_to_be32(0x80000000);
+	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+		p->counter[i] = cpu_to_be64(
+			get_counter(dev, dev->pma_counter_select[i]));
+
+	return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters(struct ib_perf *pmp,
+				     struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+		pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_layer_counters cntrs;
+	u8 port_select = p->port_select;
+
+	ipath_layer_get_counters(dev->dd, &cntrs);
+
+	/* Adjust counters for any resets done. */
+	cntrs.symbol_error_counter -= dev->n_symbol_error_counter;
+	cntrs.link_error_recovery_counter -=
+		dev->n_link_error_recovery_counter;
+	cntrs.link_downed_counter -= dev->n_link_downed_counter;
+	cntrs.port_rcv_errors += dev->rcv_errors;
+	cntrs.port_rcv_errors -= dev->n_port_rcv_errors;
+	cntrs.port_rcv_remphys_errors -= dev->n_port_rcv_remphys_errors;
+	cntrs.port_xmit_discards -= dev->n_port_xmit_discards;
+	cntrs.port_xmit_data -= dev->n_port_xmit_data;
+	cntrs.port_rcv_data -= dev->n_port_rcv_data;
+	cntrs.port_xmit_packets -= dev->n_port_xmit_packets;
+	cntrs.port_rcv_packets -= dev->n_port_rcv_packets;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+
+	p->port_select = port_select;
+	if (pmp->attr_mod != 0 ||
+	    (port_select != port && port_select != 0xFF))
+		pmp->status |= IB_SMP_INVALID_FIELD;
+
+	if (cntrs.symbol_error_counter > 0xFFFFUL)
+		p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF);
+	else
+		p->symbol_error_counter =
+			cpu_to_be16((u16)cntrs.symbol_error_counter);
+	if (cntrs.link_error_recovery_counter > 0xFFUL)
+		p->link_error_recovery_counter = 0xFF;
+	else
+		p->link_error_recovery_counter =
+			(u8)cntrs.link_error_recovery_counter;
+	if (cntrs.link_downed_counter > 0xFFUL)
+		p->link_downed_counter = 0xFF;
+	else
+		p->link_downed_counter = (u8)cntrs.link_downed_counter;
+	if (cntrs.port_rcv_errors > 0xFFFFUL)
+		p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF);
+	else
+		p->port_rcv_errors =
+			cpu_to_be16((u16) cntrs.port_rcv_errors);
+	if (cntrs.port_rcv_remphys_errors > 0xFFFFUL)
+		p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF);
+	else
+		p->port_rcv_remphys_errors =
+			cpu_to_be16((u16)cntrs.port_rcv_remphys_errors);
+	if (cntrs.port_xmit_discards > 0xFFFFUL)
+		p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF);
+	else
+		p->port_xmit_discards =
+			cpu_to_be16((u16)cntrs.port_xmit_discards);
+	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
+		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
+	else
+		p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data);
+	if (cntrs.port_rcv_data > 0xFFFFFFFFUL)
+		p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF);
+	else
+		p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data);
+	if (cntrs.port_xmit_packets > 0xFFFFFFFFUL)
+		p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+	else
+		p->port_xmit_packets =
+			cpu_to_be32((u32)cntrs.port_xmit_packets);
+	if (cntrs.port_rcv_packets > 0xFFFFFFFFUL)
+		p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF);
+	else
+		p->port_rcv_packets =
+			cpu_to_be32((u32) cntrs.port_rcv_packets);
+
+	return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
+					 struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portcounters_ext *p =
+		(struct ib_pma_portcounters_ext *)pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	u64 swords, rwords, spkts, rpkts, xwait;
+	u8 port_select = p->port_select;
+
+	ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+				      &rpkts, &xwait);
+
+	/* Adjust counters for any resets done. */
+	swords -= dev->n_port_xmit_data;
+	rwords -= dev->n_port_rcv_data;
+	spkts -= dev->n_port_xmit_packets;
+	rpkts -= dev->n_port_rcv_packets;
+
+	memset(pmp->data, 0, sizeof(pmp->data));
+
+	p->port_select = port_select;
+	if (pmp->attr_mod != 0 ||
+	    (port_select != port && port_select != 0xFF))
+		pmp->status |= IB_SMP_INVALID_FIELD;
+
+	p->port_xmit_data = cpu_to_be64(swords);
+	p->port_rcv_data = cpu_to_be64(rwords);
+	p->port_xmit_packets = cpu_to_be64(spkts);
+	p->port_rcv_packets = cpu_to_be64(rpkts);
+	p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit);
+	p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv);
+	p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit);
+	p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv);
+
+	return reply((struct ib_smp *) pmp);
+}
+
+static int recv_pma_set_portcounters(struct ib_perf *pmp,
+				     struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+		pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	struct ipath_layer_counters cntrs;
+
+	/*
+	 * Since the HW doesn't support clearing counters, we save the
+	 * current count and subtract it from future responses.
+	 */
+	ipath_layer_get_counters(dev->dd, &cntrs);
+
+	if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR)
+		dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+
+	if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY)
+		dev->n_link_error_recovery_counter =
+			cntrs.link_error_recovery_counter;
+
+	if (p->counter_select & IB_PMA_SEL_LINK_DOWNED)
+		dev->n_link_downed_counter = cntrs.link_downed_counter;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS)
+		dev->n_port_rcv_errors =
+			cntrs.port_rcv_errors + dev->rcv_errors;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS)
+		dev->n_port_rcv_remphys_errors =
+			cntrs.port_rcv_remphys_errors;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS)
+		dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
+		dev->n_port_xmit_data = cntrs.port_xmit_data;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA)
+		dev->n_port_rcv_data = cntrs.port_rcv_data;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS)
+		dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+
+	if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS)
+		dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+
+	return recv_pma_get_portcounters(pmp, ibdev, port);
+}
+
+static int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
+					 struct ib_device *ibdev, u8 port)
+{
+	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
+		pmp->data;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	u64 swords, rwords, spkts, rpkts, xwait;
+
+	ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
+				      &rpkts, &xwait);
+
+	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA)
+		dev->n_port_xmit_data = swords;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA)
+		dev->n_port_rcv_data = rwords;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS)
+		dev->n_port_xmit_packets = spkts;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)
+		dev->n_port_rcv_packets = rpkts;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS)
+		dev->n_unicast_xmit = 0;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS)
+		dev->n_unicast_rcv = 0;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS)
+		dev->n_multicast_xmit = 0;
+
+	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS)
+		dev->n_multicast_rcv = 0;
+
+	return recv_pma_get_portcounters_ext(pmp, ibdev, port);
+}
+
+static int process_subn(struct ib_device *ibdev, int mad_flags,
+			u8 port_num, struct ib_mad *in_mad,
+			struct ib_mad *out_mad)
+{
+	struct ib_smp *smp = (struct ib_smp *)out_mad;
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int ret;
+
+	*out_mad = *in_mad;
+	if (smp->class_version != 1) {
+		smp->status |= IB_SMP_UNSUP_VERSION;
+		ret = reply(smp);
+		goto bail;
+	}
+
+	/* Is the mkey in the process of expiring? */
+	if (dev->mkey_lease_timeout && jiffies >= dev->mkey_lease_timeout) {
+		/* Clear timeout and mkey protection field. */
+		dev->mkey_lease_timeout = 0;
+		dev->mkeyprot_resv_lmc &= 0x3F;
+	}
+
+	/*
+	 * M_Key checking depends on
+	 * Portinfo:M_Key_protect_bits
+	 */
+	if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 &&
+	    dev->mkey != smp->mkey &&
+	    (smp->method == IB_MGMT_METHOD_SET ||
+	     (smp->method == IB_MGMT_METHOD_GET &&
+	      (dev->mkeyprot_resv_lmc >> 7) != 0))) {
+		if (dev->mkey_violations != 0xFFFF)
+			++dev->mkey_violations;
+		if (dev->mkey_lease_timeout ||
+		    dev->mkey_lease_period == 0) {
+			ret = IB_MAD_RESULT_SUCCESS |
+				IB_MAD_RESULT_CONSUMED;
+			goto bail;
+		}
+		dev->mkey_lease_timeout = jiffies +
+			dev->mkey_lease_period * HZ;
+		/* Future: Generate a trap notice. */
+		ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
+		goto bail;
+	} else if (dev->mkey_lease_timeout)
+		dev->mkey_lease_timeout = 0;
+
+	switch (smp->method) {
+	case IB_MGMT_METHOD_GET:
+		switch (smp->attr_id) {
+		case IB_SMP_ATTR_NODE_DESC:
+			ret = recv_subn_get_nodedescription(smp, ibdev);
+			goto bail;
+		case IB_SMP_ATTR_NODE_INFO:
+			ret = recv_subn_get_nodeinfo(smp, ibdev, port_num);
+			goto bail;
+		case IB_SMP_ATTR_GUID_INFO:
+			ret = recv_subn_get_guidinfo(smp, ibdev);
+			goto bail;
+		case IB_SMP_ATTR_PORT_INFO:
+			ret = recv_subn_get_portinfo(smp, ibdev, port_num);
+			goto bail;
+		case IB_SMP_ATTR_PKEY_TABLE:
+			ret = recv_subn_get_pkeytable(smp, ibdev);
+			goto bail;
+		case IB_SMP_ATTR_SM_INFO:
+			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+				ret = IB_MAD_RESULT_SUCCESS |
+					IB_MAD_RESULT_CONSUMED;
+				goto bail;
+			}
+			if (dev->port_cap_flags & IB_PORT_SM) {
+				ret = IB_MAD_RESULT_SUCCESS;
+				goto bail;
+			}
+			/* FALLTHROUGH */
+		default:
+			smp->status |= IB_SMP_UNSUP_METH_ATTR;
+			ret = reply(smp);
+			goto bail;
+		}
+
+	case IB_MGMT_METHOD_SET:
+		switch (smp->attr_id) {
+		case IB_SMP_ATTR_GUID_INFO:
+			ret = recv_subn_set_guidinfo(smp, ibdev);
+			goto bail;
+		case IB_SMP_ATTR_PORT_INFO:
+			ret = recv_subn_set_portinfo(smp, ibdev, port_num);
+			goto bail;
+		case IB_SMP_ATTR_PKEY_TABLE:
+			ret = recv_subn_set_pkeytable(smp, ibdev);
+			goto bail;
+		case IB_SMP_ATTR_SM_INFO:
+			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
+				ret = IB_MAD_RESULT_SUCCESS |
+					IB_MAD_RESULT_CONSUMED;
+				goto bail;
+			}
+			if (dev->port_cap_flags & IB_PORT_SM) {
+				ret = IB_MAD_RESULT_SUCCESS;
+				goto bail;
+			}
+			/* FALLTHROUGH */
+		default:
+			smp->status |= IB_SMP_UNSUP_METH_ATTR;
+			ret = reply(smp);
+			goto bail;
+		}
+
+	case IB_MGMT_METHOD_GET_RESP:
+		/*
+		 * The ib_mad module will call us to process responses
+		 * before checking for other consumers.
+		 * Just tell the caller to process it normally.
+		 */
+		ret = IB_MAD_RESULT_FAILURE;
+		goto bail;
+	default:
+		smp->status |= IB_SMP_UNSUP_METHOD;
+		ret = reply(smp);
+	}
+
+bail:
+	return ret;
+}
+
+static int process_perf(struct ib_device *ibdev, u8 port_num,
+			struct ib_mad *in_mad,
+			struct ib_mad *out_mad)
+{
+	struct ib_perf *pmp = (struct ib_perf *)out_mad;
+	int ret;
+
+	*out_mad = *in_mad;
+	if (pmp->class_version != 1) {
+		pmp->status |= IB_SMP_UNSUP_VERSION;
+		ret = reply((struct ib_smp *) pmp);
+		goto bail;
+	}
+
+	switch (pmp->method) {
+	case IB_MGMT_METHOD_GET:
+		switch (pmp->attr_id) {
+		case IB_PMA_CLASS_PORT_INFO:
+			ret = recv_pma_get_classportinfo(pmp);
+			goto bail;
+		case IB_PMA_PORT_SAMPLES_CONTROL:
+			ret = recv_pma_get_portsamplescontrol(pmp, ibdev,
+							      port_num);
+			goto bail;
+		case IB_PMA_PORT_SAMPLES_RESULT:
+			ret = recv_pma_get_portsamplesresult(pmp, ibdev);
+			goto bail;
+		case IB_PMA_PORT_SAMPLES_RESULT_EXT:
+			ret = recv_pma_get_portsamplesresult_ext(pmp,
+								 ibdev);
+			goto bail;
+		case IB_PMA_PORT_COUNTERS:
+			ret = recv_pma_get_portcounters(pmp, ibdev,
+							port_num);
+			goto bail;
+		case IB_PMA_PORT_COUNTERS_EXT:
+			ret = recv_pma_get_portcounters_ext(pmp, ibdev,
+							    port_num);
+			goto bail;
+		default:
+			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			ret = reply((struct ib_smp *) pmp);
+			goto bail;
+		}
+
+	case IB_MGMT_METHOD_SET:
+		switch (pmp->attr_id) {
+		case IB_PMA_PORT_SAMPLES_CONTROL:
+			ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
+							      port_num);
+			goto bail;
+		case IB_PMA_PORT_COUNTERS:
+			ret = recv_pma_set_portcounters(pmp, ibdev,
+							port_num);
+			goto bail;
+		case IB_PMA_PORT_COUNTERS_EXT:
+			ret = recv_pma_set_portcounters_ext(pmp, ibdev,
+							    port_num);
+			goto bail;
+		default:
+			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
+			ret = reply((struct ib_smp *) pmp);
+			goto bail;
+		}
+
+	case IB_MGMT_METHOD_GET_RESP:
+		/*
+		 * The ib_mad module will call us to process responses
+		 * before checking for other consumers.
+		 * Just tell the caller to process it normally.
+		 */
+		ret = IB_MAD_RESULT_FAILURE;
+		goto bail;
+	default:
+		pmp->status |= IB_SMP_UNSUP_METHOD;
+		ret = reply((struct ib_smp *) pmp);
+	}
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_process_mad - process an incoming MAD packet
+ * @ibdev: the infiniband device this packet came in on
+ * @mad_flags: MAD flags
+ * @port_num: the port number this packet came in on
+ * @in_wc: the work completion entry for this packet
+ * @in_grh: the global route header for this packet
+ * @in_mad: the incoming MAD
+ * @out_mad: any outgoing MAD reply
+ *
+ * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not
+ * interested in processing.
+ *
+ * Note that the verbs framework has already done the MAD sanity checks,
+ * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
+ * MADs.
+ *
+ * This is called by the ib_mad module.
+ */
+int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+		      struct ib_wc *in_wc, struct ib_grh *in_grh,
+		      struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int ret;
+
+	/*
+	 * Snapshot current HW counters to "clear" them.
+	 * This should be done when the driver is loaded except that for
+	 * some reason we get a zillion errors when brining up the link.
+	 */
+	if (dev->rcv_errors == 0) {
+		struct ipath_layer_counters cntrs;
+
+		ipath_layer_get_counters(to_idev(ibdev)->dd, &cntrs);
+		dev->rcv_errors++;
+		dev->n_symbol_error_counter = cntrs.symbol_error_counter;
+		dev->n_link_error_recovery_counter =
+			cntrs.link_error_recovery_counter;
+		dev->n_link_downed_counter = cntrs.link_downed_counter;
+		dev->n_port_rcv_errors = cntrs.port_rcv_errors + 1;
+		dev->n_port_rcv_remphys_errors =
+			cntrs.port_rcv_remphys_errors;
+		dev->n_port_xmit_discards = cntrs.port_xmit_discards;
+		dev->n_port_xmit_data = cntrs.port_xmit_data;
+		dev->n_port_rcv_data = cntrs.port_rcv_data;
+		dev->n_port_xmit_packets = cntrs.port_xmit_packets;
+		dev->n_port_rcv_packets = cntrs.port_rcv_packets;
+	}
+	switch (in_mad->mad_hdr.mgmt_class) {
+	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
+	case IB_MGMT_CLASS_SUBN_LID_ROUTED:
+		ret = process_subn(ibdev, mad_flags, port_num,
+				   in_mad, out_mad);
+		goto bail;
+	case IB_MGMT_CLASS_PERF_MGMT:
+		ret = process_perf(ibdev, port_num, in_mad, out_mad);
+		goto bail;
+	default:
+		ret = IB_MAD_RESULT_SUCCESS;
+	}
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
new file mode 100644
index 0000000..69ffec6
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_pack.h>
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_get_dma_mr - get a DMA memory region
+ * @pd: protection domain for this memory region
+ * @acc: access flags
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc)
+{
+	struct ipath_mr *mr;
+	struct ib_mr *ret;
+
+	mr = kzalloc(sizeof *mr, GFP_KERNEL);
+	if (!mr) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	mr->mr.access_flags = acc;
+	ret = &mr->ibmr;
+
+bail:
+	return ret;
+}
+
+static struct ipath_mr *alloc_mr(int count,
+				 struct ipath_lkey_table *lk_table)
+{
+	struct ipath_mr *mr;
+	int m, i = 0;
+
+	/* Allocate struct plus pointers to first level page tables. */
+	m = (count + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+	mr = kmalloc(sizeof *mr + m * sizeof mr->mr.map[0], GFP_KERNEL);
+	if (!mr)
+		goto done;
+
+	/* Allocate first level page tables. */
+	for (; i < m; i++) {
+		mr->mr.map[i] = kmalloc(sizeof *mr->mr.map[0], GFP_KERNEL);
+		if (!mr->mr.map[i])
+			goto bail;
+	}
+	mr->mr.mapsz = m;
+
+	/*
+	 * ib_reg_phys_mr() will initialize mr->ibmr except for
+	 * lkey and rkey.
+	 */
+	if (!ipath_alloc_lkey(lk_table, &mr->mr))
+		goto bail;
+	mr->ibmr.rkey = mr->ibmr.lkey = mr->mr.lkey;
+
+	goto done;
+
+bail:
+	while (i) {
+		i--;
+		kfree(mr->mr.map[i]);
+	}
+	kfree(mr);
+	mr = NULL;
+
+done:
+	return mr;
+}
+
+/**
+ * ipath_reg_phys_mr - register a physical memory region
+ * @pd: protection domain for this memory region
+ * @buffer_list: pointer to the list of physical buffers to register
+ * @num_phys_buf: the number of physical buffers to register
+ * @iova_start: the starting address passed over IB which maps to this MR
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+				struct ib_phys_buf *buffer_list,
+				int num_phys_buf, int acc, u64 *iova_start)
+{
+	struct ipath_mr *mr;
+	int n, m, i;
+	struct ib_mr *ret;
+
+	mr = alloc_mr(num_phys_buf, &to_idev(pd->device)->lk_table);
+	if (mr == NULL) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	mr->mr.user_base = *iova_start;
+	mr->mr.iova = *iova_start;
+	mr->mr.length = 0;
+	mr->mr.offset = 0;
+	mr->mr.access_flags = acc;
+	mr->mr.max_segs = num_phys_buf;
+
+	m = 0;
+	n = 0;
+	for (i = 0; i < num_phys_buf; i++) {
+		mr->mr.map[m]->segs[n].vaddr =
+			phys_to_virt(buffer_list[i].addr);
+		mr->mr.map[m]->segs[n].length = buffer_list[i].size;
+		mr->mr.length += buffer_list[i].size;
+		n++;
+		if (n == IPATH_SEGSZ) {
+			m++;
+			n = 0;
+		}
+	}
+
+	ret = &mr->ibmr;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_reg_user_mr - register a userspace memory region
+ * @pd: protection domain for this memory region
+ * @region: the user memory region
+ * @mr_access_flags: access flags for this memory region
+ * @udata: unused by the InfiniPath driver
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+				int mr_access_flags, struct ib_udata *udata)
+{
+	struct ipath_mr *mr;
+	struct ib_umem_chunk *chunk;
+	int n, m, i;
+	struct ib_mr *ret;
+
+	n = 0;
+	list_for_each_entry(chunk, &region->chunk_list, list)
+		n += chunk->nents;
+
+	mr = alloc_mr(n, &to_idev(pd->device)->lk_table);
+	if (!mr) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	mr->mr.user_base = region->user_base;
+	mr->mr.iova = region->virt_base;
+	mr->mr.length = region->length;
+	mr->mr.offset = region->offset;
+	mr->mr.access_flags = mr_access_flags;
+	mr->mr.max_segs = n;
+
+	m = 0;
+	n = 0;
+	list_for_each_entry(chunk, &region->chunk_list, list) {
+		for (i = 0; i < chunk->nmap; i++) {
+			mr->mr.map[m]->segs[n].vaddr =
+				page_address(chunk->page_list[i].page);
+			mr->mr.map[m]->segs[n].length = region->page_size;
+			n++;
+			if (n == IPATH_SEGSZ) {
+				m++;
+				n = 0;
+			}
+		}
+	}
+	ret = &mr->ibmr;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_dereg_mr - unregister and free a memory region
+ * @ibmr: the memory region to free
+ *
+ * Returns 0 on success.
+ *
+ * Note that this is called to free MRs created by ipath_get_dma_mr()
+ * or ipath_reg_user_mr().
+ */
+int ipath_dereg_mr(struct ib_mr *ibmr)
+{
+	struct ipath_mr *mr = to_imr(ibmr);
+	int i;
+
+	ipath_free_lkey(&to_idev(ibmr->device)->lk_table, ibmr->lkey);
+	i = mr->mr.mapsz;
+	while (i) {
+		i--;
+		kfree(mr->mr.map[i]);
+	}
+	kfree(mr);
+	return 0;
+}
+
+/**
+ * ipath_alloc_fmr - allocate a fast memory region
+ * @pd: the protection domain for this memory region
+ * @mr_access_flags: access flags for this memory region
+ * @fmr_attr: fast memory region attributes
+ *
+ * Returns the memory region on success, otherwise returns an errno.
+ */
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+			       struct ib_fmr_attr *fmr_attr)
+{
+	struct ipath_fmr *fmr;
+	int m, i = 0;
+	struct ib_fmr *ret;
+
+	/* Allocate struct plus pointers to first level page tables. */
+	m = (fmr_attr->max_pages + IPATH_SEGSZ - 1) / IPATH_SEGSZ;
+	fmr = kmalloc(sizeof *fmr + m * sizeof fmr->mr.map[0], GFP_KERNEL);
+	if (!fmr)
+		goto bail;
+
+	/* Allocate first level page tables. */
+	for (; i < m; i++) {
+		fmr->mr.map[i] = kmalloc(sizeof *fmr->mr.map[0],
+					 GFP_KERNEL);
+		if (!fmr->mr.map[i])
+			goto bail;
+	}
+	fmr->mr.mapsz = m;
+
+	/*
+	 * ib_alloc_fmr() will initialize fmr->ibfmr except for lkey &
+	 * rkey.
+	 */
+	if (!ipath_alloc_lkey(&to_idev(pd->device)->lk_table, &fmr->mr))
+		goto bail;
+	fmr->ibfmr.rkey = fmr->ibfmr.lkey = fmr->mr.lkey;
+	/*
+	 * Resources are allocated but no valid mapping (RKEY can't be
+	 * used).
+	 */
+	fmr->mr.user_base = 0;
+	fmr->mr.iova = 0;
+	fmr->mr.length = 0;
+	fmr->mr.offset = 0;
+	fmr->mr.access_flags = mr_access_flags;
+	fmr->mr.max_segs = fmr_attr->max_pages;
+	fmr->page_shift = fmr_attr->page_shift;
+
+	ret = &fmr->ibfmr;
+	goto done;
+
+bail:
+	while (i)
+		kfree(fmr->mr.map[--i]);
+	kfree(fmr);
+	ret = ERR_PTR(-ENOMEM);
+
+done:
+	return ret;
+}
+
+/**
+ * ipath_map_phys_fmr - set up a fast memory region
+ * @ibmfr: the fast memory region to set up
+ * @page_list: the list of pages to associate with the fast memory region
+ * @list_len: the number of pages to associate with the fast memory region
+ * @iova: the virtual address of the start of the fast memory region
+ *
+ * This may be called from interrupt context.
+ */
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+		       int list_len, u64 iova)
+{
+	struct ipath_fmr *fmr = to_ifmr(ibfmr);
+	struct ipath_lkey_table *rkt;
+	unsigned long flags;
+	int m, n, i;
+	u32 ps;
+	int ret;
+
+	if (list_len > fmr->mr.max_segs) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	rkt = &to_idev(ibfmr->device)->lk_table;
+	spin_lock_irqsave(&rkt->lock, flags);
+	fmr->mr.user_base = iova;
+	fmr->mr.iova = iova;
+	ps = 1 << fmr->page_shift;
+	fmr->mr.length = list_len * ps;
+	m = 0;
+	n = 0;
+	ps = 1 << fmr->page_shift;
+	for (i = 0; i < list_len; i++) {
+		fmr->mr.map[m]->segs[n].vaddr = phys_to_virt(page_list[i]);
+		fmr->mr.map[m]->segs[n].length = ps;
+		if (++n == IPATH_SEGSZ) {
+			m++;
+			n = 0;
+		}
+	}
+	spin_unlock_irqrestore(&rkt->lock, flags);
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_unmap_fmr - unmap fast memory regions
+ * @fmr_list: the list of fast memory regions to unmap
+ *
+ * Returns 0 on success.
+ */
+int ipath_unmap_fmr(struct list_head *fmr_list)
+{
+	struct ipath_fmr *fmr;
+	struct ipath_lkey_table *rkt;
+	unsigned long flags;
+
+	list_for_each_entry(fmr, fmr_list, ibfmr.list) {
+		rkt = &to_idev(fmr->ibfmr.device)->lk_table;
+		spin_lock_irqsave(&rkt->lock, flags);
+		fmr->mr.user_base = 0;
+		fmr->mr.iova = 0;
+		fmr->mr.length = 0;
+		spin_unlock_irqrestore(&rkt->lock, flags);
+	}
+	return 0;
+}
+
+/**
+ * ipath_dealloc_fmr - deallocate a fast memory region
+ * @ibfmr: the fast memory region to deallocate
+ *
+ * Returns 0 on success.
+ */
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr)
+{
+	struct ipath_fmr *fmr = to_ifmr(ibfmr);
+	int i;
+
+	ipath_free_lkey(&to_idev(ibfmr->device)->lk_table, ibfmr->lkey);
+	i = fmr->mr.mapsz;
+	while (i)
+		kfree(fmr->mr.map[--i]);
+	kfree(fmr);
+	return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c
new file mode 100644
index 0000000..e1dc4f7
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_pe800.c
@@ -0,0 +1,1247 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/*
+ * This file contains all of the code that is specific to the
+ * InfiniPath PE-800 chip.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+#include "ipath_kernel.h"
+#include "ipath_registers.h"
+
+/*
+ * This file contains all the chip-specific register information and
+ * access functions for the PathScale PE800, the PCI-Express chip.
+ *
+ * This lists the InfiniPath PE800 registers, in the actual chip layout.
+ * This structure should never be directly accessed.
+ */
+struct _infinipath_do_not_use_kernel_regs {
+	unsigned long long Revision;
+	unsigned long long Control;
+	unsigned long long PageAlign;
+	unsigned long long PortCnt;
+	unsigned long long DebugPortSelect;
+	unsigned long long Reserved0;
+	unsigned long long SendRegBase;
+	unsigned long long UserRegBase;
+	unsigned long long CounterRegBase;
+	unsigned long long Scratch;
+	unsigned long long Reserved1;
+	unsigned long long Reserved2;
+	unsigned long long IntBlocked;
+	unsigned long long IntMask;
+	unsigned long long IntStatus;
+	unsigned long long IntClear;
+	unsigned long long ErrorMask;
+	unsigned long long ErrorStatus;
+	unsigned long long ErrorClear;
+	unsigned long long HwErrMask;
+	unsigned long long HwErrStatus;
+	unsigned long long HwErrClear;
+	unsigned long long HwDiagCtrl;
+	unsigned long long MDIO;
+	unsigned long long IBCStatus;
+	unsigned long long IBCCtrl;
+	unsigned long long ExtStatus;
+	unsigned long long ExtCtrl;
+	unsigned long long GPIOOut;
+	unsigned long long GPIOMask;
+	unsigned long long GPIOStatus;
+	unsigned long long GPIOClear;
+	unsigned long long RcvCtrl;
+	unsigned long long RcvBTHQP;
+	unsigned long long RcvHdrSize;
+	unsigned long long RcvHdrCnt;
+	unsigned long long RcvHdrEntSize;
+	unsigned long long RcvTIDBase;
+	unsigned long long RcvTIDCnt;
+	unsigned long long RcvEgrBase;
+	unsigned long long RcvEgrCnt;
+	unsigned long long RcvBufBase;
+	unsigned long long RcvBufSize;
+	unsigned long long RxIntMemBase;
+	unsigned long long RxIntMemSize;
+	unsigned long long RcvPartitionKey;
+	unsigned long long Reserved3;
+	unsigned long long RcvPktLEDCnt;
+	unsigned long long Reserved4[8];
+	unsigned long long SendCtrl;
+	unsigned long long SendPIOBufBase;
+	unsigned long long SendPIOSize;
+	unsigned long long SendPIOBufCnt;
+	unsigned long long SendPIOAvailAddr;
+	unsigned long long TxIntMemBase;
+	unsigned long long TxIntMemSize;
+	unsigned long long Reserved5;
+	unsigned long long PCIeRBufTestReg0;
+	unsigned long long PCIeRBufTestReg1;
+	unsigned long long Reserved51[6];
+	unsigned long long SendBufferError;
+	unsigned long long SendBufferErrorCONT1;
+	unsigned long long Reserved6SBE[6];
+	unsigned long long RcvHdrAddr0;
+	unsigned long long RcvHdrAddr1;
+	unsigned long long RcvHdrAddr2;
+	unsigned long long RcvHdrAddr3;
+	unsigned long long RcvHdrAddr4;
+	unsigned long long Reserved7RHA[11];
+	unsigned long long RcvHdrTailAddr0;
+	unsigned long long RcvHdrTailAddr1;
+	unsigned long long RcvHdrTailAddr2;
+	unsigned long long RcvHdrTailAddr3;
+	unsigned long long RcvHdrTailAddr4;
+	unsigned long long Reserved8RHTA[11];
+	unsigned long long Reserved9SW[8];
+	unsigned long long SerdesConfig0;
+	unsigned long long SerdesConfig1;
+	unsigned long long SerdesStatus;
+	unsigned long long XGXSConfig;
+	unsigned long long IBPLLCfg;
+	unsigned long long Reserved10SW2[3];
+	unsigned long long PCIEQ0SerdesConfig0;
+	unsigned long long PCIEQ0SerdesConfig1;
+	unsigned long long PCIEQ0SerdesStatus;
+	unsigned long long Reserved11;
+	unsigned long long PCIEQ1SerdesConfig0;
+	unsigned long long PCIEQ1SerdesConfig1;
+	unsigned long long PCIEQ1SerdesStatus;
+	unsigned long long Reserved12;
+};
+
+#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+#define IPATH_CREG_OFFSET(field) (offsetof( \
+    struct infinipath_counters, field) / sizeof(u64))
+
+static const struct ipath_kregs ipath_pe_kregs = {
+	.kr_control = IPATH_KREG_OFFSET(Control),
+	.kr_counterregbase = IPATH_KREG_OFFSET(CounterRegBase),
+	.kr_debugportselect = IPATH_KREG_OFFSET(DebugPortSelect),
+	.kr_errorclear = IPATH_KREG_OFFSET(ErrorClear),
+	.kr_errormask = IPATH_KREG_OFFSET(ErrorMask),
+	.kr_errorstatus = IPATH_KREG_OFFSET(ErrorStatus),
+	.kr_extctrl = IPATH_KREG_OFFSET(ExtCtrl),
+	.kr_extstatus = IPATH_KREG_OFFSET(ExtStatus),
+	.kr_gpio_clear = IPATH_KREG_OFFSET(GPIOClear),
+	.kr_gpio_mask = IPATH_KREG_OFFSET(GPIOMask),
+	.kr_gpio_out = IPATH_KREG_OFFSET(GPIOOut),
+	.kr_gpio_status = IPATH_KREG_OFFSET(GPIOStatus),
+	.kr_hwdiagctrl = IPATH_KREG_OFFSET(HwDiagCtrl),
+	.kr_hwerrclear = IPATH_KREG_OFFSET(HwErrClear),
+	.kr_hwerrmask = IPATH_KREG_OFFSET(HwErrMask),
+	.kr_hwerrstatus = IPATH_KREG_OFFSET(HwErrStatus),
+	.kr_ibcctrl = IPATH_KREG_OFFSET(IBCCtrl),
+	.kr_ibcstatus = IPATH_KREG_OFFSET(IBCStatus),
+	.kr_intblocked = IPATH_KREG_OFFSET(IntBlocked),
+	.kr_intclear = IPATH_KREG_OFFSET(IntClear),
+	.kr_intmask = IPATH_KREG_OFFSET(IntMask),
+	.kr_intstatus = IPATH_KREG_OFFSET(IntStatus),
+	.kr_mdio = IPATH_KREG_OFFSET(MDIO),
+	.kr_pagealign = IPATH_KREG_OFFSET(PageAlign),
+	.kr_partitionkey = IPATH_KREG_OFFSET(RcvPartitionKey),
+	.kr_portcnt = IPATH_KREG_OFFSET(PortCnt),
+	.kr_rcvbthqp = IPATH_KREG_OFFSET(RcvBTHQP),
+	.kr_rcvbufbase = IPATH_KREG_OFFSET(RcvBufBase),
+	.kr_rcvbufsize = IPATH_KREG_OFFSET(RcvBufSize),
+	.kr_rcvctrl = IPATH_KREG_OFFSET(RcvCtrl),
+	.kr_rcvegrbase = IPATH_KREG_OFFSET(RcvEgrBase),
+	.kr_rcvegrcnt = IPATH_KREG_OFFSET(RcvEgrCnt),
+	.kr_rcvhdrcnt = IPATH_KREG_OFFSET(RcvHdrCnt),
+	.kr_rcvhdrentsize = IPATH_KREG_OFFSET(RcvHdrEntSize),
+	.kr_rcvhdrsize = IPATH_KREG_OFFSET(RcvHdrSize),
+	.kr_rcvintmembase = IPATH_KREG_OFFSET(RxIntMemBase),
+	.kr_rcvintmemsize = IPATH_KREG_OFFSET(RxIntMemSize),
+	.kr_rcvtidbase = IPATH_KREG_OFFSET(RcvTIDBase),
+	.kr_rcvtidcnt = IPATH_KREG_OFFSET(RcvTIDCnt),
+	.kr_revision = IPATH_KREG_OFFSET(Revision),
+	.kr_scratch = IPATH_KREG_OFFSET(Scratch),
+	.kr_sendbuffererror = IPATH_KREG_OFFSET(SendBufferError),
+	.kr_sendctrl = IPATH_KREG_OFFSET(SendCtrl),
+	.kr_sendpioavailaddr = IPATH_KREG_OFFSET(SendPIOAvailAddr),
+	.kr_sendpiobufbase = IPATH_KREG_OFFSET(SendPIOBufBase),
+	.kr_sendpiobufcnt = IPATH_KREG_OFFSET(SendPIOBufCnt),
+	.kr_sendpiosize = IPATH_KREG_OFFSET(SendPIOSize),
+	.kr_sendregbase = IPATH_KREG_OFFSET(SendRegBase),
+	.kr_txintmembase = IPATH_KREG_OFFSET(TxIntMemBase),
+	.kr_txintmemsize = IPATH_KREG_OFFSET(TxIntMemSize),
+	.kr_userregbase = IPATH_KREG_OFFSET(UserRegBase),
+	.kr_serdesconfig0 = IPATH_KREG_OFFSET(SerdesConfig0),
+	.kr_serdesconfig1 = IPATH_KREG_OFFSET(SerdesConfig1),
+	.kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus),
+	.kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),
+	.kr_ibpllcfg = IPATH_KREG_OFFSET(IBPLLCfg),
+
+	/*
+	 * These should not be used directly via ipath_read_kreg64(),
+	 * use them with ipath_read_kreg64_port()
+	 */
+	.kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0),
+	.kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
+
+	/* This group is pe-800-specific; and used only in this file */
+	/* The rcvpktled register controls one of the debug port signals, so
+	 * a packet activity LED can be connected to it. */
+	.kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt),
+	.kr_pcierbuftestreg0 = IPATH_KREG_OFFSET(PCIeRBufTestReg0),
+	.kr_pcierbuftestreg1 = IPATH_KREG_OFFSET(PCIeRBufTestReg1),
+	.kr_pcieq0serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig0),
+	.kr_pcieq0serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ0SerdesConfig1),
+	.kr_pcieq0serdesstatus = IPATH_KREG_OFFSET(PCIEQ0SerdesStatus),
+	.kr_pcieq1serdesconfig0 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig0),
+	.kr_pcieq1serdesconfig1 = IPATH_KREG_OFFSET(PCIEQ1SerdesConfig1),
+	.kr_pcieq1serdesstatus = IPATH_KREG_OFFSET(PCIEQ1SerdesStatus)
+};
+
+static const struct ipath_cregs ipath_pe_cregs = {
+	.cr_badformatcnt = IPATH_CREG_OFFSET(RxBadFormatCnt),
+	.cr_erricrccnt = IPATH_CREG_OFFSET(RxICRCErrCnt),
+	.cr_errlinkcnt = IPATH_CREG_OFFSET(RxLinkProblemCnt),
+	.cr_errlpcrccnt = IPATH_CREG_OFFSET(RxLPCRCErrCnt),
+	.cr_errpkey = IPATH_CREG_OFFSET(RxPKeyMismatchCnt),
+	.cr_errrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowCtrlErrCnt),
+	.cr_err_rlencnt = IPATH_CREG_OFFSET(RxLenErrCnt),
+	.cr_errslencnt = IPATH_CREG_OFFSET(TxLenErrCnt),
+	.cr_errtidfull = IPATH_CREG_OFFSET(RxTIDFullErrCnt),
+	.cr_errtidvalid = IPATH_CREG_OFFSET(RxTIDValidErrCnt),
+	.cr_errvcrccnt = IPATH_CREG_OFFSET(RxVCRCErrCnt),
+	.cr_ibstatuschange = IPATH_CREG_OFFSET(IBStatusChangeCnt),
+	.cr_intcnt = IPATH_CREG_OFFSET(LBIntCnt),
+	.cr_invalidrlencnt = IPATH_CREG_OFFSET(RxMaxMinLenErrCnt),
+	.cr_invalidslencnt = IPATH_CREG_OFFSET(TxMaxMinLenErrCnt),
+	.cr_lbflowstallcnt = IPATH_CREG_OFFSET(LBFlowStallCnt),
+	.cr_pktrcvcnt = IPATH_CREG_OFFSET(RxDataPktCnt),
+	.cr_pktrcvflowctrlcnt = IPATH_CREG_OFFSET(RxFlowPktCnt),
+	.cr_pktsendcnt = IPATH_CREG_OFFSET(TxDataPktCnt),
+	.cr_pktsendflowcnt = IPATH_CREG_OFFSET(TxFlowPktCnt),
+	.cr_portovflcnt = IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt),
+	.cr_rcvebpcnt = IPATH_CREG_OFFSET(RxEBPCnt),
+	.cr_rcvovflcnt = IPATH_CREG_OFFSET(RxBufOvflCnt),
+	.cr_senddropped = IPATH_CREG_OFFSET(TxDroppedPktCnt),
+	.cr_sendstallcnt = IPATH_CREG_OFFSET(TxFlowStallCnt),
+	.cr_sendunderruncnt = IPATH_CREG_OFFSET(TxUnderrunCnt),
+	.cr_wordrcvcnt = IPATH_CREG_OFFSET(RxDwordCnt),
+	.cr_wordsendcnt = IPATH_CREG_OFFSET(TxDwordCnt),
+	.cr_unsupvlcnt = IPATH_CREG_OFFSET(TxUnsupVLErrCnt),
+	.cr_rxdroppktcnt = IPATH_CREG_OFFSET(RxDroppedPktCnt),
+	.cr_iblinkerrrecovcnt = IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt),
+	.cr_iblinkdowncnt = IPATH_CREG_OFFSET(IBLinkDownedCnt),
+	.cr_ibsymbolerrcnt = IPATH_CREG_OFFSET(IBSymbolErrCnt)
+};
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_MASK 0x1F
+#define INFINIPATH_I_RCVAVAIL_MASK 0x1F
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_MASK  0x000000000000003fULL
+#define INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT 0
+#define INFINIPATH_HWE_PCIEPOISONEDTLP      0x0000000010000000ULL
+#define INFINIPATH_HWE_PCIECPLTIMEOUT       0x0000000020000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXTLH    0x0000000040000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYXADM    0x0000000080000000ULL
+#define INFINIPATH_HWE_PCIEBUSPARITYRADM    0x0000000100000000ULL
+#define INFINIPATH_HWE_COREPLL_FBSLIP       0x0080000000000000ULL
+#define INFINIPATH_HWE_COREPLL_RFSLIP       0x0100000000000000ULL
+#define INFINIPATH_HWE_PCIE1PLLFAILED       0x0400000000000000ULL
+#define INFINIPATH_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
+#define INFINIPATH_HWE_SERDESPLLFAILED      0x1000000000000000ULL
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_FREQSEL 0x2
+#define INFINIPATH_EXTS_SERDESSEL 0x4
+#define INFINIPATH_EXTS_MEMBIST_ENDTEST     0x0000000000004000
+#define INFINIPATH_EXTS_MEMBIST_FOUND       0x0000000000008000
+
+#define _IPATH_GPIO_SDA_NUM 1
+#define _IPATH_GPIO_SCL_NUM 0
+
+#define IPATH_GPIO_SDA (1ULL << \
+	(_IPATH_GPIO_SDA_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+#define IPATH_GPIO_SCL (1ULL << \
+	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
+
+/**
+ * ipath_pe_handle_hwerrors - display hardware errors.
+ * @dd: the infinipath device
+ * @msg: the output buffer
+ * @msgl: the size of the output buffer
+ *
+ * Use same msg buffer as regular errors to avoid excessive stack
+ * use.  Most hardware errors are catastrophic, but for right now,
+ * we'll print them and continue.  We reuse the same message buffer as
+ * ipath_handle_errors() to avoid excessive stack usage.
+ */
+static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+				     size_t msgl)
+{
+	ipath_err_t hwerrs;
+	u32 bits, ctrl;
+	int isfatal = 0;
+	char bitsmsg[64];
+
+	hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
+	if (!hwerrs) {
+		/*
+		 * better than printing cofusing messages
+		 * This seems to be related to clearing the crc error, or
+		 * the pll error during init.
+		 */
+		ipath_cdbg(VERBOSE, "Called but no hardware errors set\n");
+		return;
+	} else if (hwerrs == ~0ULL) {
+		ipath_dev_err(dd, "Read of hardware error status failed "
+			      "(all bits set); ignoring\n");
+		return;
+	}
+	ipath_stats.sps_hwerrs++;
+
+	/* Always clear the error status register, except MEMBISTFAIL,
+	 * regardless of whether we continue or stop using the chip.
+	 * We want that set so we know it failed, even across driver reload.
+	 * We'll still ignore it in the hwerrmask.  We do this partly for
+	 * diagnostics, but also for support */
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+			 hwerrs&~INFINIPATH_HWE_MEMBISTFAILED);
+
+	hwerrs &= dd->ipath_hwerrmask;
+
+	/*
+	 * make sure we get this much out, unless told to be quiet,
+	 * or it's occurred within the last 5 seconds
+	 */
+	if ((hwerrs & ~dd->ipath_lasthwerror) ||
+	    (ipath_debug & __IPATH_VERBDBG))
+		dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx "
+			 "(cleared)\n", (unsigned long long) hwerrs);
+	dd->ipath_lasthwerror |= hwerrs;
+
+	if (hwerrs & ~infinipath_hwe_bitsextant)
+		ipath_dev_err(dd, "hwerror interrupt with unknown errors "
+			      "%llx set\n", (unsigned long long)
+			      (hwerrs & ~infinipath_hwe_bitsextant));
+
+	ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
+	if (ctrl & INFINIPATH_C_FREEZEMODE) {
+		if (hwerrs) {
+			/*
+			 * if any set that we aren't ignoring only make the
+			 * complaint once, in case it's stuck or recurring,
+			 * and we get here multiple times
+			 */
+			if (dd->ipath_flags & IPATH_INITTED) {
+				ipath_dev_err(dd, "Fatal Error (freeze "
+					      "mode), no longer usable\n");
+				isfatal = 1;
+			}
+			/*
+			 * Mark as having had an error for driver, and also
+			 * for /sys and status word mapped to user programs.
+			 * This marks unit as not usable, until reset
+			 */
+			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+			dd->ipath_flags &= ~IPATH_INITTED;
+		} else {
+			ipath_dbg("Clearing freezemode on ignored hardware "
+				  "error\n");
+			ctrl &= ~INFINIPATH_C_FREEZEMODE;
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+					 ctrl);
+		}
+	}
+
+	*msg = '\0';
+
+	if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) {
+		strlcat(msg, "[Memory BIST test failed, PE-800 unusable]",
+			msgl);
+		/* ignore from now on, so disable until driver reloaded */
+		*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+	if (hwerrs & (INFINIPATH_HWE_RXEMEMPARITYERR_MASK
+		      << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_RXEMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg, "[RXE Parity Errs %x] ",
+			 bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & (INFINIPATH_HWE_TXEMEMPARITYERR_MASK
+		      << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_TXEMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg, "[TXE Parity Errs %x] ",
+			 bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & (INFINIPATH_HWE_PCIEMEMPARITYERR_MASK
+		      << INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT)) {
+		bits = (u32) ((hwerrs >>
+			       INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) &
+			      INFINIPATH_HWE_PCIEMEMPARITYERR_MASK);
+		snprintf(bitsmsg, sizeof bitsmsg,
+			 "[PCIe Mem Parity Errs %x] ", bits);
+		strlcat(msg, bitsmsg, msgl);
+	}
+	if (hwerrs & INFINIPATH_HWE_IBCBUSTOSPCPARITYERR)
+		strlcat(msg, "[IB2IPATH Parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_IBCBUSFRSPCPARITYERR)
+		strlcat(msg, "[IPATH2IB Parity]", msgl);
+
+#define _IPATH_PLL_FAIL (INFINIPATH_HWE_COREPLL_FBSLIP |	\
+			 INFINIPATH_HWE_COREPLL_RFSLIP )
+
+	if (hwerrs & _IPATH_PLL_FAIL) {
+		snprintf(bitsmsg, sizeof bitsmsg,
+			 "[PLL failed (%llx), PE-800 unusable]",
+			 (unsigned long long) hwerrs & _IPATH_PLL_FAIL);
+		strlcat(msg, bitsmsg, msgl);
+		/* ignore from now on, so disable until driver reloaded */
+		dd->ipath_hwerrmask &= ~(hwerrs & _IPATH_PLL_FAIL);
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+
+	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+		/*
+		 * If it occurs, it is left masked since the eternal
+		 * interface is unused
+		 */
+		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrmask,
+				 dd->ipath_hwerrmask);
+	}
+
+	if (hwerrs & INFINIPATH_HWE_PCIEPOISONEDTLP)
+		strlcat(msg, "[PCIe Poisoned TLP]", msgl);
+	if (hwerrs & INFINIPATH_HWE_PCIECPLTIMEOUT)
+		strlcat(msg, "[PCIe completion timeout]", msgl);
+
+	/*
+	 * In practice, it's unlikely wthat we'll see PCIe PLL, or bus
+	 * parity or memory parity error failures, because most likely we
+	 * won't be able to talk to the core of the chip.  Nonetheless, we
+	 * might see them, if they are in parts of the PCIe core that aren't
+	 * essential.
+	 */
+	if (hwerrs & INFINIPATH_HWE_PCIE1PLLFAILED)
+		strlcat(msg, "[PCIePLL1]", msgl);
+	if (hwerrs & INFINIPATH_HWE_PCIE0PLLFAILED)
+		strlcat(msg, "[PCIePLL0]", msgl);
+	if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXTLH)
+		strlcat(msg, "[PCIe XTLH core parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYXADM)
+		strlcat(msg, "[PCIe ADM TX core parity]", msgl);
+	if (hwerrs & INFINIPATH_HWE_PCIEBUSPARITYRADM)
+		strlcat(msg, "[PCIe ADM RX core parity]", msgl);
+
+	if (hwerrs & INFINIPATH_HWE_RXDSYNCMEMPARITYERR)
+		strlcat(msg, "[Rx Dsync]", msgl);
+	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED)
+		strlcat(msg, "[SerDes PLL]", msgl);
+
+	ipath_dev_err(dd, "%s hardware error\n", msg);
+	if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {
+		/*
+		 * for /sys status file ; if no trailing } is copied, we'll
+		 * know it was truncated.
+		 */
+		snprintf(dd->ipath_freezemsg, dd->ipath_freezelen,
+			 "{%s}", msg);
+	}
+}
+
+/**
+ * ipath_pe_boardname - fill in the board name
+ * @dd: the infinipath device
+ * @name: the output buffer
+ * @namelen: the size of the output buffer
+ *
+ * info is based on the board revision register
+ */
+static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+			      size_t namelen)
+{
+	char *n = NULL;
+	u8 boardrev = dd->ipath_boardrev;
+	int ret;
+
+	switch (boardrev) {
+	case 0:
+		n = "InfiniPath_Emulation";
+		break;
+	case 1:
+		n = "InfiniPath_PE-800-Bringup";
+		break;
+	case 2:
+		n = "InfiniPath_PE-880";
+		break;
+	case 3:
+		n = "InfiniPath_PE-850";
+		break;
+	case 4:
+		n = "InfiniPath_PE-860";
+		break;
+	default:
+		ipath_dev_err(dd,
+			      "Don't yet know about board with ID %u\n",
+			      boardrev);
+		snprintf(name, namelen, "Unknown_InfiniPath_PE-8xx_%u",
+			 boardrev);
+		break;
+	}
+	if (n)
+		snprintf(name, namelen, "%s", n);
+
+	if (dd->ipath_majrev != 4 || dd->ipath_minrev != 1) {
+		ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n",
+			      dd->ipath_majrev, dd->ipath_minrev);
+		ret = 1;
+	} else
+		ret = 0;
+
+	return ret;
+}
+
+/**
+ * ipath_pe_init_hwerrors - enable hardware errors
+ * @dd: the infinipath device
+ *
+ * now that we have finished initializing everything that might reasonably
+ * cause a hardware error, and cleared those errors bits as they occur,
+ * we can enable hardware errors in the mask (potentially enabling
+ * freeze mode), and enable hardware errors as errors (along with
+ * everything else) in errormask
+ */
+static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
+{
+	ipath_err_t val;
+	u64 extsval;
+
+	extsval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+
+	if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST))
+		ipath_dev_err(dd, "MemBIST did not complete!\n");
+
+	val = ~0ULL;	/* barring bugs, all hwerrors become interrupts, */
+
+	if (!dd->ipath_boardrev)	// no PLL for Emulator
+		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+
+	/* workaround bug 9460 in internal interface bus parity checking */
+	val &= ~INFINIPATH_HWE_PCIEBUSPARITYRADM;
+
+	dd->ipath_hwerrmask = val;
+}
+
+/**
+ * ipath_pe_bringup_serdes - bring up the serdes
+ * @dd: the infinipath device
+ */
+static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+{
+	u64 val, tmp, config1;
+	int ret = 0, change = 0;
+
+	ipath_dbg("Trying to bringup serdes\n");
+
+	if (ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus) &
+	    INFINIPATH_HWE_SERDESPLLFAILED) {
+		ipath_dbg("At start, serdes PLL failed bit set "
+			  "in hwerrstatus, clearing and continuing\n");
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+				 INFINIPATH_HWE_SERDESPLLFAILED);
+	}
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+	config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1);
+
+	ipath_cdbg(VERBOSE, "SerDes status config0=%llx config1=%llx, "
+		   "xgxsconfig %llx\n", (unsigned long long) val,
+		   (unsigned long long) config1, (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+	/*
+	 * Force reset on, also set rxdetect enable.  Must do before reading
+	 * serdesstatus at least for simulation, or some of the bits in
+	 * serdes status will come back as undefined and cause simulation
+	 * failures
+	 */
+	val |= INFINIPATH_SERDC0_RESET_PLL | INFINIPATH_SERDC0_RXDETECT_EN
+		| INFINIPATH_SERDC0_L1PWR_DN;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+	/* be sure chip saw it */
+	tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	udelay(5);		/* need pll reset set at least for a bit */
+	/*
+	 * after PLL is reset, set the per-lane Resets and TxIdle and
+	 * clear the PLL reset and rxdetect (to get falling edge).
+	 * Leave L1PWR bits set (permanently)
+	 */
+	val &= ~(INFINIPATH_SERDC0_RXDETECT_EN | INFINIPATH_SERDC0_RESET_PLL
+		 | INFINIPATH_SERDC0_L1PWR_DN);
+	val |= INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE;
+	ipath_cdbg(VERBOSE, "Clearing pll reset and setting lane resets "
+		   "and txidle (%llx)\n", (unsigned long long) val);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+	/* be sure chip saw it */
+	tmp = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+	/* need PLL reset clear for at least 11 usec before lane
+	 * resets cleared; give it a few more to be sure */
+	udelay(15);
+	val &= ~(INFINIPATH_SERDC0_RESET_MASK | INFINIPATH_SERDC0_TXIDLE);
+
+	ipath_cdbg(VERBOSE, "Clearing lane resets and txidle "
+		   "(writing %llx)\n", (unsigned long long) val);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+	/* be sure chip saw it */
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+		val &=
+			~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+			  INFINIPATH_XGXS_MDIOADDR_SHIFT);
+		/* MDIO address 3 */
+		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+		change = 1;
+	}
+	if (val & INFINIPATH_XGXS_RESET) {
+		val &= ~INFINIPATH_XGXS_RESET;
+		change = 1;
+	}
+	if (change)
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
+
+	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+	/* clear current and de-emphasis bits */
+	config1 &= ~0x0ffffffff00ULL;
+	/* set current to 20ma */
+	config1 |= 0x00000000000ULL;
+	/* set de-emphasis to -5.68dB */
+	config1 |= 0x0cccc000000ULL;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig1, config1);
+
+	ipath_cdbg(VERBOSE, "done: SerDes status config0=%llx "
+		   "config1=%llx, sstatus=%llx xgxs=%llx\n",
+		   (unsigned long long) val, (unsigned long long) config1,
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesstatus),
+		   (unsigned long long)
+		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
+
+	if (!ipath_waitfor_mdio_cmdready(dd)) {
+		ipath_write_kreg(
+			dd, dd->ipath_kregs->kr_mdio,
+			ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+				       IPATH_MDIO_CTRL_XGXS_REG_8, 0));
+		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+					   IPATH_MDIO_DATAVALID, &val))
+			ipath_dbg("Never got MDIO data for XGXS "
+				  "status read\n");
+		else
+			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+				   "'bank' 31 %x\n", (u32) val);
+	} else
+		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+
+	return ret;
+}
+
+/**
+ * ipath_pe_quiet_serdes - set serdes to txidle
+ * @dd: the infinipath device
+ * Called when driver is being unloaded
+ */
+static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
+{
+	u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
+
+	val |= INFINIPATH_SERDC0_TXIDLE;
+	ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n",
+		  (unsigned long long) val);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val);
+}
+
+/* this is not yet needed on the PE800, so just return 0. */
+static int ipath_pe_intconfig(struct ipath_devdata *dd)
+{
+	return 0;
+}
+
+/**
+ * ipath_setup_pe_setextled - set the state of the two external LEDs
+ * @dd: the infinipath device
+ * @lst: the L state
+ * @ltst: the LT state
+
+ * These LEDs indicate the physical and logical state of IB link.
+ * For this chip (at least with recommended board pinouts), LED1
+ * is Yellow (logical state) and LED2 is Green (physical state),
+ *
+ * Note:  We try to match the Mellanox HCA LED behavior as best
+ * we can.  Green indicates physical link state is OK (something is
+ * plugged in, and we can train).
+ * Amber indicates the link is logically up (ACTIVE).
+ * Mellanox further blinks the amber LED to indicate data packet
+ * activity, but we have no hardware support for that, so it would
+ * require waking up every 10-20 msecs and checking the counters
+ * on the chip, and then turning the LED off if appropriate.  That's
+ * visible overhead, so not something we will do.
+ *
+ */
+static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
+				     u64 ltst)
+{
+	u64 extctl;
+
+	/* the diags use the LED to indicate diag info, so we leave
+	 * the external LED alone when the diags are running */
+	if (ipath_diag_inuse)
+		return;
+
+	extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
+				       INFINIPATH_EXTC_LED2PRIPORT_ON);
+
+	if (ltst & INFINIPATH_IBCS_LT_STATE_LINKUP)
+		extctl |= INFINIPATH_EXTC_LED2PRIPORT_ON;
+	if (lst == INFINIPATH_IBCS_L_STATE_ACTIVE)
+		extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
+	dd->ipath_extctrl = extctl;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+}
+
+/**
+ * ipath_setup_pe_cleanup - clean up any per-chip chip-specific stuff
+ * @dd: the infinipath device
+ *
+ * This is called during driver unload.
+ * We do the pci_disable_msi here, not in generic code, because it
+ * isn't used for the HT-400. If we do end up needing pci_enable_msi
+ * at some point in the future for HT-400, we'll move the call back
+ * into the main init_one code.
+ */
+static void ipath_setup_pe_cleanup(struct ipath_devdata *dd)
+{
+	dd->ipath_msi_lo = 0;	/* just in case unload fails */
+	pci_disable_msi(dd->pcidev);
+}
+
+/**
+ * ipath_setup_pe_config - setup PCIe config related stuff
+ * @dd: the infinipath device
+ * @pdev: the PCI device
+ *
+ * The pci_enable_msi() call will fail on systems with MSI quirks
+ * such as those with AMD8131, even if the device of interest is not
+ * attached to that device, (in the 2.6.13 - 2.6.15 kernels, at least, fixed
+ * late in 2.6.16).
+ * All that can be done is to edit the kernel source to remove the quirk
+ * check until that is fixed.
+ * We do not need to call enable_msi() for our HyperTransport chip (HT-400),
+ * even those it uses MSI, and we want to avoid the quirk warning, so
+ * So we call enable_msi only for the PE-800.  If we do end up needing
+ * pci_enable_msi at some point in the future for HT-400, we'll move the
+ * call back into the main init_one code.
+ * We save the msi lo and hi values, so we can restore them after
+ * chip reset (the kernel PCI infrastructure doesn't yet handle that
+ * correctly).
+ */
+static int ipath_setup_pe_config(struct ipath_devdata *dd,
+				 struct pci_dev *pdev)
+{
+	int pos, ret;
+
+	dd->ipath_msi_lo = 0;	/* used as a flag during reset processing */
+	ret = pci_enable_msi(dd->pcidev);
+	if (ret)
+		ipath_dev_err(dd, "pci_enable_msi failed: %d, "
+			      "interrupts may not work\n", ret);
+	/* continue even if it fails, we may still be OK... */
+
+	if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+		u16 control;
+		pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+				      &dd->ipath_msi_lo);
+		pci_read_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+				      &dd->ipath_msi_hi);
+		pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+				     &control);
+		/* now save the data (vector) info */
+		pci_read_config_word(dd->pcidev,
+				     pos + ((control & PCI_MSI_FLAGS_64BIT)
+					    ? 12 : 8),
+				     &dd->ipath_msi_data);
+		ipath_cdbg(VERBOSE, "Read msi data 0x%x from config offset "
+			   "0x%x, control=0x%x\n", dd->ipath_msi_data,
+			   pos + ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+			   control);
+		/* we save the cachelinesize also, although it doesn't
+		 * really matter */
+		pci_read_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+				     &dd->ipath_pci_cacheline);
+	} else
+		ipath_dev_err(dd, "Can't find MSI capability, "
+			      "can't save MSI settings for reset\n");
+	if ((pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP))) {
+		u16 linkstat;
+		pci_read_config_word(dd->pcidev, pos + PCI_EXP_LNKSTA,
+				     &linkstat);
+		linkstat >>= 4;
+		linkstat &= 0x1f;
+		if (linkstat != 8)
+			ipath_dev_err(dd, "PCIe width %u, "
+				      "performance reduced\n", linkstat);
+	}
+	else
+		ipath_dev_err(dd, "Can't find PCI Express "
+			      "capability!\n");
+	return 0;
+}
+
+static void ipath_init_pe_variables(void)
+{
+	/*
+	 * bits for selecting i2c direction and values,
+	 * used for I2C serial flash
+	 */
+	ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+	ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+	ipath_gpio_sda = IPATH_GPIO_SDA;
+	ipath_gpio_scl = IPATH_GPIO_SCL;
+
+	/* variables for sanity checking interrupt and errors */
+	infinipath_hwe_bitsextant =
+		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+		 INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) |
+		(INFINIPATH_HWE_PCIEMEMPARITYERR_MASK <<
+		 INFINIPATH_HWE_PCIEMEMPARITYERR_SHIFT) |
+		INFINIPATH_HWE_PCIE1PLLFAILED |
+		INFINIPATH_HWE_PCIE0PLLFAILED |
+		INFINIPATH_HWE_PCIEPOISONEDTLP |
+		INFINIPATH_HWE_PCIECPLTIMEOUT |
+		INFINIPATH_HWE_PCIEBUSPARITYXTLH |
+		INFINIPATH_HWE_PCIEBUSPARITYXADM |
+		INFINIPATH_HWE_PCIEBUSPARITYRADM |
+		INFINIPATH_HWE_MEMBISTFAILED |
+		INFINIPATH_HWE_COREPLL_FBSLIP |
+		INFINIPATH_HWE_COREPLL_RFSLIP |
+		INFINIPATH_HWE_SERDESPLLFAILED |
+		INFINIPATH_HWE_IBCBUSTOSPCPARITYERR |
+		INFINIPATH_HWE_IBCBUSFRSPCPARITYERR;
+	infinipath_i_bitsextant =
+		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+		(INFINIPATH_I_RCVAVAIL_MASK <<
+		 INFINIPATH_I_RCVAVAIL_SHIFT) |
+		INFINIPATH_I_ERROR | INFINIPATH_I_SPIOSENT |
+		INFINIPATH_I_SPIOBUFAVAIL | INFINIPATH_I_GPIO;
+	infinipath_e_bitsextant =
+		INFINIPATH_E_RFORMATERR | INFINIPATH_E_RVCRC |
+		INFINIPATH_E_RICRC | INFINIPATH_E_RMINPKTLEN |
+		INFINIPATH_E_RMAXPKTLEN | INFINIPATH_E_RLONGPKTLEN |
+		INFINIPATH_E_RSHORTPKTLEN | INFINIPATH_E_RUNEXPCHAR |
+		INFINIPATH_E_RUNSUPVL | INFINIPATH_E_REBP |
+		INFINIPATH_E_RIBFLOW | INFINIPATH_E_RBADVERSION |
+		INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
+		INFINIPATH_E_RBADTID | INFINIPATH_E_RHDRLEN |
+		INFINIPATH_E_RHDR | INFINIPATH_E_RIBLOSTLINK |
+		INFINIPATH_E_SMINPKTLEN | INFINIPATH_E_SMAXPKTLEN |
+		INFINIPATH_E_SUNDERRUN | INFINIPATH_E_SPKTLEN |
+		INFINIPATH_E_SDROPPEDSMPPKT | INFINIPATH_E_SDROPPEDDATAPKT |
+		INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SUNEXPERRPKTNUM |
+		INFINIPATH_E_SUNSUPVL | INFINIPATH_E_IBSTATUSCHANGED |
+		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET |
+		INFINIPATH_E_HARDWARE;
+
+	infinipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+	infinipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+}
+
+/* setup the MSI stuff again after a reset.  I'd like to just call
+ * pci_enable_msi() and request_irq() again, but when I do that,
+ * the MSI enable bit doesn't get set in the command word, and
+ * we switch to to a different interrupt vector, which is confusing,
+ * so I instead just do it all inline.  Perhaps somehow can tie this
+ * into the PCIe hotplug support at some point
+ * Note, because I'm doing it all here, I don't call pci_disable_msi()
+ * or free_irq() at the start of ipath_setup_pe_reset().
+ */
+static int ipath_reinit_msi(struct ipath_devdata *dd)
+{
+	int pos;
+	u16 control;
+	int ret;
+
+	if (!dd->ipath_msi_lo) {
+		dev_info(&dd->pcidev->dev, "Can't restore MSI config, "
+			 "initial setup failed?\n");
+		ret = 0;
+		goto bail;
+	}
+
+	if (!(pos = pci_find_capability(dd->pcidev, PCI_CAP_ID_MSI))) {
+		ipath_dev_err(dd, "Can't find MSI capability, "
+			      "can't restore MSI settings\n");
+		ret = 0;
+		goto bail;
+	}
+	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+		   dd->ipath_msi_lo, pos + PCI_MSI_ADDRESS_LO);
+	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_LO,
+			       dd->ipath_msi_lo);
+	ipath_cdbg(VERBOSE, "Writing msi_lo 0x%x to config offset 0x%x\n",
+		   dd->ipath_msi_hi, pos + PCI_MSI_ADDRESS_HI);
+	pci_write_config_dword(dd->pcidev, pos + PCI_MSI_ADDRESS_HI,
+			       dd->ipath_msi_hi);
+	pci_read_config_word(dd->pcidev, pos + PCI_MSI_FLAGS, &control);
+	if (!(control & PCI_MSI_FLAGS_ENABLE)) {
+		ipath_cdbg(VERBOSE, "MSI control at off %x was %x, "
+			   "setting MSI enable (%x)\n", pos + PCI_MSI_FLAGS,
+			   control, control | PCI_MSI_FLAGS_ENABLE);
+		control |= PCI_MSI_FLAGS_ENABLE;
+		pci_write_config_word(dd->pcidev, pos + PCI_MSI_FLAGS,
+				      control);
+	}
+	/* now rewrite the data (vector) info */
+	pci_write_config_word(dd->pcidev, pos +
+			      ((control & PCI_MSI_FLAGS_64BIT) ? 12 : 8),
+			      dd->ipath_msi_data);
+	/* we restore the cachelinesize also, although it doesn't really
+	 * matter */
+	pci_write_config_byte(dd->pcidev, PCI_CACHE_LINE_SIZE,
+			      dd->ipath_pci_cacheline);
+	/* and now set the pci master bit again */
+	pci_set_master(dd->pcidev);
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+/* This routine sleeps, so it can only be called from user context, not
+ * from interrupt context.  If we need interrupt context, we can split
+ * it into two routines.
+*/
+static int ipath_setup_pe_reset(struct ipath_devdata *dd)
+{
+	u64 val;
+	int i;
+	int ret;
+
+	/* Use ERROR so it shows up in logs, etc. */
+	ipath_dev_err(dd, "Resetting PE-800 unit %u\n",
+		      dd->ipath_unit);
+	val = dd->ipath_control | INFINIPATH_C_RESET;
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
+	mb();
+
+	for (i = 1; i <= 5; i++) {
+		int r;
+		/* allow MBIST, etc. to complete; longer on each retry.
+		 * We sometimes get machine checks from bus timeout if no
+		 * response, so for now, make it *really* long.
+		 */
+		msleep(1000 + (1 + i) * 2000);
+		if ((r =
+		     pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0,
+					    dd->ipath_pcibar0)))
+			ipath_dev_err(dd, "rewrite of BAR0 failed: %d\n",
+				      r);
+		if ((r =
+		     pci_write_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1,
+					    dd->ipath_pcibar1)))
+			ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n",
+				      r);
+		/* now re-enable memory access */
+		if ((r = pci_enable_device(dd->pcidev)))
+			ipath_dev_err(dd, "pci_enable_device failed after "
+				      "reset: %d\n", r);
+		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
+		if (val == dd->ipath_revision) {
+			ipath_cdbg(VERBOSE, "Got matching revision "
+				   "register %llx on try %d\n",
+				   (unsigned long long) val, i);
+			ret = ipath_reinit_msi(dd);
+			goto bail;
+		}
+		/* Probably getting -1 back */
+		ipath_dbg("Didn't get expected revision register, "
+			  "got %llx, try %d\n", (unsigned long long) val,
+			  i + 1);
+	}
+	ret = 0; /* failed */
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_pe_put_tid - write a TID in chip
+ * @dd: the infinipath device
+ * @tidptr: pointer to the expected TID (in chip) to udpate
+ * @tidtype: 0 for eager, 1 for expected
+ * @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
+ *
+ * This exists as a separate routine to allow for special locking etc.
+ * It's used for both the full cleanup on exit, as well as the normal
+ * setup and teardown.
+ */
+static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
+			     u32 type, unsigned long pa)
+{
+	u32 __iomem *tidp32 = (u32 __iomem *)tidptr;
+	unsigned long flags = 0; /* keep gcc quiet */
+
+	if (pa != dd->ipath_tidinvalid) {
+		if (pa & ((1U << 11) - 1)) {
+			dev_info(&dd->pcidev->dev, "BUG: physaddr %lx "
+				 "not 4KB aligned!\n", pa);
+			return;
+		}
+		pa >>= 11;
+		/* paranoia check */
+		if (pa & (7<<29))
+			ipath_dev_err(dd,
+				      "BUG: Physical page address 0x%lx "
+				      "has bits set in 31-29\n", pa);
+
+		if (type == 0)
+			pa |= dd->ipath_tidtemplate;
+		else /* for now, always full 4KB page */
+			pa |= 2 << 29;
+	}
+
+	/* workaround chip bug 9437 by writing each TID twice
+	 * and holding a spinlock around the writes, so they don't
+	 * intermix with other TID (eager or expected) writes
+	 * Unfortunately, this call can be done from interrupt level
+	 * for the port 0 eager TIDs, so we have to use irqsave
+	 */
+	spin_lock_irqsave(&dd->ipath_tid_lock, flags);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf);
+	if (dd->ipath_kregbase)
+		writel(pa, tidp32);
+	ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef);
+	mmiowb();
+	spin_unlock_irqrestore(&dd->ipath_tid_lock, flags);
+}
+
+/**
+ * ipath_pe_clear_tid - clear all TID entries for a port, expected and eager
+ * @dd: the infinipath device
+ * @port: the port
+ *
+ * clear all TID entries for a port, expected and eager.
+ * Used from ipath_close().  On PE800, TIDs are only 32 bits,
+ * not 64, but they are still on 64 bit boundaries, so tidbase
+ * is declared as u64 * for the pointer math, even though we write 32 bits
+ */
+static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
+{
+	u64 __iomem *tidbase;
+	unsigned long tidinv;
+	int i;
+
+	if (!dd->ipath_kregbase)
+		return;
+
+	ipath_cdbg(VERBOSE, "Invalidate TIDs for port %u\n", port);
+
+	tidinv = dd->ipath_tidinvalid;
+	tidbase = (u64 __iomem *)
+		((char __iomem *)(dd->ipath_kregbase) +
+		 dd->ipath_rcvtidbase +
+		 port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
+
+	for (i = 0; i < dd->ipath_rcvtidcnt; i++)
+		ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+
+	tidbase = (u64 __iomem *)
+		((char __iomem *)(dd->ipath_kregbase) +
+		 dd->ipath_rcvegrbase +
+		 port * dd->ipath_rcvegrcnt * sizeof(*tidbase));
+
+	for (i = 0; i < dd->ipath_rcvegrcnt; i++)
+		ipath_pe_put_tid(dd, &tidbase[i], 1, tidinv);
+}
+
+/**
+ * ipath_pe_tidtemplate - setup constants for TID updates
+ * @dd: the infinipath device
+ *
+ * We setup stuff that we use a lot, to avoid calculating each time
+ */
+static void ipath_pe_tidtemplate(struct ipath_devdata *dd)
+{
+	u32 egrsize = dd->ipath_rcvegrbufsize;
+
+	/* For now, we always allocate 4KB buffers (at init) so we can
+	 * receive max size packets.  We may want a module parameter to
+	 * specify 2KB or 4KB and/or make be per port instead of per device
+	 * for those who want to reduce memory footprint.  Note that the
+	 * ipath_rcvhdrentsize size must be large enough to hold the largest
+	 * IB header (currently 96 bytes) that we expect to handle (plus of
+	 * course the 2 dwords of RHF).
+	 */
+	if (egrsize == 2048)
+		dd->ipath_tidtemplate = 1U << 29;
+	else if (egrsize == 4096)
+		dd->ipath_tidtemplate = 2U << 29;
+	else {
+		egrsize = 4096;
+		dev_info(&dd->pcidev->dev, "BUG: unsupported egrbufsize "
+			 "%u, using %u\n", dd->ipath_rcvegrbufsize,
+			 egrsize);
+		dd->ipath_tidtemplate = 2U << 29;
+	}
+	dd->ipath_tidinvalid = 0;
+}
+
+static int ipath_pe_early_init(struct ipath_devdata *dd)
+{
+	dd->ipath_flags |= IPATH_4BYTE_TID;
+
+	/*
+	 * For openib, we need to be able to handle an IB header of 96 bytes
+	 * or 24 dwords.  HT-400 has arbitrary sized receive buffers, so we
+	 * made them the same size as the PIO buffers.  The PE-800 does not
+	 * handle arbitrary size buffers, so we need the header large enough
+	 * to handle largest IB header, but still have room for a 2KB MTU
+	 * standard IB packet.
+	 */
+	dd->ipath_rcvhdrentsize = 24;
+	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
+
+	/* For HT-400, we allocate a somewhat overly large eager buffer,
+	 * such that we can guarantee that we can receive the largest packet
+	 * that we can send out.  To truly support a 4KB MTU, we need to
+	 * bump this to a larger value.  We'll do this when I get around to
+	 * testing 4KB sends on the PE-800, which I have not yet done.
+	 */
+	dd->ipath_rcvegrbufsize = 2048;
+	/*
+	 * the min() check here is currently a nop, but it may not always
+	 * be, depending on just how we do ipath_rcvegrbufsize
+	 */
+	dd->ipath_ibmaxlen = min(dd->ipath_piosize2k,
+				 dd->ipath_rcvegrbufsize +
+				 (dd->ipath_rcvhdrentsize << 2));
+	dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen;
+
+	/*
+	 * For PE-800, we can request a receive interrupt for 1 or
+	 * more packets from current offset.  For now, we set this
+	 * up for a single packet, to match the HT-400 behavior.
+	 */
+	dd->ipath_rhdrhead_intr_off = 1ULL<<32;
+
+	return 0;
+}
+
+int __attribute__((weak)) ipath_unordered_wc(void)
+{
+	return 0;
+}
+
+/**
+ * ipath_init_pe_get_base_info - set chip-specific flags for user code
+ * @dd: the infinipath device
+ * @kbase: ipath_base_info pointer
+ *
+ * We set the PCIE flag because the lower bandwidth on PCIe vs
+ * HyperTransport can affect some user packet algorithims.
+ */
+static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
+{
+	struct ipath_base_info *kinfo = kbase;
+
+	if (ipath_unordered_wc()) {
+		kinfo->spi_runtime_flags |= IPATH_RUNTIME_FORCE_WC_ORDER;
+		ipath_cdbg(PROC, "Intel processor, forcing WC order\n");
+	}
+	else
+		ipath_cdbg(PROC, "Not Intel processor, WC ordered\n");
+
+	kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
+
+	return 0;
+}
+
+/**
+ * ipath_init_pe800_funcs - set up the chip-specific function pointers
+ * @dd: the infinipath device
+ *
+ * This is global, and is called directly at init to set up the
+ * chip-specific function pointers for later use.
+ */
+void ipath_init_pe800_funcs(struct ipath_devdata *dd)
+{
+	dd->ipath_f_intrsetup = ipath_pe_intconfig;
+	dd->ipath_f_bus = ipath_setup_pe_config;
+	dd->ipath_f_reset = ipath_setup_pe_reset;
+	dd->ipath_f_get_boardname = ipath_pe_boardname;
+	dd->ipath_f_init_hwerrors = ipath_pe_init_hwerrors;
+	dd->ipath_f_early_init = ipath_pe_early_init;
+	dd->ipath_f_handle_hwerrors = ipath_pe_handle_hwerrors;
+	dd->ipath_f_quiet_serdes = ipath_pe_quiet_serdes;
+	dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
+	dd->ipath_f_clear_tids = ipath_pe_clear_tids;
+	dd->ipath_f_put_tid = ipath_pe_put_tid;
+	dd->ipath_f_cleanup = ipath_setup_pe_cleanup;
+	dd->ipath_f_setextled = ipath_setup_pe_setextled;
+	dd->ipath_f_get_base_info = ipath_pe_get_base_info;
+
+	/* initialize chip-specific variables */
+	dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
+
+	/*
+	 * setup the register offsets, since they are different for each
+	 * chip
+	 */
+	dd->ipath_kregs = &ipath_pe_kregs;
+	dd->ipath_cregs = &ipath_pe_cregs;
+
+	ipath_init_pe_variables();
+}
+
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
new file mode 100644
index 0000000..1889071
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+#define BITS_PER_PAGE		(PAGE_SIZE*BITS_PER_BYTE)
+#define BITS_PER_PAGE_MASK	(BITS_PER_PAGE-1)
+#define mk_qpn(qpt, map, off)	(((map) - (qpt)->map) * BITS_PER_PAGE + \
+				 (off))
+#define find_next_offset(map, off) find_next_zero_bit((map)->page, \
+						      BITS_PER_PAGE, off)
+
+#define TRANS_INVALID	0
+#define TRANS_ANY2RST	1
+#define TRANS_RST2INIT	2
+#define TRANS_INIT2INIT	3
+#define TRANS_INIT2RTR	4
+#define TRANS_RTR2RTS	5
+#define TRANS_RTS2RTS	6
+#define TRANS_SQERR2RTS	7
+#define TRANS_ANY2ERR	8
+#define TRANS_RTS2SQD	9  /* XXX Wait for expected ACKs & signal event */
+#define TRANS_SQD2SQD	10 /* error if not drained & parameter change */
+#define TRANS_SQD2RTS	11 /* error if not drained */
+
+/*
+ * Convert the AETH credit code into the number of credits.
+ */
+static u32 credit_table[31] = {
+	0,			/* 0 */
+	1,			/* 1 */
+	2,			/* 2 */
+	3,			/* 3 */
+	4,			/* 4 */
+	6,			/* 5 */
+	8,			/* 6 */
+	12,			/* 7 */
+	16,			/* 8 */
+	24,			/* 9 */
+	32,			/* A */
+	48,			/* B */
+	64,			/* C */
+	96,			/* D */
+	128,			/* E */
+	192,			/* F */
+	256,			/* 10 */
+	384,			/* 11 */
+	512,			/* 12 */
+	768,			/* 13 */
+	1024,			/* 14 */
+	1536,			/* 15 */
+	2048,			/* 16 */
+	3072,			/* 17 */
+	4096,			/* 18 */
+	6144,			/* 19 */
+	8192,			/* 1A */
+	12288,			/* 1B */
+	16384,			/* 1C */
+	24576,			/* 1D */
+	32768			/* 1E */
+};
+
+static u32 alloc_qpn(struct ipath_qp_table *qpt)
+{
+	u32 i, offset, max_scan, qpn;
+	struct qpn_map *map;
+	u32 ret;
+
+	qpn = qpt->last + 1;
+	if (qpn >= QPN_MAX)
+		qpn = 2;
+	offset = qpn & BITS_PER_PAGE_MASK;
+	map = &qpt->map[qpn / BITS_PER_PAGE];
+	max_scan = qpt->nmaps - !offset;
+	for (i = 0;;) {
+		if (unlikely(!map->page)) {
+			unsigned long page = get_zeroed_page(GFP_KERNEL);
+			unsigned long flags;
+
+			/*
+			 * Free the page if someone raced with us
+			 * installing it:
+			 */
+			spin_lock_irqsave(&qpt->lock, flags);
+			if (map->page)
+				free_page(page);
+			else
+				map->page = (void *)page;
+			spin_unlock_irqrestore(&qpt->lock, flags);
+			if (unlikely(!map->page))
+				break;
+		}
+		if (likely(atomic_read(&map->n_free))) {
+			do {
+				if (!test_and_set_bit(offset, map->page)) {
+					atomic_dec(&map->n_free);
+					qpt->last = qpn;
+					ret = qpn;
+					goto bail;
+				}
+				offset = find_next_offset(map, offset);
+				qpn = mk_qpn(qpt, map, offset);
+				/*
+				 * This test differs from alloc_pidmap().
+				 * If find_next_offset() does find a zero
+				 * bit, we don't need to check for QPN
+				 * wrapping around past our starting QPN.
+				 * We just need to be sure we don't loop
+				 * forever.
+				 */
+			} while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
+		}
+		/*
+		 * In order to keep the number of pages allocated to a
+		 * minimum, we scan the all existing pages before increasing
+		 * the size of the bitmap table.
+		 */
+		if (++i > max_scan) {
+			if (qpt->nmaps == QPNMAP_ENTRIES)
+				break;
+			map = &qpt->map[qpt->nmaps++];
+			offset = 0;
+		} else if (map < &qpt->map[qpt->nmaps]) {
+			++map;
+			offset = 0;
+		} else {
+			map = &qpt->map[0];
+			offset = 2;
+		}
+		qpn = mk_qpn(qpt, map, offset);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static void free_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+	struct qpn_map *map;
+
+	map = qpt->map + qpn / BITS_PER_PAGE;
+	if (map->page)
+		clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
+	atomic_inc(&map->n_free);
+}
+
+/**
+ * ipath_alloc_qpn - allocate a QP number
+ * @qpt: the QP table
+ * @qp: the QP
+ * @type: the QP type (IB_QPT_SMI and IB_QPT_GSI are special)
+ *
+ * Allocate the next available QPN and put the QP into the hash table.
+ * The hash table holds a reference to the QP.
+ */
+static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
+			   enum ib_qp_type type)
+{
+	unsigned long flags;
+	u32 qpn;
+	int ret;
+
+	if (type == IB_QPT_SMI)
+		qpn = 0;
+	else if (type == IB_QPT_GSI)
+		qpn = 1;
+	else {
+		/* Allocate the next available QPN */
+		qpn = alloc_qpn(qpt);
+		if (qpn == 0) {
+			ret = -ENOMEM;
+			goto bail;
+		}
+	}
+	qp->ibqp.qp_num = qpn;
+
+	/* Add the QP to the hash table. */
+	spin_lock_irqsave(&qpt->lock, flags);
+
+	qpn %= qpt->max;
+	qp->next = qpt->table[qpn];
+	qpt->table[qpn] = qp;
+	atomic_inc(&qp->refcount);
+
+	spin_unlock_irqrestore(&qpt->lock, flags);
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_free_qp - remove a QP from the QP table
+ * @qpt: the QP table
+ * @qp: the QP to remove
+ *
+ * Remove the QP from the table so it can't be found asynchronously by
+ * the receive interrupt routine.
+ */
+static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
+{
+	struct ipath_qp *q, **qpp;
+	unsigned long flags;
+	int fnd = 0;
+
+	spin_lock_irqsave(&qpt->lock, flags);
+
+	/* Remove QP from the hash table. */
+	qpp = &qpt->table[qp->ibqp.qp_num % qpt->max];
+	for (; (q = *qpp) != NULL; qpp = &q->next) {
+		if (q == qp) {
+			*qpp = qp->next;
+			qp->next = NULL;
+			atomic_dec(&qp->refcount);
+			fnd = 1;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&qpt->lock, flags);
+
+	if (!fnd)
+		return;
+
+	/* If QPN is not reserved, mark QPN free in the bitmap. */
+	if (qp->ibqp.qp_num > 1)
+		free_qpn(qpt, qp->ibqp.qp_num);
+
+	wait_event(qp->wait, !atomic_read(&qp->refcount));
+}
+
+/**
+ * ipath_free_all_qps - remove all QPs from the table
+ * @qpt: the QP table to empty
+ */
+void ipath_free_all_qps(struct ipath_qp_table *qpt)
+{
+	unsigned long flags;
+	struct ipath_qp *qp, *nqp;
+	u32 n;
+
+	for (n = 0; n < qpt->max; n++) {
+		spin_lock_irqsave(&qpt->lock, flags);
+		qp = qpt->table[n];
+		qpt->table[n] = NULL;
+		spin_unlock_irqrestore(&qpt->lock, flags);
+
+		while (qp) {
+			nqp = qp->next;
+			if (qp->ibqp.qp_num > 1)
+				free_qpn(qpt, qp->ibqp.qp_num);
+			if (!atomic_dec_and_test(&qp->refcount) ||
+			    !ipath_destroy_qp(&qp->ibqp))
+				_VERBS_INFO("QP memory leak!\n");
+			qp = nqp;
+		}
+	}
+
+	for (n = 0; n < ARRAY_SIZE(qpt->map); n++) {
+		if (qpt->map[n].page)
+			free_page((unsigned long)qpt->map[n].page);
+	}
+}
+
+/**
+ * ipath_lookup_qpn - return the QP with the given QPN
+ * @qpt: the QP table
+ * @qpn: the QP number to look up
+ *
+ * The caller is responsible for decrementing the QP reference count
+ * when done.
+ */
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn)
+{
+	unsigned long flags;
+	struct ipath_qp *qp;
+
+	spin_lock_irqsave(&qpt->lock, flags);
+
+	for (qp = qpt->table[qpn % qpt->max]; qp; qp = qp->next) {
+		if (qp->ibqp.qp_num == qpn) {
+			atomic_inc(&qp->refcount);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&qpt->lock, flags);
+	return qp;
+}
+
+/**
+ * ipath_reset_qp - initialize the QP state to the reset state
+ * @qp: the QP to reset
+ */
+static void ipath_reset_qp(struct ipath_qp *qp)
+{
+	qp->remote_qpn = 0;
+	qp->qkey = 0;
+	qp->qp_access_flags = 0;
+	qp->s_hdrwords = 0;
+	qp->s_psn = 0;
+	qp->r_psn = 0;
+	atomic_set(&qp->msn, 0);
+	if (qp->ibqp.qp_type == IB_QPT_RC) {
+		qp->s_state = IB_OPCODE_RC_SEND_LAST;
+		qp->r_state = IB_OPCODE_RC_SEND_LAST;
+	} else {
+		qp->s_state = IB_OPCODE_UC_SEND_LAST;
+		qp->r_state = IB_OPCODE_UC_SEND_LAST;
+	}
+	qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+	qp->s_nak_state = 0;
+	qp->s_rnr_timeout = 0;
+	qp->s_head = 0;
+	qp->s_tail = 0;
+	qp->s_cur = 0;
+	qp->s_last = 0;
+	qp->s_ssn = 1;
+	qp->s_lsn = 0;
+	qp->r_rq.head = 0;
+	qp->r_rq.tail = 0;
+	qp->r_reuse_sge = 0;
+}
+
+/**
+ * ipath_error_qp - put a QP into an error state
+ * @qp: the QP to put into an error state
+ *
+ * Flushes both send and receive work queues.
+ * QP r_rq.lock and s_lock should be held.
+ */
+
+static void ipath_error_qp(struct ipath_qp *qp)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ib_wc wc;
+
+	_VERBS_INFO("QP%d/%d in error state\n",
+		    qp->ibqp.qp_num, qp->remote_qpn);
+
+	spin_lock(&dev->pending_lock);
+	/* XXX What if its already removed by the timeout code? */
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	if (qp->piowait.next != LIST_POISON1)
+		list_del(&qp->piowait);
+	spin_unlock(&dev->pending_lock);
+
+	wc.status = IB_WC_WR_FLUSH_ERR;
+	wc.vendor_err = 0;
+	wc.byte_len = 0;
+	wc.imm_data = 0;
+	wc.qp_num = qp->ibqp.qp_num;
+	wc.src_qp = 0;
+	wc.wc_flags = 0;
+	wc.pkey_index = 0;
+	wc.slid = 0;
+	wc.sl = 0;
+	wc.dlid_path_bits = 0;
+	wc.port_num = 0;
+
+	while (qp->s_last != qp->s_head) {
+		struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+		wc.wr_id = wqe->wr.wr_id;
+		wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		if (++qp->s_last >= qp->s_size)
+			qp->s_last = 0;
+		ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+	}
+	qp->s_cur = qp->s_tail = qp->s_head;
+	qp->s_hdrwords = 0;
+	qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+
+	wc.opcode = IB_WC_RECV;
+	while (qp->r_rq.tail != qp->r_rq.head) {
+		wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
+		if (++qp->r_rq.tail >= qp->r_rq.size)
+			qp->r_rq.tail = 0;
+		ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+	}
+}
+
+/**
+ * ipath_modify_qp - modify the attributes of a queue pair
+ * @ibqp: the queue pair who's attributes we're modifying
+ * @attr: the new attributes
+ * @attr_mask: the mask of attributes to modify
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	enum ib_qp_state cur_state, new_state;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&qp->r_rq.lock, flags);
+	spin_lock(&qp->s_lock);
+
+	cur_state = attr_mask & IB_QP_CUR_STATE ?
+		attr->cur_qp_state : qp->state;
+	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
+
+	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
+				attr_mask))
+		goto inval;
+
+	switch (new_state) {
+	case IB_QPS_RESET:
+		ipath_reset_qp(qp);
+		break;
+
+	case IB_QPS_ERR:
+		ipath_error_qp(qp);
+		break;
+
+	default:
+		break;
+
+	}
+
+	if (attr_mask & IB_QP_PKEY_INDEX) {
+		struct ipath_ibdev *dev = to_idev(ibqp->device);
+
+		if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd))
+			goto inval;
+		qp->s_pkey_index = attr->pkey_index;
+	}
+
+	if (attr_mask & IB_QP_DEST_QPN)
+		qp->remote_qpn = attr->dest_qp_num;
+
+	if (attr_mask & IB_QP_SQ_PSN) {
+		qp->s_next_psn = attr->sq_psn;
+		qp->s_last_psn = qp->s_next_psn - 1;
+	}
+
+	if (attr_mask & IB_QP_RQ_PSN)
+		qp->r_psn = attr->rq_psn;
+
+	if (attr_mask & IB_QP_ACCESS_FLAGS)
+		qp->qp_access_flags = attr->qp_access_flags;
+
+	if (attr_mask & IB_QP_AV) {
+		if (attr->ah_attr.dlid == 0 ||
+		    attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE)
+			goto inval;
+		qp->remote_ah_attr = attr->ah_attr;
+	}
+
+	if (attr_mask & IB_QP_PATH_MTU)
+		qp->path_mtu = attr->path_mtu;
+
+	if (attr_mask & IB_QP_RETRY_CNT)
+		qp->s_retry = qp->s_retry_cnt = attr->retry_cnt;
+
+	if (attr_mask & IB_QP_RNR_RETRY) {
+		qp->s_rnr_retry = attr->rnr_retry;
+		if (qp->s_rnr_retry > 7)
+			qp->s_rnr_retry = 7;
+		qp->s_rnr_retry_cnt = qp->s_rnr_retry;
+	}
+
+	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+		if (attr->min_rnr_timer > 31)
+			goto inval;
+		qp->s_min_rnr_timer = attr->min_rnr_timer;
+	}
+
+	if (attr_mask & IB_QP_QKEY)
+		qp->qkey = attr->qkey;
+
+	if (attr_mask & IB_QP_PKEY_INDEX)
+		qp->s_pkey_index = attr->pkey_index;
+
+	qp->state = new_state;
+	spin_unlock(&qp->s_lock);
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+	/*
+	 * If QP1 changed to the RTS state, try to move to the link to INIT
+	 * even if it was ACTIVE so the SM will reinitialize the SMA's
+	 * state.
+	 */
+	if (qp->ibqp.qp_num == 1 && new_state == IB_QPS_RTS) {
+		struct ipath_ibdev *dev = to_idev(ibqp->device);
+
+		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+	}
+	ret = 0;
+	goto bail;
+
+inval:
+	spin_unlock(&qp->s_lock);
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+	ret = -EINVAL;
+
+bail:
+	return ret;
+}
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		   int attr_mask, struct ib_qp_init_attr *init_attr)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+
+	attr->qp_state = qp->state;
+	attr->cur_qp_state = attr->qp_state;
+	attr->path_mtu = qp->path_mtu;
+	attr->path_mig_state = 0;
+	attr->qkey = qp->qkey;
+	attr->rq_psn = qp->r_psn;
+	attr->sq_psn = qp->s_next_psn;
+	attr->dest_qp_num = qp->remote_qpn;
+	attr->qp_access_flags = qp->qp_access_flags;
+	attr->cap.max_send_wr = qp->s_size - 1;
+	attr->cap.max_recv_wr = qp->r_rq.size - 1;
+	attr->cap.max_send_sge = qp->s_max_sge;
+	attr->cap.max_recv_sge = qp->r_rq.max_sge;
+	attr->cap.max_inline_data = 0;
+	attr->ah_attr = qp->remote_ah_attr;
+	memset(&attr->alt_ah_attr, 0, sizeof(attr->alt_ah_attr));
+	attr->pkey_index = qp->s_pkey_index;
+	attr->alt_pkey_index = 0;
+	attr->en_sqd_async_notify = 0;
+	attr->sq_draining = 0;
+	attr->max_rd_atomic = 1;
+	attr->max_dest_rd_atomic = 1;
+	attr->min_rnr_timer = qp->s_min_rnr_timer;
+	attr->port_num = 1;
+	attr->timeout = 0;
+	attr->retry_cnt = qp->s_retry_cnt;
+	attr->rnr_retry = qp->s_rnr_retry;
+	attr->alt_port_num = 0;
+	attr->alt_timeout = 0;
+
+	init_attr->event_handler = qp->ibqp.event_handler;
+	init_attr->qp_context = qp->ibqp.qp_context;
+	init_attr->send_cq = qp->ibqp.send_cq;
+	init_attr->recv_cq = qp->ibqp.recv_cq;
+	init_attr->srq = qp->ibqp.srq;
+	init_attr->cap = attr->cap;
+	init_attr->sq_sig_type =
+		(qp->s_flags & (1 << IPATH_S_SIGNAL_REQ_WR))
+		? IB_SIGNAL_REQ_WR : 0;
+	init_attr->qp_type = qp->ibqp.qp_type;
+	init_attr->port_num = 1;
+	return 0;
+}
+
+/**
+ * ipath_compute_aeth - compute the AETH (syndrome + MSN)
+ * @qp: the queue pair to compute the AETH for
+ *
+ * Returns the AETH.
+ *
+ * The QP s_lock should be held.
+ */
+__be32 ipath_compute_aeth(struct ipath_qp *qp)
+{
+	u32 aeth = atomic_read(&qp->msn) & IPS_MSN_MASK;
+
+	if (qp->s_nak_state) {
+		aeth |= qp->s_nak_state << IPS_AETH_CREDIT_SHIFT;
+	} else if (qp->ibqp.srq) {
+		/*
+		 * Shared receive queues don't generate credits.
+		 * Set the credit field to the invalid value.
+		 */
+		aeth |= IPS_AETH_CREDIT_INVAL << IPS_AETH_CREDIT_SHIFT;
+	} else {
+		u32 min, max, x;
+		u32 credits;
+
+		/*
+		 * Compute the number of credits available (RWQEs).
+		 * XXX Not holding the r_rq.lock here so there is a small
+		 * chance that the pair of reads are not atomic.
+		 */
+		credits = qp->r_rq.head - qp->r_rq.tail;
+		if ((int)credits < 0)
+			credits += qp->r_rq.size;
+		/*
+		 * Binary search the credit table to find the code to
+		 * use.
+		 */
+		min = 0;
+		max = 31;
+		for (;;) {
+			x = (min + max) / 2;
+			if (credit_table[x] == credits)
+				break;
+			if (credit_table[x] > credits)
+				max = x;
+			else if (min == x)
+				break;
+			else
+				min = x;
+		}
+		aeth |= x << IPS_AETH_CREDIT_SHIFT;
+	}
+	return cpu_to_be32(aeth);
+}
+
+/**
+ * ipath_create_qp - create a queue pair for a device
+ * @ibpd: the protection domain who's device we create the queue pair for
+ * @init_attr: the attributes of the queue pair
+ * @udata: unused by InfiniPath
+ *
+ * Returns the queue pair on success, otherwise returns an errno.
+ *
+ * Called by the ib_create_qp() core verbs function.
+ */
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+			      struct ib_qp_init_attr *init_attr,
+			      struct ib_udata *udata)
+{
+	struct ipath_qp *qp;
+	int err;
+	struct ipath_swqe *swq = NULL;
+	struct ipath_ibdev *dev;
+	size_t sz;
+	struct ib_qp *ret;
+
+	if (init_attr->cap.max_send_sge > 255 ||
+	    init_attr->cap.max_recv_sge > 255) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	switch (init_attr->qp_type) {
+	case IB_QPT_UC:
+	case IB_QPT_RC:
+		sz = sizeof(struct ipath_sge) *
+			init_attr->cap.max_send_sge +
+			sizeof(struct ipath_swqe);
+		swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
+		if (swq == NULL) {
+			ret = ERR_PTR(-ENOMEM);
+			goto bail;
+		}
+		/* FALLTHROUGH */
+	case IB_QPT_UD:
+	case IB_QPT_SMI:
+	case IB_QPT_GSI:
+		qp = kmalloc(sizeof(*qp), GFP_KERNEL);
+		if (!qp) {
+			ret = ERR_PTR(-ENOMEM);
+			goto bail;
+		}
+		qp->r_rq.size = init_attr->cap.max_recv_wr + 1;
+		sz = sizeof(struct ipath_sge) *
+			init_attr->cap.max_recv_sge +
+			sizeof(struct ipath_rwqe);
+		qp->r_rq.wq = vmalloc(qp->r_rq.size * sz);
+		if (!qp->r_rq.wq) {
+			kfree(qp);
+			ret = ERR_PTR(-ENOMEM);
+			goto bail;
+		}
+
+		/*
+		 * ib_create_qp() will initialize qp->ibqp
+		 * except for qp->ibqp.qp_num.
+		 */
+		spin_lock_init(&qp->s_lock);
+		spin_lock_init(&qp->r_rq.lock);
+		atomic_set(&qp->refcount, 0);
+		init_waitqueue_head(&qp->wait);
+		tasklet_init(&qp->s_task,
+			     init_attr->qp_type == IB_QPT_RC ?
+			     ipath_do_rc_send : ipath_do_uc_send,
+			     (unsigned long)qp);
+		qp->piowait.next = LIST_POISON1;
+		qp->piowait.prev = LIST_POISON2;
+		qp->timerwait.next = LIST_POISON1;
+		qp->timerwait.prev = LIST_POISON2;
+		qp->state = IB_QPS_RESET;
+		qp->s_wq = swq;
+		qp->s_size = init_attr->cap.max_send_wr + 1;
+		qp->s_max_sge = init_attr->cap.max_send_sge;
+		qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
+		qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ?
+			1 << IPATH_S_SIGNAL_REQ_WR : 0;
+		dev = to_idev(ibpd->device);
+		err = ipath_alloc_qpn(&dev->qp_table, qp,
+				      init_attr->qp_type);
+		if (err) {
+			vfree(swq);
+			vfree(qp->r_rq.wq);
+			kfree(qp);
+			ret = ERR_PTR(err);
+			goto bail;
+		}
+		ipath_reset_qp(qp);
+
+		/* Tell the core driver that the kernel SMA is present. */
+		if (qp->ibqp.qp_type == IB_QPT_SMI)
+			ipath_layer_set_verbs_flags(dev->dd,
+						    IPATH_VERBS_KERNEL_SMA);
+		break;
+
+	default:
+		/* Don't support raw QPs */
+		ret = ERR_PTR(-ENOSYS);
+		goto bail;
+	}
+
+	init_attr->cap.max_inline_data = 0;
+
+	ret = &qp->ibqp;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_destroy_qp - destroy a queue pair
+ * @ibqp: the queue pair to destroy
+ *
+ * Returns 0 on success.
+ *
+ * Note that this can be called while the QP is actively sending or
+ * receiving!
+ */
+int ipath_destroy_qp(struct ib_qp *ibqp)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	struct ipath_ibdev *dev = to_idev(ibqp->device);
+	unsigned long flags;
+
+	/* Tell the core driver that the kernel SMA is gone. */
+	if (qp->ibqp.qp_type == IB_QPT_SMI)
+		ipath_layer_set_verbs_flags(dev->dd, 0);
+
+	spin_lock_irqsave(&qp->r_rq.lock, flags);
+	spin_lock(&qp->s_lock);
+	qp->state = IB_QPS_ERR;
+	spin_unlock(&qp->s_lock);
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+	/* Stop the sending tasklet. */
+	tasklet_kill(&qp->s_task);
+
+	/* Make sure the QP isn't on the timeout list. */
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	if (qp->piowait.next != LIST_POISON1)
+		list_del(&qp->piowait);
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+	/*
+	 * Make sure that the QP is not in the QPN table so receive
+	 * interrupts will discard packets for this QP.  XXX Also remove QP
+	 * from multicast table.
+	 */
+	if (atomic_read(&qp->refcount) != 0)
+		ipath_free_qp(&dev->qp_table, qp);
+
+	vfree(qp->s_wq);
+	vfree(qp->r_rq.wq);
+	kfree(qp);
+	return 0;
+}
+
+/**
+ * ipath_init_qp_table - initialize the QP table for a device
+ * @idev: the device who's QP table we're initializing
+ * @size: the size of the QP table
+ *
+ * Returns 0 on success, otherwise returns an errno.
+ */
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size)
+{
+	int i;
+	int ret;
+
+	idev->qp_table.last = 1;	/* QPN 0 and 1 are special. */
+	idev->qp_table.max = size;
+	idev->qp_table.nmaps = 1;
+	idev->qp_table.table = kzalloc(size * sizeof(*idev->qp_table.table),
+				       GFP_KERNEL);
+	if (idev->qp_table.table == NULL) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(idev->qp_table.map); i++) {
+		atomic_set(&idev->qp_table.map[i].n_free, BITS_PER_PAGE);
+		idev->qp_table.map[i].page = NULL;
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_sqerror_qp - put a QP's send queue into an error state
+ * @qp: QP who's send queue will be put into an error state
+ * @wc: the WC responsible for putting the QP in this state
+ *
+ * Flushes the send work queue.
+ * The QP s_lock should be held.
+ */
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+	_VERBS_INFO("Send queue error on QP%d/%d: err: %d\n",
+		    qp->ibqp.qp_num, qp->remote_qpn, wc->status);
+
+	spin_lock(&dev->pending_lock);
+	/* XXX What if its already removed by the timeout code? */
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	if (qp->piowait.next != LIST_POISON1)
+		list_del(&qp->piowait);
+	spin_unlock(&dev->pending_lock);
+
+	ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+	if (++qp->s_last >= qp->s_size)
+		qp->s_last = 0;
+
+	wc->status = IB_WC_WR_FLUSH_ERR;
+
+	while (qp->s_last != qp->s_head) {
+		wc->wr_id = wqe->wr.wr_id;
+		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1);
+		if (++qp->s_last >= qp->s_size)
+			qp->s_last = 0;
+		wqe = get_swqe_ptr(qp, qp->s_last);
+	}
+	qp->s_cur = qp->s_tail = qp->s_head;
+	qp->state = IB_QPS_SQE;
+}
+
+/**
+ * ipath_get_credit - flush the send work queue of a QP
+ * @qp: the qp who's send work queue to flush
+ * @aeth: the Acknowledge Extended Transport Header
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth)
+{
+	u32 credit = (aeth >> IPS_AETH_CREDIT_SHIFT) & IPS_AETH_CREDIT_MASK;
+
+	/*
+	 * If the credit is invalid, we can send
+	 * as many packets as we like.  Otherwise, we have to
+	 * honor the credit field.
+	 */
+	if (credit == IPS_AETH_CREDIT_INVAL) {
+		qp->s_lsn = (u32) -1;
+	} else if (qp->s_lsn != (u32) -1) {
+		/* Compute new LSN (i.e., MSN + credit) */
+		credit = (aeth + credit_table[credit]) & IPS_MSN_MASK;
+		if (ipath_cmp24(credit, qp->s_lsn) > 0)
+			qp->s_lsn = credit;
+	}
+
+	/* Restart sending if it was blocked due to lack of credits. */
+	if (qp->s_cur != qp->s_head &&
+	    (qp->s_lsn == (u32) -1 ||
+	     ipath_cmp24(get_swqe_ptr(qp, qp->s_cur)->ssn,
+			 qp->s_lsn + 1) <= 0))
+		tasklet_hi_schedule(&qp->s_task);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
new file mode 100644
index 0000000..a4055ca
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -0,0 +1,1857 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_RC_##x
+
+/**
+ * ipath_init_restart- initialize the qp->s_sge after a restart
+ * @qp: the QP who's SGE we're restarting
+ * @wqe: the work queue to initialize the QP's SGE from
+ *
+ * The QP s_lock should be held.
+ */
+static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe)
+{
+	struct ipath_ibdev *dev;
+	u32 len;
+
+	len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) *
+		ib_mtu_enum_to_int(qp->path_mtu);
+	qp->s_sge.sge = wqe->sg_list[0];
+	qp->s_sge.sg_list = wqe->sg_list + 1;
+	qp->s_sge.num_sge = wqe->wr.num_sge;
+	ipath_skip_sge(&qp->s_sge, len);
+	qp->s_len = wqe->length - len;
+	dev = to_idev(qp->ibqp.device);
+	spin_lock(&dev->pending_lock);
+	if (qp->timerwait.next == LIST_POISON1)
+		list_add_tail(&qp->timerwait,
+			      &dev->pending[dev->pending_index]);
+	spin_unlock(&dev->pending_lock);
+}
+
+/**
+ * ipath_make_rc_ack - construct a response packet (ACK, NAK, or RDMA read)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ *
+ * Return bth0 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline u32 ipath_make_rc_ack(struct ipath_qp *qp,
+				    struct ipath_other_headers *ohdr,
+				    u32 pmtu)
+{
+	struct ipath_sge_state *ss;
+	u32 hwords;
+	u32 len;
+	u32 bth0;
+
+	/* header size in 32-bit words LRH+BTH = (8+12)/4. */
+	hwords = 5;
+
+	/*
+	 * Send a response.  Note that we are in the responder's
+	 * side of the QP context.
+	 */
+	switch (qp->s_ack_state) {
+	case OP(RDMA_READ_REQUEST):
+		ss = &qp->s_rdma_sge;
+		len = qp->s_rdma_len;
+		if (len > pmtu) {
+			len = pmtu;
+			qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
+		}
+		else
+			qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+		qp->s_rdma_len -= len;
+		bth0 = qp->s_ack_state << 24;
+		ohdr->u.aeth = ipath_compute_aeth(qp);
+		hwords++;
+		break;
+
+	case OP(RDMA_READ_RESPONSE_FIRST):
+		qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+		/* FALLTHROUGH */
+	case OP(RDMA_READ_RESPONSE_MIDDLE):
+		ss = &qp->s_rdma_sge;
+		len = qp->s_rdma_len;
+		if (len > pmtu)
+			len = pmtu;
+		else {
+			ohdr->u.aeth = ipath_compute_aeth(qp);
+			hwords++;
+			qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+		}
+		qp->s_rdma_len -= len;
+		bth0 = qp->s_ack_state << 24;
+		break;
+
+	case OP(RDMA_READ_RESPONSE_LAST):
+	case OP(RDMA_READ_RESPONSE_ONLY):
+		/*
+		 * We have to prevent new requests from changing
+		 * the r_sge state while a ipath_verbs_send()
+		 * is in progress.
+		 * Changing r_state allows the receiver
+		 * to continue processing new packets.
+		 * We do it here now instead of above so
+		 * that we are sure the packet was sent before
+		 * changing the state.
+		 */
+		qp->r_state = OP(RDMA_READ_RESPONSE_LAST);
+		qp->s_ack_state = OP(ACKNOWLEDGE);
+		return 0;
+
+	case OP(COMPARE_SWAP):
+	case OP(FETCH_ADD):
+		ss = NULL;
+		len = 0;
+		qp->r_state = OP(SEND_LAST);
+		qp->s_ack_state = OP(ACKNOWLEDGE);
+		bth0 = IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+		ohdr->u.at.aeth = ipath_compute_aeth(qp);
+		ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+		hwords += sizeof(ohdr->u.at) / 4;
+		break;
+
+	default:
+		/* Send a regular ACK. */
+		ss = NULL;
+		len = 0;
+		qp->s_ack_state = OP(ACKNOWLEDGE);
+		bth0 = qp->s_ack_state << 24;
+		ohdr->u.aeth = ipath_compute_aeth(qp);
+		hwords++;
+	}
+	qp->s_hdrwords = hwords;
+	qp->s_cur_sge = ss;
+	qp->s_cur_size = len;
+
+	return bth0;
+}
+
+/**
+ * ipath_make_rc_req - construct a request packet (SEND, RDMA r/w, ATOMIC)
+ * @qp: a pointer to the QP
+ * @ohdr: a pointer to the IB header being constructed
+ * @pmtu: the path MTU
+ * @bth0p: pointer to the BTH opcode word
+ * @bth2p: pointer to the BTH PSN word
+ *
+ * Return 1 if constructed; otherwise, return 0.
+ * Note the QP s_lock must be held.
+ */
+static inline int ipath_make_rc_req(struct ipath_qp *qp,
+				    struct ipath_other_headers *ohdr,
+				    u32 pmtu, u32 *bth0p, u32 *bth2p)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ipath_sge_state *ss;
+	struct ipath_swqe *wqe;
+	u32 hwords;
+	u32 len;
+	u32 bth0;
+	u32 bth2;
+	char newreq;
+
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) ||
+	    qp->s_rnr_timeout)
+		goto done;
+
+	/* header size in 32-bit words LRH+BTH = (8+12)/4. */
+	hwords = 5;
+	bth0 = 0;
+
+	/* Send a request. */
+	wqe = get_swqe_ptr(qp, qp->s_cur);
+	switch (qp->s_state) {
+	default:
+		/*
+		 * Resend an old request or start a new one.
+		 *
+		 * We keep track of the current SWQE so that
+		 * we don't reset the "furthest progress" state
+		 * if we need to back up.
+		 */
+		newreq = 0;
+		if (qp->s_cur == qp->s_tail) {
+			/* Check if send work queue is empty. */
+			if (qp->s_tail == qp->s_head)
+				goto done;
+			qp->s_psn = wqe->psn = qp->s_next_psn;
+			newreq = 1;
+		}
+		/*
+		 * Note that we have to be careful not to modify the
+		 * original work request since we may need to resend
+		 * it.
+		 */
+		qp->s_sge.sge = wqe->sg_list[0];
+		qp->s_sge.sg_list = wqe->sg_list + 1;
+		qp->s_sge.num_sge = wqe->wr.num_sge;
+		qp->s_len = len = wqe->length;
+		ss = &qp->s_sge;
+		bth2 = 0;
+		switch (wqe->wr.opcode) {
+		case IB_WR_SEND:
+		case IB_WR_SEND_WITH_IMM:
+			/* If no credit, return. */
+			if (qp->s_lsn != (u32) -1 &&
+			    ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+				goto done;
+			wqe->lpsn = wqe->psn;
+			if (len > pmtu) {
+				wqe->lpsn += (len - 1) / pmtu;
+				qp->s_state = OP(SEND_FIRST);
+				len = pmtu;
+				break;
+			}
+			if (wqe->wr.opcode == IB_WR_SEND)
+				qp->s_state = OP(SEND_ONLY);
+			else {
+				qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
+				/* Immediate data comes after the BTH */
+				ohdr->u.imm_data = wqe->wr.imm_data;
+				hwords += 1;
+			}
+			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+				bth0 |= 1 << 23;
+			bth2 = 1 << 31;	/* Request ACK. */
+			if (++qp->s_cur == qp->s_size)
+				qp->s_cur = 0;
+			break;
+
+		case IB_WR_RDMA_WRITE:
+			if (newreq)
+				qp->s_lsn++;
+			/* FALLTHROUGH */
+		case IB_WR_RDMA_WRITE_WITH_IMM:
+			/* If no credit, return. */
+			if (qp->s_lsn != (u32) -1 &&
+			    ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0)
+				goto done;
+			ohdr->u.rc.reth.vaddr =
+				cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+			ohdr->u.rc.reth.rkey =
+				cpu_to_be32(wqe->wr.wr.rdma.rkey);
+			ohdr->u.rc.reth.length = cpu_to_be32(len);
+			hwords += sizeof(struct ib_reth) / 4;
+			wqe->lpsn = wqe->psn;
+			if (len > pmtu) {
+				wqe->lpsn += (len - 1) / pmtu;
+				qp->s_state = OP(RDMA_WRITE_FIRST);
+				len = pmtu;
+				break;
+			}
+			if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+				qp->s_state = OP(RDMA_WRITE_ONLY);
+			else {
+				qp->s_state =
+					OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+				/* Immediate data comes
+				 * after RETH */
+				ohdr->u.rc.imm_data = wqe->wr.imm_data;
+				hwords += 1;
+				if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+					bth0 |= 1 << 23;
+			}
+			bth2 = 1 << 31;	/* Request ACK. */
+			if (++qp->s_cur == qp->s_size)
+				qp->s_cur = 0;
+			break;
+
+		case IB_WR_RDMA_READ:
+			ohdr->u.rc.reth.vaddr =
+				cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+			ohdr->u.rc.reth.rkey =
+				cpu_to_be32(wqe->wr.wr.rdma.rkey);
+			ohdr->u.rc.reth.length = cpu_to_be32(len);
+			qp->s_state = OP(RDMA_READ_REQUEST);
+			hwords += sizeof(ohdr->u.rc.reth) / 4;
+			if (newreq) {
+				qp->s_lsn++;
+				/*
+				 * Adjust s_next_psn to count the
+				 * expected number of responses.
+				 */
+				if (len > pmtu)
+					qp->s_next_psn += (len - 1) / pmtu;
+				wqe->lpsn = qp->s_next_psn++;
+			}
+			ss = NULL;
+			len = 0;
+			if (++qp->s_cur == qp->s_size)
+				qp->s_cur = 0;
+			break;
+
+		case IB_WR_ATOMIC_CMP_AND_SWP:
+		case IB_WR_ATOMIC_FETCH_AND_ADD:
+			if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP)
+				qp->s_state = OP(COMPARE_SWAP);
+			else
+				qp->s_state = OP(FETCH_ADD);
+			ohdr->u.atomic_eth.vaddr = cpu_to_be64(
+				wqe->wr.wr.atomic.remote_addr);
+			ohdr->u.atomic_eth.rkey = cpu_to_be32(
+				wqe->wr.wr.atomic.rkey);
+			ohdr->u.atomic_eth.swap_data = cpu_to_be64(
+				wqe->wr.wr.atomic.swap);
+			ohdr->u.atomic_eth.compare_data = cpu_to_be64(
+				wqe->wr.wr.atomic.compare_add);
+			hwords += sizeof(struct ib_atomic_eth) / 4;
+			if (newreq) {
+				qp->s_lsn++;
+				wqe->lpsn = wqe->psn;
+			}
+			if (++qp->s_cur == qp->s_size)
+				qp->s_cur = 0;
+			ss = NULL;
+			len = 0;
+			break;
+
+		default:
+			goto done;
+		}
+		if (newreq) {
+			qp->s_tail++;
+			if (qp->s_tail >= qp->s_size)
+				qp->s_tail = 0;
+		}
+		bth2 |= qp->s_psn++ & IPS_PSN_MASK;
+		if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+			qp->s_next_psn = qp->s_psn;
+		spin_lock(&dev->pending_lock);
+		if (qp->timerwait.next == LIST_POISON1)
+			list_add_tail(&qp->timerwait,
+				      &dev->pending[dev->pending_index]);
+		spin_unlock(&dev->pending_lock);
+		break;
+
+	case OP(RDMA_READ_RESPONSE_FIRST):
+		/*
+		 * This case can only happen if a send is restarted.  See
+		 * ipath_restart_rc().
+		 */
+		ipath_init_restart(qp, wqe);
+		/* FALLTHROUGH */
+	case OP(SEND_FIRST):
+		qp->s_state = OP(SEND_MIDDLE);
+		/* FALLTHROUGH */
+	case OP(SEND_MIDDLE):
+		bth2 = qp->s_psn++ & IPS_PSN_MASK;
+		if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+			qp->s_next_psn = qp->s_psn;
+		ss = &qp->s_sge;
+		len = qp->s_len;
+		if (len > pmtu) {
+			/*
+			 * Request an ACK every 1/2 MB to avoid retransmit
+			 * timeouts.
+			 */
+			if (((wqe->length - len) % (512 * 1024)) == 0)
+				bth2 |= 1 << 31;
+			len = pmtu;
+			break;
+		}
+		if (wqe->wr.opcode == IB_WR_SEND)
+			qp->s_state = OP(SEND_LAST);
+		else {
+			qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+			/* Immediate data comes after the BTH */
+			ohdr->u.imm_data = wqe->wr.imm_data;
+			hwords += 1;
+		}
+		if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+			bth0 |= 1 << 23;
+		bth2 |= 1 << 31;	/* Request ACK. */
+		qp->s_cur++;
+		if (qp->s_cur >= qp->s_size)
+			qp->s_cur = 0;
+		break;
+
+	case OP(RDMA_READ_RESPONSE_LAST):
+		/*
+		 * This case can only happen if a RDMA write is restarted.
+		 * See ipath_restart_rc().
+		 */
+		ipath_init_restart(qp, wqe);
+		/* FALLTHROUGH */
+	case OP(RDMA_WRITE_FIRST):
+		qp->s_state = OP(RDMA_WRITE_MIDDLE);
+		/* FALLTHROUGH */
+	case OP(RDMA_WRITE_MIDDLE):
+		bth2 = qp->s_psn++ & IPS_PSN_MASK;
+		if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+			qp->s_next_psn = qp->s_psn;
+		ss = &qp->s_sge;
+		len = qp->s_len;
+		if (len > pmtu) {
+			/*
+			 * Request an ACK every 1/2 MB to avoid retransmit
+			 * timeouts.
+			 */
+			if (((wqe->length - len) % (512 * 1024)) == 0)
+				bth2 |= 1 << 31;
+			len = pmtu;
+			break;
+		}
+		if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+			qp->s_state = OP(RDMA_WRITE_LAST);
+		else {
+			qp->s_state = OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+			/* Immediate data comes after the BTH */
+			ohdr->u.imm_data = wqe->wr.imm_data;
+			hwords += 1;
+			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+				bth0 |= 1 << 23;
+		}
+		bth2 |= 1 << 31;	/* Request ACK. */
+		qp->s_cur++;
+		if (qp->s_cur >= qp->s_size)
+			qp->s_cur = 0;
+		break;
+
+	case OP(RDMA_READ_RESPONSE_MIDDLE):
+		/*
+		 * This case can only happen if a RDMA read is restarted.
+		 * See ipath_restart_rc().
+		 */
+		ipath_init_restart(qp, wqe);
+		len = ((qp->s_psn - wqe->psn) & IPS_PSN_MASK) * pmtu;
+		ohdr->u.rc.reth.vaddr =
+			cpu_to_be64(wqe->wr.wr.rdma.remote_addr + len);
+		ohdr->u.rc.reth.rkey =
+			cpu_to_be32(wqe->wr.wr.rdma.rkey);
+		ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len);
+		qp->s_state = OP(RDMA_READ_REQUEST);
+		hwords += sizeof(ohdr->u.rc.reth) / 4;
+		bth2 = qp->s_psn++ & IPS_PSN_MASK;
+		if ((int)(qp->s_psn - qp->s_next_psn) > 0)
+			qp->s_next_psn = qp->s_psn;
+		ss = NULL;
+		len = 0;
+		qp->s_cur++;
+		if (qp->s_cur == qp->s_size)
+			qp->s_cur = 0;
+		break;
+
+	case OP(RDMA_READ_REQUEST):
+	case OP(COMPARE_SWAP):
+	case OP(FETCH_ADD):
+		/*
+		 * We shouldn't start anything new until this request is
+		 * finished.  The ACK will handle rescheduling us.  XXX The
+		 * number of outstanding ones is negotiated at connection
+		 * setup time (see pg. 258,289)?  XXX Also, if we support
+		 * multiple outstanding requests, we need to check the WQE
+		 * IB_SEND_FENCE flag and not send a new request if a RDMA
+		 * read or atomic is pending.
+		 */
+		goto done;
+	}
+	qp->s_len -= len;
+	qp->s_hdrwords = hwords;
+	qp->s_cur_sge = ss;
+	qp->s_cur_size = len;
+	*bth0p = bth0 | (qp->s_state << 24);
+	*bth2p = bth2;
+	return 1;
+
+done:
+	return 0;
+}
+
+static inline void ipath_make_rc_grh(struct ipath_qp *qp,
+				     struct ib_global_route *grh,
+				     u32 nwords)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+
+	/* GRH header size in 32-bit words. */
+	qp->s_hdrwords += 10;
+	qp->s_hdr.u.l.grh.version_tclass_flow =
+		cpu_to_be32((6 << 28) |
+			    (grh->traffic_class << 20) |
+			    grh->flow_label);
+	qp->s_hdr.u.l.grh.paylen =
+		cpu_to_be16(((qp->s_hdrwords - 12) + nwords +
+			     SIZE_OF_CRC) << 2);
+	/* next_hdr is defined by C8-7 in ch. 8.4.1 */
+	qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+	qp->s_hdr.u.l.grh.hop_limit = grh->hop_limit;
+	/* The SGID is 32-bit aligned. */
+	qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = dev->gid_prefix;
+	qp->s_hdr.u.l.grh.sgid.global.interface_id =
+		ipath_layer_get_guid(dev->dd);
+	qp->s_hdr.u.l.grh.dgid = grh->dgid;
+}
+
+/**
+ * ipath_do_rc_send - perform a send on an RC QP
+ * @data: contains a pointer to the QP
+ *
+ * Process entries in the send work queue until credit or queue is
+ * exhausted.  Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP s_lock, two threads could send
+ * packets out of order.
+ */
+void ipath_do_rc_send(unsigned long data)
+{
+	struct ipath_qp *qp = (struct ipath_qp *)data;
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	unsigned long flags;
+	u16 lrh0;
+	u32 nwords;
+	u32 extra_bytes;
+	u32 bth0;
+	u32 bth2;
+	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	struct ipath_other_headers *ohdr;
+
+	if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+		goto bail;
+
+	if (unlikely(qp->remote_ah_attr.dlid ==
+		     ipath_layer_get_lid(dev->dd))) {
+		struct ib_wc wc;
+
+		/*
+		 * Pass in an uninitialized ib_wc to be consistent with
+		 * other places where ipath_ruc_loopback() is called.
+		 */
+		ipath_ruc_loopback(qp, &wc);
+		goto clear;
+	}
+
+	ohdr = &qp->s_hdr.u.oth;
+	if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+		ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+	/* Check for a constructed packet to be sent. */
+	if (qp->s_hdrwords != 0) {
+		/*
+		 * If no PIO bufs are available, return.  An interrupt will
+		 * call ipath_ib_piobufavail() when one is available.
+		 */
+		_VERBS_INFO("h %u %p\n", qp->s_hdrwords, &qp->s_hdr);
+		_VERBS_INFO("d %u %p %u %p %u %u %u %u\n", qp->s_cur_size,
+			    qp->s_cur_sge->sg_list,
+			    qp->s_cur_sge->num_sge,
+			    qp->s_cur_sge->sge.vaddr,
+			    qp->s_cur_sge->sge.sge_length,
+			    qp->s_cur_sge->sge.length,
+			    qp->s_cur_sge->sge.m,
+			    qp->s_cur_sge->sge.n);
+		if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+				     (u32 *) &qp->s_hdr, qp->s_cur_size,
+				     qp->s_cur_sge)) {
+			ipath_no_bufs_available(qp, dev);
+			goto bail;
+		}
+		dev->n_unicast_xmit++;
+		/* Record that we sent the packet and s_hdr is empty. */
+		qp->s_hdrwords = 0;
+	}
+
+	/*
+	 * The lock is needed to synchronize between setting
+	 * qp->s_ack_state, resend timer, and post_send().
+	 */
+	spin_lock_irqsave(&qp->s_lock, flags);
+
+	/* Sending responses has higher priority over sending requests. */
+	if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+	    (bth0 = ipath_make_rc_ack(qp, ohdr, pmtu)) != 0)
+		bth2 = qp->s_ack_psn++ & IPS_PSN_MASK;
+	else if (!ipath_make_rc_req(qp, ohdr, pmtu, &bth0, &bth2))
+		goto done;
+
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+
+	/* Construct the header. */
+	extra_bytes = (4 - qp->s_cur_size) & 3;
+	nwords = (qp->s_cur_size + extra_bytes) >> 2;
+	lrh0 = IPS_LRH_BTH;
+	if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+		ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, nwords);
+		lrh0 = IPS_LRH_GRH;
+	}
+	lrh0 |= qp->remote_ah_attr.sl << 4;
+	qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+	qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+	qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords +
+				       SIZE_OF_CRC);
+	qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+	bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+	bth0 |= extra_bytes << 20;
+	ohdr->bth[0] = cpu_to_be32(bth0);
+	ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+	ohdr->bth[2] = cpu_to_be32(bth2);
+
+	/* Check for more work to do. */
+	goto again;
+
+done:
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+clear:
+	clear_bit(IPATH_S_BUSY, &qp->s_flags);
+bail:
+	return;
+}
+
+static void send_rc_ack(struct ipath_qp *qp)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	u16 lrh0;
+	u32 bth0;
+	struct ipath_other_headers *ohdr;
+
+	/* Construct the header. */
+	ohdr = &qp->s_hdr.u.oth;
+	lrh0 = IPS_LRH_BTH;
+	/* header size in 32-bit words LRH+BTH+AETH = (8+12+4)/4. */
+	qp->s_hdrwords = 6;
+	if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+		ipath_make_rc_grh(qp, &qp->remote_ah_attr.grh, 0);
+		ohdr = &qp->s_hdr.u.l.oth;
+		lrh0 = IPS_LRH_GRH;
+	}
+	bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+	ohdr->u.aeth = ipath_compute_aeth(qp);
+	if (qp->s_ack_state >= OP(COMPARE_SWAP)) {
+		bth0 |= IB_OPCODE_ATOMIC_ACKNOWLEDGE << 24;
+		ohdr->u.at.atomic_ack_eth = cpu_to_be64(qp->s_ack_atomic);
+		qp->s_hdrwords += sizeof(ohdr->u.at.atomic_ack_eth) / 4;
+	}
+	else
+		bth0 |= OP(ACKNOWLEDGE) << 24;
+	lrh0 |= qp->remote_ah_attr.sl << 4;
+	qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+	qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+	qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + SIZE_OF_CRC);
+	qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+	ohdr->bth[0] = cpu_to_be32(bth0);
+	ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+	ohdr->bth[2] = cpu_to_be32(qp->s_ack_psn & IPS_PSN_MASK);
+
+	/*
+	 * If we can send the ACK, clear the ACK state.
+	 */
+	if (ipath_verbs_send(dev->dd, qp->s_hdrwords, (u32 *) &qp->s_hdr,
+			     0, NULL) == 0) {
+		qp->s_ack_state = OP(ACKNOWLEDGE);
+		dev->n_rc_qacks++;
+		dev->n_unicast_xmit++;
+	}
+}
+
+/**
+ * ipath_restart_rc - back up requester to resend the last un-ACKed request
+ * @qp: the QP to restart
+ * @psn: packet sequence number for the request
+ * @wc: the work completion request
+ *
+ * The QP s_lock should be held.
+ */
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
+{
+	struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+	struct ipath_ibdev *dev;
+	u32 n;
+
+	/*
+	 * If there are no requests pending, we are done.
+	 */
+	if (ipath_cmp24(psn, qp->s_next_psn) >= 0 ||
+	    qp->s_last == qp->s_tail)
+		goto done;
+
+	if (qp->s_retry == 0) {
+		wc->wr_id = wqe->wr.wr_id;
+		wc->status = IB_WC_RETRY_EXC_ERR;
+		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		wc->vendor_err = 0;
+		wc->byte_len = 0;
+		wc->qp_num = qp->ibqp.qp_num;
+		wc->src_qp = qp->remote_qpn;
+		wc->pkey_index = 0;
+		wc->slid = qp->remote_ah_attr.dlid;
+		wc->sl = qp->remote_ah_attr.sl;
+		wc->dlid_path_bits = 0;
+		wc->port_num = 0;
+		ipath_sqerror_qp(qp, wc);
+		goto bail;
+	}
+	qp->s_retry--;
+
+	/*
+	 * Remove the QP from the timeout queue.
+	 * Note: it may already have been removed by ipath_ib_timer().
+	 */
+	dev = to_idev(qp->ibqp.device);
+	spin_lock(&dev->pending_lock);
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	spin_unlock(&dev->pending_lock);
+
+	if (wqe->wr.opcode == IB_WR_RDMA_READ)
+		dev->n_rc_resends++;
+	else
+		dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+	/*
+	 * If we are starting the request from the beginning, let the normal
+	 * send code handle initialization.
+	 */
+	qp->s_cur = qp->s_last;
+	if (ipath_cmp24(psn, wqe->psn) <= 0) {
+		qp->s_state = OP(SEND_LAST);
+		qp->s_psn = wqe->psn;
+	} else {
+		n = qp->s_cur;
+		for (;;) {
+			if (++n == qp->s_size)
+				n = 0;
+			if (n == qp->s_tail) {
+				if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+					qp->s_cur = n;
+					wqe = get_swqe_ptr(qp, n);
+				}
+				break;
+			}
+			wqe = get_swqe_ptr(qp, n);
+			if (ipath_cmp24(psn, wqe->psn) < 0)
+				break;
+			qp->s_cur = n;
+		}
+		qp->s_psn = psn;
+
+		/*
+		 * Reset the state to restart in the middle of a request.
+		 * Don't change the s_sge, s_cur_sge, or s_cur_size.
+		 * See ipath_do_rc_send().
+		 */
+		switch (wqe->wr.opcode) {
+		case IB_WR_SEND:
+		case IB_WR_SEND_WITH_IMM:
+			qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+			break;
+
+		case IB_WR_RDMA_WRITE:
+		case IB_WR_RDMA_WRITE_WITH_IMM:
+			qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+			break;
+
+		case IB_WR_RDMA_READ:
+			qp->s_state =
+				OP(RDMA_READ_RESPONSE_MIDDLE);
+			break;
+
+		default:
+			/*
+			 * This case shouldn't happen since its only
+			 * one PSN per req.
+			 */
+			qp->s_state = OP(SEND_LAST);
+		}
+	}
+
+done:
+	tasklet_hi_schedule(&qp->s_task);
+
+bail:
+	return;
+}
+
+/**
+ * reset_psn - reset the QP state to send starting from PSN
+ * @qp: the QP
+ * @psn: the packet sequence number to restart at
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ */
+static void reset_psn(struct ipath_qp *qp, u32 psn)
+{
+	struct ipath_swqe *wqe;
+	u32 n;
+
+	n = qp->s_cur;
+	wqe = get_swqe_ptr(qp, n);
+	for (;;) {
+		if (++n == qp->s_size)
+			n = 0;
+		if (n == qp->s_tail) {
+			if (ipath_cmp24(psn, qp->s_next_psn) >= 0) {
+				qp->s_cur = n;
+				wqe = get_swqe_ptr(qp, n);
+			}
+			break;
+		}
+		wqe = get_swqe_ptr(qp, n);
+		if (ipath_cmp24(psn, wqe->psn) < 0)
+			break;
+		qp->s_cur = n;
+	}
+	qp->s_psn = psn;
+
+	/*
+	 * Set the state to restart in the middle of a
+	 * request.  Don't change the s_sge, s_cur_sge, or
+	 * s_cur_size.  See ipath_do_rc_send().
+	 */
+	switch (wqe->wr.opcode) {
+	case IB_WR_SEND:
+	case IB_WR_SEND_WITH_IMM:
+		qp->s_state = OP(RDMA_READ_RESPONSE_FIRST);
+		break;
+
+	case IB_WR_RDMA_WRITE:
+	case IB_WR_RDMA_WRITE_WITH_IMM:
+		qp->s_state = OP(RDMA_READ_RESPONSE_LAST);
+		break;
+
+	case IB_WR_RDMA_READ:
+		qp->s_state = OP(RDMA_READ_RESPONSE_MIDDLE);
+		break;
+
+	default:
+		/*
+		 * This case shouldn't happen since its only
+		 * one PSN per req.
+		 */
+		qp->s_state = OP(SEND_LAST);
+	}
+}
+
+/**
+ * do_rc_ack - process an incoming RC ACK
+ * @qp: the QP the ACK came in on
+ * @psn: the packet sequence number of the ACK
+ * @opcode: the opcode of the request that resulted in the ACK
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC ACK
+ * for the given QP.
+ * Called at interrupt level with the QP s_lock held.
+ * Returns 1 if OK, 0 if current operation should be aborted (NAK).
+ */
+static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ib_wc wc;
+	struct ipath_swqe *wqe;
+	int ret = 0;
+
+	/*
+	 * Remove the QP from the timeout queue (or RNR timeout queue).
+	 * If ipath_ib_timer() has already removed it,
+	 * it's OK since we hold the QP s_lock and ipath_restart_rc()
+	 * just won't find anything to restart if we ACK everything.
+	 */
+	spin_lock(&dev->pending_lock);
+	if (qp->timerwait.next != LIST_POISON1)
+		list_del(&qp->timerwait);
+	spin_unlock(&dev->pending_lock);
+
+	/*
+	 * Note that NAKs implicitly ACK outstanding SEND and RDMA write
+	 * requests and implicitly NAK RDMA read and atomic requests issued
+	 * before the NAK'ed request.  The MSN won't include the NAK'ed
+	 * request but will include an ACK'ed request(s).
+	 */
+	wqe = get_swqe_ptr(qp, qp->s_last);
+
+	/* Nothing is pending to ACK/NAK. */
+	if (qp->s_last == qp->s_tail)
+		goto bail;
+
+	/*
+	 * The MSN might be for a later WQE than the PSN indicates so
+	 * only complete WQEs that the PSN finishes.
+	 */
+	while (ipath_cmp24(psn, wqe->lpsn) >= 0) {
+		/* If we are ACKing a WQE, the MSN should be >= the SSN. */
+		if (ipath_cmp24(aeth, wqe->ssn) < 0)
+			break;
+		/*
+		 * If this request is a RDMA read or atomic, and the ACK is
+		 * for a later operation, this ACK NAKs the RDMA read or
+		 * atomic.  In other words, only a RDMA_READ_LAST or ONLY
+		 * can ACK a RDMA read and likewise for atomic ops.  Note
+		 * that the NAK case can only happen if relaxed ordering is
+		 * used and requests are sent after an RDMA read or atomic
+		 * is sent but before the response is received.
+		 */
+		if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
+		     opcode != OP(RDMA_READ_RESPONSE_LAST)) ||
+		    ((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+		      wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
+		     (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
+		      ipath_cmp24(wqe->psn, psn) != 0))) {
+			/*
+			 * The last valid PSN seen is the previous
+			 * request's.
+			 */
+			qp->s_last_psn = wqe->psn - 1;
+			/* Retry this request. */
+			ipath_restart_rc(qp, wqe->psn, &wc);
+			/*
+			 * No need to process the ACK/NAK since we are
+			 * restarting an earlier request.
+			 */
+			goto bail;
+		}
+		/* Post a send completion queue entry if requested. */
+		if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+			wc.wr_id = wqe->wr.wr_id;
+			wc.status = IB_WC_SUCCESS;
+			wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+			wc.vendor_err = 0;
+			wc.byte_len = wqe->length;
+			wc.qp_num = qp->ibqp.qp_num;
+			wc.src_qp = qp->remote_qpn;
+			wc.pkey_index = 0;
+			wc.slid = qp->remote_ah_attr.dlid;
+			wc.sl = qp->remote_ah_attr.sl;
+			wc.dlid_path_bits = 0;
+			wc.port_num = 0;
+			ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+		}
+		qp->s_retry = qp->s_retry_cnt;
+		/*
+		 * If we are completing a request which is in the process of
+		 * being resent, we can stop resending it since we know the
+		 * responder has already seen it.
+		 */
+		if (qp->s_last == qp->s_cur) {
+			if (++qp->s_cur >= qp->s_size)
+				qp->s_cur = 0;
+			wqe = get_swqe_ptr(qp, qp->s_cur);
+			qp->s_state = OP(SEND_LAST);
+			qp->s_psn = wqe->psn;
+		}
+		if (++qp->s_last >= qp->s_size)
+			qp->s_last = 0;
+		wqe = get_swqe_ptr(qp, qp->s_last);
+		if (qp->s_last == qp->s_tail)
+			break;
+	}
+
+	switch (aeth >> 29) {
+	case 0:		/* ACK */
+		dev->n_rc_acks++;
+		/* If this is a partial ACK, reset the retransmit timer. */
+		if (qp->s_last != qp->s_tail) {
+			spin_lock(&dev->pending_lock);
+			list_add_tail(&qp->timerwait,
+				      &dev->pending[dev->pending_index]);
+			spin_unlock(&dev->pending_lock);
+		}
+		ipath_get_credit(qp, aeth);
+		qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+		qp->s_retry = qp->s_retry_cnt;
+		qp->s_last_psn = psn;
+		ret = 1;
+		goto bail;
+
+	case 1:		/* RNR NAK */
+		dev->n_rnr_naks++;
+		if (qp->s_rnr_retry == 0) {
+			if (qp->s_last == qp->s_tail)
+				goto bail;
+
+			wc.status = IB_WC_RNR_RETRY_EXC_ERR;
+			goto class_b;
+		}
+		if (qp->s_rnr_retry_cnt < 7)
+			qp->s_rnr_retry--;
+		if (qp->s_last == qp->s_tail)
+			goto bail;
+
+		/* The last valid PSN seen is the previous request's. */
+		qp->s_last_psn = wqe->psn - 1;
+
+		dev->n_rc_resends += (int)qp->s_psn - (int)psn;
+
+		/*
+		 * If we are starting the request from the beginning, let
+		 * the normal send code handle initialization.
+		 */
+		qp->s_cur = qp->s_last;
+		wqe = get_swqe_ptr(qp, qp->s_cur);
+		if (ipath_cmp24(psn, wqe->psn) <= 0) {
+			qp->s_state = OP(SEND_LAST);
+			qp->s_psn = wqe->psn;
+		} else
+			reset_psn(qp, psn);
+
+		qp->s_rnr_timeout =
+			ib_ipath_rnr_table[(aeth >> IPS_AETH_CREDIT_SHIFT) &
+					   IPS_AETH_CREDIT_MASK];
+		ipath_insert_rnr_queue(qp);
+		goto bail;
+
+	case 3:		/* NAK */
+		/* The last valid PSN seen is the previous request's. */
+		if (qp->s_last != qp->s_tail)
+			qp->s_last_psn = wqe->psn - 1;
+		switch ((aeth >> IPS_AETH_CREDIT_SHIFT) &
+			IPS_AETH_CREDIT_MASK) {
+		case 0:	/* PSN sequence error */
+			dev->n_seq_naks++;
+			/*
+			 * Back up to the responder's expected PSN.  XXX
+			 * Note that we might get a NAK in the middle of an
+			 * RDMA READ response which terminates the RDMA
+			 * READ.
+			 */
+			if (qp->s_last == qp->s_tail)
+				break;
+
+			if (ipath_cmp24(psn, wqe->psn) < 0)
+				break;
+
+			/* Retry the request. */
+			ipath_restart_rc(qp, psn, &wc);
+			break;
+
+		case 1:	/* Invalid Request */
+			wc.status = IB_WC_REM_INV_REQ_ERR;
+			dev->n_other_naks++;
+			goto class_b;
+
+		case 2:	/* Remote Access Error */
+			wc.status = IB_WC_REM_ACCESS_ERR;
+			dev->n_other_naks++;
+			goto class_b;
+
+		case 3:	/* Remote Operation Error */
+			wc.status = IB_WC_REM_OP_ERR;
+			dev->n_other_naks++;
+		class_b:
+			wc.wr_id = wqe->wr.wr_id;
+			wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+			wc.vendor_err = 0;
+			wc.byte_len = 0;
+			wc.qp_num = qp->ibqp.qp_num;
+			wc.src_qp = qp->remote_qpn;
+			wc.pkey_index = 0;
+			wc.slid = qp->remote_ah_attr.dlid;
+			wc.sl = qp->remote_ah_attr.sl;
+			wc.dlid_path_bits = 0;
+			wc.port_num = 0;
+			ipath_sqerror_qp(qp, &wc);
+			break;
+
+		default:
+			/* Ignore other reserved NAK error codes */
+			goto reserved;
+		}
+		qp->s_rnr_retry = qp->s_rnr_retry_cnt;
+		goto bail;
+
+	default:		/* 2: reserved */
+	reserved:
+		/* Ignore reserved NAK codes. */
+		goto bail;
+	}
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_rc_rcv_resp - process an incoming RC response packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @hdrsize: the header length
+ * @pmtu: the path MTU
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an incoming RC response
+ * packet for the given QP.
+ * Called at interrupt level.
+ */
+static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
+				     struct ipath_other_headers *ohdr,
+				     void *data, u32 tlen,
+				     struct ipath_qp *qp,
+				     u32 opcode,
+				     u32 psn, u32 hdrsize, u32 pmtu,
+				     int header_in_data)
+{
+	unsigned long flags;
+	struct ib_wc wc;
+	int diff;
+	u32 pad;
+	u32 aeth;
+
+	spin_lock_irqsave(&qp->s_lock, flags);
+
+	/* Ignore invalid responses. */
+	if (ipath_cmp24(psn, qp->s_next_psn) >= 0)
+		goto ack_done;
+
+	/* Ignore duplicate responses. */
+	diff = ipath_cmp24(psn, qp->s_last_psn);
+	if (unlikely(diff <= 0)) {
+		/* Update credits for "ghost" ACKs */
+		if (diff == 0 && opcode == OP(ACKNOWLEDGE)) {
+			if (!header_in_data)
+				aeth = be32_to_cpu(ohdr->u.aeth);
+			else {
+				aeth = be32_to_cpu(((__be32 *) data)[0]);
+				data += sizeof(__be32);
+			}
+			if ((aeth >> 29) == 0)
+				ipath_get_credit(qp, aeth);
+		}
+		goto ack_done;
+	}
+
+	switch (opcode) {
+	case OP(ACKNOWLEDGE):
+	case OP(ATOMIC_ACKNOWLEDGE):
+	case OP(RDMA_READ_RESPONSE_FIRST):
+		if (!header_in_data)
+			aeth = be32_to_cpu(ohdr->u.aeth);
+		else {
+			aeth = be32_to_cpu(((__be32 *) data)[0]);
+			data += sizeof(__be32);
+		}
+		if (opcode == OP(ATOMIC_ACKNOWLEDGE))
+			*(u64 *) qp->s_sge.sge.vaddr = *(u64 *) data;
+		if (!do_rc_ack(qp, aeth, psn, opcode) ||
+		    opcode != OP(RDMA_READ_RESPONSE_FIRST))
+			goto ack_done;
+		hdrsize += 4;
+		/*
+		 * do_rc_ack() has already checked the PSN so skip
+		 * the sequence check.
+		 */
+		goto rdma_read;
+
+	case OP(RDMA_READ_RESPONSE_MIDDLE):
+		/* no AETH, no ACK */
+		if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+			dev->n_rdma_seq++;
+			ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+			goto ack_done;
+		}
+	rdma_read:
+	if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+		goto ack_done;
+	if (unlikely(tlen != (hdrsize + pmtu + 4)))
+		goto ack_done;
+	if (unlikely(pmtu >= qp->s_len))
+		goto ack_done;
+	/* We got a response so update the timeout. */
+	if (unlikely(qp->s_last == qp->s_tail ||
+		     get_swqe_ptr(qp, qp->s_last)->wr.opcode !=
+		     IB_WR_RDMA_READ))
+		goto ack_done;
+	spin_lock(&dev->pending_lock);
+	if (qp->s_rnr_timeout == 0 &&
+	    qp->timerwait.next != LIST_POISON1)
+		list_move_tail(&qp->timerwait,
+			       &dev->pending[dev->pending_index]);
+	spin_unlock(&dev->pending_lock);
+	/*
+	 * Update the RDMA receive state but do the copy w/o holding the
+	 * locks and blocking interrupts.  XXX Yet another place that
+	 * affects relaxed RDMA order since we don't want s_sge modified.
+	 */
+	qp->s_len -= pmtu;
+	qp->s_last_psn = psn;
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+	ipath_copy_sge(&qp->s_sge, data, pmtu);
+	goto bail;
+
+	case OP(RDMA_READ_RESPONSE_LAST):
+		/* ACKs READ req. */
+		if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
+			dev->n_rdma_seq++;
+			ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+			goto ack_done;
+		}
+		/* FALLTHROUGH */
+	case OP(RDMA_READ_RESPONSE_ONLY):
+		if (unlikely(qp->s_state != OP(RDMA_READ_REQUEST)))
+			goto ack_done;
+		/*
+		 * Get the number of bytes the message was padded by.
+		 */
+		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+		/*
+		 * Check that the data size is >= 1 && <= pmtu.
+		 * Remember to account for the AETH header (4) and
+		 * ICRC (4).
+		 */
+		if (unlikely(tlen <= (hdrsize + pad + 8))) {
+			/*
+			 * XXX Need to generate an error CQ
+			 * entry.
+			 */
+			goto ack_done;
+		}
+		tlen -= hdrsize + pad + 8;
+		if (unlikely(tlen != qp->s_len)) {
+			/*
+			 * XXX Need to generate an error CQ
+			 * entry.
+			 */
+			goto ack_done;
+		}
+		if (!header_in_data)
+			aeth = be32_to_cpu(ohdr->u.aeth);
+		else {
+			aeth = be32_to_cpu(((__be32 *) data)[0]);
+			data += sizeof(__be32);
+		}
+		ipath_copy_sge(&qp->s_sge, data, tlen);
+		if (do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST))) {
+			/*
+			 * Change the state so we contimue
+			 * processing new requests.
+			 */
+			qp->s_state = OP(SEND_LAST);
+		}
+		goto ack_done;
+	}
+
+ack_done:
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+bail:
+	return;
+}
+
+/**
+ * ipath_rc_rcv_error - process an incoming duplicate or error RC packet
+ * @dev: the device this packet came in on
+ * @ohdr: the other headers for this packet
+ * @data: the packet data
+ * @qp: the QP for this packet
+ * @opcode: the opcode for this packet
+ * @psn: the packet sequence number for this packet
+ * @diff: the difference between the PSN and the expected PSN
+ * @header_in_data: true if part of the header data is in the data buffer
+ *
+ * This is called from ipath_rc_rcv() to process an unexpected
+ * incoming RC packet for the given QP.
+ * Called at interrupt level.
+ * Return 1 if no more processing is needed; otherwise return 0 to
+ * schedule a response to be sent and the s_lock unlocked.
+ */
+static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
+				     struct ipath_other_headers *ohdr,
+				     void *data,
+				     struct ipath_qp *qp,
+				     u32 opcode,
+				     u32 psn,
+				     int diff,
+				     int header_in_data)
+{
+	struct ib_reth *reth;
+
+	if (diff > 0) {
+		/*
+		 * Packet sequence error.
+		 * A NAK will ACK earlier sends and RDMA writes.
+		 * Don't queue the NAK if a RDMA read, atomic, or
+		 * NAK is pending though.
+		 */
+		spin_lock(&qp->s_lock);
+		if ((qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+		     qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) ||
+		    qp->s_nak_state != 0) {
+			spin_unlock(&qp->s_lock);
+			goto done;
+		}
+		qp->s_ack_state = OP(SEND_ONLY);
+		qp->s_nak_state = IB_NAK_PSN_ERROR;
+		/* Use the expected PSN. */
+		qp->s_ack_psn = qp->r_psn;
+		goto resched;
+	}
+
+	/*
+	 * Handle a duplicate request.  Don't re-execute SEND, RDMA
+	 * write or atomic op.  Don't NAK errors, just silently drop
+	 * the duplicate request.  Note that r_sge, r_len, and
+	 * r_rcv_len may be in use so don't modify them.
+	 *
+	 * We are supposed to ACK the earliest duplicate PSN but we
+	 * can coalesce an outstanding duplicate ACK.  We have to
+	 * send the earliest so that RDMA reads can be restarted at
+	 * the requester's expected PSN.
+	 */
+	spin_lock(&qp->s_lock);
+	if (qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE &&
+	    ipath_cmp24(psn, qp->s_ack_psn) >= 0) {
+		if (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST)
+			qp->s_ack_psn = psn;
+		spin_unlock(&qp->s_lock);
+		goto done;
+	}
+	switch (opcode) {
+	case OP(RDMA_READ_REQUEST):
+		/*
+		 * We have to be careful to not change s_rdma_sge
+		 * while ipath_do_rc_send() is using it and not
+		 * holding the s_lock.
+		 */
+		if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+		    qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+			spin_unlock(&qp->s_lock);
+			dev->n_rdma_dup_busy++;
+			goto done;
+		}
+		/* RETH comes after BTH */
+		if (!header_in_data)
+			reth = &ohdr->u.rc.reth;
+		else {
+			reth = (struct ib_reth *)data;
+			data += sizeof(*reth);
+		}
+		qp->s_rdma_len = be32_to_cpu(reth->length);
+		if (qp->s_rdma_len != 0) {
+			u32 rkey = be32_to_cpu(reth->rkey);
+			u64 vaddr = be64_to_cpu(reth->vaddr);
+			int ok;
+
+			/*
+			 * Address range must be a subset of the original
+			 * request and start on pmtu boundaries.
+			 */
+			ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+					   qp->s_rdma_len, vaddr, rkey,
+					   IB_ACCESS_REMOTE_READ);
+			if (unlikely(!ok))
+				goto done;
+		} else {
+			qp->s_rdma_sge.sg_list = NULL;
+			qp->s_rdma_sge.num_sge = 0;
+			qp->s_rdma_sge.sge.mr = NULL;
+			qp->s_rdma_sge.sge.vaddr = NULL;
+			qp->s_rdma_sge.sge.length = 0;
+			qp->s_rdma_sge.sge.sge_length = 0;
+		}
+		break;
+
+	case OP(COMPARE_SWAP):
+	case OP(FETCH_ADD):
+		/*
+		 * Check for the PSN of the last atomic operations
+		 * performed and resend the result if found.
+		 */
+		if ((psn & IPS_PSN_MASK) != qp->r_atomic_psn) {
+			spin_unlock(&qp->s_lock);
+			goto done;
+		}
+		qp->s_ack_atomic = qp->r_atomic_data;
+		break;
+	}
+	qp->s_ack_state = opcode;
+	qp->s_nak_state = 0;
+	qp->s_ack_psn = psn;
+resched:
+	return 0;
+
+done:
+	return 1;
+}
+
+/**
+ * ipath_rc_rcv - process an incoming RC packet
+ * @dev: the device this packet came in on
+ * @hdr: the header of this packet
+ * @has_grh: true if the header has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP for this packet
+ *
+ * This is called from ipath_qp_rcv() to process an incoming RC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+	struct ipath_other_headers *ohdr;
+	u32 opcode;
+	u32 hdrsize;
+	u32 psn;
+	u32 pad;
+	unsigned long flags;
+	struct ib_wc wc;
+	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	int diff;
+	struct ib_reth *reth;
+	int header_in_data;
+
+	/* Check for GRH */
+	if (!has_grh) {
+		ohdr = &hdr->u.oth;
+		hdrsize = 8 + 12;	/* LRH + BTH */
+		psn = be32_to_cpu(ohdr->bth[2]);
+		header_in_data = 0;
+	} else {
+		ohdr = &hdr->u.l.oth;
+		hdrsize = 8 + 40 + 12;	/* LRH + GRH + BTH */
+		/*
+		 * The header with GRH is 60 bytes and the core driver sets
+		 * the eager header buffer size to 56 bytes so the last 4
+		 * bytes of the BTH header (PSN) is in the data buffer.
+		 */
+		header_in_data =
+			ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+		if (header_in_data) {
+			psn = be32_to_cpu(((__be32 *) data)[0]);
+			data += sizeof(__be32);
+		} else
+			psn = be32_to_cpu(ohdr->bth[2]);
+	}
+	/*
+	 * The opcode is in the low byte when its in network order
+	 * (top byte when in host order).
+	 */
+	opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+	/*
+	 * Process responses (ACKs) before anything else.  Note that the
+	 * packet sequence number will be for something in the send work
+	 * queue rather than the expected receive packet sequence number.
+	 * In other words, this QP is the requester.
+	 */
+	if (opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
+	    opcode <= OP(ATOMIC_ACKNOWLEDGE)) {
+		ipath_rc_rcv_resp(dev, ohdr, data, tlen, qp, opcode, psn,
+				  hdrsize, pmtu, header_in_data);
+		goto bail;
+	}
+
+	spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+	/* Compute 24 bits worth of difference. */
+	diff = ipath_cmp24(psn, qp->r_psn);
+	if (unlikely(diff)) {
+		if (ipath_rc_rcv_error(dev, ohdr, data, qp, opcode,
+				       psn, diff, header_in_data))
+			goto done;
+		goto resched;
+	}
+
+	/* Check for opcode sequence errors. */
+	switch (qp->r_state) {
+	case OP(SEND_FIRST):
+	case OP(SEND_MIDDLE):
+		if (opcode == OP(SEND_MIDDLE) ||
+		    opcode == OP(SEND_LAST) ||
+		    opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+			break;
+	nack_inv:
+	/*
+	 * A NAK will ACK earlier sends and RDMA writes.  Don't queue the
+	 * NAK if a RDMA read, atomic, or NAK is pending though.
+	 */
+	spin_lock(&qp->s_lock);
+	if (qp->s_ack_state >= OP(RDMA_READ_REQUEST) &&
+	    qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+		spin_unlock(&qp->s_lock);
+		goto done;
+	}
+	/* XXX Flush WQEs */
+	qp->state = IB_QPS_ERR;
+	qp->s_ack_state = OP(SEND_ONLY);
+	qp->s_nak_state = IB_NAK_INVALID_REQUEST;
+	qp->s_ack_psn = qp->r_psn;
+	goto resched;
+
+	case OP(RDMA_WRITE_FIRST):
+	case OP(RDMA_WRITE_MIDDLE):
+		if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+		    opcode == OP(RDMA_WRITE_LAST) ||
+		    opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+			break;
+		goto nack_inv;
+
+	case OP(RDMA_READ_REQUEST):
+	case OP(COMPARE_SWAP):
+	case OP(FETCH_ADD):
+		/*
+		 * Drop all new requests until a response has been sent.  A
+		 * new request then ACKs the RDMA response we sent.  Relaxed
+		 * ordering would allow new requests to be processed but we
+		 * would need to keep a queue of rwqe's for all that are in
+		 * progress.  Note that we can't RNR NAK this request since
+		 * the RDMA READ or atomic response is already queued to be
+		 * sent (unless we implement a response send queue).
+		 */
+		goto done;
+
+	default:
+		if (opcode == OP(SEND_MIDDLE) ||
+		    opcode == OP(SEND_LAST) ||
+		    opcode == OP(SEND_LAST_WITH_IMMEDIATE) ||
+		    opcode == OP(RDMA_WRITE_MIDDLE) ||
+		    opcode == OP(RDMA_WRITE_LAST) ||
+		    opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+			goto nack_inv;
+		break;
+	}
+
+	wc.imm_data = 0;
+	wc.wc_flags = 0;
+
+	/* OK, process the packet. */
+	switch (opcode) {
+	case OP(SEND_FIRST):
+		if (!ipath_get_rwqe(qp, 0)) {
+		rnr_nak:
+			/*
+			 * A RNR NAK will ACK earlier sends and RDMA writes.
+			 * Don't queue the NAK if a RDMA read or atomic
+			 * is pending though.
+			 */
+			spin_lock(&qp->s_lock);
+			if (qp->s_ack_state >=
+			    OP(RDMA_READ_REQUEST) &&
+			    qp->s_ack_state != IB_OPCODE_ACKNOWLEDGE) {
+				spin_unlock(&qp->s_lock);
+				goto done;
+			}
+			qp->s_ack_state = OP(SEND_ONLY);
+			qp->s_nak_state = IB_RNR_NAK | qp->s_min_rnr_timer;
+			qp->s_ack_psn = qp->r_psn;
+			goto resched;
+		}
+		qp->r_rcv_len = 0;
+		/* FALLTHROUGH */
+	case OP(SEND_MIDDLE):
+	case OP(RDMA_WRITE_MIDDLE):
+	send_middle:
+		/* Check for invalid length PMTU or posted rwqe len. */
+		if (unlikely(tlen != (hdrsize + pmtu + 4)))
+			goto nack_inv;
+		qp->r_rcv_len += pmtu;
+		if (unlikely(qp->r_rcv_len > qp->r_len))
+			goto nack_inv;
+		ipath_copy_sge(&qp->r_sge, data, pmtu);
+		break;
+
+	case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+		/* consume RWQE */
+		if (!ipath_get_rwqe(qp, 1))
+			goto rnr_nak;
+		goto send_last_imm;
+
+	case OP(SEND_ONLY):
+	case OP(SEND_ONLY_WITH_IMMEDIATE):
+		if (!ipath_get_rwqe(qp, 0))
+			goto rnr_nak;
+		qp->r_rcv_len = 0;
+		if (opcode == OP(SEND_ONLY))
+			goto send_last;
+		/* FALLTHROUGH */
+	case OP(SEND_LAST_WITH_IMMEDIATE):
+	send_last_imm:
+		if (header_in_data) {
+			wc.imm_data = *(__be32 *) data;
+			data += sizeof(__be32);
+		} else {
+			/* Immediate data comes after BTH */
+			wc.imm_data = ohdr->u.imm_data;
+		}
+		hdrsize += 4;
+		wc.wc_flags = IB_WC_WITH_IMM;
+		/* FALLTHROUGH */
+	case OP(SEND_LAST):
+	case OP(RDMA_WRITE_LAST):
+	send_last:
+		/* Get the number of bytes the message was padded by. */
+		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+		/* Check for invalid length. */
+		/* XXX LAST len should be >= 1 */
+		if (unlikely(tlen < (hdrsize + pad + 4)))
+			goto nack_inv;
+		/* Don't count the CRC. */
+		tlen -= (hdrsize + pad + 4);
+		wc.byte_len = tlen + qp->r_rcv_len;
+		if (unlikely(wc.byte_len > qp->r_len))
+			goto nack_inv;
+		ipath_copy_sge(&qp->r_sge, data, tlen);
+		atomic_inc(&qp->msn);
+		if (opcode == OP(RDMA_WRITE_LAST) ||
+		    opcode == OP(RDMA_WRITE_ONLY))
+			break;
+		wc.wr_id = qp->r_wr_id;
+		wc.status = IB_WC_SUCCESS;
+		wc.opcode = IB_WC_RECV;
+		wc.vendor_err = 0;
+		wc.qp_num = qp->ibqp.qp_num;
+		wc.src_qp = qp->remote_qpn;
+		wc.pkey_index = 0;
+		wc.slid = qp->remote_ah_attr.dlid;
+		wc.sl = qp->remote_ah_attr.sl;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		/* Signal completion event if the solicited bit is set. */
+		ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+			       (ohdr->bth[0] &
+				__constant_cpu_to_be32(1 << 23)) != 0);
+		break;
+
+	case OP(RDMA_WRITE_FIRST):
+	case OP(RDMA_WRITE_ONLY):
+	case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+		/* consume RWQE */
+		/* RETH comes after BTH */
+		if (!header_in_data)
+			reth = &ohdr->u.rc.reth;
+		else {
+			reth = (struct ib_reth *)data;
+			data += sizeof(*reth);
+		}
+		hdrsize += sizeof(*reth);
+		qp->r_len = be32_to_cpu(reth->length);
+		qp->r_rcv_len = 0;
+		if (qp->r_len != 0) {
+			u32 rkey = be32_to_cpu(reth->rkey);
+			u64 vaddr = be64_to_cpu(reth->vaddr);
+			int ok;
+
+			/* Check rkey & NAK */
+			ok = ipath_rkey_ok(dev, &qp->r_sge,
+					   qp->r_len, vaddr, rkey,
+					   IB_ACCESS_REMOTE_WRITE);
+			if (unlikely(!ok)) {
+			nack_acc:
+				/*
+				 * A NAK will ACK earlier sends and RDMA
+				 * writes.  Don't queue the NAK if a RDMA
+				 * read, atomic, or NAK is pending though.
+				 */
+				spin_lock(&qp->s_lock);
+				if (qp->s_ack_state >=
+				    OP(RDMA_READ_REQUEST) &&
+				    qp->s_ack_state !=
+				    IB_OPCODE_ACKNOWLEDGE) {
+					spin_unlock(&qp->s_lock);
+					goto done;
+				}
+				/* XXX Flush WQEs */
+				qp->state = IB_QPS_ERR;
+				qp->s_ack_state = OP(RDMA_WRITE_ONLY);
+				qp->s_nak_state =
+					IB_NAK_REMOTE_ACCESS_ERROR;
+				qp->s_ack_psn = qp->r_psn;
+				goto resched;
+			}
+		} else {
+			qp->r_sge.sg_list = NULL;
+			qp->r_sge.sge.mr = NULL;
+			qp->r_sge.sge.vaddr = NULL;
+			qp->r_sge.sge.length = 0;
+			qp->r_sge.sge.sge_length = 0;
+		}
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_WRITE)))
+			goto nack_acc;
+		if (opcode == OP(RDMA_WRITE_FIRST))
+			goto send_middle;
+		else if (opcode == OP(RDMA_WRITE_ONLY))
+			goto send_last;
+		if (!ipath_get_rwqe(qp, 1))
+			goto rnr_nak;
+		goto send_last_imm;
+
+	case OP(RDMA_READ_REQUEST):
+		/* RETH comes after BTH */
+		if (!header_in_data)
+			reth = &ohdr->u.rc.reth;
+		else {
+			reth = (struct ib_reth *)data;
+			data += sizeof(*reth);
+		}
+		spin_lock(&qp->s_lock);
+		if (qp->s_ack_state != OP(ACKNOWLEDGE) &&
+		    qp->s_ack_state >= IB_OPCODE_RDMA_READ_REQUEST) {
+			spin_unlock(&qp->s_lock);
+			goto done;
+		}
+		qp->s_rdma_len = be32_to_cpu(reth->length);
+		if (qp->s_rdma_len != 0) {
+			u32 rkey = be32_to_cpu(reth->rkey);
+			u64 vaddr = be64_to_cpu(reth->vaddr);
+			int ok;
+
+			/* Check rkey & NAK */
+			ok = ipath_rkey_ok(dev, &qp->s_rdma_sge,
+					   qp->s_rdma_len, vaddr, rkey,
+					   IB_ACCESS_REMOTE_READ);
+			if (unlikely(!ok)) {
+				spin_unlock(&qp->s_lock);
+				goto nack_acc;
+			}
+			/*
+			 * Update the next expected PSN.  We add 1 later
+			 * below, so only add the remainder here.
+			 */
+			if (qp->s_rdma_len > pmtu)
+				qp->r_psn += (qp->s_rdma_len - 1) / pmtu;
+		} else {
+			qp->s_rdma_sge.sg_list = NULL;
+			qp->s_rdma_sge.num_sge = 0;
+			qp->s_rdma_sge.sge.mr = NULL;
+			qp->s_rdma_sge.sge.vaddr = NULL;
+			qp->s_rdma_sge.sge.length = 0;
+			qp->s_rdma_sge.sge.sge_length = 0;
+		}
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_READ)))
+			goto nack_acc;
+		/*
+		 * We need to increment the MSN here instead of when we
+		 * finish sending the result since a duplicate request would
+		 * increment it more than once.
+		 */
+		atomic_inc(&qp->msn);
+		qp->s_ack_state = opcode;
+		qp->s_nak_state = 0;
+		qp->s_ack_psn = psn;
+		qp->r_psn++;
+		qp->r_state = opcode;
+		goto rdmadone;
+
+	case OP(COMPARE_SWAP):
+	case OP(FETCH_ADD): {
+		struct ib_atomic_eth *ateth;
+		u64 vaddr;
+		u64 sdata;
+		u32 rkey;
+
+		if (!header_in_data)
+			ateth = &ohdr->u.atomic_eth;
+		else {
+			ateth = (struct ib_atomic_eth *)data;
+			data += sizeof(*ateth);
+		}
+		vaddr = be64_to_cpu(ateth->vaddr);
+		if (unlikely(vaddr & (sizeof(u64) - 1)))
+			goto nack_inv;
+		rkey = be32_to_cpu(ateth->rkey);
+		/* Check rkey & NAK */
+		if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge,
+					    sizeof(u64), vaddr, rkey,
+					    IB_ACCESS_REMOTE_ATOMIC)))
+			goto nack_acc;
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_ATOMIC)))
+			goto nack_acc;
+		/* Perform atomic OP and save result. */
+		sdata = be64_to_cpu(ateth->swap_data);
+		spin_lock(&dev->pending_lock);
+		qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+		if (opcode == OP(FETCH_ADD))
+			*(u64 *) qp->r_sge.sge.vaddr =
+				qp->r_atomic_data + sdata;
+		else if (qp->r_atomic_data ==
+			 be64_to_cpu(ateth->compare_data))
+			*(u64 *) qp->r_sge.sge.vaddr = sdata;
+		spin_unlock(&dev->pending_lock);
+		atomic_inc(&qp->msn);
+		qp->r_atomic_psn = psn & IPS_PSN_MASK;
+		psn |= 1 << 31;
+		break;
+	}
+
+	default:
+		/* Drop packet for unknown opcodes. */
+		goto done;
+	}
+	qp->r_psn++;
+	qp->r_state = opcode;
+	/* Send an ACK if requested or required. */
+	if (psn & (1 << 31)) {
+		/*
+		 * Coalesce ACKs unless there is a RDMA READ or
+		 * ATOMIC pending.
+		 */
+		spin_lock(&qp->s_lock);
+		if (qp->s_ack_state == OP(ACKNOWLEDGE) ||
+		    qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST) {
+			qp->s_ack_state = opcode;
+			qp->s_nak_state = 0;
+			qp->s_ack_psn = psn;
+			qp->s_ack_atomic = qp->r_atomic_data;
+			goto resched;
+		}
+		spin_unlock(&qp->s_lock);
+	}
+done:
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+	goto bail;
+
+resched:
+	/*
+	 * Try to send ACK right away but not if ipath_do_rc_send() is
+	 * active.
+	 */
+	if (qp->s_hdrwords == 0 &&
+	    (qp->s_ack_state < IB_OPCODE_RDMA_READ_REQUEST ||
+	     qp->s_ack_state >= IB_OPCODE_COMPARE_SWAP))
+		send_rc_ack(qp);
+
+rdmadone:
+	spin_unlock(&qp->s_lock);
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+	/* Call ipath_do_rc_send() in another thread. */
+	tasklet_hi_schedule(&qp->s_task);
+
+bail:
+	return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
new file mode 100644
index 0000000..1e59750
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _IPATH_REGISTERS_H
+#define _IPATH_REGISTERS_H
+
+/*
+ * This file should only be included by kernel source, and by the diags.
+ * It defines the registers, and their contents, for the InfiniPath HT-400 chip
+ */
+
+/*
+ * These are the InfiniPath register and buffer bit definitions,
+ * that are visible to software, and needed only by the kernel
+ * and diag code.  A few, that are visible to protocol and user
+ * code are in ipath_common.h.  Some bits are specific
+ * to a given chip implementation, and have been moved to the
+ * chip-specific source file
+ */
+
+/* kr_revision bits */
+#define INFINIPATH_R_CHIPREVMINOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMINOR_SHIFT 0
+#define INFINIPATH_R_CHIPREVMAJOR_MASK 0xFF
+#define INFINIPATH_R_CHIPREVMAJOR_SHIFT 8
+#define INFINIPATH_R_ARCH_MASK 0xFF
+#define INFINIPATH_R_ARCH_SHIFT 16
+#define INFINIPATH_R_SOFTWARE_MASK 0xFF
+#define INFINIPATH_R_SOFTWARE_SHIFT 24
+#define INFINIPATH_R_BOARDID_MASK 0xFF
+#define INFINIPATH_R_BOARDID_SHIFT 32
+
+/* kr_control bits */
+#define INFINIPATH_C_FREEZEMODE 0x00000002
+#define INFINIPATH_C_LINKENABLE 0x00000004
+#define INFINIPATH_C_RESET 0x00000001
+
+/* kr_sendctrl bits */
+#define INFINIPATH_S_DISARMPIOBUF_SHIFT 16
+
+#define IPATH_S_ABORT		0
+#define IPATH_S_PIOINTBUFAVAIL	1
+#define IPATH_S_PIOBUFAVAILUPD	2
+#define IPATH_S_PIOENABLE	3
+#define IPATH_S_DISARM		31
+
+#define INFINIPATH_S_ABORT		(1U << IPATH_S_ABORT)
+#define INFINIPATH_S_PIOINTBUFAVAIL	(1U << IPATH_S_PIOINTBUFAVAIL)
+#define INFINIPATH_S_PIOBUFAVAILUPD	(1U << IPATH_S_PIOBUFAVAILUPD)
+#define INFINIPATH_S_PIOENABLE		(1U << IPATH_S_PIOENABLE)
+#define INFINIPATH_S_DISARM		(1U << IPATH_S_DISARM)
+
+/* kr_rcvctrl bits */
+#define INFINIPATH_R_PORTENABLE_SHIFT 0
+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
+#define INFINIPATH_R_TAILUPD   0x80000000
+
+/* kr_intstatus, kr_intclear, kr_intmask bits */
+#define INFINIPATH_I_RCVURG_SHIFT 0
+#define INFINIPATH_I_RCVAVAIL_SHIFT 12
+#define INFINIPATH_I_ERROR        0x80000000
+#define INFINIPATH_I_SPIOSENT     0x40000000
+#define INFINIPATH_I_SPIOBUFAVAIL 0x20000000
+#define INFINIPATH_I_GPIO         0x10000000
+
+/* kr_errorstatus, kr_errorclear, kr_errormask bits */
+#define INFINIPATH_E_RFORMATERR      0x0000000000000001ULL
+#define INFINIPATH_E_RVCRC           0x0000000000000002ULL
+#define INFINIPATH_E_RICRC           0x0000000000000004ULL
+#define INFINIPATH_E_RMINPKTLEN      0x0000000000000008ULL
+#define INFINIPATH_E_RMAXPKTLEN      0x0000000000000010ULL
+#define INFINIPATH_E_RLONGPKTLEN     0x0000000000000020ULL
+#define INFINIPATH_E_RSHORTPKTLEN    0x0000000000000040ULL
+#define INFINIPATH_E_RUNEXPCHAR      0x0000000000000080ULL
+#define INFINIPATH_E_RUNSUPVL        0x0000000000000100ULL
+#define INFINIPATH_E_REBP            0x0000000000000200ULL
+#define INFINIPATH_E_RIBFLOW         0x0000000000000400ULL
+#define INFINIPATH_E_RBADVERSION     0x0000000000000800ULL
+#define INFINIPATH_E_RRCVEGRFULL     0x0000000000001000ULL
+#define INFINIPATH_E_RRCVHDRFULL     0x0000000000002000ULL
+#define INFINIPATH_E_RBADTID         0x0000000000004000ULL
+#define INFINIPATH_E_RHDRLEN         0x0000000000008000ULL
+#define INFINIPATH_E_RHDR            0x0000000000010000ULL
+#define INFINIPATH_E_RIBLOSTLINK     0x0000000000020000ULL
+#define INFINIPATH_E_SMINPKTLEN      0x0000000020000000ULL
+#define INFINIPATH_E_SMAXPKTLEN      0x0000000040000000ULL
+#define INFINIPATH_E_SUNDERRUN       0x0000000080000000ULL
+#define INFINIPATH_E_SPKTLEN         0x0000000100000000ULL
+#define INFINIPATH_E_SDROPPEDSMPPKT  0x0000000200000000ULL
+#define INFINIPATH_E_SDROPPEDDATAPKT 0x0000000400000000ULL
+#define INFINIPATH_E_SPIOARMLAUNCH   0x0000000800000000ULL
+#define INFINIPATH_E_SUNEXPERRPKTNUM 0x0000001000000000ULL
+#define INFINIPATH_E_SUNSUPVL        0x0000002000000000ULL
+#define INFINIPATH_E_IBSTATUSCHANGED 0x0001000000000000ULL
+#define INFINIPATH_E_INVALIDADDR     0x0002000000000000ULL
+#define INFINIPATH_E_RESET           0x0004000000000000ULL
+#define INFINIPATH_E_HARDWARE        0x0008000000000000ULL
+
+/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */
+/* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
+ * RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: eagerTID, 3: expTID
+ * 		bit 4: flag buffer, 5: datainfo, 6: header info */
+#define INFINIPATH_HWE_TXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_HWE_RXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_HWE_RXDSYNCMEMPARITYERR  0x0000000400000000ULL
+#define INFINIPATH_HWE_MEMBISTFAILED        0x0040000000000000ULL
+#define INFINIPATH_HWE_IBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_HWE_IBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_hwdiagctrl bits */
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_MASK 0xFULL
+#define INFINIPATH_DC_FORCETXEMEMPARITYERR_SHIFT 40
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_MASK 0x7FULL
+#define INFINIPATH_DC_FORCERXEMEMPARITYERR_SHIFT 44
+#define INFINIPATH_DC_FORCERXDSYNCMEMPARITYERR  0x0000000400000000ULL
+#define INFINIPATH_DC_COUNTERDISABLE            0x1000000000000000ULL
+#define INFINIPATH_DC_COUNTERWREN               0x2000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSTOSPCPARITYERR 0x4000000000000000ULL
+#define INFINIPATH_DC_FORCEIBCBUSFRSPCPARITYERR 0x8000000000000000ULL
+
+/* kr_ibcctrl bits */
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLPERIOD_SHIFT 0
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_MASK 0xFFULL
+#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8
+#define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1
+#define INFINIPATH_IBCC_LINKINITCMD_POLL 2	/* cycle through TS1/TS2 till OK */
+#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3	/* wait for TS1, then go on */
+#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
+#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
+#define INFINIPATH_IBCC_LINKCMD_INIT 1	/* move to 0x11 */
+#define INFINIPATH_IBCC_LINKCMD_ARMED 2	/* move to 0x21 */
+#define INFINIPATH_IBCC_LINKCMD_ACTIVE 3	/* move to 0x31 */
+#define INFINIPATH_IBCC_LINKCMD_SHIFT 18
+#define INFINIPATH_IBCC_MAXPKTLEN_MASK 0x7FFULL
+#define INFINIPATH_IBCC_MAXPKTLEN_SHIFT 20
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT 32
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK 0xFULL
+#define INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT 36
+#define INFINIPATH_IBCC_CREDITSCALE_MASK 0x7ULL
+#define INFINIPATH_IBCC_CREDITSCALE_SHIFT 40
+#define INFINIPATH_IBCC_LOOPBACK             0x8000000000000000ULL
+#define INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE 0x4000000000000000ULL
+
+/* kr_ibcstatus bits */
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_MASK 0xF
+#define INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT 0
+#define INFINIPATH_IBCS_LINKSTATE_MASK 0x7
+#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
+#define INFINIPATH_IBCS_TXREADY       0x40000000
+#define INFINIPATH_IBCS_TXCREDITOK    0x80000000
+/* link training states (shift by INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */
+#define INFINIPATH_IBCS_LT_STATE_DISABLED	0x00
+#define INFINIPATH_IBCS_LT_STATE_LINKUP		0x01
+#define INFINIPATH_IBCS_LT_STATE_POLLACTIVE	0x02
+#define INFINIPATH_IBCS_LT_STATE_POLLQUIET	0x03
+#define INFINIPATH_IBCS_LT_STATE_SLEEPDELAY	0x04
+#define INFINIPATH_IBCS_LT_STATE_SLEEPQUIET	0x05
+#define INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE	0x08
+#define INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG	0x09
+#define INFINIPATH_IBCS_LT_STATE_CFGWAITRMT	0x0a
+#define INFINIPATH_IBCS_LT_STATE_CFGIDLE	0x0b
+#define INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN	0x0c
+#define INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT	0x0e
+#define INFINIPATH_IBCS_LT_STATE_RECOVERIDLE	0x0f
+/* link state machine states (shift by INFINIPATH_IBCS_LINKSTATE_SHIFT) */
+#define INFINIPATH_IBCS_L_STATE_DOWN		0x0
+#define INFINIPATH_IBCS_L_STATE_INIT		0x1
+#define INFINIPATH_IBCS_L_STATE_ARM		0x2
+#define INFINIPATH_IBCS_L_STATE_ACTIVE		0x3
+#define INFINIPATH_IBCS_L_STATE_ACT_DEFER	0x4
+
+/* combination link status states that we use with some frequency */
+#define IPATH_IBSTATE_MASK ((INFINIPATH_IBCS_LINKTRAININGSTATE_MASK \
+		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+		(INFINIPATH_IBCS_LINKSTATE_MASK \
+		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_INIT ((INFINIPATH_IBCS_L_STATE_INIT \
+		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ARM ((INFINIPATH_IBCS_L_STATE_ARM \
+		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+#define IPATH_IBSTATE_ACTIVE ((INFINIPATH_IBCS_L_STATE_ACTIVE \
+		<< INFINIPATH_IBCS_LINKSTATE_SHIFT) | \
+		(INFINIPATH_IBCS_LT_STATE_LINKUP \
+		<<INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT))
+
+/* kr_extstatus bits */
+#define INFINIPATH_EXTS_SERDESPLLLOCK 0x1
+#define INFINIPATH_EXTS_GPIOIN_MASK 0xFFFFULL
+#define INFINIPATH_EXTS_GPIOIN_SHIFT 48
+
+/* kr_extctrl bits */
+#define INFINIPATH_EXTC_GPIOINVERT_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOINVERT_SHIFT 32
+#define INFINIPATH_EXTC_GPIOOE_MASK 0xFFFFULL
+#define INFINIPATH_EXTC_GPIOOE_SHIFT 48
+#define INFINIPATH_EXTC_SERDESENABLE         0x80000000ULL
+#define INFINIPATH_EXTC_SERDESCONNECT        0x40000000ULL
+#define INFINIPATH_EXTC_SERDESENTRUNKING     0x20000000ULL
+#define INFINIPATH_EXTC_SERDESDISRXFIFO      0x10000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK1       0x08000000ULL
+#define INFINIPATH_EXTC_SERDESENPLPBK2       0x04000000ULL
+#define INFINIPATH_EXTC_SERDESENENCDEC       0x02000000ULL
+#define INFINIPATH_EXTC_LED1SECPORT_ON       0x00000020ULL
+#define INFINIPATH_EXTC_LED2SECPORT_ON       0x00000010ULL
+#define INFINIPATH_EXTC_LED1PRIPORT_ON       0x00000008ULL
+#define INFINIPATH_EXTC_LED2PRIPORT_ON       0x00000004ULL
+#define INFINIPATH_EXTC_LEDGBLOK_ON          0x00000002ULL
+#define INFINIPATH_EXTC_LEDGBLERR_OFF        0x00000001ULL
+
+/* kr_mdio bits */
+#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
+#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
+#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
+#define INFINIPATH_MDIO_COMMAND_SHIFT 26
+#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
+#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
+#define INFINIPATH_MDIO_REGADDR_SHIFT 16
+#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
+#define INFINIPATH_MDIO_DATA_SHIFT 0
+#define INFINIPATH_MDIO_CMDVALID    0x0000000040000000ULL
+#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
+
+/* kr_partitionkey bits */
+#define INFINIPATH_PKEY_SIZE 16
+#define INFINIPATH_PKEY_MASK 0xFFFF
+#define INFINIPATH_PKEY_DEFAULT_PKEY 0xFFFF
+
+/* kr_serdesconfig0 bits */
+#define INFINIPATH_SERDC0_RESET_MASK  0xfULL	/* overal reset bits */
+#define INFINIPATH_SERDC0_RESET_PLL   0x10000000ULL	/* pll reset */
+#define INFINIPATH_SERDC0_TXIDLE      0xF000ULL	/* tx idle enables (per lane) */
+#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL	/* rx detect enables (per lane) */
+#define INFINIPATH_SERDC0_L1PWR_DN	 0xF0ULL	/* L1 Power down; use with RXDETECT,
+							   Otherwise not used on IB side */
+
+/* kr_xgxsconfig bits */
+#define INFINIPATH_XGXS_RESET          0x7ULL
+#define INFINIPATH_XGXS_MDIOADDR_MASK  0xfULL
+#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
+
+#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL	/* 40 bits valid */
+
+/* TID entries (memory), HT400-only */
+#define INFINIPATH_RT_VALID 0x8000000000000000ULL
+#define INFINIPATH_RT_ADDR_SHIFT 0
+#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFF
+#define INFINIPATH_RT_BUFSIZE_SHIFT 48
+
+/*
+ * IPATH_PIO_MAXIBHDR is the max IB header size allowed for in our
+ * PIO send buffers.  This is well beyond anything currently
+ * defined in the InfiniBand spec.
+ */
+#define IPATH_PIO_MAXIBHDR 128
+
+typedef u64 ipath_err_t;
+
+/* mask of defined bits for various registers */
+extern u64 infinipath_i_bitsextant;
+extern ipath_err_t infinipath_e_bitsextant, infinipath_hwe_bitsextant;
+
+/* masks that are different in various chips, or only exist in some chips */
+extern u32 infinipath_i_rcvavail_mask, infinipath_i_rcvurg_mask;
+
+/*
+ * register bits for selecting i2c direction and values, used for I2C serial
+ * flash
+ */
+extern u16 ipath_gpio_sda_num, ipath_gpio_scl_num;
+extern u64 ipath_gpio_sda, ipath_gpio_scl;
+
+/*
+ * These are the infinipath general register numbers (not offsets).
+ * The kernel registers are used directly, those beyond the kernel
+ * registers are calculated from one of the base registers.  The use of
+ * an integer type doesn't allow type-checking as thorough as, say,
+ * an enum but allows for better hiding of chip differences.
+ */
+typedef const u16 ipath_kreg,	/* infinipath general registers */
+ ipath_creg,			/* infinipath counter registers */
+ ipath_sreg;			/* kernel-only, infinipath send registers */
+
+/*
+ * These are the chip registers common to all infinipath chips, and
+ * used both by the kernel and the diagnostics or other user code.
+ * They are all implemented such that 64 bit accesses work.
+ * Some implement no more than 32 bits.  Because 64 bit reads
+ * require 2 HT cmds on opteron, we access those with 32 bit
+ * reads for efficiency (they are written as 64 bits, since
+ * the extra 32 bits are nearly free on writes, and it slightly reduces
+ * complexity).  The rest are all accessed as 64 bits.
+ */
+struct ipath_kregs {
+	/* These are the 32 bit group */
+	ipath_kreg kr_control;
+	ipath_kreg kr_counterregbase;
+	ipath_kreg kr_intmask;
+	ipath_kreg kr_intstatus;
+	ipath_kreg kr_pagealign;
+	ipath_kreg kr_portcnt;
+	ipath_kreg kr_rcvtidbase;
+	ipath_kreg kr_rcvtidcnt;
+	ipath_kreg kr_rcvegrbase;
+	ipath_kreg kr_rcvegrcnt;
+	ipath_kreg kr_scratch;
+	ipath_kreg kr_sendctrl;
+	ipath_kreg kr_sendpiobufbase;
+	ipath_kreg kr_sendpiobufcnt;
+	ipath_kreg kr_sendpiosize;
+	ipath_kreg kr_sendregbase;
+	ipath_kreg kr_userregbase;
+	/* These are the 64 bit group */
+	ipath_kreg kr_debugport;
+	ipath_kreg kr_debugportselect;
+	ipath_kreg kr_errorclear;
+	ipath_kreg kr_errormask;
+	ipath_kreg kr_errorstatus;
+	ipath_kreg kr_extctrl;
+	ipath_kreg kr_extstatus;
+	ipath_kreg kr_gpio_clear;
+	ipath_kreg kr_gpio_mask;
+	ipath_kreg kr_gpio_out;
+	ipath_kreg kr_gpio_status;
+	ipath_kreg kr_hwdiagctrl;
+	ipath_kreg kr_hwerrclear;
+	ipath_kreg kr_hwerrmask;
+	ipath_kreg kr_hwerrstatus;
+	ipath_kreg kr_ibcctrl;
+	ipath_kreg kr_ibcstatus;
+	ipath_kreg kr_intblocked;
+	ipath_kreg kr_intclear;
+	ipath_kreg kr_interruptconfig;
+	ipath_kreg kr_mdio;
+	ipath_kreg kr_partitionkey;
+	ipath_kreg kr_rcvbthqp;
+	ipath_kreg kr_rcvbufbase;
+	ipath_kreg kr_rcvbufsize;
+	ipath_kreg kr_rcvctrl;
+	ipath_kreg kr_rcvhdrcnt;
+	ipath_kreg kr_rcvhdrentsize;
+	ipath_kreg kr_rcvhdrsize;
+	ipath_kreg kr_rcvintmembase;
+	ipath_kreg kr_rcvintmemsize;
+	ipath_kreg kr_revision;
+	ipath_kreg kr_sendbuffererror;
+	ipath_kreg kr_sendpioavailaddr;
+	ipath_kreg kr_serdesconfig0;
+	ipath_kreg kr_serdesconfig1;
+	ipath_kreg kr_serdesstatus;
+	ipath_kreg kr_txintmembase;
+	ipath_kreg kr_txintmemsize;
+	ipath_kreg kr_xgxsconfig;
+	ipath_kreg kr_ibpllcfg;
+	/* use these two (and the following N ports) only with ipath_k*_kreg64_port();
+	 * not *kreg64() */
+	ipath_kreg kr_rcvhdraddr;
+	ipath_kreg kr_rcvhdrtailaddr;
+
+	/* remaining registers are not present on all types of infinipath chips  */
+	ipath_kreg kr_rcvpktledcnt;
+	ipath_kreg kr_pcierbuftestreg0;
+	ipath_kreg kr_pcierbuftestreg1;
+	ipath_kreg kr_pcieq0serdesconfig0;
+	ipath_kreg kr_pcieq0serdesconfig1;
+	ipath_kreg kr_pcieq0serdesstatus;
+	ipath_kreg kr_pcieq1serdesconfig0;
+	ipath_kreg kr_pcieq1serdesconfig1;
+	ipath_kreg kr_pcieq1serdesstatus;
+};
+
+struct ipath_cregs {
+	ipath_creg cr_badformatcnt;
+	ipath_creg cr_erricrccnt;
+	ipath_creg cr_errlinkcnt;
+	ipath_creg cr_errlpcrccnt;
+	ipath_creg cr_errpkey;
+	ipath_creg cr_errrcvflowctrlcnt;
+	ipath_creg cr_err_rlencnt;
+	ipath_creg cr_errslencnt;
+	ipath_creg cr_errtidfull;
+	ipath_creg cr_errtidvalid;
+	ipath_creg cr_errvcrccnt;
+	ipath_creg cr_ibstatuschange;
+	ipath_creg cr_intcnt;
+	ipath_creg cr_invalidrlencnt;
+	ipath_creg cr_invalidslencnt;
+	ipath_creg cr_lbflowstallcnt;
+	ipath_creg cr_iblinkdowncnt;
+	ipath_creg cr_iblinkerrrecovcnt;
+	ipath_creg cr_ibsymbolerrcnt;
+	ipath_creg cr_pktrcvcnt;
+	ipath_creg cr_pktrcvflowctrlcnt;
+	ipath_creg cr_pktsendcnt;
+	ipath_creg cr_pktsendflowcnt;
+	ipath_creg cr_portovflcnt;
+	ipath_creg cr_rcvebpcnt;
+	ipath_creg cr_rcvovflcnt;
+	ipath_creg cr_rxdroppktcnt;
+	ipath_creg cr_senddropped;
+	ipath_creg cr_sendstallcnt;
+	ipath_creg cr_sendunderruncnt;
+	ipath_creg cr_unsupvlcnt;
+	ipath_creg cr_wordrcvcnt;
+	ipath_creg cr_wordsendcnt;
+};
+
+#endif				/* _IPATH_REGISTERS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
new file mode 100644
index 0000000..f232e77
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+
+/*
+ * Convert the AETH RNR timeout code into the number of milliseconds.
+ */
+const u32 ib_ipath_rnr_table[32] = {
+	656,			/* 0 */
+	1,			/* 1 */
+	1,			/* 2 */
+	1,			/* 3 */
+	1,			/* 4 */
+	1,			/* 5 */
+	1,			/* 6 */
+	1,			/* 7 */
+	1,			/* 8 */
+	1,			/* 9 */
+	1,			/* A */
+	1,			/* B */
+	1,			/* C */
+	1,			/* D */
+	2,			/* E */
+	2,			/* F */
+	3,			/* 10 */
+	4,			/* 11 */
+	6,			/* 12 */
+	8,			/* 13 */
+	11,			/* 14 */
+	16,			/* 15 */
+	21,			/* 16 */
+	31,			/* 17 */
+	41,			/* 18 */
+	62,			/* 19 */
+	82,			/* 1A */
+	123,			/* 1B */
+	164,			/* 1C */
+	246,			/* 1D */
+	328,			/* 1E */
+	492			/* 1F */
+};
+
+/**
+ * ipath_insert_rnr_queue - put QP on the RNR timeout list for the device
+ * @qp: the QP
+ *
+ * XXX Use a simple list for now.  We might need a priority
+ * queue if we have lots of QPs waiting for RNR timeouts
+ * but that should be rare.
+ */
+void ipath_insert_rnr_queue(struct ipath_qp *qp)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	if (list_empty(&dev->rnrwait))
+		list_add(&qp->timerwait, &dev->rnrwait);
+	else {
+		struct list_head *l = &dev->rnrwait;
+		struct ipath_qp *nqp = list_entry(l->next, struct ipath_qp,
+						  timerwait);
+
+		while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
+			qp->s_rnr_timeout -= nqp->s_rnr_timeout;
+			l = l->next;
+			if (l->next == &dev->rnrwait)
+				break;
+			nqp = list_entry(l->next, struct ipath_qp,
+					 timerwait);
+		}
+		list_add(&qp->timerwait, l);
+	}
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+}
+
+/**
+ * ipath_get_rwqe - copy the next RWQE into the QP's RWQE
+ * @qp: the QP
+ * @wr_id_only: update wr_id only, not SGEs
+ *
+ * Return 0 if no RWQE is available, otherwise return 1.
+ *
+ * Called at interrupt level with the QP r_rq.lock held.
+ */
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
+{
+	struct ipath_rq *rq;
+	struct ipath_srq *srq;
+	struct ipath_rwqe *wqe;
+	int ret;
+
+	if (!qp->ibqp.srq) {
+		rq = &qp->r_rq;
+		if (unlikely(rq->tail == rq->head)) {
+			ret = 0;
+			goto bail;
+		}
+		wqe = get_rwqe_ptr(rq, rq->tail);
+		qp->r_wr_id = wqe->wr_id;
+		if (!wr_id_only) {
+			qp->r_sge.sge = wqe->sg_list[0];
+			qp->r_sge.sg_list = wqe->sg_list + 1;
+			qp->r_sge.num_sge = wqe->num_sge;
+			qp->r_len = wqe->length;
+		}
+		if (++rq->tail >= rq->size)
+			rq->tail = 0;
+		ret = 1;
+		goto bail;
+	}
+
+	srq = to_isrq(qp->ibqp.srq);
+	rq = &srq->rq;
+	spin_lock(&rq->lock);
+	if (unlikely(rq->tail == rq->head)) {
+		spin_unlock(&rq->lock);
+		ret = 0;
+		goto bail;
+	}
+	wqe = get_rwqe_ptr(rq, rq->tail);
+	qp->r_wr_id = wqe->wr_id;
+	if (!wr_id_only) {
+		qp->r_sge.sge = wqe->sg_list[0];
+		qp->r_sge.sg_list = wqe->sg_list + 1;
+		qp->r_sge.num_sge = wqe->num_sge;
+		qp->r_len = wqe->length;
+	}
+	if (++rq->tail >= rq->size)
+		rq->tail = 0;
+	if (srq->ibsrq.event_handler) {
+		struct ib_event ev;
+		u32 n;
+
+		if (rq->head < rq->tail)
+			n = rq->size + rq->head - rq->tail;
+		else
+			n = rq->head - rq->tail;
+		if (n < srq->limit) {
+			srq->limit = 0;
+			spin_unlock(&rq->lock);
+			ev.device = qp->ibqp.device;
+			ev.element.srq = qp->ibqp.srq;
+			ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+			srq->ibsrq.event_handler(&ev,
+						 srq->ibsrq.srq_context);
+		} else
+			spin_unlock(&rq->lock);
+	} else
+		spin_unlock(&rq->lock);
+	ret = 1;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_ruc_loopback - handle UC and RC lookback requests
+ * @sqp: the loopback QP
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_do_uc_send() or ipath_do_rc_send() to
+ * forward a WQE addressed to the same HCA.
+ * Note that although we are single threaded due to the tasklet, we still
+ * have to protect against post_send().  We don't have to worry about
+ * receive interrupts since this is a connected protocol and all packets
+ * will pass through here.
+ */
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc)
+{
+	struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+	struct ipath_qp *qp;
+	struct ipath_swqe *wqe;
+	struct ipath_sge *sge;
+	unsigned long flags;
+	u64 sdata;
+
+	qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn);
+	if (!qp) {
+		dev->n_pkt_drops++;
+		return;
+	}
+
+again:
+	spin_lock_irqsave(&sqp->s_lock, flags);
+
+	if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK)) {
+		spin_unlock_irqrestore(&sqp->s_lock, flags);
+		goto done;
+	}
+
+	/* Get the next send request. */
+	if (sqp->s_last == sqp->s_head) {
+		/* Send work queue is empty. */
+		spin_unlock_irqrestore(&sqp->s_lock, flags);
+		goto done;
+	}
+
+	/*
+	 * We can rely on the entry not changing without the s_lock
+	 * being held until we update s_last.
+	 */
+	wqe = get_swqe_ptr(sqp, sqp->s_last);
+	spin_unlock_irqrestore(&sqp->s_lock, flags);
+
+	wc->wc_flags = 0;
+	wc->imm_data = 0;
+
+	sqp->s_sge.sge = wqe->sg_list[0];
+	sqp->s_sge.sg_list = wqe->sg_list + 1;
+	sqp->s_sge.num_sge = wqe->wr.num_sge;
+	sqp->s_len = wqe->length;
+	switch (wqe->wr.opcode) {
+	case IB_WR_SEND_WITH_IMM:
+		wc->wc_flags = IB_WC_WITH_IMM;
+		wc->imm_data = wqe->wr.imm_data;
+		/* FALLTHROUGH */
+	case IB_WR_SEND:
+		spin_lock_irqsave(&qp->r_rq.lock, flags);
+		if (!ipath_get_rwqe(qp, 0)) {
+		rnr_nak:
+			spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+			/* Handle RNR NAK */
+			if (qp->ibqp.qp_type == IB_QPT_UC)
+				goto send_comp;
+			if (sqp->s_rnr_retry == 0) {
+				wc->status = IB_WC_RNR_RETRY_EXC_ERR;
+				goto err;
+			}
+			if (sqp->s_rnr_retry_cnt < 7)
+				sqp->s_rnr_retry--;
+			dev->n_rnr_naks++;
+			sqp->s_rnr_timeout =
+				ib_ipath_rnr_table[sqp->s_min_rnr_timer];
+			ipath_insert_rnr_queue(sqp);
+			goto done;
+		}
+		spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+		break;
+
+	case IB_WR_RDMA_WRITE_WITH_IMM:
+		wc->wc_flags = IB_WC_WITH_IMM;
+		wc->imm_data = wqe->wr.imm_data;
+		spin_lock_irqsave(&qp->r_rq.lock, flags);
+		if (!ipath_get_rwqe(qp, 1))
+			goto rnr_nak;
+		spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+		/* FALLTHROUGH */
+	case IB_WR_RDMA_WRITE:
+		if (wqe->length == 0)
+			break;
+		if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, wqe->length,
+					    wqe->wr.wr.rdma.remote_addr,
+					    wqe->wr.wr.rdma.rkey,
+					    IB_ACCESS_REMOTE_WRITE))) {
+		acc_err:
+			wc->status = IB_WC_REM_ACCESS_ERR;
+		err:
+			wc->wr_id = wqe->wr.wr_id;
+			wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+			wc->vendor_err = 0;
+			wc->byte_len = 0;
+			wc->qp_num = sqp->ibqp.qp_num;
+			wc->src_qp = sqp->remote_qpn;
+			wc->pkey_index = 0;
+			wc->slid = sqp->remote_ah_attr.dlid;
+			wc->sl = sqp->remote_ah_attr.sl;
+			wc->dlid_path_bits = 0;
+			wc->port_num = 0;
+			ipath_sqerror_qp(sqp, wc);
+			goto done;
+		}
+		break;
+
+	case IB_WR_RDMA_READ:
+		if (unlikely(!ipath_rkey_ok(dev, &sqp->s_sge, wqe->length,
+					    wqe->wr.wr.rdma.remote_addr,
+					    wqe->wr.wr.rdma.rkey,
+					    IB_ACCESS_REMOTE_READ)))
+			goto acc_err;
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_READ)))
+			goto acc_err;
+		qp->r_sge.sge = wqe->sg_list[0];
+		qp->r_sge.sg_list = wqe->sg_list + 1;
+		qp->r_sge.num_sge = wqe->wr.num_sge;
+		break;
+
+	case IB_WR_ATOMIC_CMP_AND_SWP:
+	case IB_WR_ATOMIC_FETCH_AND_ADD:
+		if (unlikely(!ipath_rkey_ok(dev, &qp->r_sge, sizeof(u64),
+					    wqe->wr.wr.rdma.remote_addr,
+					    wqe->wr.wr.rdma.rkey,
+					    IB_ACCESS_REMOTE_ATOMIC)))
+			goto acc_err;
+		/* Perform atomic OP and save result. */
+		sdata = wqe->wr.wr.atomic.swap;
+		spin_lock_irqsave(&dev->pending_lock, flags);
+		qp->r_atomic_data = *(u64 *) qp->r_sge.sge.vaddr;
+		if (wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+			*(u64 *) qp->r_sge.sge.vaddr =
+				qp->r_atomic_data + sdata;
+		else if (qp->r_atomic_data == wqe->wr.wr.atomic.compare_add)
+			*(u64 *) qp->r_sge.sge.vaddr = sdata;
+		spin_unlock_irqrestore(&dev->pending_lock, flags);
+		*(u64 *) sqp->s_sge.sge.vaddr = qp->r_atomic_data;
+		goto send_comp;
+
+	default:
+		goto done;
+	}
+
+	sge = &sqp->s_sge.sge;
+	while (sqp->s_len) {
+		u32 len = sqp->s_len;
+
+		if (len > sge->length)
+			len = sge->length;
+		BUG_ON(len == 0);
+		ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
+		sge->vaddr += len;
+		sge->length -= len;
+		sge->sge_length -= len;
+		if (sge->sge_length == 0) {
+			if (--sqp->s_sge.num_sge)
+				*sge = *sqp->s_sge.sg_list++;
+		} else if (sge->length == 0 && sge->mr != NULL) {
+			if (++sge->n >= IPATH_SEGSZ) {
+				if (++sge->m >= sge->mr->mapsz)
+					break;
+				sge->n = 0;
+			}
+			sge->vaddr =
+				sge->mr->map[sge->m]->segs[sge->n].vaddr;
+			sge->length =
+				sge->mr->map[sge->m]->segs[sge->n].length;
+		}
+		sqp->s_len -= len;
+	}
+
+	if (wqe->wr.opcode == IB_WR_RDMA_WRITE ||
+	    wqe->wr.opcode == IB_WR_RDMA_READ)
+		goto send_comp;
+
+	if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+		wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
+	else
+		wc->opcode = IB_WC_RECV;
+	wc->wr_id = qp->r_wr_id;
+	wc->status = IB_WC_SUCCESS;
+	wc->vendor_err = 0;
+	wc->byte_len = wqe->length;
+	wc->qp_num = qp->ibqp.qp_num;
+	wc->src_qp = qp->remote_qpn;
+	/* XXX do we know which pkey matched? Only needed for GSI. */
+	wc->pkey_index = 0;
+	wc->slid = qp->remote_ah_attr.dlid;
+	wc->sl = qp->remote_ah_attr.sl;
+	wc->dlid_path_bits = 0;
+	/* Signal completion event if the solicited bit is set. */
+	ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+		       wqe->wr.send_flags & IB_SEND_SOLICITED);
+
+send_comp:
+	sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
+
+	if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &sqp->s_flags) ||
+	    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+		wc->wr_id = wqe->wr.wr_id;
+		wc->status = IB_WC_SUCCESS;
+		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		wc->vendor_err = 0;
+		wc->byte_len = wqe->length;
+		wc->qp_num = sqp->ibqp.qp_num;
+		wc->src_qp = 0;
+		wc->pkey_index = 0;
+		wc->slid = 0;
+		wc->sl = 0;
+		wc->dlid_path_bits = 0;
+		wc->port_num = 0;
+		ipath_cq_enter(to_icq(sqp->ibqp.send_cq), wc, 0);
+	}
+
+	/* Update s_last now that we are finished with the SWQE */
+	spin_lock_irqsave(&sqp->s_lock, flags);
+	if (++sqp->s_last >= sqp->s_size)
+		sqp->s_last = 0;
+	spin_unlock_irqrestore(&sqp->s_lock, flags);
+	goto again;
+
+done:
+	if (atomic_dec_and_test(&qp->refcount))
+		wake_up(&qp->wait);
+}
+
+/**
+ * ipath_no_bufs_available - tell the layer driver we need buffers
+ * @qp: the QP that caused the problem
+ * @dev: the device we ran out of buffers on
+ *
+ * Called when we run out of PIO buffers.
+ */
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	if (qp->piowait.next == LIST_POISON1)
+		list_add_tail(&qp->piowait, &dev->piowait);
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+	/*
+	 * Note that as soon as ipath_layer_want_buffer() is called and
+	 * possibly before it returns, ipath_ib_piobufavail()
+	 * could be called.  If we are still in the tasklet function,
+	 * tasklet_hi_schedule() will not call us until the next time
+	 * tasklet_hi_schedule() is called.
+	 * We clear the tasklet flag now since we are committing to return
+	 * from the tasklet function.
+	 */
+	clear_bit(IPATH_S_BUSY, &qp->s_flags);
+	tasklet_unlock(&qp->s_task);
+	ipath_layer_want_buffer(dev->dd);
+	dev->n_piowait++;
+}
+
+/**
+ * ipath_post_rc_send - post RC and UC sends
+ * @qp: the QP to post on
+ * @wr: the work request to send
+ */
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+	struct ipath_swqe *wqe;
+	unsigned long flags;
+	u32 next;
+	int i, j;
+	int acc;
+	int ret;
+
+	/*
+	 * Don't allow RDMA reads or atomic operations on UC or
+	 * undefined operations.
+	 * Make sure buffer is large enough to hold the result for atomics.
+	 */
+	if (qp->ibqp.qp_type == IB_QPT_UC) {
+		if ((unsigned) wr->opcode >= IB_WR_RDMA_READ) {
+			ret = -EINVAL;
+			goto bail;
+		}
+	} else if ((unsigned) wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD) {
+		ret = -EINVAL;
+		goto bail;
+	} else if (wr->opcode >= IB_WR_ATOMIC_CMP_AND_SWP &&
+		   (wr->num_sge == 0 ||
+		    wr->sg_list[0].length < sizeof(u64) ||
+		    wr->sg_list[0].addr & (sizeof(u64) - 1))) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	/* IB spec says that num_sge == 0 is OK. */
+	if (wr->num_sge > qp->s_max_sge) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+	spin_lock_irqsave(&qp->s_lock, flags);
+	next = qp->s_head + 1;
+	if (next >= qp->s_size)
+		next = 0;
+	if (next == qp->s_last) {
+		spin_unlock_irqrestore(&qp->s_lock, flags);
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	wqe = get_swqe_ptr(qp, qp->s_head);
+	wqe->wr = *wr;
+	wqe->ssn = qp->s_ssn++;
+	wqe->sg_list[0].mr = NULL;
+	wqe->sg_list[0].vaddr = NULL;
+	wqe->sg_list[0].length = 0;
+	wqe->sg_list[0].sge_length = 0;
+	wqe->length = 0;
+	acc = wr->opcode >= IB_WR_RDMA_READ ? IB_ACCESS_LOCAL_WRITE : 0;
+	for (i = 0, j = 0; i < wr->num_sge; i++) {
+		if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+			spin_unlock_irqrestore(&qp->s_lock, flags);
+			ret = -EINVAL;
+			goto bail;
+		}
+		if (wr->sg_list[i].length == 0)
+			continue;
+		if (!ipath_lkey_ok(&to_idev(qp->ibqp.device)->lk_table,
+				   &wqe->sg_list[j], &wr->sg_list[i],
+				   acc)) {
+			spin_unlock_irqrestore(&qp->s_lock, flags);
+			ret = -EINVAL;
+			goto bail;
+		}
+		wqe->length += wr->sg_list[i].length;
+		j++;
+	}
+	wqe->wr.num_sge = j;
+	qp->s_head = next;
+	/*
+	 * Wake up the send tasklet if the QP is not waiting
+	 * for an RNR timeout.
+	 */
+	next = qp->s_rnr_timeout;
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+
+	if (next == 0) {
+		if (qp->ibqp.qp_type == IB_QPT_UC)
+			ipath_do_uc_send((unsigned long) qp);
+		else
+			ipath_do_rc_send((unsigned long) qp);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
new file mode 100644
index 0000000..01c4c6c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/err.h>
+#include <linux/vmalloc.h>
+
+#include "ipath_verbs.h"
+
+/**
+ * ipath_post_srq_receive - post a receive on a shared receive queue
+ * @ibsrq: the SRQ to post the receive on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first WR to cause a problem is put here
+ *
+ * This may be called from interrupt context.
+ */
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+			   struct ib_recv_wr **bad_wr)
+{
+	struct ipath_srq *srq = to_isrq(ibsrq);
+	struct ipath_ibdev *dev = to_idev(ibsrq->device);
+	unsigned long flags;
+	int ret;
+
+	for (; wr; wr = wr->next) {
+		struct ipath_rwqe *wqe;
+		u32 next;
+		int i, j;
+
+		if (wr->num_sge > srq->rq.max_sge) {
+			*bad_wr = wr;
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		spin_lock_irqsave(&srq->rq.lock, flags);
+		next = srq->rq.head + 1;
+		if (next >= srq->rq.size)
+			next = 0;
+		if (next == srq->rq.tail) {
+			spin_unlock_irqrestore(&srq->rq.lock, flags);
+			*bad_wr = wr;
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		wqe = get_rwqe_ptr(&srq->rq, srq->rq.head);
+		wqe->wr_id = wr->wr_id;
+		wqe->sg_list[0].mr = NULL;
+		wqe->sg_list[0].vaddr = NULL;
+		wqe->sg_list[0].length = 0;
+		wqe->sg_list[0].sge_length = 0;
+		wqe->length = 0;
+		for (i = 0, j = 0; i < wr->num_sge; i++) {
+			/* Check LKEY */
+			if (to_ipd(srq->ibsrq.pd)->user &&
+			    wr->sg_list[i].lkey == 0) {
+				spin_unlock_irqrestore(&srq->rq.lock,
+						       flags);
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto bail;
+			}
+			if (wr->sg_list[i].length == 0)
+				continue;
+			if (!ipath_lkey_ok(&dev->lk_table,
+					   &wqe->sg_list[j],
+					   &wr->sg_list[i],
+					   IB_ACCESS_LOCAL_WRITE)) {
+				spin_unlock_irqrestore(&srq->rq.lock,
+						       flags);
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto bail;
+			}
+			wqe->length += wr->sg_list[i].length;
+			j++;
+		}
+		wqe->num_sge = j;
+		srq->rq.head = next;
+		spin_unlock_irqrestore(&srq->rq.lock, flags);
+	}
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_create_srq - create a shared receive queue
+ * @ibpd: the protection domain of the SRQ to create
+ * @attr: the attributes of the SRQ
+ * @udata: not used by the InfiniPath verbs driver
+ */
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+				struct ib_srq_init_attr *srq_init_attr,
+				struct ib_udata *udata)
+{
+	struct ipath_srq *srq;
+	u32 sz;
+	struct ib_srq *ret;
+
+	if (srq_init_attr->attr.max_sge < 1) {
+		ret = ERR_PTR(-EINVAL);
+		goto bail;
+	}
+
+	srq = kmalloc(sizeof(*srq), GFP_KERNEL);
+	if (!srq) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	/*
+	 * Need to use vmalloc() if we want to support large #s of entries.
+	 */
+	srq->rq.size = srq_init_attr->attr.max_wr + 1;
+	sz = sizeof(struct ipath_sge) * srq_init_attr->attr.max_sge +
+		sizeof(struct ipath_rwqe);
+	srq->rq.wq = vmalloc(srq->rq.size * sz);
+	if (!srq->rq.wq) {
+		kfree(srq);
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	/*
+	 * ib_create_srq() will initialize srq->ibsrq.
+	 */
+	spin_lock_init(&srq->rq.lock);
+	srq->rq.head = 0;
+	srq->rq.tail = 0;
+	srq->rq.max_sge = srq_init_attr->attr.max_sge;
+	srq->limit = srq_init_attr->attr.srq_limit;
+
+	ret = &srq->ibsrq;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_modify_srq - modify a shared receive queue
+ * @ibsrq: the SRQ to modify
+ * @attr: the new attributes of the SRQ
+ * @attr_mask: indicates which attributes to modify
+ */
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+		     enum ib_srq_attr_mask attr_mask)
+{
+	struct ipath_srq *srq = to_isrq(ibsrq);
+	unsigned long flags;
+	int ret;
+
+	if (attr_mask & IB_SRQ_LIMIT) {
+		spin_lock_irqsave(&srq->rq.lock, flags);
+		srq->limit = attr->srq_limit;
+		spin_unlock_irqrestore(&srq->rq.lock, flags);
+	}
+	if (attr_mask & IB_SRQ_MAX_WR) {
+		u32 size = attr->max_wr + 1;
+		struct ipath_rwqe *wq, *p;
+		u32 n;
+		u32 sz;
+
+		if (attr->max_sge < srq->rq.max_sge) {
+			ret = -EINVAL;
+			goto bail;
+		}
+
+		sz = sizeof(struct ipath_rwqe) +
+			attr->max_sge * sizeof(struct ipath_sge);
+		wq = vmalloc(size * sz);
+		if (!wq) {
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		spin_lock_irqsave(&srq->rq.lock, flags);
+		if (srq->rq.head < srq->rq.tail)
+			n = srq->rq.size + srq->rq.head - srq->rq.tail;
+		else
+			n = srq->rq.head - srq->rq.tail;
+		if (size <= n || size <= srq->limit) {
+			spin_unlock_irqrestore(&srq->rq.lock, flags);
+			vfree(wq);
+			ret = -EINVAL;
+			goto bail;
+		}
+		n = 0;
+		p = wq;
+		while (srq->rq.tail != srq->rq.head) {
+			struct ipath_rwqe *wqe;
+			int i;
+
+			wqe = get_rwqe_ptr(&srq->rq, srq->rq.tail);
+			p->wr_id = wqe->wr_id;
+			p->length = wqe->length;
+			p->num_sge = wqe->num_sge;
+			for (i = 0; i < wqe->num_sge; i++)
+				p->sg_list[i] = wqe->sg_list[i];
+			n++;
+			p = (struct ipath_rwqe *)((char *) p + sz);
+			if (++srq->rq.tail >= srq->rq.size)
+				srq->rq.tail = 0;
+		}
+		vfree(srq->rq.wq);
+		srq->rq.wq = wq;
+		srq->rq.size = size;
+		srq->rq.head = n;
+		srq->rq.tail = 0;
+		srq->rq.max_sge = attr->max_sge;
+		spin_unlock_irqrestore(&srq->rq.lock, flags);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr)
+{
+	struct ipath_srq *srq = to_isrq(ibsrq);
+
+	attr->max_wr = srq->rq.size - 1;
+	attr->max_sge = srq->rq.max_sge;
+	attr->srq_limit = srq->limit;
+	return 0;
+}
+
+/**
+ * ipath_destroy_srq - destroy a shared receive queue
+ * @ibsrq: the SRQ to destroy
+ */
+int ipath_destroy_srq(struct ib_srq *ibsrq)
+{
+	struct ipath_srq *srq = to_isrq(ibsrq);
+
+	vfree(srq->rq.wq);
+	kfree(srq);
+
+	return 0;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
new file mode 100644
index 0000000..fe20913
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+
+struct infinipath_stats ipath_stats;
+
+/**
+ * ipath_snap_cntr - snapshot a chip counter
+ * @dd: the infinipath device
+ * @creg: the counter to snapshot
+ *
+ * called from add_timer and user counter read calls, to deal with
+ * counters that wrap in "human time".  The words sent and received, and
+ * the packets sent and received are all that we worry about.  For now,
+ * at least, we don't worry about error counters, because if they wrap
+ * that quickly, we probably don't care.  We may eventually just make this
+ * handle all the counters.  word counters can wrap in about 20 seconds
+ * of full bandwidth traffic, packet counters in a few hours.
+ */
+
+u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
+{
+	u32 val, reg64 = 0;
+	u64 val64;
+	unsigned long t0, t1;
+	u64 ret;
+
+	t0 = jiffies;
+	/* If fast increment counters are only 32 bits, snapshot them,
+	 * and maintain them as 64bit values in the driver */
+	if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
+	    (creg == dd->ipath_cregs->cr_wordsendcnt ||
+	     creg == dd->ipath_cregs->cr_wordrcvcnt ||
+	     creg == dd->ipath_cregs->cr_pktsendcnt ||
+	     creg == dd->ipath_cregs->cr_pktrcvcnt)) {
+		val64 = ipath_read_creg(dd, creg);
+		val = val64 == ~0ULL ? ~0U : 0;
+		reg64 = 1;
+	} else			/* val64 just to keep gcc quiet... */
+		val64 = val = ipath_read_creg32(dd, creg);
+	/*
+	 * See if a second has passed.  This is just a way to detect things
+	 * that are quite broken.  Normally this should take just a few
+	 * cycles (the check is for long enough that we don't care if we get
+	 * pre-empted.)  An Opteron HT O read timeout is 4 seconds with
+	 * normal NB values
+	 */
+	t1 = jiffies;
+	if (time_before(t0 + HZ, t1) && val == -1) {
+		ipath_dev_err(dd, "Error!  Read counter 0x%x timed out\n",
+			      creg);
+		ret = 0ULL;
+		goto bail;
+	}
+	if (reg64) {
+		ret = val64;
+		goto bail;
+	}
+
+	if (creg == dd->ipath_cregs->cr_wordsendcnt) {
+		if (val != dd->ipath_lastsword) {
+			dd->ipath_sword += val - dd->ipath_lastsword;
+			dd->ipath_lastsword = val;
+		}
+		val64 = dd->ipath_sword;
+	} else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
+		if (val != dd->ipath_lastrword) {
+			dd->ipath_rword += val - dd->ipath_lastrword;
+			dd->ipath_lastrword = val;
+		}
+		val64 = dd->ipath_rword;
+	} else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
+		if (val != dd->ipath_lastspkts) {
+			dd->ipath_spkts += val - dd->ipath_lastspkts;
+			dd->ipath_lastspkts = val;
+		}
+		val64 = dd->ipath_spkts;
+	} else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
+		if (val != dd->ipath_lastrpkts) {
+			dd->ipath_rpkts += val - dd->ipath_lastrpkts;
+			dd->ipath_lastrpkts = val;
+		}
+		val64 = dd->ipath_rpkts;
+	} else
+		val64 = (u64) val;
+
+	ret = val64;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_qcheck - print delta of egrfull/hdrqfull errors for kernel ports
+ * @dd: the infinipath device
+ *
+ * print the delta of egrfull/hdrqfull errors for kernel ports no more than
+ * every 5 seconds.  User processes are printed at close, but kernel doesn't
+ * close, so...  Separate routine so may call from other places someday, and
+ * so function name when printed by _IPATH_INFO is meaningfull
+ */
+static void ipath_qcheck(struct ipath_devdata *dd)
+{
+	static u64 last_tot_hdrqfull;
+	size_t blen = 0;
+	char buf[128];
+
+	*buf = 0;
+	if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+		blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
+				dd->ipath_pd[0]->port_hdrqfull -
+				dd->ipath_p0_hdrqfull);
+		dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
+	}
+	if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
+		blen += snprintf(buf + blen, sizeof buf - blen,
+				 "%srcvegrfull %llu",
+				 blen ? ", " : "",
+				 (unsigned long long)
+				 (ipath_stats.sps_etidfull -
+				  dd->ipath_last_tidfull));
+		dd->ipath_last_tidfull = ipath_stats.sps_etidfull;
+	}
+
+	/*
+	 * this is actually the number of hdrq full interrupts, not actual
+	 * events, but at the moment that's mostly what I'm interested in.
+	 * Actual count, etc. is in the counters, if needed.  For production
+	 * users this won't ordinarily be printed.
+	 */
+
+	if ((ipath_debug & (__IPATH_PKTDBG | __IPATH_DBG)) &&
+	    ipath_stats.sps_hdrqfull != last_tot_hdrqfull) {
+		blen += snprintf(buf + blen, sizeof buf - blen,
+				 "%shdrqfull %llu (all ports)",
+				 blen ? ", " : "",
+				 (unsigned long long)
+				 (ipath_stats.sps_hdrqfull -
+				  last_tot_hdrqfull));
+		last_tot_hdrqfull = ipath_stats.sps_hdrqfull;
+	}
+	if (blen)
+		ipath_dbg("%s\n", buf);
+
+	if (dd->ipath_port0head != (u32)
+	    le64_to_cpu(*dd->ipath_hdrqtailptr)) {
+		if (dd->ipath_lastport0rcv_cnt ==
+		    ipath_stats.sps_port0pkts) {
+			ipath_cdbg(PKT, "missing rcv interrupts? "
+				   "port0 hd=%llx tl=%x; port0pkts %llx\n",
+				   (unsigned long long)
+				   le64_to_cpu(*dd->ipath_hdrqtailptr),
+				   dd->ipath_port0head,
+				   (unsigned long long)
+				   ipath_stats.sps_port0pkts);
+			ipath_kreceive(dd);
+		}
+		dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
+	}
+}
+
+/**
+ * ipath_get_faststats - get word counters from chip before they overflow
+ * @opaque - contains a pointer to the infinipath device ipath_devdata
+ *
+ * called from add_timer
+ */
+void ipath_get_faststats(unsigned long opaque)
+{
+	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
+	u32 val;
+	static unsigned cnt;
+
+	/*
+	 * don't access the chip while running diags, or memory diags can
+	 * fail
+	 */
+	if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT) ||
+	    ipath_diag_inuse)
+		/* but re-arm the timer, for diags case; won't hurt other */
+		goto done;
+
+	if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
+		ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
+	}
+
+	ipath_qcheck(dd);
+
+	/*
+	 * deal with repeat error suppression.  Doesn't really matter if
+	 * last error was almost a full interval ago, or just a few usecs
+	 * ago; still won't get more than 2 per interval.  We may want
+	 * longer intervals for this eventually, could do with mod, counter
+	 * or separate timer.  Also see code in ipath_handle_errors() and
+	 * ipath_handle_hwerrors().
+	 */
+
+	if (dd->ipath_lasterror)
+		dd->ipath_lasterror = 0;
+	if (dd->ipath_lasthwerror)
+		dd->ipath_lasthwerror = 0;
+	if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs)
+	    && time_after(jiffies, dd->ipath_unmasktime)) {
+		char ebuf[256];
+		ipath_decode_err(ebuf, sizeof ebuf,
+				 (dd->ipath_maskederrs & ~dd->
+				  ipath_ignorederrs));
+		if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &
+		    ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL))
+			ipath_dev_err(dd, "Re-enabling masked errors "
+				      "(%s)\n", ebuf);
+		else {
+			/*
+			 * rcvegrfull and rcvhdrqfull are "normal", for some
+			 * types of processes (mostly benchmarks) that send
+			 * huge numbers of messages, while not processing
+			 * them.  So only complain about these at debug
+			 * level.
+			 */
+			ipath_dbg("Disabling frequent queue full errors "
+				  "(%s)\n", ebuf);
+		}
+		dd->ipath_maskederrs = dd->ipath_ignorederrs;
+		ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+				 ~dd->ipath_maskederrs);
+	}
+
+	/* limit qfull messages to ~one per minute per port */
+	if ((++cnt & 0x10)) {
+		for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
+		     val--) {
+			if (dd->ipath_lastegrheads[val] != -1)
+				dd->ipath_lastegrheads[val] = -1;
+			if (dd->ipath_lastrcvhdrqtails[val] != -1)
+				dd->ipath_lastrcvhdrqtails[val] = -1;
+		}
+	}
+
+	if (dd->ipath_nosma_bufs) {
+		dd->ipath_nosma_secs += 5;
+		if (dd->ipath_nosma_secs >= 30) {
+			ipath_cdbg(SMA, "No SMA bufs avail %u seconds; "
+				   "cancelling pending sends\n",
+				   dd->ipath_nosma_secs);
+			/*
+			 * issue an abort as well, in case we have a packet
+			 * stuck in launch fifo.  This could corrupt an
+			 * outgoing user packet in the worst case,
+			 * but this is a pretty catastrophic, anyway.
+			 */
+			ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+					 INFINIPATH_S_ABORT);
+			ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
+					     dd->ipath_piobcnt2k +
+					     dd->ipath_piobcnt4k -
+					     dd->ipath_lastport_piobuf);
+			/* start again, if necessary */
+			dd->ipath_nosma_secs = 0;
+		} else
+			ipath_cdbg(SMA, "No SMA bufs avail %u tries, "
+				   "after %u seconds\n",
+				   dd->ipath_nosma_bufs,
+				   dd->ipath_nosma_secs);
+	}
+
+done:
+	mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
new file mode 100644
index 0000000..32acd80
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/ctype.h>
+#include <linux/pci.h>
+
+#include "ipath_kernel.h"
+#include "ips_common.h"
+#include "ipath_layer.h"
+
+/**
+ * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
+ * @str: the string containing the number
+ * @valp: where to put the result
+ *
+ * returns the number of bytes consumed, or negative value on error
+ */
+int ipath_parse_ushort(const char *str, unsigned short *valp)
+{
+	unsigned long val;
+	char *end;
+	int ret;
+
+	if (!isdigit(str[0])) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	val = simple_strtoul(str, &end, 0);
+
+	if (val > 0xffff) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	*valp = val;
+
+	ret = end + 1 - str;
+	if (ret == 0)
+		ret = -EINVAL;
+
+bail:
+	return ret;
+}
+
+static ssize_t show_version(struct device_driver *dev, char *buf)
+{
+	/* The string printed here is already newline-terminated. */
+	return scnprintf(buf, PAGE_SIZE, "%s", ipath_core_version);
+}
+
+static ssize_t show_num_units(struct device_driver *dev, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 ipath_count_units(NULL, NULL, NULL));
+}
+
+#define DRIVER_STAT(name, attr) \
+	static ssize_t show_stat_##name(struct device_driver *dev, \
+					char *buf) \
+	{ \
+		return scnprintf( \
+			buf, PAGE_SIZE, "%llu\n", \
+			(unsigned long long) ipath_stats.sps_ ##attr); \
+	} \
+	static DRIVER_ATTR(name, S_IRUGO, show_stat_##name, NULL)
+
+DRIVER_STAT(intrs, ints);
+DRIVER_STAT(err_intrs, errints);
+DRIVER_STAT(errs, errs);
+DRIVER_STAT(pkt_errs, pkterrs);
+DRIVER_STAT(crc_errs, crcerrs);
+DRIVER_STAT(hw_errs, hwerrs);
+DRIVER_STAT(ib_link, iblink);
+DRIVER_STAT(port0_pkts, port0pkts);
+DRIVER_STAT(ether_spkts, ether_spkts);
+DRIVER_STAT(ether_rpkts, ether_rpkts);
+DRIVER_STAT(sma_spkts, sma_spkts);
+DRIVER_STAT(sma_rpkts, sma_rpkts);
+DRIVER_STAT(hdrq_full, hdrqfull);
+DRIVER_STAT(etid_full, etidfull);
+DRIVER_STAT(no_piobufs, nopiobufs);
+DRIVER_STAT(ports, ports);
+DRIVER_STAT(pkey0, pkeys[0]);
+DRIVER_STAT(pkey1, pkeys[1]);
+DRIVER_STAT(pkey2, pkeys[2]);
+DRIVER_STAT(pkey3, pkeys[3]);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(lid0, lid[0]);
+DRIVER_STAT(lid1, lid[1]);
+DRIVER_STAT(lid2, lid[2]);
+DRIVER_STAT(lid3, lid[3]);
+
+DRIVER_STAT(nports, nports);
+DRIVER_STAT(null_intr, nullintr);
+DRIVER_STAT(max_pkts_call, maxpkts_call);
+DRIVER_STAT(avg_pkts_call, avgpkts_call);
+DRIVER_STAT(page_locks, pagelocks);
+DRIVER_STAT(page_unlocks, pageunlocks);
+DRIVER_STAT(krdrops, krdrops);
+/* XXX fix the following when dynamic table of devices used */
+DRIVER_STAT(mlid0, mlid[0]);
+DRIVER_STAT(mlid1, mlid[1]);
+DRIVER_STAT(mlid2, mlid[2]);
+DRIVER_STAT(mlid3, mlid[3]);
+
+static struct attribute *driver_stat_attributes[] = {
+	&driver_attr_intrs.attr,
+	&driver_attr_err_intrs.attr,
+	&driver_attr_errs.attr,
+	&driver_attr_pkt_errs.attr,
+	&driver_attr_crc_errs.attr,
+	&driver_attr_hw_errs.attr,
+	&driver_attr_ib_link.attr,
+	&driver_attr_port0_pkts.attr,
+	&driver_attr_ether_spkts.attr,
+	&driver_attr_ether_rpkts.attr,
+	&driver_attr_sma_spkts.attr,
+	&driver_attr_sma_rpkts.attr,
+	&driver_attr_hdrq_full.attr,
+	&driver_attr_etid_full.attr,
+	&driver_attr_no_piobufs.attr,
+	&driver_attr_ports.attr,
+	&driver_attr_pkey0.attr,
+	&driver_attr_pkey1.attr,
+	&driver_attr_pkey2.attr,
+	&driver_attr_pkey3.attr,
+	&driver_attr_lid0.attr,
+	&driver_attr_lid1.attr,
+	&driver_attr_lid2.attr,
+	&driver_attr_lid3.attr,
+	&driver_attr_nports.attr,
+	&driver_attr_null_intr.attr,
+	&driver_attr_max_pkts_call.attr,
+	&driver_attr_avg_pkts_call.attr,
+	&driver_attr_page_locks.attr,
+	&driver_attr_page_unlocks.attr,
+	&driver_attr_krdrops.attr,
+	&driver_attr_mlid0.attr,
+	&driver_attr_mlid1.attr,
+	&driver_attr_mlid2.attr,
+	&driver_attr_mlid3.attr,
+	NULL
+};
+
+static struct attribute_group driver_stat_attr_group = {
+	.name = "stats",
+	.attrs = driver_stat_attributes
+};
+
+static ssize_t show_status(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	if (!dd->ipath_statusp) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
+			(unsigned long long) *(dd->ipath_statusp));
+
+bail:
+	return ret;
+}
+
+static const char *ipath_status_str[] = {
+	"Initted",
+	"Disabled",
+	"Admin_Disabled",
+	"OIB_SMA",
+	"SMA",
+	"Present",
+	"IB_link_up",
+	"IB_configured",
+	"NoIBcable",
+	"Fatal_Hardware_Error",
+	NULL,
+};
+
+static ssize_t show_status_str(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int i, any;
+	u64 s;
+	ssize_t ret;
+
+	if (!dd->ipath_statusp) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	s = *(dd->ipath_statusp);
+	*buf = '\0';
+	for (any = i = 0; s && ipath_status_str[i]; i++) {
+		if (s & 1) {
+			if (any && strlcat(buf, " ", PAGE_SIZE) >=
+			    PAGE_SIZE)
+				/* overflow */
+				break;
+			if (strlcat(buf, ipath_status_str[i],
+				    PAGE_SIZE) >= PAGE_SIZE)
+				break;
+			any = 1;
+		}
+		s >>= 1;
+	}
+	if (any)
+		strlcat(buf, "\n", PAGE_SIZE);
+
+	ret = strlen(buf);
+
+bail:
+	return ret;
+}
+
+static ssize_t show_boardversion(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	/* The string printed here is already newline-terminated. */
+	return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
+}
+
+static ssize_t show_lid(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
+}
+
+static ssize_t store_lid(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	u16 lid;
+	int ret;
+
+	ret = ipath_parse_ushort(buf, &lid);
+	if (ret < 0)
+		goto invalid;
+
+	if (lid == 0 || lid >= 0xc000) {
+		ret = -EINVAL;
+		goto invalid;
+	}
+
+	ipath_set_sps_lid(dd, lid, 0);
+
+	goto bail;
+invalid:
+	ipath_dev_err(dd, "attempt to set invalid LID\n");
+bail:
+	return ret;
+}
+
+static ssize_t show_mlid(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
+}
+
+static ssize_t store_mlid(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int unit;
+	u16 mlid;
+	int ret;
+
+	ret = ipath_parse_ushort(buf, &mlid);
+	if (ret < 0)
+		goto invalid;
+
+	unit = dd->ipath_unit;
+
+	dd->ipath_mlid = mlid;
+	ipath_stats.sps_mlid[unit] = mlid;
+	ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST);
+
+	goto bail;
+invalid:
+	ipath_dev_err(dd, "attempt to set invalid MLID\n");
+bail:
+	return ret;
+}
+
+static ssize_t show_guid(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	u8 *guid;
+
+	guid = (u8 *) & (dd->ipath_guid);
+
+	return scnprintf(buf, PAGE_SIZE,
+			 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 guid[0], guid[1], guid[2], guid[3],
+			 guid[4], guid[5], guid[6], guid[7]);
+}
+
+static ssize_t store_guid(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	ssize_t ret;
+	unsigned short guid[8];
+	__be64 nguid;
+	u8 *ng;
+	int i;
+
+	if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
+		   &guid[0], &guid[1], &guid[2], &guid[3],
+		   &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
+		goto invalid;
+
+	ng = (u8 *) &nguid;
+
+	for (i = 0; i < 8; i++) {
+		if (guid[i] > 0xff)
+			goto invalid;
+		ng[i] = guid[i];
+	}
+
+	dd->ipath_guid = nguid;
+	dd->ipath_nguid = 1;
+
+	ret = strlen(buf);
+	goto bail;
+
+invalid:
+	ipath_dev_err(dd, "attempt to set invalid GUID\n");
+	ret = -EINVAL;
+
+bail:
+	return ret;
+}
+
+static ssize_t show_nguid(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
+}
+
+static ssize_t show_serial(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+	buf[sizeof dd->ipath_serial] = '\0';
+	memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
+	strcat(buf, "\n");
+	return strlen(buf);
+}
+
+static ssize_t show_unit(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
+}
+
+#define DEVICE_COUNTER(name, attr) \
+	static ssize_t show_counter_##name(struct device *dev, \
+					   struct device_attribute *attr, \
+					   char *buf) \
+	{ \
+		struct ipath_devdata *dd = dev_get_drvdata(dev); \
+		return scnprintf(\
+			buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
+			ipath_snap_cntr( \
+				dd, offsetof(struct infinipath_counters, \
+					     attr) / sizeof(u64)));	\
+	} \
+	static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
+
+DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
+DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
+DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
+DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
+DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
+DEVICE_COUNTER(lb_ints, LBIntCnt);
+DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
+DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
+DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
+DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
+DEVICE_COUNTER(rx_dwords, RxDwordCnt);
+DEVICE_COUNTER(rx_ebps, RxEBPCnt);
+DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
+DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
+DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
+DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
+DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
+DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
+DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
+DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
+DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
+DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
+DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
+DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
+DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
+DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
+DEVICE_COUNTER(tx_dwords, TxDwordCnt);
+DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
+DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
+DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
+DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
+DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
+DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
+
+static struct attribute *dev_counter_attributes[] = {
+	&dev_attr_ib_link_downeds.attr,
+	&dev_attr_ib_link_err_recoveries.attr,
+	&dev_attr_ib_status_changes.attr,
+	&dev_attr_ib_symbol_errs.attr,
+	&dev_attr_lb_flow_stalls.attr,
+	&dev_attr_lb_ints.attr,
+	&dev_attr_rx_bad_formats.attr,
+	&dev_attr_rx_buf_ovfls.attr,
+	&dev_attr_rx_data_pkts.attr,
+	&dev_attr_rx_dropped_pkts.attr,
+	&dev_attr_rx_dwords.attr,
+	&dev_attr_rx_ebps.attr,
+	&dev_attr_rx_flow_ctrl_errs.attr,
+	&dev_attr_rx_flow_pkts.attr,
+	&dev_attr_rx_icrc_errs.attr,
+	&dev_attr_rx_len_errs.attr,
+	&dev_attr_rx_link_problems.attr,
+	&dev_attr_rx_lpcrc_errs.attr,
+	&dev_attr_rx_max_min_len_errs.attr,
+	&dev_attr_rx_p0_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p1_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p2_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p3_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p4_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p5_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p6_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p7_hdr_egr_ovfls.attr,
+	&dev_attr_rx_p8_hdr_egr_ovfls.attr,
+	&dev_attr_rx_pkey_mismatches.attr,
+	&dev_attr_rx_tid_full_errs.attr,
+	&dev_attr_rx_tid_valid_errs.attr,
+	&dev_attr_rx_vcrc_errs.attr,
+	&dev_attr_tx_data_pkts.attr,
+	&dev_attr_tx_dropped_pkts.attr,
+	&dev_attr_tx_dwords.attr,
+	&dev_attr_tx_flow_pkts.attr,
+	&dev_attr_tx_flow_stalls.attr,
+	&dev_attr_tx_len_errs.attr,
+	&dev_attr_tx_max_min_len_errs.attr,
+	&dev_attr_tx_underruns.attr,
+	&dev_attr_tx_unsup_vl_errs.attr,
+	NULL
+};
+
+static struct attribute_group dev_counter_attr_group = {
+	.name = "counters",
+	.attrs = dev_counter_attributes
+};
+
+static ssize_t store_reset(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int ret;
+
+	if (count < 5 || memcmp(buf, "reset", 5)) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if (dd->ipath_flags & IPATH_DISABLED) {
+		/*
+		 * post-reset init would re-enable interrupts, etc.
+		 * so don't allow reset on disabled devices.  Not
+		 * perfect error, but about the best choice.
+		 */
+		dev_info(dev,"Unit %d is disabled, can't reset\n",
+			 dd->ipath_unit);
+		ret = -EINVAL;
+	}
+	ret = ipath_reset_device(dd->ipath_unit);
+bail:
+	return ret<0 ? ret : count;
+}
+
+static ssize_t store_link_state(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	int ret, r;
+	u16 state;
+
+	ret = ipath_parse_ushort(buf, &state);
+	if (ret < 0)
+		goto invalid;
+
+	r = ipath_layer_set_linkstate(dd, state);
+	if (r < 0) {
+		ret = r;
+		goto bail;
+	}
+
+	goto bail;
+invalid:
+	ipath_dev_err(dd, "attempt to set invalid link state\n");
+bail:
+	return ret;
+}
+
+static ssize_t show_mtu(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
+}
+
+static ssize_t store_mtu(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	ssize_t ret;
+	u16 mtu = 0;
+	int r;
+
+	ret = ipath_parse_ushort(buf, &mtu);
+	if (ret < 0)
+		goto invalid;
+
+	r = ipath_layer_set_mtu(dd, mtu);
+	if (r < 0)
+		ret = r;
+
+	goto bail;
+invalid:
+	ipath_dev_err(dd, "attempt to set invalid MTU\n");
+bail:
+	return ret;
+}
+
+static ssize_t show_enabled(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%u\n",
+			 (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
+}
+
+static ssize_t store_enabled(struct device *dev,
+			 struct device_attribute *attr,
+			  const char *buf,
+			  size_t count)
+{
+	struct ipath_devdata *dd = dev_get_drvdata(dev);
+	ssize_t ret;
+	u16 enable = 0;
+
+	ret = ipath_parse_ushort(buf, &enable);
+	if (ret < 0) {
+		ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
+		goto bail;
+	}
+
+	if (enable) {
+		if (!(dd->ipath_flags & IPATH_DISABLED))
+			goto bail;
+
+		dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
+		/* same as post-reset */
+		ret = ipath_init_chip(dd, 1);
+		if (ret)
+			ipath_dev_err(dd, "Failed to enable unit %d\n",
+				      dd->ipath_unit);
+		else {
+			dd->ipath_flags &= ~IPATH_DISABLED;
+			*dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
+		}
+	}
+	else if (!(dd->ipath_flags & IPATH_DISABLED)) {
+		dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
+		ipath_shutdown_device(dd);
+		dd->ipath_flags |= IPATH_DISABLED;
+		*dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
+	}
+
+bail:
+	return ret;
+}
+
+static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
+static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
+
+static struct attribute *driver_attributes[] = {
+	&driver_attr_num_units.attr,
+	&driver_attr_version.attr,
+	NULL
+};
+
+static struct attribute_group driver_attr_group = {
+	.attrs = driver_attributes
+};
+
+static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
+static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
+static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
+static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
+static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
+static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
+static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
+static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
+static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
+static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
+static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
+
+static struct attribute *dev_attributes[] = {
+	&dev_attr_guid.attr,
+	&dev_attr_lid.attr,
+	&dev_attr_link_state.attr,
+	&dev_attr_mlid.attr,
+	&dev_attr_mtu.attr,
+	&dev_attr_nguid.attr,
+	&dev_attr_serial.attr,
+	&dev_attr_status.attr,
+	&dev_attr_status_str.attr,
+	&dev_attr_boardversion.attr,
+	&dev_attr_unit.attr,
+	&dev_attr_enabled.attr,
+	NULL
+};
+
+static struct attribute_group dev_attr_group = {
+	.attrs = dev_attributes
+};
+
+/**
+ * ipath_expose_reset - create a device reset file
+ * @dev: the device structure
+ *
+ * Only expose a file that lets us reset the device after someone
+ * enters diag mode.  A device reset is quite likely to crash the
+ * machine entirely, so we don't want to normally make it
+ * available.
+ */
+int ipath_expose_reset(struct device *dev)
+{
+	return device_create_file(dev, &dev_attr_reset);
+}
+
+int ipath_driver_create_group(struct device_driver *drv)
+{
+	int ret;
+
+	ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
+	if (ret)
+		goto bail;
+
+	ret = sysfs_create_group(&drv->kobj, &driver_stat_attr_group);
+	if (ret)
+		sysfs_remove_group(&drv->kobj, &driver_attr_group);
+
+bail:
+	return ret;
+}
+
+void ipath_driver_remove_group(struct device_driver *drv)
+{
+	sysfs_remove_group(&drv->kobj, &driver_stat_attr_group);
+	sysfs_remove_group(&drv->kobj, &driver_attr_group);
+}
+
+int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
+{
+	int ret;
+	char unit[5];
+
+	ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
+	if (ret)
+		goto bail;
+
+	ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
+	if (ret)
+		goto bail_attrs;
+
+	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
+	if (ret == 0)
+		goto bail;
+
+	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+bail_attrs:
+	sysfs_remove_group(&dev->kobj, &dev_attr_group);
+bail:
+	return ret;
+}
+
+void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
+{
+	char unit[5];
+
+	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+	sysfs_remove_link(&dev->driver->kobj, unit);
+
+	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+	sysfs_remove_group(&dev->kobj, &dev_attr_group);
+
+	device_remove_file(dev, &dev_attr_reset);
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
new file mode 100644
index 0000000..0d6dbc0
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* cut down ridiculously long IB macro names */
+#define OP(x) IB_OPCODE_UC_##x
+
+static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
+			       struct ib_wc *wc)
+{
+	if (++qp->s_last == qp->s_size)
+		qp->s_last = 0;
+	if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+	    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
+		wc->wr_id = wqe->wr.wr_id;
+		wc->status = IB_WC_SUCCESS;
+		wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+		wc->vendor_err = 0;
+		wc->byte_len = wqe->length;
+		wc->qp_num = qp->ibqp.qp_num;
+		wc->src_qp = qp->remote_qpn;
+		wc->pkey_index = 0;
+		wc->slid = qp->remote_ah_attr.dlid;
+		wc->sl = qp->remote_ah_attr.sl;
+		wc->dlid_path_bits = 0;
+		wc->port_num = 0;
+		ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
+	}
+	wqe = get_swqe_ptr(qp, qp->s_last);
+}
+
+/**
+ * ipath_do_uc_send - do a send on a UC queue
+ * @data: contains a pointer to the QP to send on
+ *
+ * Process entries in the send work queue until the queue is exhausted.
+ * Only allow one CPU to send a packet per QP (tasklet).
+ * Otherwise, after we drop the QP lock, two threads could send
+ * packets out of order.
+ * This is similar to ipath_do_rc_send() below except we don't have
+ * timeouts or resends.
+ */
+void ipath_do_uc_send(unsigned long data)
+{
+	struct ipath_qp *qp = (struct ipath_qp *)data;
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ipath_swqe *wqe;
+	unsigned long flags;
+	u16 lrh0;
+	u32 hwords;
+	u32 nwords;
+	u32 extra_bytes;
+	u32 bth0;
+	u32 bth2;
+	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	u32 len;
+	struct ipath_other_headers *ohdr;
+	struct ib_wc wc;
+
+	if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags))
+		goto bail;
+
+	if (unlikely(qp->remote_ah_attr.dlid ==
+		     ipath_layer_get_lid(dev->dd))) {
+		/* Pass in an uninitialized ib_wc to save stack space. */
+		ipath_ruc_loopback(qp, &wc);
+		clear_bit(IPATH_S_BUSY, &qp->s_flags);
+		goto bail;
+	}
+
+	ohdr = &qp->s_hdr.u.oth;
+	if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
+		ohdr = &qp->s_hdr.u.l.oth;
+
+again:
+	/* Check for a constructed packet to be sent. */
+	if (qp->s_hdrwords != 0) {
+			/*
+			 * If no PIO bufs are available, return.
+			 * An interrupt will call ipath_ib_piobufavail()
+			 * when one is available.
+			 */
+			if (ipath_verbs_send(dev->dd, qp->s_hdrwords,
+					     (u32 *) &qp->s_hdr,
+					     qp->s_cur_size,
+					     qp->s_cur_sge)) {
+				ipath_no_bufs_available(qp, dev);
+				goto bail;
+			}
+			dev->n_unicast_xmit++;
+		/* Record that we sent the packet and s_hdr is empty. */
+		qp->s_hdrwords = 0;
+	}
+
+	lrh0 = IPS_LRH_BTH;
+	/* header size in 32-bit words LRH+BTH = (8+12)/4. */
+	hwords = 5;
+
+	/*
+	 * The lock is needed to synchronize between
+	 * setting qp->s_ack_state and post_send().
+	 */
+	spin_lock_irqsave(&qp->s_lock, flags);
+
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK))
+		goto done;
+
+	bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+
+	/* Send a request. */
+	wqe = get_swqe_ptr(qp, qp->s_last);
+	switch (qp->s_state) {
+	default:
+		/*
+		 * Signal the completion of the last send (if there is
+		 * one).
+		 */
+		if (qp->s_last != qp->s_tail)
+			complete_last_send(qp, wqe, &wc);
+
+		/* Check if send work queue is empty. */
+		if (qp->s_tail == qp->s_head)
+			goto done;
+		/*
+		 * Start a new request.
+		 */
+		qp->s_psn = wqe->psn = qp->s_next_psn;
+		qp->s_sge.sge = wqe->sg_list[0];
+		qp->s_sge.sg_list = wqe->sg_list + 1;
+		qp->s_sge.num_sge = wqe->wr.num_sge;
+		qp->s_len = len = wqe->length;
+		switch (wqe->wr.opcode) {
+		case IB_WR_SEND:
+		case IB_WR_SEND_WITH_IMM:
+			if (len > pmtu) {
+				qp->s_state = OP(SEND_FIRST);
+				len = pmtu;
+				break;
+			}
+			if (wqe->wr.opcode == IB_WR_SEND)
+				qp->s_state = OP(SEND_ONLY);
+			else {
+				qp->s_state =
+					OP(SEND_ONLY_WITH_IMMEDIATE);
+				/* Immediate data comes after the BTH */
+				ohdr->u.imm_data = wqe->wr.imm_data;
+				hwords += 1;
+			}
+			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+				bth0 |= 1 << 23;
+			break;
+
+		case IB_WR_RDMA_WRITE:
+		case IB_WR_RDMA_WRITE_WITH_IMM:
+			ohdr->u.rc.reth.vaddr =
+				cpu_to_be64(wqe->wr.wr.rdma.remote_addr);
+			ohdr->u.rc.reth.rkey =
+				cpu_to_be32(wqe->wr.wr.rdma.rkey);
+			ohdr->u.rc.reth.length = cpu_to_be32(len);
+			hwords += sizeof(struct ib_reth) / 4;
+			if (len > pmtu) {
+				qp->s_state = OP(RDMA_WRITE_FIRST);
+				len = pmtu;
+				break;
+			}
+			if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+				qp->s_state = OP(RDMA_WRITE_ONLY);
+			else {
+				qp->s_state =
+					OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);
+				/* Immediate data comes after the RETH */
+				ohdr->u.rc.imm_data = wqe->wr.imm_data;
+				hwords += 1;
+				if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+					bth0 |= 1 << 23;
+			}
+			break;
+
+		default:
+			goto done;
+		}
+		if (++qp->s_tail >= qp->s_size)
+			qp->s_tail = 0;
+		break;
+
+	case OP(SEND_FIRST):
+		qp->s_state = OP(SEND_MIDDLE);
+		/* FALLTHROUGH */
+	case OP(SEND_MIDDLE):
+		len = qp->s_len;
+		if (len > pmtu) {
+			len = pmtu;
+			break;
+		}
+		if (wqe->wr.opcode == IB_WR_SEND)
+			qp->s_state = OP(SEND_LAST);
+		else {
+			qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
+			/* Immediate data comes after the BTH */
+			ohdr->u.imm_data = wqe->wr.imm_data;
+			hwords += 1;
+		}
+		if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+			bth0 |= 1 << 23;
+		break;
+
+	case OP(RDMA_WRITE_FIRST):
+		qp->s_state = OP(RDMA_WRITE_MIDDLE);
+		/* FALLTHROUGH */
+	case OP(RDMA_WRITE_MIDDLE):
+		len = qp->s_len;
+		if (len > pmtu) {
+			len = pmtu;
+			break;
+		}
+		if (wqe->wr.opcode == IB_WR_RDMA_WRITE)
+			qp->s_state = OP(RDMA_WRITE_LAST);
+		else {
+			qp->s_state =
+				OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);
+			/* Immediate data comes after the BTH */
+			ohdr->u.imm_data = wqe->wr.imm_data;
+			hwords += 1;
+			if (wqe->wr.send_flags & IB_SEND_SOLICITED)
+				bth0 |= 1 << 23;
+		}
+		break;
+	}
+	bth2 = qp->s_next_psn++ & IPS_PSN_MASK;
+	qp->s_len -= len;
+	bth0 |= qp->s_state << 24;
+
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+
+	/* Construct the header. */
+	extra_bytes = (4 - len) & 3;
+	nwords = (len + extra_bytes) >> 2;
+	if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
+		/* Header size in 32-bit words. */
+		hwords += 10;
+		lrh0 = IPS_LRH_GRH;
+		qp->s_hdr.u.l.grh.version_tclass_flow =
+			cpu_to_be32((6 << 28) |
+				    (qp->remote_ah_attr.grh.traffic_class
+				     << 20) |
+				    qp->remote_ah_attr.grh.flow_label);
+		qp->s_hdr.u.l.grh.paylen =
+			cpu_to_be16(((hwords - 12) + nwords +
+				     SIZE_OF_CRC) << 2);
+		/* next_hdr is defined by C8-7 in ch. 8.4.1 */
+		qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+		qp->s_hdr.u.l.grh.hop_limit =
+			qp->remote_ah_attr.grh.hop_limit;
+		/* The SGID is 32-bit aligned. */
+		qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+			dev->gid_prefix;
+		qp->s_hdr.u.l.grh.sgid.global.interface_id =
+			ipath_layer_get_guid(dev->dd);
+		qp->s_hdr.u.l.grh.dgid = qp->remote_ah_attr.grh.dgid;
+	}
+	qp->s_hdrwords = hwords;
+	qp->s_cur_sge = &qp->s_sge;
+	qp->s_cur_size = len;
+	lrh0 |= qp->remote_ah_attr.sl << 4;
+	qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+	/* DEST LID */
+	qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid);
+	qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+	qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd));
+	bth0 |= extra_bytes << 20;
+	ohdr->bth[0] = cpu_to_be32(bth0);
+	ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);
+	ohdr->bth[2] = cpu_to_be32(bth2);
+
+	/* Check for more work to do. */
+	goto again;
+
+done:
+	spin_unlock_irqrestore(&qp->s_lock, flags);
+	clear_bit(IPATH_S_BUSY, &qp->s_flags);
+
+bail:
+	return;
+}
+
+/**
+ * ipath_uc_rcv - handle an incoming UC packet
+ * @dev: the device the packet came in on
+ * @hdr: the header of the packet
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the length of the packet
+ * @qp: the QP for this packet.
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UC packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+	struct ipath_other_headers *ohdr;
+	int opcode;
+	u32 hdrsize;
+	u32 psn;
+	u32 pad;
+	unsigned long flags;
+	struct ib_wc wc;
+	u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);
+	struct ib_reth *reth;
+	int header_in_data;
+
+	/* Check for GRH */
+	if (!has_grh) {
+		ohdr = &hdr->u.oth;
+		hdrsize = 8 + 12;	/* LRH + BTH */
+		psn = be32_to_cpu(ohdr->bth[2]);
+		header_in_data = 0;
+	} else {
+		ohdr = &hdr->u.l.oth;
+		hdrsize = 8 + 40 + 12;	/* LRH + GRH + BTH */
+		/*
+		 * The header with GRH is 60 bytes and the
+		 * core driver sets the eager header buffer
+		 * size to 56 bytes so the last 4 bytes of
+		 * the BTH header (PSN) is in the data buffer.
+		 */
+		header_in_data =
+			ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+		if (header_in_data) {
+			psn = be32_to_cpu(((__be32 *) data)[0]);
+			data += sizeof(__be32);
+		} else
+			psn = be32_to_cpu(ohdr->bth[2]);
+	}
+	/*
+	 * The opcode is in the low byte when its in network order
+	 * (top byte when in host order).
+	 */
+	opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+
+	wc.imm_data = 0;
+	wc.wc_flags = 0;
+
+	spin_lock_irqsave(&qp->r_rq.lock, flags);
+
+	/* Compare the PSN verses the expected PSN. */
+	if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) {
+		/*
+		 * Handle a sequence error.
+		 * Silently drop any current message.
+		 */
+		qp->r_psn = psn;
+	inv:
+		qp->r_state = OP(SEND_LAST);
+		switch (opcode) {
+		case OP(SEND_FIRST):
+		case OP(SEND_ONLY):
+		case OP(SEND_ONLY_WITH_IMMEDIATE):
+			goto send_first;
+
+		case OP(RDMA_WRITE_FIRST):
+		case OP(RDMA_WRITE_ONLY):
+		case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+			goto rdma_first;
+
+		default:
+			dev->n_pkt_drops++;
+			goto done;
+		}
+	}
+
+	/* Check for opcode sequence errors. */
+	switch (qp->r_state) {
+	case OP(SEND_FIRST):
+	case OP(SEND_MIDDLE):
+		if (opcode == OP(SEND_MIDDLE) ||
+		    opcode == OP(SEND_LAST) ||
+		    opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+			break;
+		goto inv;
+
+	case OP(RDMA_WRITE_FIRST):
+	case OP(RDMA_WRITE_MIDDLE):
+		if (opcode == OP(RDMA_WRITE_MIDDLE) ||
+		    opcode == OP(RDMA_WRITE_LAST) ||
+		    opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
+			break;
+		goto inv;
+
+	default:
+		if (opcode == OP(SEND_FIRST) ||
+		    opcode == OP(SEND_ONLY) ||
+		    opcode == OP(SEND_ONLY_WITH_IMMEDIATE) ||
+		    opcode == OP(RDMA_WRITE_FIRST) ||
+		    opcode == OP(RDMA_WRITE_ONLY) ||
+		    opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+			break;
+		goto inv;
+	}
+
+	/* OK, process the packet. */
+	switch (opcode) {
+	case OP(SEND_FIRST):
+	case OP(SEND_ONLY):
+	case OP(SEND_ONLY_WITH_IMMEDIATE):
+	send_first:
+		if (qp->r_reuse_sge) {
+			qp->r_reuse_sge = 0;
+			qp->r_sge = qp->s_rdma_sge;
+		} else if (!ipath_get_rwqe(qp, 0)) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		/* Save the WQE so we can reuse it in case of an error. */
+		qp->s_rdma_sge = qp->r_sge;
+		qp->r_rcv_len = 0;
+		if (opcode == OP(SEND_ONLY))
+			goto send_last;
+		else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))
+			goto send_last_imm;
+		/* FALLTHROUGH */
+	case OP(SEND_MIDDLE):
+		/* Check for invalid length PMTU or posted rwqe len. */
+		if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+			qp->r_reuse_sge = 1;
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		qp->r_rcv_len += pmtu;
+		if (unlikely(qp->r_rcv_len > qp->r_len)) {
+			qp->r_reuse_sge = 1;
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		ipath_copy_sge(&qp->r_sge, data, pmtu);
+		break;
+
+	case OP(SEND_LAST_WITH_IMMEDIATE):
+	send_last_imm:
+		if (header_in_data) {
+			wc.imm_data = *(__be32 *) data;
+			data += sizeof(__be32);
+		} else {
+			/* Immediate data comes after BTH */
+			wc.imm_data = ohdr->u.imm_data;
+		}
+		hdrsize += 4;
+		wc.wc_flags = IB_WC_WITH_IMM;
+		/* FALLTHROUGH */
+	case OP(SEND_LAST):
+	send_last:
+		/* Get the number of bytes the message was padded by. */
+		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+		/* Check for invalid length. */
+		/* XXX LAST len should be >= 1 */
+		if (unlikely(tlen < (hdrsize + pad + 4))) {
+			qp->r_reuse_sge = 1;
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		/* Don't count the CRC. */
+		tlen -= (hdrsize + pad + 4);
+		wc.byte_len = tlen + qp->r_rcv_len;
+		if (unlikely(wc.byte_len > qp->r_len)) {
+			qp->r_reuse_sge = 1;
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		/* XXX Need to free SGEs */
+	last_imm:
+		ipath_copy_sge(&qp->r_sge, data, tlen);
+		wc.wr_id = qp->r_wr_id;
+		wc.status = IB_WC_SUCCESS;
+		wc.opcode = IB_WC_RECV;
+		wc.vendor_err = 0;
+		wc.qp_num = qp->ibqp.qp_num;
+		wc.src_qp = qp->remote_qpn;
+		wc.pkey_index = 0;
+		wc.slid = qp->remote_ah_attr.dlid;
+		wc.sl = qp->remote_ah_attr.sl;
+		wc.dlid_path_bits = 0;
+		wc.port_num = 0;
+		/* Signal completion event if the solicited bit is set. */
+		ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+			       (ohdr->bth[0] &
+				__constant_cpu_to_be32(1 << 23)) != 0);
+		break;
+
+	case OP(RDMA_WRITE_FIRST):
+	case OP(RDMA_WRITE_ONLY):
+	case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */
+	rdma_first:
+		/* RETH comes after BTH */
+		if (!header_in_data)
+			reth = &ohdr->u.rc.reth;
+		else {
+			reth = (struct ib_reth *)data;
+			data += sizeof(*reth);
+		}
+		hdrsize += sizeof(*reth);
+		qp->r_len = be32_to_cpu(reth->length);
+		qp->r_rcv_len = 0;
+		if (qp->r_len != 0) {
+			u32 rkey = be32_to_cpu(reth->rkey);
+			u64 vaddr = be64_to_cpu(reth->vaddr);
+
+			/* Check rkey */
+			if (unlikely(!ipath_rkey_ok(
+					     dev, &qp->r_sge, qp->r_len,
+					     vaddr, rkey,
+					     IB_ACCESS_REMOTE_WRITE))) {
+				dev->n_pkt_drops++;
+				goto done;
+			}
+		} else {
+			qp->r_sge.sg_list = NULL;
+			qp->r_sge.sge.mr = NULL;
+			qp->r_sge.sge.vaddr = NULL;
+			qp->r_sge.sge.length = 0;
+			qp->r_sge.sge.sge_length = 0;
+		}
+		if (unlikely(!(qp->qp_access_flags &
+			       IB_ACCESS_REMOTE_WRITE))) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		if (opcode == OP(RDMA_WRITE_ONLY))
+			goto rdma_last;
+		else if (opcode ==
+			 OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+			goto rdma_last_imm;
+		/* FALLTHROUGH */
+	case OP(RDMA_WRITE_MIDDLE):
+		/* Check for invalid length PMTU or posted rwqe len. */
+		if (unlikely(tlen != (hdrsize + pmtu + 4))) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		qp->r_rcv_len += pmtu;
+		if (unlikely(qp->r_rcv_len > qp->r_len)) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		ipath_copy_sge(&qp->r_sge, data, pmtu);
+		break;
+
+	case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
+	rdma_last_imm:
+		/* Get the number of bytes the message was padded by. */
+		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+		/* Check for invalid length. */
+		/* XXX LAST len should be >= 1 */
+		if (unlikely(tlen < (hdrsize + pad + 4))) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		/* Don't count the CRC. */
+		tlen -= (hdrsize + pad + 4);
+		if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		if (qp->r_reuse_sge) {
+			qp->r_reuse_sge = 0;
+		} else if (!ipath_get_rwqe(qp, 1)) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		if (header_in_data) {
+			wc.imm_data = *(__be32 *) data;
+			data += sizeof(__be32);
+		} else {
+			/* Immediate data comes after BTH */
+			wc.imm_data = ohdr->u.imm_data;
+		}
+		hdrsize += 4;
+		wc.wc_flags = IB_WC_WITH_IMM;
+		wc.byte_len = 0;
+		goto last_imm;
+
+	case OP(RDMA_WRITE_LAST):
+	rdma_last:
+		/* Get the number of bytes the message was padded by. */
+		pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+		/* Check for invalid length. */
+		/* XXX LAST len should be >= 1 */
+		if (unlikely(tlen < (hdrsize + pad + 4))) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		/* Don't count the CRC. */
+		tlen -= (hdrsize + pad + 4);
+		if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {
+			dev->n_pkt_drops++;
+			goto done;
+		}
+		ipath_copy_sge(&qp->r_sge, data, tlen);
+		break;
+
+	default:
+		/* Drop packet for unknown opcodes. */
+		spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+	qp->r_psn++;
+	qp->r_state = opcode;
+done:
+	spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+
+bail:
+	return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
new file mode 100644
index 0000000..01cfb30
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_smi.h>
+
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/**
+ * ipath_ud_loopback - handle send on loopback QPs
+ * @sqp: the QP
+ * @ss: the SGE state
+ * @length: the length of the data to send
+ * @wr: the work request
+ * @wc: the work completion entry
+ *
+ * This is called from ipath_post_ud_send() to forward a WQE addressed
+ * to the same HCA.
+ */
+static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
+			      u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
+{
+	struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
+	struct ipath_qp *qp;
+	struct ib_ah_attr *ah_attr;
+	unsigned long flags;
+	struct ipath_rq *rq;
+	struct ipath_srq *srq;
+	struct ipath_sge_state rsge;
+	struct ipath_sge *sge;
+	struct ipath_rwqe *wqe;
+
+	qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn);
+	if (!qp)
+		return;
+
+	/*
+	 * Check that the qkey matches (except for QP0, see 9.6.1.4.1).
+	 * Qkeys with the high order bit set mean use the
+	 * qkey from the QP context instead of the WR (see 10.2.5).
+	 */
+	if (unlikely(qp->ibqp.qp_num &&
+		     ((int) wr->wr.ud.remote_qkey < 0
+		      ? qp->qkey : wr->wr.ud.remote_qkey) != qp->qkey)) {
+		/* XXX OK to lose a count once in a while. */
+		dev->qkey_violations++;
+		dev->n_pkt_drops++;
+		goto done;
+	}
+
+	/*
+	 * A GRH is expected to preceed the data even if not
+	 * present on the wire.
+	 */
+	wc->byte_len = length + sizeof(struct ib_grh);
+
+	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+		wc->wc_flags = IB_WC_WITH_IMM;
+		wc->imm_data = wr->imm_data;
+	} else {
+		wc->wc_flags = 0;
+		wc->imm_data = 0;
+	}
+
+	/*
+	 * Get the next work request entry to find where to put the data.
+	 * Note that it is safe to drop the lock after changing rq->tail
+	 * since ipath_post_receive() won't fill the empty slot.
+	 */
+	if (qp->ibqp.srq) {
+		srq = to_isrq(qp->ibqp.srq);
+		rq = &srq->rq;
+	} else {
+		srq = NULL;
+		rq = &qp->r_rq;
+	}
+	spin_lock_irqsave(&rq->lock, flags);
+	if (rq->tail == rq->head) {
+		spin_unlock_irqrestore(&rq->lock, flags);
+		dev->n_pkt_drops++;
+		goto done;
+	}
+	/* Silently drop packets which are too big. */
+	wqe = get_rwqe_ptr(rq, rq->tail);
+	if (wc->byte_len > wqe->length) {
+		spin_unlock_irqrestore(&rq->lock, flags);
+		dev->n_pkt_drops++;
+		goto done;
+	}
+	wc->wr_id = wqe->wr_id;
+	rsge.sge = wqe->sg_list[0];
+	rsge.sg_list = wqe->sg_list + 1;
+	rsge.num_sge = wqe->num_sge;
+	if (++rq->tail >= rq->size)
+		rq->tail = 0;
+	if (srq && srq->ibsrq.event_handler) {
+		u32 n;
+
+		if (rq->head < rq->tail)
+			n = rq->size + rq->head - rq->tail;
+		else
+			n = rq->head - rq->tail;
+		if (n < srq->limit) {
+			struct ib_event ev;
+
+			srq->limit = 0;
+			spin_unlock_irqrestore(&rq->lock, flags);
+			ev.device = qp->ibqp.device;
+			ev.element.srq = qp->ibqp.srq;
+			ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+			srq->ibsrq.event_handler(&ev,
+						 srq->ibsrq.srq_context);
+		} else
+			spin_unlock_irqrestore(&rq->lock, flags);
+	} else
+		spin_unlock_irqrestore(&rq->lock, flags);
+	ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+	if (ah_attr->ah_flags & IB_AH_GRH) {
+		ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh));
+		wc->wc_flags |= IB_WC_GRH;
+	} else
+		ipath_skip_sge(&rsge, sizeof(struct ib_grh));
+	sge = &ss->sge;
+	while (length) {
+		u32 len = sge->length;
+
+		if (len > length)
+			len = length;
+		BUG_ON(len == 0);
+		ipath_copy_sge(&rsge, sge->vaddr, len);
+		sge->vaddr += len;
+		sge->length -= len;
+		sge->sge_length -= len;
+		if (sge->sge_length == 0) {
+			if (--ss->num_sge)
+				*sge = *ss->sg_list++;
+		} else if (sge->length == 0 && sge->mr != NULL) {
+			if (++sge->n >= IPATH_SEGSZ) {
+				if (++sge->m >= sge->mr->mapsz)
+					break;
+				sge->n = 0;
+			}
+			sge->vaddr =
+				sge->mr->map[sge->m]->segs[sge->n].vaddr;
+			sge->length =
+				sge->mr->map[sge->m]->segs[sge->n].length;
+		}
+		length -= len;
+	}
+	wc->status = IB_WC_SUCCESS;
+	wc->opcode = IB_WC_RECV;
+	wc->vendor_err = 0;
+	wc->qp_num = qp->ibqp.qp_num;
+	wc->src_qp = sqp->ibqp.qp_num;
+	/* XXX do we know which pkey matched? Only needed for GSI. */
+	wc->pkey_index = 0;
+	wc->slid = ipath_layer_get_lid(dev->dd) |
+		(ah_attr->src_path_bits &
+		 ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1));
+	wc->sl = ah_attr->sl;
+	wc->dlid_path_bits =
+		ah_attr->dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+	/* Signal completion event if the solicited bit is set. */
+	ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc,
+		       wr->send_flags & IB_SEND_SOLICITED);
+
+done:
+	if (atomic_dec_and_test(&qp->refcount))
+		wake_up(&qp->wait);
+}
+
+/**
+ * ipath_post_ud_send - post a UD send on QP
+ * @qp: the QP
+ * @wr: the work request
+ *
+ * Note that we actually send the data as it is posted instead of putting
+ * the request into a ring buffer.  If we wanted to use a ring buffer,
+ * we would need to save a reference to the destination address in the SWQE.
+ */
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr)
+{
+	struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+	struct ipath_other_headers *ohdr;
+	struct ib_ah_attr *ah_attr;
+	struct ipath_sge_state ss;
+	struct ipath_sge *sg_list;
+	struct ib_wc wc;
+	u32 hwords;
+	u32 nwords;
+	u32 len;
+	u32 extra_bytes;
+	u32 bth0;
+	u16 lrh0;
+	u16 lid;
+	int i;
+	int ret;
+
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) {
+		ret = 0;
+		goto bail;
+	}
+
+	/* IB spec says that num_sge == 0 is OK. */
+	if (wr->num_sge > qp->s_max_sge) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	if (wr->num_sge > 1) {
+		sg_list = kmalloc((qp->s_max_sge - 1) * sizeof(*sg_list),
+				  GFP_ATOMIC);
+		if (!sg_list) {
+			ret = -ENOMEM;
+			goto bail;
+		}
+	} else
+		sg_list = NULL;
+
+	/* Check the buffer to send. */
+	ss.sg_list = sg_list;
+	ss.sge.mr = NULL;
+	ss.sge.vaddr = NULL;
+	ss.sge.length = 0;
+	ss.sge.sge_length = 0;
+	ss.num_sge = 0;
+	len = 0;
+	for (i = 0; i < wr->num_sge; i++) {
+		/* Check LKEY */
+		if (to_ipd(qp->ibqp.pd)->user && wr->sg_list[i].lkey == 0) {
+			ret = -EINVAL;
+			goto bail;
+		}
+
+		if (wr->sg_list[i].length == 0)
+			continue;
+		if (!ipath_lkey_ok(&dev->lk_table, ss.num_sge ?
+				   sg_list + ss.num_sge - 1 : &ss.sge,
+				   &wr->sg_list[i], 0)) {
+			ret = -EINVAL;
+			goto bail;
+		}
+		len += wr->sg_list[i].length;
+		ss.num_sge++;
+	}
+	extra_bytes = (4 - len) & 3;
+	nwords = (len + extra_bytes) >> 2;
+
+	/* Construct the header. */
+	ah_attr = &to_iah(wr->wr.ud.ah)->attr;
+	if (ah_attr->dlid == 0) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE) {
+		if (ah_attr->dlid != IPS_PERMISSIVE_LID)
+			dev->n_multicast_xmit++;
+		else
+			dev->n_unicast_xmit++;
+	} else {
+		dev->n_unicast_xmit++;
+		lid = ah_attr->dlid &
+			~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+		if (unlikely(lid == ipath_layer_get_lid(dev->dd))) {
+			/*
+			 * Pass in an uninitialized ib_wc to save stack
+			 * space.
+			 */
+			ipath_ud_loopback(qp, &ss, len, wr, &wc);
+			goto done;
+		}
+	}
+	if (ah_attr->ah_flags & IB_AH_GRH) {
+		/* Header size in 32-bit words. */
+		hwords = 17;
+		lrh0 = IPS_LRH_GRH;
+		ohdr = &qp->s_hdr.u.l.oth;
+		qp->s_hdr.u.l.grh.version_tclass_flow =
+			cpu_to_be32((6 << 28) |
+				    (ah_attr->grh.traffic_class << 20) |
+				    ah_attr->grh.flow_label);
+		qp->s_hdr.u.l.grh.paylen =
+			cpu_to_be16(((wr->opcode ==
+				      IB_WR_SEND_WITH_IMM ? 6 : 5) +
+				     nwords + SIZE_OF_CRC) << 2);
+		/* next_hdr is defined by C8-7 in ch. 8.4.1 */
+		qp->s_hdr.u.l.grh.next_hdr = 0x1B;
+		qp->s_hdr.u.l.grh.hop_limit = ah_attr->grh.hop_limit;
+		/* The SGID is 32-bit aligned. */
+		qp->s_hdr.u.l.grh.sgid.global.subnet_prefix =
+			dev->gid_prefix;
+		qp->s_hdr.u.l.grh.sgid.global.interface_id =
+			ipath_layer_get_guid(dev->dd);
+		qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid;
+		/*
+		 * Don't worry about sending to locally attached multicast
+		 * QPs.  It is unspecified by the spec. what happens.
+		 */
+	} else {
+		/* Header size in 32-bit words. */
+		hwords = 7;
+		lrh0 = IPS_LRH_BTH;
+		ohdr = &qp->s_hdr.u.oth;
+	}
+	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+		ohdr->u.ud.imm_data = wr->imm_data;
+		wc.imm_data = wr->imm_data;
+		hwords += 1;
+		bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+	} else if (wr->opcode == IB_WR_SEND) {
+		wc.imm_data = 0;
+		bth0 = IB_OPCODE_UD_SEND_ONLY << 24;
+	} else {
+		ret = -EINVAL;
+		goto bail;
+	}
+	lrh0 |= ah_attr->sl << 4;
+	if (qp->ibqp.qp_type == IB_QPT_SMI)
+		lrh0 |= 0xF000;	/* Set VL (see ch. 13.5.3.1) */
+	qp->s_hdr.lrh[0] = cpu_to_be16(lrh0);
+	qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid);	/* DEST LID */
+	qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC);
+	lid = ipath_layer_get_lid(dev->dd);
+	if (lid) {
+		lid |= ah_attr->src_path_bits &
+			((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+		qp->s_hdr.lrh[3] = cpu_to_be16(lid);
+	} else
+		qp->s_hdr.lrh[3] = IB_LID_PERMISSIVE;
+	if (wr->send_flags & IB_SEND_SOLICITED)
+		bth0 |= 1 << 23;
+	bth0 |= extra_bytes << 20;
+	bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPS_DEFAULT_P_KEY :
+		ipath_layer_get_pkey(dev->dd, qp->s_pkey_index);
+	ohdr->bth[0] = cpu_to_be32(bth0);
+	/*
+	 * Use the multicast QP if the destination LID is a multicast LID.
+	 */
+	ohdr->bth[1] = ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+		ah_attr->dlid != IPS_PERMISSIVE_LID ?
+		__constant_cpu_to_be32(IPS_MULTICAST_QPN) :
+		cpu_to_be32(wr->wr.ud.remote_qpn);
+	/* XXX Could lose a PSN count but not worth locking */
+	ohdr->bth[2] = cpu_to_be32(qp->s_next_psn++ & IPS_PSN_MASK);
+	/*
+	 * Qkeys with the high order bit set mean use the
+	 * qkey from the QP context instead of the WR (see 10.2.5).
+	 */
+	ohdr->u.ud.deth[0] = cpu_to_be32((int)wr->wr.ud.remote_qkey < 0 ?
+					 qp->qkey : wr->wr.ud.remote_qkey);
+	ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
+	if (ipath_verbs_send(dev->dd, hwords, (u32 *) &qp->s_hdr,
+			     len, &ss))
+		dev->n_no_piobuf++;
+
+done:
+	/* Queue the completion status entry. */
+	if (!test_bit(IPATH_S_SIGNAL_REQ_WR, &qp->s_flags) ||
+	    (wr->send_flags & IB_SEND_SIGNALED)) {
+		wc.wr_id = wr->wr_id;
+		wc.status = IB_WC_SUCCESS;
+		wc.vendor_err = 0;
+		wc.opcode = IB_WC_SEND;
+		wc.byte_len = len;
+		wc.qp_num = qp->ibqp.qp_num;
+		wc.src_qp = 0;
+		wc.wc_flags = 0;
+		/* XXX initialize other fields? */
+		ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
+	}
+	kfree(sg_list);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_ud_rcv - receive an incoming UD packet
+ * @dev: the device the packet came in on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_qp_rcv() to process an incoming UD packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp)
+{
+	struct ipath_other_headers *ohdr;
+	int opcode;
+	u32 hdrsize;
+	u32 pad;
+	unsigned long flags;
+	struct ib_wc wc;
+	u32 qkey;
+	u32 src_qp;
+	struct ipath_rq *rq;
+	struct ipath_srq *srq;
+	struct ipath_rwqe *wqe;
+	u16 dlid;
+	int header_in_data;
+
+	/* Check for GRH */
+	if (!has_grh) {
+		ohdr = &hdr->u.oth;
+		hdrsize = 8 + 12 + 8;	/* LRH + BTH + DETH */
+		qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+		src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+		header_in_data = 0;
+	} else {
+		ohdr = &hdr->u.l.oth;
+		hdrsize = 8 + 40 + 12 + 8; /* LRH + GRH + BTH + DETH */
+		/*
+		 * The header with GRH is 68 bytes and the core driver sets
+		 * the eager header buffer size to 56 bytes so the last 12
+		 * bytes of the IB header is in the data buffer.
+		 */
+		header_in_data =
+			ipath_layer_get_rcvhdrentsize(dev->dd) == 16;
+		if (header_in_data) {
+			qkey = be32_to_cpu(((__be32 *) data)[1]);
+			src_qp = be32_to_cpu(((__be32 *) data)[2]);
+			data += 12;
+		} else {
+			qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
+			src_qp = be32_to_cpu(ohdr->u.ud.deth[1]);
+		}
+	}
+	src_qp &= IPS_QPN_MASK;
+
+	/*
+	 * Check that the permissive LID is only used on QP0
+	 * and the QKEY matches (see 9.6.1.4.1 and 9.6.1.5.1).
+	 */
+	if (qp->ibqp.qp_num) {
+		if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE ||
+			     hdr->lrh[3] == IB_LID_PERMISSIVE)) {
+			dev->n_pkt_drops++;
+			goto bail;
+		}
+		if (unlikely(qkey != qp->qkey)) {
+			/* XXX OK to lose a count once in a while. */
+			dev->qkey_violations++;
+			dev->n_pkt_drops++;
+			goto bail;
+		}
+	} else if (hdr->lrh[1] == IB_LID_PERMISSIVE ||
+		   hdr->lrh[3] == IB_LID_PERMISSIVE) {
+		struct ib_smp *smp = (struct ib_smp *) data;
+
+		if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+			dev->n_pkt_drops++;
+			goto bail;
+		}
+	}
+
+	/* Get the number of bytes the message was padded by. */
+	pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+	if (unlikely(tlen < (hdrsize + pad + 4))) {
+		/* Drop incomplete packets. */
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+	tlen -= hdrsize + pad + 4;
+
+	/* Drop invalid MAD packets (see 13.5.3.1). */
+	if (unlikely((qp->ibqp.qp_num == 0 &&
+		      (tlen != 256 ||
+		       (be16_to_cpu(hdr->lrh[0]) >> 12) != 15)) ||
+		     (qp->ibqp.qp_num == 1 &&
+		      (tlen != 256 ||
+		       (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))) {
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+
+	/*
+	 * A GRH is expected to preceed the data even if not
+	 * present on the wire.
+	 */
+	wc.byte_len = tlen + sizeof(struct ib_grh);
+
+	/*
+	 * The opcode is in the low byte when its in network order
+	 * (top byte when in host order).
+	 */
+	opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+	if (qp->ibqp.qp_num > 1 &&
+	    opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
+		if (header_in_data) {
+			wc.imm_data = *(__be32 *) data;
+			data += sizeof(__be32);
+		} else
+			wc.imm_data = ohdr->u.ud.imm_data;
+		wc.wc_flags = IB_WC_WITH_IMM;
+		hdrsize += sizeof(u32);
+	} else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
+		wc.imm_data = 0;
+		wc.wc_flags = 0;
+	} else {
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+
+	/*
+	 * Get the next work request entry to find where to put the data.
+	 * Note that it is safe to drop the lock after changing rq->tail
+	 * since ipath_post_receive() won't fill the empty slot.
+	 */
+	if (qp->ibqp.srq) {
+		srq = to_isrq(qp->ibqp.srq);
+		rq = &srq->rq;
+	} else {
+		srq = NULL;
+		rq = &qp->r_rq;
+	}
+	spin_lock_irqsave(&rq->lock, flags);
+	if (rq->tail == rq->head) {
+		spin_unlock_irqrestore(&rq->lock, flags);
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+	/* Silently drop packets which are too big. */
+	wqe = get_rwqe_ptr(rq, rq->tail);
+	if (wc.byte_len > wqe->length) {
+		spin_unlock_irqrestore(&rq->lock, flags);
+		dev->n_pkt_drops++;
+		goto bail;
+	}
+	wc.wr_id = wqe->wr_id;
+	qp->r_sge.sge = wqe->sg_list[0];
+	qp->r_sge.sg_list = wqe->sg_list + 1;
+	qp->r_sge.num_sge = wqe->num_sge;
+	if (++rq->tail >= rq->size)
+		rq->tail = 0;
+	if (srq && srq->ibsrq.event_handler) {
+		u32 n;
+
+		if (rq->head < rq->tail)
+			n = rq->size + rq->head - rq->tail;
+		else
+			n = rq->head - rq->tail;
+		if (n < srq->limit) {
+			struct ib_event ev;
+
+			srq->limit = 0;
+			spin_unlock_irqrestore(&rq->lock, flags);
+			ev.device = qp->ibqp.device;
+			ev.element.srq = qp->ibqp.srq;
+			ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+			srq->ibsrq.event_handler(&ev,
+						 srq->ibsrq.srq_context);
+		} else
+			spin_unlock_irqrestore(&rq->lock, flags);
+	} else
+		spin_unlock_irqrestore(&rq->lock, flags);
+	if (has_grh) {
+		ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh,
+			       sizeof(struct ib_grh));
+		wc.wc_flags |= IB_WC_GRH;
+	} else
+		ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh));
+	ipath_copy_sge(&qp->r_sge, data,
+		       wc.byte_len - sizeof(struct ib_grh));
+	wc.status = IB_WC_SUCCESS;
+	wc.opcode = IB_WC_RECV;
+	wc.vendor_err = 0;
+	wc.qp_num = qp->ibqp.qp_num;
+	wc.src_qp = src_qp;
+	/* XXX do we know which pkey matched? Only needed for GSI. */
+	wc.pkey_index = 0;
+	wc.slid = be16_to_cpu(hdr->lrh[3]);
+	wc.sl = (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF;
+	dlid = be16_to_cpu(hdr->lrh[1]);
+	/*
+	 * Save the LMC lower bits if the destination LID is a unicast LID.
+	 */
+	wc.dlid_path_bits = dlid >= IPS_MULTICAST_LID_BASE ? 0 :
+		dlid & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+	/* Signal completion event if the solicited bit is set. */
+	ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,
+		       (ohdr->bth[0] &
+			__constant_cpu_to_be32(1 << 23)) != 0);
+
+bail:;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
new file mode 100644
index 0000000..2bb08af
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/mm.h>
+#include <linux/device.h>
+
+#include "ipath_kernel.h"
+
+static void __ipath_release_user_pages(struct page **p, size_t num_pages,
+				   int dirty)
+{
+	size_t i;
+
+	for (i = 0; i < num_pages; i++) {
+		ipath_cdbg(MM, "%lu/%lu put_page %p\n", (unsigned long) i,
+			   (unsigned long) num_pages, p[i]);
+		if (dirty)
+			set_page_dirty_lock(p[i]);
+		put_page(p[i]);
+	}
+}
+
+/* call with current->mm->mmap_sem held */
+static int __get_user_pages(unsigned long start_page, size_t num_pages,
+			struct page **p, struct vm_area_struct **vma)
+{
+	unsigned long lock_limit;
+	size_t got;
+	int ret;
+
+#if 0
+	/*
+	 * XXX - causes MPI programs to fail, haven't had time to check
+	 * yet
+	 */
+	if (!capable(CAP_IPC_LOCK)) {
+		ret = -EPERM;
+		goto bail;
+	}
+#endif
+
+	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
+		PAGE_SHIFT;
+
+	if (num_pages > lock_limit) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+
+	ipath_cdbg(VERBOSE, "pin %lx pages from vaddr %lx\n",
+		   (unsigned long) num_pages, start_page);
+
+	for (got = 0; got < num_pages; got += ret) {
+		ret = get_user_pages(current, current->mm,
+				     start_page + got * PAGE_SIZE,
+				     num_pages - got, 1, 1,
+				     p + got, vma);
+		if (ret < 0)
+			goto bail_release;
+	}
+
+	current->mm->locked_vm += num_pages;
+
+	ret = 0;
+	goto bail;
+
+bail_release:
+	__ipath_release_user_pages(p, got, 0);
+bail:
+	return ret;
+}
+
+/**
+ * ipath_get_user_pages - lock user pages into memory
+ * @start_page: the start page
+ * @num_pages: the number of pages
+ * @p: the output page structures
+ *
+ * This function takes a given start page (page aligned user virtual
+ * address) and pins it and the following specified number of pages.  For
+ * now, num_pages is always 1, but that will probably change at some point
+ * (because caller is doing expected sends on a single virtually contiguous
+ * buffer, so we can do all pages at once).
+ */
+int ipath_get_user_pages(unsigned long start_page, size_t num_pages,
+			 struct page **p)
+{
+	int ret;
+
+	down_write(&current->mm->mmap_sem);
+
+	ret = __get_user_pages(start_page, num_pages, p, NULL);
+
+	up_write(&current->mm->mmap_sem);
+
+	return ret;
+}
+
+/**
+ * ipath_get_user_pages_nocopy - lock a single page for I/O and mark shared
+ * @start_page: the page to lock
+ * @p: the output page structure
+ *
+ * This is similar to ipath_get_user_pages, but it's always one page, and we
+ * mark the page as locked for I/O, and shared.  This is used for the user
+ * process page that contains the destination address for the rcvhdrq tail
+ * update, so we need to have the vma. If we don't do this, the page can be
+ * taken away from us on fork, even if the child never touches it, and then
+ * the user process never sees the tail register updates.
+ */
+int ipath_get_user_pages_nocopy(unsigned long page, struct page **p)
+{
+	struct vm_area_struct *vma;
+	int ret;
+
+	down_write(&current->mm->mmap_sem);
+
+	ret = __get_user_pages(page, 1, p, &vma);
+
+	up_write(&current->mm->mmap_sem);
+
+	return ret;
+}
+
+void ipath_release_user_pages(struct page **p, size_t num_pages)
+{
+	down_write(&current->mm->mmap_sem);
+
+	__ipath_release_user_pages(p, num_pages, 1);
+
+	current->mm->locked_vm -= num_pages;
+
+	up_write(&current->mm->mmap_sem);
+}
+
+struct ipath_user_pages_work {
+	struct work_struct work;
+	struct mm_struct *mm;
+	unsigned long num_pages;
+};
+
+static void user_pages_account(void *ptr)
+{
+	struct ipath_user_pages_work *work = ptr;
+
+	down_write(&work->mm->mmap_sem);
+	work->mm->locked_vm -= work->num_pages;
+	up_write(&work->mm->mmap_sem);
+	mmput(work->mm);
+	kfree(work);
+}
+
+void ipath_release_user_pages_on_close(struct page **p, size_t num_pages)
+{
+	struct ipath_user_pages_work *work;
+	struct mm_struct *mm;
+
+	__ipath_release_user_pages(p, num_pages, 1);
+
+	mm = get_task_mm(current);
+	if (!mm)
+		goto bail;
+
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		goto bail_mm;
+
+	goto bail;
+
+	INIT_WORK(&work->work, user_pages_account, work);
+	work->mm = mm;
+	work->num_pages = num_pages;
+
+bail_mm:
+	mmput(mm);
+bail:
+	return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
new file mode 100644
index 0000000..8d2558a
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -0,0 +1,1222 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_mad.h>
+#include <rdma/ib_user_verbs.h>
+#include <linux/utsname.h>
+
+#include "ipath_kernel.h"
+#include "ipath_verbs.h"
+#include "ips_common.h"
+
+/* Not static, because we don't want the compiler removing it */
+const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR;
+
+static unsigned int ib_ipath_qp_table_size = 251;
+module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO);
+MODULE_PARM_DESC(qp_table_size, "QP table size");
+
+unsigned int ib_ipath_lkey_table_size = 12;
+module_param_named(lkey_table_size, ib_ipath_lkey_table_size, uint,
+		   S_IRUGO);
+MODULE_PARM_DESC(lkey_table_size,
+		 "LKEY table size in bits (2^n, 1 <= n <= 23)");
+
+unsigned int ib_ipath_debug;	/* debug mask */
+module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "Verbs debug mask");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("PathScale <support@pathscale.com>");
+MODULE_DESCRIPTION("Pathscale InfiniPath driver");
+
+const int ib_ipath_state_ops[IB_QPS_ERR + 1] = {
+	[IB_QPS_RESET] = 0,
+	[IB_QPS_INIT] = IPATH_POST_RECV_OK,
+	[IB_QPS_RTR] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+	[IB_QPS_RTS] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+	    IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK,
+	[IB_QPS_SQD] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK |
+	    IPATH_POST_SEND_OK,
+	[IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK,
+	[IB_QPS_ERR] = 0,
+};
+
+/*
+ * Translate ib_wr_opcode into ib_wc_opcode.
+ */
+const enum ib_wc_opcode ib_ipath_wc_opcode[] = {
+	[IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
+	[IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
+	[IB_WR_SEND] = IB_WC_SEND,
+	[IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
+	[IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
+	[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
+	[IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD
+};
+
+/*
+ * System image GUID.
+ */
+static __be64 sys_image_guid;
+
+/**
+ * ipath_copy_sge - copy data to SGE memory
+ * @ss: the SGE state
+ * @data: the data to copy
+ * @length: the length of the data
+ */
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
+{
+	struct ipath_sge *sge = &ss->sge;
+
+	while (length) {
+		u32 len = sge->length;
+
+		BUG_ON(len == 0);
+		if (len > length)
+			len = length;
+		memcpy(sge->vaddr, data, len);
+		sge->vaddr += len;
+		sge->length -= len;
+		sge->sge_length -= len;
+		if (sge->sge_length == 0) {
+			if (--ss->num_sge)
+				*sge = *ss->sg_list++;
+		} else if (sge->length == 0 && sge->mr != NULL) {
+			if (++sge->n >= IPATH_SEGSZ) {
+				if (++sge->m >= sge->mr->mapsz)
+					break;
+				sge->n = 0;
+			}
+			sge->vaddr =
+				sge->mr->map[sge->m]->segs[sge->n].vaddr;
+			sge->length =
+				sge->mr->map[sge->m]->segs[sge->n].length;
+		}
+		data += len;
+		length -= len;
+	}
+}
+
+/**
+ * ipath_skip_sge - skip over SGE memory - XXX almost dup of prev func
+ * @ss: the SGE state
+ * @length: the number of bytes to skip
+ */
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
+{
+	struct ipath_sge *sge = &ss->sge;
+
+	while (length > sge->sge_length) {
+		length -= sge->sge_length;
+		ss->sge = *ss->sg_list++;
+	}
+	while (length) {
+		u32 len = sge->length;
+
+		BUG_ON(len == 0);
+		if (len > length)
+			len = length;
+		sge->vaddr += len;
+		sge->length -= len;
+		sge->sge_length -= len;
+		if (sge->sge_length == 0) {
+			if (--ss->num_sge)
+				*sge = *ss->sg_list++;
+		} else if (sge->length == 0 && sge->mr != NULL) {
+			if (++sge->n >= IPATH_SEGSZ) {
+				if (++sge->m >= sge->mr->mapsz)
+					break;
+				sge->n = 0;
+			}
+			sge->vaddr =
+				sge->mr->map[sge->m]->segs[sge->n].vaddr;
+			sge->length =
+				sge->mr->map[sge->m]->segs[sge->n].length;
+		}
+		length -= len;
+	}
+}
+
+/**
+ * ipath_post_send - post a send on a QP
+ * @ibqp: the QP to post the send on
+ * @wr: the list of work requests to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+			   struct ib_send_wr **bad_wr)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	int err = 0;
+
+	/* Check that state is OK to post send. */
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK)) {
+		*bad_wr = wr;
+		err = -EINVAL;
+		goto bail;
+	}
+
+	for (; wr; wr = wr->next) {
+		switch (qp->ibqp.qp_type) {
+		case IB_QPT_UC:
+		case IB_QPT_RC:
+			err = ipath_post_rc_send(qp, wr);
+			break;
+
+		case IB_QPT_SMI:
+		case IB_QPT_GSI:
+		case IB_QPT_UD:
+			err = ipath_post_ud_send(qp, wr);
+			break;
+
+		default:
+			err = -EINVAL;
+		}
+		if (err) {
+			*bad_wr = wr;
+			break;
+		}
+	}
+
+bail:
+	return err;
+}
+
+/**
+ * ipath_post_receive - post a receive on a QP
+ * @ibqp: the QP to post the receive on
+ * @wr: the WR to post
+ * @bad_wr: the first bad WR is put here
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+			      struct ib_recv_wr **bad_wr)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	unsigned long flags;
+	int ret;
+
+	/* Check that state is OK to post receive. */
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK)) {
+		*bad_wr = wr;
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	for (; wr; wr = wr->next) {
+		struct ipath_rwqe *wqe;
+		u32 next;
+		int i, j;
+
+		if (wr->num_sge > qp->r_rq.max_sge) {
+			*bad_wr = wr;
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		spin_lock_irqsave(&qp->r_rq.lock, flags);
+		next = qp->r_rq.head + 1;
+		if (next >= qp->r_rq.size)
+			next = 0;
+		if (next == qp->r_rq.tail) {
+			spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+			*bad_wr = wr;
+			ret = -ENOMEM;
+			goto bail;
+		}
+
+		wqe = get_rwqe_ptr(&qp->r_rq, qp->r_rq.head);
+		wqe->wr_id = wr->wr_id;
+		wqe->sg_list[0].mr = NULL;
+		wqe->sg_list[0].vaddr = NULL;
+		wqe->sg_list[0].length = 0;
+		wqe->sg_list[0].sge_length = 0;
+		wqe->length = 0;
+		for (i = 0, j = 0; i < wr->num_sge; i++) {
+			/* Check LKEY */
+			if (to_ipd(qp->ibqp.pd)->user &&
+			    wr->sg_list[i].lkey == 0) {
+				spin_unlock_irqrestore(&qp->r_rq.lock,
+						       flags);
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto bail;
+			}
+			if (wr->sg_list[i].length == 0)
+				continue;
+			if (!ipath_lkey_ok(
+				    &to_idev(qp->ibqp.device)->lk_table,
+				    &wqe->sg_list[j], &wr->sg_list[i],
+				    IB_ACCESS_LOCAL_WRITE)) {
+				spin_unlock_irqrestore(&qp->r_rq.lock,
+						       flags);
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto bail;
+			}
+			wqe->length += wr->sg_list[i].length;
+			j++;
+		}
+		wqe->num_sge = j;
+		qp->r_rq.head = next;
+		spin_unlock_irqrestore(&qp->r_rq.lock, flags);
+	}
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_qp_rcv - processing an incoming packet on a QP
+ * @dev: the device the packet came on
+ * @hdr: the packet header
+ * @has_grh: true if the packet has a GRH
+ * @data: the packet data
+ * @tlen: the packet length
+ * @qp: the QP the packet came on
+ *
+ * This is called from ipath_ib_rcv() to process an incoming packet
+ * for the given QP.
+ * Called at interrupt level.
+ */
+static void ipath_qp_rcv(struct ipath_ibdev *dev,
+			 struct ipath_ib_header *hdr, int has_grh,
+			 void *data, u32 tlen, struct ipath_qp *qp)
+{
+	/* Check for valid receive state. */
+	if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) {
+		dev->n_pkt_drops++;
+		return;
+	}
+
+	switch (qp->ibqp.qp_type) {
+	case IB_QPT_SMI:
+	case IB_QPT_GSI:
+	case IB_QPT_UD:
+		ipath_ud_rcv(dev, hdr, has_grh, data, tlen, qp);
+		break;
+
+	case IB_QPT_RC:
+		ipath_rc_rcv(dev, hdr, has_grh, data, tlen, qp);
+		break;
+
+	case IB_QPT_UC:
+		ipath_uc_rcv(dev, hdr, has_grh, data, tlen, qp);
+		break;
+
+	default:
+		break;
+	}
+}
+
+/**
+ * ipath_ib_rcv - process and incoming packet
+ * @arg: the device pointer
+ * @rhdr: the header of the packet
+ * @data: the packet data
+ * @tlen: the packet length
+ *
+ * This is called from ipath_kreceive() to process an incoming packet at
+ * interrupt level. Tlen is the length of the header + data + CRC in bytes.
+ */
+static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen)
+{
+	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+	struct ipath_ib_header *hdr = rhdr;
+	struct ipath_other_headers *ohdr;
+	struct ipath_qp *qp;
+	u32 qp_num;
+	int lnh;
+	u8 opcode;
+	u16 lid;
+
+	if (unlikely(dev == NULL))
+		goto bail;
+
+	if (unlikely(tlen < 24)) {	/* LRH+BTH+CRC */
+		dev->rcv_errors++;
+		goto bail;
+	}
+
+	/* Check for a valid destination LID (see ch. 7.11.1). */
+	lid = be16_to_cpu(hdr->lrh[1]);
+	if (lid < IPS_MULTICAST_LID_BASE) {
+		lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1);
+		if (unlikely(lid != ipath_layer_get_lid(dev->dd))) {
+			dev->rcv_errors++;
+			goto bail;
+		}
+	}
+
+	/* Check for GRH */
+	lnh = be16_to_cpu(hdr->lrh[0]) & 3;
+	if (lnh == IPS_LRH_BTH)
+		ohdr = &hdr->u.oth;
+	else if (lnh == IPS_LRH_GRH)
+		ohdr = &hdr->u.l.oth;
+	else {
+		dev->rcv_errors++;
+		goto bail;
+	}
+
+	opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+	dev->opstats[opcode].n_bytes += tlen;
+	dev->opstats[opcode].n_packets++;
+
+	/* Get the destination QP number. */
+	qp_num = be32_to_cpu(ohdr->bth[1]) & IPS_QPN_MASK;
+	if (qp_num == IPS_MULTICAST_QPN) {
+		struct ipath_mcast *mcast;
+		struct ipath_mcast_qp *p;
+
+		mcast = ipath_mcast_find(&hdr->u.l.grh.dgid);
+		if (mcast == NULL) {
+			dev->n_pkt_drops++;
+			goto bail;
+		}
+		dev->n_multicast_rcv++;
+		list_for_each_entry_rcu(p, &mcast->qp_list, list)
+			ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+				     tlen, p->qp);
+		/*
+		 * Notify ipath_multicast_detach() if it is waiting for us
+		 * to finish.
+		 */
+		if (atomic_dec_return(&mcast->refcount) <= 1)
+			wake_up(&mcast->wait);
+	} else {
+		qp = ipath_lookup_qpn(&dev->qp_table, qp_num);
+		if (qp) {
+			dev->n_unicast_rcv++;
+			ipath_qp_rcv(dev, hdr, lnh == IPS_LRH_GRH, data,
+				     tlen, qp);
+			/*
+			 * Notify ipath_destroy_qp() if it is waiting
+			 * for us to finish.
+			 */
+			if (atomic_dec_and_test(&qp->refcount))
+				wake_up(&qp->wait);
+		} else
+			dev->n_pkt_drops++;
+	}
+
+bail:;
+}
+
+/**
+ * ipath_ib_timer - verbs timer
+ * @arg: the device pointer
+ *
+ * This is called from ipath_do_rcv_timer() at interrupt level to check for
+ * QPs which need retransmits and to collect performance numbers.
+ */
+static void ipath_ib_timer(void *arg)
+{
+	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+	struct ipath_qp *resend = NULL;
+	struct ipath_qp *rnr = NULL;
+	struct list_head *last;
+	struct ipath_qp *qp;
+	unsigned long flags;
+
+	if (dev == NULL)
+		return;
+
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	/* Start filling the next pending queue. */
+	if (++dev->pending_index >= ARRAY_SIZE(dev->pending))
+		dev->pending_index = 0;
+	/* Save any requests still in the new queue, they have timed out. */
+	last = &dev->pending[dev->pending_index];
+	while (!list_empty(last)) {
+		qp = list_entry(last->next, struct ipath_qp, timerwait);
+		if (last->next == LIST_POISON1 ||
+		    last->next != &qp->timerwait ||
+		    qp->timerwait.prev != last) {
+			INIT_LIST_HEAD(last);
+		} else {
+			list_del(&qp->timerwait);
+			qp->timerwait.prev = (struct list_head *) resend;
+			resend = qp;
+			atomic_inc(&qp->refcount);
+		}
+	}
+	last = &dev->rnrwait;
+	if (!list_empty(last)) {
+		qp = list_entry(last->next, struct ipath_qp, timerwait);
+		if (--qp->s_rnr_timeout == 0) {
+			do {
+				if (last->next == LIST_POISON1 ||
+				    last->next != &qp->timerwait ||
+				    qp->timerwait.prev != last) {
+					INIT_LIST_HEAD(last);
+					break;
+				}
+				list_del(&qp->timerwait);
+				qp->timerwait.prev =
+					(struct list_head *) rnr;
+				rnr = qp;
+				if (list_empty(last))
+					break;
+				qp = list_entry(last->next, struct ipath_qp,
+						timerwait);
+			} while (qp->s_rnr_timeout == 0);
+		}
+	}
+	/*
+	 * We should only be in the started state if pma_sample_start != 0
+	 */
+	if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED &&
+	    --dev->pma_sample_start == 0) {
+		dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING;
+		ipath_layer_snapshot_counters(dev->dd, &dev->ipath_sword,
+					      &dev->ipath_rword,
+					      &dev->ipath_spkts,
+					      &dev->ipath_rpkts,
+					      &dev->ipath_xmit_wait);
+	}
+	if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) {
+		if (dev->pma_sample_interval == 0) {
+			u64 ta, tb, tc, td, te;
+
+			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE;
+			ipath_layer_snapshot_counters(dev->dd, &ta, &tb,
+						      &tc, &td, &te);
+
+			dev->ipath_sword = ta - dev->ipath_sword;
+			dev->ipath_rword = tb - dev->ipath_rword;
+			dev->ipath_spkts = tc - dev->ipath_spkts;
+			dev->ipath_rpkts = td - dev->ipath_rpkts;
+			dev->ipath_xmit_wait = te - dev->ipath_xmit_wait;
+		}
+		else
+			dev->pma_sample_interval--;
+	}
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+	/* XXX What if timer fires again while this is running? */
+	for (qp = resend; qp != NULL;
+	     qp = (struct ipath_qp *) qp->timerwait.prev) {
+		struct ib_wc wc;
+
+		spin_lock_irqsave(&qp->s_lock, flags);
+		if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) {
+			dev->n_timeouts++;
+			ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+		}
+		spin_unlock_irqrestore(&qp->s_lock, flags);
+
+		/* Notify ipath_destroy_qp() if it is waiting. */
+		if (atomic_dec_and_test(&qp->refcount))
+			wake_up(&qp->wait);
+	}
+	for (qp = rnr; qp != NULL;
+	     qp = (struct ipath_qp *) qp->timerwait.prev)
+		tasklet_hi_schedule(&qp->s_task);
+}
+
+/**
+ * ipath_ib_piobufavail - callback when a PIO buffer is available
+ * @arg: the device pointer
+ *
+ * This is called from ipath_intr() at interrupt level when a PIO buffer is
+ * available after ipath_verbs_send() returned an error that no buffers were
+ * available.  Return 0 if we consumed all the PIO buffers and we still have
+ * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
+ * return one).
+ */
+static int ipath_ib_piobufavail(void *arg)
+{
+	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+	struct ipath_qp *qp;
+	unsigned long flags;
+
+	if (dev == NULL)
+		goto bail;
+
+	spin_lock_irqsave(&dev->pending_lock, flags);
+	while (!list_empty(&dev->piowait)) {
+		qp = list_entry(dev->piowait.next, struct ipath_qp,
+				piowait);
+		list_del(&qp->piowait);
+		tasklet_hi_schedule(&qp->s_task);
+	}
+	spin_unlock_irqrestore(&dev->pending_lock, flags);
+
+bail:
+	return 1;
+}
+
+static int ipath_query_device(struct ib_device *ibdev,
+			      struct ib_device_attr *props)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	u32 vendor, boardrev, majrev, minrev;
+
+	memset(props, 0, sizeof(*props));
+
+	props->device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
+		IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
+		IB_DEVICE_SYS_IMAGE_GUID;
+	ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+				 &majrev, &minrev);
+	props->vendor_id = vendor;
+	props->vendor_part_id = boardrev;
+	props->hw_ver = boardrev << 16 | majrev << 8 | minrev;
+
+	props->sys_image_guid = dev->sys_image_guid;
+
+	props->max_mr_size = ~0ull;
+	props->max_qp = 0xffff;
+	props->max_qp_wr = 0xffff;
+	props->max_sge = 255;
+	props->max_cq = 0xffff;
+	props->max_cqe = 0xffff;
+	props->max_mr = 0xffff;
+	props->max_pd = 0xffff;
+	props->max_qp_rd_atom = 1;
+	props->max_qp_init_rd_atom = 1;
+	/* props->max_res_rd_atom */
+	props->max_srq = 0xffff;
+	props->max_srq_wr = 0xffff;
+	props->max_srq_sge = 255;
+	/* props->local_ca_ack_delay */
+	props->atomic_cap = IB_ATOMIC_HCA;
+	props->max_pkeys = ipath_layer_get_npkeys(dev->dd);
+	props->max_mcast_grp = 0xffff;
+	props->max_mcast_qp_attach = 0xffff;
+	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
+		props->max_mcast_grp;
+
+	return 0;
+}
+
+const u8 ipath_cvt_physportstate[16] = {
+	[INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
+	[INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
+	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
+	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
+	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
+	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
+	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
+	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
+	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
+	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
+	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
+	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
+	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
+};
+
+static int ipath_query_port(struct ib_device *ibdev,
+			    u8 port, struct ib_port_attr *props)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	enum ib_mtu mtu;
+	u16 lid = ipath_layer_get_lid(dev->dd);
+	u64 ibcstat;
+
+	memset(props, 0, sizeof(*props));
+	props->lid = lid ? lid : __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+	props->lmc = dev->mkeyprot_resv_lmc & 7;
+	props->sm_lid = dev->sm_lid;
+	props->sm_sl = dev->sm_sl;
+	ibcstat = ipath_layer_get_lastibcstat(dev->dd);
+	props->state = ((ibcstat >> 4) & 0x3) + 1;
+	/* See phys_state_show() */
+	props->phys_state = ipath_cvt_physportstate[
+		ipath_layer_get_lastibcstat(dev->dd) & 0xf];
+	props->port_cap_flags = dev->port_cap_flags;
+	props->gid_tbl_len = 1;
+	props->max_msg_sz = 4096;
+	props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd);
+	props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) -
+		dev->n_pkey_violations;
+	props->qkey_viol_cntr = dev->qkey_violations;
+	props->active_width = IB_WIDTH_4X;
+	/* See rate_show() */
+	props->active_speed = 1;	/* Regular 10Mbs speed. */
+	props->max_vl_num = 1;		/* VLCap = VL0 */
+	props->init_type_reply = 0;
+
+	props->max_mtu = IB_MTU_4096;
+	switch (ipath_layer_get_ibmtu(dev->dd)) {
+	case 4096:
+		mtu = IB_MTU_4096;
+		break;
+	case 2048:
+		mtu = IB_MTU_2048;
+		break;
+	case 1024:
+		mtu = IB_MTU_1024;
+		break;
+	case 512:
+		mtu = IB_MTU_512;
+		break;
+	case 256:
+		mtu = IB_MTU_256;
+		break;
+	default:
+		mtu = IB_MTU_2048;
+	}
+	props->active_mtu = mtu;
+	props->subnet_timeout = dev->subnet_timeout;
+
+	return 0;
+}
+
+static int ipath_modify_device(struct ib_device *device,
+			       int device_modify_mask,
+			       struct ib_device_modify *device_modify)
+{
+	int ret;
+
+	if (device_modify_mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID |
+				   IB_DEVICE_MODIFY_NODE_DESC)) {
+		ret = -EOPNOTSUPP;
+		goto bail;
+	}
+
+	if (device_modify_mask & IB_DEVICE_MODIFY_NODE_DESC)
+		memcpy(device->node_desc, device_modify->node_desc, 64);
+
+	if (device_modify_mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID)
+		to_idev(device)->sys_image_guid =
+			cpu_to_be64(device_modify->sys_image_guid);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static int ipath_modify_port(struct ib_device *ibdev,
+			     u8 port, int port_modify_mask,
+			     struct ib_port_modify *props)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+
+	dev->port_cap_flags |= props->set_port_cap_mask;
+	dev->port_cap_flags &= ~props->clr_port_cap_mask;
+	if (port_modify_mask & IB_PORT_SHUTDOWN)
+		ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN);
+	if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)
+		dev->qkey_violations = 0;
+	return 0;
+}
+
+static int ipath_query_gid(struct ib_device *ibdev, u8 port,
+			   int index, union ib_gid *gid)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int ret;
+
+	if (index >= 1) {
+		ret = -EINVAL;
+		goto bail;
+	}
+	gid->global.subnet_prefix = dev->gid_prefix;
+	gid->global.interface_id = ipath_layer_get_guid(dev->dd);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev,
+				    struct ib_ucontext *context,
+				    struct ib_udata *udata)
+{
+	struct ipath_pd *pd;
+	struct ib_pd *ret;
+
+	pd = kmalloc(sizeof *pd, GFP_KERNEL);
+	if (!pd) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	/* ib_alloc_pd() will initialize pd->ibpd. */
+	pd->user = udata != NULL;
+
+	ret = &pd->ibpd;
+
+bail:
+	return ret;
+}
+
+static int ipath_dealloc_pd(struct ib_pd *ibpd)
+{
+	struct ipath_pd *pd = to_ipd(ibpd);
+
+	kfree(pd);
+
+	return 0;
+}
+
+/**
+ * ipath_create_ah - create an address handle
+ * @pd: the protection domain
+ * @ah_attr: the attributes of the AH
+ *
+ * This may be called from interrupt context.
+ */
+static struct ib_ah *ipath_create_ah(struct ib_pd *pd,
+				     struct ib_ah_attr *ah_attr)
+{
+	struct ipath_ah *ah;
+	struct ib_ah *ret;
+
+	/* A multicast address requires a GRH (see ch. 8.4.1). */
+	if (ah_attr->dlid >= IPS_MULTICAST_LID_BASE &&
+	    ah_attr->dlid != IPS_PERMISSIVE_LID &&
+	    !(ah_attr->ah_flags & IB_AH_GRH)) {
+		ret = ERR_PTR(-EINVAL);
+		goto bail;
+	}
+
+	ah = kmalloc(sizeof *ah, GFP_ATOMIC);
+	if (!ah) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	/* ib_create_ah() will initialize ah->ibah. */
+	ah->attr = *ah_attr;
+
+	ret = &ah->ibah;
+
+bail:
+	return ret;
+}
+
+/**
+ * ipath_destroy_ah - destroy an address handle
+ * @ibah: the AH to destroy
+ *
+ * This may be called from interrupt context.
+ */
+static int ipath_destroy_ah(struct ib_ah *ibah)
+{
+	struct ipath_ah *ah = to_iah(ibah);
+
+	kfree(ah);
+
+	return 0;
+}
+
+static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
+{
+	struct ipath_ah *ah = to_iah(ibah);
+
+	*ah_attr = ah->attr;
+
+	return 0;
+}
+
+static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+			    u16 *pkey)
+{
+	struct ipath_ibdev *dev = to_idev(ibdev);
+	int ret;
+
+	if (index >= ipath_layer_get_npkeys(dev->dd)) {
+		ret = -EINVAL;
+		goto bail;
+	}
+
+	*pkey = ipath_layer_get_pkey(dev->dd, index);
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+
+/**
+ * ipath_alloc_ucontext - allocate a ucontest
+ * @ibdev: the infiniband device
+ * @udata: not used by the InfiniPath driver
+ */
+
+static struct ib_ucontext *ipath_alloc_ucontext(struct ib_device *ibdev,
+						struct ib_udata *udata)
+{
+	struct ipath_ucontext *context;
+	struct ib_ucontext *ret;
+
+	context = kmalloc(sizeof *context, GFP_KERNEL);
+	if (!context) {
+		ret = ERR_PTR(-ENOMEM);
+		goto bail;
+	}
+
+	ret = &context->ibucontext;
+
+bail:
+	return ret;
+}
+
+static int ipath_dealloc_ucontext(struct ib_ucontext *context)
+{
+	kfree(to_iucontext(context));
+	return 0;
+}
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev);
+
+/**
+ * ipath_register_ib_device - register our device with the infiniband core
+ * @unit: the device number to register
+ * @dd: the device data structure
+ * Return the allocated ipath_ibdev pointer or NULL on error.
+ */
+static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd)
+{
+	struct ipath_ibdev *idev;
+	struct ib_device *dev;
+	int ret;
+
+	idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev);
+	if (idev == NULL)
+		goto bail;
+
+	dev = &idev->ibdev;
+
+	/* Only need to initialize non-zero fields. */
+	spin_lock_init(&idev->qp_table.lock);
+	spin_lock_init(&idev->lk_table.lock);
+	idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE);
+	/* Set the prefix to the default value (see ch. 4.1.1) */
+	idev->gid_prefix = __constant_cpu_to_be64(0xfe80000000000000ULL);
+
+	ret = ipath_init_qp_table(idev, ib_ipath_qp_table_size);
+	if (ret)
+		goto err_qp;
+
+	/*
+	 * The top ib_ipath_lkey_table_size bits are used to index the
+	 * table.  The lower 8 bits can be owned by the user (copied from
+	 * the LKEY).  The remaining bits act as a generation number or tag.
+	 */
+	idev->lk_table.max = 1 << ib_ipath_lkey_table_size;
+	idev->lk_table.table = kzalloc(idev->lk_table.max *
+				       sizeof(*idev->lk_table.table),
+				       GFP_KERNEL);
+	if (idev->lk_table.table == NULL) {
+		ret = -ENOMEM;
+		goto err_lk;
+	}
+	spin_lock_init(&idev->pending_lock);
+	INIT_LIST_HEAD(&idev->pending[0]);
+	INIT_LIST_HEAD(&idev->pending[1]);
+	INIT_LIST_HEAD(&idev->pending[2]);
+	INIT_LIST_HEAD(&idev->piowait);
+	INIT_LIST_HEAD(&idev->rnrwait);
+	idev->pending_index = 0;
+	idev->port_cap_flags =
+		IB_PORT_SYS_IMAGE_GUID_SUP | IB_PORT_CLIENT_REG_SUP;
+	idev->pma_counter_select[0] = IB_PMA_PORT_XMIT_DATA;
+	idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA;
+	idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS;
+	idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS;
+	idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT;
+	idev->link_width_enabled = 3;	/* 1x or 4x */
+
+	/*
+	 * The system image GUID is supposed to be the same for all
+	 * IB HCAs in a single system but since there can be other
+	 * device types in the system, we can't be sure this is unique.
+	 */
+	if (!sys_image_guid)
+		sys_image_guid = ipath_layer_get_guid(dd);
+	idev->sys_image_guid = sys_image_guid;
+	idev->ib_unit = unit;
+	idev->dd = dd;
+
+	strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX);
+	dev->node_guid = ipath_layer_get_guid(dd);
+	dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION;
+	dev->uverbs_cmd_mask =
+		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|
+		(1ull << IB_USER_VERBS_CMD_QUERY_PORT)		|
+		(1ull << IB_USER_VERBS_CMD_ALLOC_PD)		|
+		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_AH)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_AH)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_AH)		|
+		(1ull << IB_USER_VERBS_CMD_REG_MR)		|
+		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_RESIZE_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_POLL_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ)	|
+		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_POST_SEND)		|
+		(1ull << IB_USER_VERBS_CMD_POST_RECV)		|
+		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)	|
+		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)	|
+		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ)		|
+		(1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
+	dev->node_type = IB_NODE_CA;
+	dev->phys_port_cnt = 1;
+	dev->dma_device = ipath_layer_get_device(dd);
+	dev->class_dev.dev = dev->dma_device;
+	dev->query_device = ipath_query_device;
+	dev->modify_device = ipath_modify_device;
+	dev->query_port = ipath_query_port;
+	dev->modify_port = ipath_modify_port;
+	dev->query_pkey = ipath_query_pkey;
+	dev->query_gid = ipath_query_gid;
+	dev->alloc_ucontext = ipath_alloc_ucontext;
+	dev->dealloc_ucontext = ipath_dealloc_ucontext;
+	dev->alloc_pd = ipath_alloc_pd;
+	dev->dealloc_pd = ipath_dealloc_pd;
+	dev->create_ah = ipath_create_ah;
+	dev->destroy_ah = ipath_destroy_ah;
+	dev->query_ah = ipath_query_ah;
+	dev->create_srq = ipath_create_srq;
+	dev->modify_srq = ipath_modify_srq;
+	dev->query_srq = ipath_query_srq;
+	dev->destroy_srq = ipath_destroy_srq;
+	dev->create_qp = ipath_create_qp;
+	dev->modify_qp = ipath_modify_qp;
+	dev->query_qp = ipath_query_qp;
+	dev->destroy_qp = ipath_destroy_qp;
+	dev->post_send = ipath_post_send;
+	dev->post_recv = ipath_post_receive;
+	dev->post_srq_recv = ipath_post_srq_receive;
+	dev->create_cq = ipath_create_cq;
+	dev->destroy_cq = ipath_destroy_cq;
+	dev->resize_cq = ipath_resize_cq;
+	dev->poll_cq = ipath_poll_cq;
+	dev->req_notify_cq = ipath_req_notify_cq;
+	dev->get_dma_mr = ipath_get_dma_mr;
+	dev->reg_phys_mr = ipath_reg_phys_mr;
+	dev->reg_user_mr = ipath_reg_user_mr;
+	dev->dereg_mr = ipath_dereg_mr;
+	dev->alloc_fmr = ipath_alloc_fmr;
+	dev->map_phys_fmr = ipath_map_phys_fmr;
+	dev->unmap_fmr = ipath_unmap_fmr;
+	dev->dealloc_fmr = ipath_dealloc_fmr;
+	dev->attach_mcast = ipath_multicast_attach;
+	dev->detach_mcast = ipath_multicast_detach;
+	dev->process_mad = ipath_process_mad;
+
+	snprintf(dev->node_desc, sizeof(dev->node_desc),
+		 IPATH_IDSTR " %s kernel_SMA", system_utsname.nodename);
+
+	ret = ib_register_device(dev);
+	if (ret)
+		goto err_reg;
+
+	if (ipath_verbs_register_sysfs(dev))
+		goto err_class;
+
+	ipath_layer_enable_timer(dd);
+
+	goto bail;
+
+err_class:
+	ib_unregister_device(dev);
+err_reg:
+	kfree(idev->lk_table.table);
+err_lk:
+	kfree(idev->qp_table.table);
+err_qp:
+	ib_dealloc_device(dev);
+	_VERBS_ERROR("ib_ipath%d cannot register verbs (%d)!\n",
+		     unit, -ret);
+	idev = NULL;
+
+bail:
+	return idev;
+}
+
+static void ipath_unregister_ib_device(void *arg)
+{
+	struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
+	struct ib_device *ibdev = &dev->ibdev;
+
+	ipath_layer_disable_timer(dev->dd);
+
+	ib_unregister_device(ibdev);
+
+	if (!list_empty(&dev->pending[0]) ||
+	    !list_empty(&dev->pending[1]) ||
+	    !list_empty(&dev->pending[2]))
+		_VERBS_ERROR("ipath%d pending list not empty!\n",
+			     dev->ib_unit);
+	if (!list_empty(&dev->piowait))
+		_VERBS_ERROR("ipath%d piowait list not empty!\n",
+			     dev->ib_unit);
+	if (!list_empty(&dev->rnrwait))
+		_VERBS_ERROR("ipath%d rnrwait list not empty!\n",
+			     dev->ib_unit);
+	if (!ipath_mcast_tree_empty())
+		_VERBS_ERROR("ipath%d multicast table memory leak!\n",
+			     dev->ib_unit);
+	/*
+	 * Note that ipath_unregister_ib_device() can be called before all
+	 * the QPs are destroyed!
+	 */
+	ipath_free_all_qps(&dev->qp_table);
+	kfree(dev->qp_table.table);
+	kfree(dev->lk_table.table);
+	ib_dealloc_device(ibdev);
+}
+
+static int __init ipath_verbs_init(void)
+{
+	return ipath_verbs_register(ipath_register_ib_device,
+				    ipath_unregister_ib_device,
+				    ipath_ib_piobufavail, ipath_ib_rcv,
+				    ipath_ib_timer);
+}
+
+static void __exit ipath_verbs_cleanup(void)
+{
+	ipath_verbs_unregister();
+}
+
+static ssize_t show_rev(struct class_device *cdev, char *buf)
+{
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int vendor, boardrev, majrev, minrev;
+
+	ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+				 &majrev, &minrev);
+	return sprintf(buf, "%d.%d\n", majrev, minrev);
+}
+
+static ssize_t show_hca(struct class_device *cdev, char *buf)
+{
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int ret;
+
+	ret = ipath_layer_get_boardname(dev->dd, buf, 128);
+	if (ret < 0)
+		goto bail;
+	strcat(buf, "\n");
+	ret = strlen(buf);
+
+bail:
+	return ret;
+}
+
+static ssize_t show_stats(struct class_device *cdev, char *buf)
+{
+	struct ipath_ibdev *dev =
+		container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+	int i;
+	int len;
+
+	len = sprintf(buf,
+		      "RC resends  %d\n"
+		      "RC QACKs    %d\n"
+		      "RC ACKs     %d\n"
+		      "RC SEQ NAKs %d\n"
+		      "RC RDMA seq %d\n"
+		      "RC RNR NAKs %d\n"
+		      "RC OTH NAKs %d\n"
+		      "RC timeouts %d\n"
+		      "RC RDMA dup %d\n"
+		      "piobuf wait %d\n"
+		      "no piobuf   %d\n"
+		      "PKT drops   %d\n"
+		      "WQE errs    %d\n",
+		      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+		      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+		      dev->n_other_naks, dev->n_timeouts,
+		      dev->n_rdma_dup_busy, dev->n_piowait,
+		      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
+	for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+		const struct ipath_opcode_stats *si = &dev->opstats[i];
+
+		if (!si->n_packets && !si->n_bytes)
+			continue;
+		len += sprintf(buf + len, "%02x %llu/%llu\n", i,
+			       (unsigned long long) si->n_packets,
+			       (unsigned long long) si->n_bytes);
+	}
+	return len;
+}
+
+static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
+static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
+static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
+
+static struct class_device_attribute *ipath_class_attributes[] = {
+	&class_device_attr_hw_rev,
+	&class_device_attr_hca_type,
+	&class_device_attr_board_id,
+	&class_device_attr_stats
+};
+
+static int ipath_verbs_register_sysfs(struct ib_device *dev)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+		if (class_device_create_file(&dev->class_dev,
+					     ipath_class_attributes[i])) {
+			ret = 1;
+			goto bail;
+		}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+module_init(ipath_verbs_init);
+module_exit(ipath_verbs_cleanup);
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
new file mode 100644
index 0000000..fcafbc7
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -0,0 +1,692 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IPATH_VERBS_H
+#define IPATH_VERBS_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <rdma/ib_pack.h>
+
+#include "ipath_layer.h"
+#include "verbs_debug.h"
+
+#define QPN_MAX                 (1 << 24)
+#define QPNMAP_ENTRIES          (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE)
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IPATH_UVERBS_ABI_VERSION       1
+
+/*
+ * Define an ib_cq_notify value that is not valid so we know when CQ
+ * notifications are armed.
+ */
+#define IB_CQ_NONE	(IB_CQ_NEXT_COMP + 1)
+
+#define IB_RNR_NAK			0x20
+#define IB_NAK_PSN_ERROR		0x60
+#define IB_NAK_INVALID_REQUEST		0x61
+#define IB_NAK_REMOTE_ACCESS_ERROR	0x62
+#define IB_NAK_REMOTE_OPERATIONAL_ERROR 0x63
+#define IB_NAK_INVALID_RD_REQUEST	0x64
+
+#define IPATH_POST_SEND_OK		0x01
+#define IPATH_POST_RECV_OK		0x02
+#define IPATH_PROCESS_RECV_OK		0x04
+#define IPATH_PROCESS_SEND_OK		0x08
+
+/* IB Performance Manager status values */
+#define IB_PMA_SAMPLE_STATUS_DONE	0x00
+#define IB_PMA_SAMPLE_STATUS_STARTED	0x01
+#define IB_PMA_SAMPLE_STATUS_RUNNING	0x02
+
+/* Mandatory IB performance counter select values. */
+#define IB_PMA_PORT_XMIT_DATA	__constant_htons(0x0001)
+#define IB_PMA_PORT_RCV_DATA	__constant_htons(0x0002)
+#define IB_PMA_PORT_XMIT_PKTS	__constant_htons(0x0003)
+#define IB_PMA_PORT_RCV_PKTS	__constant_htons(0x0004)
+#define IB_PMA_PORT_XMIT_WAIT	__constant_htons(0x0005)
+
+struct ib_reth {
+	__be64 vaddr;
+	__be32 rkey;
+	__be32 length;
+} __attribute__ ((packed));
+
+struct ib_atomic_eth {
+	__be64 vaddr;
+	__be32 rkey;
+	__be64 swap_data;
+	__be64 compare_data;
+} __attribute__ ((packed));
+
+struct ipath_other_headers {
+	__be32 bth[3];
+	union {
+		struct {
+			__be32 deth[2];
+			__be32 imm_data;
+		} ud;
+		struct {
+			struct ib_reth reth;
+			__be32 imm_data;
+		} rc;
+		struct {
+			__be32 aeth;
+			__be64 atomic_ack_eth;
+		} at;
+		__be32 imm_data;
+		__be32 aeth;
+		struct ib_atomic_eth atomic_eth;
+	} u;
+} __attribute__ ((packed));
+
+/*
+ * Note that UD packets with a GRH header are 8+40+12+8 = 68 bytes
+ * long (72 w/ imm_data).  Only the first 56 bytes of the IB header
+ * will be in the eager header buffer.  The remaining 12 or 16 bytes
+ * are in the data buffer.
+ */
+struct ipath_ib_header {
+	__be16 lrh[4];
+	union {
+		struct {
+			struct ib_grh grh;
+			struct ipath_other_headers oth;
+		} l;
+		struct ipath_other_headers oth;
+	} u;
+} __attribute__ ((packed));
+
+/*
+ * There is one struct ipath_mcast for each multicast GID.
+ * All attached QPs are then stored as a list of
+ * struct ipath_mcast_qp.
+ */
+struct ipath_mcast_qp {
+	struct list_head list;
+	struct ipath_qp *qp;
+};
+
+struct ipath_mcast {
+	struct rb_node rb_node;
+	union ib_gid mgid;
+	struct list_head qp_list;
+	wait_queue_head_t wait;
+	atomic_t refcount;
+};
+
+/* Memory region */
+struct ipath_mr {
+	struct ib_mr ibmr;
+	struct ipath_mregion mr;	/* must be last */
+};
+
+/* Fast memory region */
+struct ipath_fmr {
+	struct ib_fmr ibfmr;
+	u8 page_shift;
+	struct ipath_mregion mr;	/* must be last */
+};
+
+/* Protection domain */
+struct ipath_pd {
+	struct ib_pd ibpd;
+	int user;		/* non-zero if created from user space */
+};
+
+/* Address Handle */
+struct ipath_ah {
+	struct ib_ah ibah;
+	struct ib_ah_attr attr;
+};
+
+/*
+ * Quick description of our CQ/QP locking scheme:
+ *
+ * We have one global lock that protects dev->cq/qp_table.  Each
+ * struct ipath_cq/qp also has its own lock.  An individual qp lock
+ * may be taken inside of an individual cq lock.  Both cqs attached to
+ * a qp may be locked, with the send cq locked first.  No other
+ * nesting should be done.
+ *
+ * Each struct ipath_cq/qp also has an atomic_t ref count.  The
+ * pointer from the cq/qp_table to the struct counts as one reference.
+ * This reference also is good for access through the consumer API, so
+ * modifying the CQ/QP etc doesn't need to take another reference.
+ * Access because of a completion being polled does need a reference.
+ *
+ * Finally, each struct ipath_cq/qp has a wait_queue_head_t for the
+ * destroy function to sleep on.
+ *
+ * This means that access from the consumer API requires nothing but
+ * taking the struct's lock.
+ *
+ * Access because of a completion event should go as follows:
+ * - lock cq/qp_table and look up struct
+ * - increment ref count in struct
+ * - drop cq/qp_table lock
+ * - lock struct, do your thing, and unlock struct
+ * - decrement ref count; if zero, wake up waiters
+ *
+ * To destroy a CQ/QP, we can do the following:
+ * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock
+ * - decrement ref count
+ * - wait_event until ref count is zero
+ *
+ * It is the consumer's responsibilty to make sure that no QP
+ * operations (WQE posting or state modification) are pending when the
+ * QP is destroyed.  Also, the consumer must make sure that calls to
+ * qp_modify are serialized.
+ *
+ * Possible optimizations (wait for profile data to see if/where we
+ * have locks bouncing between CPUs):
+ * - split cq/qp table lock into n separate (cache-aligned) locks,
+ *   indexed (say) by the page in the table
+ */
+
+struct ipath_cq {
+	struct ib_cq ibcq;
+	struct tasklet_struct comptask;
+	spinlock_t lock;
+	u8 notify;
+	u8 triggered;
+	u32 head;		/* new records added to the head */
+	u32 tail;		/* poll_cq() reads from here. */
+	struct ib_wc *queue;	/* this is actually ibcq.cqe + 1 */
+};
+
+/*
+ * Send work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->s_max_sge.
+ */
+struct ipath_swqe {
+	struct ib_send_wr wr;	/* don't use wr.sg_list */
+	u32 psn;		/* first packet sequence number */
+	u32 lpsn;		/* last packet sequence number */
+	u32 ssn;		/* send sequence number */
+	u32 length;		/* total length of data in sg_list */
+	struct ipath_sge sg_list[0];
+};
+
+/*
+ * Receive work request queue entry.
+ * The size of the sg_list is determined when the QP is created and stored
+ * in qp->r_max_sge.
+ */
+struct ipath_rwqe {
+	u64 wr_id;
+	u32 length;		/* total length of data in sg_list */
+	u8 num_sge;
+	struct ipath_sge sg_list[0];
+};
+
+struct ipath_rq {
+	spinlock_t lock;
+	u32 head;		/* new work requests posted to the head */
+	u32 tail;		/* receives pull requests from here. */
+	u32 size;		/* size of RWQE array */
+	u8 max_sge;
+	struct ipath_rwqe *wq;	/* RWQE array */
+};
+
+struct ipath_srq {
+	struct ib_srq ibsrq;
+	struct ipath_rq rq;
+	/* send signal when number of RWQEs < limit */
+	u32 limit;
+};
+
+/*
+ * Variables prefixed with s_ are for the requester (sender).
+ * Variables prefixed with r_ are for the responder (receiver).
+ * Variables prefixed with ack_ are for responder replies.
+ *
+ * Common variables are protected by both r_rq.lock and s_lock in that order
+ * which only happens in modify_qp() or changing the QP 'state'.
+ */
+struct ipath_qp {
+	struct ib_qp ibqp;
+	struct ipath_qp *next;	/* link list for QPN hash table */
+	struct list_head piowait;	/* link for wait PIO buf */
+	struct list_head timerwait;	/* link for waiting for timeouts */
+	struct ib_ah_attr remote_ah_attr;
+	struct ipath_ib_header s_hdr;	/* next packet header to send */
+	atomic_t refcount;
+	wait_queue_head_t wait;
+	struct tasklet_struct s_task;
+	struct ipath_sge_state *s_cur_sge;
+	struct ipath_sge_state s_sge;	/* current send request data */
+	/* current RDMA read send data */
+	struct ipath_sge_state s_rdma_sge;
+	struct ipath_sge_state r_sge;	/* current receive data */
+	spinlock_t s_lock;
+	unsigned long s_flags;
+	u32 s_hdrwords;		/* size of s_hdr in 32 bit words */
+	u32 s_cur_size;		/* size of send packet in bytes */
+	u32 s_len;		/* total length of s_sge */
+	u32 s_rdma_len;		/* total length of s_rdma_sge */
+	u32 s_next_psn;		/* PSN for next request */
+	u32 s_last_psn;		/* last response PSN processed */
+	u32 s_psn;		/* current packet sequence number */
+	u32 s_rnr_timeout;	/* number of milliseconds for RNR timeout */
+	u32 s_ack_psn;		/* PSN for next ACK or RDMA_READ */
+	u64 s_ack_atomic;	/* data for atomic ACK */
+	u64 r_wr_id;		/* ID for current receive WQE */
+	u64 r_atomic_data;	/* data for last atomic op */
+	u32 r_atomic_psn;	/* PSN of last atomic op */
+	u32 r_len;		/* total length of r_sge */
+	u32 r_rcv_len;		/* receive data len processed */
+	u32 r_psn;		/* expected rcv packet sequence number */
+	u8 state;		/* QP state */
+	u8 s_state;		/* opcode of last packet sent */
+	u8 s_ack_state;		/* opcode of packet to ACK */
+	u8 s_nak_state;		/* non-zero if NAK is pending */
+	u8 r_state;		/* opcode of last packet received */
+	u8 r_reuse_sge;		/* for UC receive errors */
+	u8 r_sge_inx;		/* current index into sg_list */
+	u8 s_max_sge;		/* size of s_wq->sg_list */
+	u8 qp_access_flags;
+	u8 s_retry_cnt;		/* number of times to retry */
+	u8 s_rnr_retry_cnt;
+	u8 s_min_rnr_timer;
+	u8 s_retry;		/* requester retry counter */
+	u8 s_rnr_retry;		/* requester RNR retry counter */
+	u8 s_pkey_index;	/* PKEY index to use */
+	enum ib_mtu path_mtu;
+	atomic_t msn;		/* message sequence number */
+	u32 remote_qpn;
+	u32 qkey;		/* QKEY for this QP (for UD or RD) */
+	u32 s_size;		/* send work queue size */
+	u32 s_head;		/* new entries added here */
+	u32 s_tail;		/* next entry to process */
+	u32 s_cur;		/* current work queue entry */
+	u32 s_last;		/* last un-ACK'ed entry */
+	u32 s_ssn;		/* SSN of tail entry */
+	u32 s_lsn;		/* limit sequence number (credit) */
+	struct ipath_swqe *s_wq;	/* send work queue */
+	struct ipath_rq r_rq;	/* receive work queue */
+};
+
+/*
+ * Bit definitions for s_flags.
+ */
+#define IPATH_S_BUSY		0
+#define IPATH_S_SIGNAL_REQ_WR	1
+
+/*
+ * Since struct ipath_swqe is not a fixed size, we can't simply index into
+ * struct ipath_qp.s_wq.  This function does the array index computation.
+ */
+static inline struct ipath_swqe *get_swqe_ptr(struct ipath_qp *qp,
+					      unsigned n)
+{
+	return (struct ipath_swqe *)((char *)qp->s_wq +
+				     (sizeof(struct ipath_swqe) +
+				      qp->s_max_sge *
+				      sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * Since struct ipath_rwqe is not a fixed size, we can't simply index into
+ * struct ipath_rq.wq.  This function does the array index computation.
+ */
+static inline struct ipath_rwqe *get_rwqe_ptr(struct ipath_rq *rq,
+					      unsigned n)
+{
+	return (struct ipath_rwqe *)
+		((char *) rq->wq +
+		 (sizeof(struct ipath_rwqe) +
+		  rq->max_sge * sizeof(struct ipath_sge)) * n);
+}
+
+/*
+ * QPN-map pages start out as NULL, they get allocated upon
+ * first use and are never deallocated. This way,
+ * large bitmaps are not allocated unless large numbers of QPs are used.
+ */
+struct qpn_map {
+	atomic_t n_free;
+	void *page;
+};
+
+struct ipath_qp_table {
+	spinlock_t lock;
+	u32 last;		/* last QP number allocated */
+	u32 max;		/* size of the hash table */
+	u32 nmaps;		/* size of the map table */
+	struct ipath_qp **table;
+	/* bit map of free numbers */
+	struct qpn_map map[QPNMAP_ENTRIES];
+};
+
+struct ipath_lkey_table {
+	spinlock_t lock;
+	u32 next;		/* next unused index (speeds search) */
+	u32 gen;		/* generation count */
+	u32 max;		/* size of the table */
+	struct ipath_mregion **table;
+};
+
+struct ipath_opcode_stats {
+	u64 n_packets;		/* number of packets */
+	u64 n_bytes;		/* total number of bytes */
+};
+
+struct ipath_ibdev {
+	struct ib_device ibdev;
+	struct list_head dev_list;
+	struct ipath_devdata *dd;
+	int ib_unit;		/* This is the device number */
+	u16 sm_lid;		/* in host order */
+	u8 sm_sl;
+	u8 mkeyprot_resv_lmc;
+	/* non-zero when timer is set */
+	unsigned long mkey_lease_timeout;
+
+	/* The following fields are really per port. */
+	struct ipath_qp_table qp_table;
+	struct ipath_lkey_table lk_table;
+	struct list_head pending[3];	/* FIFO of QPs waiting for ACKs */
+	struct list_head piowait;	/* list for wait PIO buf */
+	/* list of QPs waiting for RNR timer */
+	struct list_head rnrwait;
+	spinlock_t pending_lock;
+	__be64 sys_image_guid;	/* in network order */
+	__be64 gid_prefix;	/* in network order */
+	__be64 mkey;
+	u64 ipath_sword;	/* total dwords sent (sample result) */
+	u64 ipath_rword;	/* total dwords received (sample result) */
+	u64 ipath_spkts;	/* total packets sent (sample result) */
+	u64 ipath_rpkts;	/* total packets received (sample result) */
+	/* # of ticks no data sent (sample result) */
+	u64 ipath_xmit_wait;
+	u64 rcv_errors;		/* # of packets with SW detected rcv errs */
+	u64 n_unicast_xmit;	/* total unicast packets sent */
+	u64 n_unicast_rcv;	/* total unicast packets received */
+	u64 n_multicast_xmit;	/* total multicast packets sent */
+	u64 n_multicast_rcv;	/* total multicast packets received */
+	u64 n_symbol_error_counter;	/* starting count for PMA */
+	u64 n_link_error_recovery_counter;	/* starting count for PMA */
+	u64 n_link_downed_counter;	/* starting count for PMA */
+	u64 n_port_rcv_errors;	/* starting count for PMA */
+	u64 n_port_rcv_remphys_errors;	/* starting count for PMA */
+	u64 n_port_xmit_discards;	/* starting count for PMA */
+	u64 n_port_xmit_data;	/* starting count for PMA */
+	u64 n_port_rcv_data;	/* starting count for PMA */
+	u64 n_port_xmit_packets;	/* starting count for PMA */
+	u64 n_port_rcv_packets;	/* starting count for PMA */
+	u32 n_pkey_violations;	/* starting count for PMA */
+	u32 n_rc_resends;
+	u32 n_rc_acks;
+	u32 n_rc_qacks;
+	u32 n_seq_naks;
+	u32 n_rdma_seq;
+	u32 n_rnr_naks;
+	u32 n_other_naks;
+	u32 n_timeouts;
+	u32 n_pkt_drops;
+	u32 n_wqe_errs;
+	u32 n_rdma_dup_busy;
+	u32 n_piowait;
+	u32 n_no_piobuf;
+	u32 port_cap_flags;
+	u32 pma_sample_start;
+	u32 pma_sample_interval;
+	__be16 pma_counter_select[5];
+	u16 pma_tag;
+	u16 qkey_violations;
+	u16 mkey_violations;
+	u16 mkey_lease_period;
+	u16 pending_index;	/* which pending queue is active */
+	u8 pma_sample_status;
+	u8 subnet_timeout;
+	u8 link_width_enabled;
+	u8 vl_high_limit;
+	struct ipath_opcode_stats opstats[128];
+};
+
+struct ipath_ucontext {
+	struct ib_ucontext ibucontext;
+};
+
+static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+{
+	return container_of(ibmr, struct ipath_mr, ibmr);
+}
+
+static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr)
+{
+	return container_of(ibfmr, struct ipath_fmr, ibfmr);
+}
+
+static inline struct ipath_pd *to_ipd(struct ib_pd *ibpd)
+{
+	return container_of(ibpd, struct ipath_pd, ibpd);
+}
+
+static inline struct ipath_ah *to_iah(struct ib_ah *ibah)
+{
+	return container_of(ibah, struct ipath_ah, ibah);
+}
+
+static inline struct ipath_cq *to_icq(struct ib_cq *ibcq)
+{
+	return container_of(ibcq, struct ipath_cq, ibcq);
+}
+
+static inline struct ipath_srq *to_isrq(struct ib_srq *ibsrq)
+{
+	return container_of(ibsrq, struct ipath_srq, ibsrq);
+}
+
+static inline struct ipath_qp *to_iqp(struct ib_qp *ibqp)
+{
+	return container_of(ibqp, struct ipath_qp, ibqp);
+}
+
+static inline struct ipath_ibdev *to_idev(struct ib_device *ibdev)
+{
+	return container_of(ibdev, struct ipath_ibdev, ibdev);
+}
+
+int ipath_process_mad(struct ib_device *ibdev,
+		      int mad_flags,
+		      u8 port_num,
+		      struct ib_wc *in_wc,
+		      struct ib_grh *in_grh,
+		      struct ib_mad *in_mad, struct ib_mad *out_mad);
+
+static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext
+						  *ibucontext)
+{
+	return container_of(ibucontext, struct ipath_ucontext, ibucontext);
+}
+
+/*
+ * Compare the lower 24 bits of the two values.
+ * Returns an integer <, ==, or > than zero.
+ */
+static inline int ipath_cmp24(u32 a, u32 b)
+{
+	return (((int) a) - ((int) b)) << 8;
+}
+
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid);
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
+
+int ipath_mcast_tree_empty(void);
+
+__be32 ipath_compute_aeth(struct ipath_qp *qp);
+
+struct ipath_qp *ipath_lookup_qpn(struct ipath_qp_table *qpt, u32 qpn);
+
+struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+			      struct ib_qp_init_attr *init_attr,
+			      struct ib_udata *udata);
+
+int ipath_destroy_qp(struct ib_qp *ibqp);
+
+int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask);
+
+int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		   int attr_mask, struct ib_qp_init_attr *init_attr);
+
+void ipath_free_all_qps(struct ipath_qp_table *qpt);
+
+int ipath_init_qp_table(struct ipath_ibdev *idev, int size);
+
+void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
+
+void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
+
+void ipath_do_rc_send(unsigned long data);
+
+void ipath_do_uc_send(unsigned long data);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+		  u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+		  struct ib_sge *sge, int acc);
+
+void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length);
+
+void ipath_skip_sge(struct ipath_sge_state *ss, u32 length);
+
+int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc);
+
+int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr);
+
+void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+		  int has_grh, void *data, u32 tlen, struct ipath_qp *qp);
+
+int ipath_alloc_lkey(struct ipath_lkey_table *rkt,
+		     struct ipath_mregion *mr);
+
+void ipath_free_lkey(struct ipath_lkey_table *rkt, u32 lkey);
+
+int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge,
+		  struct ib_sge *sge, int acc);
+
+int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss,
+		  u32 len, u64 vaddr, u32 rkey, int acc);
+
+int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+			   struct ib_recv_wr **bad_wr);
+
+struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+				struct ib_srq_init_attr *srq_init_attr,
+				struct ib_udata *udata);
+
+int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+		     enum ib_srq_attr_mask attr_mask);
+
+int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr);
+
+int ipath_destroy_srq(struct ib_srq *ibsrq);
+
+void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig);
+
+int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);
+
+struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
+			      struct ib_ucontext *context,
+			      struct ib_udata *udata);
+
+int ipath_destroy_cq(struct ib_cq *ibcq);
+
+int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify);
+
+int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata);
+
+struct ib_mr *ipath_get_dma_mr(struct ib_pd *pd, int acc);
+
+struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd,
+				struct ib_phys_buf *buffer_list,
+				int num_phys_buf, int acc, u64 *iova_start);
+
+struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+				int mr_access_flags,
+				struct ib_udata *udata);
+
+int ipath_dereg_mr(struct ib_mr *ibmr);
+
+struct ib_fmr *ipath_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
+			       struct ib_fmr_attr *fmr_attr);
+
+int ipath_map_phys_fmr(struct ib_fmr *ibfmr, u64 * page_list,
+		       int list_len, u64 iova);
+
+int ipath_unmap_fmr(struct list_head *fmr_list);
+
+int ipath_dealloc_fmr(struct ib_fmr *ibfmr);
+
+void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev);
+
+void ipath_insert_rnr_queue(struct ipath_qp *qp);
+
+int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only);
+
+void ipath_ruc_loopback(struct ipath_qp *sqp, struct ib_wc *wc);
+
+extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
+
+extern const u8 ipath_cvt_physportstate[];
+
+extern const int ib_ipath_state_ops[];
+
+extern unsigned int ib_ipath_lkey_table_size;
+
+extern const u32 ib_ipath_rnr_table[];
+
+#endif				/* IPATH_VERBS_H */
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
new file mode 100644
index 0000000..10b31d2
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/list.h>
+#include <linux/rcupdate.h>
+
+#include "ipath_verbs.h"
+
+/*
+ * Global table of GID to attached QPs.
+ * The table is global to all ipath devices since a send from one QP/device
+ * needs to be locally routed to any locally attached QPs on the same
+ * or different device.
+ */
+static struct rb_root mcast_tree;
+static DEFINE_SPINLOCK(mcast_lock);
+
+/**
+ * ipath_mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct
+ * @qp: the QP to link
+ */
+static struct ipath_mcast_qp *ipath_mcast_qp_alloc(struct ipath_qp *qp)
+{
+	struct ipath_mcast_qp *mqp;
+
+	mqp = kmalloc(sizeof *mqp, GFP_KERNEL);
+	if (!mqp)
+		goto bail;
+
+	mqp->qp = qp;
+	atomic_inc(&qp->refcount);
+
+bail:
+	return mqp;
+}
+
+static void ipath_mcast_qp_free(struct ipath_mcast_qp *mqp)
+{
+	struct ipath_qp *qp = mqp->qp;
+
+	/* Notify ipath_destroy_qp() if it is waiting. */
+	if (atomic_dec_and_test(&qp->refcount))
+		wake_up(&qp->wait);
+
+	kfree(mqp);
+}
+
+/**
+ * ipath_mcast_alloc - allocate the multicast GID structure
+ * @mgid: the multicast GID
+ *
+ * A list of QPs will be attached to this structure.
+ */
+static struct ipath_mcast *ipath_mcast_alloc(union ib_gid *mgid)
+{
+	struct ipath_mcast *mcast;
+
+	mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
+	if (!mcast)
+		goto bail;
+
+	mcast->mgid = *mgid;
+	INIT_LIST_HEAD(&mcast->qp_list);
+	init_waitqueue_head(&mcast->wait);
+	atomic_set(&mcast->refcount, 0);
+
+bail:
+	return mcast;
+}
+
+static void ipath_mcast_free(struct ipath_mcast *mcast)
+{
+	struct ipath_mcast_qp *p, *tmp;
+
+	list_for_each_entry_safe(p, tmp, &mcast->qp_list, list)
+		ipath_mcast_qp_free(p);
+
+	kfree(mcast);
+}
+
+/**
+ * ipath_mcast_find - search the global table for the given multicast GID
+ * @mgid: the multicast GID to search for
+ *
+ * Returns NULL if not found.
+ *
+ * The caller is responsible for decrementing the reference count if found.
+ */
+struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid)
+{
+	struct rb_node *n;
+	unsigned long flags;
+	struct ipath_mcast *mcast;
+
+	spin_lock_irqsave(&mcast_lock, flags);
+	n = mcast_tree.rb_node;
+	while (n) {
+		int ret;
+
+		mcast = rb_entry(n, struct ipath_mcast, rb_node);
+
+		ret = memcmp(mgid->raw, mcast->mgid.raw,
+			     sizeof(union ib_gid));
+		if (ret < 0)
+			n = n->rb_left;
+		else if (ret > 0)
+			n = n->rb_right;
+		else {
+			atomic_inc(&mcast->refcount);
+			spin_unlock_irqrestore(&mcast_lock, flags);
+			goto bail;
+		}
+	}
+	spin_unlock_irqrestore(&mcast_lock, flags);
+
+	mcast = NULL;
+
+bail:
+	return mcast;
+}
+
+/**
+ * ipath_mcast_add - insert mcast GID into table and attach QP struct
+ * @mcast: the mcast GID table
+ * @mqp: the QP to attach
+ *
+ * Return zero if both were added.  Return EEXIST if the GID was already in
+ * the table but the QP was added.  Return ESRCH if the QP was already
+ * attached and neither structure was added.
+ */
+static int ipath_mcast_add(struct ipath_mcast *mcast,
+			   struct ipath_mcast_qp *mqp)
+{
+	struct rb_node **n = &mcast_tree.rb_node;
+	struct rb_node *pn = NULL;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mcast_lock, flags);
+
+	while (*n) {
+		struct ipath_mcast *tmcast;
+		struct ipath_mcast_qp *p;
+
+		pn = *n;
+		tmcast = rb_entry(pn, struct ipath_mcast, rb_node);
+
+		ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw,
+			     sizeof(union ib_gid));
+		if (ret < 0) {
+			n = &pn->rb_left;
+			continue;
+		}
+		if (ret > 0) {
+			n = &pn->rb_right;
+			continue;
+		}
+
+		/* Search the QP list to see if this is already there. */
+		list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
+			if (p->qp == mqp->qp) {
+				spin_unlock_irqrestore(&mcast_lock, flags);
+				ret = ESRCH;
+				goto bail;
+			}
+		}
+		list_add_tail_rcu(&mqp->list, &tmcast->qp_list);
+		spin_unlock_irqrestore(&mcast_lock, flags);
+		ret = EEXIST;
+		goto bail;
+	}
+
+	list_add_tail_rcu(&mqp->list, &mcast->qp_list);
+
+	atomic_inc(&mcast->refcount);
+	rb_link_node(&mcast->rb_node, pn, n);
+	rb_insert_color(&mcast->rb_node, &mcast_tree);
+
+	spin_unlock_irqrestore(&mcast_lock, flags);
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	struct ipath_mcast *mcast;
+	struct ipath_mcast_qp *mqp;
+	int ret;
+
+	/*
+	 * Allocate data structures since its better to do this outside of
+	 * spin locks and it will most likely be needed.
+	 */
+	mcast = ipath_mcast_alloc(gid);
+	if (mcast == NULL) {
+		ret = -ENOMEM;
+		goto bail;
+	}
+	mqp = ipath_mcast_qp_alloc(qp);
+	if (mqp == NULL) {
+		ipath_mcast_free(mcast);
+		ret = -ENOMEM;
+		goto bail;
+	}
+	switch (ipath_mcast_add(mcast, mqp)) {
+	case ESRCH:
+		/* Neither was used: can't attach the same QP twice. */
+		ipath_mcast_qp_free(mqp);
+		ipath_mcast_free(mcast);
+		ret = -EINVAL;
+		goto bail;
+	case EEXIST:		/* The mcast wasn't used */
+		ipath_mcast_free(mcast);
+		break;
+	default:
+		break;
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+	struct ipath_qp *qp = to_iqp(ibqp);
+	struct ipath_mcast *mcast = NULL;
+	struct ipath_mcast_qp *p, *tmp;
+	struct rb_node *n;
+	unsigned long flags;
+	int last = 0;
+	int ret;
+
+	spin_lock_irqsave(&mcast_lock, flags);
+
+	/* Find the GID in the mcast table. */
+	n = mcast_tree.rb_node;
+	while (1) {
+		if (n == NULL) {
+			spin_unlock_irqrestore(&mcast_lock, flags);
+			ret = 0;
+			goto bail;
+		}
+
+		mcast = rb_entry(n, struct ipath_mcast, rb_node);
+		ret = memcmp(gid->raw, mcast->mgid.raw,
+			     sizeof(union ib_gid));
+		if (ret < 0)
+			n = n->rb_left;
+		else if (ret > 0)
+			n = n->rb_right;
+		else
+			break;
+	}
+
+	/* Search the QP list. */
+	list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
+		if (p->qp != qp)
+			continue;
+		/*
+		 * We found it, so remove it, but don't poison the forward
+		 * link until we are sure there are no list walkers.
+		 */
+		list_del_rcu(&p->list);
+
+		/* If this was the last attached QP, remove the GID too. */
+		if (list_empty(&mcast->qp_list)) {
+			rb_erase(&mcast->rb_node, &mcast_tree);
+			last = 1;
+		}
+		break;
+	}
+
+	spin_unlock_irqrestore(&mcast_lock, flags);
+
+	if (p) {
+		/*
+		 * Wait for any list walkers to finish before freeing the
+		 * list element.
+		 */
+		wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+		ipath_mcast_qp_free(p);
+	}
+	if (last) {
+		atomic_dec(&mcast->refcount);
+		wait_event(mcast->wait, !atomic_read(&mcast->refcount));
+		ipath_mcast_free(mcast);
+	}
+
+	ret = 0;
+
+bail:
+	return ret;
+}
+
+int ipath_mcast_tree_empty(void)
+{
+	return mcast_tree.rb_node == NULL;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
new file mode 100644
index 0000000..adc5322
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * This file is conditionally built on x86_64 only.  Otherwise weak symbol
+ * versions of the functions exported from here are used.
+ */
+
+#include <linux/pci.h>
+#include <asm/mtrr.h>
+#include <asm/processor.h>
+
+#include "ipath_kernel.h"
+
+/**
+ * ipath_enable_wc - enable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ *
+ * This routine is x86_64-specific; it twiddles the CPU's MTRRs to enable
+ * write combining.
+ */
+int ipath_enable_wc(struct ipath_devdata *dd)
+{
+	int ret = 0;
+	u64 pioaddr, piolen;
+	unsigned bits;
+	const unsigned long addr = pci_resource_start(dd->pcidev, 0);
+	const size_t len = pci_resource_len(dd->pcidev, 0);
+
+	/*
+	 * Set the PIO buffers to be WCCOMB, so we get HT bursts to the
+	 * chip.  Linux (possibly the hardware) requires it to be on a power
+	 * of 2 address matching the length (which has to be a power of 2).
+	 * For rev1, that means the base address, for rev2, it will be just
+	 * the PIO buffers themselves.
+	 */
+	pioaddr = addr + dd->ipath_piobufbase;
+	piolen = (dd->ipath_piobcnt2k +
+		  dd->ipath_piobcnt4k) *
+		ALIGN(dd->ipath_piobcnt2k +
+		      dd->ipath_piobcnt4k, dd->ipath_palign);
+
+	for (bits = 0; !(piolen & (1ULL << bits)); bits++)
+		/* do nothing */ ;
+
+	if (piolen != (1ULL << bits)) {
+		piolen >>= bits;
+		while (piolen >>= 1)
+			bits++;
+		piolen = 1ULL << (bits + 1);
+	}
+	if (pioaddr & (piolen - 1)) {
+		u64 atmp;
+		ipath_dbg("pioaddr %llx not on right boundary for size "
+			  "%llx, fixing\n",
+			  (unsigned long long) pioaddr,
+			  (unsigned long long) piolen);
+		atmp = pioaddr & ~(piolen - 1);
+		if (atmp < addr || (atmp + piolen) > (addr + len)) {
+			ipath_dev_err(dd, "No way to align address/size "
+				      "(%llx/%llx), no WC mtrr\n",
+				      (unsigned long long) atmp,
+				      (unsigned long long) piolen << 1);
+			ret = -ENODEV;
+		} else {
+			ipath_dbg("changing WC base from %llx to %llx, "
+				  "len from %llx to %llx\n",
+				  (unsigned long long) pioaddr,
+				  (unsigned long long) atmp,
+				  (unsigned long long) piolen,
+				  (unsigned long long) piolen << 1);
+			pioaddr = atmp;
+			piolen <<= 1;
+		}
+	}
+
+	if (!ret) {
+		int cookie;
+		ipath_cdbg(VERBOSE, "Setting mtrr for chip to WC "
+			   "(addr %llx, len=0x%llx)\n",
+			   (unsigned long long) pioaddr,
+			   (unsigned long long) piolen);
+		cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
+		if (cookie < 0) {
+			{
+				dev_info(&dd->pcidev->dev,
+					 "mtrr_add()  WC for PIO bufs "
+					 "failed (%d)\n",
+					 cookie);
+				ret = -EINVAL;
+			}
+		} else {
+			ipath_cdbg(VERBOSE, "Set mtrr for chip to WC, "
+				   "cookie is %d\n", cookie);
+			dd->ipath_wc_cookie = cookie;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * ipath_disable_wc - disable write combining for MMIO writes to the device
+ * @dd: infinipath device
+ */
+void ipath_disable_wc(struct ipath_devdata *dd)
+{
+	if (dd->ipath_wc_cookie) {
+		ipath_cdbg(VERBOSE, "undoing WCCOMB on pio buffers\n");
+		mtrr_del(dd->ipath_wc_cookie, 0, 0);
+		dd->ipath_wc_cookie = 0;
+	}
+}
+
+/**
+ * ipath_unordered_wc - indicate whether write combining is ordered
+ *
+ * Because our performance depends on our ability to do write combining mmio
+ * writes in the most efficient way, we need to know if we are on an Intel
+ * or AMD x86_64 processor.  AMD x86_64 processors flush WC buffers out in
+ * the order completed, and so no special flushing is required to get
+ * correct ordering.  Intel processors, however, will flush write buffers
+ * out in "random" orders, and so explicit ordering is needed at times.
+ */
+int ipath_unordered_wc(void)
+{
+	return boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
+}
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h
new file mode 100644
index 0000000..410a764
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/ips_common.h
@@ -0,0 +1,263 @@
+#ifndef IPS_COMMON_H
+#define IPS_COMMON_H
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ipath_common.h"
+
+struct ipath_header {
+	/*
+	 * Version - 4 bits, Port - 4 bits, TID - 10 bits and Offset -
+	 * 14 bits before ECO change ~28 Dec 03.  After that, Vers 4,
+	 * Port 3, TID 11, offset 14.
+	 */
+	__le32 ver_port_tid_offset;
+	__le16 chksum;
+	__le16 pkt_flags;
+};
+
+struct ips_message_header {
+	__be16 lrh[4];
+	__be32 bth[3];
+	/* fields below this point are in host byte order */
+	struct ipath_header iph;
+	__u8 sub_opcode;
+	__u8 flags;
+	__u16 src_rank;
+	/* 24 bits. The upper 8 bit is available for other use */
+	union {
+		struct {
+			unsigned ack_seq_num:24;
+			unsigned port:4;
+			unsigned unused:4;
+		};
+		__u32 ack_seq_num_org;
+	};
+	__u8 expected_tid_session_id;
+	__u8 tinylen;		/* to aid MPI */
+	union {
+	    __u16 tag;		/* to aid MPI */
+	    __u16 mqhdr;	/* for PSM MQ */
+	};
+	union {
+		__u32 mpi[4];	/* to aid MPI */
+		__u32 data[4];
+		__u64 mq[2];	/* for PSM MQ */
+		struct {
+			__u16 mtu;
+			__u8 major_ver;
+			__u8 minor_ver;
+			__u32 not_used;	//free
+			__u32 run_id;
+			__u32 client_ver;
+		};
+	};
+};
+
+struct ether_header {
+	__be16 lrh[4];
+	__be32 bth[3];
+	struct ipath_header iph;
+	__u8 sub_opcode;
+	__u8 cmd;
+	__be16 lid;
+	__u16 mac[3];
+	__u8 frag_num;
+	__u8 seq_num;
+	__le32 len;
+	/* MUST be of word size due to PIO write requirements */
+	__u32 csum;
+	__le16 csum_offset;
+	__le16 flags;
+	__u16 first_2_bytes;
+	__u8 unused[2];		/* currently unused */
+};
+
+/*
+ * The PIO buffer used for sending infinipath messages must only be written
+ * in 32-bit words, all the data must be written, and no writes can occur
+ * after the last word is written (which transfers "ownership" of the buffer
+ * to the chip and triggers the message to be sent).
+ * Since the Linux sk_buff structure can be recursive, non-aligned, and
+ * any number of bytes in each segment, we use the following structure
+ * to keep information about the overall state of the copy operation.
+ * This is used to save the information needed to store the checksum
+ * in the right place before sending the last word to the hardware and
+ * to buffer the last 0-3 bytes of non-word sized segments.
+ */
+struct copy_data_s {
+	struct ether_header *hdr;
+	/* addr of PIO buf to write csum to */
+	__u32 __iomem *csum_pio;
+	__u32 __iomem *to;	/* addr of PIO buf to write data to */
+	__u32 device;		/* which device to allocate PIO bufs from */
+	__s32 error;		/* set if there is an error. */
+	__s32 extra;		/* amount of data saved in u.buf below */
+	__u32 len;		/* total length to send in bytes */
+	__u32 flen;		/* frament length in words */
+	__u32 csum;		/* partial IP checksum */
+	__u32 pos;		/* position for partial checksum */
+	__u32 offset;		/* offset to where data currently starts */
+	__s32 checksum_calc;	/* set to 1 when csum has been calculated */
+	struct sk_buff *skb;
+	union {
+		__u32 w;
+		__u8 buf[4];
+	} u;
+};
+
+/* IB - LRH header consts */
+#define IPS_LRH_GRH 0x0003	/* 1. word of IB LRH - next header: GRH */
+#define IPS_LRH_BTH 0x0002	/* 1. word of IB LRH - next header: BTH */
+
+#define IPS_OFFSET  0
+
+/*
+ * defines the cut-off point between the header queue and eager/expected
+ * TID queue
+ */
+#define NUM_OF_EXTRA_WORDS_IN_HEADER_QUEUE \
+	((sizeof(struct ips_message_header) - \
+	  offsetof(struct ips_message_header, iph)) >> 2)
+
+/* OpCodes  */
+#define OPCODE_IPS 0xC0
+#define OPCODE_ITH4X 0xC1
+
+/* OpCode 30 is use by stand-alone test programs  */
+#define OPCODE_RAW_DATA 0xDE
+/* last OpCode (31) is reserved for test  */
+#define OPCODE_TEST 0xDF
+
+/* sub OpCodes - ips  */
+#define OPCODE_SEQ_DATA 0x01
+#define OPCODE_SEQ_CTRL 0x02
+
+#define OPCODE_SEQ_MQ_DATA 0x03
+#define OPCODE_SEQ_MQ_CTRL 0x04
+
+#define OPCODE_ACK 0x10
+#define OPCODE_NAK 0x11
+
+#define OPCODE_ERR_CHK 0x20
+#define OPCODE_ERR_CHK_PLS 0x21
+
+#define OPCODE_STARTUP 0x30
+#define OPCODE_STARTUP_ACK 0x31
+#define OPCODE_STARTUP_NAK 0x32
+
+#define OPCODE_STARTUP_EXT 0x34
+#define OPCODE_STARTUP_ACK_EXT 0x35
+#define OPCODE_STARTUP_NAK_EXT 0x36
+
+#define OPCODE_TIDS_RELEASE 0x40
+#define OPCODE_TIDS_RELEASE_CONFIRM 0x41
+
+#define OPCODE_CLOSE 0x50
+#define OPCODE_CLOSE_ACK 0x51
+/*
+ * like OPCODE_CLOSE, but no complaint if other side has already closed.
+ * Used when doing abort(), MPI_Abort(), etc.
+ */
+#define OPCODE_ABORT 0x52
+
+/* sub OpCodes - ith4x  */
+#define OPCODE_ENCAP 0x81
+#define OPCODE_LID_ARP 0x82
+
+/* Receive Header Queue: receive type (from infinipath) */
+#define RCVHQ_RCV_TYPE_EXPECTED  0
+#define RCVHQ_RCV_TYPE_EAGER     1
+#define RCVHQ_RCV_TYPE_NON_KD    2
+#define RCVHQ_RCV_TYPE_ERROR     3
+
+/* misc. */
+#define SIZE_OF_CRC 1
+
+#define EAGER_TID_ID INFINIPATH_I_TID_MASK
+
+#define IPS_DEFAULT_P_KEY 0xFFFF
+
+#define IPS_PERMISSIVE_LID 0xFFFF
+#define IPS_MULTICAST_LID_BASE 0xC000
+
+#define IPS_AETH_CREDIT_SHIFT 24
+#define IPS_AETH_CREDIT_MASK 0x1F
+#define IPS_AETH_CREDIT_INVAL 0x1F
+
+#define IPS_PSN_MASK 0xFFFFFF
+#define IPS_MSN_MASK 0xFFFFFF
+#define IPS_QPN_MASK 0xFFFFFF
+#define IPS_MULTICAST_QPN 0xFFFFFF
+
+/* functions for extracting fields from rcvhdrq entries */
+static inline __u32 ips_get_hdr_err_flags(const __le32 * rbuf)
+{
+	return __le32_to_cpu(rbuf[1]);
+}
+
+static inline __u32 ips_get_index(const __le32 * rbuf)
+{
+	return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_EGRINDEX_SHIFT)
+	    & INFINIPATH_RHF_EGRINDEX_MASK;
+}
+
+static inline __u32 ips_get_rcv_type(const __le32 * rbuf)
+{
+	return (__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_RCVTYPE_SHIFT)
+	    & INFINIPATH_RHF_RCVTYPE_MASK;
+}
+
+static inline __u32 ips_get_length_in_bytes(const __le32 * rbuf)
+{
+	return ((__le32_to_cpu(rbuf[0]) >> INFINIPATH_RHF_LENGTH_SHIFT)
+		& INFINIPATH_RHF_LENGTH_MASK) << 2;
+}
+
+static inline void *ips_get_first_protocol_header(const __u32 * rbuf)
+{
+	return (void *)&rbuf[2];
+}
+
+static inline struct ips_message_header *ips_get_ips_header(const __u32 *
+							    rbuf)
+{
+	return (struct ips_message_header *)&rbuf[2];
+}
+
+static inline __u32 ips_get_ipath_ver(__le32 hdrword)
+{
+	return (__le32_to_cpu(hdrword) >> INFINIPATH_I_VERS_SHIFT)
+	    & INFINIPATH_I_VERS_MASK;
+}
+
+#endif				/* IPS_COMMON_H */
diff --git a/drivers/infiniband/hw/ipath/verbs_debug.h b/drivers/infiniband/hw/ipath/verbs_debug.h
new file mode 100644
index 0000000..40d693c
--- /dev/null
+++ b/drivers/infiniband/hw/ipath/verbs_debug.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _VERBS_DEBUG_H
+#define _VERBS_DEBUG_H
+
+/*
+ * This file contains tracing code for the ib_ipath kernel module.
+ */
+#ifndef _VERBS_DEBUGGING	/* tracing enabled or not */
+#define _VERBS_DEBUGGING 1
+#endif
+
+extern unsigned ib_ipath_debug;
+
+#define _VERBS_ERROR(fmt,...) \
+	do { \
+		printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+	} while(0)
+
+#define _VERBS_UNIT_ERROR(unit,fmt,...) \
+	do { \
+		printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \
+	} while(0)
+
+#if _VERBS_DEBUGGING
+
+/*
+ * Mask values for debugging.  The scheme allows us to compile out any
+ * of the debug tracing stuff, and if compiled in, to enable or
+ * disable dynamically.
+ * This can be set at modprobe time also:
+ *      modprobe ib_path ib_ipath_debug=3
+ */
+
+#define __VERBS_INFO        0x1	/* generic low verbosity stuff */
+#define __VERBS_DBG         0x2	/* generic debug */
+#define __VERBS_VDBG        0x4	/* verbose debug */
+#define __VERBS_SMADBG      0x8000	/* sma packet debug */
+
+#define _VERBS_INFO(fmt,...) \
+	do { \
+		if (unlikely(ib_ipath_debug&__VERBS_INFO)) \
+			printk(KERN_INFO "%s: " fmt,"ib_ipath", \
+			       ##__VA_ARGS__); \
+	} while(0)
+
+#define _VERBS_DBG(fmt,...) \
+	do { \
+		if (unlikely(ib_ipath_debug&__VERBS_DBG)) \
+			printk(KERN_DEBUG "%s: " fmt, __func__, \
+			       ##__VA_ARGS__); \
+	} while(0)
+
+#define _VERBS_VDBG(fmt,...) \
+	do { \
+		if (unlikely(ib_ipath_debug&__VERBS_VDBG)) \
+			printk(KERN_DEBUG "%s: " fmt, __func__, \
+			       ##__VA_ARGS__); \
+	} while(0)
+
+#define _VERBS_SMADBG(fmt,...) \
+	do { \
+		if (unlikely(ib_ipath_debug&__VERBS_SMADBG)) \
+			printk(KERN_DEBUG "%s: " fmt, __func__, \
+			       ##__VA_ARGS__); \
+	} while(0)
+
+#else /* ! _VERBS_DEBUGGING */
+
+#define _VERBS_INFO(fmt,...)
+#define _VERBS_DBG(fmt,...)
+#define _VERBS_VDBG(fmt,...)
+#define _VERBS_SMADBG(fmt,...)
+
+#endif /* _VERBS_DEBUGGING */
+
+#endif /* _VERBS_DEBUG_H */
diff --git a/drivers/infiniband/hw/mthca/Kconfig b/drivers/infiniband/hw/mthca/Kconfig
index e88be85..9aa5a44 100644
--- a/drivers/infiniband/hw/mthca/Kconfig
+++ b/drivers/infiniband/hw/mthca/Kconfig
@@ -7,10 +7,11 @@
 	  ("Tavor") and the MT25208 PCI Express HCA ("Arbel").
 
 config INFINIBAND_MTHCA_DEBUG
-	bool "Verbose debugging output"
+	bool "Verbose debugging output" if EMBEDDED
 	depends on INFINIBAND_MTHCA
-	default n
+	default y
 	---help---
-	  This option causes the mthca driver produce a bunch of debug
-	  messages.  Select this is you are developing the driver or
-	  trying to diagnose a problem.
+	  This option causes debugging code to be compiled into the
+	  mthca driver.  The output can be turned on via the
+	  debug_level module parameter (which can also be set after
+	  the driver is loaded through sysfs).
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index 47ec5a7..e388d95 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -1,7 +1,3 @@
-ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
-
 obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
 
 ib_mthca-y :=	mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index bc5bdcb..b12aa03 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -42,6 +42,20 @@
 
 #include "mthca_dev.h"
 
+enum {
+      MTHCA_RATE_TAVOR_FULL   = 0,
+      MTHCA_RATE_TAVOR_1X     = 1,
+      MTHCA_RATE_TAVOR_4X     = 2,
+      MTHCA_RATE_TAVOR_1X_DDR = 3
+};
+
+enum {
+      MTHCA_RATE_MEMFREE_FULL    = 0,
+      MTHCA_RATE_MEMFREE_QUARTER = 1,
+      MTHCA_RATE_MEMFREE_EIGHTH  = 2,
+      MTHCA_RATE_MEMFREE_HALF    = 3
+};
+
 struct mthca_av {
 	__be32 port_pd;
 	u8     reserved1;
@@ -55,6 +69,90 @@
 	__be32 dgid[4];
 };
 
+static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+	switch (mthca_rate) {
+	case MTHCA_RATE_MEMFREE_EIGHTH:
+		return mult_to_ib_rate(port_rate >> 3);
+	case MTHCA_RATE_MEMFREE_QUARTER:
+		return mult_to_ib_rate(port_rate >> 2);
+	case MTHCA_RATE_MEMFREE_HALF:
+		return mult_to_ib_rate(port_rate >> 1);
+	case MTHCA_RATE_MEMFREE_FULL:
+	default:
+		return mult_to_ib_rate(port_rate);
+	}
+}
+
+static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
+{
+	switch (mthca_rate) {
+	case MTHCA_RATE_TAVOR_1X:     return IB_RATE_2_5_GBPS;
+	case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
+	case MTHCA_RATE_TAVOR_4X:     return IB_RATE_10_GBPS;
+	default:		      return port_rate;
+	}
+}
+
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
+{
+	if (mthca_is_memfree(dev)) {
+		/* Handle old Arbel FW */
+		if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
+			return IB_RATE_2_5_GBPS;
+
+		return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+	} else
+		return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
+}
+
+static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
+{
+	if (cur_rate <= req_rate)
+		return 0;
+
+	/*
+	 * Inter-packet delay (IPD) to get from rate X down to a rate
+	 * no more than Y is (X - 1) / Y.
+	 */
+	switch ((cur_rate - 1) / req_rate) {
+	case 0:	 return MTHCA_RATE_MEMFREE_FULL;
+	case 1:	 return MTHCA_RATE_MEMFREE_HALF;
+	case 2:	 /* fall through */
+	case 3:	 return MTHCA_RATE_MEMFREE_QUARTER;
+	default: return MTHCA_RATE_MEMFREE_EIGHTH;
+	}
+}
+
+static u8 ib_rate_to_tavor(u8 static_rate)
+{
+	switch (static_rate) {
+	case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
+	case IB_RATE_5_GBPS:   return MTHCA_RATE_TAVOR_1X_DDR;
+	case IB_RATE_10_GBPS:  return MTHCA_RATE_TAVOR_4X;
+	default:	       return MTHCA_RATE_TAVOR_FULL;
+	}
+}
+
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
+{
+	u8 rate;
+
+	if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
+		return 0;
+
+	if (mthca_is_memfree(dev))
+		rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
+					  dev->rate[port - 1]);
+	else
+		rate = ib_rate_to_tavor(static_rate);
+
+	if (!(dev->limits.stat_rate_support & (1 << rate)))
+		rate = 1;
+
+	return rate;
+}
+
 int mthca_create_ah(struct mthca_dev *dev,
 		    struct mthca_pd *pd,
 		    struct ib_ah_attr *ah_attr,
@@ -107,7 +205,7 @@
 	av->g_slid  = ah_attr->src_path_bits;
 	av->dlid    = cpu_to_be16(ah_attr->dlid);
 	av->msg_sr  = (3 << 4) | /* 2K message */
-		ah_attr->static_rate;
+		mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
 	av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
 	if (ah_attr->ah_flags & IB_AH_GRH) {
 		av->g_slid |= 0x80;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 343eca5..1985b5d 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -965,6 +965,7 @@
 	u32 *outbox;
 	u8 field;
 	u16 size;
+	u16 stat_rate;
 	int err;
 
 #define QUERY_DEV_LIM_OUT_SIZE             0x100
@@ -995,6 +996,7 @@
 #define QUERY_DEV_LIM_MTU_WIDTH_OFFSET      0x36
 #define QUERY_DEV_LIM_VL_PORT_OFFSET        0x37
 #define QUERY_DEV_LIM_MAX_GID_OFFSET        0x3b
+#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET   0x3c
 #define QUERY_DEV_LIM_MAX_PKEY_OFFSET       0x3f
 #define QUERY_DEV_LIM_FLAGS_OFFSET          0x44
 #define QUERY_DEV_LIM_RSVD_UAR_OFFSET       0x48
@@ -1086,6 +1088,8 @@
 	dev_lim->num_ports = field & 0xf;
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
 	dev_lim->max_gids = 1 << (field & 0xf);
+	MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
+	dev_lim->stat_rate_support = stat_rate;
 	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
 	dev_lim->max_pkeys = 1 << (field & 0xf);
 	MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index e4ec35c..2f976f2 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -146,6 +146,7 @@
 	int max_vl;
 	int num_ports;
 	int max_gids;
+	u16 stat_rate_support;
 	int max_pkeys;
 	u32 flags;
 	int reserved_uars;
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ad52edb..4c1dcb4 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -151,6 +151,7 @@
 	int      reserved_qps;
 	int      num_srqs;
 	int      max_srq_wqes;
+	int      max_srq_sge;
 	int      reserved_srqs;
 	int      num_eecs;
 	int      reserved_eecs;
@@ -172,6 +173,7 @@
 	int      reserved_pds;
 	u32      page_size_cap;
 	u32      flags;
+	u16      stat_rate_support;
 	u8       port_width_cap;
 };
 
@@ -353,10 +355,24 @@
 	struct ib_mad_agent  *send_agent[MTHCA_MAX_PORTS][2];
 	struct ib_ah         *sm_ah[MTHCA_MAX_PORTS];
 	spinlock_t            sm_lock;
+	u8                    rate[MTHCA_MAX_PORTS];
 };
 
-#define mthca_dbg(mdev, format, arg...) \
-	dev_dbg(&mdev->pdev->dev, format, ## arg)
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+extern int mthca_debug_level;
+
+#define mthca_dbg(mdev, format, arg...)					\
+	do {								\
+		if (mthca_debug_level)					\
+			dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \
+	} while (0)
+
+#else /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
+#define mthca_dbg(mdev, format, arg...) do { (void) mdev; } while (0)
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
 #define mthca_err(mdev, format, arg...) \
 	dev_err(&mdev->pdev->dev, format, ## arg)
 #define mthca_info(mdev, format, arg...) \
@@ -492,6 +508,7 @@
 int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 		     enum ib_srq_attr_mask attr_mask);
 int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+int mthca_max_srq_sge(struct mthca_dev *dev);
 void mthca_srq_event(struct mthca_dev *dev, u32 srqn,
 		     enum ib_event_type event_type);
 void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
@@ -542,6 +559,8 @@
 		  struct ib_ud_header *header);
 int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr);
 int mthca_ah_grh_present(struct mthca_ah *ah);
+u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port);
+enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port);
 
 int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
 int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index dfb482e..4730863 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -49,6 +49,30 @@
 	MTHCA_VENDOR_CLASS2 = 0xa
 };
 
+static int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
+{
+	struct ib_port_attr *tprops = NULL;
+	int                  ret;
+
+	tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
+	if (!tprops)
+		return -ENOMEM;
+
+	ret = ib_query_port(&dev->ib_dev, port_num, tprops);
+	if (ret) {
+		printk(KERN_WARNING "ib_query_port failed (%d) for %s port %d\n",
+		       ret, dev->ib_dev.name, port_num);
+		goto out;
+	}
+
+	dev->rate[port_num - 1] = tprops->active_speed *
+				  ib_width_enum_to_int(tprops->active_width);
+
+out:
+	kfree(tprops);
+	return ret;
+}
+
 static void update_sm_ah(struct mthca_dev *dev,
 			 u8 port_num, u16 lid, u8 sl)
 {
@@ -90,6 +114,7 @@
 	     mad->mad_hdr.mgmt_class  == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
 	    mad->mad_hdr.method     == IB_MGMT_METHOD_SET) {
 		if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
+			mthca_update_rate(to_mdev(ibdev), port_num);
 			update_sm_ah(to_mdev(ibdev), port_num,
 				     be16_to_cpup((__be16 *) (mad->data + 58)),
 				     (*(u8 *) (mad->data + 76)) & 0xf);
@@ -246,6 +271,7 @@
 {
 	struct ib_mad_agent *agent;
 	int p, q;
+	int ret;
 
 	spin_lock_init(&dev->sm_lock);
 
@@ -255,11 +281,23 @@
 						      q ? IB_QPT_GSI : IB_QPT_SMI,
 						      NULL, 0, send_handler,
 						      NULL, NULL);
-			if (IS_ERR(agent))
+			if (IS_ERR(agent)) {
+				ret = PTR_ERR(agent);
 				goto err;
+			}
 			dev->send_agent[p][q] = agent;
 		}
 
+
+	for (p = 1; p <= dev->limits.num_ports; ++p) {
+		ret = mthca_update_rate(dev, p);
+		if (ret) {
+			mthca_err(dev, "Failed to obtain port %d rate."
+				  " aborting.\n", p);
+			goto err;
+		}
+	}
+
 	return 0;
 
 err:
@@ -268,7 +306,7 @@
 			if (dev->send_agent[p][q])
 				ib_unregister_mad_agent(dev->send_agent[p][q]);
 
-	return PTR_ERR(agent);
+	return ret;
 }
 
 void __devexit mthca_free_agents(struct mthca_dev *dev)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 266f347..9b9ff7b 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -52,6 +52,14 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
+
+int mthca_debug_level = 0;
+module_param_named(debug_level, mthca_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
+
+#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */
+
 #ifdef CONFIG_PCI_MSI
 
 static int msi_x = 0;
@@ -69,6 +77,10 @@
 
 #endif /* CONFIG_PCI_MSI */
 
+static int tune_pci = 0;
+module_param(tune_pci, int, 0444);
+MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");
+
 static const char mthca_version[] __devinitdata =
 	DRV_NAME ": Mellanox InfiniBand HCA driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -90,6 +102,9 @@
 	int cap;
 	u16 val;
 
+	if (!tune_pci)
+		return 0;
+
 	/* First try to max out Read Byte Count */
 	cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
 	if (cap) {
@@ -176,6 +191,7 @@
 	mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;
 	mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;
 	mdev->limits.max_desc_sz        = dev_lim->max_desc_sz;
+	mdev->limits.max_srq_sge	= mthca_max_srq_sge(mdev);
 	/*
 	 * Subtract 1 from the limit because we need to allocate a
 	 * spare CQE so the HCA HW can tell the difference between an
@@ -191,6 +207,18 @@
 	mdev->limits.port_width_cap     = dev_lim->max_port_width;
 	mdev->limits.page_size_cap      = ~(u32) (dev_lim->min_page_sz - 1);
 	mdev->limits.flags              = dev_lim->flags;
+	/*
+	 * For old FW that doesn't return static rate support, use a
+	 * value of 0x3 (only static rate values of 0 or 1 are handled),
+	 * except on Sinai, where even old FW can handle static rate
+	 * values of 2 and 3.
+	 */
+	if (dev_lim->stat_rate_support)
+		mdev->limits.stat_rate_support = dev_lim->stat_rate_support;
+	else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
+		mdev->limits.stat_rate_support = 0xf;
+	else
+		mdev->limits.stat_rate_support = 0x3;
 
 	/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
 	   May be doable since hardware supports it for SRQ.
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 2c250bc..565a24b 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -106,7 +106,7 @@
 	props->max_res_rd_atom     = props->max_qp_rd_atom * props->max_qp;
 	props->max_srq             = mdev->limits.num_srqs - mdev->limits.reserved_srqs;
 	props->max_srq_wr          = mdev->limits.max_srq_wqes;
-	props->max_srq_sge         = mdev->limits.max_sg;
+	props->max_srq_sge         = mdev->limits.max_srq_sge;
 	props->local_ca_ack_delay  = mdev->limits.local_ca_ack_delay;
 	props->atomic_cap          = mdev->limits.flags & DEV_LIM_FLAG_ATOMIC ?
 					IB_ATOMIC_HCA : IB_ATOMIC_NONE;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 2e7f521..6676a78 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -257,6 +257,8 @@
 	atomic_t               refcount;
 	u32                    qpn;
 	int                    is_direct;
+	u8                     port; /* for SQP and memfree use only */
+	u8                     alt_port; /* for memfree use only */
 	u8                     transport;
 	u8                     state;
 	u8                     atomic_rd_en;
@@ -278,7 +280,6 @@
 
 struct mthca_sqp {
 	struct mthca_qp qp;
-	int             port;
 	int             pkey_index;
 	u32             qkey;
 	u32             send_psn;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 057c8e6..f37b0e3 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -248,6 +248,9 @@
 		return;
 	}
 
+	if (event_type == IB_EVENT_PATH_MIG)
+		qp->port = qp->alt_port;
+
 	event.device      = &dev->ib_dev;
 	event.event       = event_type;
 	event.element.qp  = &qp->ibqp;
@@ -392,10 +395,16 @@
 {
 	memset(ib_ah_attr, 0, sizeof *path);
 	ib_ah_attr->port_num 	  = (be32_to_cpu(path->port_pkey) >> 24) & 0x3;
+
+	if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->limits.num_ports)
+		return;
+
 	ib_ah_attr->dlid     	  = be16_to_cpu(path->rlid);
 	ib_ah_attr->sl       	  = be32_to_cpu(path->sl_tclass_flowlabel) >> 28;
 	ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f;
-	ib_ah_attr->static_rate   = path->static_rate & 0x7;
+	ib_ah_attr->static_rate   = mthca_rate_to_ib(dev,
+						     path->static_rate & 0x7,
+						     ib_ah_attr->port_num);
 	ib_ah_attr->ah_flags      = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
 	if (ib_ah_attr->ah_flags) {
 		ib_ah_attr->grh.sgid_index = path->mgid_index & (dev->limits.gid_table_len - 1);
@@ -455,8 +464,10 @@
 	qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
 	qp_attr->cap.max_inline_data = qp->max_inline_data;
 
-	to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
-	to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+	if (qp->transport == RC || qp->transport == UC) {
+		to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
+		to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
+	}
 
 	qp_attr->pkey_index     = be32_to_cpu(context->pri_path.port_pkey) & 0x7f;
 	qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f;
@@ -484,11 +495,11 @@
 }
 
 static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah,
-			  struct mthca_qp_path *path)
+			  struct mthca_qp_path *path, u8 port)
 {
 	path->g_mylmc     = ah->src_path_bits & 0x7f;
 	path->rlid        = cpu_to_be16(ah->dlid);
-	path->static_rate = !!ah->static_rate;
+	path->static_rate = mthca_get_rate(dev, ah->static_rate, port);
 
 	if (ah->ah_flags & IB_AH_GRH) {
 		if (ah->grh.sgid_index >= dev->limits.gid_table_len) {
@@ -634,7 +645,7 @@
 
 	if (qp->transport == MLX)
 		qp_context->pri_path.port_pkey |=
-			cpu_to_be32(to_msqp(qp)->port << 24);
+			cpu_to_be32(qp->port << 24);
 	else {
 		if (attr_mask & IB_QP_PORT) {
 			qp_context->pri_path.port_pkey |=
@@ -657,7 +668,8 @@
 	}
 
 	if (attr_mask & IB_QP_AV) {
-		if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path))
+		if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
+				   attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
 			return -EINVAL;
 
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
@@ -681,7 +693,8 @@
 			return -EINVAL;
 		}
 
-		if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path))
+		if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
+				   attr->alt_ah_attr.port_num))
 			return -EINVAL;
 
 		qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
@@ -791,6 +804,10 @@
 		qp->atomic_rd_en = attr->qp_access_flags;
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
 		qp->resp_depth = attr->max_dest_rd_atomic;
+	if (attr_mask & IB_QP_PORT)
+		qp->port = attr->port_num;
+	if (attr_mask & IB_QP_ALT_PATH)
+		qp->alt_port = attr->alt_port_num;
 
 	if (is_sqp(dev, qp))
 		store_attrs(to_msqp(qp), attr, attr_mask);
@@ -802,13 +819,13 @@
 	if (is_qp0(dev, qp)) {
 		if (cur_state != IB_QPS_RTR &&
 		    new_state == IB_QPS_RTR)
-			init_port(dev, to_msqp(qp)->port);
+			init_port(dev, qp->port);
 
 		if (cur_state != IB_QPS_RESET &&
 		    cur_state != IB_QPS_ERR &&
 		    (new_state == IB_QPS_RESET ||
 		     new_state == IB_QPS_ERR))
-			mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
+			mthca_CLOSE_IB(dev, qp->port, &status);
 	}
 
 	/*
@@ -1212,6 +1229,9 @@
 	if (qp->qpn == -1)
 		return -ENOMEM;
 
+	/* initialize port to zero for error-catching. */
+	qp->port = 0;
+
 	err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
 				    send_policy, qp);
 	if (err) {
@@ -1261,7 +1281,7 @@
 	if (err)
 		goto err_out;
 
-	sqp->port = port;
+	sqp->qp.port      = port;
 	sqp->qp.qpn       = mqpn;
 	sqp->qp.transport = MLX;
 
@@ -1404,10 +1424,10 @@
 		sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
 	sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
 	if (!sqp->qp.ibqp.qp_num)
-		ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+		ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
 				   sqp->pkey_index, &pkey);
 	else
-		ib_get_cached_pkey(&dev->ib_dev, sqp->port,
+		ib_get_cached_pkey(&dev->ib_dev, sqp->qp.port,
 				   wr->wr.ud.pkey_index, &pkey);
 	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
 	sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 2dd3aea..adcaf85 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -192,7 +192,7 @@
 
 	/* Sanity check SRQ size before proceeding */
 	if (attr->max_wr  > dev->limits.max_srq_wqes ||
-	    attr->max_sge > dev->limits.max_sg)
+	    attr->max_sge > dev->limits.max_srq_sge)
 		return -EINVAL;
 
 	srq->max      = attr->max_wr;
@@ -660,6 +660,31 @@
 	return err;
 }
 
+int mthca_max_srq_sge(struct mthca_dev *dev)
+{
+	if (mthca_is_memfree(dev))
+		return dev->limits.max_sg;
+
+	/*
+	 * SRQ allocations are based on powers of 2 for Tavor,
+	 * (although they only need to be multiples of 16 bytes).
+	 *
+	 * Therefore, we need to base the max number of sg entries on
+	 * the largest power of 2 descriptor size that is <= to the
+	 * actual max WQE descriptor size, rather than return the
+	 * max_sg value given by the firmware (which is based on WQE
+	 * sizes as multiples of 16, not powers of 2).
+	 *
+	 * If SRQ implementation is changed for Tavor to be based on
+	 * multiples of 16, the calculation below can be deleted and
+	 * the FW max_sg value returned.
+	 */
+	return min_t(int, dev->limits.max_sg,
+		     ((1 << (fls(dev->limits.max_desc_sz) - 1)) -
+		      sizeof (struct mthca_next_seg)) /
+		     sizeof (struct mthca_data_seg));
+}
+
 int __devinit mthca_init_srq_table(struct mthca_dev *dev)
 {
 	int err;
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 8d2e04c..13d6d01 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -10,8 +10,9 @@
 	  group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
 
 config INFINIBAND_IPOIB_DEBUG
-	bool "IP-over-InfiniBand debugging"
+	bool "IP-over-InfiniBand debugging" if EMBEDDED
 	depends on INFINIBAND_IPOIB
+	default y
 	---help---
 	  This option causes debugging code to be compiled into the
 	  IPoIB driver.  The output can be turned on via the
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index b640107..12a1e05 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -65,6 +65,8 @@
 
 	IPOIB_RX_RING_SIZE 	  = 128,
 	IPOIB_TX_RING_SIZE 	  = 64,
+	IPOIB_MAX_QUEUE_SIZE	  = 8192,
+	IPOIB_MIN_QUEUE_SIZE	  = 2,
 
 	IPOIB_NUM_WC 		  = 4,
 
@@ -230,6 +232,9 @@
 				     INFINIBAND_ALEN, sizeof(void *));
 }
 
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
+void ipoib_neigh_free(struct ipoib_neigh *neigh);
+
 extern struct workqueue_struct *ipoib_workqueue;
 
 /* functions */
@@ -329,6 +334,8 @@
 #define ipoib_warn(priv, format, arg...)		\
 	ipoib_printk(KERN_WARNING, priv, format , ## arg)
 
+extern int ipoib_sendq_size;
+extern int ipoib_recvq_size;
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 extern int ipoib_debug_level;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 685258e..5dde380 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -213,7 +213,7 @@
 		   gid_buf, path.pathrec.dlid ? "yes" : "no");
 
 	if (path.pathrec.dlid) {
-		rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
+		rate = ib_rate_to_mult(path.pathrec.rate) * 25;
 
 		seq_printf(file,
 			   "  DLID:     0x%04x\n"
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index ed65202..a54da42 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -161,7 +161,7 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	int i;
 
-	for (i = 0; i < IPOIB_RX_RING_SIZE; ++i) {
+	for (i = 0; i < ipoib_recvq_size; ++i) {
 		if (ipoib_alloc_rx_skb(dev, i)) {
 			ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
 			return -ENOMEM;
@@ -187,7 +187,7 @@
 	if (wr_id & IPOIB_OP_RECV) {
 		wr_id &= ~IPOIB_OP_RECV;
 
-		if (wr_id < IPOIB_RX_RING_SIZE) {
+		if (wr_id < ipoib_recvq_size) {
 			struct sk_buff *skb  = priv->rx_ring[wr_id].skb;
 			dma_addr_t      addr = priv->rx_ring[wr_id].mapping;
 
@@ -252,9 +252,9 @@
 		struct ipoib_tx_buf *tx_req;
 		unsigned long flags;
 
-		if (wr_id >= IPOIB_TX_RING_SIZE) {
+		if (wr_id >= ipoib_sendq_size) {
 			ipoib_warn(priv, "completion event with wrid %d (> %d)\n",
-				   wr_id, IPOIB_TX_RING_SIZE);
+				   wr_id, ipoib_sendq_size);
 			return;
 		}
 
@@ -275,7 +275,7 @@
 		spin_lock_irqsave(&priv->tx_lock, flags);
 		++priv->tx_tail;
 		if (netif_queue_stopped(dev) &&
-		    priv->tx_head - priv->tx_tail <= IPOIB_TX_RING_SIZE / 2)
+		    priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
 			netif_wake_queue(dev);
 		spin_unlock_irqrestore(&priv->tx_lock, flags);
 
@@ -344,13 +344,13 @@
 	 * means we have to make sure everything is properly recorded and
 	 * our state is consistent before we call post_send().
 	 */
-	tx_req = &priv->tx_ring[priv->tx_head & (IPOIB_TX_RING_SIZE - 1)];
+	tx_req = &priv->tx_ring[priv->tx_head & (ipoib_sendq_size - 1)];
 	tx_req->skb = skb;
 	addr = dma_map_single(priv->ca->dma_device, skb->data, skb->len,
 			      DMA_TO_DEVICE);
 	pci_unmap_addr_set(tx_req, mapping, addr);
 
-	if (unlikely(post_send(priv, priv->tx_head & (IPOIB_TX_RING_SIZE - 1),
+	if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
 			       address->ah, qpn, addr, skb->len))) {
 		ipoib_warn(priv, "post_send failed\n");
 		++priv->stats.tx_errors;
@@ -363,7 +363,7 @@
 		address->last_send = priv->tx_head;
 		++priv->tx_head;
 
-		if (priv->tx_head - priv->tx_tail == IPOIB_TX_RING_SIZE) {
+		if (priv->tx_head - priv->tx_tail == ipoib_sendq_size) {
 			ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
 			netif_stop_queue(dev);
 		}
@@ -488,7 +488,7 @@
 	int pending = 0;
 	int i;
 
-	for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+	for (i = 0; i < ipoib_recvq_size; ++i)
 		if (priv->rx_ring[i].skb)
 			++pending;
 
@@ -527,7 +527,7 @@
 			 */
 			while ((int) priv->tx_tail - (int) priv->tx_head < 0) {
 				tx_req = &priv->tx_ring[priv->tx_tail &
-							(IPOIB_TX_RING_SIZE - 1)];
+							(ipoib_sendq_size - 1)];
 				dma_unmap_single(priv->ca->dma_device,
 						 pci_unmap_addr(tx_req, mapping),
 						 tx_req->skb->len,
@@ -536,7 +536,7 @@
 				++priv->tx_tail;
 			}
 
-			for (i = 0; i < IPOIB_RX_RING_SIZE; ++i)
+			for (i = 0; i < ipoib_recvq_size; ++i)
 				if (priv->rx_ring[i].skb) {
 					dma_unmap_single(priv->ca->dma_device,
 							 pci_unmap_addr(&priv->rx_ring[i],
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 9b0bd7c..cb078a7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/kernel.h>
 
 #include <linux/if_arp.h>	/* For ARPHRD_xxx */
 
@@ -53,6 +54,14 @@
 MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
+int ipoib_sendq_size __read_mostly = IPOIB_TX_RING_SIZE;
+int ipoib_recvq_size __read_mostly = IPOIB_RX_RING_SIZE;
+
+module_param_named(send_queue_size, ipoib_sendq_size, int, 0444);
+MODULE_PARM_DESC(send_queue_size, "Number of descriptors in send queue");
+module_param_named(recv_queue_size, ipoib_recvq_size, int, 0444);
+MODULE_PARM_DESC(recv_queue_size, "Number of descriptors in receive queue");
+
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
 int ipoib_debug_level;
 
@@ -252,8 +261,8 @@
 		 */
 		if (neigh->ah)
 			ipoib_put_ah(neigh->ah);
-		*to_ipoib_neigh(neigh->neighbour) = NULL;
-		kfree(neigh);
+
+		ipoib_neigh_free(neigh);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -327,9 +336,8 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_path *path, *tp;
 	LIST_HEAD(remove_list);
-	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irq(&priv->lock);
 
 	list_splice(&priv->path_list, &remove_list);
 	INIT_LIST_HEAD(&priv->path_list);
@@ -337,14 +345,15 @@
 	list_for_each_entry(path, &remove_list, list)
 		rb_erase(&path->rb_node, &priv->path_tree);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	list_for_each_entry_safe(path, tp, &remove_list, list) {
 		if (path->query)
 			ib_sa_cancel_query(path->query_id, path->query);
+		spin_unlock_irq(&priv->lock);
 		wait_for_completion(&path->done);
 		path_free(dev, path);
+		spin_lock_irq(&priv->lock);
 	}
+	spin_unlock_irq(&priv->lock);
 }
 
 static void path_rec_completion(int status,
@@ -373,16 +382,9 @@
 		struct ib_ah_attr av = {
 			.dlid 	       = be16_to_cpu(pathrec->dlid),
 			.sl 	       = pathrec->sl,
-			.port_num      = priv->port
+			.port_num      = priv->port,
+			.static_rate   = pathrec->rate
 		};
-		int path_rate = ib_sa_rate_enum_to_int(pathrec->rate);
-
-		if (path_rate > 0 && priv->local_rate > path_rate)
-			av.static_rate = (priv->local_rate - 1) / path_rate;
-
-		ipoib_dbg(priv, "static_rate %d for local port %dX, path %dX\n",
-			  av.static_rate, priv->local_rate,
-			  ib_sa_rate_enum_to_int(pathrec->rate));
 
 		ah = ipoib_create_ah(dev, priv->pd, &av);
 	}
@@ -481,7 +483,7 @@
 	struct ipoib_path *path;
 	struct ipoib_neigh *neigh;
 
-	neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+	neigh = ipoib_neigh_alloc(skb->dst->neighbour);
 	if (!neigh) {
 		++priv->stats.tx_dropped;
 		dev_kfree_skb_any(skb);
@@ -489,8 +491,6 @@
 	}
 
 	skb_queue_head_init(&neigh->queue);
-	neigh->neighbour = skb->dst->neighbour;
-	*to_ipoib_neigh(skb->dst->neighbour) = neigh;
 
 	/*
 	 * We can only be called from ipoib_start_xmit, so we're
@@ -503,7 +503,7 @@
 		path = path_rec_create(dev,
 				       (union ib_gid *) (skb->dst->neighbour->ha + 4));
 		if (!path)
-			goto err;
+			goto err_path;
 
 		__path_add(dev, path);
 	}
@@ -521,17 +521,17 @@
 		__skb_queue_tail(&neigh->queue, skb);
 
 		if (!path->query && path_rec_start(dev, path))
-			goto err;
+			goto err_list;
 	}
 
 	spin_unlock(&priv->lock);
 	return;
 
-err:
-	*to_ipoib_neigh(skb->dst->neighbour) = NULL;
+err_list:
 	list_del(&neigh->list);
-	kfree(neigh);
 
+err_path:
+	ipoib_neigh_free(neigh);
 	++priv->stats.tx_dropped;
 	dev_kfree_skb_any(skb);
 
@@ -763,8 +763,7 @@
 		if (neigh->ah)
 			ah = neigh->ah;
 		list_del(&neigh->list);
-		*to_ipoib_neigh(n) = NULL;
-		kfree(neigh);
+		ipoib_neigh_free(neigh);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -773,6 +772,26 @@
 		ipoib_put_ah(ah);
 }
 
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+{
+	struct ipoib_neigh *neigh;
+
+	neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+	if (!neigh)
+		return NULL;
+
+	neigh->neighbour = neighbour;
+	*to_ipoib_neigh(neighbour) = neigh;
+
+	return neigh;
+}
+
+void ipoib_neigh_free(struct ipoib_neigh *neigh)
+{
+	*to_ipoib_neigh(neigh->neighbour) = NULL;
+	kfree(neigh);
+}
+
 static int ipoib_neigh_setup_dev(struct net_device *dev, struct neigh_parms *parms)
 {
 	parms->neigh_destructor = ipoib_neigh_destructor;
@@ -785,20 +804,19 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
 	/* Allocate RX/TX "rings" to hold queued skbs */
-
-	priv->rx_ring =	kzalloc(IPOIB_RX_RING_SIZE * sizeof (struct ipoib_rx_buf),
+	priv->rx_ring =	kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
 				GFP_KERNEL);
 	if (!priv->rx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
-		       ca->name, IPOIB_RX_RING_SIZE);
+		       ca->name, ipoib_recvq_size);
 		goto out;
 	}
 
-	priv->tx_ring = kzalloc(IPOIB_TX_RING_SIZE * sizeof (struct ipoib_tx_buf),
+	priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring,
 				GFP_KERNEL);
 	if (!priv->tx_ring) {
 		printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
-		       ca->name, IPOIB_TX_RING_SIZE);
+		       ca->name, ipoib_sendq_size);
 		goto out_rx_ring_cleanup;
 	}
 
@@ -866,7 +884,7 @@
 	dev->hard_header_len 	 = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
 	dev->addr_len 		 = INFINIBAND_ALEN;
 	dev->type 		 = ARPHRD_INFINIBAND;
-	dev->tx_queue_len 	 = IPOIB_TX_RING_SIZE * 2;
+	dev->tx_queue_len 	 = ipoib_sendq_size * 2;
 	dev->features            = NETIF_F_VLAN_CHALLENGED | NETIF_F_LLTX;
 
 	/* MTU will be reset when mcast join happens */
@@ -1118,6 +1136,14 @@
 {
 	int ret;
 
+	ipoib_recvq_size = roundup_pow_of_two(ipoib_recvq_size);
+	ipoib_recvq_size = min(ipoib_recvq_size, IPOIB_MAX_QUEUE_SIZE);
+	ipoib_recvq_size = max(ipoib_recvq_size, IPOIB_MIN_QUEUE_SIZE);
+
+	ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
+	ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
+	ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
+
 	ret = ipoib_register_debugfs();
 	if (ret)
 		return ret;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 93c462e..1dae4b2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -114,8 +114,7 @@
 		 */
 		if (neigh->ah)
 			ipoib_put_ah(neigh->ah);
-		*to_ipoib_neigh(neigh->neighbour) = NULL;
-		kfree(neigh);
+		ipoib_neigh_free(neigh);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -251,6 +250,7 @@
 			.port_num      = priv->port,
 			.sl	       = mcast->mcmember.sl,
 			.ah_flags      = IB_AH_GRH,
+			.static_rate   = mcast->mcmember.rate,
 			.grh	       = {
 				.flow_label    = be32_to_cpu(mcast->mcmember.flow_label),
 				.hop_limit     = mcast->mcmember.hop_limit,
@@ -258,17 +258,8 @@
 				.traffic_class = mcast->mcmember.traffic_class
 			}
 		};
-		int path_rate = ib_sa_rate_enum_to_int(mcast->mcmember.rate);
-
 		av.grh.dgid = mcast->mcmember.mgid;
 
-		if (path_rate > 0 && priv->local_rate > path_rate)
-			av.static_rate = (priv->local_rate - 1) / path_rate;
-
-		ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n",
-				av.static_rate, priv->local_rate,
-				ib_sa_rate_enum_to_int(mcast->mcmember.rate));
-
 		ah = ipoib_create_ah(dev, priv->pd, &av);
 		if (!ah) {
 			ipoib_warn(priv, "ib_address_create failed\n");
@@ -618,6 +609,22 @@
 	return 0;
 }
 
+static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
+				struct ipoib_mcast *mcast)
+{
+	spin_lock_irq(&priv->lock);
+	if (mcast && mcast->query) {
+		ib_sa_cancel_query(mcast->query_id, mcast->query);
+		mcast->query = NULL;
+		spin_unlock_irq(&priv->lock);
+		ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
+				IPOIB_GID_ARG(mcast->mcmember.mgid));
+		wait_for_completion(&mcast->done);
+	}
+	else
+		spin_unlock_irq(&priv->lock);
+}
+
 int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -637,28 +644,10 @@
 	if (flush)
 		flush_workqueue(ipoib_workqueue);
 
-	spin_lock_irq(&priv->lock);
-	if (priv->broadcast && priv->broadcast->query) {
-		ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
-		priv->broadcast->query = NULL;
-		spin_unlock_irq(&priv->lock);
-		ipoib_dbg_mcast(priv, "waiting for bcast\n");
-		wait_for_completion(&priv->broadcast->done);
-	} else
-		spin_unlock_irq(&priv->lock);
+	wait_for_mcast_join(priv, priv->broadcast);
 
-	list_for_each_entry(mcast, &priv->multicast_list, list) {
-		spin_lock_irq(&priv->lock);
-		if (mcast->query) {
-			ib_sa_cancel_query(mcast->query_id, mcast->query);
-			mcast->query = NULL;
-			spin_unlock_irq(&priv->lock);
-			ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
-					IPOIB_GID_ARG(mcast->mcmember.mgid));
-			wait_for_completion(&mcast->done);
-		} else
-			spin_unlock_irq(&priv->lock);
-	}
+	list_for_each_entry(mcast, &priv->multicast_list, list)
+		wait_for_mcast_join(priv, mcast);
 
 	return 0;
 }
@@ -772,13 +761,11 @@
 		if (skb->dst            &&
 		    skb->dst->neighbour &&
 		    !*to_ipoib_neigh(skb->dst->neighbour)) {
-			struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC);
+			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
 
 			if (neigh) {
 				kref_get(&mcast->ah->ref);
 				neigh->ah  	= mcast->ah;
-				neigh->neighbour = skb->dst->neighbour;
-				*to_ipoib_neigh(skb->dst->neighbour) = neigh;
 				list_add_tail(&neigh->list, &mcast->neigh_list);
 			}
 		}
@@ -913,6 +900,7 @@
 
 	/* We have to cancel outside of the spinlock */
 	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+		wait_for_mcast_join(priv, mcast);
 		ipoib_mcast_leave(mcast->dev, mcast);
 		ipoib_mcast_free(mcast);
 	}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5f03880..1d49d16 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -159,8 +159,8 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ib_qp_init_attr init_attr = {
 		.cap = {
-			.max_send_wr  = IPOIB_TX_RING_SIZE,
-			.max_recv_wr  = IPOIB_RX_RING_SIZE,
+			.max_send_wr  = ipoib_sendq_size,
+			.max_recv_wr  = ipoib_recvq_size,
 			.max_send_sge = 1,
 			.max_recv_sge = 1
 		},
@@ -175,7 +175,7 @@
 	}
 
 	priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev,
-				IPOIB_TX_RING_SIZE + IPOIB_RX_RING_SIZE + 1);
+				ipoib_sendq_size + ipoib_recvq_size + 1);
 	if (IS_ERR(priv->cq)) {
 		printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
 		goto out_free_pd;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index fd8a95a..5bb5574 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -617,6 +617,14 @@
 		     scmnd->sc_data_direction);
 }
 
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req,
+			   int index)
+{
+	list_del(&req->list);
+	req->next = target->req_head;
+	target->req_head = index;
+}
+
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
 	struct srp_request *req;
@@ -664,9 +672,7 @@
 			scmnd->host_scribble = (void *) -1L;
 			scmnd->scsi_done(scmnd);
 
-			list_del(&req->list);
-			req->next = target->req_head;
-			target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+			srp_remove_req(target, req, rsp->tag & ~SRP_TAG_TSK_MGMT);
 		} else
 			req->cmd_done = 1;
 	}
@@ -1188,12 +1194,10 @@
 	spin_lock_irq(target->scsi_host->host_lock);
 
 	if (req->cmd_done) {
-		list_del(&req->list);
-		req->next = target->req_head;
-		target->req_head = req_index;
-
+		srp_remove_req(target, req, req_index);
 		scmnd->scsi_done(scmnd);
 	} else if (!req->tsk_status) {
+		srp_remove_req(target, req, req_index);
 		scmnd->result = DID_ABORT << 16;
 		ret = SUCCESS;
 	}
@@ -1434,6 +1438,7 @@
 			p = match_strdup(args);
 			if (strlen(p) != 32) {
 				printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);
+				kfree(p);
 				goto out;
 			}
 
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 1dca3cf..2e4abdc 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -350,11 +350,11 @@
 	return 0;
  bail2:
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
  bail1:
 	input_free_device(kbd->dev);
  bail0:
 	kfree(kbd);
-	serio_set_drvdata(serio, NULL);
 	return -EIO;
 }
 
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 53c4fb6..5b203fe 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -3,8 +3,8 @@
 
 config ISDN_DRV_GIGASET
 	tristate "Siemens Gigaset support (isdn)"
-	depends on ISDN_I4L && m
-#	depends on ISDN_I4L && MODULES
+	depends on ISDN_I4L
+	select CRC_CCITT
 	help
 	  Say m here if you have a Gigaset or Sinus isdn device.
 
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 171f8b7..ce3cd77 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
  *                       Hansjoerg Lipp <hjlipp@web.de>,
- *                       Stefan Eilers <Eilers.Stefan@epost.de>.
+ *                       Stefan Eilers.
  *
  * =====================================================================
  *	This program is free software; you can redistribute it and/or
@@ -11,10 +11,6 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -45,7 +41,7 @@
  *	number of processed bytes
  */
 static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
-                           struct inbuf_t *inbuf)
+			   struct inbuf_t *inbuf)
 {
 	struct cardstate *cs = inbuf->cs;
 	unsigned cbytes      = cs->cbytes;
@@ -55,10 +51,11 @@
 	for (;;) {
 		cs->respdata[cbytes] = c;
 		if (c == 10 || c == 13) {
-			dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
-			    __func__, cbytes);
+			gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+				__func__, cbytes);
 			cs->cbytes = cbytes;
-			gigaset_handle_modem_response(cs); /* can change cs->dle */
+			gigaset_handle_modem_response(cs); /* can change
+							      cs->dle */
 			cbytes = 0;
 
 			if (cs->dle &&
@@ -71,7 +68,7 @@
 			if (cbytes < MAX_RESP_SIZE - 1)
 				cbytes++;
 			else
-				warn("response too large");
+				dev_warn(cs->dev, "response too large\n");
 		}
 
 		if (!numbytes)
@@ -96,11 +93,12 @@
  *	number of processed bytes
  */
 static inline int lock_loop(unsigned char *src, int numbytes,
-                            struct inbuf_t *inbuf)
+			    struct inbuf_t *inbuf)
 {
 	struct cardstate *cs = inbuf->cs;
 
-	gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0);
+	gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
+			   numbytes, src);
 	gigaset_if_receive(cs, src, numbytes);
 
 	return numbytes;
@@ -115,24 +113,18 @@
  *	numbytes (all bytes processed) on error --FIXME
  */
 static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
-                            struct inbuf_t *inbuf)
+			    struct inbuf_t *inbuf)
 {
 	struct cardstate *cs = inbuf->cs;
 	struct bc_state *bcs = inbuf->bcs;
-	int inputstate;
-	__u16 fcs;
-	struct sk_buff *skb;
+	int inputstate = bcs->inputstate;
+	__u16 fcs = bcs->fcs;
+	struct sk_buff *skb = bcs->skb;
 	unsigned char error;
 	struct sk_buff *compskb;
 	int startbytes = numbytes;
 	int l;
 
-	IFNULLRETVAL(bcs, numbytes);
-	inputstate = bcs->inputstate;
-	fcs = bcs->fcs;
-	skb = bcs->skb;
-	IFNULLRETVAL(skb, numbytes);
-
 	if (unlikely(inputstate & INS_byte_stuff)) {
 		inputstate &= ~INS_byte_stuff;
 		goto byte_stuff;
@@ -156,39 +148,37 @@
 			c ^= PPP_TRANS;
 #ifdef CONFIG_GIGASET_DEBUG
 			if (unlikely(!muststuff(c)))
-				dbg(DEBUG_HDLC,
-				    "byte stuffed: 0x%02x", c);
+				gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
 #endif
 		} else if (unlikely(c == PPP_FLAG)) {
 			if (unlikely(inputstate & INS_skip_frame)) {
 				if (!(inputstate & INS_have_data)) { /* 7E 7E */
-					//dbg(DEBUG_HDLC, "(7e)7e------------------------");
 #ifdef CONFIG_GIGASET_DEBUG
 					++bcs->emptycount;
 #endif
 				} else
-					dbg(DEBUG_HDLC,
+					gig_dbg(DEBUG_HDLC,
 					    "7e----------------------------");
 
 				/* end of frame */
 				error = 1;
 				gigaset_rcv_error(NULL, cs, bcs);
 			} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
-				//dbg(DEBUG_HDLC, "(7e)7e------------------------");
 #ifdef CONFIG_GIGASET_DEBUG
 				++bcs->emptycount;
 #endif
 				break;
 			} else {
-				dbg(DEBUG_HDLC,
-				    "7e----------------------------");
+				gig_dbg(DEBUG_HDLC,
+					"7e----------------------------");
 
 				/* end of frame */
 				error = 0;
 
 				if (unlikely(fcs != PPP_GOODFCS)) {
-					err("Packet checksum at %lu failed, "
-					    "packet is corrupted (%u bytes)!",
+					dev_err(cs->dev,
+					    "Packet checksum at %lu failed, "
+					    "packet is corrupted (%u bytes)!\n",
 					    bcs->rcvbytes, skb->len);
 					compskb = NULL;
 					gigaset_rcv_error(compskb, cs, bcs);
@@ -202,9 +192,11 @@
 						skb = NULL;
 						inputstate |= INS_skip_frame;
 						if (l == 1) {
-							err("invalid packet size (1)!");
+							dev_err(cs->dev,
+						  "invalid packet size (1)!\n");
 							error = 1;
-							gigaset_rcv_error(NULL, cs, bcs);
+							gigaset_rcv_error(NULL,
+								cs, bcs);
 						}
 					}
 					if (likely(!(error ||
@@ -227,7 +219,8 @@
 			} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
 				skb_reserve(skb, HW_HDR_LEN);
 			} else {
-				warn("could not allocate new skb");
+				dev_warn(cs->dev,
+					 "could not allocate new skb\n");
 				inputstate |= INS_skip_frame;
 			}
 
@@ -235,7 +228,7 @@
 #ifdef CONFIG_GIGASET_DEBUG
 		} else if (unlikely(muststuff(c))) {
 			/* Should not happen. Possible after ZDLE=1<CR><LF>. */
-			dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
+			gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
 #endif
 		}
 
@@ -243,8 +236,8 @@
 
 #ifdef CONFIG_GIGASET_DEBUG
 		if (unlikely(!(inputstate & INS_have_data))) {
-			dbg(DEBUG_HDLC,
-			    "7e (%d x) ================", bcs->emptycount);
+			gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
+				bcs->emptycount);
 			bcs->emptycount = 0;
 		}
 #endif
@@ -253,14 +246,13 @@
 
 		if (likely(!(inputstate & INS_skip_frame))) {
 			if (unlikely(skb->len == SBUFSIZE)) {
-				warn("received packet too long");
+				dev_warn(cs->dev, "received packet too long\n");
 				dev_kfree_skb_any(skb);
 				skb = NULL;
 				inputstate |= INS_skip_frame;
 				break;
 			}
-			*gigaset_skb_put_quick(skb, 1) = c;
-			/* *__skb_put (skb, 1) = c; */
+			*__skb_put(skb, 1) = c;
 			fcs = crc_ccitt_byte(fcs, c);
 		}
 
@@ -289,19 +281,14 @@
  *	numbytes (all bytes processed) on error --FIXME
  */
 static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
-                            struct inbuf_t *inbuf)
+			    struct inbuf_t *inbuf)
 {
 	struct cardstate *cs = inbuf->cs;
 	struct bc_state *bcs = inbuf->bcs;
-	int inputstate;
-	struct sk_buff *skb;
+	int inputstate = bcs->inputstate;
+	struct sk_buff *skb = bcs->skb;
 	int startbytes = numbytes;
 
-	IFNULLRETVAL(bcs, numbytes);
-	inputstate = bcs->inputstate;
-	skb = bcs->skb;
-	IFNULLRETVAL(skb, numbytes);
-
 	for (;;) {
 		/* add character */
 		inputstate |= INS_have_data;
@@ -309,13 +296,13 @@
 		if (likely(!(inputstate & INS_skip_frame))) {
 			if (unlikely(skb->len == SBUFSIZE)) {
 				//FIXME just pass skb up and allocate a new one
-				warn("received packet too long");
+				dev_warn(cs->dev, "received packet too long\n");
 				dev_kfree_skb_any(skb);
 				skb = NULL;
 				inputstate |= INS_skip_frame;
 				break;
 			}
-			*gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
+			*__skb_put(skb, 1) = gigaset_invtab[c];
 		}
 
 		if (unlikely(!numbytes))
@@ -343,7 +330,7 @@
 				  != NULL)) {
 			skb_reserve(skb, HW_HDR_LEN);
 		} else {
-			warn("could not allocate new skb");
+			dev_warn(cs->dev, "could not allocate new skb\n");
 			inputstate |= INS_skip_frame;
 		}
 	}
@@ -364,13 +351,13 @@
 
 	head = atomic_read(&inbuf->head);
 	tail = atomic_read(&inbuf->tail);
-	dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 
 	if (head != tail) {
 		cs = inbuf->cs;
 		src = inbuf->data + head;
 		numbytes = (head > tail ? RBUFSIZE : tail) - head;
-		dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+		gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
 
 		while (numbytes) {
 			if (atomic_read(&cs->mstate) == MS_LOCKED) {
@@ -392,8 +379,7 @@
 
 				if (!(inbuf->inputstate & INS_DLE_char)) {
 
-					/* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]?  */
-					/* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */
+					/* FIXME use function pointers?  */
 					if (inbuf->inputstate & INS_command)
 						procbytes = cmd_loop(c, src, numbytes, inbuf);
 					else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
@@ -403,13 +389,14 @@
 
 					src += procbytes;
 					numbytes -= procbytes;
-				} else {  /* DLE-char */
+				} else {  /* DLE char */
 					inbuf->inputstate &= ~INS_DLE_char;
 					switch (c) {
 					case 'X': /*begin of command*/
 #ifdef CONFIG_GIGASET_DEBUG
 						if (inbuf->inputstate & INS_command)
-							err("received <DLE> 'X' in command mode");
+							dev_err(cs->dev,
+					"received <DLE> 'X' in command mode\n");
 #endif
 						inbuf->inputstate |=
 							INS_command | INS_DLE_command;
@@ -417,7 +404,8 @@
 					case '.': /*end of command*/
 #ifdef CONFIG_GIGASET_DEBUG
 						if (!(inbuf->inputstate & INS_command))
-							err("received <DLE> '.' in hdlc mode");
+							dev_err(cs->dev,
+					"received <DLE> '.' in hdlc mode\n");
 #endif
 						inbuf->inputstate &= cs->dle ?
 							~(INS_DLE_command|INS_command)
@@ -425,7 +413,9 @@
 						break;
 					//case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
 					default:
-						err("received 0x10 0x%02x!", (int) c);
+						dev_err(cs->dev,
+						      "received 0x10 0x%02x!\n",
+							(int) c);
 						/* FIXME: reset driver?? */
 					}
 				}
@@ -444,7 +434,7 @@
 			}
 		}
 
-		dbg(DEBUG_INTR, "setting head to %u", head);
+		gig_dbg(DEBUG_INTR, "setting head to %u", head);
 		atomic_set(&inbuf->head, head);
 	}
 }
@@ -479,14 +469,13 @@
 			stuf_cnt++;
 		fcs = crc_ccitt_byte(fcs, *cp++);
 	}
-	fcs ^= 0xffff;                 /* complement */
+	fcs ^= 0xffff;			/* complement */
 
 	/* size of new buffer: original size + number of stuffing bytes
 	 * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
 	 */
 	hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
 	if (!hdlc_skb) {
-		err("unable to allocate memory for HDLC encoding!");
 		dev_kfree_skb(skb);
 		return NULL;
 	}
@@ -508,7 +497,7 @@
 	}
 
 	/* Finally add FCS (byte stuffed) and flag sequence */
-	c = (fcs & 0x00ff);      /* least significant byte first */
+	c = (fcs & 0x00ff);	/* least significant byte first */
 	if (muststuff(c)) {
 		*(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
 		c ^= PPP_TRANS;
@@ -546,7 +535,6 @@
 	/* worst case: every byte must be stuffed */
 	iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
 	if (!iraw_skb) {
-		err("unable to allocate memory for HDLC encoding!");
 		dev_kfree_skb(skb);
 		return NULL;
 	}
@@ -577,21 +565,23 @@
  */
 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 {
-	unsigned len;
-
-	IFNULLRETVAL(bcs, -EFAULT);
-	IFNULLRETVAL(skb, -EFAULT);
-	len = skb->len;
+	unsigned len = skb->len;
+	unsigned long flags;
 
 	if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
 		skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
 	else
 		skb = iraw_encode(skb, HW_HDR_LEN, 0);
-	if (!skb)
+	if (!skb) {
+		err("unable to allocate memory for encoding!\n");
 		return -ENOMEM;
+	}
 
 	skb_queue_tail(&bcs->squeue, skb);
-	tasklet_schedule(&bcs->cs->write_tasklet);
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (bcs->cs->connected)
+		tasklet_schedule(&bcs->cs->write_tasklet);
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 
 	return len;	/* ok so far */
 }
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 31f0f07..eb41aba 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -3,9 +3,7 @@
  *
  * Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>,
- *                       Stefan Eilers <Eilers.Stefan@epost.de>.
- *
- * Based on usb-gigaset.c.
+ *                       Stefan Eilers.
  *
  * =====================================================================
  *	This program is free software; you can redistribute it and/or
@@ -13,10 +11,6 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -30,7 +24,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
 #define DRIVER_DESC "USB Driver for Gigaset 307x"
 
 
@@ -50,19 +44,20 @@
 #define GIGASET_DEVFSNAME  "gig/bas/"
 #define GIGASET_DEVNAME    "ttyGB"
 
-#define IF_WRITEBUF 256 //FIXME
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
 
 /* Values for the Gigaset 307x */
 #define USB_GIGA_VENDOR_ID      0x0681
-#define USB_GIGA_PRODUCT_ID     0x0001
-#define USB_4175_PRODUCT_ID     0x0002
+#define USB_3070_PRODUCT_ID     0x0001
+#define USB_3075_PRODUCT_ID     0x0002
 #define USB_SX303_PRODUCT_ID    0x0021
 #define USB_SX353_PRODUCT_ID    0x0022
 
 /* table of devices that work with this driver */
 static struct usb_device_id gigaset_table [] = {
-	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_GIGA_PRODUCT_ID) },
-	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_4175_PRODUCT_ID) },
+	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
+	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
 	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
 	{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) },
 	{ } /* Terminating entry */
@@ -70,9 +65,6 @@
 
 MODULE_DEVICE_TABLE(usb, gigaset_table);
 
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE	200
-
 /*======================= local function prototypes =============================*/
 
 /* This function is called if a new device is connected to the USB port. It
@@ -84,29 +76,33 @@
 /* Function will be called if the device is unplugged */
 static void gigaset_disconnect(struct usb_interface *interface);
 
+static void read_ctrl_callback(struct urb *, struct pt_regs *);
+static void stopurbs(struct bas_bc_state *);
+static int atwrite_submit(struct cardstate *, unsigned char *, int);
+static int start_cbsend(struct cardstate *);
 
 /*==============================================================================*/
 
 struct bas_cardstate {
-	struct usb_device       *udev;		/* USB device pointer */
-	struct usb_interface    *interface;	/* interface for this device */
+	struct usb_device	*udev;		/* USB device pointer */
+	struct usb_interface	*interface;	/* interface for this device */
 	unsigned char		minor;		/* starting minor number */
 
-	struct urb              *urb_ctrl;	/* control pipe default URB */
+	struct urb		*urb_ctrl;	/* control pipe default URB */
 	struct usb_ctrlrequest	dr_ctrl;
 	struct timer_list	timer_ctrl;	/* control request timeout */
 
 	struct timer_list	timer_atrdy;	/* AT command ready timeout */
-	struct urb              *urb_cmd_out;	/* for sending AT commands */
+	struct urb		*urb_cmd_out;	/* for sending AT commands */
 	struct usb_ctrlrequest	dr_cmd_out;
 	int			retry_cmd_out;
 
-	struct urb              *urb_cmd_in;	/* for receiving AT replies */
+	struct urb		*urb_cmd_in;	/* for receiving AT replies */
 	struct usb_ctrlrequest	dr_cmd_in;
 	struct timer_list	timer_cmd_in;	/* receive request timeout */
-	unsigned char           *rcvbuf;	/* AT reply receive buffer */
+	unsigned char		*rcvbuf;	/* AT reply receive buffer */
 
-	struct urb              *urb_int_in;	/* URB for interrupt pipe */
+	struct urb		*urb_int_in;	/* URB for interrupt pipe */
 	unsigned char		int_in_buf[3];
 
 	spinlock_t		lock;		/* locks all following */
@@ -118,12 +114,14 @@
 };
 
 /* status of direct USB connection to 307x base (bits in basstate) */
-#define BS_ATOPEN	0x001
-#define BS_B1OPEN	0x002
-#define BS_B2OPEN	0x004
-#define BS_ATREADY	0x008
-#define BS_INIT		0x010
-#define BS_ATTIMER	0x020
+#define BS_ATOPEN	0x001	/* AT channel open */
+#define BS_B1OPEN	0x002	/* B channel 1 open */
+#define BS_B2OPEN	0x004	/* B channel 2 open */
+#define BS_ATREADY	0x008	/* base ready for AT command */
+#define BS_INIT		0x010	/* base has signalled INIT_OK */
+#define BS_ATTIMER	0x020	/* waiting for HD_READY_SEND_ATDATA */
+#define BS_ATRDPEND	0x040	/* urb_cmd_in in use */
+#define BS_ATWRPEND	0x080	/* urb_cmd_out in use */
 
 
 static struct gigaset_driver *driver = NULL;
@@ -137,6 +135,47 @@
 	.id_table =     gigaset_table,
 };
 
+/* get message text for usb_submit_urb return code
+ */
+static char *get_usb_rcmsg(int rc)
+{
+	static char unkmsg[28];
+
+	switch (rc) {
+	case 0:
+		return "success";
+	case -ENOMEM:
+		return "out of memory";
+	case -ENODEV:
+		return "device not present";
+	case -ENOENT:
+		return "endpoint not present";
+	case -ENXIO:
+		return "URB type not supported";
+	case -EINVAL:
+		return "invalid argument";
+	case -EAGAIN:
+		return "start frame too early or too much scheduled";
+	case -EFBIG:
+		return "too many isochronous frames requested";
+	case -EPIPE:
+		return "endpoint stalled";
+	case -EMSGSIZE:
+		return "invalid packet size";
+	case -ENOSPC:
+		return "would overcommit USB bandwidth";
+	case -ESHUTDOWN:
+		return "device shut down";
+	case -EPERM:
+		return "reject flag set";
+	case -EHOSTUNREACH:
+		return "device suspended";
+	default:
+		snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc);
+		return unkmsg;
+	}
+}
+
 /* get message text for USB status code
  */
 static char *get_usb_statmsg(int status)
@@ -147,43 +186,37 @@
 	case 0:
 		return "success";
 	case -ENOENT:
-		return "canceled";
-	case -ECONNRESET:
-		return "canceled (async)";
+		return "unlinked (sync)";
 	case -EINPROGRESS:
 		return "pending";
 	case -EPROTO:
-		return "bit stuffing or unknown USB error";
+		return "bit stuffing error, timeout, or unknown USB error";
 	case -EILSEQ:
-		return "Illegal byte sequence (CRC mismatch)";
-	case -EPIPE:
-		return "babble detect or endpoint stalled";
-	case -ENOSR:
-		return "buffer error";
+		return "CRC mismatch, timeout, or unknown USB error";
 	case -ETIMEDOUT:
 		return "timed out";
-	case -ENODEV:
-		return "device not present";
+	case -EPIPE:
+		return "endpoint stalled";
+	case -ECOMM:
+		return "IN buffer overrun";
+	case -ENOSR:
+		return "OUT buffer underrun";
+	case -EOVERFLOW:
+		return "too much data";
 	case -EREMOTEIO:
 		return "short packet detected";
+	case -ENODEV:
+		return "device removed";
 	case -EXDEV:
 		return "partial isochronous transfer";
 	case -EINVAL:
 		return "invalid argument";
-	case -ENXIO:
-		return "URB already queued";
-	case -EAGAIN:
-		return "isochronous start frame too early or too much scheduled";
-	case -EFBIG:
-		return "too many isochronous frames requested";
-	case -EMSGSIZE:
-		return "endpoint message size zero";
+	case -ECONNRESET:
+		return "unlinked (async)";
 	case -ESHUTDOWN:
-		return "endpoint shutdown";
-	case -EBUSY:
-		return "another request pending";
+		return "device shut down";
 	default:
-		snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", status);
+		snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status);
 		return unkmsg;
 	}
 }
@@ -208,53 +241,54 @@
  * write content of URB to syslog for debugging
  */
 static inline void dump_urb(enum debuglevel level, const char *tag,
-                            struct urb *urb)
+			    struct urb *urb)
 {
 #ifdef CONFIG_GIGASET_DEBUG
 	int i;
-	IFNULLRET(tag);
-	dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
+	gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb);
 	if (urb) {
-		dbg(level,
-		    "  dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
-		    "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
-		    (unsigned long) urb->dev,
-		    usb_pipetype_str(urb->pipe),
-		    usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
-		    usb_pipein(urb->pipe) ? "in" : "out",
-		    urb->status, (unsigned long) urb->hcpriv,
-		    urb->transfer_flags);
-		dbg(level,
-		    "  transfer_buffer=0x%08lx[%d], actual_length=%d, "
-		    "bandwidth=%d, setup_packet=0x%08lx,",
-		    (unsigned long) urb->transfer_buffer,
-		    urb->transfer_buffer_length, urb->actual_length,
-		    urb->bandwidth, (unsigned long) urb->setup_packet);
-		dbg(level,
-		    "  start_frame=%d, number_of_packets=%d, interval=%d, "
-		    "error_count=%d,",
-		    urb->start_frame, urb->number_of_packets, urb->interval,
-		    urb->error_count);
-		dbg(level,
-		    "  context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={",
-		    (unsigned long) urb->context,
-		    (unsigned long) urb->complete);
+		gig_dbg(level,
+			"  dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
+			"status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
+			(unsigned long) urb->dev,
+			usb_pipetype_str(urb->pipe),
+			usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
+			usb_pipein(urb->pipe) ? "in" : "out",
+			urb->status, (unsigned long) urb->hcpriv,
+			urb->transfer_flags);
+		gig_dbg(level,
+			"  transfer_buffer=0x%08lx[%d], actual_length=%d, "
+			"bandwidth=%d, setup_packet=0x%08lx,",
+			(unsigned long) urb->transfer_buffer,
+			urb->transfer_buffer_length, urb->actual_length,
+			urb->bandwidth, (unsigned long) urb->setup_packet);
+		gig_dbg(level,
+			"  start_frame=%d, number_of_packets=%d, interval=%d, "
+			"error_count=%d,",
+			urb->start_frame, urb->number_of_packets, urb->interval,
+			urb->error_count);
+		gig_dbg(level,
+			"  context=0x%08lx, complete=0x%08lx, "
+			"iso_frame_desc[]={",
+			(unsigned long) urb->context,
+			(unsigned long) urb->complete);
 		for (i = 0; i < urb->number_of_packets; i++) {
-			struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i];
-			dbg(level,
-			    "    {offset=%u, length=%u, actual_length=%u, "
-			    "status=%u}",
-			    pifd->offset, pifd->length, pifd->actual_length,
-			    pifd->status);
+			struct usb_iso_packet_descriptor *pifd
+				= &urb->iso_frame_desc[i];
+			gig_dbg(level,
+				"    {offset=%u, length=%u, actual_length=%u, "
+				"status=%u}",
+				pifd->offset, pifd->length, pifd->actual_length,
+				pifd->status);
 		}
 	}
-	dbg(level, "}}");
+	gig_dbg(level, "}}");
 #endif
 }
 
 /* read/set modem control bits etc. (m10x only) */
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-                                  unsigned new_state)
+				  unsigned new_state)
 {
 	return -EINVAL;
 }
@@ -280,43 +314,39 @@
 {
 	struct cardstate *cs = bcs->cs;
 
-	dbg(DEBUG_ANY,
-	    "%s: scheduling HUP for channel %d", __func__, bcs->channel);
+	gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d",
+		__func__, bcs->channel);
 
-	if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
-		//FIXME what should we do?
-		return;
-	}
+	if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL))
+		dev_err(cs->dev, "event queue full\n");
 
 	gigaset_schedule_event(cs);
 }
 
 /* error_reset
  * reset Gigaset device because of an unrecoverable error
- * This function may be called from any context and takes care of scheduling
- * the necessary actions for execution outside of interrupt context.
+ * This function may be called from any context, and should take care of
+ * scheduling the necessary actions for execution outside of interrupt context.
+ * Right now, it just generates a kernel message calling for help.
  * argument:
  *	controller state structure
  */
 static inline void error_reset(struct cardstate *cs)
 {
 	//FIXME try to recover without bothering the user
-	err("unrecoverable error - please disconnect the Gigaset base to reset");
+	dev_err(cs->dev,
+	    "unrecoverable error - please disconnect Gigaset base to reset\n");
 }
 
 /* check_pending
  * check for completion of pending control request
  * parameter:
- *	urb	USB request block of completed request
- *		urb->context = hardware specific controller state structure
+ *	ucs	hardware specific controller state structure
  */
 static void check_pending(struct bas_cardstate *ucs)
 {
 	unsigned long flags;
 
-	IFNULLRET(ucs);
-	IFNULLRET(cardstate);
-
 	spin_lock_irqsave(&ucs->lock, flags);
 	switch (ucs->pending) {
 	case 0:
@@ -336,8 +366,6 @@
 	case HD_CLOSE_ATCHANNEL:
 		if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
 			ucs->pending = 0;
-		//wake_up_interruptible(cs->initwait);
-		//FIXME need own wait queue?
 		break;
 	case HD_CLOSE_B1CHANNEL:
 		if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
@@ -354,7 +382,9 @@
 	 * are handled separately and should never end up here
 	 */
 	default:
-		warn("unknown pending request 0x%02x cleared", ucs->pending);
+		dev_warn(&ucs->interface->dev,
+			 "unknown pending request 0x%02x cleared\n",
+			 ucs->pending);
 		ucs->pending = 0;
 	}
 
@@ -372,58 +402,53 @@
 static void cmd_in_timeout(unsigned long data)
 {
 	struct cardstate *cs = (struct cardstate *) data;
-	struct bas_cardstate *ucs;
-	unsigned long flags;
+	struct bas_cardstate *ucs = cs->hw.bas;
 
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_USBREQ, "%s: disconnected", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
-		return;
-	}
 	if (!ucs->rcvbuf_size) {
-		dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
+		gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
 		return;
 	}
-	spin_unlock_irqrestore(&cs->lock, flags);
 
-	err("timeout reading AT response");
+	dev_err(cs->dev, "timeout reading AT response\n");
 	error_reset(cs);	//FIXME retry?
 }
 
+/* set/clear bits in base connection state, return previous state
+ */
+inline static int update_basstate(struct bas_cardstate *ucs,
+				  int set, int clear)
+{
+	unsigned long flags;
+	int state;
 
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs);
+	spin_lock_irqsave(&ucs->lock, flags);
+	state = atomic_read(&ucs->basstate);
+	atomic_set(&ucs->basstate, (state & ~clear) | set);
+	spin_unlock_irqrestore(&ucs->lock, flags);
+	return state;
+}
 
 /* atread_submit
- * submit an HD_READ_ATMESSAGE command URB
+ * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout
  * parameters:
  *	cs	controller state structure
  *	timeout	timeout in 1/10 sec., 0: none
  * return value:
  *	0 on success
- *	-EINVAL if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
 static int atread_submit(struct cardstate *cs, int timeout)
 {
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	int ret;
 
-	IFNULLRETVAL(cs, -EINVAL);
-	ucs = cs->hw.bas;
-	IFNULLRETVAL(ucs, -EINVAL);
-	IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL);
+	gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
+		ucs->rcvbuf_size);
 
-	dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size);
-
-	if (ucs->urb_cmd_in->status == -EINPROGRESS) {
-		err("could not submit HD_READ_ATMESSAGE: URB busy");
+	if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
+		dev_err(cs->dev,
+			"could not submit HD_READ_ATMESSAGE: URB busy\n");
 		return -EBUSY;
 	}
 
@@ -433,19 +458,20 @@
 	ucs->dr_cmd_in.wIndex = 0;
 	ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
 	usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
-	                     usb_rcvctrlpipe(ucs->udev, 0),
-	                     (unsigned char*) & ucs->dr_cmd_in,
-	                     ucs->rcvbuf, ucs->rcvbuf_size,
-	                     read_ctrl_callback, cs->inbuf);
+			     usb_rcvctrlpipe(ucs->udev, 0),
+			     (unsigned char*) & ucs->dr_cmd_in,
+			     ucs->rcvbuf, ucs->rcvbuf_size,
+			     read_ctrl_callback, cs->inbuf);
 
 	if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
-		err("could not submit HD_READ_ATMESSAGE: %s",
-		    get_usb_statmsg(ret));
+		update_basstate(ucs, 0, BS_ATRDPEND);
+		dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
+			get_usb_statmsg(ret));
 		return ret;
 	}
 
 	if (timeout > 0) {
-		dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+		gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
 		ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10;
 		ucs->timer_cmd_in.data = (unsigned long) cs;
 		ucs->timer_cmd_in.function = cmd_in_timeout;
@@ -454,26 +480,6 @@
 	return 0;
 }
 
-static void stopurbs(struct bas_bc_state *);
-static int start_cbsend(struct cardstate *);
-
-/* set/clear bits in base connection state
- */
-inline static void update_basstate(struct bas_cardstate *ucs,
-				   int set, int clear)
-{
-	unsigned long flags;
-	int state;
-
-	spin_lock_irqsave(&ucs->lock, flags);
-	state = atomic_read(&ucs->basstate);
-	state &= ~clear;
-	state |= set;
-	atomic_set(&ucs->basstate, state);
-	spin_unlock_irqrestore(&ucs->lock, flags);
-}
-
-
 /* read_int_callback
  * USB completion handler for interrupt pipe input
  * called by the USB subsystem in interrupt context
@@ -483,48 +489,49 @@
  */
 static void read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
-	struct cardstate *cs;
-	struct bas_cardstate *ucs;
+	struct cardstate *cs = urb->context;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	struct bc_state *bcs;
 	unsigned long flags;
-	int status;
+	int rc;
 	unsigned l;
 	int channel;
 
-	IFNULLRET(urb);
-	cs = (struct cardstate *) urb->context;
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
-
-	if (unlikely(!atomic_read(&cs->connected))) {
-		warn("%s: disconnected", __func__);
-		return;
-	}
-
 	switch (urb->status) {
 	case 0:			/* success */
 		break;
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
 		/* ignore silently */
-		dbg(DEBUG_USBREQ,
-		    "%s: %s", __func__, get_usb_statmsg(urb->status));
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
+		return;
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
+		//FIXME use this as disconnect indicator?
+		gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
 		return;
 	default:		/* severe trouble */
-		warn("interrupt read: %s", get_usb_statmsg(urb->status));
+		dev_warn(cs->dev, "interrupt read: %s\n",
+			 get_usb_statmsg(urb->status));
 		//FIXME corrective action? resubmission always ok?
 		goto resubmit;
 	}
 
+	/* drop incomplete packets even if the missing bytes wouldn't matter */
+	if (unlikely(urb->actual_length < 3)) {
+		dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n",
+			 urb->actual_length);
+		goto resubmit;
+	}
+
 	l = (unsigned) ucs->int_in_buf[1] +
 	    (((unsigned) ucs->int_in_buf[2]) << 8);
 
-	dbg(DEBUG_USBREQ,
-	    "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length,
-	    (int)ucs->int_in_buf[0], l,
-	    (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
+	gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])",
+		urb->actual_length, (int)ucs->int_in_buf[0], l,
+		(int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]);
 
 	channel = 0;
 
@@ -570,62 +577,68 @@
 	case HD_B1_FLOW_CONTROL:
 		bcs = cs->bcs + channel;
 		atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES,
-		           &bcs->hw.bas->corrbytes);
-		dbg(DEBUG_ISO,
-		    "Flow control (channel %d, sub %d): 0x%02x => %d",
-		    channel, bcs->hw.bas->numsub, l,
-		    atomic_read(&bcs->hw.bas->corrbytes));
+			   &bcs->hw.bas->corrbytes);
+		gig_dbg(DEBUG_ISO,
+			"Flow control (channel %d, sub %d): 0x%02x => %d",
+			channel, bcs->hw.bas->numsub, l,
+			atomic_read(&bcs->hw.bas->corrbytes));
 		break;
 
 	case HD_RECEIVEATDATA_ACK:	/* AT response ready to be received */
 		if (!l) {
-			warn("HD_RECEIVEATDATA_ACK with length 0 ignored");
+			dev_warn(cs->dev,
+				"HD_RECEIVEATDATA_ACK with length 0 ignored\n");
 			break;
 		}
 		spin_lock_irqsave(&cs->lock, flags);
 		if (ucs->rcvbuf_size) {
-			spin_unlock_irqrestore(&cs->lock, flags);
-			err("receive AT data overrun, %d bytes lost", l);
-			error_reset(cs);	//FIXME reschedule
-			break;
+			/* throw away previous buffer - we have no queue */
+			dev_err(cs->dev,
+				"receive AT data overrun, %d bytes lost\n",
+				ucs->rcvbuf_size);
+			kfree(ucs->rcvbuf);
+			ucs->rcvbuf_size = 0;
 		}
 		if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
 			spin_unlock_irqrestore(&cs->lock, flags);
-			err("%s: out of memory, %d bytes lost", __func__, l);
-			error_reset(cs);	//FIXME reschedule
+			dev_err(cs->dev, "out of memory receiving AT data\n");
+			error_reset(cs);
 			break;
 		}
 		ucs->rcvbuf_size = l;
 		ucs->retry_cmd_in = 0;
-		if ((status = atread_submit(cs, BAS_TIMEOUT)) < 0) {
+		if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) {
 			kfree(ucs->rcvbuf);
 			ucs->rcvbuf = NULL;
 			ucs->rcvbuf_size = 0;
-			error_reset(cs);	//FIXME reschedule
+			if (rc != -ENODEV)
+				//FIXME corrective action?
+				error_reset(cs);
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
 		break;
 
 	case HD_RESET_INTERRUPT_PIPE_ACK:
-		dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
+		gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK");
 		break;
 
 	case HD_SUSPEND_END:
-		dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
+		gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END");
 		break;
 
 	default:
-		warn("unknown Gigaset signal 0x%02x (%u) ignored",
-		     (int) ucs->int_in_buf[0], l);
+		dev_warn(cs->dev,
+			 "unknown Gigaset signal 0x%02x (%u) ignored\n",
+			 (int) ucs->int_in_buf[0], l);
 	}
 
 	check_pending(ucs);
 
 resubmit:
-	status = usb_submit_urb(urb, SLAB_ATOMIC);
-	if (unlikely(status)) {
-		err("could not resubmit interrupt URB: %s",
-		    get_usb_statmsg(status));
+	rc = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (unlikely(rc != 0 && rc != -ENODEV)) {
+		dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+			get_usb_rcmsg(rc));
 		error_reset(cs);
 	}
 }
@@ -639,31 +652,17 @@
  */
 static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
 {
-	struct cardstate *cs;
-	struct bas_cardstate *ucs;
-	unsigned numbytes;
-	unsigned long flags;
-	struct inbuf_t *inbuf;
+	struct inbuf_t *inbuf = urb->context;
+	struct cardstate *cs = inbuf->cs;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	int have_data = 0;
+	unsigned numbytes;
+	int rc;
 
-	IFNULLRET(urb);
-	inbuf = (struct inbuf_t *) urb->context;
-	IFNULLRET(inbuf);
-	cs = inbuf->cs;
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
-
-	spin_lock_irqsave(&cs->lock, flags);
-	if (!atomic_read(&cs->connected)) {
-		warn("%s: disconnected", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
-		return;
-	}
+	update_basstate(ucs, 0, BS_ATRDPEND);
 
 	if (!ucs->rcvbuf_size) {
-		warn("%s: no receive in progress", __func__);
-		spin_unlock_irqrestore(&cs->lock, flags);
+		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
 		return;
 	}
 
@@ -673,12 +672,14 @@
 	case 0:				/* normal completion */
 		numbytes = urb->actual_length;
 		if (unlikely(numbytes == 0)) {
-			warn("control read: empty block received");
+			dev_warn(cs->dev,
+				 "control read: empty block received\n");
 			goto retry;
 		}
 		if (unlikely(numbytes != ucs->rcvbuf_size)) {
-			warn("control read: received %d chars, expected %d",
-			     numbytes, ucs->rcvbuf_size);
+			dev_warn(cs->dev,
+			       "control read: received %d chars, expected %d\n",
+				 numbytes, ucs->rcvbuf_size);
 			if (numbytes > ucs->rcvbuf_size)
 				numbytes = ucs->rcvbuf_size;
 		}
@@ -694,27 +695,32 @@
 		}
 		break;
 
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
 		/* no action necessary */
-		dbg(DEBUG_USBREQ,
-		    "%s: %s", __func__, get_usb_statmsg(urb->status));
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
 		break;
 
 	default:			/* severe trouble */
-		warn("control read: %s", get_usb_statmsg(urb->status));
+		dev_warn(cs->dev, "control read: %s\n",
+			 get_usb_statmsg(urb->status));
 	retry:
 		if (ucs->retry_cmd_in++ < BAS_RETRY) {
-			notice("control read: retry %d", ucs->retry_cmd_in);
-			if (atread_submit(cs, BAS_TIMEOUT) >= 0) {
-				/* resubmitted - bypass regular exit block */
-				spin_unlock_irqrestore(&cs->lock, flags);
+			dev_notice(cs->dev, "control read: retry %d\n",
+				   ucs->retry_cmd_in);
+			rc = atread_submit(cs, BAS_TIMEOUT);
+			if (rc >= 0 || rc == -ENODEV)
+				/* resubmitted or disconnected */
+				/* - bypass regular exit block */
 				return;
-			}
 		} else {
-			err("control read: giving up after %d tries",
-			    ucs->retry_cmd_in);
+			dev_err(cs->dev,
+				"control read: giving up after %d tries\n",
+				ucs->retry_cmd_in);
 		}
 		error_reset(cs);
 	}
@@ -722,9 +728,8 @@
 	kfree(ucs->rcvbuf);
 	ucs->rcvbuf = NULL;
 	ucs->rcvbuf_size = 0;
-	spin_unlock_irqrestore(&cs->lock, flags);
 	if (have_data) {
-		dbg(DEBUG_INTR, "%s-->BH", __func__);
+		gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
 		gigaset_schedule_event(cs);
 	}
 }
@@ -743,21 +748,19 @@
 	unsigned long flags;
 	int i, rc;
 
-	IFNULLRET(urb);
-	IFNULLRET(urb->context);
-	IFNULLRET(cardstate);
-
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
-	             urb->status == -EINPROGRESS)) {
-		dbg(DEBUG_ISO,
-		    "%s: %s", __func__, get_usb_statmsg(urb->status));
+	if (unlikely(urb->status == -ENOENT ||
+		     urb->status == -ECONNRESET ||
+		     urb->status == -EINPROGRESS ||
+		     urb->status == -ENODEV ||
+		     urb->status == -ESHUTDOWN)) {
+		gig_dbg(DEBUG_ISO, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
 		return;
 	}
 
-	bcs = (struct bc_state *) urb->context;
+	bcs = urb->context;
 	ubc = bcs->hw.bas;
-	IFNULLRET(ubc);
 
 	spin_lock_irqsave(&ubc->isoinlock, flags);
 	if (likely(ubc->isoindone == NULL)) {
@@ -770,21 +773,24 @@
 		for (i = 0; i < BAS_NUMFRAMES; i++) {
 			ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
 			if (unlikely(urb->iso_frame_desc[i].status != 0 &&
-				     urb->iso_frame_desc[i].status != -EINPROGRESS)) {
+				     urb->iso_frame_desc[i].status !=
+								-EINPROGRESS))
 				ubc->loststatus = urb->iso_frame_desc[i].status;
-			}
 			urb->iso_frame_desc[i].status = 0;
 			urb->iso_frame_desc[i].actual_length = 0;
 		}
 		if (likely(atomic_read(&ubc->running))) {
-			urb->dev = bcs->cs->hw.bas->udev;	/* clobbered by USB subsystem */
+			/* urb->dev is clobbered by USB subsystem */
+			urb->dev = bcs->cs->hw.bas->udev;
 			urb->transfer_flags = URB_ISO_ASAP;
 			urb->number_of_packets = BAS_NUMFRAMES;
-			dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__);
+			gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit",
+				__func__);
 			rc = usb_submit_urb(urb, SLAB_ATOMIC);
-			if (unlikely(rc != 0)) {
-				err("could not resubmit isochronous read URB: %s",
-				    get_usb_statmsg(rc));
+			if (unlikely(rc != 0 && rc != -ENODEV)) {
+				dev_err(bcs->cs->dev,
+					"could not resubmit isochronous read "
+					"URB: %s\n", get_usb_rcmsg(rc));
 				dump_urb(DEBUG_ISO, "isoc read", urb);
 				error_hangup(bcs);
 			}
@@ -806,23 +812,20 @@
 	struct bas_bc_state *ubc;
 	unsigned long flags;
 
-	IFNULLRET(urb);
-	IFNULLRET(urb->context);
-	IFNULLRET(cardstate);
-
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET ||
-	             urb->status == -EINPROGRESS)) {
-		dbg(DEBUG_ISO,
-		    "%s: %s", __func__, get_usb_statmsg(urb->status));
+	if (unlikely(urb->status == -ENOENT ||
+		     urb->status == -ECONNRESET ||
+		     urb->status == -EINPROGRESS ||
+		     urb->status == -ENODEV ||
+		     urb->status == -ESHUTDOWN)) {
+		gig_dbg(DEBUG_ISO, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
 		return;
 	}
 
 	/* pass URB context to tasklet */
-	ucx = (struct isow_urbctx_t *) urb->context;
-	IFNULLRET(ucx->bcs);
+	ucx = urb->context;
 	ubc = ucx->bcs->hw.bas;
-	IFNULLRET(ubc);
 
 	spin_lock_irqsave(&ubc->isooutlock, flags);
 	ubc->isooutovfl = ubc->isooutdone;
@@ -841,15 +844,11 @@
  */
 static int starturbs(struct bc_state *bcs)
 {
+	struct bas_bc_state *ubc = bcs->hw.bas;
 	struct urb *urb;
-	struct bas_bc_state *ubc;
 	int j, k;
 	int rc;
 
-	IFNULLRETVAL(bcs, -EFAULT);
-	ubc = bcs->hw.bas;
-	IFNULLRETVAL(ubc, -EFAULT);
-
 	/* initialize L2 reception */
 	if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
 		bcs->inputstate |= INS_flag_hunt;
@@ -859,7 +858,6 @@
 	for (k = 0; k < BAS_INURBS; k++) {
 		urb = ubc->isoinurbs[k];
 		if (!urb) {
-			err("isoinurbs[%d]==NULL", k);
 			rc = -EFAULT;
 			goto error;
 		}
@@ -881,11 +879,8 @@
 		}
 
 		dump_urb(DEBUG_ISO, "Initial isoc read", urb);
-		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
-			err("could not submit isochronous read URB %d: %s",
-			    k, get_usb_statmsg(rc));
+		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0)
 			goto error;
-		}
 	}
 
 	/* initialize L2 transmission */
@@ -895,7 +890,6 @@
 	for (k = 0; k < BAS_OUTURBS; ++k) {
 		urb = ubc->isoouturbs[k].urb;
 		if (!urb) {
-			err("isoouturbs[%d].urb==NULL", k);
 			rc = -EFAULT;
 			goto error;
 		}
@@ -921,11 +915,8 @@
 	for (k = 0; k < 2; ++k) {
 		dump_urb(DEBUG_ISO, "Initial isoc write", urb);
 		rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC);
-		if (rc != 0) {
-			err("could not submit isochronous write URB %d: %s",
-			    k, get_usb_statmsg(rc));
+		if (rc != 0)
 			goto error;
-		}
 	}
 	dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
 	ubc->isooutfree = &ubc->isoouturbs[2];
@@ -946,20 +937,20 @@
 {
 	int k, rc;
 
-	IFNULLRET(ubc);
-
 	atomic_set(&ubc->running, 0);
 
 	for (k = 0; k < BAS_INURBS; ++k) {
 		rc = usb_unlink_urb(ubc->isoinurbs[k]);
-		dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d",
-		    __func__, k, rc);
+		gig_dbg(DEBUG_ISO,
+			"%s: isoc input URB %d unlinked, result = %s",
+			__func__, k, get_usb_rcmsg(rc));
 	}
 
 	for (k = 0; k < BAS_OUTURBS; ++k) {
 		rc = usb_unlink_urb(ubc->isoouturbs[k].urb);
-		dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d",
-		    __func__, k, rc);
+		gig_dbg(DEBUG_ISO,
+			"%s: isoc output URB %d unlinked, result = %s",
+			__func__, k, get_usb_rcmsg(rc));
 	}
 }
 
@@ -969,7 +960,7 @@
 /* submit_iso_write_urb
  * fill and submit the next isochronous write URB
  * parameters:
- *	bcs	B channel state structure
+ *	ucx	context structure containing URB
  * return value:
  *	number of frames submitted in URB
  *	0 if URB not submitted because no data available (isooutbuf busy)
@@ -977,19 +968,13 @@
  */
 static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
 {
-	struct urb *urb;
-	struct bas_bc_state *ubc;
+	struct urb *urb = ucx->urb;
+	struct bas_bc_state *ubc = ucx->bcs->hw.bas;
 	struct usb_iso_packet_descriptor *ifd;
 	int corrbytes, nframe, rc;
 
-	IFNULLRETVAL(ucx, -EFAULT);
-	urb = ucx->urb;
-	IFNULLRETVAL(urb, -EFAULT);
-	IFNULLRETVAL(ucx->bcs, -EFAULT);
-	ubc = ucx->bcs->hw.bas;
-	IFNULLRETVAL(ubc, -EFAULT);
-
-	urb->dev = ucx->bcs->cs->hw.bas->udev;	/* clobbered by USB subsystem */
+	/* urb->dev is clobbered by USB subsystem */
+	urb->dev = ucx->bcs->cs->hw.bas->udev;
 	urb->transfer_flags = URB_ISO_ASAP;
 	urb->transfer_buffer = ubc->isooutbuf->data;
 	urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data);
@@ -1000,7 +985,8 @@
 		/* compute frame length according to flow control */
 		ifd->length = BAS_NORMFRAME;
 		if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) {
-			dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes);
+			gig_dbg(DEBUG_ISO, "%s: corrbytes=%d",
+				__func__, corrbytes);
 			if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
 				corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME;
 			else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME)
@@ -1008,18 +994,21 @@
 			ifd->length += corrbytes;
 			atomic_add(-corrbytes, &ubc->corrbytes);
 		}
-		//dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length);
 
 		/* retrieve block of data to send */
-		ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length);
+		ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf,
+						       ifd->length);
 		if (ifd->offset < 0) {
 			if (ifd->offset == -EBUSY) {
-				dbg(DEBUG_ISO, "%s: buffer busy at frame %d",
-				    __func__, nframe);
-				/* tasklet will be restarted from gigaset_send_skb() */
+				gig_dbg(DEBUG_ISO,
+					"%s: buffer busy at frame %d",
+					__func__, nframe);
+				/* tasklet will be restarted from
+				   gigaset_send_skb() */
 			} else {
-				err("%s: buffer error %d at frame %d",
-				    __func__, ifd->offset, nframe);
+				dev_err(ucx->bcs->cs->dev,
+					"%s: buffer error %d at frame %d\n",
+					__func__, ifd->offset, nframe);
 				return ifd->offset;
 			}
 			break;
@@ -1028,15 +1017,22 @@
 		ifd->status = 0;
 		ifd->actual_length = 0;
 	}
-	if ((urb->number_of_packets = nframe) > 0) {
-		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
-			err("could not submit isochronous write URB: %s",
-			    get_usb_statmsg(rc));
-			dump_urb(DEBUG_ISO, "isoc write", urb);
-			return rc;
-		}
-		++ubc->numsub;
+	if (unlikely(nframe == 0))
+		return 0;	/* no data to send */
+	urb->number_of_packets = nframe;
+
+	rc = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (unlikely(rc)) {
+		if (rc == -ENODEV)
+			/* device removed - give up silently */
+			gig_dbg(DEBUG_ISO, "%s: disconnected", __func__);
+		else
+			dev_err(ucx->bcs->cs->dev,
+				"could not submit isochronous write URB: %s\n",
+				get_usb_rcmsg(rc));
+		return rc;
 	}
+	++ubc->numsub;
 	return nframe;
 }
 
@@ -1048,9 +1044,9 @@
  */
 static void write_iso_tasklet(unsigned long data)
 {
-	struct bc_state *bcs;
-	struct bas_bc_state *ubc;
-	struct cardstate *cs;
+	struct bc_state *bcs = (struct bc_state *) data;
+	struct bas_bc_state *ubc = bcs->hw.bas;
+	struct cardstate *cs = bcs->cs;
 	struct isow_urbctx_t *done, *next, *ovfl;
 	struct urb *urb;
 	struct usb_iso_packet_descriptor *ifd;
@@ -1059,23 +1055,12 @@
 	int i;
 	struct sk_buff *skb;
 	int len;
-
-	bcs = (struct bc_state *) data;
-	IFNULLRET(bcs);
-	ubc = bcs->hw.bas;
-	IFNULLRET(ubc);
-	cs = bcs->cs;
-	IFNULLRET(cs);
+	int rc;
 
 	/* loop while completed URBs arrive in time */
 	for (;;) {
-		if (unlikely(!atomic_read(&cs->connected))) {
-			warn("%s: disconnected", __func__);
-			return;
-		}
-
 		if (unlikely(!(atomic_read(&ubc->running)))) {
-			dbg(DEBUG_ISO, "%s: not running", __func__);
+			gig_dbg(DEBUG_ISO, "%s: not running", __func__);
 			return;
 		}
 
@@ -1087,7 +1072,7 @@
 		ubc->isooutovfl = NULL;
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (ovfl) {
-			err("isochronous write buffer underrun - buy a faster machine :-)");
+			dev_err(cs->dev, "isochronous write buffer underrun\n");
 			error_hangup(bcs);
 			break;
 		}
@@ -1100,7 +1085,8 @@
 		ubc->isooutfree = NULL;
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (next) {
-			if (submit_iso_write_urb(next) <= 0) {
+			rc = submit_iso_write_urb(next);
+			if (unlikely(rc <= 0 && rc != -ENODEV)) {
 				/* could not submit URB, put it back */
 				spin_lock_irqsave(&ubc->isooutlock, flags);
 				if (ubc->isooutfree == NULL) {
@@ -1110,7 +1096,8 @@
 				spin_unlock_irqrestore(&ubc->isooutlock, flags);
 				if (next) {
 					/* couldn't put it back */
-					err("losing isochronous write URB");
+					dev_err(cs->dev,
+					      "losing isochronous write URB\n");
 					error_hangup(bcs);
 				}
 			}
@@ -1119,26 +1106,30 @@
 		/* process completed URB */
 		urb = done->urb;
 		switch (urb->status) {
+		case -EXDEV:			/* partial completion */
+			gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+				__func__);
+			/* fall through - what's the difference anyway? */
 		case 0:				/* normal completion */
-			break;
-		case -EXDEV:			/* inspect individual frames */
-			/* assumptions (for lack of documentation):
-			 * - actual_length bytes of the frame in error are successfully sent
+			/* inspect individual frames
+			 * assumptions (for lack of documentation):
+			 * - actual_length bytes of first frame in error are
+			 *   successfully sent
 			 * - all following frames are not sent at all
 			 */
-			dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
-			offset = done->limit;	/* just in case */
+			offset = done->limit;	/* default (no error) */
 			for (i = 0; i < BAS_NUMFRAMES; i++) {
 				ifd = &urb->iso_frame_desc[i];
 				if (ifd->status ||
 				    ifd->actual_length != ifd->length) {
-					warn("isochronous write: frame %d: %s, "
-					     "only %d of %d bytes sent",
+					dev_warn(cs->dev,
+					     "isochronous write: frame %d: %s, "
+					     "only %d of %d bytes sent\n",
 					     i, get_usb_statmsg(ifd->status),
 					     ifd->actual_length, ifd->length);
 					offset = (ifd->offset +
-					          ifd->actual_length)
-					         % BAS_OUTBUFSIZE;
+						  ifd->actual_length)
+						 % BAS_OUTBUFSIZE;
 					break;
 				}
 			}
@@ -1148,25 +1139,26 @@
 				ifd = &urb->iso_frame_desc[i];
 				if (ifd->status != -EINPROGRESS
 				    || ifd->actual_length != 0) {
-					warn("isochronous write: frame %d: %s, "
-					     "%d of %d bytes sent",
+					dev_warn(cs->dev,
+					     "isochronous write: frame %d: %s, "
+					     "%d of %d bytes sent\n",
 					     i, get_usb_statmsg(ifd->status),
 					     ifd->actual_length, ifd->length);
 					offset = (ifd->offset +
-					          ifd->actual_length)
-					         % BAS_OUTBUFSIZE;
+						  ifd->actual_length)
+						 % BAS_OUTBUFSIZE;
 					break;
 				}
 			}
 #endif
 			break;
-		case -EPIPE:			//FIXME is this the code for "underrun"?
-			err("isochronous write stalled");
+		case -EPIPE:			/* stall - probably underrun */
+			dev_err(cs->dev, "isochronous write stalled\n");
 			error_hangup(bcs);
 			break;
 		default:			/* severe trouble */
-			warn("isochronous write: %s",
-			     get_usb_statmsg(urb->status));
+			dev_warn(cs->dev, "isochronous write: %s\n",
+				 get_usb_statmsg(urb->status));
 		}
 
 		/* mark the write buffer area covered by this URB as free */
@@ -1180,7 +1172,8 @@
 		spin_unlock_irqrestore(&ubc->isooutlock, flags);
 		if (next) {
 			/* only one URB still active - resubmit one */
-			if (submit_iso_write_urb(next) <= 0) {
+			rc = submit_iso_write_urb(next);
+			if (unlikely(rc <= 0 && rc != -ENODEV)) {
 				/* couldn't submit */
 				error_hangup(bcs);
 			}
@@ -1194,8 +1187,8 @@
 		if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) {
 			/* insufficient buffer space, push back onto queue */
 			skb_queue_head(&bcs->squeue, skb);
-			dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
-			    __func__, skb_queue_len(&bcs->squeue));
+			gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d",
+				__func__, skb_queue_len(&bcs->squeue));
 			break;
 		}
 		skb_pull(skb, len);
@@ -1215,28 +1208,16 @@
  */
 static void read_iso_tasklet(unsigned long data)
 {
-	struct bc_state *bcs;
-	struct bas_bc_state *ubc;
-	struct cardstate *cs;
+	struct bc_state *bcs = (struct bc_state *) data;
+	struct bas_bc_state *ubc = bcs->hw.bas;
+	struct cardstate *cs = bcs->cs;
 	struct urb *urb;
 	char *rcvbuf;
 	unsigned long flags;
 	int totleft, numbytes, offset, frame, rc;
 
-	bcs = (struct bc_state *) data;
-	IFNULLRET(bcs);
-	ubc = bcs->hw.bas;
-	IFNULLRET(ubc);
-	cs = bcs->cs;
-	IFNULLRET(cs);
-
 	/* loop while more completed URBs arrive in the meantime */
 	for (;;) {
-		if (!atomic_read(&cs->connected)) {
-			warn("%s: disconnected", __func__);
-			return;
-		}
-
 		/* retrieve URB */
 		spin_lock_irqsave(&ubc->isoinlock, flags);
 		if (!(urb = ubc->isoindone)) {
@@ -1245,38 +1226,44 @@
 		}
 		ubc->isoindone = NULL;
 		if (unlikely(ubc->loststatus != -EINPROGRESS)) {
-			warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost",
-			     get_usb_statmsg(ubc->loststatus), ubc->isoinlost);
+			dev_warn(cs->dev,
+				 "isochronous read overrun, "
+				 "dropped URB with status: %s, %d bytes lost\n",
+				 get_usb_statmsg(ubc->loststatus),
+				 ubc->isoinlost);
 			ubc->loststatus = -EINPROGRESS;
 		}
 		spin_unlock_irqrestore(&ubc->isoinlock, flags);
 
 		if (unlikely(!(atomic_read(&ubc->running)))) {
-			dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s",
-			    __func__, get_usb_statmsg(urb->status));
+			gig_dbg(DEBUG_ISO,
+				"%s: channel not running, "
+				"dropped URB with status: %s",
+				__func__, get_usb_statmsg(urb->status));
 			return;
 		}
 
 		switch (urb->status) {
 		case 0:				/* normal completion */
 			break;
-		case -EXDEV:			/* inspect individual frames (we do that anyway) */
-			dbg(DEBUG_ISO, "%s: URB partially completed", __func__);
+		case -EXDEV:			/* inspect individual frames
+						   (we do that anyway) */
+			gig_dbg(DEBUG_ISO, "%s: URB partially completed",
+				__func__);
 			break;
 		case -ENOENT:
 		case -ECONNRESET:
-			dbg(DEBUG_ISO, "%s: URB canceled", __func__);
-			continue;		/* -> skip */
-		case -EINPROGRESS:		/* huh? */
-			dbg(DEBUG_ISO, "%s: URB still pending", __func__);
+		case -EINPROGRESS:
+			gig_dbg(DEBUG_ISO, "%s: %s",
+				__func__, get_usb_statmsg(urb->status));
 			continue;		/* -> skip */
 		case -EPIPE:
-			err("isochronous read stalled");
+			dev_err(cs->dev, "isochronous read stalled\n");
 			error_hangup(bcs);
 			continue;		/* -> skip */
 		default:			/* severe trouble */
-			warn("isochronous read: %s",
-			     get_usb_statmsg(urb->status));
+			dev_warn(cs->dev, "isochronous read: %s\n",
+				 get_usb_statmsg(urb->status));
 			goto error;
 		}
 
@@ -1284,33 +1271,44 @@
 		totleft = urb->actual_length;
 		for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) {
 			if (unlikely(urb->iso_frame_desc[frame].status)) {
-				warn("isochronous read: frame %d: %s",
-				     frame, get_usb_statmsg(urb->iso_frame_desc[frame].status));
+				dev_warn(cs->dev,
+					 "isochronous read: frame %d: %s\n",
+					 frame,
+					 get_usb_statmsg(
+					    urb->iso_frame_desc[frame].status));
 				break;
 			}
 			numbytes = urb->iso_frame_desc[frame].actual_length;
 			if (unlikely(numbytes > BAS_MAXFRAME)) {
-				warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME",
-				     frame, numbytes);
+				dev_warn(cs->dev,
+					 "isochronous read: frame %d: "
+					 "numbytes (%d) > BAS_MAXFRAME\n",
+					 frame, numbytes);
 				break;
 			}
 			if (unlikely(numbytes > totleft)) {
-				warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)",
-				     frame, numbytes, totleft);
+				dev_warn(cs->dev,
+					 "isochronous read: frame %d: "
+					 "numbytes (%d) > totleft (%d)\n",
+					 frame, numbytes, totleft);
 				break;
 			}
 			offset = urb->iso_frame_desc[frame].offset;
 			if (unlikely(offset + numbytes > BAS_INBUFSIZE)) {
-				warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE",
-				     frame, offset, numbytes);
+				dev_warn(cs->dev,
+					 "isochronous read: frame %d: "
+					 "offset (%d) + numbytes (%d) "
+					 "> BAS_INBUFSIZE\n",
+					 frame, offset, numbytes);
 				break;
 			}
 			gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs);
 			totleft -= numbytes;
 		}
 		if (unlikely(totleft > 0))
-			warn("isochronous read: %d data bytes missing",
-			     totleft);
+			dev_warn(cs->dev,
+				 "isochronous read: %d data bytes missing\n",
+				 totleft);
 
 	error:
 		/* URB processed, resubmit */
@@ -1318,12 +1316,15 @@
 			urb->iso_frame_desc[frame].status = 0;
 			urb->iso_frame_desc[frame].actual_length = 0;
 		}
-		urb->dev = bcs->cs->hw.bas->udev;	/* clobbered by USB subsystem */
+		/* urb->dev is clobbered by USB subsystem */
+		urb->dev = bcs->cs->hw.bas->udev;
 		urb->transfer_flags = URB_ISO_ASAP;
 		urb->number_of_packets = BAS_NUMFRAMES;
-		if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) {
-			err("could not resubmit isochronous read URB: %s",
-			    get_usb_statmsg(rc));
+		rc = usb_submit_urb(urb, SLAB_ATOMIC);
+		if (unlikely(rc != 0 && rc != -ENODEV)) {
+			dev_err(cs->dev,
+				"could not resubmit isochronous read URB: %s\n",
+				get_usb_rcmsg(rc));
 			dump_urb(DEBUG_ISO, "resubmit iso read", urb);
 			error_hangup(bcs);
 		}
@@ -1341,15 +1342,10 @@
 static void req_timeout(unsigned long data)
 {
 	struct bc_state *bcs = (struct bc_state *) data;
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = bcs->cs->hw.bas;
 	int pending;
 	unsigned long flags;
 
-	IFNULLRET(bcs);
-	IFNULLRET(bcs->cs);
-	ucs = bcs->cs->hw.bas;
-	IFNULLRET(ucs);
-
 	check_pending(ucs);
 
 	spin_lock_irqsave(&ucs->lock, flags);
@@ -1359,33 +1355,34 @@
 
 	switch (pending) {
 	case 0:					/* no pending request */
-		dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
+		gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__);
 		break;
 
 	case HD_OPEN_ATCHANNEL:
-		err("timeout opening AT channel");
+		dev_err(bcs->cs->dev, "timeout opening AT channel\n");
 		error_reset(bcs->cs);
 		break;
 
 	case HD_OPEN_B2CHANNEL:
 	case HD_OPEN_B1CHANNEL:
-		err("timeout opening channel %d", bcs->channel + 1);
+		dev_err(bcs->cs->dev, "timeout opening channel %d\n",
+			bcs->channel + 1);
 		error_hangup(bcs);
 		break;
 
 	case HD_CLOSE_ATCHANNEL:
-		err("timeout closing AT channel");
-		//wake_up_interruptible(cs->initwait);
-		//FIXME need own wait queue?
+		dev_err(bcs->cs->dev, "timeout closing AT channel\n");
 		break;
 
 	case HD_CLOSE_B2CHANNEL:
 	case HD_CLOSE_B1CHANNEL:
-		err("timeout closing channel %d", bcs->channel + 1);
+		dev_err(bcs->cs->dev, "timeout closing channel %d\n",
+			bcs->channel + 1);
 		break;
 
 	default:
-		warn("request 0x%02x timed out, clearing", pending);
+		dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
+			 pending);
 	}
 }
 
@@ -1398,18 +1395,14 @@
  */
 static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
 {
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = urb->context;
 	unsigned long flags;
 
-	IFNULLRET(urb);
-	IFNULLRET(urb->context);
-	IFNULLRET(cardstate);
-
-	ucs = (struct bas_cardstate *) urb->context;
 	spin_lock_irqsave(&ucs->lock, flags);
 	if (urb->status && ucs->pending) {
-		err("control request 0x%02x failed: %s",
-		    ucs->pending, get_usb_statmsg(urb->status));
+		dev_err(&ucs->interface->dev,
+			"control request 0x%02x failed: %s\n",
+			ucs->pending, get_usb_statmsg(urb->status));
 		del_timer(&ucs->timer_ctrl);
 		ucs->pending = 0;
 	}
@@ -1432,34 +1425,24 @@
  *	timeout	timeout in seconds (0: no timeout)
  * return value:
  *	0 on success
- *	-EINVAL if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
 static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
 {
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = bcs->cs->hw.bas;
 	int ret;
 	unsigned long flags;
 
-	IFNULLRETVAL(bcs, -EINVAL);
-	IFNULLRETVAL(bcs->cs, -EINVAL);
-	ucs = bcs->cs->hw.bas;
-	IFNULLRETVAL(ucs, -EINVAL);
-	IFNULLRETVAL(ucs->urb_ctrl, -EINVAL);
-
-	dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
+	gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val);
 
 	spin_lock_irqsave(&ucs->lock, flags);
 	if (ucs->pending) {
 		spin_unlock_irqrestore(&ucs->lock, flags);
-		err("submission of request 0x%02x failed: request 0x%02x still pending",
-		    req, ucs->pending);
-		return -EBUSY;
-	}
-	if (ucs->urb_ctrl->status == -EINPROGRESS) {
-		spin_unlock_irqrestore(&ucs->lock, flags);
-		err("could not submit request 0x%02x: URB busy", req);
+		dev_err(bcs->cs->dev,
+			"submission of request 0x%02x failed: "
+			"request 0x%02x still pending\n",
+			req, ucs->pending);
 		return -EBUSY;
 	}
 
@@ -1469,19 +1452,19 @@
 	ucs->dr_ctrl.wIndex = 0;
 	ucs->dr_ctrl.wLength = 0;
 	usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
-                             usb_sndctrlpipe(ucs->udev, 0),
-                             (unsigned char*) &ucs->dr_ctrl, NULL, 0,
-                             write_ctrl_callback, ucs);
+			     usb_sndctrlpipe(ucs->udev, 0),
+			     (unsigned char*) &ucs->dr_ctrl, NULL, 0,
+			     write_ctrl_callback, ucs);
 	if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) {
-		err("could not submit request 0x%02x: %s",
-		    req, get_usb_statmsg(ret));
+		dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n",
+			req, get_usb_statmsg(ret));
 		spin_unlock_irqrestore(&ucs->lock, flags);
 		return ret;
 	}
 	ucs->pending = req;
 
 	if (timeout > 0) {
-		dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
+		gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout);
 		ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10;
 		ucs->timer_ctrl.data = (unsigned long) bcs;
 		ucs->timer_ctrl.function = req_timeout;
@@ -1503,23 +1486,36 @@
 static int gigaset_init_bchannel(struct bc_state *bcs)
 {
 	int req, ret;
+	unsigned long flags;
 
-	IFNULLRETVAL(bcs, -EINVAL);
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (unlikely(!bcs->cs->connected)) {
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		return -ENODEV;
+	}
 
 	if ((ret = starturbs(bcs)) < 0) {
-		err("could not start isochronous I/O for channel %d",
-		    bcs->channel + 1);
-		error_hangup(bcs);
+		dev_err(bcs->cs->dev,
+			"could not start isochronous I/O for channel B%d: %s\n",
+			bcs->channel + 1,
+			ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
+		if (ret != -ENODEV)
+			error_hangup(bcs);
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		return ret;
 	}
 
 	req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
-		err("could not open channel %d: %s",
-		    bcs->channel + 1, get_usb_statmsg(ret));
+		dev_err(bcs->cs->dev, "could not open channel B%d\n",
+			bcs->channel + 1);
 		stopurbs(bcs->hw.bas);
-		error_hangup(bcs);
+		if (ret != -ENODEV)
+			error_hangup(bcs);
 	}
+
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	return ret;
 }
 
@@ -1536,20 +1532,30 @@
 static int gigaset_close_bchannel(struct bc_state *bcs)
 {
 	int req, ret;
+	unsigned long flags;
 
-	IFNULLRETVAL(bcs, -EINVAL);
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (unlikely(!bcs->cs->connected)) {
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		return -ENODEV;
+	}
 
 	if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
 	      (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
 		/* channel not running: just signal common.c */
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		gigaset_bchannel_down(bcs);
 		return 0;
 	}
 
+	/* channel running: tell device to close it */
 	req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
-		err("could not submit HD_CLOSE_BxCHANNEL request: %s",
-		    get_usb_statmsg(ret));
+		dev_err(bcs->cs->dev, "closing channel B%d failed\n",
+			bcs->channel + 1);
+
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	return ret;
 }
 
@@ -1564,17 +1570,13 @@
  */
 static void complete_cb(struct cardstate *cs)
 {
-	struct cmdbuf_t *cb;
-
-	IFNULLRET(cs);
-	cb = cs->cmdbuf;
-	IFNULLRET(cb);
+	struct cmdbuf_t *cb = cs->cmdbuf;
 
 	/* unqueue completed buffer */
 	cs->cmdbytes -= cs->curlen;
-	dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD,
-	    "write_command: sent %u bytes, %u left",
-	    cs->curlen, cs->cmdbytes);
+	gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
+		"write_command: sent %u bytes, %u left",
+		cs->curlen, cs->cmdbytes);
 	if ((cs->cmdbuf = cb->next) != NULL) {
 		cs->cmdbuf->prev = NULL;
 		cs->curlen = cs->cmdbuf->len;
@@ -1589,8 +1591,6 @@
 	kfree(cb);
 }
 
-static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len);
-
 /* write_command_callback
  * USB completion handler for AT command transmission
  * called by the USB subsystem in interrupt context
@@ -1600,40 +1600,43 @@
  */
 static void write_command_callback(struct urb *urb, struct pt_regs *regs)
 {
-	struct cardstate *cs;
+	struct cardstate *cs = urb->context;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	unsigned long flags;
-	struct bas_cardstate *ucs;
 
-	IFNULLRET(urb);
-	cs = (struct cardstate *) urb->context;
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
+	update_basstate(ucs, 0, BS_ATWRPEND);
 
 	/* check status */
 	switch (urb->status) {
 	case 0:					/* normal completion */
 		break;
-	case -ENOENT:			/* canceled */
-	case -ECONNRESET:		/* canceled (async) */
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
 	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
 		/* ignore silently */
-		dbg(DEBUG_USBREQ,
-		    "%s: %s", __func__, get_usb_statmsg(urb->status));
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
 		return;
 	default:				/* any failure */
 		if (++ucs->retry_cmd_out > BAS_RETRY) {
-			warn("command write: %s, giving up after %d retries",
-			     get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+			dev_warn(cs->dev,
+				 "command write: %s, "
+				 "giving up after %d retries\n",
+				 get_usb_statmsg(urb->status),
+				 ucs->retry_cmd_out);
 			break;
 		}
 		if (cs->cmdbuf == NULL) {
-			warn("command write: %s, cannot retry - cmdbuf gone",
-			     get_usb_statmsg(urb->status));
+			dev_warn(cs->dev,
+				 "command write: %s, "
+				 "cannot retry - cmdbuf gone\n",
+				 get_usb_statmsg(urb->status));
 			break;
 		}
-		notice("command write: %s, retry %d",
-		       get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+		dev_notice(cs->dev, "command write: %s, retry %d\n",
+			   get_usb_statmsg(urb->status), ucs->retry_cmd_out);
 		if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
 			/* resubmitted - bypass regular exit block */
 			return;
@@ -1655,13 +1658,9 @@
 static void atrdy_timeout(unsigned long data)
 {
 	struct cardstate *cs = (struct cardstate *) data;
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = cs->hw.bas;
 
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
-
-	warn("timeout waiting for HD_READY_SEND_ATDATA");
+	dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n");
 
 	/* fake the missing signal - what else can I do? */
 	update_basstate(ucs, BS_ATREADY, BS_ATTIMER);
@@ -1676,24 +1675,19 @@
  *	len	length of command to send
  * return value:
  *	0 on success
- *	-EFAULT if a NULL pointer is encountered somewhere
  *	-EBUSY if another request is pending
  *	any URB submission error code
  */
 static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
 {
-	struct bas_cardstate *ucs;
-	int ret;
+	struct bas_cardstate *ucs = cs->hw.bas;
+	int rc;
 
-	IFNULLRETVAL(cs, -EFAULT);
-	ucs = cs->hw.bas;
-	IFNULLRETVAL(ucs, -EFAULT);
-	IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT);
+	gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
 
-	dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len);
-
-	if (ucs->urb_cmd_out->status == -EINPROGRESS) {
-		err("could not submit HD_WRITE_ATMESSAGE: URB busy");
+	if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) {
+		dev_err(cs->dev,
+			"could not submit HD_WRITE_ATMESSAGE: URB busy\n");
 		return -EBUSY;
 	}
 
@@ -1706,25 +1700,22 @@
 			     usb_sndctrlpipe(ucs->udev, 0),
 			     (unsigned char*) &ucs->dr_cmd_out, buf, len,
 			     write_command_callback, cs);
-
-	if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) {
-		err("could not submit HD_WRITE_ATMESSAGE: %s",
-		    get_usb_statmsg(ret));
-		return ret;
+	rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC);
+	if (unlikely(rc)) {
+		update_basstate(ucs, 0, BS_ATWRPEND);
+		dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n",
+			get_usb_rcmsg(rc));
+		return rc;
 	}
 
-	/* submitted successfully */
-	update_basstate(ucs, 0, BS_ATREADY);
-
-	/* start timeout if necessary */
-	if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) {
-		dbg(DEBUG_OUTPUT,
-		    "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT);
+	/* submitted successfully, start timeout if necessary */
+	if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) {
+		gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs",
+			ATRDY_TIMEOUT);
 		ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10;
 		ucs->timer_atrdy.data = (unsigned long) cs;
 		ucs->timer_atrdy.function = atrdy_timeout;
 		add_timer(&ucs->timer_atrdy);
-		update_basstate(ucs, BS_ATTIMER, 0);
 	}
 	return 0;
 }
@@ -1740,21 +1731,16 @@
 static int start_cbsend(struct cardstate *cs)
 {
 	struct cmdbuf_t *cb;
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	unsigned long flags;
 	int rc;
 	int retval = 0;
 
-	IFNULLRETVAL(cs, -EFAULT);
-	ucs = cs->hw.bas;
-	IFNULLRETVAL(ucs, -EFAULT);
-
 	/* check if AT channel is open */
 	if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
-		dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open");
+		gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
 		rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
 		if (rc < 0) {
-			err("could not open AT channel");
 			/* flush command queue */
 			spin_lock_irqsave(&cs->cmdlock, flags);
 			while (cs->cmdbuf != NULL)
@@ -1792,27 +1778,23 @@
  *	cs		controller state structure
  *	buf		command string to send
  *	len		number of bytes to send (max. IF_WRITEBUF)
- *	wake_tasklet	tasklet to run when transmission is completed (NULL if none)
+ *	wake_tasklet	tasklet to run when transmission is completed
+ *			(NULL if none)
  * return value:
  *	number of bytes queued on success
  *	error code < 0 on error
  */
 static int gigaset_write_cmd(struct cardstate *cs,
-                             const unsigned char *buf, int len,
-                             struct tasklet_struct *wake_tasklet)
+			     const unsigned char *buf, int len,
+			     struct tasklet_struct *wake_tasklet)
 {
 	struct cmdbuf_t *cb;
 	unsigned long flags;
 	int status;
 
 	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
-	                     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-	                   "CMD Transmit", len, buf, 0);
-
-	if (!atomic_read(&cs->connected)) {
-		err("%s: not connected", __func__);
-		return -ENODEV;
-	}
+			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+			   "CMD Transmit", len, buf);
 
 	if (len <= 0)
 		return 0;			/* nothing to do */
@@ -1820,7 +1802,7 @@
 	if (len > IF_WRITEBUF)
 		len = IF_WRITEBUF;
 	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
-		err("%s: out of memory", __func__);
+		dev_err(cs->dev, "%s: out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -1842,14 +1824,21 @@
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
+	spin_lock_irqsave(&cs->lock, flags);
+	if (unlikely(!cs->connected)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
+		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
+		return -ENODEV;
+	}
 	status = start_cbsend(cs);
-
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return status < 0 ? status : len;
 }
 
 /* gigaset_write_room
  * tty_driver.write_room interface routine
- * return number of characters the driver will accept to be written via gigaset_write_cmd
+ * return number of characters the driver will accept to be written via
+ * gigaset_write_cmd
  * parameter:
  *	controller state structure
  * return value:
@@ -1904,12 +1893,32 @@
  */
 static int gigaset_freebcshw(struct bc_state *bcs)
 {
-	if (!bcs->hw.bas)
+	struct bas_bc_state *ubc = bcs->hw.bas;
+	int i;
+
+	if (!ubc)
 		return 0;
 
-	if (bcs->hw.bas->isooutbuf)
-		kfree(bcs->hw.bas->isooutbuf);
-	kfree(bcs->hw.bas);
+	/* kill URBs and tasklets before freeing - better safe than sorry */
+	atomic_set(&ubc->running, 0);
+	for (i = 0; i < BAS_OUTURBS; ++i)
+		if (ubc->isoouturbs[i].urb) {
+			gig_dbg(DEBUG_INIT, "%s: killing iso out URB %d",
+				__func__, i);
+			usb_kill_urb(ubc->isoouturbs[i].urb);
+			usb_free_urb(ubc->isoouturbs[i].urb);
+		}
+	for (i = 0; i < BAS_INURBS; ++i)
+		if (ubc->isoinurbs[i]) {
+			gig_dbg(DEBUG_INIT, "%s: killing iso in URB %d",
+				__func__, i);
+			usb_kill_urb(ubc->isoinurbs[i]);
+			usb_free_urb(ubc->isoinurbs[i]);
+		}
+	tasklet_kill(&ubc->sent_tasklet);
+	tasklet_kill(&ubc->rcvd_tasklet);
+	kfree(ubc->isooutbuf);
+	kfree(ubc);
 	bcs->hw.bas = NULL;
 	return 1;
 }
@@ -1947,7 +1956,7 @@
 		return 0;
 	}
 	tasklet_init(&ubc->sent_tasklet,
-	             &write_iso_tasklet, (unsigned long) bcs);
+		     &write_iso_tasklet, (unsigned long) bcs);
 
 	spin_lock_init(&ubc->isoinlock);
 	for (i = 0; i < BAS_INURBS; ++i)
@@ -1968,7 +1977,7 @@
 	ubc->shared0s = 0;
 	ubc->stolen0s = 0;
 	tasklet_init(&ubc->rcvd_tasklet,
-	             &read_iso_tasklet, (unsigned long) bcs);
+		     &read_iso_tasklet, (unsigned long) bcs);
 	return 1;
 }
 
@@ -1986,13 +1995,9 @@
 
 static void gigaset_freecshw(struct cardstate *cs)
 {
-	struct bas_cardstate *ucs = cs->hw.bas;
-
-	del_timer(&ucs->timer_ctrl);
-	del_timer(&ucs->timer_atrdy);
-	del_timer(&ucs->timer_cmd_in);
-
+	/* timers, URBs and rcvbuf are disposed of in disconnect */
 	kfree(cs->hw.bas);
+	cs->hw.bas = NULL;
 }
 
 static int gigaset_initcshw(struct cardstate *cs)
@@ -2027,57 +2032,56 @@
  */
 static void freeurbs(struct cardstate *cs)
 {
-	struct bas_cardstate *ucs;
+	struct bas_cardstate *ucs = cs->hw.bas;
 	struct bas_bc_state *ubc;
 	int i, j;
 
-	IFNULLRET(cs);
-	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
-
 	for (j = 0; j < 2; ++j) {
 		ubc = cs->bcs[j].hw.bas;
-		IFNULLCONT(ubc);
 		for (i = 0; i < BAS_OUTURBS; ++i)
 			if (ubc->isoouturbs[i].urb) {
 				usb_kill_urb(ubc->isoouturbs[i].urb);
-				dbg(DEBUG_INIT,
-				    "%s: isoc output URB %d/%d unlinked",
-				    __func__, j, i);
+				gig_dbg(DEBUG_INIT,
+					"%s: isoc output URB %d/%d unlinked",
+					__func__, j, i);
 				usb_free_urb(ubc->isoouturbs[i].urb);
 				ubc->isoouturbs[i].urb = NULL;
 			}
 		for (i = 0; i < BAS_INURBS; ++i)
 			if (ubc->isoinurbs[i]) {
 				usb_kill_urb(ubc->isoinurbs[i]);
-				dbg(DEBUG_INIT,
-				    "%s: isoc input URB %d/%d unlinked",
-				    __func__, j, i);
+				gig_dbg(DEBUG_INIT,
+					"%s: isoc input URB %d/%d unlinked",
+					__func__, j, i);
 				usb_free_urb(ubc->isoinurbs[i]);
 				ubc->isoinurbs[i] = NULL;
 			}
 	}
 	if (ucs->urb_int_in) {
 		usb_kill_urb(ucs->urb_int_in);
-		dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__);
+		gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked",
+			__func__);
 		usb_free_urb(ucs->urb_int_in);
 		ucs->urb_int_in = NULL;
 	}
 	if (ucs->urb_cmd_out) {
 		usb_kill_urb(ucs->urb_cmd_out);
-		dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__);
+		gig_dbg(DEBUG_INIT, "%s: command output URB unlinked",
+			__func__);
 		usb_free_urb(ucs->urb_cmd_out);
 		ucs->urb_cmd_out = NULL;
 	}
 	if (ucs->urb_cmd_in) {
 		usb_kill_urb(ucs->urb_cmd_in);
-		dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__);
+		gig_dbg(DEBUG_INIT, "%s: command input URB unlinked",
+			__func__);
 		usb_free_urb(ucs->urb_cmd_in);
 		ucs->urb_cmd_in = NULL;
 	}
 	if (ucs->urb_ctrl) {
 		usb_kill_urb(ucs->urb_ctrl);
-		dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__);
+		gig_dbg(DEBUG_INIT, "%s: control output URB unlinked",
+			__func__);
 		usb_free_urb(ucs->urb_ctrl);
 		ucs->urb_ctrl = NULL;
 	}
@@ -2097,35 +2101,24 @@
 	struct bas_bc_state *ubc;
 	struct usb_endpoint_descriptor *endpoint;
 	int i, j;
-	int ret;
+	int rc;
 
-	IFNULLRETVAL(udev, -ENODEV);
-
-	dbg(DEBUG_ANY,
-	    "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
-	    __func__, le16_to_cpu(udev->descriptor.idVendor),
-	    le16_to_cpu(udev->descriptor.idProduct));
-
-	/* See if the device offered us matches what we can accept */
-	if ((le16_to_cpu(udev->descriptor.idVendor)  != USB_GIGA_VENDOR_ID) ||
-	    (le16_to_cpu(udev->descriptor.idProduct) != USB_GIGA_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID &&
-	     le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) {
-		dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__);
-		return -ENODEV;
-	}
+	gig_dbg(DEBUG_ANY,
+		"%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+		__func__, le16_to_cpu(udev->descriptor.idVendor),
+		le16_to_cpu(udev->descriptor.idProduct));
 
 	/* set required alternate setting */
 	hostif = interface->cur_altsetting;
 	if (hostif->desc.bAlternateSetting != 3) {
-		dbg(DEBUG_ANY,
-		    "%s: wrong alternate setting %d - trying to switch",
-		    __func__, hostif->desc.bAlternateSetting);
+		gig_dbg(DEBUG_ANY,
+			"%s: wrong alternate setting %d - trying to switch",
+			__func__, hostif->desc.bAlternateSetting);
 		if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) {
-			warn("usb_set_interface failed, device %d interface %d altsetting %d",
-			     udev->devnum, hostif->desc.bInterfaceNumber,
-			     hostif->desc.bAlternateSetting);
+			dev_warn(&udev->dev, "usb_set_interface failed, "
+				 "device %d interface %d altsetting %d\n",
+				 udev->devnum, hostif->desc.bInterfaceNumber,
+				 hostif->desc.bAlternateSetting);
 			return -ENODEV;
 		}
 		hostif = interface->cur_altsetting;
@@ -2134,68 +2127,50 @@
 	/* Reject application specific interfaces
 	 */
 	if (hostif->desc.bInterfaceClass != 255) {
-		warn("%s: bInterfaceClass == %d",
-		     __func__, hostif->desc.bInterfaceClass);
+		dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n",
+			 __func__, hostif->desc.bInterfaceClass);
 		return -ENODEV;
 	}
 
-	info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)",
-	     __func__, le16_to_cpu(udev->descriptor.idVendor),
-	     le16_to_cpu(udev->descriptor.idProduct));
+	dev_info(&udev->dev,
+		 "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n",
+		 __func__, le16_to_cpu(udev->descriptor.idVendor),
+		 le16_to_cpu(udev->descriptor.idProduct));
 
 	cs = gigaset_getunassignedcs(driver);
 	if (!cs) {
-		err("%s: no free cardstate", __func__);
+		dev_err(&udev->dev, "no free cardstate\n");
 		return -ENODEV;
 	}
 	ucs = cs->hw.bas;
+
+	/* save off device structure ptrs for later use */
+	usb_get_dev(udev);
 	ucs->udev = udev;
 	ucs->interface = interface;
+	cs->dev = &interface->dev;
 
 	/* allocate URBs:
 	 * - one for the interrupt pipe
 	 * - three for the different uses of the default control pipe
 	 * - three for each isochronous pipe
 	 */
-	ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_int_in) {
-		err("No free urbs available");
-		goto error;
-	}
-	ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_cmd_in) {
-		err("No free urbs available");
-		goto error;
-	}
-	ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_cmd_out) {
-		err("No free urbs available");
-		goto error;
-	}
-	ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL);
-	if (!ucs->urb_ctrl) {
-		err("No free urbs available");
-		goto error;
-	}
+	if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) ||
+	    !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL)))
+		goto allocerr;
 
 	for (j = 0; j < 2; ++j) {
 		ubc = cs->bcs[j].hw.bas;
-		for (i = 0; i < BAS_OUTURBS; ++i) {
-			ubc->isoouturbs[i].urb =
-				usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
-			if (!ubc->isoouturbs[i].urb) {
-				err("No free urbs available");
-				goto error;
-			}
-		}
-		for (i = 0; i < BAS_INURBS; ++i) {
-			ubc->isoinurbs[i] =
-				usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL);
-			if (!ubc->isoinurbs[i]) {
-				err("No free urbs available");
-				goto error;
-			}
-		}
+		for (i = 0; i < BAS_OUTURBS; ++i)
+			if (!(ubc->isoouturbs[i].urb =
+			      usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+				goto allocerr;
+		for (i = 0; i < BAS_INURBS; ++i)
+			if (!(ubc->isoinurbs[i] =
+			      usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL)))
+				goto allocerr;
 	}
 
 	ucs->rcvbuf = NULL;
@@ -2204,35 +2179,37 @@
 	/* Fill the interrupt urb and send it to the core */
 	endpoint = &hostif->endpoint[0].desc;
 	usb_fill_int_urb(ucs->urb_int_in, udev,
-	                 usb_rcvintpipe(udev,
-	                                (endpoint->bEndpointAddress) & 0x0f),
-	                 ucs->int_in_buf, 3, read_int_callback, cs,
-	                 endpoint->bInterval);
-	ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL);
-	if (ret) {
-		err("could not submit interrupt URB: %s", get_usb_statmsg(ret));
+			 usb_rcvintpipe(udev,
+					(endpoint->bEndpointAddress) & 0x0f),
+			 ucs->int_in_buf, 3, read_int_callback, cs,
+			 endpoint->bInterval);
+	if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) {
+		dev_err(cs->dev, "could not submit interrupt URB: %s\n",
+			get_usb_rcmsg(rc));
 		goto error;
 	}
 
 	/* tell the device that the driver is ready */
-	if ((ret = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
+	if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
 		goto error;
 
 	/* tell common part that the device is ready */
 	if (startmode == SM_LOCKED)
 		atomic_set(&cs->mstate, MS_LOCKED);
-	if (!gigaset_start(cs))
-		goto error;
 
 	/* save address of controller structure */
 	usb_set_intfdata(interface, cs);
 
-	/* set up device sysfs */
-	gigaset_init_dev_sysfs(interface);
+	if (!gigaset_start(cs))
+		goto error;
+
 	return 0;
 
+allocerr:
+	dev_err(cs->dev, "could not allocate URBs\n");
 error:
 	freeurbs(cs);
+	usb_set_intfdata(interface, NULL);
 	gigaset_unassign(cs);
 	return -ENODEV;
 }
@@ -2244,24 +2221,38 @@
 {
 	struct cardstate *cs;
 	struct bas_cardstate *ucs;
-
-	/* clear device sysfs */
-	gigaset_free_dev_sysfs(interface);
+	int j;
 
 	cs = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
 
-	IFNULLRET(cs);
 	ucs = cs->hw.bas;
-	IFNULLRET(ucs);
 
-	info("disconnecting GigaSet base");
+	dev_info(cs->dev, "disconnecting Gigaset base\n");
+
+	/* mark base as not ready, all channels disconnected */
+	atomic_set(&ucs->basstate, 0);
+
+	/* tell LL all channels are down */
+	//FIXME shouldn't gigaset_stop() do this?
+	for (j = 0; j < 2; ++j)
+		gigaset_bchannel_down(cs->bcs + j);
+
+	/* stop driver (common part) */
 	gigaset_stop(cs);
+
+	/* stop timers and URBs, free ressources */
+	del_timer_sync(&ucs->timer_ctrl);
+	del_timer_sync(&ucs->timer_atrdy);
+	del_timer_sync(&ucs->timer_cmd_in);
 	freeurbs(cs);
+	usb_set_intfdata(interface, NULL);
 	kfree(ucs->rcvbuf);
 	ucs->rcvbuf = NULL;
 	ucs->rcvbuf_size = 0;
-	atomic_set(&ucs->basstate, 0);
+	usb_put_dev(ucs->udev);
+	ucs->interface = NULL;
+	ucs->udev = NULL;
+	cs->dev = NULL;
 	gigaset_unassign(cs);
 }
 
@@ -2293,13 +2284,14 @@
 
 	/* allocate memory for our driver state and intialize it */
 	if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
-	                               GIGASET_MODULENAME, GIGASET_DEVNAME,
-	                               GIGASET_DEVFSNAME, &gigops,
-	                               THIS_MODULE)) == NULL)
+				       GIGASET_MODULENAME, GIGASET_DEVNAME,
+				       GIGASET_DEVFSNAME, &gigops,
+				       THIS_MODULE)) == NULL)
 		goto error;
 
 	/* allocate memory for our device state and intialize it */
-	cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME);
+	cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode,
+				   GIGASET_MODULENAME);
 	if (!cardstate)
 		goto error;
 
@@ -2328,22 +2320,35 @@
  */
 static void __exit bas_gigaset_exit(void)
 {
+	struct bas_cardstate *ucs = cardstate->hw.bas;
+
 	gigaset_blockdriver(driver); /* => probe will fail
-	                              * => no gigaset_start any more
-	                              */
+				      * => no gigaset_start any more
+				      */
 
 	gigaset_shutdown(cardstate);
 	/* from now on, no isdn callback should be possible */
 
-	if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) {
-		dbg(DEBUG_ANY, "closing AT channel");
-		if (req_submit(cardstate->bcs,
-		               HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) {
-			/* successfully submitted - wait for completion */
-			//wait_event_interruptible(cs->initwait, !cs->hw.bas->pending);
-			//FIXME need own wait queue? wakeup?
-		}
+	/* close all still open channels */
+	if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
+		gig_dbg(DEBUG_INIT, "closing B1 channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
 	}
+	if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
+		gig_dbg(DEBUG_INIT, "closing B2 channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
+	}
+	if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
+		gig_dbg(DEBUG_INIT, "closing AT channel");
+		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
+				HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
+				NULL, 0, BAS_TIMEOUT);
+	}
+	atomic_set(&ucs->basstate, 0);
 
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&gigaset_usb_driver);
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 6437199..e55767b 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1,7 +1,7 @@
 /*
  * Stuff used by all variants of the driver
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
  *                       Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>.
  *
@@ -11,10 +11,6 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -23,7 +19,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
 #define DRIVER_DESC "Driver for Gigaset 307x"
 
 /* Module parameters */
@@ -32,21 +28,10 @@
 module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug, "debug level");
 
-/*======================================================================
-  Prototypes of internal functions
- */
-
-//static void gigaset_process_response(int resp_code, int parameter,
-//                                     struct at_state_t *at_state,
-//                                     unsigned char ** pstring);
-static struct cardstate *alloc_cs(struct gigaset_driver *drv);
-static void free_cs(struct cardstate *cs);
-static void make_valid(struct cardstate *cs, unsigned mask);
-static void make_invalid(struct cardstate *cs, unsigned mask);
-
-#define VALID_MINOR       0x01
-#define VALID_ID          0x02
-#define ASSIGNED          0x04
+/* driver state flags */
+#define VALID_MINOR	0x01
+#define VALID_ID	0x02
+#define ASSIGNED	0x04
 
 /* bitwise byte inversion table */
 __u8 gigaset_invtab[256] = {
@@ -86,42 +71,40 @@
 EXPORT_SYMBOL_GPL(gigaset_invtab);
 
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
-                        size_t len, const unsigned char *buf, int from_user)
+			size_t len, const unsigned char *buf)
 {
 	unsigned char outbuf[80];
-	unsigned char inbuf[80 - 1];
-	size_t numin;
-	const unsigned char *in;
+	unsigned char c;
 	size_t space = sizeof outbuf - 1;
 	unsigned char *out = outbuf;
+	size_t numin = len;
 
-	if (!from_user) {
-		in = buf;
-		numin = len;
-	} else {
-		numin = len < sizeof inbuf ? len : sizeof inbuf;
-		in = inbuf;
-		if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) {
-			strncpy(inbuf, "<FAULT>", sizeof inbuf);
-			numin = sizeof "<FAULT>" - 1;
+	while (numin--) {
+		c = *buf++;
+		if (c == '~' || c == '^' || c == '\\') {
+			if (!space--)
+				break;
+			*out++ = '\\';
 		}
-	}
-
-	for (; numin && space; --numin, ++in) {
-		--space;
-		if (*in >= 32)
-			*out++ = *in;
-		else {
+		if (c & 0x80) {
+			if (!space--)
+				break;
+			*out++ = '~';
+			c ^= 0x80;
+		}
+		if (c < 0x20 || c == 0x7f) {
+			if (!space--)
+				break;
 			*out++ = '^';
-			if (space) {
-				*out++ = '@' + *in;
-				--space;
-			}
+			c ^= 0x40;
 		}
+		if (!space--)
+			break;
+		*out++ = c;
 	}
 	*out = 0;
 
-	dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
+	gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
 }
 EXPORT_SYMBOL_GPL(gigaset_dbg_buffer);
 
@@ -146,11 +129,6 @@
 {
 	int i, r;
 
-	if (!atomic_read(&cs->connected)) {
-		err("not connected!");
-		return -1;
-	}
-
 	cs->control_state = TIOCM_RTS; //FIXME
 
 	r = setflags(cs, TIOCM_DTR, 200);
@@ -174,7 +152,7 @@
 	return 0;
 
 error:
-	err("error %d on setuartbits!\n", -r);
+	dev_err(cs->dev, "error %d on setuartbits\n", -r);
 	cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
 	cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);
 
@@ -187,13 +165,13 @@
 		return 0;
 
 	if (--at_state->timer_expires) {
-		dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
-		    at_state, at_state->timer_expires);
+		gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
+			at_state, at_state->timer_expires);
 		return 0;
 	}
 
 	if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
-	                       atomic_read(&at_state->timer_index), NULL)) {
+			       at_state->timer_index, NULL)) {
 		//FIXME what should we do?
 	}
 
@@ -221,10 +199,10 @@
 		if (test_timeout(at_state))
 			timeout = 1;
 
-	if (atomic_read(&cs->running)) {
-		mod_timer(&cs->timer, jiffies + GIG_TICK);
+	if (cs->running) {
+		mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
 		if (timeout) {
-			dbg(DEBUG_CMD, "scheduling timeout");
+			gig_dbg(DEBUG_CMD, "scheduling timeout");
 			tasklet_schedule(&cs->event_tasklet);
 		}
 	}
@@ -238,13 +216,14 @@
 
 	spin_lock_irqsave(&bcs->cs->lock, flags);
 	if (bcs->use_count) {
-		dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel);
+		gig_dbg(DEBUG_ANY, "could not allocate channel %d",
+			bcs->channel);
 		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		return 0;
 	}
 	++bcs->use_count;
 	bcs->busy = 1;
-	dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
+	gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
 	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 	return 1;
 }
@@ -255,13 +234,13 @@
 
 	spin_lock_irqsave(&bcs->cs->lock, flags);
 	if (!bcs->busy) {
-		dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
+		gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
 		spin_unlock_irqrestore(&bcs->cs->lock, flags);
 		return;
 	}
 	--bcs->use_count;
 	bcs->busy = 0;
-	dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
+	gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
 	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 }
 
@@ -274,14 +253,14 @@
 	for (i = 0; i < cs->channels; ++i)
 		if (cs->bcs[i].use_count) {
 			spin_unlock_irqrestore(&cs->lock, flags);
-			dbg(DEBUG_ANY, "could not allocated all channels");
+			gig_dbg(DEBUG_ANY, "could not allocate all channels");
 			return 0;
 		}
 	for (i = 0; i < cs->channels; ++i)
 		++cs->bcs[i].use_count;
 	spin_unlock_irqrestore(&cs->lock, flags);
 
-	dbg(DEBUG_ANY, "allocated all channels");
+	gig_dbg(DEBUG_ANY, "allocated all channels");
 
 	return 1;
 }
@@ -291,7 +270,7 @@
 	unsigned long flags;
 	int i;
 
-	dbg(DEBUG_ANY, "unblocking all channels");
+	gig_dbg(DEBUG_ANY, "unblocking all channels");
 	spin_lock_irqsave(&cs->lock, flags);
 	for (i = 0; i < cs->channels; ++i)
 		--cs->bcs[i].use_count;
@@ -303,7 +282,7 @@
 	unsigned long flags;
 	int i;
 
-	dbg(DEBUG_ANY, "blocking all channels");
+	gig_dbg(DEBUG_ANY, "blocking all channels");
 	spin_lock_irqsave(&cs->lock, flags);
 	for (i = 0; i < cs->channels; ++i)
 		++cs->bcs[i].use_count;
@@ -314,25 +293,27 @@
 {
 	struct event_t *ev;
 	unsigned head, tail;
+	unsigned long flags;
 
-	/* no locking needed (no reader/writer allowed) */
+	spin_lock_irqsave(&cs->ev_lock, flags);
 
-	head = atomic_read(&cs->ev_head);
-	tail = atomic_read(&cs->ev_tail);
+	head = cs->ev_head;
+	tail = cs->ev_tail;
 
 	while (tail != head) {
 		ev = cs->events + head;
 		kfree(ev->ptr);
-
 		head = (head + 1) % MAX_EVENTS;
 	}
 
-	atomic_set(&cs->ev_head, tail);
+	cs->ev_head = tail;
+
+	spin_unlock_irqrestore(&cs->ev_lock, flags);
 }
 
 struct event_t *gigaset_add_event(struct cardstate *cs,
-                                  struct at_state_t *at_state, int type,
-                                  void *ptr, int parameter, void *arg)
+				  struct at_state_t *at_state, int type,
+				  void *ptr, int parameter, void *arg)
 {
 	unsigned long flags;
 	unsigned next, tail;
@@ -340,9 +321,9 @@
 
 	spin_lock_irqsave(&cs->ev_lock, flags);
 
-	tail = atomic_read(&cs->ev_tail);
+	tail = cs->ev_tail;
 	next = (tail + 1) % MAX_EVENTS;
-	if (unlikely(next == atomic_read(&cs->ev_head)))
+	if (unlikely(next == cs->ev_head))
 		err("event queue full");
 	else {
 		event = cs->events + tail;
@@ -352,7 +333,7 @@
 		event->ptr = ptr;
 		event->arg = arg;
 		event->parameter = parameter;
-		atomic_set(&cs->ev_tail, next);
+		cs->ev_tail = next;
 	}
 
 	spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -391,14 +372,14 @@
 {
 	int i;
 
-	dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
+	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
 	if (!bcs->cs->ops->freebcshw(bcs)) {
-		dbg(DEBUG_INIT, "failed");
+		gig_dbg(DEBUG_INIT, "failed");
 	}
 
-	dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
+	gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
 	clear_at_state(&bcs->at_state);
-	dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
+	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
 
 	if (bcs->skb)
 		dev_kfree_skb(bcs->skb);
@@ -408,6 +389,52 @@
 	}
 }
 
+static struct cardstate *alloc_cs(struct gigaset_driver *drv)
+{
+	unsigned long flags;
+	unsigned i;
+	static struct cardstate *ret = NULL;
+
+	spin_lock_irqsave(&drv->lock, flags);
+	for (i = 0; i < drv->minors; ++i) {
+		if (!(drv->flags[i] & VALID_MINOR)) {
+			drv->flags[i] = VALID_MINOR;
+			ret = drv->cs + i;
+		}
+		if (ret)
+			break;
+	}
+	spin_unlock_irqrestore(&drv->lock, flags);
+	return ret;
+}
+
+static void free_cs(struct cardstate *cs)
+{
+	unsigned long flags;
+	struct gigaset_driver *drv = cs->driver;
+	spin_lock_irqsave(&drv->lock, flags);
+	drv->flags[cs->minor_index] = 0;
+	spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_valid(struct cardstate *cs, unsigned mask)
+{
+	unsigned long flags;
+	struct gigaset_driver *drv = cs->driver;
+	spin_lock_irqsave(&drv->lock, flags);
+	drv->flags[cs->minor_index] |= mask;
+	spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static void make_invalid(struct cardstate *cs, unsigned mask)
+{
+	unsigned long flags;
+	struct gigaset_driver *drv = cs->driver;
+	spin_lock_irqsave(&drv->lock, flags);
+	drv->flags[cs->minor_index] &= ~mask;
+	spin_unlock_irqrestore(&drv->lock, flags);
+}
+
 void gigaset_freecs(struct cardstate *cs)
 {
 	int i;
@@ -416,7 +443,7 @@
 	if (!cs)
 		return;
 
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	if (!cs->bcs)
 		goto f_cs;
@@ -424,8 +451,9 @@
 		goto f_bcs;
 
 	spin_lock_irqsave(&cs->lock, flags);
-	atomic_set(&cs->running, 0);
-	spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */
+	cs->running = 0;
+	spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
+						     not rescheduled below */
 
 	tasklet_kill(&cs->event_tasklet);
 	del_timer_sync(&cs->timer);
@@ -434,7 +462,7 @@
 	default:
 		gigaset_if_free(cs);
 
-		dbg(DEBUG_INIT, "clearing hw");
+		gig_dbg(DEBUG_INIT, "clearing hw");
 		cs->ops->freecshw(cs);
 
 		//FIXME cmdbuf
@@ -443,36 +471,36 @@
 	case 2: /* error in initcshw */
 		/* Deregister from LL */
 		make_invalid(cs, VALID_ID);
-		dbg(DEBUG_INIT, "clearing iif");
+		gig_dbg(DEBUG_INIT, "clearing iif");
 		gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
 
 		/* fall through */
 	case 1: /* error when regestering to LL */
-		dbg(DEBUG_INIT, "clearing at_state");
+		gig_dbg(DEBUG_INIT, "clearing at_state");
 		clear_at_state(&cs->at_state);
 		dealloc_at_states(cs);
 
 		/* fall through */
 	case 0: /* error in one call to initbcs */
 		for (i = 0; i < cs->channels; ++i) {
-			dbg(DEBUG_INIT, "clearing bcs[%d]", i);
+			gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
 			gigaset_freebcs(cs->bcs + i);
 		}
 
 		clear_events(cs);
-		dbg(DEBUG_INIT, "freeing inbuf");
+		gig_dbg(DEBUG_INIT, "freeing inbuf");
 		kfree(cs->inbuf);
 	}
-f_bcs:	dbg(DEBUG_INIT, "freeing bcs[]");
+f_bcs:	gig_dbg(DEBUG_INIT, "freeing bcs[]");
 	kfree(cs->bcs);
-f_cs:	dbg(DEBUG_INIT, "freeing cs");
-	up(&cs->sem);
+f_cs:	gig_dbg(DEBUG_INIT, "freeing cs");
+	mutex_unlock(&cs->mutex);
 	free_cs(cs);
 }
 EXPORT_SYMBOL_GPL(gigaset_freecs);
 
 void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
-                     struct cardstate *cs, int cid)
+		     struct cardstate *cs, int cid)
 {
 	int i;
 
@@ -482,8 +510,8 @@
 	at_state->pending_commands = 0;
 	at_state->timer_expires = 0;
 	at_state->timer_active = 0;
-	atomic_set(&at_state->timer_index, 0);
-	atomic_set(&at_state->seq_index, 0);
+	at_state->timer_index = 0;
+	at_state->seq_index = 0;
 	at_state->ConState = 0;
 	for (i = 0; i < STR_NUM; ++i)
 		at_state->str_var[i] = NULL;
@@ -501,7 +529,7 @@
 
 
 static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
-                               struct cardstate *cs, int inputstate)
+			       struct cardstate *cs, int inputstate)
 /* inbuf->read must be allocated before! */
 {
 	atomic_set(&inbuf->head, 0);
@@ -512,9 +540,50 @@
 	inbuf->inputstate = inputstate;
 }
 
+/* append received bytes to inbuf */
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+		       unsigned numbytes)
+{
+	unsigned n, head, tail, bytesleft;
+
+	gig_dbg(DEBUG_INTR, "received %u bytes", numbytes);
+
+	if (!numbytes)
+		return 0;
+
+	bytesleft = numbytes;
+	tail = atomic_read(&inbuf->tail);
+	head = atomic_read(&inbuf->head);
+	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+
+	while (bytesleft) {
+		if (head > tail)
+			n = head - 1 - tail;
+		else if (head == 0)
+			n = (RBUFSIZE-1) - tail;
+		else
+			n = RBUFSIZE - tail;
+		if (!n) {
+			dev_err(inbuf->cs->dev,
+				"buffer overflow (%u bytes lost)", bytesleft);
+			break;
+		}
+		if (n > bytesleft)
+			n = bytesleft;
+		memcpy(inbuf->data + tail, src, n);
+		bytesleft -= n;
+		tail = (tail + n) % RBUFSIZE;
+		src += n;
+	}
+	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
+	atomic_set(&inbuf->tail, tail);
+	return numbytes != bytesleft;
+}
+EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
+
 /* Initialize the b-channel structure */
 static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
-                                        struct cardstate *cs, int channel)
+					struct cardstate *cs, int channel)
 {
 	int i;
 
@@ -526,7 +595,7 @@
 	bcs->trans_down = 0;
 	bcs->trans_up = 0;
 
-	dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
+	gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
 	gigaset_at_init(&bcs->at_state, bcs, cs, -1);
 
 	bcs->rcvbytes = 0;
@@ -535,7 +604,7 @@
 	bcs->emptycount = 0;
 #endif
 
-	dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
+	gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
 	bcs->fcs = PPP_INITFCS;
 	bcs->inputstate = 0;
 	if (cs->ignoreframes) {
@@ -544,7 +613,7 @@
 	} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
 		skb_reserve(bcs->skb, HW_HDR_LEN);
 	else {
-		warn("could not allocate skb");
+		dev_warn(cs->dev, "could not allocate skb\n");
 		bcs->inputstate |= INS_skip_frame;
 	}
 
@@ -559,14 +628,13 @@
 	for (i = 0; i < AT_NUM; ++i)
 		bcs->commands[i] = NULL;
 
-	dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
+	gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
 	if (cs->ops->initbcshw(bcs))
 		return bcs;
 
-//error:
-	dbg(DEBUG_INIT, "  failed");
+	gig_dbg(DEBUG_INIT, "  failed");
 
-	dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
+	gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
 	if (bcs->skb)
 		dev_kfree_skb(bcs->skb);
 
@@ -578,9 +646,10 @@
  * Calls hardware dependent gigaset_initcshw() function
  * Calls B channel initialization function gigaset_initbcs() for each B channel
  * parameters:
- *      drv		hardware driver the device belongs to
+ *	drv		hardware driver the device belongs to
  *	channels	number of B channels supported by device
- *	onechannel	!=0: B channel data and AT commands share one communication channel
+ *	onechannel	!=0: B channel data and AT commands share one
+ *			     communication channel
  *			==0: B channels have separate communication channels
  *	ignoreframes	number of frames to ignore after setting up B channel
  *	cidmode		!=0: start in CallID mode
@@ -593,17 +662,18 @@
 				 int cidmode, const char *modulename)
 {
 	struct cardstate *cs = NULL;
+	unsigned long flags;
 	int i;
 
-	dbg(DEBUG_INIT, "allocating cs");
+	gig_dbg(DEBUG_INIT, "allocating cs");
 	cs = alloc_cs(drv);
 	if (!cs)
 		goto error;
-	dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
+	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
 	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
 	if (!cs->bcs)
 		goto error;
-	dbg(DEBUG_INIT, "allocating inbuf");
+	gig_dbg(DEBUG_INIT, "allocating inbuf");
 	cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
 	if (!cs->inbuf)
 		goto error;
@@ -613,19 +683,23 @@
 	cs->onechannel = onechannel;
 	cs->ignoreframes = ignoreframes;
 	INIT_LIST_HEAD(&cs->temp_at_states);
-	atomic_set(&cs->running, 0);
+	cs->running = 0;
 	init_timer(&cs->timer); /* clear next & prev */
 	spin_lock_init(&cs->ev_lock);
-	atomic_set(&cs->ev_tail, 0);
-	atomic_set(&cs->ev_head, 0);
-	init_MUTEX_LOCKED(&cs->sem);
-	tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs);
+	cs->ev_tail = 0;
+	cs->ev_head = 0;
+	mutex_init(&cs->mutex);
+	mutex_lock(&cs->mutex);
+
+	tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
+		     (unsigned long) cs);
 	atomic_set(&cs->commands_pending, 0);
 	cs->cur_at_seq = 0;
 	cs->gotfwver = -1;
 	cs->open_count = 0;
+	cs->dev = NULL;
 	cs->tty = NULL;
-	atomic_set(&cs->cidmode, cidmode != 0);
+	cs->cidmode = cidmode != 0;
 
 	//if(onechannel) { //FIXME
 		cs->tabnocid = gigaset_tab_nocid_m10x;
@@ -642,50 +716,43 @@
 	atomic_set(&cs->mstate, MS_UNINITIALIZED);
 
 	for (i = 0; i < channels; ++i) {
-		dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
+		gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
 		if (!gigaset_initbcs(cs->bcs + i, cs, i))
 			goto error;
 	}
 
 	++cs->cs_init;
 
-	dbg(DEBUG_INIT, "setting up at_state");
+	gig_dbg(DEBUG_INIT, "setting up at_state");
 	spin_lock_init(&cs->lock);
 	gigaset_at_init(&cs->at_state, NULL, cs, 0);
 	cs->dle = 0;
 	cs->cbytes = 0;
 
-	dbg(DEBUG_INIT, "setting up inbuf");
+	gig_dbg(DEBUG_INIT, "setting up inbuf");
 	if (onechannel) {			//FIXME distinction necessary?
 		gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
 	} else
 		gigaset_inbuf_init(cs->inbuf, NULL,    cs, INS_command);
 
-	atomic_set(&cs->connected, 0);
+	cs->connected = 0;
+	cs->isdn_up = 0;
 
-	dbg(DEBUG_INIT, "setting up cmdbuf");
+	gig_dbg(DEBUG_INIT, "setting up cmdbuf");
 	cs->cmdbuf = cs->lastcmdbuf = NULL;
 	spin_lock_init(&cs->cmdlock);
 	cs->curlen = 0;
 	cs->cmdbytes = 0;
 
-	/*
-	 * Tell the ISDN4Linux subsystem (the LL) that
-	 * a driver for a USB-Device is available !
-	 * If this is done, "isdnctrl" is able to bind a device for this driver even
-	 * if no physical usb-device is currently connected.
-	 * But this device will just be accessable if a physical USB device is connected
-	 * (via "gigaset_probe") .
-	 */
-	dbg(DEBUG_INIT, "setting up iif");
+	gig_dbg(DEBUG_INIT, "setting up iif");
 	if (!gigaset_register_to_LL(cs, modulename)) {
-		err("register_isdn=>error");
+		err("register_isdn failed");
 		goto error;
 	}
 
 	make_valid(cs, VALID_ID);
 	++cs->cs_init;
-	dbg(DEBUG_INIT, "setting up hw");
+	gig_dbg(DEBUG_INIT, "setting up hw");
 	if (!cs->ops->initcshw(cs))
 		goto error;
 
@@ -693,27 +760,28 @@
 
 	gigaset_if_init(cs);
 
-	atomic_set(&cs->running, 1);
-	cs->timer.data = (unsigned long) cs;
-	cs->timer.function = timer_tick;
-	cs->timer.expires = jiffies + GIG_TICK;
+	spin_lock_irqsave(&cs->lock, flags);
+	cs->running = 1;
+	spin_unlock_irqrestore(&cs->lock, flags);
+	setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
+	cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
 	/* FIXME: can jiffies increase too much until the timer is added?
 	 * Same problem(?) with mod_timer() in timer_tick(). */
 	add_timer(&cs->timer);
 
-	dbg(DEBUG_INIT, "cs initialized!");
-	up(&cs->sem);
+	gig_dbg(DEBUG_INIT, "cs initialized");
+	mutex_unlock(&cs->mutex);
 	return cs;
 
 error:	if (cs)
-		up(&cs->sem);
-	dbg(DEBUG_INIT, "failed");
+		mutex_unlock(&cs->mutex);
+	gig_dbg(DEBUG_INIT, "failed");
 	gigaset_freecs(cs);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(gigaset_initcs);
 
-/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */
+/* ReInitialize the b-channel structure on hangup */
 void gigaset_bcs_reinit(struct bc_state *bcs)
 {
 	struct sk_buff *skb;
@@ -723,12 +791,12 @@
 	while ((skb = skb_dequeue(&bcs->squeue)) != NULL)
 		dev_kfree_skb(skb);
 
-	spin_lock_irqsave(&cs->lock, flags); //FIXME
+	spin_lock_irqsave(&cs->lock, flags);
 	clear_at_state(&bcs->at_state);
 	bcs->at_state.ConState = 0;
 	bcs->at_state.timer_active = 0;
 	bcs->at_state.timer_expires = 0;
-	bcs->at_state.cid = -1;                     /* No CID defined */
+	bcs->at_state.cid = -1;			/* No CID defined */
 	spin_unlock_irqrestore(&cs->lock, flags);
 
 	bcs->inputstate = 0;
@@ -803,11 +871,14 @@
 
 int gigaset_start(struct cardstate *cs)
 {
-	if (down_interruptible(&cs->sem))
-		return 0;
-	//info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor);
+	unsigned long flags;
 
-	atomic_set(&cs->connected, 1);
+	if (mutex_lock_interruptible(&cs->mutex))
+		return 0;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	cs->connected = 1;
+	spin_unlock_irqrestore(&cs->lock, flags);
 
 	if (atomic_read(&cs->mstate) != MS_LOCKED) {
 		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
@@ -826,23 +897,26 @@
 		goto error;
 	}
 
-	dbg(DEBUG_CMD, "scheduling START");
+	gig_dbg(DEBUG_CMD, "scheduling START");
 	gigaset_schedule_event(cs);
 
 	wait_event(cs->waitqueue, !cs->waiting);
 
-	up(&cs->sem);
+	/* set up device sysfs */
+	gigaset_init_dev_sysfs(cs);
+
+	mutex_unlock(&cs->mutex);
 	return 1;
 
 error:
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gigaset_start);
 
 void gigaset_shutdown(struct cardstate *cs)
 {
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	cs->waiting = 1;
 
@@ -851,11 +925,11 @@
 		goto exit;
 	}
 
-	dbg(DEBUG_CMD, "scheduling SHUTDOWN");
+	gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
 	gigaset_schedule_event(cs);
 
 	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("aborted");
+		warn("%s: aborted", __func__);
 		//FIXME
 	}
 
@@ -872,15 +946,13 @@
 	cleanup_cs(cs);
 
 exit:
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 EXPORT_SYMBOL_GPL(gigaset_shutdown);
 
 void gigaset_stop(struct cardstate *cs)
 {
-	down(&cs->sem);
-
-	atomic_set(&cs->connected, 0);
+	mutex_lock(&cs->mutex);
 
 	cs->waiting = 1;
 
@@ -889,21 +961,21 @@
 		goto exit;
 	}
 
-	dbg(DEBUG_CMD, "scheduling STOP");
+	gig_dbg(DEBUG_CMD, "scheduling STOP");
 	gigaset_schedule_event(cs);
 
 	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("aborted");
+		warn("%s: aborted", __func__);
 		//FIXME
 	}
 
-	/* Tell the LL that the device is not available .. */
-	gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer?
+	/* clear device sysfs */
+	gigaset_free_dev_sysfs(cs);
 
 	cleanup_cs(cs);
 
 exit:
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 EXPORT_SYMBOL_GPL(gigaset_stop);
 
@@ -947,31 +1019,25 @@
 
 	spin_lock_irqsave(&driver_lock, flags);
 	list_for_each_entry(drv, &drivers, list) {
-		dbg(DEBUG_DRIVER, "driver %p", drv);
+		gig_dbg(DEBUG_DRIVER, "driver %p", drv);
 		spin_lock(&drv->lock);
 		for (i = 0; i < drv->minors; ++i) {
-			dbg(DEBUG_DRIVER, "  index %u", i);
-			dbg(DEBUG_DRIVER, "    flags 0x%02x", drv->flags[i]);
+			gig_dbg(DEBUG_DRIVER, "  index %u", i);
+			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x",
+				drv->flags[i]);
 			cs = drv->cs + i;
-			dbg(DEBUG_DRIVER, "    cardstate %p", cs);
-			dbg(DEBUG_DRIVER, "    minor_index %u", cs->minor_index);
-			dbg(DEBUG_DRIVER, "    driver %p", cs->driver);
-			dbg(DEBUG_DRIVER, "    i4l id %d", cs->myid);
+			gig_dbg(DEBUG_DRIVER, "    cardstate %p", cs);
+			gig_dbg(DEBUG_DRIVER, "    minor_index %u",
+				cs->minor_index);
+			gig_dbg(DEBUG_DRIVER, "    driver %p", cs->driver);
+			gig_dbg(DEBUG_DRIVER, "    i4l id %d", cs->myid);
 		}
 		spin_unlock(&drv->lock);
 	}
 	spin_unlock_irqrestore(&driver_lock, flags);
 }
-EXPORT_SYMBOL_GPL(gigaset_debugdrivers);
 
-struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
-{
-	if (tty->index < 0 || tty->index >= tty->driver->num)
-		return NULL;
-	return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
-}
-
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
+static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
 {
 	unsigned long flags;
 	static struct cardstate *ret = NULL;
@@ -994,6 +1060,13 @@
 	return ret;
 }
 
+struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
+{
+	if (tty->index < 0 || tty->index >= tty->driver->num)
+		return NULL;
+	return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
+}
+
 void gigaset_freedriver(struct gigaset_driver *drv)
 {
 	unsigned long flags;
@@ -1014,20 +1087,20 @@
 /* gigaset_initdriver
  * Allocate and initialize gigaset_driver structure. Initialize interface.
  * parameters:
- *      minor           First minor number
- *      minors          Number of minors this driver can handle
- *      procname        Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver)
- *      devname         Name of the device files (prefix without minor number)
- *      devfsname       Devfs name of the device files without %d
+ *	minor		First minor number
+ *	minors		Number of minors this driver can handle
+ *	procname	Name of the driver
+ *	devname		Name of the device files (prefix without minor number)
+ *	devfsname	Devfs name of the device files without %d
  * return value:
- *      Pointer to the gigaset_driver structure on success, NULL on failure.
+ *	Pointer to the gigaset_driver structure on success, NULL on failure.
  */
 struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
-                                          const char *procname,
-                                          const char *devname,
-                                          const char *devfsname,
-                                          const struct gigaset_ops *ops,
-                                          struct module *owner)
+					  const char *procname,
+					  const char *devname,
+					  const char *devfsname,
+					  const struct gigaset_ops *ops,
+					  struct module *owner)
 {
 	struct gigaset_driver *drv;
 	unsigned long flags;
@@ -1036,8 +1109,9 @@
 	drv = kmalloc(sizeof *drv, GFP_KERNEL);
 	if (!drv)
 		return NULL;
+
 	if (!try_module_get(owner))
-		return NULL;
+		goto out1;
 
 	drv->cs = NULL;
 	drv->have_tty = 0;
@@ -1051,10 +1125,11 @@
 
 	drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
 	if (!drv->cs)
-		goto out1;
+		goto out2;
+
 	drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
 	if (!drv->flags)
-		goto out2;
+		goto out3;
 
 	for (i = 0; i < minors; ++i) {
 		drv->flags[i] = 0;
@@ -1071,61 +1146,16 @@
 
 	return drv;
 
-out2:
+out3:
 	kfree(drv->cs);
+out2:
+	module_put(owner);
 out1:
 	kfree(drv);
-	module_put(owner);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(gigaset_initdriver);
 
-static struct cardstate *alloc_cs(struct gigaset_driver *drv)
-{
-	unsigned long flags;
-	unsigned i;
-	static struct cardstate *ret = NULL;
-
-	spin_lock_irqsave(&drv->lock, flags);
-	for (i = 0; i < drv->minors; ++i) {
-		if (!(drv->flags[i] & VALID_MINOR)) {
-			drv->flags[i] = VALID_MINOR;
-			ret = drv->cs + i;
-		}
-		if (ret)
-			break;
-	}
-	spin_unlock_irqrestore(&drv->lock, flags);
-	return ret;
-}
-
-static void free_cs(struct cardstate *cs)
-{
-	unsigned long flags;
-	struct gigaset_driver *drv = cs->driver;
-	spin_lock_irqsave(&drv->lock, flags);
-	drv->flags[cs->minor_index] = 0;
-	spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_valid(struct cardstate *cs, unsigned mask)
-{
-	unsigned long flags;
-	struct gigaset_driver *drv = cs->driver;
-	spin_lock_irqsave(&drv->lock, flags);
-	drv->flags[cs->minor_index] |= mask;
-	spin_unlock_irqrestore(&drv->lock, flags);
-}
-
-static void make_invalid(struct cardstate *cs, unsigned mask)
-{
-	unsigned long flags;
-	struct gigaset_driver *drv = cs->driver;
-	spin_lock_irqsave(&drv->lock, flags);
-	drv->flags[cs->minor_index] &= ~mask;
-	spin_unlock_irqrestore(&drv->lock, flags);
-}
-
 /* For drivers without fixed assignment device<->cardstate (usb) */
 struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
 {
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index fdcb80b..18e05c0 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1,7 +1,7 @@
 /*
  * Stuff used by all variants of the driver
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
  *                       Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>.
  *
@@ -11,82 +11,78 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
 
 /* ========================================================== */
 /* bit masks for pending commands */
-#define PC_INIT       0x004
-#define PC_DLE0       0x008
-#define PC_DLE1       0x010
-#define PC_CID        0x080
-#define PC_NOCID      0x100
-#define PC_HUP        0x002
-#define PC_DIAL       0x001
-#define PC_ACCEPT     0x040
-#define PC_SHUTDOWN   0x020
-#define PC_CIDMODE    0x200
-#define PC_UMMODE     0x400
+#define PC_DIAL		0x001
+#define PC_HUP		0x002
+#define PC_INIT		0x004
+#define PC_DLE0		0x008
+#define PC_DLE1		0x010
+#define PC_SHUTDOWN	0x020
+#define PC_ACCEPT	0x040
+#define PC_CID		0x080
+#define PC_NOCID	0x100
+#define PC_CIDMODE	0x200
+#define PC_UMMODE	0x400
 
 /* types of modem responses */
-#define RT_NOTHING 0
-#define RT_ZSAU    1
-#define RT_RING    2
-#define RT_NUMBER  3
-#define RT_STRING  4
-#define RT_HEX     5
-#define RT_ZCAU    6
+#define RT_NOTHING	0
+#define RT_ZSAU		1
+#define RT_RING		2
+#define RT_NUMBER	3
+#define RT_STRING	4
+#define RT_HEX		5
+#define RT_ZCAU		6
 
 /* Possible ASCII responses */
-#define RSP_OK           0
-//#define RSP_BUSY       1
-//#define RSP_CONNECT    2
-#define RSP_ZGCI         3
-#define RSP_RING         4
-#define RSP_ZAOC         5
-#define RSP_ZCSTR        6
-#define RSP_ZCFGT        7
-#define RSP_ZCFG         8
-#define RSP_ZCCR         9
-#define RSP_EMPTY        10
-#define RSP_ZLOG         11
-#define RSP_ZCAU         12
-#define RSP_ZMWI         13
-#define RSP_ZABINFO      14
-#define RSP_ZSMLSTCHG    15
-#define RSP_VAR          100
-#define RSP_ZSAU         (RSP_VAR + VAR_ZSAU)
-#define RSP_ZDLE         (RSP_VAR + VAR_ZDLE)
-#define RSP_ZVLS         (RSP_VAR + VAR_ZVLS)
-#define RSP_ZCTP         (RSP_VAR + VAR_ZCTP)
-#define RSP_STR          (RSP_VAR + VAR_NUM)
-#define RSP_NMBR         (RSP_STR + STR_NMBR)
-#define RSP_ZCPN         (RSP_STR + STR_ZCPN)
-#define RSP_ZCON         (RSP_STR + STR_ZCON)
-#define RSP_ZBC          (RSP_STR + STR_ZBC)
-#define RSP_ZHLC         (RSP_STR + STR_ZHLC)
-#define RSP_ERROR       -1       /* ERROR              */
-#define RSP_WRONG_CID   -2       /* unknown cid in cmd */
-//#define RSP_EMPTY     -3
-#define RSP_UNKNOWN     -4       /* unknown response   */
-#define RSP_FAIL        -5       /* internal error     */
-#define RSP_INVAL       -6       /* invalid response   */
+#define RSP_OK		0
+//#define RSP_BUSY	1
+//#define RSP_CONNECT	2
+#define RSP_ZGCI	3
+#define RSP_RING	4
+#define RSP_ZAOC	5
+#define RSP_ZCSTR	6
+#define RSP_ZCFGT	7
+#define RSP_ZCFG	8
+#define RSP_ZCCR	9
+#define RSP_EMPTY	10
+#define RSP_ZLOG	11
+#define RSP_ZCAU	12
+#define RSP_ZMWI	13
+#define RSP_ZABINFO	14
+#define RSP_ZSMLSTCHG	15
+#define RSP_VAR		100
+#define RSP_ZSAU	(RSP_VAR + VAR_ZSAU)
+#define RSP_ZDLE	(RSP_VAR + VAR_ZDLE)
+#define RSP_ZVLS	(RSP_VAR + VAR_ZVLS)
+#define RSP_ZCTP	(RSP_VAR + VAR_ZCTP)
+#define RSP_STR		(RSP_VAR + VAR_NUM)
+#define RSP_NMBR	(RSP_STR + STR_NMBR)
+#define RSP_ZCPN	(RSP_STR + STR_ZCPN)
+#define RSP_ZCON	(RSP_STR + STR_ZCON)
+#define RSP_ZBC		(RSP_STR + STR_ZBC)
+#define RSP_ZHLC	(RSP_STR + STR_ZHLC)
+#define RSP_ERROR	-1	/* ERROR              */
+#define RSP_WRONG_CID	-2	/* unknown cid in cmd */
+//#define RSP_EMPTY	-3
+#define RSP_UNKNOWN	-4	/* unknown response   */
+#define RSP_FAIL	-5	/* internal error     */
+#define RSP_INVAL	-6	/* invalid response   */
 
-#define RSP_NONE        -19
-#define RSP_STRING      -20
-#define RSP_NULL        -21
-//#define RSP_RETRYFAIL -22
-//#define RSP_RETRY     -23
-//#define RSP_SKIP      -24
-#define RSP_INIT        -27
-#define RSP_ANY         -26
-#define RSP_LAST        -28
-#define RSP_NODEV       -9
+#define RSP_NONE	-19
+#define RSP_STRING	-20
+#define RSP_NULL	-21
+//#define RSP_RETRYFAIL	-22
+//#define RSP_RETRY	-23
+//#define RSP_SKIP	-24
+#define RSP_INIT	-27
+#define RSP_ANY		-26
+#define RSP_LAST	-28
+#define RSP_NODEV	-9
 
 /* actions for process_response */
 #define ACT_NOTHING		0
@@ -112,7 +108,7 @@
 #define ACT_DISCONNECT		20
 #define ACT_CONNECT		21
 #define ACT_REMOTEREJECT	22
-#define ACT_CONNTIMEOUT         23
+#define ACT_CONNTIMEOUT		23
 #define ACT_REMOTEHUP		24
 #define ACT_ABORTHUP		25
 #define ACT_ICALL		26
@@ -127,40 +123,40 @@
 #define ACT_ERROR		35
 #define ACT_ABORTCID		36
 #define ACT_ZCAU		37
-#define ACT_NOTIFY_BC_DOWN      38
-#define ACT_NOTIFY_BC_UP        39
-#define ACT_DIAL                40
-#define ACT_ACCEPT              41
-#define ACT_PROTO_L2            42
-#define ACT_HUP                 43
-#define ACT_IF_LOCK             44
-#define ACT_START               45
-#define ACT_STOP                46
-#define ACT_FAKEDLE0            47
-#define ACT_FAKEHUP             48
-#define ACT_FAKESDOWN           49
-#define ACT_SHUTDOWN            50
-#define ACT_PROC_CIDMODE        51
-#define ACT_UMODESET            52
-#define ACT_FAILUMODE           53
-#define ACT_CMODESET            54
-#define ACT_FAILCMODE           55
-#define ACT_IF_VER              56
+#define ACT_NOTIFY_BC_DOWN	38
+#define ACT_NOTIFY_BC_UP	39
+#define ACT_DIAL		40
+#define ACT_ACCEPT		41
+#define ACT_PROTO_L2		42
+#define ACT_HUP			43
+#define ACT_IF_LOCK		44
+#define ACT_START		45
+#define ACT_STOP		46
+#define ACT_FAKEDLE0		47
+#define ACT_FAKEHUP		48
+#define ACT_FAKESDOWN		49
+#define ACT_SHUTDOWN		50
+#define ACT_PROC_CIDMODE	51
+#define ACT_UMODESET		52
+#define ACT_FAILUMODE		53
+#define ACT_CMODESET		54
+#define ACT_FAILCMODE		55
+#define ACT_IF_VER		56
 #define ACT_CMD			100
 
 /* at command sequences */
-#define SEQ_NONE      0
-#define SEQ_INIT      100
-#define SEQ_DLE0      200
-#define SEQ_DLE1      250
-#define SEQ_CID       300
-#define SEQ_NOCID     350
-#define SEQ_HUP       400
-#define SEQ_DIAL      600
-#define SEQ_ACCEPT    720
-#define SEQ_SHUTDOWN  500
-#define SEQ_CIDMODE   10
-#define SEQ_UMMODE    11
+#define SEQ_NONE	0
+#define SEQ_INIT	100
+#define SEQ_DLE0	200
+#define SEQ_DLE1	250
+#define SEQ_CID		300
+#define SEQ_NOCID	350
+#define SEQ_HUP		400
+#define SEQ_DIAL	600
+#define SEQ_ACCEPT	720
+#define SEQ_SHUTDOWN	500
+#define SEQ_CIDMODE	10
+#define SEQ_UMMODE	11
 
 
 // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
@@ -175,7 +171,7 @@
 	//                                                  {ACT_TIMEOUT}},
 
 	{RSP_INIT,     -1, -1,SEQ_INIT,           100, INIT_TIMEOUT,
-	                                                  {ACT_TIMEOUT}},                /* wait until device is ready */
+							  {ACT_TIMEOUT}},                /* wait until device is ready */
 
 	{EV_TIMEOUT,  100,100, -1,                101, 3, {0},             "Z\r"},       /* device in transparent mode? try to initialize it. */
 	{RSP_OK,      101,103, -1,                120, 5, {ACT_GETSTRING}, "+GMR\r"},    /* get version */
@@ -190,8 +186,8 @@
 	{RSP_ERROR,   108,108, -1,                  0, 0, {ACT_FAILINIT}},
 
 	{EV_TIMEOUT,  108,108, -1,                105, 2, {ACT_SETDLE0,
-	                                                   ACT_HUPMODEM,
-	                                                   ACT_TIMEOUT}},                /* still timeout => connection in unimodem mode? */
+							   ACT_HUPMODEM,
+							   ACT_TIMEOUT}},                /* still timeout => connection in unimodem mode? */
 	{EV_TIMEOUT,  105,105, -1,                103, 5, {0},             "Z\r"},
 
 	{RSP_ERROR,   102,102, -1,                107, 5, {0},             "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */
@@ -377,6 +373,9 @@
 
 	{EV_TIMEOUT,  750,750, -1,                  0, 0, {ACT_CONNTIMEOUT}},
 
+	/* B channel closed (general case) */
+	{EV_BC_CLOSED, -1, -1, -1,                 -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
+
 	/* misc. */
 	{EV_PROTO_L2,  -1, -1, -1,                 -1,-1, {ACT_PROTO_L2}}, //FIXME
 
@@ -393,7 +392,7 @@
 
 
 #if 0
-static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME
 {
 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
 
@@ -401,7 +400,7 @@
 	{RSP_LAST,0,0,0,0,0,0}
 };
 
-static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen
+static struct reply_t tab_cid[] = /* no dle mode */ //FIXME
 {
 	/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
 
@@ -412,30 +411,30 @@
 
 static struct resp_type_t resp_type[]=
 {
-	/*{"",          RSP_EMPTY,  RT_NOTHING},*/
-	{"OK",        RSP_OK,     RT_NOTHING},
-	{"ERROR",     RSP_ERROR,  RT_NOTHING},
-	{"ZSAU",      RSP_ZSAU,   RT_ZSAU},
-	{"ZCAU",      RSP_ZCAU,   RT_ZCAU},
-	{"RING",      RSP_RING,   RT_RING},
-	{"ZGCI",      RSP_ZGCI,   RT_NUMBER},
-	{"ZVLS",      RSP_ZVLS,   RT_NUMBER},
-	{"ZCTP",      RSP_ZCTP,   RT_NUMBER},
-	{"ZDLE",      RSP_ZDLE,   RT_NUMBER},
-	{"ZCFGT",     RSP_ZCFGT,  RT_NUMBER},
-	{"ZCCR",      RSP_ZCCR,   RT_NUMBER},
-	{"ZMWI",      RSP_ZMWI,   RT_NUMBER},
-	{"ZHLC",      RSP_ZHLC,   RT_STRING},
-	{"ZBC",       RSP_ZBC,    RT_STRING},
-	{"NMBR",      RSP_NMBR,   RT_STRING},
-	{"ZCPN",      RSP_ZCPN,   RT_STRING},
-	{"ZCON",      RSP_ZCON,   RT_STRING},
-	{"ZAOC",      RSP_ZAOC,   RT_STRING},
-	{"ZCSTR",     RSP_ZCSTR,  RT_STRING},
-	{"ZCFG",      RSP_ZCFG,   RT_HEX},
-	{"ZLOG",      RSP_ZLOG,   RT_NOTHING},
-	{"ZABINFO",   RSP_ZABINFO, RT_NOTHING},
-	{"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
+	/*{"",		RSP_EMPTY,	RT_NOTHING},*/
+	{"OK",		RSP_OK,		RT_NOTHING},
+	{"ERROR",	RSP_ERROR,	RT_NOTHING},
+	{"ZSAU",	RSP_ZSAU,	RT_ZSAU},
+	{"ZCAU",	RSP_ZCAU,	RT_ZCAU},
+	{"RING",	RSP_RING,	RT_RING},
+	{"ZGCI",	RSP_ZGCI,	RT_NUMBER},
+	{"ZVLS",	RSP_ZVLS,	RT_NUMBER},
+	{"ZCTP",	RSP_ZCTP,	RT_NUMBER},
+	{"ZDLE",	RSP_ZDLE,	RT_NUMBER},
+	{"ZCFGT",	RSP_ZCFGT,	RT_NUMBER},
+	{"ZCCR",	RSP_ZCCR,	RT_NUMBER},
+	{"ZMWI",	RSP_ZMWI,	RT_NUMBER},
+	{"ZHLC",	RSP_ZHLC,	RT_STRING},
+	{"ZBC",		RSP_ZBC,	RT_STRING},
+	{"NMBR",	RSP_NMBR,	RT_STRING},
+	{"ZCPN",	RSP_ZCPN,	RT_STRING},
+	{"ZCON",	RSP_ZCON,	RT_STRING},
+	{"ZAOC",	RSP_ZAOC,	RT_STRING},
+	{"ZCSTR",	RSP_ZCSTR,	RT_STRING},
+	{"ZCFG",	RSP_ZCFG,	RT_HEX},
+	{"ZLOG",	RSP_ZLOG,	RT_NOTHING},
+	{"ZABINFO",	RSP_ZABINFO,	RT_NOTHING},
+	{"ZSMLSTCHG",	RSP_ZSMLSTCHG,	RT_NOTHING},
 	{NULL,0,0}
 };
 
@@ -446,9 +445,7 @@
 {
 	int v = -1;
 
-	IFNULLRETVAL(p, -1);
-
-	dbg(DEBUG_TRANSCMD, "string: %s", p);
+	gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
 
 	while (*p >= '0' && *p <= '9')
 		v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0');
@@ -465,9 +462,7 @@
 	int v = 0;
 	int c;
 
-	IFNULLRETVAL(p, -1);
-
-	dbg(DEBUG_TRANSCMD, "string: %s", p);
+	gig_dbg(DEBUG_TRANSCMD, "string: %s", p);
 
 	if (!*p)
 		return -1;
@@ -490,14 +485,6 @@
 	return v;
 }
 
-static inline void new_index(atomic_t *index, int max)
-{
-	if (atomic_read(index) == max)	//FIXME race?
-		atomic_set(index, 0);
-	else
-		atomic_inc(index);
-}
-
 /* retrieve CID from parsed response
  * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
  */
@@ -536,16 +523,14 @@
 	int cid;
 	int rawstring;
 
-	IFNULLRET(cs);
-
 	len = cs->cbytes;
 	if (!len) {
 		/* ignore additional LFs/CRs (M10x config mode or cx100) */
-		dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
+		gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
 		return;
 	}
 	cs->respdata[len] = 0;
-	dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
+	gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata);
 	argv[0] = cs->respdata;
 	params = 1;
 	if (cs->at_state.getstring) {
@@ -561,7 +546,8 @@
 			case ',':
 			case '=':
 				if (params > MAX_REC_PARAMS) {
-					warn("too many parameters in response");
+					dev_warn(cs->dev,
+					   "too many parameters in response\n");
 					/* need last parameter (might be CID) */
 					params--;
 				}
@@ -572,33 +558,33 @@
 		cid = params > 1 ? cid_of_response(argv[params-1]) : 0;
 		if (cid < 0) {
 			gigaset_add_event(cs, &cs->at_state, RSP_INVAL,
-			                  NULL, 0, NULL);
+					  NULL, 0, NULL);
 			return;
 		}
 
 		for (j = 1; j < params; ++j)
 			argv[j][-1] = 0;
 
-		dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
+		gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]);
 		if (cid) {
 			--params;
-			dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
+			gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]);
 		}
-		dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
+		gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1);
 		for (j = 1; j < params; j++)
-			dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
+			gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]);
 	}
 
 	spin_lock_irqsave(&cs->ev_lock, flags);
-	head = atomic_read(&cs->ev_head);
-	tail = atomic_read(&cs->ev_tail);
+	head = cs->ev_head;
+	tail = cs->ev_tail;
 
 	abort = 1;
 	curarg = 0;
 	while (curarg < params) {
 		next = (tail + 1) % MAX_EVENTS;
 		if (unlikely(next == head)) {
-			err("event queue full");
+			dev_err(cs->dev, "event queue full\n");
 			break;
 		}
 
@@ -619,8 +605,9 @@
 
 			if (!rt->response) {
 				event->type = RSP_UNKNOWN;
-				warn("unknown modem response: %s",
-				     argv[curarg]);
+				dev_warn(cs->dev,
+					 "unknown modem response: %s\n",
+					 argv[curarg]);
 				break;
 			}
 
@@ -636,7 +623,8 @@
 			break;
 		case RT_RING:
 			if (!cid) {
-				err("received RING without CID!");
+				dev_err(cs->dev,
+					"received RING without CID!\n");
 				event->type = RSP_INVAL;
 				abort = 1;
 			} else {
@@ -664,27 +652,25 @@
 				event->parameter = ZSAU_DISCONNECT_REQ;
 			else {
 				event->parameter = ZSAU_UNKNOWN;
-				warn("%s: unknown parameter %s after ZSAU",
-				     __func__, argv[curarg]);
+				dev_warn(cs->dev,
+					"%s: unknown parameter %s after ZSAU\n",
+					 __func__, argv[curarg]);
 			}
 			++curarg;
 			break;
 		case RT_STRING:
 			if (curarg < params) {
-				len = strlen(argv[curarg]) + 1;
-				event->ptr = kmalloc(len, GFP_ATOMIC);
-				if (event->ptr)
-					memcpy(event->ptr, argv[curarg], len);
-				else
-					err("no memory for string!");
+				event->ptr = kstrdup(argv[curarg], GFP_ATOMIC);
+				if (!event->ptr)
+					dev_err(cs->dev, "out of memory\n");
 				++curarg;
 			}
 #ifdef CONFIG_GIGASET_DEBUG
 			if (!event->ptr)
-				dbg(DEBUG_CMD, "string==NULL");
+				gig_dbg(DEBUG_CMD, "string==NULL");
 			else
-				dbg(DEBUG_CMD,
-				    "string==%s", (char *) event->ptr);
+				gig_dbg(DEBUG_CMD, "string==%s",
+					(char *) event->ptr);
 #endif
 			break;
 		case RT_ZCAU:
@@ -694,7 +680,7 @@
 				j = isdn_gethex(argv[curarg + 1]);
 				if (i >= 0 && i < 256 && j >= 0 && j < 256)
 					event->parameter = (unsigned) i << 8
-					                   | j;
+							   | j;
 				curarg += 2;
 			} else
 				curarg = params - 1;
@@ -712,7 +698,7 @@
 			} else
 				event->parameter = -1;
 #ifdef CONFIG_GIGASET_DEBUG
-			dbg(DEBUG_CMD, "parameter==%d", event->parameter);
+			gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter);
 #endif
 			break;
 		}
@@ -724,12 +710,13 @@
 			break;
 	}
 
-	atomic_set(&cs->ev_tail, tail);
+	cs->ev_tail = tail;
 	spin_unlock_irqrestore(&cs->ev_lock, flags);
 
 	if (curarg != params)
-		dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d",
-		    curarg, params);
+		gig_dbg(DEBUG_ANY,
+			"invalid number of processed parameters: %d/%d",
+			curarg, params);
 }
 EXPORT_SYMBOL_GPL(gigaset_handle_modem_response);
 
@@ -739,23 +726,19 @@
 static void disconnect(struct at_state_t **at_state_p)
 {
 	unsigned long flags;
-	struct bc_state *bcs;
-	struct cardstate *cs;
+	struct bc_state *bcs = (*at_state_p)->bcs;
+	struct cardstate *cs = (*at_state_p)->cs;
 
-	IFNULLRET(at_state_p);
-	IFNULLRET(*at_state_p);
-	bcs = (*at_state_p)->bcs;
-	cs = (*at_state_p)->cs;
-	IFNULLRET(cs);
-
-	new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX);
+	spin_lock_irqsave(&cs->lock, flags);
+	++(*at_state_p)->seq_index;
 
 	/* revert to selected idle mode */
-	if (!atomic_read(&cs->cidmode)) {
+	if (!cs->cidmode) {
 		cs->at_state.pending_commands |= PC_UMMODE;
 		atomic_set(&cs->commands_pending, 1); //FIXME
-		dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+		gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 
 	if (bcs) {
 		/* B channel assigned: invoke hardware specific handler */
@@ -777,7 +760,7 @@
  * The structure should be freed by calling disconnect() after use.
  */
 static inline struct at_state_t *get_free_channel(struct cardstate *cs,
-                                                  int cid)
+						  int cid)
 /* cids: >0: siemens-cid
 	  0: without cid
 	 -1: no cid assigned yet
@@ -826,7 +809,7 @@
 static void schedule_init(struct cardstate *cs, int state)
 {
 	if (cs->at_state.pending_commands & PC_INIT) {
-		dbg(DEBUG_CMD, "not scheduling PC_INIT again");
+		gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again");
 		return;
 	}
 	atomic_set(&cs->mstate, state);
@@ -834,52 +817,56 @@
 	gigaset_block_channels(cs);
 	cs->at_state.pending_commands |= PC_INIT;
 	atomic_set(&cs->commands_pending, 1);
-	dbg(DEBUG_CMD, "Scheduling PC_INIT");
+	gig_dbg(DEBUG_CMD, "Scheduling PC_INIT");
 }
 
-/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */
+/* Add "AT" to a command, add the cid, dle encode it, send the result to the
+   hardware. */
 static void send_command(struct cardstate *cs, const char *cmd, int cid,
-                         int dle, gfp_t kmallocflags)
+			 int dle, gfp_t kmallocflags)
 {
 	size_t cmdlen, buflen;
 	char *cmdpos, *cmdbuf, *cmdtail;
 
 	cmdlen = strlen(cmd);
 	buflen = 11 + cmdlen;
+	if (unlikely(buflen <= cmdlen)) {
+		dev_err(cs->dev, "integer overflow in buflen\n");
+		return;
+	}
 
-	if (likely(buflen > cmdlen)) {
-		cmdbuf = kmalloc(buflen, kmallocflags);
-		if (likely(cmdbuf != NULL)) {
-			cmdpos = cmdbuf + 9;
-			cmdtail = cmdpos + cmdlen;
-			memcpy(cmdpos, cmd, cmdlen);
+	cmdbuf = kmalloc(buflen, kmallocflags);
+	if (unlikely(!cmdbuf)) {
+		dev_err(cs->dev, "out of memory\n");
+		return;
+	}
 
-			if (cid > 0 && cid <= 65535) {
-				do {
-					*--cmdpos = '0' + cid % 10;
-					cid /= 10;
-					++cmdlen;
-				} while (cid);
-			}
+	cmdpos = cmdbuf + 9;
+	cmdtail = cmdpos + cmdlen;
+	memcpy(cmdpos, cmd, cmdlen);
 
-			cmdlen += 2;
-			*--cmdpos = 'T';
-			*--cmdpos = 'A';
+	if (cid > 0 && cid <= 65535) {
+		do {
+			*--cmdpos = '0' + cid % 10;
+			cid /= 10;
+			++cmdlen;
+		} while (cid);
+	}
 
-			if (dle) {
-				cmdlen += 4;
-				*--cmdpos = '(';
-				*--cmdpos = 0x10;
-				*cmdtail++ = 0x10;
-				*cmdtail++ = ')';
-			}
+	cmdlen += 2;
+	*--cmdpos = 'T';
+	*--cmdpos = 'A';
 
-			cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
-			kfree(cmdbuf);
-		} else
-			err("no memory for command buffer");
-	} else
-		err("overflow in buflen");
+	if (dle) {
+		cmdlen += 4;
+		*--cmdpos = '(';
+		*--cmdpos = 0x10;
+		*cmdtail++ = 0x10;
+		*cmdtail++ = ')';
+	}
+
+	cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
+	kfree(cmdbuf);
 }
 
 static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
@@ -910,9 +897,6 @@
 
 static void bchannel_down(struct bc_state *bcs)
 {
-	IFNULLRET(bcs);
-	IFNULLRET(bcs->cs);
-
 	if (bcs->chstate & CHS_B_UP) {
 		bcs->chstate &= ~CHS_B_UP;
 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
@@ -930,16 +914,15 @@
 
 static void bchannel_up(struct bc_state *bcs)
 {
-	IFNULLRET(bcs);
-
 	if (!(bcs->chstate & CHS_D_UP)) {
-		notice("%s: D channel not up", __func__);
+		dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
 		bcs->chstate |= CHS_D_UP;
 		gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
 	}
 
 	if (bcs->chstate & CHS_B_UP) {
-		notice("%s: B channel already up", __func__);
+		dev_notice(bcs->cs->dev, "%s: B channel already up\n",
+			   __func__);
 		return;
 	}
 
@@ -947,17 +930,21 @@
 	gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
 }
 
-static void start_dial(struct at_state_t *at_state, void *data, int seq_index)
+static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index)
 {
 	struct bc_state *bcs = at_state->bcs;
 	struct cardstate *cs = at_state->cs;
 	int retval;
+	unsigned long flags;
 
 	bcs->chstate |= CHS_NOTIFY_LL;
-	//atomic_set(&bcs->status, BCS_INIT);
 
-	if (atomic_read(&at_state->seq_index) != seq_index)
+	spin_lock_irqsave(&cs->lock, flags);
+	if (at_state->seq_index != seq_index) {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		goto error;
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 
 	retval = gigaset_isdn_setup_dial(at_state, data);
 	if (retval != 0)
@@ -965,20 +952,14 @@
 
 
 	at_state->pending_commands |= PC_CID;
-	dbg(DEBUG_CMD, "Scheduling PC_CID");
-//#ifdef GIG_MAYINITONDIAL
-//	if (atomic_read(&cs->MState) == MS_UNKNOWN) {
-//		cs->at_state.pending_commands |= PC_INIT;
-//		dbg(DEBUG_CMD, "Scheduling PC_INIT");
-//	}
-//#endif
-	atomic_set(&cs->commands_pending, 1); //FIXME
+	gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
+	atomic_set(&cs->commands_pending, 1);
 	return;
 
 error:
 	at_state->pending_commands |= PC_NOCID;
-	dbg(DEBUG_CMD, "Scheduling PC_NOCID");
-	atomic_set(&cs->commands_pending, 1); //FIXME
+	gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
+	atomic_set(&cs->commands_pending, 1);
 	return;
 }
 
@@ -991,13 +972,13 @@
 
 	if (retval == 0) {
 		at_state->pending_commands |= PC_ACCEPT;
-		dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
-		atomic_set(&cs->commands_pending, 1); //FIXME
+		gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
+		atomic_set(&cs->commands_pending, 1);
 	} else {
 		//FIXME
 		at_state->pending_commands |= PC_HUP;
-		dbg(DEBUG_CMD, "Scheduling PC_HUP");
-		atomic_set(&cs->commands_pending, 1); //FIXME
+		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
+		atomic_set(&cs->commands_pending, 1);
 	}
 }
 
@@ -1008,9 +989,10 @@
 	if (atomic_read(&cs->mstate) != MS_LOCKED)
 		schedule_init(cs, MS_INIT);
 
+	cs->isdn_up = 1;
 	gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
-	                                // FIXME: not in locked mode
-	                                // FIXME 2: only after init sequence
+					// FIXME: not in locked mode
+					// FIXME 2: only after init sequence
 
 	cs->waiting = 0;
 	wake_up(&cs->waitqueue);
@@ -1023,6 +1005,12 @@
 		atomic_set(&cs->mode, M_UNKNOWN);
 	}
 
+	/* Tell the LL that the device is not available .. */
+	if (cs->isdn_up) {
+		cs->isdn_up = 0;
+		gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
+	}
+
 	/* The rest is done by cleanup_cs () in user mode. */
 
 	cs->cmd_result = -ENODEV;
@@ -1037,15 +1025,20 @@
 	if (atomic_read(&cs->mstate) == MS_READY) {
 		atomic_set(&cs->mstate, MS_SHUTDOWN);
 		cs->at_state.pending_commands |= PC_SHUTDOWN;
-		atomic_set(&cs->commands_pending, 1); //FIXME
-		dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME
-		//gigaset_schedule_event(cs); //FIXME
+		atomic_set(&cs->commands_pending, 1);
+		gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN");
 	} else
 		finish_shutdown(cs);
 }
 
 static void do_stop(struct cardstate *cs)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs->lock, flags);
+	cs->connected = 0;
+	spin_unlock_irqrestore(&cs->lock, flags);
+
 	do_shutdown(cs);
 }
 
@@ -1069,9 +1062,11 @@
 			return 0;
 
 	if (channel < 0)
-		warn("Could not enter cid mode. Reinit device and try again.");
+		dev_warn(cs->dev,
+		    "Could not enter cid mode. Reinit device and try again.\n");
 	else {
-		warn("Could not get a call id. Reinit device and try again.");
+		dev_warn(cs->dev,
+		    "Could not get a call id. Reinit device and try again.\n");
 		cs->bcs[channel].at_state.pending_commands |= PC_CID;
 	}
 	schedule_init(cs, MS_INIT);
@@ -1079,7 +1074,7 @@
 }
 
 static int at_state_invalid(struct cardstate *cs,
-                            struct at_state_t *test_ptr)
+			    struct at_state_t *test_ptr)
 {
 	unsigned long flags;
 	unsigned channel;
@@ -1116,7 +1111,7 @@
 	case ICALL_ACCEPT:
 		break;
 	default:
-		err("internal error: disposition=%d", retval);
+		dev_err(cs->dev, "internal error: disposition=%d\n", retval);
 		/* --v-- fall through --v-- */
 	case ICALL_IGNORE:
 	case ICALL_REJECT:
@@ -1160,7 +1155,6 @@
 	mode = atomic_read(&cs->mode);
 	atomic_set(&cs->mstate, MS_LOCKED);
 	atomic_set(&cs->mode, M_UNKNOWN);
-	//FIXME reset card state / at states / bcs states
 
 	return mode;
 }
@@ -1173,8 +1167,7 @@
 	atomic_set(&cs->mstate, MS_UNINITIALIZED);
 	atomic_set(&cs->mode, M_UNKNOWN);
 	gigaset_free_channels(cs);
-	//FIXME reset card state / at states / bcs states
-	if (atomic_read(&cs->connected))
+	if (cs->connected)
 		schedule_init(cs, MS_INIT);
 
 	return 0;
@@ -1203,21 +1196,23 @@
 		at_state->waiting = 1;
 		break;
 	case ACT_INIT:
-		//FIXME setup everything
 		cs->at_state.pending_commands &= ~PC_INIT;
 		cs->cur_at_seq = SEQ_NONE;
 		atomic_set(&cs->mode, M_UNIMODEM);
-		if (!atomic_read(&cs->cidmode)) {
+		spin_lock_irqsave(&cs->lock, flags);
+		if (!cs->cidmode) {
+			spin_unlock_irqrestore(&cs->lock, flags);
 			gigaset_free_channels(cs);
 			atomic_set(&cs->mstate, MS_READY);
 			break;
 		}
+		spin_unlock_irqrestore(&cs->lock, flags);
 		cs->at_state.pending_commands |= PC_CIDMODE;
-		atomic_set(&cs->commands_pending, 1); //FIXME
-		dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+		atomic_set(&cs->commands_pending, 1);
+		gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
 		break;
 	case ACT_FAILINIT:
-		warn("Could not initialize the device.");
+		dev_warn(cs->dev, "Could not initialize the device.\n");
 		cs->dle = 0;
 		init_failed(cs, M_UNKNOWN);
 		cs->cur_at_seq = SEQ_NONE;
@@ -1273,8 +1268,8 @@
 		/* get fresh AT state structure for new CID */
 		at_state2 = get_free_channel(cs, ev->parameter);
 		if (!at_state2) {
-			warn("RING ignored: "
-			     "could not allocate channel structure");
+			dev_warn(cs->dev,
+			"RING ignored: could not allocate channel structure\n");
 			break;
 		}
 
@@ -1302,7 +1297,7 @@
 		at_state = *p_at_state;
 		break;
 	case ACT_FAILSDOWN:
-		warn("Could not shut down the device.");
+		dev_warn(cs->dev, "Could not shut down the device.\n");
 		/* fall through */
 	case ACT_FAKESDOWN:
 	case ACT_SDOWN:
@@ -1355,7 +1350,7 @@
 		break;
 	case ACT_ABORTHUP:
 		cs->cur_at_seq = SEQ_NONE;
-		warn("Could not hang up.");
+		dev_warn(cs->dev, "Could not hang up.\n");
 		at_state->cid = -1;
 		if (bcs && cs->onechannel)
 			at_state->pending_commands |= PC_DLE0;
@@ -1367,14 +1362,15 @@
 		break;
 	case ACT_FAILDLE0:
 		cs->cur_at_seq = SEQ_NONE;
-		warn("Could not leave DLE mode.");
+		dev_warn(cs->dev, "Could not leave DLE mode.\n");
 		at_state2 = &cs->bcs[cs->curchannel].at_state;
 		disconnect(&at_state2);
 		schedule_init(cs, MS_RECOVER);
 		break;
 	case ACT_FAILDLE1:
 		cs->cur_at_seq = SEQ_NONE;
-		warn("Could not enter DLE mode. Try to hang up.");
+		dev_warn(cs->dev,
+			 "Could not enter DLE mode. Trying to hang up.\n");
 		channel = cs->curchannel;
 		cs->bcs[channel].at_state.pending_commands |= PC_HUP;
 		atomic_set(&cs->commands_pending, 1);
@@ -1395,7 +1391,8 @@
 		cs->cur_at_seq = SEQ_NONE;
 		channel = cs->curchannel;
 		if (!reinit_and_retry(cs, channel)) {
-			warn("Could not get a call id. Dialing not possible");
+			dev_warn(cs->dev,
+				 "Could not get a call ID. Cannot dial.\n");
 			at_state2 = &cs->bcs[channel].at_state;
 			disconnect(&at_state2);
 		}
@@ -1428,7 +1425,8 @@
 		at_state->pending_commands |= PC_HUP;
 		atomic_set(&cs->commands_pending, 1);
 		break;
-	case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */
+	case ACT_GETSTRING: /* warning: RING, ZDLE, ...
+			       are not handled properly anymore */
 		at_state->getstring = 1;
 		break;
 	case ACT_SETVER:
@@ -1469,16 +1467,16 @@
 	case ACT_GOTVER:
 		if (cs->gotfwver == 0) {
 			cs->gotfwver = 1;
-			dbg(DEBUG_ANY,
-			    "firmware version %02d.%03d.%02d.%02d",
-			    cs->fwver[0], cs->fwver[1],
-			    cs->fwver[2], cs->fwver[3]);
+			gig_dbg(DEBUG_ANY,
+				"firmware version %02d.%03d.%02d.%02d",
+				cs->fwver[0], cs->fwver[1],
+				cs->fwver[2], cs->fwver[3]);
 			break;
 		}
 		/* fall through */
 	case ACT_FAILVER:
 		cs->gotfwver = -1;
-		err("could not read firmware version.");
+		dev_err(cs->dev, "could not read firmware version.\n");
 		break;
 #ifdef CONFIG_GIGASET_DEBUG
 	case ACT_ERROR:
@@ -1496,16 +1494,16 @@
 		break;
 #endif
 	case ACT_DEBUG:
-		dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
+		gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
 			__func__, ev->type, at_state->ConState);
 		break;
 	case ACT_WARN:
-		warn("%s: resp_code %d in ConState %d!",
-			__func__, ev->type, at_state->ConState);
+		dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n",
+			 __func__, ev->type, at_state->ConState);
 		break;
 	case ACT_ZCAU:
-		warn("cause code %04x in connection state %d.",
-		     ev->parameter, at_state->ConState);
+		dev_warn(cs->dev, "cause code %04x in connection state %d.\n",
+			 ev->parameter, at_state->ConState);
 		break;
 
 	/* events from the LL */
@@ -1516,14 +1514,14 @@
 		start_accept(at_state);
 		break;
 	case ACT_PROTO_L2:
-		dbg(DEBUG_CMD,
-		    "set protocol to %u", (unsigned) ev->parameter);
+		gig_dbg(DEBUG_CMD, "set protocol to %u",
+			(unsigned) ev->parameter);
 		at_state->bcs->proto2 = ev->parameter;
 		break;
 	case ACT_HUP:
 		at_state->pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1); //FIXME
-		dbg(DEBUG_CMD, "Scheduling PC_HUP");
+		atomic_set(&cs->commands_pending, 1);
+		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
 		break;
 
 	/* hotplug events */
@@ -1555,17 +1553,19 @@
 
 	/* events from the proc file system */ // FIXME without ACT_xxxx?
 	case ACT_PROC_CIDMODE:
-		if (ev->parameter != atomic_read(&cs->cidmode)) {
-			atomic_set(&cs->cidmode, ev->parameter);
+		spin_lock_irqsave(&cs->lock, flags);
+		if (ev->parameter != cs->cidmode) {
+			cs->cidmode = ev->parameter;
 			if (ev->parameter) {
 				cs->at_state.pending_commands |= PC_CIDMODE;
-				dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+				gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
 			} else {
 				cs->at_state.pending_commands |= PC_UMMODE;
-				dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
+				gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
 			}
 			atomic_set(&cs->commands_pending, 1);
 		}
+		spin_unlock_irqrestore(&cs->lock, flags);
 		cs->waiting = 0;
 		wake_up(&cs->waitqueue);
 		break;
@@ -1590,7 +1590,7 @@
 				*p_resp_code = RSP_NULL;
 			}
 		} else
-			err("%s: action==%d!", __func__, action);
+			dev_err(cs->dev, "%s: action==%d!\n", __func__, action);
 	}
 }
 
@@ -1609,47 +1609,46 @@
 	int curact;
 	unsigned long flags;
 
-	IFNULLRET(cs);
-	IFNULLRET(ev);
-
 	if (ev->cid >= 0) {
 		at_state = at_state_from_cid(cs, ev->cid);
 		if (!at_state) {
 			gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID,
-			                  NULL, 0, NULL);
+					  NULL, 0, NULL);
 			return;
 		}
 	} else {
 		at_state = ev->at_state;
 		if (at_state_invalid(cs, at_state)) {
-			dbg(DEBUG_ANY,
-			    "event for invalid at_state %p", at_state);
+			gig_dbg(DEBUG_ANY, "event for invalid at_state %p",
+				at_state);
 			return;
 		}
 	}
 
-	dbg(DEBUG_CMD,
-	    "connection state %d, event %d", at_state->ConState, ev->type);
+	gig_dbg(DEBUG_CMD, "connection state %d, event %d",
+		at_state->ConState, ev->type);
 
 	bcs = at_state->bcs;
 	sendcid = at_state->cid;
 
 	/* Setting the pointer to the dial array */
 	rep = at_state->replystruct;
-	IFNULLRET(rep);
 
+	spin_lock_irqsave(&cs->lock, flags);
 	if (ev->type == EV_TIMEOUT) {
-		if (ev->parameter != atomic_read(&at_state->timer_index)
+		if (ev->parameter != at_state->timer_index
 		    || !at_state->timer_active) {
 			ev->type = RSP_NONE; /* old timeout */
-			dbg(DEBUG_ANY, "old timeout");
+			gig_dbg(DEBUG_ANY, "old timeout");
 		} else if (!at_state->waiting)
-			dbg(DEBUG_ANY, "timeout occured");
+			gig_dbg(DEBUG_ANY, "timeout occurred");
 		else
-			dbg(DEBUG_ANY, "stopped waiting");
+			gig_dbg(DEBUG_ANY, "stopped waiting");
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 
-	/* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */
+	/* if the response belongs to a variable in at_state->int_var[VAR_XXXX]
+	   or at_state->str_var[STR_XXXX], set it */
 	if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) {
 		index = ev->type - RSP_VAR;
 		at_state->int_var[index] = ev->parameter;
@@ -1657,20 +1656,22 @@
 		index = ev->type - RSP_STR;
 		kfree(at_state->str_var[index]);
 		at_state->str_var[index] = ev->ptr;
-		ev->ptr = NULL; /* prevent process_events() from deallocating ptr */
+		ev->ptr = NULL; /* prevent process_events() from
+				   deallocating ptr */
 	}
 
 	if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING)
 		at_state->getstring = 0;
 
-	/* Search row in dial array which matches modem response and current constate */
+	/* Search row in dial array which matches modem response and current
+	   constate */
 	for (;; rep++) {
 		rcode = rep->resp_code;
-		/* dbg (DEBUG_ANY, "rcode %d", rcode); */
 		if (rcode == RSP_LAST) {
 			/* found nothing...*/
-			warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!",
-				__func__, ev->type, at_state->ConState);
+			dev_warn(cs->dev, "%s: rcode=RSP_LAST: "
+					"resp_code %d in ConState %d!\n",
+				 __func__, ev->type, at_state->ConState);
 			return;
 		}
 		if ((rcode == RSP_ANY || rcode == ev->type)
@@ -1706,14 +1707,14 @@
 		} else {
 			/* Send command to modem if not NULL... */
 			if (p_command/*rep->command*/) {
-				if (atomic_read(&cs->connected))
+				if (cs->connected)
 					send_command(cs, p_command,
-					             sendcid, cs->dle,
-					             GFP_ATOMIC);
+						     sendcid, cs->dle,
+						     GFP_ATOMIC);
 				else
 					gigaset_add_event(cs, at_state,
-					                  RSP_NODEV,
-					                  NULL, 0, NULL);
+							  RSP_NODEV,
+							  NULL, 0, NULL);
 			}
 
 			spin_lock_irqsave(&cs->lock, flags);
@@ -1723,8 +1724,7 @@
 			} else if (rep->timeout > 0) { /* new timeout */
 				at_state->timer_expires = rep->timeout * 10;
 				at_state->timer_active = 1;
-				new_index(&at_state->timer_index,
-				          MAX_TIMER_INDEX);
+				++at_state->timer_index;
 			}
 			spin_unlock_irqrestore(&cs->lock, flags);
 		}
@@ -1744,17 +1744,16 @@
 	struct bc_state *bcs;
 	int i;
 	int sequence;
-
-	IFNULLRET(cs);
+	unsigned long flags;
 
 	atomic_set(&cs->commands_pending, 0);
 
 	if (cs->cur_at_seq) {
-		dbg(DEBUG_CMD, "not searching scheduled commands: busy");
+		gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy");
 		return;
 	}
 
-	dbg(DEBUG_CMD, "searching scheduled commands");
+	gig_dbg(DEBUG_CMD, "searching scheduled commands");
 
 	sequence = SEQ_NONE;
 
@@ -1795,8 +1794,9 @@
 	}
 
 	/* only switch back to unimodem mode, if no commands are pending and no channels are up */
+	spin_lock_irqsave(&cs->lock, flags);
 	if (cs->at_state.pending_commands == PC_UMMODE
-	    && !atomic_read(&cs->cidmode)
+	    && !cs->cidmode
 	    && list_empty(&cs->temp_at_states)
 	    && atomic_read(&cs->mode) == M_CID) {
 		sequence = SEQ_UMMODE;
@@ -1810,6 +1810,7 @@
 			}
 		}
 	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 	cs->at_state.pending_commands &= ~PC_UMMODE;
 	if (sequence != SEQ_NONE) {
 		schedule_sequence(cs, at_state, sequence);
@@ -1865,11 +1866,7 @@
 	if (cs->at_state.pending_commands & PC_CIDMODE) {
 		cs->at_state.pending_commands &= ~PC_CIDMODE;
 		if (atomic_read(&cs->mode) == M_UNIMODEM) {
-#if 0
-			cs->retry_count = 2;
-#else
 			cs->retry_count = 1;
-#endif
 			schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
 			return;
 		}
@@ -1897,7 +1894,7 @@
 			switch (atomic_read(&cs->mode)) {
 			case M_UNIMODEM:
 				cs->at_state.pending_commands |= PC_CIDMODE;
-				dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
+				gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
 				atomic_set(&cs->commands_pending, 1);
 				return;
 #ifdef GIG_MAYINITONDIAL
@@ -1926,18 +1923,21 @@
 	int i;
 	int check_flags = 0;
 	int was_busy;
+	unsigned long flags;
 
-	/* no locking needed (only one reader) */
-	head = atomic_read(&cs->ev_head);
+	spin_lock_irqsave(&cs->ev_lock, flags);
+	head = cs->ev_head;
 
 	for (i = 0; i < 2 * MAX_EVENTS; ++i) {
-		tail = atomic_read(&cs->ev_tail);
+		tail = cs->ev_tail;
 		if (tail == head) {
 			if (!check_flags && !atomic_read(&cs->commands_pending))
 				break;
 			check_flags = 0;
+			spin_unlock_irqrestore(&cs->ev_lock, flags);
 			process_command_flags(cs);
-			tail = atomic_read(&cs->ev_tail);
+			spin_lock_irqsave(&cs->ev_lock, flags);
+			tail = cs->ev_tail;
 			if (tail == head) {
 				if (!atomic_read(&cs->commands_pending))
 					break;
@@ -1947,18 +1947,23 @@
 
 		ev = cs->events + head;
 		was_busy = cs->cur_at_seq != SEQ_NONE;
+		spin_unlock_irqrestore(&cs->ev_lock, flags);
 		process_event(cs, ev);
+		spin_lock_irqsave(&cs->ev_lock, flags);
 		kfree(ev->ptr);
 		ev->ptr = NULL;
 		if (was_busy && cs->cur_at_seq == SEQ_NONE)
 			check_flags = 1;
 
 		head = (head + 1) % MAX_EVENTS;
-		atomic_set(&cs->ev_head, head);
+		cs->ev_head = head;
 	}
 
+	spin_unlock_irqrestore(&cs->ev_lock, flags);
+
 	if (i == 2 * MAX_EVENTS) {
-		err("infinite loop in process_events; aborting.");
+		dev_err(cs->dev,
+			"infinite loop in process_events; aborting.\n");
 	}
 }
 
@@ -1970,12 +1975,9 @@
 {
 	struct cardstate *cs = (struct cardstate *) data;
 
-	IFNULLRET(cs);
-	IFNULLRET(cs->inbuf);
-
 	/* handle incoming data on control/common channel */
 	if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
-		dbg(DEBUG_INTR, "processing new data");
+		gig_dbg(DEBUG_INTR, "processing new data");
 		cs->ops->handle_input(cs->inbuf);
 	}
 
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 729edcd..22b9693 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -1,11 +1,16 @@
-/* Siemens Gigaset 307x driver
+/*
+ * Siemens Gigaset 307x driver
  * Common header file for all connection variants
  *
- * Written by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Written by Stefan Eilers
  *        and Hansjoerg Lipp <hjlipp@web.de>
  *
- * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $
- * ===========================================================================
+ * =====================================================================
+ *	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.
+ * =====================================================================
  */
 
 #ifndef GIGASET_H
@@ -15,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <asm/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/isdnif.h>
 #include <linux/usb.h>
@@ -27,21 +31,22 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/list.h>
+#include <asm/atomic.h>
 
 #define GIG_VERSION {0,5,0,0}
 #define GIG_COMPAT  {0,4,0,0}
 
-#define MAX_REC_PARAMS 10                         /* Max. number of params in response string */
-#define MAX_RESP_SIZE 512                         /* Max. size of a response string */
-#define HW_HDR_LEN 2                              /* Header size used to store ack info */
+#define MAX_REC_PARAMS 10	/* Max. number of params in response string */
+#define MAX_RESP_SIZE 512	/* Max. size of a response string */
+#define HW_HDR_LEN 2		/* Header size used to store ack info */
 
-#define MAX_EVENTS 64                          /* size of event queue */
+#define MAX_EVENTS 64		/* size of event queue */
 
 #define RBUFSIZE 8192
-#define SBUFSIZE 4096				/* sk_buff payload size */
+#define SBUFSIZE 4096		/* sk_buff payload size */
 
-#define MAX_BUF_SIZE (SBUFSIZE - 2)		/* Max. size of a data packet from LL */
-#define TRANSBUFSIZE 768			/* bytes per skb for transparent receive */
+#define TRANSBUFSIZE 768	/* bytes per skb for transparent receive */
+#define MAX_BUF_SIZE (SBUFSIZE - 2)	/* Max. size of a data packet from LL */
 
 /* compile time options */
 #define GIG_MAJOR 0
@@ -50,10 +55,7 @@
 #define GIG_RETRYCID
 #define GIG_X75
 
-#define MAX_TIMER_INDEX 1000
-#define MAX_SEQ_INDEX   1000
-
-#define GIG_TICK (HZ / 10)
+#define GIG_TICK 100		/* in milliseconds */
 
 /* timeout values (unit: 1 sec) */
 #define INIT_TIMEOUT 1
@@ -67,74 +69,89 @@
 
 #define MAXACT 3
 
-#define IFNULL(a)         if (unlikely(!(a)))
-#define IFNULLRET(a)      if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; }
-#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); }
-#define IFNULLCONT(a)     if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; }
-#define IFNULLGOTO(a,b)   if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; }
-
 extern int gigaset_debuglevel;	/* "needs" cast to (enum debuglevel) */
 
-/* any combination of these can be given with the 'debug=' parameter to insmod, e.g.
- * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */
-enum debuglevel { /* up to 24 bits (atomic_t) */
+/* any combination of these can be given with the 'debug=' parameter to insmod,
+ * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
+ * DEBUG_INTR.
+ */
+enum debuglevel {
 	DEBUG_REG	  = 0x0002, /* serial port I/O register operations */
 	DEBUG_OPEN	  = 0x0004, /* open/close serial port */
 	DEBUG_INTR	  = 0x0008, /* interrupt processing */
-	DEBUG_INTR_DUMP   = 0x0010, /* Activating hexdump debug output on interrupt
-				      requests, not available as run-time option */
+	DEBUG_INTR_DUMP	  = 0x0010, /* Activating hexdump debug output on
+				       interrupt requests, not available as
+				       run-time option */
 	DEBUG_CMD	  = 0x00020, /* sent/received LL commands */
 	DEBUG_STREAM	  = 0x00040, /* application data stream I/O events */
 	DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
 	DEBUG_LLDATA	  = 0x00100, /* sent/received LL data */
-	DEBUG_INTR_0	  = 0x00200, /* serial port output interrupt processing */
+	DEBUG_INTR_0	  = 0x00200, /* serial port interrupt processing */
 	DEBUG_DRIVER	  = 0x00400, /* driver structure */
 	DEBUG_HDLC	  = 0x00800, /* M10x HDLC processing */
 	DEBUG_WRITE	  = 0x01000, /* M105 data write */
-	DEBUG_TRANSCMD    = 0x02000, /*AT-COMMANDS+RESPONSES*/
-	DEBUG_MCMD        = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/
-	DEBUG_INIT	  = 0x08000, /* (de)allocation+initialization of data structures */
+	DEBUG_TRANSCMD	  = 0x02000, /* AT-COMMANDS+RESPONSES */
+	DEBUG_MCMD	  = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */
+	DEBUG_INIT	  = 0x08000, /* (de)allocation+initialization of data
+					structures */
 	DEBUG_LOCK	  = 0x10000, /* semaphore operations */
 	DEBUG_OUTPUT	  = 0x20000, /* output to device */
-	DEBUG_ISO         = 0x40000, /* isochronous transfers */
+	DEBUG_ISO	  = 0x40000, /* isochronous transfers */
 	DEBUG_IF	  = 0x80000, /* character device operations */
-	DEBUG_USBREQ	  = 0x100000, /* USB communication (except payload data) */
-	DEBUG_LOCKCMD     = 0x200000, /* AT commands and responses when MS_LOCKED */
+	DEBUG_USBREQ	  = 0x100000, /* USB communication (except payload
+					 data) */
+	DEBUG_LOCKCMD	  = 0x200000, /* AT commands and responses when
+					 MS_LOCKED */
 
-	DEBUG_ANY	  = 0x3fffff, /* print message if any of the others is activated */
+	DEBUG_ANY	  = 0x3fffff, /* print message if any of the others is
+					 activated */
 };
 
-#ifdef CONFIG_GIGASET_DEBUG
-#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
-//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR)
-#else
-#define DEBUG_DEFAULT 0
+/* missing from linux/device.h ... */
+#ifndef dev_notice
+#define dev_notice(dev, format, arg...)		\
+	dev_printk(KERN_NOTICE , dev , format , ## arg)
 #endif
 
-/* redefine syslog macros to prepend module name instead of entire source path */
-/* The space before the comma in ", ##" is needed by gcc 2.95 */
-#undef info
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
-#undef notice
-#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
-#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
-
+/* Kernel message macros for situations where dev_printk and friends cannot be
+ * used for lack of reliable access to a device structure.
+ * linux/usb.h already contains these but in an obsolete form which clutters
+ * the log needlessly, and according to the USB maintainer those should be
+ * removed rather than fixed anyway.
+ */
 #undef err
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg)
+#undef info
+#undef warn
+#undef notice
 
-#undef dbg
+#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
+	format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
+	format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \
+	format "\n" , ## arg)
+#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \
+	format "\n" , ## arg)
+
 #ifdef CONFIG_GIGASET_DEBUG
-#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
-	printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0)
+
+#define gig_dbg(level, format, arg...) \
+	do { \
+		if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \
+			printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \
+			       ## arg); \
+	} while (0)
+#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ)
+
 #else
-#define dbg(level, format, arg...) do {} while (0)
+
+#define gig_dbg(level, format, arg...) do {} while (0)
+#define DEBUG_DEFAULT 0
+
 #endif
 
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
-                        size_t len, const unsigned char *buf, int from_user);
+			size_t len, const unsigned char *buf);
 
 /* connection state */
 #define ZSAU_NONE			0
@@ -148,13 +165,14 @@
 #define ZSAU_UNKNOWN			-1
 
 /* USB control transfer requests */
-#define OUT_VENDOR_REQ			(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
-#define IN_VENDOR_REQ			(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define OUT_VENDOR_REQ	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
+#define IN_VENDOR_REQ	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
 
 /* int-in-events 3070 */
 #define HD_B1_FLOW_CONTROL		0x80
 #define HD_B2_FLOW_CONTROL		0x81
-#define HD_RECEIVEATDATA_ACK		(0x35)		// 3070		// att: HD_RECEIVE>>AT<<DATA_ACK
+#define HD_RECEIVEATDATA_ACK		(0x35)		// 3070
+						// att: HD_RECEIVE>>AT<<DATA_ACK
 #define HD_READY_SEND_ATDATA		(0x36)		// 3070
 #define HD_OPEN_ATCHANNEL_ACK		(0x37)		// 3070
 #define HD_CLOSE_ATCHANNEL_ACK		(0x38)		// 3070
@@ -181,17 +199,18 @@
 #define	HD_CLOSE_ATCHANNEL		(0x29)		// 3070
 
 /* USB frames for isochronous transfer */
-#define BAS_FRAMETIME	1		/* number of milliseconds between frames */
-#define BAS_NUMFRAMES	8		/* number of frames per URB */
-#define BAS_MAXFRAME	16		/* allocated bytes per frame */
-#define BAS_NORMFRAME	8		/* send size without flow control */
-#define BAS_HIGHFRAME	10		/* "    "    with positive flow control */
-#define BAS_LOWFRAME	5		/* "    "    with negative flow control */
-#define BAS_CORRFRAMES	4		/* flow control multiplicator */
+#define BAS_FRAMETIME	1	/* number of milliseconds between frames */
+#define BAS_NUMFRAMES	8	/* number of frames per URB */
+#define BAS_MAXFRAME	16	/* allocated bytes per frame */
+#define BAS_NORMFRAME	8	/* send size without flow control */
+#define BAS_HIGHFRAME	10	/* "    "    with positive flow control */
+#define BAS_LOWFRAME	5	/* "    "    with negative flow control */
+#define BAS_CORRFRAMES	4	/* flow control multiplicator */
 
-#define BAS_INBUFSIZE	(BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */
-#define BAS_OUTBUFSIZE	4096		/* size of common isochronous output buffer */
-#define BAS_OUTBUFPAD	BAS_MAXFRAME	/* size of pad area for isochronous output buffer */
+#define BAS_INBUFSIZE	(BAS_MAXFRAME * BAS_NUMFRAMES)
+					/* size of isoc in buf per URB */
+#define BAS_OUTBUFSIZE	4096		/* size of common isoc out buffer */
+#define BAS_OUTBUFPAD	BAS_MAXFRAME	/* size of pad area for isoc out buf */
 
 #define BAS_INURBS	3
 #define BAS_OUTURBS	3
@@ -207,40 +226,40 @@
 #define AT_NUM		7
 
 /* variables in struct at_state_t */
-#define VAR_ZSAU   0
-#define VAR_ZDLE   1
-#define VAR_ZVLS   2
-#define VAR_ZCTP   3
-#define VAR_NUM    4
+#define VAR_ZSAU	0
+#define VAR_ZDLE	1
+#define VAR_ZVLS	2
+#define VAR_ZCTP	3
+#define VAR_NUM		4
 
-#define STR_NMBR   0
-#define STR_ZCPN   1
-#define STR_ZCON   2
-#define STR_ZBC    3
-#define STR_ZHLC   4
-#define STR_NUM    5
+#define STR_NMBR	0
+#define STR_ZCPN	1
+#define STR_ZCON	2
+#define STR_ZBC		3
+#define STR_ZHLC	4
+#define STR_NUM		5
 
-#define EV_TIMEOUT      -105
-#define EV_IF_VER       -106
-#define EV_PROC_CIDMODE -107
-#define EV_SHUTDOWN     -108
-#define EV_START        -110
-#define EV_STOP         -111
-#define EV_IF_LOCK      -112
-#define EV_PROTO_L2     -113
-#define EV_ACCEPT       -114
-#define EV_DIAL         -115
-#define EV_HUP          -116
-#define EV_BC_OPEN      -117
-#define EV_BC_CLOSED    -118
+#define EV_TIMEOUT	-105
+#define EV_IF_VER	-106
+#define EV_PROC_CIDMODE	-107
+#define EV_SHUTDOWN	-108
+#define EV_START	-110
+#define EV_STOP		-111
+#define EV_IF_LOCK	-112
+#define EV_PROTO_L2	-113
+#define EV_ACCEPT	-114
+#define EV_DIAL		-115
+#define EV_HUP		-116
+#define EV_BC_OPEN	-117
+#define EV_BC_CLOSED	-118
 
 /* input state */
-#define INS_command     0x0001
-#define INS_DLE_char    0x0002
-#define INS_byte_stuff  0x0004
-#define INS_have_data   0x0008
-#define INS_skip_frame  0x0010
-#define INS_DLE_command 0x0020
+#define INS_command	0x0001
+#define INS_DLE_char	0x0002
+#define INS_byte_stuff	0x0004
+#define INS_have_data	0x0008
+#define INS_skip_frame	0x0010
+#define INS_DLE_command	0x0020
 #define INS_flag_hunt	0x0040
 
 /* channel state */
@@ -248,27 +267,27 @@
 #define CHS_B_UP	0x02
 #define CHS_NOTIFY_LL	0x04
 
-#define ICALL_REJECT  0
-#define ICALL_ACCEPT  1
-#define ICALL_IGNORE  2
+#define ICALL_REJECT	0
+#define ICALL_ACCEPT	1
+#define ICALL_IGNORE	2
 
 /* device state */
-#define MS_UNINITIALIZED        0
-#define MS_INIT                 1
-#define MS_LOCKED               2
-#define MS_SHUTDOWN             3
-#define MS_RECOVER              4
-#define MS_READY                5
+#define MS_UNINITIALIZED	0
+#define MS_INIT			1
+#define MS_LOCKED		2
+#define MS_SHUTDOWN		3
+#define MS_RECOVER		4
+#define MS_READY		5
 
 /* mode */
-#define M_UNKNOWN       0
-#define M_CONFIG        1
-#define M_UNIMODEM      2
-#define M_CID           3
+#define M_UNKNOWN	0
+#define M_CONFIG	1
+#define M_UNIMODEM	2
+#define M_CID		3
 
 /* start mode */
-#define SM_LOCKED       0
-#define SM_ISDN         1 /* default */
+#define SM_LOCKED	0
+#define SM_ISDN		1 /* default */
 
 struct gigaset_ops;
 struct gigaset_driver;
@@ -283,27 +302,26 @@
 struct bas_bc_state;
 
 struct reply_t {
-	int	resp_code;      /* RSP_XXXX */
-	int	min_ConState;   /* <0 => ignore */
-	int	max_ConState;   /* <0 => ignore */
-	int	parameter;      /* e.g. ZSAU_XXXX <0: ignore*/
-	int	new_ConState;   /* <0 => ignore */
-	int	timeout;        /* >0 => *HZ; <=0 => TOUT_XXXX*/
-	int	action[MAXACT]; /* ACT_XXXX */
-	char *command;        /* NULL==none */
+	int	resp_code;	/* RSP_XXXX */
+	int	min_ConState;	/* <0 => ignore */
+	int	max_ConState;	/* <0 => ignore */
+	int	parameter;	/* e.g. ZSAU_XXXX <0: ignore*/
+	int	new_ConState;	/* <0 => ignore */
+	int	timeout;	/* >0 => *HZ; <=0 => TOUT_XXXX*/
+	int	action[MAXACT];	/* ACT_XXXX */
+	char	*command;	/* NULL==none */
 };
 
 extern struct reply_t gigaset_tab_cid_m10x[];
 extern struct reply_t gigaset_tab_nocid_m10x[];
 
 struct inbuf_t {
-	unsigned char           *rcvbuf;                /* usb-gigaset receive buffer */
+	unsigned char		*rcvbuf;	/* usb-gigaset receive buffer */
 	struct bc_state		*bcs;
-	struct cardstate *cs;
-	int inputstate;
-
-	atomic_t head, tail;
-	unsigned char data[RBUFSIZE];
+	struct cardstate	*cs;
+	int			inputstate;
+	atomic_t		head, tail;
+	unsigned char		data[RBUFSIZE];
 };
 
 /* isochronous write buffer structure
@@ -319,16 +337,9 @@
  *   if writesem <= 0, data[write..read-1] is currently being written to
  * - idle contains the byte value to repeat when the end of valid data is
  *   reached; if nextread==write (buffer contains no data to send), either the
- *   BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD)
- *   or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that
- *   value
- * - optionally, the following statistics on the buffer's usage can be collected:
- *   maxfill: maximum number of bytes occupied
- *   idlefills: number of times a frame of idle bytes is prepared
- *   emptygets: number of times the buffer was empty when a data frame was requested
- *   backtoback: number of times two data packets were entered into the buffer
- *    without intervening idle flags
- *   nakedback: set if no idle flags have been inserted since the last data packet
+ *   BAS_OUTBUFPAD bytes immediately before data[write] (if
+ *   write>=BAS_OUTBUFPAD) or those of the pad area (if write<BAS_OUTBUFPAD)
+ *   are also filled with that value
  */
 struct isowbuf_t {
 	atomic_t	read;
@@ -358,34 +369,28 @@
  * it is currently assigned a B channel
  */
 struct at_state_t {
-	struct list_head        list;
-	int                     waiting;
-	int                     getstring;
-	atomic_t		timer_index;
+	struct list_head	list;
+	int			waiting;
+	int			getstring;
+	unsigned		timer_index;
 	unsigned long		timer_expires;
 	int			timer_active;
-	unsigned int		ConState;                           /* State of connection */
-	struct reply_t          *replystruct;
-	int                     cid;
-	int                     int_var[VAR_NUM];   /* see VAR_XXXX */
-	char                    *str_var[STR_NUM];  /* see STR_XXXX */
-	unsigned                pending_commands;   /* see PC_XXXX */
-	atomic_t                seq_index;
+	unsigned int		ConState;	/* State of connection */
+	struct reply_t		*replystruct;
+	int			cid;
+	int			int_var[VAR_NUM];	/* see VAR_XXXX */
+	char			*str_var[STR_NUM];	/* see STR_XXXX */
+	unsigned		pending_commands;	/* see PC_XXXX */
+	unsigned		seq_index;
 
-	struct cardstate    *cs;
-	struct bc_state         *bcs;
+	struct cardstate	*cs;
+	struct bc_state		*bcs;
 };
 
 struct resp_type_t {
 	unsigned char	*response;
-	int		resp_code;           /* RSP_XXXX */
-	int		type;                /* RT_XXXX */
-};
-
-struct prot_skb {
-	atomic_t		empty;
-	struct semaphore	*sem;
-	struct sk_buff		*skb;
+	int		resp_code;	/* RSP_XXXX */
+	int		type;		/* RT_XXXX */
 };
 
 struct event_t {
@@ -398,29 +403,29 @@
 
 /* This buffer holds all information about the used B-Channel */
 struct bc_state {
-	struct sk_buff *tx_skb;                        /* Current transfer buffer to modem */
-	struct sk_buff_head squeue;	               /* B-Channel send Queue */
+	struct sk_buff *tx_skb;		/* Current transfer buffer to modem */
+	struct sk_buff_head squeue;	/* B-Channel send Queue */
 
 	/* Variables for debugging .. */
-	int corrupted;                                   /* Counter for corrupted packages */
-	int trans_down;                                  /* Counter of packages (downstream) */
-	int trans_up;                                    /* Counter of packages (upstream) */
+	int corrupted;			/* Counter for corrupted packages */
+	int trans_down;			/* Counter of packages (downstream) */
+	int trans_up;			/* Counter of packages (upstream) */
 
 	struct at_state_t at_state;
 	unsigned long rcvbytes;
 
 	__u16 fcs;
 	struct sk_buff *skb;
-	int inputstate; /* see INS_XXXX */
+	int inputstate;			/* see INS_XXXX */
 
 	int channel;
 
 	struct cardstate *cs;
 
-	unsigned chstate;			/* bitmap (CHS_*) */
+	unsigned chstate;		/* bitmap (CHS_*) */
 	int ignore;
-	unsigned	proto2;			/* Layer 2 protocol (ISDN_PROTO_L2_*) */
-	char		*commands[AT_NUM]; /* see AT_XXXX */
+	unsigned proto2;		/* Layer 2 protocol (ISDN_PROTO_L2_*) */
+	char *commands[AT_NUM];		/* see AT_XXXX */
 
 #ifdef CONFIG_GIGASET_DEBUG
 	int emptycount;
@@ -428,37 +433,39 @@
 	int busy;
 	int use_count;
 
-	/* hardware drivers */
+	/* private data of hardware drivers */
 	union {
-		struct ser_bc_state *ser;		 /* private data of serial hardware driver */
-		struct usb_bc_state *usb;		 /* private data of usb hardware driver */
-		struct bas_bc_state *bas;
+		struct ser_bc_state *ser;	/* serial hardware driver */
+		struct usb_bc_state *usb;	/* usb hardware driver (m105) */
+		struct bas_bc_state *bas;	/* usb hardware driver (base) */
 	} hw;
 };
 
 struct cardstate {
 	struct gigaset_driver *driver;
 	unsigned minor_index;
+	struct device *dev;
 
 	const struct gigaset_ops *ops;
 
 	/* Stuff to handle communication */
-	//wait_queue_head_t initwait;
 	wait_queue_head_t waitqueue;
 	int waiting;
-	atomic_t mode;                       /* see M_XXXX */
-	atomic_t mstate;                     /* Modem state: see MS_XXXX */
-	                                     /* only changed by the event layer */
+	atomic_t mode;			/* see M_XXXX */
+	atomic_t mstate;		/* Modem state: see MS_XXXX */
+					/* only changed by the event layer */
 	int cmd_result;
 
 	int channels;
-	struct bc_state *bcs;                /* Array of struct bc_state */
+	struct bc_state *bcs;		/* Array of struct bc_state */
 
-	int onechannel;                      /* data and commands transmitted in one stream (M10x) */
+	int onechannel;			/* data and commands transmitted in one
+					   stream (M10x) */
 
 	spinlock_t lock;
-	struct at_state_t at_state;          /* at_state_t for cid == 0 */
-	struct list_head temp_at_states;     /* list of temporary "struct at_state_t"s without B channel */
+	struct at_state_t at_state;	/* at_state_t for cid == 0 */
+	struct list_head temp_at_states;/* list of temporary "struct
+					   at_state_t"s without B channel */
 
 	struct inbuf_t *inbuf;
 
@@ -474,58 +481,69 @@
 	unsigned fwver[4];
 	int gotfwver;
 
-	atomic_t running;                    /* !=0 if events are handled */
-	atomic_t connected;                  /* !=0 if hardware is connected */
+	unsigned running;		/* !=0 if events are handled */
+	unsigned connected;		/* !=0 if hardware is connected */
+	unsigned isdn_up;		/* !=0 after ISDN_STAT_RUN */
 
-	atomic_t cidmode;
+	unsigned cidmode;
 
-	int myid;                            /* id for communication with LL */
+	int myid;			/* id for communication with LL */
 	isdn_if iif;
 
 	struct reply_t *tabnocid;
 	struct reply_t *tabcid;
 	int cs_init;
-	int ignoreframes;                    /* frames to ignore after setting up the B channel */
-	struct semaphore sem;                /* locks this structure: */
-	                                     /*   connected is not changed, */
-	                                     /*   hardware_up is not changed, */
-	                                     /*   MState is not changed to or from MS_LOCKED */
+	int ignoreframes;		/* frames to ignore after setting up the
+					   B channel */
+	struct mutex mutex;		/* locks this structure:
+					 *   connected is not changed,
+					 *   hardware_up is not changed,
+					 *   MState is not changed to or from
+					 *   MS_LOCKED */
 
 	struct timer_list timer;
 	int retry_count;
-	int dle;                             /* !=0 if modem commands/responses are dle encoded */
-	int cur_at_seq;                      /* sequence of AT commands being processed */
-	int curchannel;                      /* channel, those commands are meant for */
-	atomic_t commands_pending;           /* flag(s) in xxx.commands_pending have been set */
-	struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled
-	                                      *   -> for modem reponses (and incomming data for M10x)
-	                                      *   -> on timeout
-	                                      *   -> after setting bits in xxx.at_state.pending_command
-	                                      *      (e.g. command from LL) */
-	struct tasklet_struct write_tasklet; /* tasklet for serial output
-					      * (not used in base driver) */
+	int dle;			/* !=0 if modem commands/responses are
+					   dle encoded */
+	int cur_at_seq;			/* sequence of AT commands being
+					   processed */
+	int curchannel;			/* channel those commands are meant
+					   for */
+	atomic_t commands_pending;	/* flag(s) in xxx.commands_pending have
+					   been set */
+	struct tasklet_struct event_tasklet;
+					/* tasklet for serializing AT commands.
+					 * Scheduled
+					 *   -> for modem reponses (and
+					 *      incoming data for M10x)
+					 *   -> on timeout
+					 *   -> after setting bits in
+					 *      xxx.at_state.pending_command
+					 *      (e.g. command from LL) */
+	struct tasklet_struct write_tasklet;
+					/* tasklet for serial output
+					 * (not used in base driver) */
 
 	/* event queue */
 	struct event_t events[MAX_EVENTS];
-	atomic_t ev_tail, ev_head;
+	unsigned ev_tail, ev_head;
 	spinlock_t ev_lock;
 
 	/* current modem response */
 	unsigned char respdata[MAX_RESP_SIZE];
 	unsigned cbytes;
 
-	/* hardware drivers */
+	/* private data of hardware drivers */
 	union {
-		struct usb_cardstate *usb; /* private data of USB hardware driver */
-		struct ser_cardstate *ser; /* private data of serial hardware driver */
-		struct bas_cardstate *bas; /* private data of base hardware driver */
+		struct usb_cardstate *usb; /* USB hardware driver (m105) */
+		struct ser_cardstate *ser; /* serial hardware driver */
+		struct bas_cardstate *bas; /* USB hardware driver (base) */
 	} hw;
 };
 
 struct gigaset_driver {
 	struct list_head list;
-	spinlock_t lock;                       /* locks minor tables and blocked */
-	//struct semaphore sem;                /* locks this structure */
+	spinlock_t lock;		/* locks minor tables and blocked */
 	struct tty_driver *tty;
 	unsigned have_tty;
 	unsigned minor;
@@ -553,37 +571,42 @@
 	struct isow_urbctx_t	isoouturbs[BAS_OUTURBS];
 	struct isow_urbctx_t	*isooutdone, *isooutfree, *isooutovfl;
 	struct isowbuf_t	*isooutbuf;
-	unsigned numsub;			/* submitted URB counter (for diagnostic messages only) */
+	unsigned numsub;		/* submitted URB counter
+					   (for diagnostic messages only) */
 	struct tasklet_struct	sent_tasklet;
 
 	/* isochronous input state */
 	spinlock_t isoinlock;
 	struct urb *isoinurbs[BAS_INURBS];
 	unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
-	struct urb *isoindone;	                /* completed isoc read URB */
-	int loststatus;				/* status of dropped URB */
-	unsigned isoinlost;			/* number of bytes lost */
-	/* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */
-	unsigned seqlen;			/* number of '1' bits not yet unstuffed */
-	unsigned inbyte, inbits;		/* collected bits for next byte */
+	struct urb *isoindone;		/* completed isoc read URB */
+	int loststatus;			/* status of dropped URB */
+	unsigned isoinlost;		/* number of bytes lost */
+	/* state of bit unstuffing algorithm
+	   (in addition to BC_state.inputstate) */
+	unsigned seqlen;		/* number of '1' bits not yet
+					   unstuffed */
+	unsigned inbyte, inbits;	/* collected bits for next byte */
 	/* statistics */
-	unsigned goodbytes;			/* bytes correctly received */
-	unsigned alignerrs;			/* frames with incomplete byte at end */
-	unsigned fcserrs;			/* FCS errors */
-	unsigned frameerrs;			/* framing errors */
-	unsigned giants;			/* long frames */
-	unsigned runts;				/* short frames */
-	unsigned aborts;			/* HDLC aborts */
-	unsigned shared0s;			/* '0' bits shared between flags */
-	unsigned stolen0s;			/* '0' stuff bits also serving as leading flag bits */
+	unsigned goodbytes;		/* bytes correctly received */
+	unsigned alignerrs;		/* frames with incomplete byte at end */
+	unsigned fcserrs;		/* FCS errors */
+	unsigned frameerrs;		/* framing errors */
+	unsigned giants;		/* long frames */
+	unsigned runts;			/* short frames */
+	unsigned aborts;		/* HDLC aborts */
+	unsigned shared0s;		/* '0' bits shared between flags */
+	unsigned stolen0s;		/* '0' stuff bits also serving as
+					   leading flag bits */
 	struct tasklet_struct rcvd_tasklet;
 };
 
 struct gigaset_ops {
-	/* Called from ev-layer.c/interface.c for sending AT commands to the device */
+	/* Called from ev-layer.c/interface.c for sending AT commands to the
+	   device */
 	int (*write_cmd)(struct cardstate *cs,
-	                 const unsigned char *buf, int len,
-	                 struct tasklet_struct *wake_tasklet);
+			 const unsigned char *buf, int len,
+			 struct tasklet_struct *wake_tasklet);
 
 	/* Called from interface.c for additional device control */
 	int (*write_room)(struct cardstate *cs);
@@ -604,7 +627,7 @@
 	/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
 	int (*freebcshw)(struct bc_state *bcs);
 
-	/* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */
+	/* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
 	void (*reinitbcshw)(struct bc_state *bcs);
 
 	/* Called by gigaset_initcs() for setting up cs->hw.xxx */
@@ -613,13 +636,10 @@
 	/* Called by gigaset_freecs() for freeing cs->hw.xxx */
 	void (*freecshw)(struct cardstate *cs);
 
-	///* Called by gigaset_stop() for killing URBs, shutting down the device, ...
-	//   hardwareup: ==0: don't try to shut down the device, hardware is really not accessible
-	//	       !=0: hardware still up */
-	//void (*stophw)(struct cardstate *cs, int hardwareup);
-
-	/* Called from common.c/interface.c for additional serial port control */
-	int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state);
+	/* Called from common.c/interface.c for additional serial port
+	   control */
+	int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state,
+			      unsigned new_state);
 	int (*baud_rate)(struct cardstate *cs, unsigned cflag);
 	int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag);
 
@@ -639,7 +659,7 @@
  * <DLE_FLAG>:  0x10
  * <EVENT>:     ((a-z)* | (A-Z)* | (0-10)*)+
  */
-#define DLE_FLAG       0x10
+#define DLE_FLAG	0x10
 
 /* ===========================================================================
  *  Functions implemented in asyncdata.c
@@ -667,7 +687,8 @@
 
 /* Called from bas-gigaset.c to process a block of data
  * received through the isochronous channel */
-void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs);
+void gigaset_isoc_receive(unsigned char *src, unsigned count,
+			  struct bc_state *bcs);
 
 /* Called from bas-gigaset.c to put a block of data
  * into the isochronous output buffer */
@@ -703,7 +724,7 @@
 	isdn_ctrl response;
 
 	/* error -> LL */
-	dbg(DEBUG_CMD, "sending L1ERR");
+	gig_dbg(DEBUG_CMD, "sending L1ERR");
 	response.driver = bcs->cs->myid;
 	response.command = ISDN_STAT_L1ERR;
 	response.arg = bcs->channel;
@@ -727,8 +748,8 @@
  */
 
 /* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface);
-void gigaset_free_dev_sysfs(struct usb_interface *interface);
+void gigaset_init_dev_sysfs(struct cardstate *cs);
+void gigaset_free_dev_sysfs(struct cardstate *cs);
 
 /* ===========================================================================
  *  Functions implemented in common.c/gigaset.h
@@ -736,7 +757,7 @@
 
 void gigaset_bcs_reinit(struct bc_state *bcs);
 void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
-                     struct cardstate *cs, int cid);
+		     struct cardstate *cs, int cid);
 int gigaset_get_channel(struct bc_state *bcs);
 void gigaset_free_channel(struct bc_state *bcs);
 int gigaset_get_channels(struct cardstate *cs);
@@ -745,16 +766,15 @@
 
 /* Allocate and initialize driver structure. */
 struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
-                                          const char *procname,
-                                          const char *devname,
-                                          const char *devfsname,
-                                          const struct gigaset_ops *ops,
-                                          struct module *owner);
+					  const char *procname,
+					  const char *devname,
+					  const char *devfsname,
+					  const struct gigaset_ops *ops,
+					  struct module *owner);
 
 /* Deallocate driver structure. */
 void gigaset_freedriver(struct gigaset_driver *drv);
 void gigaset_debugdrivers(void);
-struct cardstate *gigaset_get_cs_by_minor(unsigned minor);
 struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
 struct cardstate *gigaset_get_cs_by_id(int id);
 
@@ -763,7 +783,8 @@
 void gigaset_unassign(struct cardstate *cs);
 void gigaset_blockdriver(struct gigaset_driver *drv);
 
-/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */
+/* Allocate and initialize card state. Calls hardware dependent
+   gigaset_init[b]cs(). */
 struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
 				 int onechannel, int ignoreframes,
 				 int cidmode, const char *modulename);
@@ -788,8 +809,8 @@
  * ptr must be kmalloc()ed (and not be freed by the caller).
  */
 struct event_t *gigaset_add_event(struct cardstate *cs,
-                                  struct at_state_t *at_state, int type,
-                                  void *ptr, int parameter, void *arg);
+				  struct at_state_t *at_state, int type,
+				  void *ptr, int parameter, void *arg);
 
 /* Called on CONFIG1 command from frontend. */
 int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode
@@ -799,7 +820,7 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&cs->lock, flags);
-	if (atomic_read(&cs->running))
+	if (cs->running)
 		tasklet_schedule(&cs->event_tasklet);
 	spin_unlock_irqrestore(&cs->lock, flags);
 }
@@ -810,7 +831,7 @@
 {
 	gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL);
 
-	dbg(DEBUG_CMD, "scheduling BC_CLOSED");
+	gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED");
 	gigaset_schedule_event(bcs->cs);
 }
 
@@ -820,36 +841,19 @@
 {
 	gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL);
 
-	dbg(DEBUG_CMD, "scheduling BC_OPEN");
+	gig_dbg(DEBUG_CMD, "scheduling BC_OPEN");
 	gigaset_schedule_event(bcs->cs);
 }
 
 /* handling routines for sk_buff */
 /* ============================= */
 
-/* private version of __skb_put()
- * append 'len' bytes to the content of 'skb', already knowing that the
- * existing buffer can accomodate them
- * returns a pointer to the location where the new bytes should be copied to
- * This function does not take any locks so it must be called with the
- * appropriate locks held only.
- */
-static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb,
-                                                   unsigned int len)
-{
-	unsigned char *tmp = skb->tail;
-	/*SKB_LINEAR_ASSERT(skb);*/		/* not needed here */
-	skb->tail += len;
-	skb->len += len;
-	return tmp;
-}
-
 /* pass received skb to LL
  * Warning: skb must not be accessed anymore!
  */
 static inline void gigaset_rcv_skb(struct sk_buff *skb,
-                                   struct cardstate *cs,
-                                   struct bc_state *bcs)
+				   struct cardstate *cs,
+				   struct bc_state *bcs)
 {
 	cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb);
 	bcs->trans_down++;
@@ -859,8 +863,8 @@
  * Warning: skb must not be accessed anymore!
  */
 static inline void gigaset_rcv_error(struct sk_buff *procskb,
-                                     struct cardstate *cs,
-                                     struct bc_state *bcs)
+				     struct cardstate *cs,
+				     struct bc_state *bcs)
 {
 	if (procskb)
 		dev_kfree_skb(procskb);
@@ -877,46 +881,9 @@
 /* bitwise byte inversion table */
 extern __u8 gigaset_invtab[];	/* in common.c */
 
-
 /* append received bytes to inbuf */
-static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf,
-                                     const unsigned char *src,
-                                     unsigned numbytes)
-{
-	unsigned n, head, tail, bytesleft;
-
-	dbg(DEBUG_INTR, "received %u bytes", numbytes);
-
-	if (!numbytes)
-		return 0;
-
-	bytesleft = numbytes;
-	tail = atomic_read(&inbuf->tail);
-	head = atomic_read(&inbuf->head);
-	dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
-
-	while (bytesleft) {
-		if (head > tail)
-			n = head - 1 - tail;
-		else if (head == 0)
-			n = (RBUFSIZE-1) - tail;
-		else
-			n = RBUFSIZE - tail;
-		if (!n) {
-			err("buffer overflow (%u bytes lost)", bytesleft);
-			break;
-		}
-		if (n > bytesleft)
-			n = bytesleft;
-		memcpy(inbuf->data + tail, src, n);
-		bytesleft -= n;
-		tail = (tail + n) % RBUFSIZE;
-		src += n;
-	}
-	dbg(DEBUG_INTR, "setting tail to %u", tail);
-	atomic_set(&inbuf->tail, tail);
-	return numbytes != bytesleft;
-}
+int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
+		       unsigned numbytes);
 
 /* ===========================================================================
  *  Functions implemented in interface.c
@@ -924,7 +891,7 @@
 
 /* initialize interface */
 void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
-                           const char *devname, const char *devfsname);
+			   const char *devname, const char *devfsname);
 /* release interface */
 void gigaset_if_freedriver(struct gigaset_driver *drv);
 /* add minor */
@@ -933,6 +900,6 @@
 void gigaset_if_free(struct cardstate *cs);
 /* device received data */
 void gigaset_if_receive(struct cardstate *cs,
-                        unsigned char *buffer, size_t len);
+			unsigned char *buffer, size_t len);
 
 #endif
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 731a675..1654fa4 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -1,9 +1,9 @@
 /*
  * Stuff used by all variants of the driver
  *
- * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de),
- *                       Hansjoerg Lipp (hjlipp@web.de),
- *                       Tilman Schmidt (tilman@imap.cc).
+ * Copyright (c) 2001 by Stefan Eilers,
+ *                       Hansjoerg Lipp <hjlipp@web.de>,
+ *                       Tilman Schmidt <tilman@imap.cc>.
  *
  * =====================================================================
  *	This program is free software; you can redistribute it and/or
@@ -11,15 +11,11 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
 
-/* == Handling of I4L IO ============================================================================*/
+/* == Handling of I4L IO =====================================================*/
 
 /* writebuf_from_LL
  * called by LL to transmit data on an open channel
@@ -29,14 +25,16 @@
  * parameters:
  *	driverID	driver ID as assigned by LL
  *	channel		channel number
- *	ack		if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT)
+ *	ack		if != 0 LL wants to be notified on completion via
+ *			statcallb(ISDN_STAT_BSENT)
  *	skb		skb containing data to send
  * return value:
  *	number of accepted bytes
  *	0 if temporarily unable to accept data (out of buffer space)
  *	<0 on error (eg. -EINVAL)
  */
-static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb)
+static int writebuf_from_LL(int driverID, int channel, int ack,
+			    struct sk_buff *skb)
 {
 	struct cardstate *cs;
 	struct bc_state *bcs;
@@ -54,28 +52,25 @@
 	bcs = &cs->bcs[channel];
 	len = skb->len;
 
-	dbg(DEBUG_LLDATA,
-	    "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)",
-	    driverID, channel, ack, len);
+	gig_dbg(DEBUG_LLDATA,
+		"Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)",
+		driverID, channel, ack, len);
 
 	if (!len) {
 		if (ack)
-			warn("not ACKing empty packet from LL");
+			notice("%s: not ACKing empty packet", __func__);
 		return 0;
 	}
 	if (len > MAX_BUF_SIZE) {
-		err("%s: packet too large (%d bytes)", __func__, channel);
+		err("%s: packet too large (%d bytes)", __func__, len);
 		return -EINVAL;
 	}
 
-	if (!atomic_read(&cs->connected))
-		return -ENODEV;
-
 	skblen = ack ? len : 0;
 	skb->head[0] = skblen & 0xff;
 	skb->head[1] = skblen >> 8;
-	dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen,
-	     (unsigned) skb->head[0], (unsigned) skb->head[1]);
+	gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
+		len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
 
 	/* pass to device-specific module */
 	return cs->ops->send_skb(bcs, skb);
@@ -89,14 +84,14 @@
 	++bcs->trans_up;
 
 	if (skb->len)
-		warn("%s: skb->len==%d", __func__, skb->len);
+		dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
+			 __func__, skb->len);
 
 	len = (unsigned char) skb->head[0] |
 	      (unsigned) (unsigned char) skb->head[1] << 8;
 	if (len) {
-		dbg(DEBUG_MCMD,
-		    "Acknowledge sending to LL (id: %d, channel: %d size: %u)",
-		    bcs->cs->myid, bcs->channel, len);
+		gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
+			bcs->cs->myid, bcs->channel, len);
 
 		response.driver = bcs->cs->myid;
 		response.command = ISDN_STAT_BSENT;
@@ -119,15 +114,12 @@
 	struct bc_state *bcs;
 	int retval = 0;
 	struct setup_parm *sp;
+	unsigned param;
+	unsigned long flags;
 
-	//dbg(DEBUG_ANY, "Gigaset_HW: Receiving command");
 	gigaset_debugdrivers();
 
-	/* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or
-	 * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent !
-	 */
-	//FIXME "remove test for &connected"
-	if ((!cs || !atomic_read(&cs->connected))) {
+	if (!cs) {
 		warn("LL tried to access unknown device with nr. %d",
 		     cntrl->driver);
 		return -ENODEV;
@@ -135,29 +127,30 @@
 
 	switch (cntrl->command) {
 	case ISDN_CMD_IOCTL:
-
-		dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)",
-		    cntrl->driver, cntrl->arg);
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
+			cntrl->driver, cntrl->arg);
 
 		warn("ISDN_CMD_IOCTL is not supported.");
 		return -EINVAL;
 
 	case ISDN_CMD_DIAL:
-		dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, "
-		    "phone: %s,ownmsn: %s, si1: %d, si2: %d)",
-		    cntrl->driver, cntrl->arg,
-		    cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
-		    cntrl->parm.setup.si1, cntrl->parm.setup.si2);
+		gig_dbg(DEBUG_ANY,
+			"ISDN_CMD_DIAL (driver: %d, ch: %ld, "
+			"phone: %s, ownmsn: %s, si1: %d, si2: %d)",
+			cntrl->driver, cntrl->arg,
+			cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
+			cntrl->parm.setup.si1, cntrl->parm.setup.si2);
 
 		if (cntrl->arg >= cs->channels) {
-			err("invalid channel (%d)", (int) cntrl->arg);
+			err("ISDN_CMD_DIAL: invalid channel (%d)",
+			    (int) cntrl->arg);
 			return -EINVAL;
 		}
 
 		bcs = cs->bcs + cntrl->arg;
 
 		if (!gigaset_get_channel(bcs)) {
-			err("channel not free");
+			err("ISDN_CMD_DIAL: channel not free");
 			return -EBUSY;
 		}
 
@@ -169,42 +162,46 @@
 		}
 		*sp = cntrl->parm.setup;
 
-		if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
-			               atomic_read(&bcs->at_state.seq_index),
-			               NULL)) {
+		spin_lock_irqsave(&cs->lock, flags);
+		param = bcs->at_state.seq_index;
+		spin_unlock_irqrestore(&cs->lock, flags);
+
+		if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param,
+				       NULL)) {
 			//FIXME what should we do?
 			kfree(sp);
 			gigaset_free_channel(bcs);
 			return -ENOMEM;
 		}
 
-		dbg(DEBUG_CMD, "scheduling DIAL");
+		gig_dbg(DEBUG_CMD, "scheduling DIAL");
 		gigaset_schedule_event(cs);
 		break;
 	case ISDN_CMD_ACCEPTD: //FIXME
-		dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
 
 		if (cntrl->arg >= cs->channels) {
-			err("invalid channel (%d)", (int) cntrl->arg);
+			err("ISDN_CMD_ACCEPTD: invalid channel (%d)",
+			    (int) cntrl->arg);
 			return -EINVAL;
 		}
 
 		if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
-			               EV_ACCEPT, NULL, 0, NULL)) {
+				       EV_ACCEPT, NULL, 0, NULL)) {
 			//FIXME what should we do?
 			return -ENOMEM;
 		}
 
-		dbg(DEBUG_CMD, "scheduling ACCEPT");
+		gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
 		gigaset_schedule_event(cs);
 
 		break;
 	case ISDN_CMD_ACCEPTB:
-		dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
 		break;
 	case ISDN_CMD_HANGUP:
-		dbg(DEBUG_ANY,
-		    "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg);
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
+			(int) cntrl->arg);
 
 		if (cntrl->arg >= cs->channels) {
 			err("ISDN_CMD_HANGUP: invalid channel (%u)",
@@ -213,66 +210,68 @@
 		}
 
 		if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
-			               EV_HUP, NULL, 0, NULL)) {
+				       EV_HUP, NULL, 0, NULL)) {
 			//FIXME what should we do?
 			return -ENOMEM;
 		}
 
-		dbg(DEBUG_CMD, "scheduling HUP");
+		gig_dbg(DEBUG_CMD, "scheduling HUP");
 		gigaset_schedule_event(cs);
 
 		break;
-	case ISDN_CMD_CLREAZ:               /* Do not signal incoming signals */ //FIXME
-		dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
+	case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
 		break;
-	case ISDN_CMD_SETEAZ:               /* Signal incoming calls for given MSN */ //FIXME
-		dbg(DEBUG_ANY,
-		    "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)",
-		    cntrl->driver, cntrl->arg, cntrl->parm.num);
+	case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
+		gig_dbg(DEBUG_ANY,
+			"ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
+			cntrl->driver, cntrl->arg, cntrl->parm.num);
 		break;
-	case ISDN_CMD_SETL2:                /* Set L2 to given protocol */
-		dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)",
-		     cntrl->arg & 0xff, (cntrl->arg >> 8));
+	case ISDN_CMD_SETL2: /* Set L2 to given protocol */
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
+			cntrl->arg & 0xff, (cntrl->arg >> 8));
 
 		if ((cntrl->arg & 0xff) >= cs->channels) {
-			err("invalid channel (%u)",
+			err("ISDN_CMD_SETL2: invalid channel (%u)",
 			    (unsigned) cntrl->arg & 0xff);
 			return -EINVAL;
 		}
 
 		if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
-		                       EV_PROTO_L2, NULL, cntrl->arg >> 8,
-		                       NULL)) {
+				       EV_PROTO_L2, NULL, cntrl->arg >> 8,
+				       NULL)) {
 			//FIXME what should we do?
 			return -ENOMEM;
 		}
 
-		dbg(DEBUG_CMD, "scheduling PROTO_L2");
+		gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
 		gigaset_schedule_event(cs);
 		break;
-	case ISDN_CMD_SETL3:              /* Set L3 to given protocol */
-		dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)",
-		     cntrl->arg & 0xff, (cntrl->arg >> 8));
+	case ISDN_CMD_SETL3: /* Set L3 to given protocol */
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
+			cntrl->arg & 0xff, (cntrl->arg >> 8));
 
 		if ((cntrl->arg & 0xff) >= cs->channels) {
-			err("invalid channel (%u)",
+			err("ISDN_CMD_SETL3: invalid channel (%u)",
 			    (unsigned) cntrl->arg & 0xff);
 			return -EINVAL;
 		}
 
 		if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
-			err("invalid protocol %lu", cntrl->arg >> 8);
+			err("ISDN_CMD_SETL3: invalid protocol %lu",
+			    cntrl->arg >> 8);
 			return -EINVAL;
 		}
 
 		break;
 	case ISDN_CMD_PROCEED:
-		dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
 		break;
 	case ISDN_CMD_ALERT:
-		dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
 		if (cntrl->arg >= cs->channels) {
-			err("invalid channel (%d)", (int) cntrl->arg);
+			err("ISDN_CMD_ALERT: invalid channel (%d)",
+			    (int) cntrl->arg);
 			return -EINVAL;
 		}
 		//bcs = cs->bcs + cntrl->arg;
@@ -280,32 +279,31 @@
 		// FIXME
 		break;
 	case ISDN_CMD_REDIR:
-		dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
 		break;
 	case ISDN_CMD_PROT_IO:
-		dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
 		break;
 	case ISDN_CMD_FAXCMD:
-		dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD");
 		break;
 	case ISDN_CMD_GETL2:
-		dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2");
 		break;
 	case ISDN_CMD_GETL3:
-		dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3");
 		break;
 	case ISDN_CMD_GETEAZ:
-		dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");
 		break;
 	case ISDN_CMD_SETSIL:
-		dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");
 		break;
 	case ISDN_CMD_GETSIL:
-		dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
+		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");
 		break;
 	default:
-		err("unknown command %d from LL",
-		     cntrl->command);
+		err("unknown command %d from LL", cntrl->command);
 		return -EINVAL;
 	}
 
@@ -350,7 +348,8 @@
 		proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
 		break;
 	default:
-		err("invalid protocol: %u", bcs->proto2);
+		dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",
+			__func__, bcs->proto2);
 		return -EINVAL;
 	}
 
@@ -378,7 +377,7 @@
 		bcs->commands[i] = NULL;
 		if (length[i] &&
 		    !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
-			err("out of memory");
+			dev_err(bcs->cs->dev, "out of memory\n");
 			return -ENOMEM;
 		}
 	}
@@ -396,10 +395,14 @@
 	}
 
 	if (bcs->commands[AT_MSN])
-		snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn);
-	snprintf(bcs->commands[AT_BC   ], length[AT_BC   ], "^SBC=%s\r", bc);
-	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
-	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ], "^SISO=%u\r", (unsigned)bcs->channel + 1);
+		snprintf(bcs->commands[AT_MSN], length[AT_MSN],
+			 "^SMSN=%s\r", sp->eazmsn);
+	snprintf(bcs->commands[AT_BC   ], length[AT_BC   ],
+		 "^SBC=%s\r", bc);
+	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+		 "^SBPR=%u\r", proto);
+	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],
+		 "^SISO=%u\r", (unsigned)bcs->channel + 1);
 
 	return 0;
 }
@@ -419,7 +422,8 @@
 		proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
 		break;
 	default:
-		err("invalid protocol: %u", bcs->proto2);
+		dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",
+			__func__, bcs->proto2);
 		return -EINVAL;
 	}
 
@@ -436,13 +440,15 @@
 		bcs->commands[i] = NULL;
 		if (length[i] &&
 		    !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
-			err("out of memory");
+			dev_err(at_state->cs->dev, "out of memory\n");
 			return -ENOMEM;
 		}
 	}
 
-	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto);
-	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ], "^SISO=%u\r", (unsigned) bcs->channel + 1);
+	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
+		 "^SBPR=%u\r", proto);
+	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],
+		 "^SISO=%u\r", (unsigned) bcs->channel + 1);
 
 	return 0;
 }
@@ -473,7 +479,7 @@
 		response.parm.setup.si1 = 1;
 		response.parm.setup.si2 = 2;
 	} else {
-		warn("RING ignored - unsupported BC %s",
+		dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",
 		     at_state->str_var[STR_ZBC]);
 		return ICALL_IGNORE;
 	}
@@ -491,18 +497,17 @@
 		response.parm.setup.eazmsn[0] = 0;
 
 	if (!bcs) {
-		notice("no channel for incoming call");
-		dbg(DEBUG_CMD, "Sending ICALLW");
+		dev_notice(cs->dev, "no channel for incoming call\n");
 		response.command = ISDN_STAT_ICALLW;
 		response.arg = 0; //FIXME
 	} else {
-		dbg(DEBUG_CMD, "Sending ICALL");
+		gig_dbg(DEBUG_CMD, "Sending ICALL");
 		response.command = ISDN_STAT_ICALL;
 		response.arg = bcs->channel; //FIXME
 	}
 	response.driver = cs->myid;
 	retval = cs->iif.statcallb(&response);
-	dbg(DEBUG_CMD, "Response: %d", retval);
+	gig_dbg(DEBUG_CMD, "Response: %d", retval);
 	switch (retval) {
 	case 0:	/* no takers */
 		return ICALL_IGNORE;
@@ -512,7 +517,8 @@
 	case 2:	/* reject */
 		return ICALL_REJECT;
 	case 3:	/* incomplete */
-		warn("LL requested unsupported feature: Incomplete Number");
+		dev_warn(cs->dev,
+		       "LL requested unsupported feature: Incomplete Number\n");
 		return ICALL_IGNORE;
 	case 4:	/* proceeding */
 		/* Gigaset will send ALERTING anyway.
@@ -520,10 +526,11 @@
 		 */
 		return ICALL_ACCEPT;
 	case 5:	/* deflect */
-		warn("LL requested unsupported feature: Call Deflection");
+		dev_warn(cs->dev,
+			 "LL requested unsupported feature: Call Deflection\n");
 		return ICALL_IGNORE;
 	default:
-		err("LL error %d on ICALL", retval);
+		dev_err(cs->dev, "LL error %d on ICALL\n", retval);
 		return ICALL_IGNORE;
 	}
 }
@@ -533,7 +540,7 @@
 {
 	isdn_if *iif = &cs->iif;
 
-	dbg(DEBUG_ANY, "Register driver capabilities to LL");
+	gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
 
 	//iif->id[sizeof(iif->id) - 1]=0;
 	//strncpy(iif->id, isdnid, sizeof(iif->id) - 1);
@@ -542,26 +549,26 @@
 		return -ENOMEM; //FIXME EINVAL/...??
 
 	iif->owner = THIS_MODULE;
-	iif->channels = cs->channels;                        /* I am supporting just one channel *//* I was supporting...*/
+	iif->channels = cs->channels;
 	iif->maxbufsize = MAX_BUF_SIZE;
-	iif->features = ISDN_FEATURE_L2_TRANS |   /* Our device is very advanced, therefore */
+	iif->features = ISDN_FEATURE_L2_TRANS |
 		ISDN_FEATURE_L2_HDLC |
 #ifdef GIG_X75
 		ISDN_FEATURE_L2_X75I |
 #endif
 		ISDN_FEATURE_L3_TRANS |
 		ISDN_FEATURE_P_EURO;
-	iif->hl_hdrlen = HW_HDR_LEN;              /* Area for storing ack */
+	iif->hl_hdrlen = HW_HDR_LEN;		/* Area for storing ack */
 	iif->command = command_from_LL;
 	iif->writebuf_skb = writebuf_from_LL;
-	iif->writecmd = NULL;                     /* Don't support isdnctrl */
-	iif->readstat = NULL;                     /* Don't support isdnctrl */
-	iif->rcvcallb_skb = NULL;                 /* Will be set by LL */
-	iif->statcallb = NULL;                    /* Will be set by LL */
+	iif->writecmd = NULL;			/* Don't support isdnctrl */
+	iif->readstat = NULL;			/* Don't support isdnctrl */
+	iif->rcvcallb_skb = NULL;		/* Will be set by LL */
+	iif->statcallb = NULL;			/* Will be set by LL */
 
 	if (!register_isdn(iif))
 		return 0;
 
-	cs->myid = iif->channels;                 /* Set my device id */
+	cs->myid = iif->channels;		/* Set my device id */
 	return 1;
 }
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 3a81d9c..08e4c4e 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -9,8 +9,6 @@
  *    published by the Free Software Foundation; either version 2 of
  *    the License, or (at your option) any later version.
  * =====================================================================
- * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -24,7 +22,7 @@
 {
 	int cmd = *arg;
 
-	dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
+	gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);
 
 	if (cmd > 1)
 		return -EINVAL;
@@ -35,7 +33,7 @@
 	}
 
 	if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
-	    && atomic_read(&cs->connected)) {
+	    && cs->connected) {
 		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
 		cs->ops->baud_rate(cs, B115200);
 		cs->ops->set_line_ctrl(cs, CS8);
@@ -44,12 +42,12 @@
 
 	cs->waiting = 1;
 	if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,
-		               NULL, cmd, NULL)) {
+			       NULL, cmd, NULL)) {
 		cs->waiting = 0;
 		return -ENOMEM;
 	}
 
-	dbg(DEBUG_CMD, "scheduling IF_LOCK");
+	gig_dbg(DEBUG_CMD, "scheduling IF_LOCK");
 	gigaset_schedule_event(cs);
 
 	wait_event(cs->waitqueue, !cs->waiting);
@@ -68,7 +66,7 @@
 	static const unsigned compat[4] = GIG_COMPAT;
 	unsigned cmd = arg[0];
 
-	dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
+	gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);
 
 	switch (cmd) {
 	case GIGVER_DRIVER:
@@ -80,12 +78,12 @@
 	case GIGVER_FWBASE:
 		cs->waiting = 1;
 		if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,
-			               NULL, 0, arg)) {
+				       NULL, 0, arg)) {
 			cs->waiting = 0;
 			return -ENOMEM;
 		}
 
-		dbg(DEBUG_CMD, "scheduling IF_VER");
+		gig_dbg(DEBUG_CMD, "scheduling IF_VER");
 		gigaset_schedule_event(cs);
 
 		wait_event(cs->waitqueue, !cs->waiting);
@@ -101,7 +99,7 @@
 
 static int if_config(struct cardstate *cs, int *arg)
 {
-	dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
+	gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);
 
 	if (*arg != 1)
 		return -EINVAL;
@@ -109,6 +107,11 @@
 	if (atomic_read(&cs->mstate) != MS_LOCKED)
 		return -EBUSY;
 
+	if (!cs->connected) {
+		err("not connected!");
+		return -ENODEV;
+	}
+
 	*arg = 0;
 	return gigaset_enterconfigmode(cs);
 }
@@ -119,7 +122,7 @@
 static int  if_open(struct tty_struct *tty, struct file *filp);
 static void if_close(struct tty_struct *tty, struct file *filp);
 static int  if_ioctl(struct tty_struct *tty, struct file *file,
-                     unsigned int cmd, unsigned long arg);
+		     unsigned int cmd, unsigned long arg);
 static int  if_write_room(struct tty_struct *tty);
 static int  if_chars_in_buffer(struct tty_struct *tty);
 static void if_throttle(struct tty_struct *tty);
@@ -127,9 +130,9 @@
 static void if_set_termios(struct tty_struct *tty, struct termios *old);
 static int  if_tiocmget(struct tty_struct *tty, struct file *file);
 static int  if_tiocmset(struct tty_struct *tty, struct file *file,
-                        unsigned int set, unsigned int clear);
+			unsigned int set, unsigned int clear);
 static int  if_write(struct tty_struct *tty,
-                     const unsigned char *buf, int count);
+		     const unsigned char *buf, int count);
 
 static struct tty_operations if_ops = {
 	.open =			if_open,
@@ -153,8 +156,8 @@
 	struct cardstate *cs;
 	unsigned long flags;
 
-	dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index,
-	    __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%d+%d: %s()",
+		tty->driver->minor_start, tty->index, __func__);
 
 	tty->driver_data = NULL;
 
@@ -162,7 +165,7 @@
 	if (!cs)
 		return -ENODEV;
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 	tty->driver_data = cs;
 
@@ -173,10 +176,9 @@
 		cs->tty = tty;
 		spin_unlock_irqrestore(&cs->lock, flags);
 		tty->low_latency = 1; //FIXME test
-		//FIXME
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 	return 0;
 }
 
@@ -187,30 +189,29 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else {
 		if (!--cs->open_count) {
 			spin_lock_irqsave(&cs->lock, flags);
 			cs->tty = NULL;
 			spin_unlock_irqrestore(&cs->lock, flags);
-			//FIXME
 		}
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 
 static int if_ioctl(struct tty_struct *tty, struct file *file,
-                    unsigned int cmd, unsigned long arg)
+		    unsigned int cmd, unsigned long arg)
 {
 	struct cardstate *cs;
 	int retval = -ENODEV;
@@ -220,17 +221,17 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd);
+	gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else {
 		retval = 0;
 		switch (cmd) {
@@ -250,37 +251,40 @@
 			break;
 		case GIGASET_BRKCHARS:
 			//FIXME test if MS_LOCKED
-			gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
-			                   6, (const unsigned char *) arg, 1);
-			if (!atomic_read(&cs->connected)) {
-				dbg(DEBUG_ANY, "can't communicate with unplugged device");
+			if (!cs->connected) {
+				gig_dbg(DEBUG_ANY,
+				    "can't communicate with unplugged device");
 				retval = -ENODEV;
 				break;
 			}
 			retval = copy_from_user(&buf,
-			                        (const unsigned char __user *) arg, 6)
-			         ? -EFAULT : 0;
-			if (retval >= 0)
+					(const unsigned char __user *) arg, 6)
+				? -EFAULT : 0;
+			if (retval >= 0) {
+				gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",
+						6, (const unsigned char *) arg);
 				retval = cs->ops->brkchars(cs, buf);
+			}
 			break;
 		case GIGASET_VERSION:
-			retval = copy_from_user(version, (unsigned __user *) arg,
-			                        sizeof version) ? -EFAULT : 0;
+			retval = copy_from_user(version,
+					(unsigned __user *) arg, sizeof version)
+				? -EFAULT : 0;
 			if (retval >= 0)
 				retval = if_version(cs, version);
 			if (retval >= 0)
-				retval = copy_to_user((unsigned __user *) arg, version,
-				                      sizeof version)
-				         ? -EFAULT : 0;
+				retval = copy_to_user((unsigned __user *) arg,
+						      version, sizeof version)
+					? -EFAULT : 0;
 			break;
-	        default:
-			dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
-			    __FUNCTION__, cmd);
+		default:
+			gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",
+				__func__, cmd);
 			retval = -ENOIOCTLCMD;
 		}
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
@@ -292,25 +296,25 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	// FIXME read from device?
 	retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
 
 static int if_tiocmset(struct tty_struct *tty, struct file *file,
-                       unsigned int set, unsigned int clear)
+		       unsigned int set, unsigned int clear)
 {
 	struct cardstate *cs;
 	int retval;
@@ -318,18 +322,18 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF,
-	    "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear);
+	gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)",
+		cs->minor_index, __func__, set, clear);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
-	if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_ANY, "can't communicate with unplugged device");
+	if (!cs->connected) {
+		gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
 		retval = -ENODEV;
 	} else {
 		mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR);
@@ -337,7 +341,7 @@
 		cs->control_state = mc;
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
@@ -349,29 +353,29 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
 		warn("can't write to unlocked device");
 		retval = -EBUSY;
-	} else if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_ANY, "can't write to unplugged device");
+	} else if (!cs->connected) {
+		gig_dbg(DEBUG_ANY, "can't write to unplugged device");
 		retval = -EBUSY; //FIXME
 	} else {
 		retval = cs->ops->write_cmd(cs, buf, count,
-		                            &cs->if_wake_tasklet);
+					    &cs->if_wake_tasklet);
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
@@ -383,27 +387,27 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
 		warn("can't write to unlocked device");
 		retval = -EBUSY; //FIXME
-	} else if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_ANY, "can't write to unplugged device");
+	} else if (!cs->connected) {
+		gig_dbg(DEBUG_ANY, "can't write to unplugged device");
 		retval = -EBUSY; //FIXME
 	} else
 		retval = cs->ops->write_room(cs);
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
@@ -415,27 +419,27 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return -ENODEV;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
 		warn("can't write to unlocked device");
 		retval = -EBUSY;
-	} else if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_ANY, "can't write to unplugged device");
+	} else if (!cs->connected) {
+		gig_dbg(DEBUG_ANY, "can't write to unplugged device");
 		retval = -EBUSY; //FIXME
 	} else
 		retval = cs->ops->chars_in_buffer(cs);
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return retval;
 }
@@ -446,21 +450,21 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else {
 		//FIXME
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 
 static void if_unthrottle(struct tty_struct *tty)
@@ -469,21 +473,21 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	if (!cs->open_count)
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 	else {
 		//FIXME
 	}
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 
 static void if_set_termios(struct tty_struct *tty, struct termios *old)
@@ -496,21 +500,21 @@
 
 	cs = (struct cardstate *) tty->driver_data;
 	if (!cs) {
-		err("cs==NULL in %s", __FUNCTION__);
+		err("cs==NULL in %s", __func__);
 		return;
 	}
 
-	dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__);
+	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
 
-	down(&cs->sem);
+	mutex_lock(&cs->mutex);
 
 	if (!cs->open_count) {
-		warn("%s: device not opened", __FUNCTION__);
+		warn("%s: device not opened", __func__);
 		goto out;
 	}
 
-	if (!atomic_read(&cs->connected)) {
-		dbg(DEBUG_ANY, "can't communicate with unplugged device");
+	if (!cs->connected) {
+		gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");
 		goto out;
 	}
 
@@ -518,8 +522,8 @@
 	iflag = tty->termios->c_iflag;
 	cflag = tty->termios->c_cflag;
 	old_cflag = old ? old->c_cflag : cflag; //FIXME?
-	dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index,
-	    iflag, cflag, old_cflag);
+	gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
+		cs->minor_index, iflag, cflag, old_cflag);
 
 	/* get a local copy of the current port settings */
 	control_state = cs->control_state;
@@ -531,14 +535,15 @@
 	 * Premature optimization is the root of all evil.
 	 */
 
-        /* reassert DTR and (maybe) RTS on transition from B0 */
+	/* reassert DTR and (maybe) RTS on transition from B0 */
 	if ((old_cflag & CBAUD) == B0) {
 		new_state = control_state | TIOCM_DTR;
 		/* don't set RTS if using hardware flow control */
 		if (!(old_cflag & CRTSCTS))
 			new_state |= TIOCM_RTS;
-		dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index,
-		    (new_state & TIOCM_RTS) ? " only" : "/RTS");
+		gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s",
+			cs->minor_index,
+			(new_state & TIOCM_RTS) ? " only" : "/RTS");
 		cs->ops->set_modem_ctrl(cs, control_state, new_state);
 		control_state = new_state;
 	}
@@ -547,7 +552,7 @@
 
 	if ((cflag & CBAUD) == B0) {
 		/* Drop RTS and DTR */
-		dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
+		gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index);
 		new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS);
 		cs->ops->set_modem_ctrl(cs, control_state, new_state);
 		control_state = new_state;
@@ -567,15 +572,17 @@
 	 * Just do what we have seen with SniffUSB on Win98.
 	 */
 	/* Drop DTR/RTS if no flow control otherwise assert */
-	dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state);
+	gig_dbg(DEBUG_IF, "%u: control_state %x",
+		cs->minor_index, control_state);
 	new_state = control_state;
 	if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
 		new_state |= TIOCM_DTR | TIOCM_RTS;
 	else
 		new_state &= ~(TIOCM_DTR | TIOCM_RTS);
 	if (new_state != control_state) {
-		dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state);
-		gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug?
+		gig_dbg(DEBUG_IF, "%u: new_state %x",
+			cs->minor_index, new_state);
+		gigaset_set_modem_ctrl(cs, control_state, new_state);
 		control_state = new_state;
 	}
 #endif
@@ -584,7 +591,7 @@
 	cs->control_state = control_state;
 
 out:
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 }
 
 
@@ -600,7 +607,7 @@
 
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup) {
-		dbg(DEBUG_IF, "write wakeup call");
+		gig_dbg(DEBUG_IF, "write wakeup call");
 		tty->ldisc.write_wakeup(tty);
 	}
 
@@ -635,14 +642,14 @@
 }
 
 void gigaset_if_receive(struct cardstate *cs,
-                        unsigned char *buffer, size_t len)
+			unsigned char *buffer, size_t len)
 {
 	unsigned long flags;
 	struct tty_struct *tty;
 
 	spin_lock_irqsave(&cs->lock, flags);
 	if ((tty = cs->tty) == NULL)
-		dbg(DEBUG_ANY, "receive on closed device");
+		gig_dbg(DEBUG_ANY, "receive on closed device");
 	else {
 		tty_buffer_request_room(tty, len);
 		tty_insert_flip_string(tty, buffer, len);
@@ -655,13 +662,13 @@
 /* gigaset_if_initdriver
  * Initialize tty interface.
  * parameters:
- *      drv             Driver
- *      procname        Name of the driver (e.g. for /proc/tty/drivers)
- *      devname         Name of the device files (prefix without minor number)
- *      devfsname       Devfs name of the device files without %d
+ *	drv		Driver
+ *	procname	Name of the driver (e.g. for /proc/tty/drivers)
+ *	devname		Name of the device files (prefix without minor number)
+ *	devfsname	Devfs name of the device files without %d
  */
 void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
-                           const char *devname, const char *devfsname)
+			   const char *devname, const char *devfsname)
 {
 	unsigned minors = drv->minors;
 	int ret;
@@ -696,7 +703,7 @@
 		warn("failed to register tty driver (error %d)", ret);
 		goto error;
 	}
-	dbg(DEBUG_IF, "tty driver initialized");
+	gig_dbg(DEBUG_IF, "tty driver initialized");
 	drv->have_tty = 1;
 	return;
 
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index 5744eb9..8667daa 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -10,10 +10,6 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -87,14 +83,14 @@
 {
 	if (!atomic_dec_and_test(&iwb->writesem)) {
 		atomic_inc(&iwb->writesem);
-		dbg(DEBUG_ISO,
-		    "%s: couldn't acquire iso write semaphore", __func__);
+		gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
+			__func__);
 		return 0;
 	}
 #ifdef CONFIG_GIGASET_DEBUG
-	dbg(DEBUG_ISO,
-	    "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
-	    __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
+	gig_dbg(DEBUG_ISO,
+		"%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
+		__func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
 #endif
 	return 1;
 }
@@ -147,7 +143,7 @@
 	/* recover the idle flag byte */
 	write = atomic_read(&iwb->write);
 	iwb->idle = iwb->data[write];
-	dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
+	gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
 	/* mask extraneous bits in buffer */
 	iwb->data[write] &= (1 << iwb->wbits) - 1;
 }
@@ -166,15 +162,14 @@
 	read = atomic_read(&iwb->nextread);
 	write = atomic_read(&iwb->write);
 	if (likely(read == write)) {
-		//dbg(DEBUG_STREAM, "%s: send buffer empty", __func__);
 		/* return idle frame */
 		return read < BAS_OUTBUFPAD ?
-		        BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
+			BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
 	}
 
 	limit = read + size;
-	dbg(DEBUG_STREAM,
-	    "%s: read=%d write=%d limit=%d", __func__, read, write, limit);
+	gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d",
+		__func__, read, write, limit);
 #ifdef CONFIG_GIGASET_DEBUG
 	if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
 		err("invalid size %d", size);
@@ -196,11 +191,12 @@
 				return -EBUSY;
 			/* write position could have changed */
 			if (limit >= (write = atomic_read(&iwb->write))) {
-				pbyte = iwb->data[write]; /* save partial byte */
+				pbyte = iwb->data[write]; /* save
+							     partial byte */
 				limit = write + BAS_OUTBUFPAD;
-				dbg(DEBUG_STREAM,
-				    "%s: filling %d->%d with %02x",
-				    __func__, write, limit, iwb->idle);
+				gig_dbg(DEBUG_STREAM,
+					"%s: filling %d->%d with %02x",
+					__func__, write, limit, iwb->idle);
 				if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
 					memset(iwb->data + write, iwb->idle,
 					       BAS_OUTBUFPAD);
@@ -211,9 +207,11 @@
 					       - write);
 					limit = 0;
 				}
-				dbg(DEBUG_STREAM, "%s: restoring %02x at %d",
-				    __func__, pbyte, limit);
-				iwb->data[limit] = pbyte; /* restore partial byte */
+				gig_dbg(DEBUG_STREAM,
+					"%s: restoring %02x at %d",
+					__func__, pbyte, limit);
+				iwb->data[limit] = pbyte; /* restore
+							     partial byte */
 				atomic_set(&iwb->write, limit);
 			}
 			isowbuf_donewrite(iwb);
@@ -242,19 +240,17 @@
  * write hex bytes to syslog for debugging
  */
 static inline void dump_bytes(enum debuglevel level, const char *tag,
-                              unsigned char *bytes, int count)
+			      unsigned char *bytes, int count)
 {
 #ifdef CONFIG_GIGASET_DEBUG
 	unsigned char c;
 	static char dbgline[3 * 32 + 1];
 	static const char hexdigit[] = "0123456789abcdef";
 	int i = 0;
-	IFNULLRET(tag);
-	IFNULLRET(bytes);
 	while (count-- > 0) {
 		if (i > sizeof(dbgline) - 4) {
 			dbgline[i] = '\0';
-			dbg(level, "%s:%s", tag, dbgline);
+			gig_dbg(level, "%s:%s", tag, dbgline);
 			i = 0;
 		}
 		c = *bytes++;
@@ -264,7 +260,7 @@
 		dbgline[i++] = hexdigit[c & 0x0f];
 	}
 	dbgline[i] = '\0';
-	dbg(level, "%s:%s", tag, dbgline);
+	gig_dbg(level, "%s:%s", tag, dbgline);
 #endif
 }
 
@@ -380,7 +376,7 @@
  */
 
 static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
-                                     int ones)
+				     int ones)
 {
 	u16 stuff;
 	int shiftinc, newones;
@@ -422,7 +418,7 @@
  */
 
 static inline int hdlc_buildframe(struct isowbuf_t *iwb,
-                                  unsigned char *in, int count)
+				  unsigned char *in, int count)
 {
 	int ones;
 	u16 fcs;
@@ -431,8 +427,8 @@
 
 	if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
 	    !isowbuf_startwrite(iwb)) {
-		dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
-		    __func__, isowbuf_freebytes(iwb));
+		gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
+			__func__, isowbuf_freebytes(iwb));
 		return -EAGAIN;
 	}
 
@@ -484,11 +480,11 @@
 
 	if (isowbuf_freebytes(iwb) < count ||
 	    !isowbuf_startwrite(iwb)) {
-		dbg(DEBUG_ISO, "can't put %d bytes", count);
+		gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
 		return -EAGAIN;
 	}
 
-	dbg(DEBUG_STREAM, "put %d bytes", count);
+	gig_dbg(DEBUG_STREAM, "put %d bytes", count);
 	write = atomic_read(&iwb->write);
 	do {
 		c = gigaset_invtab[*in++];
@@ -508,11 +504,13 @@
 	switch (bcs->proto2) {
 	case ISDN_PROTO_L2_HDLC:
 		result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
-		dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result);
+		gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
+			__func__, len, result);
 		break;
 	default:			/* assume transparent */
 		result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
-		dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result);
+		gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d",
+			__func__, len, result);
 	}
 	return result;
 }
@@ -528,13 +526,13 @@
 		return;
 	}
 	if (unlikely(bcs->skb->len == SBUFSIZE)) {
-		warn("received oversized packet discarded");
+		dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
 		bcs->hw.bas->giants++;
 		dev_kfree_skb_any(bcs->skb);
 		bcs->skb = NULL;
 		return;
 	}
-	*gigaset_skb_put_quick(bcs->skb, 1) = c;
+	*__skb_put(bcs->skb, 1) = c;
 }
 
 /* hdlc_flush
@@ -549,7 +547,7 @@
 		if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
 			skb_reserve(bcs->skb, HW_HDR_LEN);
 		else
-			err("could not allocate skb");
+			dev_err(bcs->cs->dev, "could not allocate skb\n");
 	}
 
 	/* reset packet state */
@@ -571,23 +569,25 @@
 
 	if ((procskb = bcs->skb) == NULL) {
 		/* previous error */
-		dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
+		gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
 		gigaset_rcv_error(NULL, bcs->cs, bcs);
 	} else if (procskb->len < 2) {
-		notice("received short frame (%d octets)", procskb->len);
+		dev_notice(bcs->cs->dev, "received short frame (%d octets)\n",
+			   procskb->len);
 		bcs->hw.bas->runts++;
 		gigaset_rcv_error(procskb, bcs->cs, bcs);
 	} else if (bcs->fcs != PPP_GOODFCS) {
-		notice("frame check error (0x%04x)", bcs->fcs);
+		dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
+			   bcs->fcs);
 		bcs->hw.bas->fcserrs++;
 		gigaset_rcv_error(procskb, bcs->cs, bcs);
 	} else {
 		procskb->len -= 2;		/* subtract FCS */
 		procskb->tail -= 2;
-		dbg(DEBUG_ISO,
-		    "%s: good frame (%d octets)", __func__, procskb->len);
+		gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
+			__func__, procskb->len);
 		dump_bytes(DEBUG_STREAM,
-		           "rcv data", procskb->data, procskb->len);
+			   "rcv data", procskb->data, procskb->len);
 		bcs->hw.bas->goodbytes += procskb->len;
 		gigaset_rcv_skb(procskb, bcs->cs, bcs);
 	}
@@ -595,7 +595,7 @@
 	if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
 		skb_reserve(bcs->skb, HW_HDR_LEN);
 	else
-		err("could not allocate skb");
+		dev_err(bcs->cs->dev, "could not allocate skb\n");
 	bcs->fcs = PPP_INITFCS;
 }
 
@@ -610,14 +610,14 @@
 		return;
 	}
 
-	notice("received partial byte (%d bits)", inbits);
+	dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
 	bcs->hw.bas->alignerrs++;
 	gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
 
 	if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
 		skb_reserve(bcs->skb, HW_HDR_LEN);
 	else
-		err("could not allocate skb");
+		dev_err(bcs->cs->dev, "could not allocate skb\n");
 	bcs->fcs = PPP_INITFCS;
 }
 
@@ -659,16 +659,12 @@
  *	bcs	receiving B channel structure
  */
 static inline void hdlc_unpack(unsigned char *src, unsigned count,
-                               struct bc_state *bcs)
+			       struct bc_state *bcs)
 {
-	struct bas_bc_state *ubc;
+	struct bas_bc_state *ubc = bcs->hw.bas;
 	int inputstate;
 	unsigned seqlen, inbyte, inbits;
 
-	IFNULLRET(bcs);
-	ubc = bcs->hw.bas;
-	IFNULLRET(ubc);
-
 	/* load previous state:
 	 * inputstate = set of flag bits:
 	 * - INS_flag_hunt: no complete opening flag received since connection setup or last abort
@@ -856,7 +852,7 @@
  *	bcs	receiving B channel structure
  */
 static inline void trans_receive(unsigned char *src, unsigned count,
-                                 struct bc_state *bcs)
+				 struct bc_state *bcs)
 {
 	struct sk_buff *skb;
 	int dobytes;
@@ -870,7 +866,7 @@
 	if (unlikely((skb = bcs->skb) == NULL)) {
 		bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
 		if (!skb) {
-			err("could not allocate skb");
+			dev_err(bcs->cs->dev, "could not allocate skb\n");
 			return;
 		}
 		skb_reserve(skb, HW_HDR_LEN);
@@ -888,7 +884,8 @@
 			gigaset_rcv_skb(skb, bcs->cs, bcs);
 			bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
 			if (!skb) {
-				err("could not allocate skb");
+				dev_err(bcs->cs->dev,
+					"could not allocate skb\n");
 				return;
 			}
 			skb_reserve(bcs->skb, HW_HDR_LEN);
@@ -921,8 +918,8 @@
 		case '\r':
 		case '\n':
 			/* end of line */
-			dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
-			    __func__, cbytes);
+			gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
+				__func__, cbytes);
 			cs->cbytes = cbytes;
 			gigaset_handle_modem_response(cs);
 			cbytes = 0;
@@ -932,7 +929,7 @@
 			if (cbytes < MAX_RESP_SIZE - 1)
 				cbytes++;
 			else
-				warn("response too large");
+				dev_warn(cs->dev, "response too large\n");
 		}
 	}
 
@@ -951,27 +948,27 @@
 
 	head = atomic_read(&inbuf->head);
 	while (head != (tail = atomic_read(&inbuf->tail))) {
-		dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
+		gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 		if (head > tail)
 			tail = RBUFSIZE;
 		src = inbuf->data + head;
 		numbytes = tail - head;
-		dbg(DEBUG_INTR, "processing %u bytes", numbytes);
+		gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
 
 		if (atomic_read(&cs->mstate) == MS_LOCKED) {
 			gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
-			                   numbytes, src, 0);
+					   numbytes, src);
 			gigaset_if_receive(inbuf->cs, src, numbytes);
 		} else {
 			gigaset_dbg_buffer(DEBUG_CMD, "received response",
-			                   numbytes, src, 0);
+					   numbytes, src);
 			cmd_loop(src, numbytes, inbuf);
 		}
 
 		head += numbytes;
 		if (head == RBUFSIZE)
 			head = 0;
-		dbg(DEBUG_INTR, "setting head to %u", head);
+		gig_dbg(DEBUG_INTR, "setting head to %u", head);
 		atomic_set(&inbuf->head, head);
 	}
 }
@@ -992,18 +989,22 @@
  */
 int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 {
-	int len;
+	int len = skb->len;
+	unsigned long flags;
 
-	IFNULLRETVAL(bcs, -EFAULT);
-	IFNULLRETVAL(skb, -EFAULT);
-	len = skb->len;
+	spin_lock_irqsave(&bcs->cs->lock, flags);
+	if (!bcs->cs->connected) {
+		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		return -ENODEV;
+	}
 
 	skb_queue_tail(&bcs->squeue, skb);
-	dbg(DEBUG_ISO,
-	    "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue));
+	gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
+		__func__, skb_queue_len(&bcs->squeue));
 
 	/* tasklet submits URB if necessary */
 	tasklet_schedule(&bcs->hw.bas->sent_tasklet);
+	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 
 	return len;	/* ok so far */
 }
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index c6915fa..d267a63 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -1,7 +1,7 @@
 /*
  * Stuff used by all variants of the driver
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>,
+ * Copyright (c) 2001 by Stefan Eilers,
  *                       Hansjoerg Lipp <hjlipp@web.de>,
  *                       Tilman Schmidt <tilman@imap.cc>.
  *
@@ -11,26 +11,29 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
 #include <linux/ctype.h>
 
-static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct cardstate *cs = usb_get_intfdata(intf);
-	return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096)
+	int ret;
+	unsigned long flags;
+	struct cardstate *cs = dev_get_drvdata(dev);
+
+	spin_lock_irqsave(&cs->lock, flags);
+	ret = sprintf(buf, "%u\n", cs->cidmode);
+	spin_unlock_irqrestore(&cs->lock, flags);
+
+	return ret;
 }
 
-static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct cardstate *cs = usb_get_intfdata(intf);
+	struct cardstate *cs = dev_get_drvdata(dev);
 	long int value;
 	char *end;
 
@@ -41,23 +44,23 @@
 	if (value < 0 || value > 1)
 			return -EINVAL;
 
-	if (down_interruptible(&cs->sem))
+	if (mutex_lock_interruptible(&cs->mutex))
 		return -ERESTARTSYS; // FIXME -EINTR?
 
 	cs->waiting = 1;
 	if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
-		               NULL, value, NULL)) {
+			       NULL, value, NULL)) {
 		cs->waiting = 0;
-		up(&cs->sem);
+		mutex_unlock(&cs->mutex);
 		return -ENOMEM;
 	}
 
-	dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
+	gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
 	gigaset_schedule_event(cs);
 
 	wait_event(cs->waitqueue, !cs->waiting);
 
-	up(&cs->sem);
+	mutex_unlock(&cs->mutex);
 
 	return count;
 }
@@ -65,17 +68,15 @@
 static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
 
 /* free sysfs for device */
-void gigaset_free_dev_sysfs(struct usb_interface *interface)
+void gigaset_free_dev_sysfs(struct cardstate *cs)
 {
-	dbg(DEBUG_INIT, "removing sysfs entries");
-	device_remove_file(&interface->dev, &dev_attr_cidmode);
+	gig_dbg(DEBUG_INIT, "removing sysfs entries");
+	device_remove_file(cs->dev, &dev_attr_cidmode);
 }
-EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs);
 
 /* initialize sysfs for device */
-void gigaset_init_dev_sysfs(struct usb_interface *interface)
+void gigaset_init_dev_sysfs(struct cardstate *cs)
 {
-	dbg(DEBUG_INIT, "setting up sysfs");
-	device_create_file(&interface->dev, &dev_attr_cidmode);
+	gig_dbg(DEBUG_INIT, "setting up sysfs");
+	device_create_file(cs->dev, &dev_attr_cidmode);
 }
-EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index 323fc73..bfb73fd 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -1,7 +1,7 @@
 /*
  * USB driver for Gigaset 307x directly or using M105 Data.
  *
- * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>
+ * Copyright (c) 2001 by Stefan Eilers
  *                   and Hansjoerg Lipp <hjlipp@web.de>.
  *
  * This driver was derived from the USB skeleton driver by
@@ -13,10 +13,6 @@
  *	published by the Free Software Foundation; either version 2 of
  *	the License, or (at your option) any later version.
  * =====================================================================
- * ToDo: ...
- * =====================================================================
- * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $
- * =====================================================================
  */
 
 #include "gigaset.h"
@@ -29,7 +25,7 @@
 #include <linux/moduleparam.h>
 
 /* Version Information */
-#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>"
+#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers"
 #define DRIVER_DESC "USB Driver for Gigaset 307x using M105"
 
 /* Module parameters */
@@ -62,10 +58,6 @@
 
 MODULE_DEVICE_TABLE(usb, gigaset_table);
 
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE	200
-
-
 /*
  * Control requests (empty fields: 00)
  *
@@ -114,7 +106,7 @@
  */
 
 static int gigaset_probe(struct usb_interface *interface,
-                         const struct usb_device_id *id);
+			 const struct usb_device_id *id);
 static void gigaset_disconnect(struct usb_interface *interface);
 
 static struct gigaset_driver *driver = NULL;
@@ -122,29 +114,29 @@
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver gigaset_usb_driver = {
-	.name =         GIGASET_MODULENAME,
-	.probe =        gigaset_probe,
-	.disconnect =   gigaset_disconnect,
-	.id_table =     gigaset_table,
+	.name =		GIGASET_MODULENAME,
+	.probe =	gigaset_probe,
+	.disconnect =	gigaset_disconnect,
+	.id_table =	gigaset_table,
 };
 
 struct usb_cardstate {
-	struct usb_device       *udev;                  /* save off the usb device pointer */
-	struct usb_interface    *interface;             /* the interface for this device */
-	atomic_t                busy;                   /* bulk output in progress */
+	struct usb_device	*udev;		/* usb device pointer */
+	struct usb_interface	*interface;	/* interface for this device */
+	atomic_t		busy;		/* bulk output in progress */
 
-	/* Output buffer for commands (M105: and data)*/
-	unsigned char           *bulk_out_buffer;       /* the buffer to send data */
-	int                     bulk_out_size;          /* the size of the send buffer */
-	__u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
-	struct urb              *bulk_out_urb;          /* the urb used to transmit data */
+	/* Output buffer */
+	unsigned char		*bulk_out_buffer;
+	int			bulk_out_size;
+	__u8			bulk_out_endpointAddr;
+	struct urb		*bulk_out_urb;
 
-	/* Input buffer for command responses (M105: and data)*/
-	int                     rcvbuf_size;            /* the size of the receive buffer */
-	struct urb              *read_urb;              /* the urb used to receive data */
-	__u8                    int_in_endpointAddr;    /* the address of the bulk in endpoint */
+	/* Input buffer */
+	int			rcvbuf_size;
+	struct urb		*read_urb;
+	__u8			int_in_endpointAddr;
 
-	char                    bchars[6];              /* req. 0x19 */
+	char			bchars[6];		/* for request 0x19 */
 };
 
 struct usb_bc_state {};
@@ -157,19 +149,20 @@
 #ifdef CONFIG_GIGASET_UNDOCREQ
 /* WARNING: EXPERIMENTAL! */
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-                                  unsigned new_state)
+				  unsigned new_state)
 {
+	struct usb_device *udev = cs->hw.usb->udev;
 	unsigned mask, val;
 	int r;
 
 	mask = tiocm_to_gigaset(old_state ^ new_state);
 	val = tiocm_to_gigaset(new_state);
 
-	dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
-	r = usb_control_msg(cs->hw.usb->udev,
-	                    usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41,
-	                    (val & 0xff) | ((mask & 0xff) << 8), 0,
-	                    NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH
+	gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
+	// don't use this in an interrupt/BH
+	r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
+			    (val & 0xff) | ((mask & 0xff) << 8), 0,
+			    NULL, 0, 2000 /* timeout? */);
 	if (r < 0)
 		return r;
 	//..
@@ -178,30 +171,29 @@
 
 static int set_value(struct cardstate *cs, u8 req, u16 val)
 {
+	struct usb_device *udev = cs->hw.usb->udev;
 	int r, r2;
 
-	dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val);
-	r = usb_control_msg(cs->hw.usb->udev,
-	                    usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41,
-	                    0xf /*?*/, 0,
-	                    NULL, 0, 2000 /*?*/); /* no idea, what this does */
+	gig_dbg(DEBUG_USBREQ, "request %02x (%04x)",
+		(unsigned)req, (unsigned)val);
+	r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41,
+			    0xf /*?*/, 0, NULL, 0, 2000 /*?*/);
+			    /* no idea what this does */
 	if (r < 0) {
-		err("error %d on request 0x12", -r);
+		dev_err(&udev->dev, "error %d on request 0x12\n", -r);
 		return r;
 	}
 
-	r = usb_control_msg(cs->hw.usb->udev,
-	                    usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41,
-	                    val, 0,
-	                    NULL, 0, 2000 /*?*/);
+	r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41,
+			    val, 0, NULL, 0, 2000 /*?*/);
 	if (r < 0)
-		err("error %d on request 0x%02x", -r, (unsigned)req);
+		dev_err(&udev->dev, "error %d on request 0x%02x\n",
+			-r, (unsigned)req);
 
-	r2 = usb_control_msg(cs->hw.usb->udev,
-	                     usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
-	                     0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
+	r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+			     0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/);
 	if (r2 < 0)
-		err("error %d on request 0x19", -r2);
+		dev_err(&udev->dev, "error %d on request 0x19\n", -r2);
 
 	return r < 0 ? r : (r2 < 0 ? r2 : 0);
 }
@@ -229,8 +221,8 @@
 	case B115200: rate =  115200; break;
 	default:
 		rate =  9600;
-		err("unsupported baudrate request 0x%x,"
-		    " using default of B9600", cflag);
+		dev_err(cs->dev, "unsupported baudrate request 0x%x,"
+			" using default of B9600\n", cflag);
 	}
 
 	val = 0x383fff / rate + 1;
@@ -259,7 +251,7 @@
 	case CS8:
 		val |= 8 << 8; break;
 	default:
-		err("CSIZE was not CS5-CS8, using default of 8");
+		dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n");
 		val |= 8 << 8;
 		break;
 	}
@@ -277,7 +269,7 @@
 
 #else
 static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
-                                  unsigned new_state)
+				  unsigned new_state)
 {
 	return -EINVAL;
 }
@@ -309,15 +301,12 @@
 	return 0;
 }
 
-//void send_ack_to_LL(void *data);
 static int write_modem(struct cardstate *cs);
 static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb);
 
 
-/* Handling of send queue. If there is already a skb opened, put data to
- * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue.
- * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler
- * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data.
+/* Write tasklet handler: Continue sending current skb, or send command, or
+ * start sending an skb from the send queue.
  */
 static void gigaset_modem_fill(unsigned long data)
 {
@@ -327,10 +316,10 @@
 	unsigned long flags;
 	int again;
 
-	dbg(DEBUG_OUTPUT, "modem_fill");
+	gig_dbg(DEBUG_OUTPUT, "modem_fill");
 
 	if (atomic_read(&cs->hw.usb->busy)) {
-		dbg(DEBUG_OUTPUT, "modem_fill: busy");
+		gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
 		return;
 	}
 
@@ -341,26 +330,27 @@
 			cb = cs->cmdbuf;
 			spin_unlock_irqrestore(&cs->cmdlock, flags);
 			if (cb) { /* commands to send? */
-				dbg(DEBUG_OUTPUT, "modem_fill: cb");
+				gig_dbg(DEBUG_OUTPUT, "modem_fill: cb");
 				if (send_cb(cs, cb) < 0) {
-					dbg(DEBUG_OUTPUT,
-					    "modem_fill: send_cb failed");
-					again = 1; /* no callback will be called! */
+					gig_dbg(DEBUG_OUTPUT,
+						"modem_fill: send_cb failed");
+					again = 1; /* no callback will be
+						      called! */
 				}
 			} else { /* skbs to send? */
 				bcs->tx_skb = skb_dequeue(&bcs->squeue);
 				if (bcs->tx_skb)
-					dbg(DEBUG_INTR,
-					    "Dequeued skb (Adr: %lx)!",
-					    (unsigned long) bcs->tx_skb);
+					gig_dbg(DEBUG_INTR,
+						"Dequeued skb (Adr: %lx)!",
+						(unsigned long) bcs->tx_skb);
 			}
 		}
 
 		if (bcs->tx_skb) {
-			dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
+			gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb");
 			if (write_modem(cs) < 0) {
-				dbg(DEBUG_OUTPUT,
-				    "modem_fill: write_modem failed");
+				gig_dbg(DEBUG_OUTPUT,
+					"modem_fill: write_modem failed");
 				// FIXME should we tell the LL?
 				again = 1; /* no callback will be called! */
 			}
@@ -371,88 +361,85 @@
 /**
  *	gigaset_read_int_callback
  *
- *      It is called if the data was received from the device. This is almost similiar to
- *      the interrupt service routine in the serial device.
+ *	It is called if the data was received from the device.
  */
 static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
+	struct inbuf_t *inbuf = urb->context;
+	struct cardstate *cs = inbuf->cs;
 	int resubmit = 0;
 	int r;
-	struct cardstate *cs;
 	unsigned numbytes;
 	unsigned char *src;
-	//unsigned long flags;
-	struct inbuf_t *inbuf;
-
-	IFNULLRET(urb);
-	inbuf = (struct inbuf_t *) urb->context;
-	IFNULLRET(inbuf);
-	//spin_lock_irqsave(&inbuf->lock, flags);
-	cs = inbuf->cs;
-	IFNULLGOTO(cs, exit);
-	IFNULLGOTO(cardstate, exit);
-
-	if (!atomic_read(&cs->connected)) {
-		err("%s: disconnected", __func__);
-		goto exit;
-	}
+	unsigned long flags;
 
 	if (!urb->status) {
+		if (!cs->connected) {
+			err("%s: disconnected", __func__); /* should never happen */
+			return;
+		}
+
 		numbytes = urb->actual_length;
 
 		if (numbytes) {
 			src = inbuf->rcvbuf;
 			if (unlikely(*src))
-				warn("%s: There was no leading 0, but 0x%02x!",
-				     __func__, (unsigned) *src);
+				dev_warn(cs->dev,
+				    "%s: There was no leading 0, but 0x%02x!\n",
+					 __func__, (unsigned) *src);
 			++src; /* skip leading 0x00 */
 			--numbytes;
 			if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
-				dbg(DEBUG_INTR, "%s-->BH", __func__);
+				gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
 				gigaset_schedule_event(inbuf->cs);
 			}
 		} else
-			dbg(DEBUG_INTR, "Received zero block length");
+			gig_dbg(DEBUG_INTR, "Received zero block length");
 		resubmit = 1;
 	} else {
 		/* The urb might have been killed. */
-		dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
-		    __func__, urb->status);
-		if (urb->status != -ENOENT) /* not killed */
+		gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
+			__func__, urb->status);
+		if (urb->status != -ENOENT) { /* not killed */
+			if (!cs->connected) {
+				err("%s: disconnected", __func__); /* should never happen */
+				return;
+			}
 			resubmit = 1;
+		}
 	}
-exit:
-	//spin_unlock_irqrestore(&inbuf->lock, flags);
+
 	if (resubmit) {
-		r = usb_submit_urb(urb, SLAB_ATOMIC);
+		spin_lock_irqsave(&cs->lock, flags);
+		r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
+		spin_unlock_irqrestore(&cs->lock, flags);
 		if (r)
-			err("error %d when resubmitting urb.", -r);
+			dev_err(cs->dev, "error %d when resubmitting urb.\n",
+				-r);
 	}
 }
 
 
-/* This callback routine is called when data was transmitted to a B-Channel.
- * Therefore it has to check if there is still data to transmit. This
- * happens by calling modem_fill via task queue.
- *
- */
+/* This callback routine is called when data was transmitted to the device. */
 static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
-	struct cardstate *cs = (struct cardstate *) urb->context;
+	struct cardstate *cs = urb->context;
+	unsigned long flags;
 
-	IFNULLRET(cs);
-#ifdef CONFIG_GIGASET_DEBUG
-	if (!atomic_read(&cs->connected)) {
-		err("%s:not connected", __func__);
-		return;
-	}
-#endif
 	if (urb->status)
-		err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems
-		                                                           are handeled by timeouts or network protocols */
+		dev_err(cs->dev, "bulk transfer failed (status %d)\n",
+			-urb->status);
+		/* That's all we can do. Communication problems
+		   are handled by timeouts or network protocols. */
 
-	atomic_set(&cs->hw.usb->busy, 0);
-	tasklet_schedule(&cs->write_tasklet);
+	spin_lock_irqsave(&cs->lock, flags);
+	if (!cs->connected) {
+		err("%s: not connected", __func__);
+	} else {
+		atomic_set(&cs->hw.usb->busy, 0);
+		tasklet_schedule(&cs->write_tasklet);
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
 }
 
 static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
@@ -469,8 +456,8 @@
 
 			spin_lock_irqsave(&cs->cmdlock, flags);
 			cs->cmdbytes -= cs->curlen;
-			dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
-			    cs->curlen, cs->cmdbytes);
+			gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left",
+				cs->curlen, cs->cmdbytes);
 			cs->cmdbuf = cb = cb->next;
 			if (cb) {
 				cb->prev = NULL;
@@ -487,52 +474,51 @@
 		}
 		if (cb) {
 			count = min(cb->len, ucs->bulk_out_size);
+			gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
+
 			usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
-			                  usb_sndbulkpipe(ucs->udev,
-			                     ucs->bulk_out_endpointAddr & 0x0f),
-			                  cb->buf + cb->offset, count,
-			                  gigaset_write_bulk_callback, cs);
+					  usb_sndbulkpipe(ucs->udev,
+					     ucs->bulk_out_endpointAddr & 0x0f),
+					  cb->buf + cb->offset, count,
+					  gigaset_write_bulk_callback, cs);
 
 			cb->offset += count;
 			cb->len -= count;
 			atomic_set(&ucs->busy, 1);
-			dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count);
 
-			status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+			spin_lock_irqsave(&cs->lock, flags);
+			status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV;
+			spin_unlock_irqrestore(&cs->lock, flags);
+
 			if (status) {
 				atomic_set(&ucs->busy, 0);
-				err("could not submit urb (error %d).",
+				err("could not submit urb (error %d)\n",
 				    -status);
-				cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */
+				cb->len = 0; /* skip urb => remove cb+wakeup
+						in next loop cycle */
 			}
 		}
-	} while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */
+	} while (cb && status); /* next command on error */
 
 	return status;
 }
 
-/* Write string into transbuf and send it to modem.
- */
+/* Send command to device. */
 static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
-                             int len, struct tasklet_struct *wake_tasklet)
+			     int len, struct tasklet_struct *wake_tasklet)
 {
 	struct cmdbuf_t *cb;
 	unsigned long flags;
 
 	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
-	                     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
-	                   "CMD Transmit", len, buf, 0);
-
-	if (!atomic_read(&cs->connected)) {
-		err("%s: not connected", __func__);
-		return -ENODEV;
-	}
+			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+			   "CMD Transmit", len, buf);
 
 	if (len <= 0)
 		return 0;
 
 	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
-		err("%s: out of memory", __func__);
+		dev_err(cs->dev, "%s: out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -554,7 +540,10 @@
 	cs->lastcmdbuf = cb;
 	spin_unlock_irqrestore(&cs->cmdlock, flags);
 
-	tasklet_schedule(&cs->write_tasklet);
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->connected)
+		tasklet_schedule(&cs->write_tasklet);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return len;
 }
 
@@ -578,11 +567,12 @@
 static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
 {
 #ifdef CONFIG_GIGASET_UNDOCREQ
-	gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0);
+	struct usb_device *udev = cs->hw.usb->udev;
+
+	gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf);
 	memcpy(cs->hw.usb->bchars, buf, 6);
-	return usb_control_msg(cs->hw.usb->udev,
-	                       usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41,
-	                       0, 0, &buf, 6, 2000);
+	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41,
+			       0, 0, &buf, 6, 2000);
 #else
 	return -EINVAL;
 #endif
@@ -604,7 +594,6 @@
 	if (!bcs->hw.usb)
 		return 0;
 
-	//bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */
 	return 1;
 }
 
@@ -614,7 +603,6 @@
 
 static void gigaset_freecshw(struct cardstate *cs)
 {
-	//FIXME
 	tasklet_kill(&cs->write_tasklet);
 	kfree(cs->hw.usb);
 }
@@ -639,33 +627,21 @@
 	//ucs->urb_cmd_out = NULL;
 	ucs->read_urb = NULL;
 	tasklet_init(&cs->write_tasklet,
-	             &gigaset_modem_fill, (unsigned long) cs);
+		     &gigaset_modem_fill, (unsigned long) cs);
 
 	return 1;
 }
 
-/* Writes the data of the current open skb into the modem.
- * We have to protect against multiple calls until the
- * callback handler () is called , due to the fact that we
- * are just allowed to send data once to an endpoint. Therefore
- * we using "trans_flg" to synchonize ...
- */
+/* Send data from current skb to the device. */
 static int write_modem(struct cardstate *cs)
 {
-	int ret;
+	int ret = 0;
 	int count;
 	struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
 	struct usb_cardstate *ucs = cs->hw.usb;
-	//unsigned long flags;
+	unsigned long flags;
 
-	IFNULLRETVAL(bcs->tx_skb, -EINVAL);
-
-	dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
-
-	ret = -ENODEV;
-	IFNULLGOTO(ucs->bulk_out_buffer, error);
-	IFNULLGOTO(ucs->bulk_out_urb, error);
-	ret = 0;
+	gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len);
 
 	if (!bcs->tx_skb->len) {
 		dev_kfree_skb_any(bcs->tx_skb);
@@ -679,40 +655,42 @@
 	count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
 	memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count);
 	skb_pull(bcs->tx_skb, count);
-
-	usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
-	                  usb_sndbulkpipe(ucs->udev,
-	                                  ucs->bulk_out_endpointAddr & 0x0f),
-	                  ucs->bulk_out_buffer, count,
-	                  gigaset_write_bulk_callback, cs);
 	atomic_set(&ucs->busy, 1);
-	dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
+	gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
 
-	ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->connected) {
+		usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
+				  usb_sndbulkpipe(ucs->udev,
+						  ucs->bulk_out_endpointAddr & 0x0f),
+				  ucs->bulk_out_buffer, count,
+				  gigaset_write_bulk_callback, cs);
+		ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC);
+	} else {
+		ret = -ENODEV;
+	}
+	spin_unlock_irqrestore(&cs->lock, flags);
+
 	if (ret) {
-		err("could not submit urb (error %d).", -ret);
+		err("could not submit urb (error %d)\n", -ret);
 		atomic_set(&ucs->busy, 0);
 	}
+
 	if (!bcs->tx_skb->len) {
 		/* skb sent completely */
 		gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
 
-		dbg(DEBUG_INTR,
-		    "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb);
+		gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+			(unsigned long) bcs->tx_skb);
 		dev_kfree_skb_any(bcs->tx_skb);
 		bcs->tx_skb = NULL;
 	}
 
 	return ret;
-error:
-	dev_kfree_skb_any(bcs->tx_skb);
-	bcs->tx_skb = NULL;
-	return ret;
-
 }
 
 static int gigaset_probe(struct usb_interface *interface,
-                         const struct usb_device_id *id)
+			 const struct usb_device_id *id)
 {
 	int retval;
 	struct usb_device *udev = interface_to_usbdev(interface);
@@ -720,16 +698,14 @@
 	struct usb_host_interface *hostif;
 	struct cardstate *cs = NULL;
 	struct usb_cardstate *ucs = NULL;
-	//struct usb_interface_descriptor *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
-	//isdn_ctrl command;
 	int buffer_size;
 	int alt;
-	//unsigned long flags;
 
-	info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
-	    __func__, le16_to_cpu(udev->descriptor.idVendor),
-	    le16_to_cpu(udev->descriptor.idProduct));
+	gig_dbg(DEBUG_ANY,
+		"%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
+		__func__, le16_to_cpu(udev->descriptor.idVendor),
+		le16_to_cpu(udev->descriptor.idProduct));
 
 	retval = -ENODEV; //FIXME
 
@@ -744,7 +720,7 @@
 	ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
 
 	if (alt != 0 || ifnum != 0) {
-		warn("ifnum %d, alt %d", ifnum, alt);
+		dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
 		return -ENODEV;
 	}
 
@@ -752,42 +728,29 @@
 	 *
 	 */
 	if (hostif->desc.bInterfaceClass != 255) {
-		info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !",
-		       __func__, ifnum, hostif->desc.bInterfaceClass);
+		dev_info(&udev->dev,
+		"%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
+			 __func__, ifnum, hostif->desc.bInterfaceClass);
 		return -ENODEV;
 	}
 
-	info("%s: Device matched ... !", __func__);
+	dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
 	cs = gigaset_getunassignedcs(driver);
 	if (!cs) {
-		warn("No free cardstate!");
+		dev_warn(&udev->dev, "no free cardstate\n");
 		return -ENODEV;
 	}
 	ucs = cs->hw.usb;
 
-#if 0
-	if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) {
-		warn("set_configuration failed");
-		goto error;
-	}
+	/* save off device structure ptrs for later use */
+	usb_get_dev(udev);
+	ucs->udev = udev;
+	ucs->interface = interface;
+	cs->dev = &interface->dev;
 
-
-	if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) {
-		warn("usb_set_interface failed, device %d interface %d altsetting %d",
-		     udev->devnum, ifnum, alt);
-		goto error;
-	}
-#endif
-
-	/* set up the endpoint information */
-	/* check out the endpoints */
-	/* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to
-	 * poll messages from the device(int in).
-	 * Therefore we will have an almost similiar situation as with our serial port handler.
-	 * If an connection will be established, we will have to create data in/out pipes
-	 * dynamically...
-	 */
+	/* save address of controller structure */
+	usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs);
 
 	endpoint = &hostif->endpoint[0].desc;
 
@@ -796,14 +759,14 @@
 	ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress;
 	ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
 	if (!ucs->bulk_out_buffer) {
-		err("Couldn't allocate bulk_out_buffer");
+		dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 
 	ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL);
 	if (!ucs->bulk_out_urb) {
-		err("Couldn't allocate bulk_out_buffer");
+		dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n");
 		retval = -ENOMEM;
 		goto error;
 	}
@@ -811,12 +774,10 @@
 	endpoint = &hostif->endpoint[1].desc;
 
 	atomic_set(&ucs->busy, 0);
-	ucs->udev = udev;
-	ucs->interface = interface;
 
 	ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL);
 	if (!ucs->read_urb) {
-		err("No free urbs available");
+		dev_err(cs->dev, "No free urbs available\n");
 		retval = -ENOMEM;
 		goto error;
 	}
@@ -825,38 +786,33 @@
 	ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
 	cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
 	if (!cs->inbuf[0].rcvbuf) {
-		err("Couldn't allocate rcvbuf");
+		dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 	/* Fill the interrupt urb and send it to the core */
 	usb_fill_int_urb(ucs->read_urb, udev,
-	                 usb_rcvintpipe(udev,
-	                                endpoint->bEndpointAddress & 0x0f),
-	                 cs->inbuf[0].rcvbuf, buffer_size,
-	                 gigaset_read_int_callback,
-	                 cs->inbuf + 0, endpoint->bInterval);
+			 usb_rcvintpipe(udev,
+					endpoint->bEndpointAddress & 0x0f),
+			 cs->inbuf[0].rcvbuf, buffer_size,
+			 gigaset_read_int_callback,
+			 cs->inbuf + 0, endpoint->bInterval);
 
 	retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL);
 	if (retval) {
-		err("Could not submit URB!");
+		dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval);
 		goto error;
 	}
 
 	/* tell common part that the device is ready */
 	if (startmode == SM_LOCKED)
 		atomic_set(&cs->mstate, MS_LOCKED);
+
 	if (!gigaset_start(cs)) {
 		tasklet_kill(&cs->write_tasklet);
 		retval = -ENODEV; //FIXME
 		goto error;
 	}
-
-	/* save address of controller structure */
-	usb_set_intfdata(interface, cs);
-
-	/* set up device sysfs */
-	gigaset_init_dev_sysfs(interface);
 	return 0;
 
 error:
@@ -868,48 +824,45 @@
 	kfree(cs->inbuf[0].rcvbuf);
 	if (ucs->read_urb != NULL)
 		usb_free_urb(ucs->read_urb);
+	usb_set_intfdata(interface, NULL);
 	ucs->read_urb = ucs->bulk_out_urb = NULL;
 	cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
+	usb_put_dev(ucs->udev);
+	ucs->udev = NULL;
+	ucs->interface = NULL;
 	gigaset_unassign(cs);
 	return retval;
 }
 
-/**
- *	skel_disconnect
- */
 static void gigaset_disconnect(struct usb_interface *interface)
 {
 	struct cardstate *cs;
 	struct usb_cardstate *ucs;
 
 	cs = usb_get_intfdata(interface);
-
-	/* clear device sysfs */
-	gigaset_free_dev_sysfs(interface);
-
-	usb_set_intfdata(interface, NULL);
 	ucs = cs->hw.usb;
 	usb_kill_urb(ucs->read_urb);
-	//info("GigaSet USB device #%d will be disconnected", minor);
 
 	gigaset_stop(cs);
 
+	usb_set_intfdata(interface, NULL);
 	tasklet_kill(&cs->write_tasklet);
 
-	usb_kill_urb(ucs->bulk_out_urb);  /* FIXME: nur, wenn noetig */
-	//usb_kill_urb(ucs->urb_cmd_out);  /* FIXME: nur, wenn noetig */
+	usb_kill_urb(ucs->bulk_out_urb);	/* FIXME: only if active? */
 
 	kfree(ucs->bulk_out_buffer);
 	if (ucs->bulk_out_urb != NULL)
 		usb_free_urb(ucs->bulk_out_urb);
-	//if(ucs->urb_cmd_out != NULL)
-	//	usb_free_urb(ucs->urb_cmd_out);
 	kfree(cs->inbuf[0].rcvbuf);
 	if (ucs->read_urb != NULL)
 		usb_free_urb(ucs->read_urb);
-	ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL;
+	ucs->read_urb = ucs->bulk_out_urb = NULL;
 	cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
 
+	usb_put_dev(ucs->udev);
+	ucs->interface = NULL;
+	ucs->udev = NULL;
+	cs->dev = NULL;
 	gigaset_unassign(cs);
 }
 
@@ -942,9 +895,9 @@
 
 	/* allocate memory for our driver state and intialize it */
 	if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
-	                               GIGASET_MODULENAME, GIGASET_DEVNAME,
-	                               GIGASET_DEVFSNAME, &ops,
-	                               THIS_MODULE)) == NULL)
+				       GIGASET_MODULENAME, GIGASET_DEVNAME,
+				       GIGASET_DEVFSNAME, &ops,
+				       THIS_MODULE)) == NULL)
 		goto error;
 
 	/* allocate memory for our device state and intialize it */
@@ -981,8 +934,8 @@
 static void __exit usb_gigaset_exit(void)
 {
 	gigaset_blockdriver(driver); /* => probe will fail
-	                              * => no gigaset_start any more
-	                              */
+				      * => no gigaset_start any more
+				      */
 
 	gigaset_shutdown(cardstate);
 	/* from now on, no isdn callback should be possible */
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 2a2b03f..7bbfd85 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -51,8 +51,8 @@
    handler.
 */
 
-static void avmcs_config(dev_link_t *link);
-static void avmcs_release(dev_link_t *link);
+static int avmcs_config(struct pcmcia_device *link);
+static void avmcs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -65,10 +65,10 @@
 /*
    A linked list of "instances" of the skeleton device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -78,7 +78,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -99,54 +99,38 @@
     
 ======================================================================*/
 
-static int avmcs_attach(struct pcmcia_device *p_dev)
+static int avmcs_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     local_info_t *local;
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-        goto err;
-    memset(link, 0, sizeof(struct dev_link_t));
-
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 0;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts2 = 0;
 
     /* Interrupt setup */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
 
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local)
-        goto err_kfree;
+        goto err;
     memset(local, 0, sizeof(local_info_t));
-    link->priv = local;
+    p_dev->priv = local;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
+    return avmcs_config(p_dev);
 
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    avmcs_config(link);
-
-    return 0;
-
- err_kfree:
-    kfree(link);
  err:
-    return -EINVAL;
+    return -ENOMEM;
 } /* avmcs_attach */
 
 /*======================================================================
@@ -158,15 +142,10 @@
 
 ======================================================================*/
 
-static void avmcs_detach(struct pcmcia_device *p_dev)
+static void avmcs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    if (link->state & DEV_CONFIG)
 	avmcs_release(link);
-
-    kfree(link->priv);
-    kfree(link);
+	kfree(link->priv);
 } /* avmcs_detach */
 
 /*======================================================================
@@ -177,7 +156,7 @@
     
 ======================================================================*/
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -185,7 +164,7 @@
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -193,7 +172,7 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -201,9 +180,8 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static void avmcs_config(dev_link_t *link)
+static int avmcs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -213,8 +191,7 @@
     char devname[128];
     int cardtype;
     int (*addcard)(unsigned int port, unsigned irq);
-    
-    handle = link->handle;
+
     dev = link->priv;
 
     /*
@@ -223,25 +200,21 @@
     */
     do {
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	i = pcmcia_get_first_tuple(handle, &tuple);
+	i = pcmcia_get_first_tuple(link, &tuple);
 	if (i != CS_SUCCESS) break;
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = 64;
 	tuple.TupleOffset = 0;
-	i = pcmcia_get_tuple_data(handle, &tuple);
+	i = pcmcia_get_tuple_data(link, &tuple);
 	if (i != CS_SUCCESS) break;
-	i = pcmcia_parse_tuple(handle, &tuple, &parse);
+	i = pcmcia_parse_tuple(link, &tuple, &parse);
 	if (i != CS_SUCCESS) break;
 	link->conf.ConfigBase = parse.config.base;
     } while (0);
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, ParseTuple, i);
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	cs_error(link, ParseTuple, i);
+	return -ENODEV;
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     do {
 
@@ -252,7 +225,7 @@
 	tuple.DesiredTuple = CISTPL_VERS_1;
 
 	devname[0] = 0;
-	if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+	if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
 	    strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
 			sizeof(devname));
 	}
@@ -263,7 +236,7 @@
 	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(link, &tuple, &parse);
 	while (i == CS_SUCCESS) {
 	    if (cf->io.nwin > 0) {
 		link->conf.ConfigIndex = cf->index;
@@ -273,36 +246,36 @@
                 printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
 			link->io.BasePort1,
 		        link->io.BasePort1+link->io.NumPorts1-1);
-		i = pcmcia_request_io(link->handle, &link->io);
+		i = pcmcia_request_io(link, &link->io);
 		if (i == CS_SUCCESS) goto found_port;
 	    }
-	    i = next_tuple(handle, &tuple, &parse);
+	    i = next_tuple(link, &tuple, &parse);
 	}
 
 found_port:
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestIO, i);
+	    cs_error(link, RequestIO, i);
 	    break;
 	}
-	
+
 	/*
 	 * allocate an interrupt line
 	 */
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestIRQ, i);
-	    pcmcia_release_io(link->handle, &link->io);
+	    cs_error(link, RequestIRQ, i);
+	    /* undo */
+	    pcmcia_disable_device(link);
 	    break;
 	}
-	
+
 	/*
          * configure the PCMCIA socket
 	  */
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestConfiguration, i);
-	    pcmcia_release_io(link->handle, &link->io);
-	    pcmcia_release_irq(link->handle, &link->irq);
+	    cs_error(link, RequestConfiguration, i);
+	    pcmcia_disable_device(link);
 	    break;
 	}
 
@@ -331,13 +304,12 @@
 
     dev->node.major = 64;
     dev->node.minor = 0;
-    link->dev = &dev->node;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &dev->node;
+
     /* If any step failed, release any partially configured state */
     if (i != 0) {
 	avmcs_release(link);
-	return;
+	return -ENODEV;
     }
 
 
@@ -351,9 +323,10 @@
         printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
 		dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
 	avmcs_release(link);
-	return;
+	return -ENODEV;
     }
     dev->node.minor = i;
+    return 0;
 
 } /* avmcs_config */
 
@@ -365,56 +338,12 @@
     
 ======================================================================*/
 
-static void avmcs_release(dev_link_t *link)
+static void avmcs_release(struct pcmcia_device *link)
 {
-    b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
-
-    /* Unlink the device chain */
-    link->dev = NULL;
-    
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+	b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
+	pcmcia_disable_device(link);
 } /* avmcs_release */
 
-static int avmcs_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int avmcs_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
-
-/*======================================================================
-
-    The card status event handler.  Mostly, this schedules other
-    stuff to run after an event is received.  A CARD_REMOVAL event
-    also sets some flags to discourage the net drivers from trying
-    to talk to the card any more.
-
-    When a CARD_REMOVAL event is received, we immediately set a flag
-    to block future accesses to this device.  All the functions that
-    actually access the device should check this flag to make sure
-    the card is still present.
-    
-======================================================================*/
-
 
 static struct pcmcia_device_id avmcs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -429,11 +358,9 @@
 	.drv	= {
 		.name	= "avm_cs",
 	},
-	.probe = avmcs_attach,
+	.probe = avmcs_probe,
 	.remove	= avmcs_detach,
 	.id_table = avmcs_ids,
-	.suspend= avmcs_suspend,
-	.resume = avmcs_resume,
 };
 
 static int __init avmcs_init(void)
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 969da40..ac28e32 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -67,8 +67,8 @@
    handler.
 */
 
-static void avma1cs_config(dev_link_t *link);
-static void avma1cs_release(dev_link_t *link);
+static int avma1cs_config(struct pcmcia_device *link);
+static void avma1cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -82,10 +82,10 @@
 /*
    A linked list of "instances" of the skeleton device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -95,7 +95,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -116,55 +116,40 @@
     
 ======================================================================*/
 
-static int avma1cs_attach(struct pcmcia_device *p_dev)
+static int avma1cs_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "avma1cs_attach()\n");
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-	return -ENOMEM;
-    memset(link, 0, sizeof(struct dev_link_t));
-
     /* Allocate space for private device-specific data */
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    if (!local) {
-	kfree(link);
+    if (!local)
 	return -ENOMEM;
-    }
+
     memset(local, 0, sizeof(local_info_t));
-    link->priv = local;
+    p_dev->priv = local;
 
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 16;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
-    link->io.IOAddrLines = 5;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts2 = 16;
+    p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+    p_dev->io.IOAddrLines = 5;
 
     /* Interrupt setup */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    avma1cs_config(link);
-
-    return 0;
+    return avma1cs_config(p_dev);
 } /* avma1cs_attach */
 
 /*======================================================================
@@ -176,17 +161,11 @@
 
 ======================================================================*/
 
-static void avma1cs_detach(struct pcmcia_device *p_dev)
+static void avma1cs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
-    DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-
-    if (link->state & DEV_CONFIG)
-	    avma1cs_release(link);
-
-    kfree(link->priv);
-    kfree(link);
+	DEBUG(0, "avma1cs_detach(0x%p)\n", link);
+	avma1cs_release(link);
+	kfree(link->priv);
 } /* avma1cs_detach */
 
 /*======================================================================
@@ -197,7 +176,7 @@
     
 ======================================================================*/
 
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -205,7 +184,7 @@
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -213,7 +192,7 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		     cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -221,9 +200,8 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static void avma1cs_config(dev_link_t *link)
+static int avma1cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
@@ -233,8 +211,7 @@
     char devname[128];
     IsdnCard_t	icard;
     int busy = 0;
-    
-    handle = link->handle;
+
     dev = link->priv;
 
     DEBUG(0, "avma1cs_config(0x%p)\n", link);
@@ -245,25 +222,21 @@
     */
     do {
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	i = pcmcia_get_first_tuple(handle, &tuple);
+	i = pcmcia_get_first_tuple(link, &tuple);
 	if (i != CS_SUCCESS) break;
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = 64;
 	tuple.TupleOffset = 0;
-	i = pcmcia_get_tuple_data(handle, &tuple);
+	i = pcmcia_get_tuple_data(link, &tuple);
 	if (i != CS_SUCCESS) break;
-	i = pcmcia_parse_tuple(handle, &tuple, &parse);
+	i = pcmcia_parse_tuple(link, &tuple, &parse);
 	if (i != CS_SUCCESS) break;
 	link->conf.ConfigBase = parse.config.base;
     } while (0);
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, ParseTuple, i);
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	cs_error(link, ParseTuple, i);
+	return -ENODEV;
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     do {
 
@@ -274,7 +247,7 @@
 	tuple.DesiredTuple = CISTPL_VERS_1;
 
 	devname[0] = 0;
-	if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
+	if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
 	    strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
 			sizeof(devname));
 	}
@@ -285,7 +258,7 @@
 	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	i = first_tuple(handle, &tuple, &parse);
+	i = first_tuple(link, &tuple, &parse);
 	while (i == CS_SUCCESS) {
 	    if (cf->io.nwin > 0) {
 		link->conf.ConfigIndex = cf->index;
@@ -295,36 +268,36 @@
 		printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
 			link->io.BasePort1,
 			link->io.BasePort1+link->io.NumPorts1 - 1);
-		i = pcmcia_request_io(link->handle, &link->io);
+		i = pcmcia_request_io(link, &link->io);
 		if (i == CS_SUCCESS) goto found_port;
 	    }
-	    i = next_tuple(handle, &tuple, &parse);
+	    i = next_tuple(link, &tuple, &parse);
 	}
 
 found_port:
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestIO, i);
+	    cs_error(link, RequestIO, i);
 	    break;
 	}
 	
 	/*
 	 * allocate an interrupt line
 	 */
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestIRQ, i);
-	    pcmcia_release_io(link->handle, &link->io);
+	    cs_error(link, RequestIRQ, i);
+	    /* undo */
+	    pcmcia_disable_device(link);
 	    break;
 	}
-	
+
 	/*
 	 * configure the PCMCIA socket
 	 */
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-	    cs_error(link->handle, RequestConfiguration, i);
-	    pcmcia_release_io(link->handle, &link->io);
-	    pcmcia_release_irq(link->handle, &link->irq);
+	    cs_error(link, RequestConfiguration, i);
+	    pcmcia_disable_device(link);
 	    break;
 	}
 
@@ -336,13 +309,12 @@
     strcpy(dev->node.dev_name, "A1");
     dev->node.major = 45;
     dev->node.minor = 0;
-    link->dev = &dev->node;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &dev->node;
+
     /* If any step failed, release any partially configured state */
     if (i != 0) {
 	avma1cs_release(link);
-	return;
+	return -ENODEV;
     }
 
     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
@@ -357,10 +329,11 @@
     if (i < 0) {
     	printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
 	avma1cs_release(link);
-	return;
+	return -ENODEV;
     }
     dev->node.minor = i;
 
+    return 0;
 } /* avma1cs_config */
 
 /*======================================================================
@@ -371,47 +344,18 @@
     
 ======================================================================*/
 
-static void avma1cs_release(dev_link_t *link)
+static void avma1cs_release(struct pcmcia_device *link)
 {
-    local_info_t *local = link->priv;
+	local_info_t *local = link->priv;
 
-    DEBUG(0, "avma1cs_release(0x%p)\n", link);
+	DEBUG(0, "avma1cs_release(0x%p)\n", link);
 
-    /* no unregister function with hisax */
-    HiSax_closecard(local->node.minor);
+	/* now unregister function with hisax */
+	HiSax_closecard(local->node.minor);
 
-    /* Unlink the device chain */
-    link->dev = NULL;
-    
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 } /* avma1cs_release */
 
-static int avma1cs_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int avma1cs_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
-
 
 static struct pcmcia_device_id avma1cs_ids[] = {
 	PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -425,13 +369,11 @@
 	.drv		= {
 		.name	= "avma1_cs",
 	},
-	.probe		= avma1cs_attach,
+	.probe		= avma1cs_probe,
 	.remove		= avma1cs_detach,
 	.id_table	= avma1cs_ids,
-	.suspend	= avma1cs_suspend,
-	.resume		= avma1cs_resume,
 };
- 
+
 /*====================================================================*/
 
 static int __init init_avma1_cs(void)
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 062fb8f..e18e75b 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -94,8 +94,8 @@
    handler.
 */
 
-static void elsa_cs_config(dev_link_t *link);
-static void elsa_cs_release(dev_link_t *link);
+static int elsa_cs_config(struct pcmcia_device *link);
+static void elsa_cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -111,7 +111,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
    In this case, we also provide a flag to indicate if a device is
@@ -121,7 +121,7 @@
 */
 
 typedef struct local_info_t {
-    dev_link_t          link;
+	struct pcmcia_device	*p_dev;
     dev_node_t          node;
     int                 busy;
     int			cardnr;
@@ -139,9 +139,8 @@
 
 ======================================================================*/
 
-static int elsa_cs_attach(struct pcmcia_device *p_dev)
+static int elsa_cs_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "elsa_cs_attach()\n");
@@ -150,8 +149,11 @@
     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
+
+    local->p_dev = link;
+    link->priv = local;
+
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -170,16 +172,9 @@
     link->io.IOAddrLines = 3;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    elsa_cs_config(link);
-
-    return 0;
+    return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
 /*======================================================================
@@ -191,20 +186,16 @@
 
 ======================================================================*/
 
-static void elsa_cs_detach(struct pcmcia_device *p_dev)
+static void elsa_cs_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    local_info_t *info = link->priv;
+	local_info_t *info = link->priv;
 
-    DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
+	DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG) {
-	    info->busy = 1;
-	    elsa_cs_release(link);
-    }
+	info->busy = 1;
+	elsa_cs_release(link);
 
-    kfree(info);
-
+	kfree(info);
 } /* elsa_cs_detach */
 
 /*======================================================================
@@ -214,7 +205,7 @@
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -222,7 +213,7 @@
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -230,7 +221,7 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -238,9 +229,8 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static void elsa_cs_config(dev_link_t *link)
+static int elsa_cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     local_info_t *dev;
@@ -250,7 +240,6 @@
     IsdnCard_t icard;
 
     DEBUG(0, "elsa_config(0x%p)\n", link);
-    handle = link->handle;
     dev = link->priv;
 
     /*
@@ -262,7 +251,7 @@
     tuple.TupleDataMax = 255;
     tuple.TupleOffset = 0;
     tuple.Attributes = 0;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     if (i != CS_SUCCESS) {
         last_fn = ParseTuple;
 	goto cs_failed;
@@ -270,32 +259,29 @@
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     while (i == CS_SUCCESS) {
         if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
             printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
             link->conf.ConfigIndex = cf->index;
             link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
         } else {
           printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
           link->conf.ConfigIndex = cf->index;
           for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
             link->io.BasePort1 = j;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
           }
           break;
         }
-        i = next_tuple(handle, &tuple, &parse);
+        i = next_tuple(link, &tuple, &parse);
     }
 
     if (i != CS_SUCCESS) {
@@ -303,14 +289,14 @@
 	goto cs_failed;
     }
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS) {
         link->irq.AssignedIRQ = 0;
 	last_fn = RequestIRQ;
         goto cs_failed;
     }
 
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     if (i != CS_SUCCESS) {
       last_fn = RequestConfiguration;
       goto cs_failed;
@@ -321,14 +307,11 @@
     sprintf(dev->node.dev_name, "elsa");
     dev->node.major = dev->node.minor = 0x0;
 
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-           dev->node.dev_name, link->conf.ConfigIndex,
-           link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x: ",
+           dev->node.dev_name, link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
         printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -339,8 +322,6 @@
                link->io.BasePort2+link->io.NumPorts2-1);
     printk("\n");
 
-    link->state &= ~DEV_CONFIG_PENDING;
-
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
     icard.protocol = protocol;
@@ -354,10 +335,11 @@
     } else
     	((local_info_t*)link->priv)->cardnr = i;
 
-    return;
+    return 0;
 cs_failed:
-    cs_error(link->handle, last_fn, i);
+    cs_error(link, last_fn, i);
     elsa_cs_release(link);
+    return -ENODEV;
 } /* elsa_cs_config */
 
 /*======================================================================
@@ -368,7 +350,7 @@
 
 ======================================================================*/
 
-static void elsa_cs_release(dev_link_t *link)
+static void elsa_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
 
@@ -380,39 +362,23 @@
 	    HiSax_closecard(local->cardnr);
 	}
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
 
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-        pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+    pcmcia_disable_device(link);
 } /* elsa_cs_release */
 
-static int elsa_suspend(struct pcmcia_device *p_dev)
+static int elsa_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
         dev->busy = 1;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 
 	return 0;
 }
 
-static int elsa_resume(struct pcmcia_device *p_dev)
+static int elsa_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
 
 	return 0;
@@ -430,7 +396,7 @@
 	.drv		= {
 		.name	= "elsa_cs",
 	},
-	.probe		= elsa_cs_attach,
+	.probe		= elsa_cs_probe,
 	.remove		= elsa_cs_detach,
 	.id_table	= elsa_ids,
 	.suspend	= elsa_suspend,
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 6f5213a..9bb18f3 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -95,8 +95,8 @@
    event handler. 
 */
 
-static void sedlbauer_config(dev_link_t *link);
-static void sedlbauer_release(dev_link_t *link);
+static int sedlbauer_config(struct pcmcia_device *link);
+static void sedlbauer_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -119,7 +119,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -130,7 +130,7 @@
 */
    
 typedef struct local_info_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t		node;
     int			stop;
     int			cardnr;
@@ -148,11 +148,10 @@
     
 ======================================================================*/
 
-static int sedlbauer_attach(struct pcmcia_device *p_dev)
+static int sedlbauer_probe(struct pcmcia_device *link)
 {
     local_info_t *local;
-    dev_link_t *link;
-    
+
     DEBUG(0, "sedlbauer_attach()\n");
 
     /* Allocate space for private device-specific data */
@@ -160,8 +159,10 @@
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
-    
+
+    local->p_dev = link;
+    link->priv = local;
+
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -182,18 +183,10 @@
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
     link->io.IOAddrLines = 3;
 
-
     link->conf.Attributes = 0;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    sedlbauer_config(link);
-
-    return 0;
+    return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
 /*======================================================================
@@ -205,19 +198,15 @@
 
 ======================================================================*/
 
-static void sedlbauer_detach(struct pcmcia_device *p_dev)
+static void sedlbauer_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
+	DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
 
-    DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
+	((local_info_t *)link->priv)->stop = 1;
+	sedlbauer_release(link);
 
-    if (link->state & DEV_CONFIG) {
-	    ((local_info_t *)link->priv)->stop = 1;
-	    sedlbauer_release(link);
-    }
-
-    /* This points to the parent local_info_t struct */
-    kfree(link->priv);
+	/* This points to the parent local_info_t struct */
+	kfree(link->priv);
 } /* sedlbauer_detach */
 
 /*======================================================================
@@ -230,9 +219,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void sedlbauer_config(dev_link_t *link)
+static int sedlbauer_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     local_info_t *dev = link->priv;
     tuple_t tuple;
     cisparse_t parse;
@@ -254,18 +242,13 @@
     tuple.TupleData = buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
-    /* Look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
+    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
 
     /*
       In this loop, we scan the CIS for configuration table entries,
@@ -280,12 +263,12 @@
       will only use the CIS to fill in implementation-defined details.
     */
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
 	cistpl_cftable_entry_t dflt = { 0 };
 	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 	    goto next_entry;
 
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -309,10 +292,10 @@
 	}
 	    
 	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-	    link->conf.Vpp1 = link->conf.Vpp2 =
+	    link->conf.Vpp =
 		cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 	else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-	    link->conf.Vpp1 = link->conf.Vpp2 =
+	    link->conf.Vpp =
 		dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
 	
 	/* Do we need to allocate an interrupt? */
@@ -339,13 +322,13 @@
 		link->io.NumPorts2 = io->win[1].len;
 	    }
 	    /* This reserves IO space but doesn't actually enable it */
-	    if (pcmcia_request_io(link->handle, &link->io) != 0)
+	    if (pcmcia_request_io(link, &link->io) != 0)
 		goto next_entry;
 	}
 
 	/*
 	  Now set up a common memory window, if needed.  There is room
-	  in the dev_link_t structure for one memory window handle,
+	  in the struct pcmcia_device structure for one memory window handle,
 	  but if the base addresses need to be saved, or if multiple
 	  windows are needed, the info should go in the private data
 	  structure for this device.
@@ -366,7 +349,7 @@
                 req.Size = 0x1000;
 */
 	    req.AccessSpeed = 0;
-	    if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+	    if (pcmcia_request_window(&link, &req, &link->win) != 0)
 		goto next_entry;
 	    map.Page = 0; map.CardOffset = mem->win[0].card_addr;
 	    if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -374,29 +357,25 @@
 	}
 	/* If we got this far, we're cool! */
 	break;
-	
+
     next_entry:
-/* new in dummy.cs 2001/01/28 MN 
-        if (link->io.NumPorts1)
-           pcmcia_release_io(link->handle, &link->io);
-*/
-	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
-    
+
     /*
        Allocate an interrupt line.  Note that this does not assign a
        handler to the interrupt, unless the 'Handler' member of the
        irq structure is initialized.
     */
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 	
     /*
        This actually configures the PCMCIA socket -- setting up
        the I/O windows and the interrupt mapping, and putting the
        card and host interface into "Memory and IO" mode.
     */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*
       At this point, the dev_node_t structure(s) need to be
@@ -404,14 +383,13 @@
     */
     sprintf(dev->node.dev_name, "sedlbauer");
     dev->node.major = dev->node.minor = 0;
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-	   dev->node.dev_name, link->conf.ConfigIndex,
-	   link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-	printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x:",
+	   dev->node.dev_name, link->conf.ConfigIndex);
+    if (link->conf.Vpp)
+	printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -424,8 +402,6 @@
 	printk(", mem 0x%06lx-0x%06lx", req.Base,
 	       req.Base+req.Size-1);
     printk("\n");
-    
-    link->state &= ~DEV_CONFIG_PENDING;
 
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
@@ -437,14 +413,16 @@
     	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
     		last_ret, link->io.BasePort1);
     	sedlbauer_release(link);
+	return -ENODEV;
     } else
     	((local_info_t*)link->priv)->cardnr = last_ret;
 
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     sedlbauer_release(link);
+    return -ENODEV;
 
 } /* sedlbauer_config */
 
@@ -456,7 +434,7 @@
     
 ======================================================================*/
 
-static void sedlbauer_release(dev_link_t *link)
+static void sedlbauer_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
     DEBUG(0, "sedlbauer_release(0x%p)\n", link);
@@ -467,46 +445,23 @@
 	    HiSax_closecard(local->cardnr);
 	}
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
 
-    /*
-      In a normal driver, additional code may be needed to release
-      other kernel data structures associated with this device. 
-    */
-    
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-	pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    if (link->io.NumPorts1)
-	pcmcia_release_io(link->handle, &link->io);
-    if (link->irq.AssignedIRQ)
-	pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+    pcmcia_disable_device(link);
 } /* sedlbauer_release */
 
-static int sedlbauer_suspend(struct pcmcia_device *p_dev)
+static int sedlbauer_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
 	dev->stop = 1;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 
 	return 0;
 }
 
-static int sedlbauer_resume(struct pcmcia_device *p_dev)
+static int sedlbauer_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
 	dev->stop = 0;
 
 	return 0;
@@ -530,7 +485,7 @@
 	.drv		= {
 		.name	= "sedlbauer_cs",
 	},
-	.probe		= sedlbauer_attach,
+	.probe		= sedlbauer_probe,
 	.remove		= sedlbauer_detach,
 	.id_table	= sedlbauer_ids,
 	.suspend	= sedlbauer_suspend,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 4e5c14c..afcc2ae 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -75,8 +75,8 @@
    handler.
 */
 
-static void teles_cs_config(dev_link_t *link);
-static void teles_cs_release(dev_link_t *link);
+static int teles_cs_config(struct pcmcia_device *link);
+static void teles_cs_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -89,10 +89,10 @@
 /*
    A linked list of "instances" of the teles_cs device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -102,7 +102,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
    In this case, we also provide a flag to indicate if a device is
@@ -112,7 +112,7 @@
 */
 
 typedef struct local_info_t {
-    dev_link_t          link;
+	struct pcmcia_device	*p_dev;
     dev_node_t          node;
     int                 busy;
     int			cardnr;
@@ -130,9 +130,8 @@
 
 ======================================================================*/
 
-static int teles_attach(struct pcmcia_device *p_dev)
+static int teles_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     local_info_t *local;
 
     DEBUG(0, "teles_attach()\n");
@@ -142,7 +141,9 @@
     if (!local) return -ENOMEM;
     memset(local, 0, sizeof(local_info_t));
     local->cardnr = -1;
-    link = &local->link; link->priv = local;
+
+    local->p_dev = link;
+    link->priv = local;
 
     /* Interrupt setup */
     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
@@ -161,16 +162,9 @@
     link->io.IOAddrLines = 5;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    teles_cs_config(link);
-
-    return 0;
+    return teles_cs_config(link);
 } /* teles_attach */
 
 /*======================================================================
@@ -182,20 +176,16 @@
 
 ======================================================================*/
 
-static void teles_detach(struct pcmcia_device *p_dev)
+static void teles_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    local_info_t *info = link->priv;
+	local_info_t *info = link->priv;
 
-    DEBUG(0, "teles_detach(0x%p)\n", link);
+	DEBUG(0, "teles_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG) {
-	    info->busy = 1;
-	    teles_cs_release(link);
-    }
+	info->busy = 1;
+	teles_cs_release(link);
 
-    kfree(info);
-
+	kfree(info);
 } /* teles_detach */
 
 /*======================================================================
@@ -205,7 +195,7 @@
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(client_handle_t handle, tuple_t *tuple,
+static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_tuple_data(handle, tuple);
@@ -213,7 +203,7 @@
     return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_first_tuple(handle, tuple);
@@ -221,7 +211,7 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
                      cisparse_t *parse)
 {
     int i = pcmcia_get_next_tuple(handle, tuple);
@@ -229,9 +219,8 @@
     return get_tuple(handle, tuple, parse);
 }
 
-static void teles_cs_config(dev_link_t *link)
+static int teles_cs_config(struct pcmcia_device *link)
 {
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     local_info_t *dev;
@@ -241,7 +230,6 @@
     IsdnCard_t icard;
 
     DEBUG(0, "teles_config(0x%p)\n", link);
-    handle = link->handle;
     dev = link->priv;
 
     /*
@@ -253,7 +241,7 @@
     tuple.TupleDataMax = 255;
     tuple.TupleOffset = 0;
     tuple.Attributes = 0;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     if (i != CS_SUCCESS) {
         last_fn = ParseTuple;
 	goto cs_failed;
@@ -261,32 +249,29 @@
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(handle, &tuple, &parse);
+    i = first_tuple(link, &tuple, &parse);
     while (i == CS_SUCCESS) {
         if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
             printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
             link->conf.ConfigIndex = cf->index;
             link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
         } else {
           printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
           link->conf.ConfigIndex = cf->index;
           for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
             link->io.BasePort1 = j;
-            i = pcmcia_request_io(link->handle, &link->io);
+            i = pcmcia_request_io(link, &link->io);
             if (i == CS_SUCCESS) break;
           }
           break;
         }
-        i = next_tuple(handle, &tuple, &parse);
+        i = next_tuple(link, &tuple, &parse);
     }
 
     if (i != CS_SUCCESS) {
@@ -294,14 +279,14 @@
 	goto cs_failed;
     }
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS) {
         link->irq.AssignedIRQ = 0;
 	last_fn = RequestIRQ;
         goto cs_failed;
     }
 
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     if (i != CS_SUCCESS) {
       last_fn = RequestConfiguration;
       goto cs_failed;
@@ -312,14 +297,11 @@
     sprintf(dev->node.dev_name, "teles");
     dev->node.major = dev->node.minor = 0x0;
 
-    link->dev = &dev->node;
+    link->dev_node = &dev->node;
 
     /* Finally, report what we've done */
-    printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-           dev->node.dev_name, link->conf.ConfigIndex,
-           link->conf.Vcc/10, link->conf.Vcc%10);
-    if (link->conf.Vpp1)
-        printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+    printk(KERN_INFO "%s: index 0x%02x:",
+           dev->node.dev_name, link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
         printk(", irq %d", link->irq.AssignedIRQ);
     if (link->io.NumPorts1)
@@ -330,8 +312,6 @@
                link->io.BasePort2+link->io.NumPorts2-1);
     printk("\n");
 
-    link->state &= ~DEV_CONFIG_PENDING;
-
     icard.para[0] = link->irq.AssignedIRQ;
     icard.para[1] = link->io.BasePort1;
     icard.protocol = protocol;
@@ -342,13 +322,16 @@
     	printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
     		i, link->io.BasePort1);
     	teles_cs_release(link);
-    } else
-    	((local_info_t*)link->priv)->cardnr = i;
+	return -ENODEV;
+    }
 
-    return;
+    ((local_info_t*)link->priv)->cardnr = i;
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, i);
+    cs_error(link, last_fn, i);
     teles_cs_release(link);
+    return -ENODEV;
 } /* teles_cs_config */
 
 /*======================================================================
@@ -359,7 +342,7 @@
 
 ======================================================================*/
 
-static void teles_cs_release(dev_link_t *link)
+static void teles_cs_release(struct pcmcia_device *link)
 {
     local_info_t *local = link->priv;
 
@@ -371,39 +354,23 @@
 	    HiSax_closecard(local->cardnr);
 	}
     }
-    /* Unlink the device chain */
-    link->dev = NULL;
 
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win)
-        pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
+    pcmcia_disable_device(link);
 } /* teles_cs_release */
 
-static int teles_suspend(struct pcmcia_device *p_dev)
+static int teles_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
         dev->busy = 1;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 
 	return 0;
 }
 
-static int teles_resume(struct pcmcia_device *p_dev)
+static int teles_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
         dev->busy = 0;
 
 	return 0;
@@ -421,7 +388,7 @@
 	.drv		= {
 		.name	= "teles_cs",
 	},
-	.probe		= teles_attach,
+	.probe		= teles_probe,
 	.remove		= teles_detach,
 	.id_table       = teles_ids,
 	.suspend	= teles_suspend,
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a0927d1..9187422 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -109,7 +109,7 @@
 {
 	struct ippp_struct *is;
 
-	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
 		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
 			__FUNCTION__, lp->ppp_slot);
 		return 0;
@@ -126,7 +126,7 @@
 	lp->netdev->pb->ref_ct--;
 	spin_unlock(&lp->netdev->pb->lock);
 #endif /* CONFIG_ISDN_MPP */
-	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
 		printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
 			__FUNCTION__, lp->ppp_slot);
 		return 0;
@@ -279,7 +279,7 @@
 	int slot;
 	struct ippp_struct *is;
 
-	if (min < 0 || min > ISDN_MAX_CHANNELS)
+	if (min < 0 || min >= ISDN_MAX_CHANNELS)
 		return -ENODEV;
 
 	slot = isdn_ppp_get_slot();
@@ -1042,7 +1042,7 @@
  	if (lp->master) { // FIXME?
 		mlp = (isdn_net_local *) lp->master->priv;
  		slot = mlp->ppp_slot;
- 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ 		if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
  			printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
  				lp->ppp_slot);
 			goto drop_packet;
@@ -1264,7 +1264,7 @@
 	/* we have our lp locked from now on */
 
 	slot = lp->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
 		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
 			lp->ppp_slot);
 		kfree_skb(skb);
@@ -1603,7 +1603,7 @@
     	mp = net_dev->pb;
         stats = &mp->stats;
 	slot = lp->ppp_slot;
-	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
 		printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
 			__FUNCTION__, lp->ppp_slot);
 		stats->frame_drops++;
@@ -1640,7 +1640,7 @@
 	is->last_link_seqno = minseq = newseq;
 	for (lpq = net_dev->queue;;) {
 		slot = lpq->ppp_slot;
-		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
 			printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
 				__FUNCTION__, lpq->ppp_slot);
 		} else {
@@ -2648,7 +2648,7 @@
 
 	printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
 		lp->ppp_slot);
-	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
 		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
 			__FUNCTION__, lp->ppp_slot);
 		return;
@@ -2658,7 +2658,7 @@
 
 	if(lp->master) {
 		int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
-		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
 			printk(KERN_ERR "%s: slot(%d) out of range\n",
 				__FUNCTION__, slot);
 			return;
@@ -2845,7 +2845,7 @@
 
 	if (lp->master) {
 		slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
-		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
 			printk(KERN_ERR "%s: slot(%d) out of range\n",
 				__FUNCTION__, slot);
 			return;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 2c4f20b..3f5b647 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -14,13 +14,7 @@
 	  This option enables the led sysfs class in /sys/class/leds.  You'll
 	  need this to do anything useful with LEDs.  If unsure, say N.
 
-config LEDS_TRIGGERS
-	bool "LED Trigger support"
-	depends NEW_LEDS
-	help
-	  This option enables trigger support for the leds class.
-	  These triggers allow kernel events to drive the LEDs and can
-	  be configured via sysfs. If unsure, say Y.
+comment "LED drivers"
 
 config LEDS_CORGI
 	tristate "LED Support for the Sharp SL-C7x0 series"
@@ -59,6 +53,23 @@
 	  This option enables support for the LEDs on Sharp Zaurus
 	  SL-6000 series.
 
+config LEDS_S3C24XX
+	tristate "LED Support for Samsung S3C24XX GPIO LEDs"
+	depends on LEDS_CLASS && ARCH_S3C2410
+	help
+	  This option enables support for LEDs connected to GPIO lines
+	  on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
+
+comment "LED Triggers"
+
+config LEDS_TRIGGERS
+	bool "LED Trigger support"
+	depends NEW_LEDS
+	help
+	  This option enables trigger support for the leds class.
+	  These triggers allow kernel events to drive the LEDs and can
+	  be configured via sysfs. If unsure, say Y.
+
 config LEDS_TRIGGER_TIMER
 	tristate "LED Timer Trigger"
 	depends LEDS_TRIGGERS
@@ -67,7 +78,7 @@
 	  via sysfs. If unsure, say Y.
 
 config LEDS_TRIGGER_IDE_DISK
-	bool "LED Timer Trigger"
+	bool "LED IDE Disk Trigger"
 	depends LEDS_TRIGGERS && BLK_DEV_IDEDISK
 	help
 	  This allows LEDs to be controlled by IDE disk activity.
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 40699d3..40f0426 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_LEDS_SPITZ)		+= leds-spitz.o
 obj-$(CONFIG_LEDS_IXP4XX)		+= leds-ixp4xx-gpio.o
 obj-$(CONFIG_LEDS_TOSA)			+= leds-tosa.o
+obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
new file mode 100644
index 0000000..650cf72
--- /dev/null
+++ b/drivers/leds/leds-s3c24xx.c
@@ -0,0 +1,163 @@
+/* drivers/leds/leds-s3c24xx.c
+ *
+ * (c) 2006 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO driver
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
+
+/* our context */
+
+struct s3c24xx_gpio_led {
+	struct led_classdev		 cdev;
+	struct s3c24xx_led_platdata	*pdata;
+};
+
+static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
+{
+	return platform_get_drvdata(dev);
+}
+
+static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
+{
+	return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
+}
+
+static void s3c24xx_led_set(struct led_classdev *led_cdev,
+			    enum led_brightness value)
+{
+	struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
+	struct s3c24xx_led_platdata *pd = led->pdata;
+
+	/* there will be a sort delay between setting the output and
+	 * going from output to input when using tristate. */
+
+	s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
+			    (pd->flags & S3C24XX_LEDF_ACTLOW));
+
+	if (pd->flags & S3C24XX_LEDF_TRISTATE)
+		s3c2410_gpio_cfgpin(pd->gpio,
+				    value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
+
+}
+
+static int s3c24xx_led_remove(struct platform_device *dev)
+{
+	struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+	led_classdev_unregister(&led->cdev);
+	kfree(led);
+
+	return 0;
+}
+
+static int s3c24xx_led_probe(struct platform_device *dev)
+{
+	struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
+	struct s3c24xx_gpio_led *led;
+	int ret;
+
+	led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);
+	if (led == NULL) {
+		dev_err(&dev->dev, "No memory for device\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(dev, led);
+
+	led->cdev.brightness_set = s3c24xx_led_set;
+	led->cdev.default_trigger = pdata->def_trigger;
+	led->cdev.name = pdata->name;
+
+	led->pdata = pdata;
+
+	/* no point in having a pull-up if we are always driving */
+
+	if (pdata->flags & S3C24XX_LEDF_TRISTATE) {
+		s3c2410_gpio_setpin(pdata->gpio, 0);
+		s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT);
+	} else {
+		s3c2410_gpio_pullup(pdata->gpio, 0);
+		s3c2410_gpio_setpin(pdata->gpio, 0);
+		s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT);
+	}
+
+	/* register our new led device */
+
+	ret = led_classdev_register(&dev->dev, &led->cdev);
+	if (ret < 0) {
+		dev_err(&dev->dev, "led_classdev_register failed\n");
+		goto exit_err1;
+	}
+
+	return 0;
+
+ exit_err1:
+	kfree(led);
+	return ret;
+}
+
+
+#ifdef CONFIG_PM
+static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+	led_classdev_suspend(&led->cdev);
+	return 0;
+}
+
+static int s3c24xx_led_resume(struct platform_device *dev)
+{
+	struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
+
+	led_classdev_resume(&led->cdev);
+	return 0;
+}
+#else
+#define s3c24xx_led_suspend NULL
+#define s3c24xx_led_resume NULL
+#endif
+
+static struct platform_driver s3c24xx_led_driver = {
+	.probe		= s3c24xx_led_probe,
+	.remove		= s3c24xx_led_remove,
+	.suspend	= s3c24xx_led_suspend,
+	.resume		= s3c24xx_led_resume,
+	.driver		= {
+		.name		= "s3c24xx_led",
+		.owner		= THIS_MODULE,
+	},
+};
+
+static int __init s3c24xx_led_init(void)
+{
+	return platform_driver_register(&s3c24xx_led_driver);
+}
+
+static void __exit s3c24xx_led_exit(void)
+{
+ 	platform_driver_unregister(&s3c24xx_led_driver);
+}
+
+module_init(s3c24xx_led_init);
+module_exit(s3c24xx_led_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("S3C24XX LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 5ebfd1d..5282fec 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -627,8 +627,8 @@
 	if(therm_type == ADT7460)
 		device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
 
-#ifndef CONFIG_I2C_KEYWEST
-	request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+	request_module("i2c-powermac");
 #endif
 
 	return i2c_add_driver(&thermostat_driver);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index fd2aae1..ac25a48 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -139,11 +139,12 @@
 	  is online.  However it is still EXPERIMENTAL code.  It should
 	  work, but please be sure that you have backups.
 
-	  You will need a version of mdadm newer than 2.3.1.   During the
-	  early stage of reshape there is a critical section where live data
-	  is being over-written.  A crash during this time needs extra care
-	  for recovery.  The newer mdadm takes a copy of the data in the
-	  critical section and will restore it, if necessary, after a crash.
+	  You will need mdadm verion 2.4.1 or later to use this
+	  feature safely.  During the early stage of reshape there is
+	  a critical section where live data is being over-written.  A
+	  crash during this time needs extra care for recovery.  The
+	  newer mdadm takes a copy of the data in the critical section
+	  and will restore it, if necessary, after a crash.
 
 	  The mdadm usage is e.g.
 	       mdadm --grow /dev/md1 --raid-disks=6
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index aecd9e0..64fd8e7 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -78,8 +78,7 @@
 	if (--ti->use == 0)
 		module_put(ti->tt.module);
 
-	if (ti->use < 0)
-		BUG();
+	BUG_ON(ti->use < 0);
 	up_read(&_lock);
 
 	return;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1ed5152..d7316b8 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -163,6 +163,7 @@
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
+	sysfs_notify(&mddev->kobj, NULL, "sync_action");
 }
 EXPORT_SYMBOL_GPL(md_new_event);
 
@@ -278,11 +279,6 @@
 	return mutex_lock_interruptible(&mddev->reconfig_mutex);
 }
 
-static inline void mddev_lock_uninterruptible(mddev_t * mddev)
-{
-	mutex_lock(&mddev->reconfig_mutex);
-}
-
 static inline int mddev_trylock(mddev_t * mddev)
 {
 	return mutex_trylock(&mddev->reconfig_mutex);
@@ -2457,9 +2453,11 @@
 
 	if (!entry->show)
 		return -EIO;
-	mddev_lock(mddev);
-	rv = entry->show(mddev, page);
-	mddev_unlock(mddev);
+	rv = mddev_lock(mddev);
+	if (!rv) {
+		rv = entry->show(mddev, page);
+		mddev_unlock(mddev);
+	}
 	return rv;
 }
 
@@ -2473,9 +2471,11 @@
 
 	if (!entry->store)
 		return -EIO;
-	mddev_lock(mddev);
-	rv = entry->store(mddev, page, length);
-	mddev_unlock(mddev);
+	rv = mddev_lock(mddev);
+	if (!rv) {
+		rv = entry->store(mddev, page, length);
+		mddev_unlock(mddev);
+	}
 	return rv;
 }
 
@@ -4340,8 +4340,9 @@
 		return 0;
 	}
 
-	if (mddev_lock(mddev)!=0) 
+	if (mddev_lock(mddev) < 0)
 		return -EINTR;
+
 	if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
 		seq_printf(seq, "%s : %sactive", mdname(mddev),
 						mddev->pers ? "" : "in");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9b374c9..6081941 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1558,8 +1558,7 @@
 	int buffs;
 
 	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
-	if (conf->r1buf_pool)
-		BUG();
+	BUG_ON(conf->r1buf_pool);
 	conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
 					  conf->poolinfo);
 	if (!conf->r1buf_pool)
@@ -1732,8 +1731,7 @@
 			    !conf->fullsync &&
 			    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
 				break;
-			if (sync_blocks < (PAGE_SIZE>>9))
-				BUG();
+			BUG_ON(sync_blocks < (PAGE_SIZE>>9));
 			if (len > (sync_blocks<<9))
 				len = sync_blocks<<9;
 		}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ab90a6d..617012b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1117,8 +1117,7 @@
 	for (i=0; i<conf->copies; i++)
 		if (r10_bio->devs[i].bio == bio)
 			break;
-	if (i == conf->copies)
-		BUG();
+	BUG_ON(i == conf->copies);
 	update_head_pos(i, r10_bio);
 	d = r10_bio->devs[i].devnum;
 
@@ -1518,8 +1517,7 @@
 	int buffs;
 
 	buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
-	if (conf->r10buf_pool)
-		BUG();
+	BUG_ON(conf->r10buf_pool);
 	conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf);
 	if (!conf->r10buf_pool)
 		return -ENOMEM;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index dae740a..3184360 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -73,10 +73,8 @@
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
-		if (!list_empty(&sh->lru))
-			BUG();
-		if (atomic_read(&conf->active_stripes)==0)
-			BUG();
+		BUG_ON(!list_empty(&sh->lru));
+		BUG_ON(atomic_read(&conf->active_stripes)==0);
 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
 			if (test_bit(STRIPE_DELAYED, &sh->state))
 				list_add_tail(&sh->lru, &conf->delayed_list);
@@ -184,10 +182,8 @@
 	raid5_conf_t *conf = sh->raid_conf;
 	int i;
 
-	if (atomic_read(&sh->count) != 0)
-		BUG();
-	if (test_bit(STRIPE_HANDLE, &sh->state))
-		BUG();
+	BUG_ON(atomic_read(&sh->count) != 0);
+	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 	
 	CHECK_DEVLOCK();
 	PRINTK("init_stripe called, stripe %llu\n", 
@@ -269,8 +265,7 @@
 				init_stripe(sh, sector, pd_idx, disks);
 		} else {
 			if (atomic_read(&sh->count)) {
-				if (!list_empty(&sh->lru))
-					BUG();
+			  BUG_ON(!list_empty(&sh->lru));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
@@ -465,8 +460,7 @@
 	spin_unlock_irq(&conf->device_lock);
 	if (!sh)
 		return 0;
-	if (atomic_read(&sh->count))
-		BUG();
+	BUG_ON(atomic_read(&sh->count));
 	shrink_buffers(sh, conf->pool_size);
 	kmem_cache_free(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
@@ -882,8 +876,7 @@
 	ptr[0] = page_address(sh->dev[pd_idx].page);
 	switch(method) {
 	case READ_MODIFY_WRITE:
-		if (!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags))
-			BUG();
+		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
 		for (i=disks ; i-- ;) {
 			if (i==pd_idx)
 				continue;
@@ -896,7 +889,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 				check_xor();
 			}
@@ -912,7 +905,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 			}
 		break;
@@ -995,8 +988,7 @@
 	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
 		goto overlap;
 
-	if (*bip && bi->bi_next && (*bip) != bi->bi_next)
-		BUG();
+	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
 	if (*bip)
 		bi->bi_next = *bip;
 	*bip = bi;
@@ -1430,8 +1422,7 @@
 		set_bit(STRIPE_HANDLE, &sh->state);
 		if (failed == 0) {
 			char *pagea;
-			if (uptodate != disks)
-				BUG();
+			BUG_ON(uptodate != disks);
 			compute_parity(sh, CHECK_PARITY);
 			uptodate--;
 			pagea = page_address(sh->dev[sh->pd_idx].page);
@@ -2096,8 +2087,7 @@
 
 		list_del_init(first);
 		atomic_inc(&sh->count);
-		if (atomic_read(&sh->count)!= 1)
-			BUG();
+		BUG_ON(atomic_read(&sh->count)!= 1);
 		spin_unlock_irq(&conf->device_lock);
 		
 		handled++;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index ab64b37..bc69355 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -91,10 +91,8 @@
 static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
-		if (!list_empty(&sh->lru))
-			BUG();
-		if (atomic_read(&conf->active_stripes)==0)
-			BUG();
+		BUG_ON(!list_empty(&sh->lru));
+		BUG_ON(atomic_read(&conf->active_stripes)==0);
 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
 			if (test_bit(STRIPE_DELAYED, &sh->state))
 				list_add_tail(&sh->lru, &conf->delayed_list);
@@ -202,10 +200,8 @@
 	raid6_conf_t *conf = sh->raid_conf;
 	int disks = conf->raid_disks, i;
 
-	if (atomic_read(&sh->count) != 0)
-		BUG();
-	if (test_bit(STRIPE_HANDLE, &sh->state))
-		BUG();
+	BUG_ON(atomic_read(&sh->count) != 0);
+	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
 
 	CHECK_DEVLOCK();
 	PRINTK("init_stripe called, stripe %llu\n",
@@ -284,13 +280,11 @@
 				init_stripe(sh, sector, pd_idx);
 		} else {
 			if (atomic_read(&sh->count)) {
-				if (!list_empty(&sh->lru))
-					BUG();
+				BUG_ON(!list_empty(&sh->lru));
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
-				if (list_empty(&sh->lru))
-					BUG();
+				BUG_ON(list_empty(&sh->lru));
 				list_del_init(&sh->lru);
 			}
 		}
@@ -353,8 +347,7 @@
 	spin_unlock_irq(&conf->device_lock);
 	if (!sh)
 		return 0;
-	if (atomic_read(&sh->count))
-		BUG();
+	BUG_ON(atomic_read(&sh->count));
 	shrink_buffers(sh, conf->raid_disks);
 	kmem_cache_free(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
@@ -780,7 +773,7 @@
 				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 					wake_up(&conf->wait_for_overlap);
 
-				if (sh->dev[i].written) BUG();
+				BUG_ON(sh->dev[i].written);
 				sh->dev[i].written = chosen;
 			}
 		break;
@@ -970,8 +963,7 @@
 	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
 		goto overlap;
 
-	if (*bip && bi->bi_next && (*bip) != bi->bi_next)
-		BUG();
+	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
 	if (*bip)
 		bi->bi_next = *bip;
 	*bip = bi;
@@ -1906,8 +1898,7 @@
 
 		list_del_init(first);
 		atomic_inc(&sh->count);
-		if (atomic_read(&sh->count)!= 1)
-			BUG();
+		BUG_ON(atomic_read(&sh->count)!= 1);
 		spin_unlock_irq(&conf->device_lock);
 
 		handled++;
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index baa9f58..fffc711 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -51,18 +51,18 @@
 	tristate
 
 config USB_DABUSB
-        tristate "DABUSB driver"
-        depends on USB
-        ---help---
-          A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
-          brought to you by the DAB-Team
-          <http://wwwbode.cs.tum.edu/Par/arch/dab/>.  This driver can be taken
-          as an example for URB-based bulk, control, and isochronous
-          transactions. URB's are explained in
-          <Documentation/usb/URB.txt>.
+	tristate "DABUSB driver"
+	depends on USB
+	---help---
+	  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+	  brought to you by the DAB-Team
+	  <http://wwwbode.cs.tum.edu/Par/arch/dab/>.  This driver can be taken
+	  as an example for URB-based bulk, control, and isochronous
+	  transactions. URB's are explained in
+	  <Documentation/usb/URB.txt>.
 
-          To compile this driver as a module, choose M here: the
-          module will be called dabusb.
+	  To compile this driver as a module, choose M here: the
+	  module will be called dabusb.
 
 endmenu
 
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index 2337b41..376ca48f 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -7,6 +7,7 @@
 	select DVB_CX24110
 	select DVB_OR51211
 	select DVB_LGDT330X
+	select FW_LOADER
 	help
 	  Support for PCI cards based on the Bt8xx PCI bridge. Examples are
 	  the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 09e96e9..04578df 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -141,12 +141,18 @@
 	}
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		void *mem = vmalloc(DVR_BUFFER_SIZE);
+		void *mem;
+		if (!dvbdev->readers) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EBUSY;
+		}
+		mem = vmalloc(DVR_BUFFER_SIZE);
 		if (!mem) {
 			mutex_unlock(&dmxdev->mutex);
 			return -ENOMEM;
 		}
 		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+		dvbdev->readers--;
 	}
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
@@ -184,6 +190,7 @@
 						dmxdev->dvr_orig_fe);
 	}
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		dvbdev->readers++;
 		if (dmxdev->dvr_buffer.data) {
 			void *mem = dmxdev->dvr_buffer.data;
 			mb();
@@ -1029,8 +1036,7 @@
 
 static struct dvb_device dvbdev_dvr = {
 	.priv = NULL,
-	.users = 1,
-	.writers = 1,
+	.readers = 1,
 	.fops = &dvb_dvr_fops
 };
 
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 2c3ea8f..4f8f257 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -105,6 +105,7 @@
 	fe_status_t status;
 	unsigned long tune_mode_flags;
 	unsigned int delay;
+	unsigned int reinitialise;
 
 	/* swzigzag values */
 	unsigned int state;
@@ -121,6 +122,7 @@
 	unsigned int check_wrapped;
 };
 
+static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 
 static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 {
@@ -213,6 +215,15 @@
 		fe->ops->init(fe);
 }
 
+void dvb_frontend_reinitialise(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	fepriv->reinitialise = 1;
+	dvb_frontend_wakeup(fe);
+}
+EXPORT_SYMBOL(dvb_frontend_reinitialise);
+
 static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
 {
 	int q2;
@@ -505,8 +516,8 @@
 	fepriv->quality = 0;
 	fepriv->delay = 3*HZ;
 	fepriv->status = 0;
-	dvb_frontend_init(fe);
 	fepriv->wakeup = 0;
+	fepriv->reinitialise = 1;
 
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
@@ -524,6 +535,11 @@
 		if (down_interruptible(&fepriv->sem))
 			break;
 
+		if (fepriv->reinitialise) {
+			dvb_frontend_init(fe);
+			fepriv->reinitialise = 0;
+		}
+
 		/* do an iteration of the tuning loop */
 		if (fe->ops->tune) {
 			/* have we been asked to retune? */
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index d5aee5a..5926a3b 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -112,6 +112,8 @@
 
 extern int dvb_unregister_frontend(struct dvb_frontend* fe);
 
+extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
+
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
 extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
 
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index a14e737..7edd636 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -233,6 +233,45 @@
 	{ 0xfe, 0x4e, KEY_POWER },
 };
 
+static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
+	{ 0xfc, 0x02, KEY_SETUP },       /* Profile */
+	{ 0xfc, 0x43, KEY_POWER2 },
+	{ 0xfc, 0x06, KEY_EPG },
+	{ 0xfc, 0x5a, KEY_BACK },
+	{ 0xfc, 0x05, KEY_MENU },
+	{ 0xfc, 0x47, KEY_INFO },
+	{ 0xfc, 0x01, KEY_TAB },
+	{ 0xfc, 0x42, KEY_PREVIOUSSONG },/* Replay */
+	{ 0xfc, 0x49, KEY_VOLUMEUP },
+	{ 0xfc, 0x09, KEY_VOLUMEDOWN },
+	{ 0xfc, 0x54, KEY_CHANNELUP },
+	{ 0xfc, 0x0b, KEY_CHANNELDOWN },
+	{ 0xfc, 0x16, KEY_CAMERA },
+	{ 0xfc, 0x40, KEY_TUNER },	/* ATV/DTV */
+	{ 0xfc, 0x45, KEY_OPEN },
+	{ 0xfc, 0x19, KEY_1 },
+	{ 0xfc, 0x18, KEY_2 },
+	{ 0xfc, 0x1b, KEY_3 },
+	{ 0xfc, 0x1a, KEY_4 },
+	{ 0xfc, 0x58, KEY_5 },
+	{ 0xfc, 0x59, KEY_6 },
+	{ 0xfc, 0x15, KEY_7 },
+	{ 0xfc, 0x14, KEY_8 },
+	{ 0xfc, 0x17, KEY_9 },
+	{ 0xfc, 0x44, KEY_ANGLE },	/* Aspect */
+	{ 0xfc, 0x55, KEY_0 },
+	{ 0xfc, 0x07, KEY_ZOOM },
+	{ 0xfc, 0x0a, KEY_REWIND },
+	{ 0xfc, 0x08, KEY_PLAYPAUSE },
+	{ 0xfc, 0x4b, KEY_FASTFORWARD },
+	{ 0xfc, 0x5b, KEY_MUTE },
+	{ 0xfc, 0x04, KEY_STOP },
+	{ 0xfc, 0x56, KEY_RECORD },
+	{ 0xfc, 0x57, KEY_POWER },
+	{ 0xfc, 0x41, KEY_UNKNOWN },    /* INPUT */
+	{ 0xfc, 0x00, KEY_UNKNOWN },    /* HD */
+};
+
 static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
 {
 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
@@ -511,6 +550,11 @@
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
+	.rc_interval      = 100,
+	.rc_key_map       = dvico_portable_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(dvico_portable_rc_keys),
+	.rc_query         = cxusb_rc_query,
+
 	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
 	.urb = {
@@ -600,6 +644,11 @@
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
+	.rc_interval      = 100,
+	.rc_key_map       = dvico_portable_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(dvico_portable_rc_keys),
+	.rc_query         = cxusb_rc_query,
+
 	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
 	.urb = {
@@ -640,6 +689,11 @@
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
+	.rc_interval      = 100,
+	.rc_key_map       = dvico_portable_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(dvico_portable_rc_keys),
+	.rc_query         = cxusb_rc_query,
+
 	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
 	.urb = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 12ebaf8..70afcfd 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -94,12 +94,14 @@
 
 static struct dvb_usb_properties dtt200u_properties;
 static struct dvb_usb_properties wt220u_properties;
+static struct dvb_usb_properties wt220u_zl0353_properties;
 
 static int dtt200u_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
 	if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
-		dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
+		dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+		dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
 		return 0;
 
 	return -ENODEV;
@@ -110,6 +112,8 @@
 	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
 	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
 	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
+	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD)  },
+	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM)  },
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -196,6 +200,47 @@
 	}
 };
 
+static struct dvb_usb_properties wt220u_zl0353_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+	.pid_filter_count = 15,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-wt220u-zl0353-01.fw",
+
+	.power_ctrl      = dtt200u_power_ctrl,
+	.streaming_ctrl  = dtt200u_streaming_ctrl,
+	.pid_filter      = dtt200u_pid_filter,
+	.frontend_attach = dtt200u_frontend_attach,
+
+	.rc_interval     = 300,
+	.rc_key_map      = dtt200u_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+	.rc_query        = dtt200u_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "WideView WT-220U PenType Receiver (based on ZL353)",
+		  .cold_ids = { &dtt200u_usb_table[4], NULL },
+		  .warm_ids = { &dtt200u_usb_table[5], NULL },
+		},
+		{ NULL },
+	}
+};
+
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver dtt200u_usb_driver = {
 	.name		= "dvb_usb_dtt200u",
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 4a1b9e77..cb23904 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -83,6 +83,8 @@
 #define USB_PID_DTT200U_WARM				0x0301
 #define USB_PID_WT220U_COLD					0x0222
 #define USB_PID_WT220U_WARM					0x0221
+#define USB_PID_WT220U_ZL0353_COLD			0x022a
+#define USB_PID_WT220U_ZL0353_WARM			0x022b
 #define USB_PID_WINTV_NOVA_T_USB2_COLD		0x9300
 #define USB_PID_WINTV_NOVA_T_USB2_WARM		0x9301
 #define USB_PID_NEBULA_DIGITV				0x0201
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index b6d95e1..2a89f8c 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -147,8 +147,9 @@
 	cmd[4] = (sr >> 4)  & 0xff;
 	cmd[5] = (sr << 4)  & 0xf0;
 
-	deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
-			fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
+	deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
+			fep->frequency,freq,freq, fep->u.qpsk.symbol_rate,
+			(unsigned long) sr, (unsigned long) sr);
 
 /*	if (fep->inversion == INVERSION_ON)
 		cmd[6] |= 0x80; */
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 9423316..37d5e0a 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -181,6 +181,11 @@
 	help
 	  An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
 
+	  This driver needs external firmware. Please use the command
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+	  download it, and then copy it to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
 config DVB_OR51132
 	tristate "Oren OR51132 based"
 	depends on DVB_CORE
@@ -189,6 +194,13 @@
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+	  This driver needs external firmware. Please use the commands
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
+	  download firmwares for 8VSB and QAM64/256, respectively. Copy them to
+	  /usr/lib/hotplug/firmware or /lib/firmware (depending on
+	  configuration of firmware hotplug).
+
 config DVB_BCM3510
 	tristate "Broadcom BCM3510"
 	depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 8e8df7b..b83dafa 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -52,7 +52,6 @@
 	struct dvb_frontend frontend;
 
 	/* private demod data */
-	u8 initialised;
 	enum tda1004x_demod demod_type;
 };
 
@@ -594,9 +593,6 @@
 
 	dprintk("%s\n", __FUNCTION__);
 
-	if (state->initialised)
-		return 0;
-
 	if (tda10045_fwupload(fe)) {
 		printk("tda1004x: firmware upload failed\n");
 		return -EIO;
@@ -626,7 +622,6 @@
 
 	tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
 
-	state->initialised = 1;
 	return 0;
 }
 
@@ -635,9 +630,6 @@
 	struct tda1004x_state* state = fe->demodulator_priv;
 	dprintk("%s\n", __FUNCTION__);
 
-	if (state->initialised)
-		return 0;
-
 	if (tda10046_fwupload(fe)) {
 		printk("tda1004x: firmware upload failed\n");
 			return -EIO;
@@ -697,7 +689,6 @@
 	// tda1004x_write_mask(state, 0x50, 0x80, 0x80);         // handle out of guard echoes
 	tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
 
-	state->initialised = 1;
 	return 0;
 }
 
@@ -1207,7 +1198,6 @@
 		tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
 		break;
 	}
-	state->initialised = 0;
 
 	return 0;
 }
@@ -1271,7 +1261,6 @@
 	state->config = config;
 	state->i2c = i2c;
 	memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
-	state->initialised = 0;
 	state->demod_type = TDA1004X_DEMOD_TDA10045;
 
 	/* check if the demod is there */
@@ -1330,7 +1319,6 @@
 	state->config = config;
 	state->i2c = i2c;
 	memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
-	state->initialised = 0;
 	state->demod_type = TDA1004X_DEMOD_TDA10046;
 
 	/* check if the demod is there */
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 840efec..d028245 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -87,6 +87,7 @@
 static int budgetpatch;
 static int wss_cfg_4_3 = 0x4008;
 static int wss_cfg_16_9 = 0x0007;
+static int tv_standard;
 
 module_param_named(debug, av7110_debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -109,6 +110,8 @@
 MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
 module_param(wss_cfg_16_9, int, 0444);
 MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
+module_param(tv_standard, int, 0444);
+MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
 
 static void restart_feeds(struct av7110 *av7110);
 
@@ -2123,7 +2126,7 @@
 							read_pwm(av7110));
 				break;
 			case 0x0003:
-				/* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */
+				/* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
 				av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
 							read_pwm(av7110));
 				break;
@@ -2543,6 +2546,9 @@
 	av7110->osdwin = 1;
 	mutex_init(&av7110->osd_mutex);
 
+	/* TV standard */
+	av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
+
 	/* ARM "watchdog" */
 	init_waitqueue_head(&av7110->arm_wait);
 	av7110->arm_thread = NULL;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 400face..2eff09f 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1479,8 +1479,6 @@
 	void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
 	int i, ret;
 
-	av7110->vidmode = VIDEO_MODE_PAL;
-
 	for (i = 0; i < 2; i++) {
 		struct ipack *ipack = av7110->ipack + i;
 
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9dd4745..8efe3ce 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -60,11 +60,11 @@
 	struct dvb_ca_en50221 ca;
 };
 
-/* GPIO CI Connections:
- * 0 - Vcc/Reset (Reset is controlled by capacitor)
- * 1 - Attribute Memory
- * 2 - Card Enable (Active Low)
- * 3 - Card Detect
+/* GPIO Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
+ * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
+ * 2 - CI Card Enable (Active Low)
+ * 3 - CI Card Detect
  */
 
 /****************************************************************************
@@ -214,6 +214,9 @@
 	while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
 		msleep(100);
 
+	/* reinitialise the frontend */
+	dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+
 	if (timeout <= 0)
 	{
 		printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 633e68c..ea2066d 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -39,9 +39,21 @@
 #include "budget.h"
 #include "ttpci-eeprom.h"
 
+#define TS_WIDTH		(2 * TS_SIZE)
+#define TS_WIDTH_ACTIVY		TS_SIZE
+#define TS_HEIGHT_MASK		0xf00
+#define TS_HEIGHT_MASK_ACTIVY	0xc00
+#define TS_MIN_BUFSIZE_K	188
+#define TS_MAX_BUFSIZE_K	1410
+#define TS_MAX_BUFSIZE_K_ACTIVY	564
+#define BUFFER_WARNING_WAIT	(30*HZ)
+
 int budget_debug;
+static int dma_buffer_size = TS_MIN_BUFSIZE_K;
 module_param_named(debug, budget_debug, int, 0644);
+module_param_named(bufsize, dma_buffer_size, int, 0444);
 MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
+MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
 
 /****************************************************************************
  * TT budget / WinTV Nova
@@ -70,11 +82,10 @@
 
 	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
 
-	memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
+	memset(budget->grabbing, 0x00, budget->buffer_size);
 
 	saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
 
-	budget->tsf = 0xff;
 	budget->ttbp = 0;
 
 	/*
@@ -115,16 +126,12 @@
 
 	saa7146_write(dev, BASE_ODD3, 0);
 	saa7146_write(dev, BASE_EVEN3, 0);
-	saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+	saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
 	saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
 
-	if (budget->card->type == BUDGET_FS_ACTIVY) {
-		saa7146_write(dev, PITCH3, TS_WIDTH / 2);
-		saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT * 2) << 16) | (TS_WIDTH / 2));
-	} else {
-		saa7146_write(dev, PITCH3, TS_WIDTH);
-		saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
-	}
+	saa7146_write(dev, PITCH3, budget->buffer_width);
+	saa7146_write(dev, NUM_LINE_BYTE3,
+			(budget->buffer_height << 16) | budget->buffer_width);
 
 	saa7146_write(dev, MC2, (MASK_04 | MASK_20));
 
@@ -141,11 +148,12 @@
 	u8 *mem = (u8 *) (budget->grabbing);
 	u32 olddma = budget->ttbp;
 	u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+	u32 count;
 
 	/* nearest lower position divisible by 188 */
 	newdma -= newdma % 188;
 
-	if (newdma >= TS_BUFLEN)
+	if (newdma >= budget->buffer_size)
 		return;
 
 	budget->ttbp = newdma;
@@ -154,11 +162,24 @@
 		return;
 
 	if (newdma > olddma) {	/* no wraparound, dump olddma..newdma */
-		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
+		count = newdma - olddma;
+		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
 	} else {		/* wraparound, dump olddma..buflen and 0..newdma */
-		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+		count = budget->buffer_size - olddma;
+		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
+		count += newdma;
 		dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
 	}
+
+	if (count > budget->buffer_warning_threshold)
+		budget->buffer_warnings++;
+
+	if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
+		printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
+			budget->dev->name, __FUNCTION__, budget->buffer_warnings, count);
+		budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
+		budget->buffer_warnings = 0;
+	}
 }
 
 
@@ -341,9 +362,10 @@
 		      struct saa7146_pci_extension_data *info,
 		      struct module *owner)
 {
-	int length = TS_WIDTH * TS_HEIGHT;
 	int ret = 0;
 	struct budget_info *bi = info->ext_priv;
+	int max_bufsize;
+	int height_mask;
 
 	memset(budget, 0, sizeof(struct budget));
 
@@ -352,6 +374,32 @@
 	budget->card = bi;
 	budget->dev = (struct saa7146_dev *) dev;
 
+	if (budget->card->type == BUDGET_FS_ACTIVY) {
+		budget->buffer_width = TS_WIDTH_ACTIVY;
+		max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
+		height_mask = TS_HEIGHT_MASK_ACTIVY;
+	} else {
+		budget->buffer_width = TS_WIDTH;
+		max_bufsize = TS_MAX_BUFSIZE_K;
+		height_mask = TS_HEIGHT_MASK;
+	}
+
+	if (dma_buffer_size < TS_MIN_BUFSIZE_K)
+		dma_buffer_size = TS_MIN_BUFSIZE_K;
+	else if (dma_buffer_size > max_bufsize)
+		dma_buffer_size = max_bufsize;
+
+	budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
+	budget->buffer_height &= height_mask;
+	budget->buffer_size = budget->buffer_height * budget->buffer_width;
+	budget->buffer_warning_threshold = budget->buffer_size * 80/100;
+	budget->buffer_warnings = 0;
+	budget->buffer_warning_time = jiffies;
+
+	dprintk(2, "%s: width = %d, height = %d\n",
+		budget->dev->name, budget->buffer_width, budget->buffer_height);
+	printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
+
 	dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
 
 	/* set dd1 stream a & b */
@@ -392,7 +440,7 @@
 	ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
 
 	if (NULL ==
-	    (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) {
+	    (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) {
 		ret = -ENOMEM;
 		goto err;
 	}
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 9fc9185..1b3aaac 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -577,20 +577,6 @@
 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
 	// Set RPS1 Address register to point to RPS code               (r108 p42)
 	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-	// Set Source Line Counter Threshold, using BRS                 (rCC p43)
-	// It generates HS event every TS_HEIGHT lines
-	// this is related to TS_WIDTH set in register
-	// NUM_LINE_BYTE3 in budget-core.c. If NUM_LINE_BYTE
-	// low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188
-	//,then RPS_THRESH1
-	// should be set to trigger every TS_HEIGHT (512) lines.
-	//
-	saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
-
-	// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
-	// Enable RPS1                                                  (rFC p33)
-	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
 
 	if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
 		return -ENOMEM;
@@ -602,6 +588,20 @@
 		return err;
 	}
 
+	// Set Source Line Counter Threshold, using BRS                 (rCC p43)
+	// It generates HS event every TS_HEIGHT lines
+	// this is related to TS_WIDTH set in register
+	// NUM_LINE_BYTE3 in budget-core.c. If NUM_LINE_BYTE
+	// low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188
+	//,then RPS_THRESH1
+	// should be set to trigger every TS_HEIGHT (512) lines.
+	//
+	saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 );
+
+	// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
+	// Enable RPS1                                                  (rFC p33)
+	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
 
 	dev->ext_priv = budget;
 
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 4ac0f4d..ecea3a1 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -58,7 +58,13 @@
 	int ci_present;
 	int video_port;
 
-	u8 tsf;
+	u32 buffer_width;
+	u32 buffer_height;
+	u32 buffer_size;
+	u32 buffer_warning_threshold;
+	u32 buffer_warnings;
+	unsigned long buffer_warning_time;
+
 	u32 ttbp;
 	int feeding;
 
@@ -79,11 +85,6 @@
 	.ext_priv = &x_var ## _info, \
 	.ext = &budget_extension };
 
-#define TS_WIDTH  (376)
-#define TS_HEIGHT (512)
-#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
-#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
-
 #define BUDGET_TT		   0
 #define BUDGET_TT_HW_DISEQC	   1
 #define BUDGET_PATCH		   3
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f31a198..85888a8 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -300,7 +300,7 @@
 	  camera drivers.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ovcamchip
+	  module will be called ovcamchip.
 
 config VIDEO_M32R_AR
 	tristate "AR devices"
@@ -316,6 +316,13 @@
 	  Say Y here to use the Renesas M64278E-800 camera module,
 	  which supports VGA(640x480 pixcels) size of images.
 
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders and Decoders"
+	depends on VIDEO_DEV
+
 config VIDEO_MSP3400
 	tristate "Micronas MSP34xx audio decoders"
 	depends on VIDEO_DEV && I2C
@@ -323,7 +330,7 @@
 	  Support for the Micronas MSP34xx series of audio decoders.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called msp3400
+	  module will be called msp3400.
 
 config VIDEO_CS53L32A
 	tristate "Cirrus Logic CS53L32A audio ADC"
@@ -333,17 +340,27 @@
 	  stereo A/D converter.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called cs53l32a
+	  module will be called cs53l32a.
 
 config VIDEO_WM8775
-	tristate "Wolfson Microelectronics WM8775 audio ADC"
+	tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
 	depends on VIDEO_DEV && I2C && EXPERIMENTAL
 	---help---
-	  Support for the Wolfson Microelectronics WM8775
-	  high performance stereo A/D Converter.
+	  Support for the Wolfson Microelectronics WM8775 high
+	  performance stereo A/D Converter with a 4 channel input mixer.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called wm8775
+	  module will be called wm8775.
+
+config VIDEO_WM8739
+	tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+	depends on VIDEO_DEV && I2C && EXPERIMENTAL
+	---help---
+	  Support for the Wolfson Microelectronics WM8739
+	  stereo A/D Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm8739.
 
 source "drivers/media/video/cx25840/Kconfig"
 
@@ -354,7 +371,7 @@
 	  Support for the Philips SAA7113/4/5 video decoders.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called saa7115
+	  module will be called saa7115.
 
 config VIDEO_SAA7127
 	tristate "Philips SAA7127/9 digital video encoders"
@@ -363,7 +380,32 @@
 	  Support for the Philips SAA7127/9 digital video encoders.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called saa7127
+	  module will be called saa7127.
+
+config VIDEO_UPD64031A
+	tristate "NEC Electronics uPD64031A Ghost Reduction"
+	depends on VIDEO_DEV && I2C && EXPERIMENTAL
+	---help---
+	  Support for the NEC Electronics uPD64031A Ghost Reduction
+	  video chip. It is most often found in NTSC TV cards made for
+	  Japan and is used to reduce the 'ghosting' effect that can
+	  be present in analog TV broadcasts.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called upd64031a.
+
+config VIDEO_UPD64083
+	tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+	depends on VIDEO_DEV && I2C && EXPERIMENTAL
+	---help---
+	  Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+	  separation video chip. It is used to improve the quality of
+	  the colors of a composite signal.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called upd64083.
+
+endmenu # encoder / decoder chips
 
 #
 # USB Multimedia device configuration
@@ -374,20 +416,6 @@
 
 source "drivers/media/video/em28xx/Kconfig"
 
-config USB_VICAM
-	tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
-	depends on USB && VIDEO_DEV && EXPERIMENTAL
-	---help---
-	  Say Y here if you have 3com homeconnect camera (vicam).
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Multimedia Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vicam.
-
 config USB_DSBR
 	tristate "D-Link USB FM radio support (EXPERIMENTAL)"
 	depends on USB && VIDEO_DEV && EXPERIMENTAL
@@ -397,79 +425,20 @@
 	  you must connect the line out connector to a sound card or a
 	  set of speakers.
 
-	  This driver uses the Video For Linux API.  You must enable
-	  (Y or M in config) Video For Linux (under Character Devices)
-	  to use this driver.  Information on this API and pointers to
-	  "v4l" programs may be found at
-	  <file:Documentation/video4linux/API.html>.
-
 	  To compile this driver as a module, choose M here: the
 	  module will be called dsbr100.
 
-config USB_ET61X251
-	tristate "USB ET61X[12]51 PC Camera Controller support"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y here if you want support for cameras based on Etoms ET61X151
-	  or ET61X251 PC Camera Controllers.
+source "drivers/media/video/usbvideo/Kconfig"
 
-	  See <file:Documentation/usb/et61x251.txt> for more informations.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" to use this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called et61x251.
-
-config USB_IBMCAM
-	tristate "USB IBM (Xirlink) C-it Camera support"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y here if you want to connect a IBM "C-It" camera, also known as
-	  "Xirlink PC Camera" to your computer's USB port.  For more
-	  information, read <file:Documentation/usb/ibmcam.txt>.
-
-	  This driver uses the Video For Linux API.  You must enable
-	  (Y or M in config) Video For Linux (under Character Devices)
-	  to use this driver.  Information on this API and pointers to
-	  "v4l" programs may be found at
-	  <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ibmcam.
-
-	  This camera has several configuration options which
-	  can be specified when you load the module. Read
-	  <file:Documentation/usb/ibmcam.txt> to learn more.
-
-config USB_KONICAWC
-	tristate "USB Konica Webcam support"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y here if you want support for webcams based on a Konica
-	  chipset. This is known to work with the Intel YC76 webcam.
-
-	  This driver uses the Video For Linux API.  You must enable
-	  (Y or M in config) Video For Linux (under Character Devices)
-	  to use this driver.  Information on this API and pointers to
-	  "v4l" programs may be found at
-	  <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called konicawc.
+source "drivers/media/video/et61x251/Kconfig"
 
 config USB_OV511
 	tristate "USB OV511 Camera support"
 	depends on USB && VIDEO_DEV
 	---help---
 	  Say Y here if you want to connect this type of camera to your
-	  computer's USB port. See <file:Documentation/usb/ov511.txt> for more
-	  information and for a list of supported cameras.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Character Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
+	  computer's USB port. See <file:Documentation/video4linux/ov511.txt>
+	  for more information and for a list of supported cameras.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ov511.
@@ -479,31 +448,13 @@
 	depends on USB && VIDEO_DEV
 	---help---
 	  Say Y here if you want to connect this type of camera to your
-	  computer's USB port. See <file:Documentation/usb/se401.txt> for more
-	  information and for a list of supported cameras.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Multimedia Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
+	  computer's USB port. See <file:Documentation/video4linux/se401.txt>
+	  for more information and for a list of supported cameras.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called se401.
 
-config USB_SN9C102
-	tristate "USB SN9C10x PC Camera Controller support"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y here if you want support for cameras based on SONiX SN9C101,
-	  SN9C102 or SN9C103 PC Camera Controllers.
-
-	  See <file:Documentation/usb/sn9c102.txt> for more informations.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" to use this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sn9c102.
+source "drivers/media/video/sn9c102/Kconfig"
 
 config USB_STV680
 	tristate "USB STV680 (Pencam) Camera support"
@@ -511,20 +462,16 @@
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port. This includes the Pencam line of cameras.
-	  See <file:Documentation/usb/stv680.txt> for more information and for
-	  a list of supported cameras.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Multimedia Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
+	  See <file:Documentation/video4linux/stv680.txt> for more information
+	  and for a list of supported cameras.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called stv680.
 
 config USB_W9968CF
 	tristate "USB W996[87]CF JPEG Dual Mode Camera support"
-	depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP
+	depends on USB && VIDEO_DEV && I2C
+	select VIDEO_OVCAMCHIP
 	---help---
 	  Say Y here if you want support for cameras based on OV681 or
 	  Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
@@ -534,64 +481,14 @@
 	  resolutions and framerates, but cannot be included in the official
 	  Linux kernel for performance purposes.
 
-	  See <file:Documentation/usb/w9968cf.txt> for more informations.
-
-	  This driver uses the Video For Linux and the I2C APIs. It needs the
-	  OmniVision Camera Chip support as well. You must say Y or M to
-	  "Video For Linux", "I2C Support" and "OmniVision Camera Chip
-	  support" to use this driver.
+	  See <file:Documentation/video4linux/w9968cf.txt> for more info.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called w9968cf.
 
-config USB_ZC0301
-	tristate "USB ZC0301 Image Processor and Control Chip support"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y here if you want support for cameras based on the ZC0301
-	  Image Processor and Control Chip.
+source "drivers/media/video/zc0301/Kconfig"
 
-	  See <file:Documentation/usb/zc0301.txt> for more informations.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" to use this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called zc0301.
-
-config USB_PWC
-	tristate "USB Philips Cameras"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y or M here if you want to use one of these Philips & OEM
-	  webcams:
-	   * Philips PCA645, PCA646
-	   * Philips PCVC675, PCVC680, PCVC690
-	   * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
-	   * Askey VC010
-	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
-	     and 'Orbit'/'Sphere'
-	   * Samsung MPC-C10, MPC-C30
-	   * Creative Webcam 5, Pro Ex
-	   * SOTEC Afina Eye
-	   * Visionite VCS-UC300, VCS-UM100
-
-	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
-	  and never will be, but the 665 and 720/20 are supported by other
-	  drivers.
-
-	  See <file:Documentation/usb/philips.txt> for more information and
-	  installation instructions.
-
-	  The built-in microphone is enabled by selecting USB Audio support.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Character Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pwc.
+source "drivers/media/video/pwc/Kconfig"
 
 endmenu # V4L USB devices
 
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 1c0e72e..b3ea2d6 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -45,6 +45,7 @@
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
 obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o
@@ -64,9 +65,8 @@
 obj-$(CONFIG_VIDEO_CX25840) += cx25840/
 obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
-
-et61x251-objs   := et61x251_core.o et61x251_tas5130d1b.o
-zc0301-objs     := zc0301_core.o zc0301_pas202bcb.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
 obj-$(CONFIG_USB_DSBR)          += dsbr100.o
@@ -84,4 +84,4 @@
 obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
 obj-$(CONFIG_USB_VICAM)         += usbvideo/
 
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
index 94350f2..db641a3 100644
--- a/drivers/media/video/bt8xx/Makefile
+++ b/drivers/media/video/bt8xx/Makefile
@@ -9,4 +9,4 @@
 obj-$(CONFIG_VIDEO_BT848) += bttv.o
 
 EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 74def9c..423e954 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -973,12 +973,12 @@
 		   For now this is sufficient. */
 		switch (input) {
 		case TVAUDIO_INPUT_RADIO:
-			route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
-				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+			route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
 			break;
 		case TVAUDIO_INPUT_EXTERN:
-			route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
-				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+			route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
 			break;
 		case TVAUDIO_INPUT_INTERN:
 			/* Yes, this is the same input as for RADIO. I doubt
@@ -986,8 +986,8 @@
 			   input is the BTTV_BOARD_AVERMEDIA98. I wonder how
 			   that was tested. My guess is that the whole INTERN
 			   input does not work. */
-			route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1,
-				    MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART);
+			route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
 			break;
 		case TVAUDIO_INPUT_TUNER:
 		default:
@@ -1023,14 +1023,11 @@
 static void
 i2c_vidiocschan(struct bttv *btv)
 {
-	struct video_channel c;
+	v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
 
-	memset(&c,0,sizeof(c));
-	c.norm    = btv->tvnorm;
-	c.channel = btv->input;
-	bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c);
+	bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
 	if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
-		bttv_tda9880_setnorm(btv,c.norm);
+		bttv_tda9880_setnorm(btv,btv->tvnorm);
 }
 
 static int
@@ -1184,11 +1181,27 @@
 			break;
 	if (i == BTTV_CTLS)
 		return -EINVAL;
-	if (i >= 4 && i <= 8) {
+	if (btv->audio_hook && i >= 4 && i <= 8) {
 		memset(&va,0,sizeof(va));
-		bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
-		if (btv->audio_hook)
-			btv->audio_hook(btv,&va,0);
+		btv->audio_hook(btv,&va,0);
+		switch (c->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
+			break;
+		case V4L2_CID_AUDIO_VOLUME:
+			c->value = va.volume;
+			break;
+		case V4L2_CID_AUDIO_BALANCE:
+			c->value = va.balance;
+			break;
+		case V4L2_CID_AUDIO_BASS:
+			c->value = va.bass;
+			break;
+		case V4L2_CID_AUDIO_TREBLE:
+			c->value = va.treble;
+			break;
+		}
+		return 0;
 	}
 	switch (c->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -1205,19 +1218,11 @@
 		break;
 
 	case V4L2_CID_AUDIO_MUTE:
-		c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0;
-		break;
 	case V4L2_CID_AUDIO_VOLUME:
-		c->value = va.volume;
-		break;
 	case V4L2_CID_AUDIO_BALANCE:
-		c->value = va.balance;
-		break;
 	case V4L2_CID_AUDIO_BASS:
-		c->value = va.bass;
-		break;
 	case V4L2_CID_AUDIO_TREBLE:
-		c->value = va.treble;
+		bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
 		break;
 
 	case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1269,11 +1274,35 @@
 			break;
 	if (i == BTTV_CTLS)
 		return -EINVAL;
-	if (i >= 4 && i <= 8) {
+	if (btv->audio_hook && i >= 4 && i <= 8) {
 		memset(&va,0,sizeof(va));
-		bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
-		if (btv->audio_hook)
-			btv->audio_hook(btv,&va,0);
+		btv->audio_hook(btv,&va,0);
+		switch (c->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			if (c->value) {
+				va.flags |= VIDEO_AUDIO_MUTE;
+				audio_mute(btv, 1);
+			} else {
+				va.flags &= ~VIDEO_AUDIO_MUTE;
+				audio_mute(btv, 0);
+			}
+			break;
+
+		case V4L2_CID_AUDIO_VOLUME:
+			va.volume = c->value;
+			break;
+		case V4L2_CID_AUDIO_BALANCE:
+			va.balance = c->value;
+			break;
+		case V4L2_CID_AUDIO_BASS:
+			va.bass = c->value;
+			break;
+		case V4L2_CID_AUDIO_TREBLE:
+			va.treble = c->value;
+			break;
+		}
+		btv->audio_hook(btv,&va,1);
+		return 0;
 	}
 	switch (c->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -1289,26 +1318,13 @@
 		bt848_sat(btv,c->value);
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		if (c->value) {
-			va.flags |= VIDEO_AUDIO_MUTE;
-			audio_mute(btv, 1);
-		} else {
-			va.flags &= ~VIDEO_AUDIO_MUTE;
-			audio_mute(btv, 0);
-		}
-		break;
-
+		audio_mute(btv, c->value);
+		/* fall through */
 	case V4L2_CID_AUDIO_VOLUME:
-		va.volume = c->value;
-		break;
 	case V4L2_CID_AUDIO_BALANCE:
-		va.balance = c->value;
-		break;
 	case V4L2_CID_AUDIO_BASS:
-		va.bass = c->value;
-		break;
 	case V4L2_CID_AUDIO_TREBLE:
-		va.treble = c->value;
+		bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
 		break;
 
 	case V4L2_CID_PRIVATE_CHROMA_AGC:
@@ -1364,11 +1380,6 @@
 	default:
 		return -EINVAL;
 	}
-	if (i >= 4 && i <= 8) {
-		bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
-		if (btv->audio_hook)
-			btv->audio_hook(btv,&va,1);
-	}
 	return 0;
 }
 
@@ -1591,12 +1602,16 @@
 	}
 	case VIDIOCSFREQ:
 	{
-		unsigned long *freq = arg;
+		struct v4l2_frequency freq;
+
+		memset(&freq, 0, sizeof(freq));
+		freq.frequency = *(unsigned long *)arg;
 		mutex_lock(&btv->lock);
-		btv->freq=*freq;
-		bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
+		freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+		btv->freq = *(unsigned long *)arg;
+		bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq);
 		if (btv->has_matchbox && btv->radio_user)
-			tea5757_set_freq(btv,*freq);
+			tea5757_set_freq(btv,*(unsigned long *)arg);
 		mutex_unlock(&btv->lock);
 		return 0;
 	}
@@ -1827,33 +1842,26 @@
 			return -EINVAL;
 		mutex_lock(&btv->lock);
 		memset(t,0,sizeof(*t));
-		strcpy(t->name, "Television");
-		t->type       = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM;
 		t->rxsubchans = V4L2_TUNER_SUB_MONO;
+		bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+		strcpy(t->name, "Television");
+		t->capability = V4L2_TUNER_CAP_NORM;
+		t->type       = V4L2_TUNER_ANALOG_TV;
 		if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
 			t->signal = 0xffff;
-		{
-			struct video_tuner tuner;
 
-			memset(&tuner, 0, sizeof (tuner));
-			tuner.rangehigh = 0xffffffffUL;
-			bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner);
-			t->rangelow = tuner.rangelow;
-			t->rangehigh = tuner.rangehigh;
-		}
-		{
+		if (btv->audio_hook) {
 			/* Hmmm ... */
 			struct video_audio va;
 			memset(&va, 0, sizeof(struct video_audio));
-			bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
-			if (btv->audio_hook)
-				btv->audio_hook(btv,&va,0);
+			btv->audio_hook(btv,&va,0);
+			t->audmode    = V4L2_TUNER_MODE_MONO;
+			t->rxsubchans = V4L2_TUNER_SUB_MONO;
 			if(va.mode & VIDEO_SOUND_STEREO) {
-				t->audmode     = V4L2_TUNER_MODE_STEREO;
-				t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+				t->audmode    = V4L2_TUNER_MODE_STEREO;
+				t->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			}
-			if(va.mode & VIDEO_SOUND_LANG1) {
+			if(va.mode & VIDEO_SOUND_LANG2) {
 				t->audmode    = V4L2_TUNER_MODE_LANG1;
 				t->rxsubchans = V4L2_TUNER_SUB_LANG1
 					| V4L2_TUNER_SUB_LANG2;
@@ -1872,10 +1880,10 @@
 		if (0 != t->index)
 			return -EINVAL;
 		mutex_lock(&btv->lock);
-		{
+		bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+		if (btv->audio_hook) {
 			struct video_audio va;
 			memset(&va, 0, sizeof(struct video_audio));
-			bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
 			if (t->audmode == V4L2_TUNER_MODE_MONO)
 				va.mode = VIDEO_SOUND_MONO;
 			else if (t->audmode == V4L2_TUNER_MODE_STEREO ||
@@ -1885,9 +1893,7 @@
 				va.mode = VIDEO_SOUND_LANG1;
 			else if (t->audmode == V4L2_TUNER_MODE_LANG2)
 				va.mode = VIDEO_SOUND_LANG2;
-			bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va);
-			if (btv->audio_hook)
-				btv->audio_hook(btv,&va,1);
+			btv->audio_hook(btv,&va,1);
 		}
 		mutex_unlock(&btv->lock);
 		return 0;
@@ -1912,7 +1918,7 @@
 			return -EINVAL;
 		mutex_lock(&btv->lock);
 		btv->freq = f->frequency;
-		bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
+		bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f);
 		if (btv->has_matchbox && btv->radio_user)
 			tea5757_set_freq(btv,btv->freq);
 		mutex_unlock(&btv->lock);
@@ -1920,7 +1926,9 @@
 	}
 	case VIDIOC_LOG_STATUS:
 	{
+		printk(KERN_INFO "bttv%d: =================  START STATUS CARD #%d  =================\n", btv->c.nr, btv->c.nr);
 		bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+		printk(KERN_INFO "bttv%d: ==================  END STATUS CARD #%d  ==================\n", btv->c.nr, btv->c.nr);
 		return 0;
 	}
 
@@ -2870,12 +2878,10 @@
 			return 0;
 		}
 		*c = bttv_ctls[i];
-		if (i >= 4 && i <= 8) {
+		if (btv->audio_hook && i >= 4 && i <= 8) {
 			struct video_audio va;
 			memset(&va,0,sizeof(va));
-			bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);
-			if (btv->audio_hook)
-				btv->audio_hook(btv,&va,0);
+			btv->audio_hook(btv,&va,0);
 			switch (bttv_ctls[i].id) {
 			case V4L2_CID_AUDIO_VOLUME:
 				if (!(va.flags & VIDEO_AUDIO_VOLUME))
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index e20ff23..8c9f0f7 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -184,7 +184,7 @@
 		- tvnorm->vbistart[0];
 	count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
 		- tvnorm->vbistart[1];
-	count  = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
+	count  = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES);
 
 	f->fmt.vbi.start[0] = tvnorm->vbistart[0];
 	f->fmt.vbi.start[1] = tvnorm->vbistart[1];
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 2227c56..85d84e8 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -64,14 +64,13 @@
 MODULE_SUPPORTED_DEVICE("video");
 #endif
 
-static unsigned short colorspace_conv = 0;
+static unsigned short colorspace_conv;
 module_param(colorspace_conv, ushort, 0444);
 MODULE_PARM_DESC(colorspace_conv,
-		 "\n<n> Colorspace conversion:"
-		 "\n0 = disable"
-		 "\n1 = enable"
-		 "\nDefault value is 0"
-		 "\n");
+                 " Colorspace conversion:"
+                 "\n  0 = disable, 1 = enable"
+                 "\n  Default value is 0"
+                 );
 
 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
 
@@ -4042,7 +4041,7 @@
 	       "allowed, it is disabled by default now. Users should fix the "
 	       "applications in case they don't work without conversion "
 	       "reenabled by setting the 'colorspace_conv' module "
-	       "parameter to 1");
+	       "parameter to 1\n");
 
 #ifdef CONFIG_PROC_FS
 	proc_cpia_create();
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 8394283..1764991 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -456,7 +456,7 @@
 int cpia2_allocate_buffers(struct camera_data *cam);
 void cpia2_free_buffers(struct camera_data *cam);
 long cpia2_read(struct camera_data *cam,
-		char *buf, unsigned long count, int noblock);
+		char __user *buf, unsigned long count, int noblock);
 unsigned int cpia2_poll(struct camera_data *cam,
 			struct file *filp, poll_table *wait);
 int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile
index 32a896c..6e8665b 100644
--- a/drivers/media/video/cx25840/Makefile
+++ b/drivers/media/video/cx25840/Makefile
@@ -3,4 +3,4 @@
 
 obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
 
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index a4540e8..9a4b813 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -19,8 +19,9 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-common.h>
+#include <media/cx25840.h>
 
-#include "cx25840.h"
+#include "cx25840-core.h"
 
 static int set_audclk_freq(struct i2c_client *client, u32 freq)
 {
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index a65b3cc..a961bb2 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -32,8 +32,9 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-common.h>
+#include <media/cx25840.h>
 
-#include "cx25840.h"
+#include "cx25840-core.h"
 
 MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
 MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
@@ -668,6 +669,7 @@
 {
 	struct cx25840_state *state = i2c_get_clientdata(client);
 	struct v4l2_tuner *vt = arg;
+	struct v4l2_routing *route = arg;
 
 	switch (cmd) {
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -749,19 +751,21 @@
 		state->radio = 1;
 		break;
 
-	case VIDIOC_G_INPUT:
-		*(int *)arg = state->vid_input;
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+		route->input = state->vid_input;
+		route->output = 0;
 		break;
 
-	case VIDIOC_S_INPUT:
-		return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+		return set_input(client, route->input, state->aud_input);
 
-	case VIDIOC_S_AUDIO:
-	{
-		struct v4l2_audio *input = arg;
+	case VIDIOC_INT_G_AUDIO_ROUTING:
+		route->input = state->aud_input;
+		route->output = 0;
+		break;
 
-		return set_input(client, state->vid_input, input->index);
-	}
+	case VIDIOC_INT_S_AUDIO_ROUTING:
+		return set_input(client, state->vid_input, route->input);
 
 	case VIDIOC_S_FREQUENCY:
 		input_change(client);
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840-core.h
similarity index 72%
rename from drivers/media/video/cx25840/cx25840.h
rename to drivers/media/video/cx25840/cx25840-core.h
index dd70664..1736929 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -1,4 +1,4 @@
-/* cx25840 API header
+/* cx25840 internal API header
  *
  * Copyright (C) 2003-2004 Chris Kennedy
  *
@@ -17,8 +17,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#ifndef _CX25840_H_
-#define _CX25840_H_
+#ifndef _CX25840_CORE_H_
+#define _CX25840_CORE_H_
 
 
 #include <linux/videodev2.h>
@@ -32,46 +32,6 @@
    providing this information. */
 #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
 
-enum cx25840_video_input {
-	/* Composite video inputs In1-In8 */
-	CX25840_COMPOSITE1 = 1,
-	CX25840_COMPOSITE2,
-	CX25840_COMPOSITE3,
-	CX25840_COMPOSITE4,
-	CX25840_COMPOSITE5,
-	CX25840_COMPOSITE6,
-	CX25840_COMPOSITE7,
-	CX25840_COMPOSITE8,
-
-	/* S-Video inputs consist of one luma input (In1-In4) ORed with one
-	   chroma input (In5-In8) */
-	CX25840_SVIDEO_LUMA1 = 0x10,
-	CX25840_SVIDEO_LUMA2 = 0x20,
-	CX25840_SVIDEO_LUMA3 = 0x30,
-	CX25840_SVIDEO_LUMA4 = 0x40,
-	CX25840_SVIDEO_CHROMA4 = 0x400,
-	CX25840_SVIDEO_CHROMA5 = 0x500,
-	CX25840_SVIDEO_CHROMA6 = 0x600,
-	CX25840_SVIDEO_CHROMA7 = 0x700,
-	CX25840_SVIDEO_CHROMA8 = 0x800,
-
-	/* S-Video aliases for common luma/chroma combinations */
-	CX25840_SVIDEO1 = 0x510,
-	CX25840_SVIDEO2 = 0x620,
-	CX25840_SVIDEO3 = 0x730,
-	CX25840_SVIDEO4 = 0x840,
-};
-
-enum cx25840_audio_input {
-	/* Audio inputs: serial or In4-In8 */
-	CX25840_AUDIO_SERIAL,
-	CX25840_AUDIO4 = 4,
-	CX25840_AUDIO5,
-	CX25840_AUDIO6,
-	CX25840_AUDIO7,
-	CX25840_AUDIO8,
-};
-
 struct cx25840_state {
 	int pvr150_workaround;
 	int radio;
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index e1a7823..f59ced1 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -20,11 +20,22 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/firmware.h>
 #include <media/v4l2-common.h>
+#include <media/cx25840.h>
 
-#include "cx25840.h"
+#include "cx25840-core.h"
 
 #define FWFILE "v4l-cx25840.fw"
-#define FWSEND 1024
+
+/*
+ * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the
+ * size of the firmware chunks sent down the I2C bus to the chip.
+ * Previously this had been set to 1024 but unfortunately some I2C
+ * implementations can't transfer data in such big gulps.
+ * Specifically, the pvrusb2 driver has a hard limit of around 60
+ * bytes, due to the encapsulation there of I2C traffic into USB
+ * messages.  So we have to significantly reduce this parameter.
+ */
+#define FWSEND 48
 
 #define FWDEV(x) &((x)->adapter->dev)
 
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index e96fd1f..57feca2 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -19,8 +19,9 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 #include <media/v4l2-common.h>
+#include <media/cx25840.h>
 
-#include "cx25840.h"
+#include "cx25840-core.h"
 
 static int odd_parity(u8 c)
 {
@@ -151,7 +152,7 @@
 	case VIDIOC_G_FMT:
 	{
 		static u16 lcr2vbi[] = {
-			0, V4L2_SLICED_TELETEXT_PAL_B, 0,	/* 1 */
+			0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
 			0, V4L2_SLICED_WSS_625, 0,	/* 4 */
 			V4L2_SLICED_CAPTION_525,	/* 6 */
 			0, 0, V4L2_SLICED_VPS, 0, 0,	/* 9 */
@@ -231,7 +232,7 @@
 		for (i = 7; i <= 23; i++) {
 			for (x = 0; x <= 1; x++) {
 				switch (svbi->service_lines[1-x][i]) {
-				case V4L2_SLICED_TELETEXT_PAL_B:
+				case V4L2_SLICED_TELETEXT_B:
 					lcr[i] |= 1 << (4 * x);
 					break;
 				case V4L2_SLICED_WSS_625:
@@ -282,7 +283,7 @@
 
 		switch (id2) {
 		case 1:
-			id2 = V4L2_SLICED_TELETEXT_PAL_B;
+			id2 = V4L2_SLICED_TELETEXT_B;
 			break;
 		case 4:
 			id2 = V4L2_SLICED_WSS_625;
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index ff0f723..6302739 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -1,3 +1,7 @@
+config VIDEO_CX88_VP3054
+	tristate
+	depends on VIDEO_CX88_DVB && DVB_MT352
+
 config VIDEO_CX88
 	tristate "Conexant 2388x (bt878 successor) support"
 	depends on VIDEO_DEV && PCI && I2C
@@ -25,7 +29,7 @@
 
 	  It only works with boards with function 01 enabled.
 	  To check if your board supports, use lspci -n.
-	  If supported, you should see 1471:8801 or 1471:8811
+	  If supported, you should see 14f1:8801 or 14f1:8811
 	  PCI device.
 
 	  To compile this driver as a module, choose M here: the
@@ -73,10 +77,11 @@
 	  This adds DVB-T support for cards based on the
 	  Connexant 2388x chip and the MT352 demodulator.
 
-config VIDEO_CX88_VP3054
-	tristate "VP-3054 Secondary I2C Bus Support"
-	default m
-	depends on DVB_MT352
+config VIDEO_CX88_DVB_VP3054
+	bool "VP-3054 Secondary I2C Bus Support"
+	default y
+	depends on VIDEO_CX88_DVB_MT352
+	select VIDEO_CX88_VP3054
 	---help---
 	  This adds DVB-T support for cards based on the
 	  Connexant 2388x chip and the MT352 demodulator,
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6482b9a..0dcd09b 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -8,9 +8,9 @@
 obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
 extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
 extra-cflags-$(CONFIG_DVB_CX22702)   += -DHAVE_CX22702=1
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
index da457a0..826d0e3 100644
--- a/drivers/media/video/em28xx/Makefile
+++ b/drivers/media/video/em28xx/Makefile
@@ -3,4 +3,4 @@
 
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
 
-EXTRA_CFLAGS += -I$(src)/..
+EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index f62fd706b..3ba3439 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -151,8 +151,8 @@
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = 2,
-			.amux     = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1,
-					MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART),
+			.amux     = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+					MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
 		}},
 	},
 	[EM2820_BOARD_MSI_VOX_USB_2] = {
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index dfba33d..ddc92cb 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -222,7 +222,7 @@
 		if (dev->i2s_speed)
 			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
 		route.input = dev->ctl_ainput;
-		route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA);
+		route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
 		/* Note: this is msp3400 specific */
 		em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route);
 		ainput = EM28XX_AUDIO_SRC_TUNER;
@@ -1141,26 +1141,16 @@
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *t = arg;
-		int status = 0;
 
 		if (0 != t->index)
 			return -EINVAL;
 
 		memset(t, 0, sizeof(*t));
 		strcpy(t->name, "Tuner");
-		t->type = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM;
-		t->rangehigh = 0xffffffffUL;	/* FIXME: set correct range */
-/*		t->signal = 0xffff;*/
-/*		em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/
-		/* No way to get signal strength? */
 		mutex_lock(&dev->lock);
-		em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
-					&status);
+		/* let clients fill in the remainder of this struct */
+		em28xx_i2c_call_clients(dev, cmd, t);
 		mutex_unlock(&dev->lock);
-		t->signal =
-			(status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
 		em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal,
 				t->afc);
 		return 0;
@@ -1168,26 +1158,13 @@
 	case VIDIOC_S_TUNER:
 	{
 		struct v4l2_tuner *t = arg;
-		int status = 0;
 
 		if (0 != t->index)
 			return -EINVAL;
-		memset(t, 0, sizeof(*t));
-		strcpy(t->name, "Tuner");
-		t->type = V4L2_TUNER_ANALOG_TV;
-		t->capability = V4L2_TUNER_CAP_NORM;
-		t->rangehigh = 0xffffffffUL;	/* FIXME: set correct range */
-/*		t->signal = 0xffff; */
-		/* No way to get signal strength? */
 		mutex_lock(&dev->lock);
-		em28xx_i2c_call_clients(dev, DECODER_GET_STATUS,
-					&status);
+		/* let clients handle this */
+		em28xx_i2c_call_clients(dev, cmd, t);
 		mutex_unlock(&dev->lock);
-		t->signal =
-			(status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0;
-
-		em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n",
-				t->signal, t->afc);
 		return 0;
 	}
 	case VIDIOC_G_FREQUENCY:
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig
new file mode 100644
index 0000000..6c43a90
--- /dev/null
+++ b/drivers/media/video/et61x251/Kconfig
@@ -0,0 +1,14 @@
+config USB_ET61X251
+	tristate "USB ET61X[12]51 PC Camera Controller support"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y here if you want support for cameras based on Etoms ET61X151
+	  or ET61X251 PC Camera Controllers.
+
+	  See <file:Documentation/video4linux/et61x251.txt> for more info.
+
+	  This driver uses the Video For Linux API. You must say Y or M to
+	  "Video For Linux" to use this driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called et61x251.
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 95bacf4..7e66d83 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -411,6 +411,9 @@
 	case I2C_HW_B_BT848:
 		probe = probe_bttv;
 		break;
+	case I2C_HW_B_CX2341X:
+		probe = probe_bttv;
+		break;
 	case I2C_HW_SAA7134:
 		probe = probe_saa7134;
 		break;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index c40e8ba..b806999 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -279,20 +279,8 @@
 	msp_write_dsp(client, 0x13, state->acb);
 
 	/* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
-	msp_write_dem(client, 0x40, state->i2s_mode);
-}
-
-void msp_set_mute(struct i2c_client *client)
-{
-	struct msp_state *state = i2c_get_clientdata(client);
-
-	v4l_dbg(1, msp_debug, client, "mute audio\n");
-	msp_write_dsp(client, 0x0000, 0);
-	msp_write_dsp(client, 0x0007, 1);
-	if (state->has_scart2_out_volume)
-		msp_write_dsp(client, 0x0040, 1);
-	if (state->has_headphones)
-		msp_write_dsp(client, 0x0006, 0);
+	if (state->has_i2s_conf)
+		msp_write_dem(client, 0x40, state->i2s_mode);
 }
 
 void msp_set_audio(struct i2c_client *client)
@@ -300,17 +288,19 @@
 	struct msp_state *state = i2c_get_clientdata(client);
 	int bal = 0, bass, treble, loudness;
 	int val = 0;
+	int reallymuted = state->muted | state->scan_in_progress;
 
-	if (!state->muted)
+	if (!reallymuted)
 		val = (state->volume * 0x7f / 65535) << 8;
 
-	v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
-		state->muted ? "on" : "off", state->volume);
+	v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
+		state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no",
+		state->volume);
 
 	msp_write_dsp(client, 0x0000, val);
-	msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
+	msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
 	if (state->has_scart2_out_volume)
-		msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
+		msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
 	if (state->has_headphones)
 		msp_write_dsp(client, 0x0006, val);
 	if (!state->has_sound_processing)
@@ -346,7 +336,6 @@
 
 	if (NULL == state->kthread)
 		return;
-	msp_set_mute(client);
 	state->watch_stereo = 0;
 	state->restart = 1;
 	wake_up_interruptible(&state->wq);
@@ -374,19 +363,15 @@
 
 /* ------------------------------------------------------------------------ */
 
-static int msp_mode_v4l2_to_v4l1(int rxsubchans)
+static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
 {
-	int mode = 0;
-
-	if (rxsubchans & V4L2_TUNER_SUB_STEREO)
-		mode |= VIDEO_SOUND_STEREO;
-	if (rxsubchans & V4L2_TUNER_SUB_LANG2)
-		mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO;
-	if (rxsubchans & V4L2_TUNER_SUB_LANG1)
-		mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO;
-	if (mode == 0)
-		mode |= VIDEO_SOUND_MONO;
-	return mode;
+	if (rxsubchans == V4L2_TUNER_SUB_MONO)
+		return VIDEO_SOUND_MONO;
+	if (rxsubchans == V4L2_TUNER_SUB_STEREO)
+		return VIDEO_SOUND_STEREO;
+	if (audmode == V4L2_TUNER_MODE_LANG2)
+		return VIDEO_SOUND_LANG2;
+	return VIDEO_SOUND_LANG1;
 }
 
 static int msp_mode_v4l1_to_v4l2(int mode)
@@ -605,7 +590,7 @@
 			break;
 		if (state->opmode == OPMODE_AUTOSELECT)
 			msp_detect_stereo(client);
-		va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
+		va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode);
 		break;
 	}
 
@@ -620,7 +605,8 @@
 		state->treble = va->treble;
 		msp_set_audio(client);
 
-		if (va->mode != 0 && state->radio == 0) {
+		if (va->mode != 0 && state->radio == 0 &&
+		    state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) {
 			state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
 			msp_set_audmode(client);
 		}
@@ -687,21 +673,23 @@
 		int sc_in = rt->input & 0x7;
 		int sc1_out = rt->output & 0xf;
 		int sc2_out = (rt->output >> 4) & 0xf;
-		u16 val;
+		u16 val, reg;
 
+		if (state->routing.input == rt->input &&
+		    state->routing.output == rt->output)
+			break;
 		state->routing = *rt;
-		if (state->opmode == OPMODE_AUTOSELECT) {
-			val = msp_read_dem(client, 0x30) & ~0x100;
-			msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
-		} else {
-			val = msp_read_dem(client, 0xbb) & ~0x100;
-			msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
-		}
 		msp_set_scart(client, sc_in, 0);
 		msp_set_scart(client, sc1_out, 1);
 		msp_set_scart(client, sc2_out, 2);
 		msp_set_audmode(client);
-		msp_wake_thread(client);
+		reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
+		val = msp_read_dem(client, reg);
+		if (tuner != ((val >> 8) & 1)) {
+			msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+			/* wake thread when a new tuner input is chosen */
+			msp_wake_thread(client);
+		}
 		break;
 	}
 
@@ -715,7 +703,7 @@
 			msp_detect_stereo(client);
 		vt->audmode    = state->audmode;
 		vt->rxsubchans = state->rxsubchans;
-		vt->capability = V4L2_TUNER_CAP_STEREO |
+		vt->capability |= V4L2_TUNER_CAP_STEREO |
 			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
 		break;
 	}
@@ -726,6 +714,8 @@
 
 		if (state->radio)  /* TODO: add mono/stereo support for radio */
 			break;
+		if (state->audmode == vt->audmode)
+			break;
 		state->audmode = vt->audmode;
 		/* only set audmode */
 		msp_set_audmode(client);
@@ -887,7 +877,7 @@
 
 	memset(state, 0, sizeof(*state));
 	state->v4l2_std = V4L2_STD_NTSC;
-	state->audmode = V4L2_TUNER_MODE_LANG1;
+	state->audmode = V4L2_TUNER_MODE_STEREO;
 	state->volume = 58880;	/* 0db gain */
 	state->balance = 32768;	/* 0db gain */
 	state->bass = 32768;
@@ -931,13 +921,16 @@
 	state->has_radio = msp_revision >= 'G';
 	/* Has headphones output: not for stripped down products */
 	state->has_headphones = msp_prod_lo < 5;
+	/* Has scart2 input: not in stripped down products of the '3' family */
+	state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7;
+	/* Has scart3 input: not in stripped down products of the '3' family */
+	state->has_scart3 = msp_family >= 4 || msp_prod_lo < 5;
 	/* Has scart4 input: not in pre D revisions, not in stripped D revs */
 	state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
-	/* Has scart2 and scart3 inputs and scart2 output: not in stripped
-	   down products of the '3' family */
-	state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
+	/* Has scart2 output: not in stripped down products of the '3' family */
+	state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
 	/* Has scart2 a volume control? Not in pre-D revisions. */
-	state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
+	state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out;
 	/* Has a configurable i2s out? */
 	state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7;
 	/* Has subwoofer output: not in pre-D revs and not in stripped down products */
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 1940748..4e45104 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -54,8 +54,10 @@
 	u8 has_radio;
 	u8 has_headphones;
 	u8 has_ntsc_jp_d_k3;
+	u8 has_scart2;
+	u8 has_scart3;
 	u8 has_scart4;
-	u8 has_scart23_in_scart2_out;
+	u8 has_scart2_out;
 	u8 has_scart2_out_volume;
 	u8 has_i2s_conf;
 	u8 has_subwoofer;
@@ -83,6 +85,7 @@
 	int volume, muted;
 	int balance, loudness;
 	int bass, treble;
+	int scan_in_progress;
 
 	/* thread */
 	struct task_struct   *kthread;
@@ -98,7 +101,6 @@
 int msp_read_dsp(struct i2c_client *client, int addr);
 int msp_reset(struct i2c_client *client);
 void msp_set_scart(struct i2c_client *client, int in, int out);
-void msp_set_mute(struct i2c_client *client);
 void msp_set_audio(struct i2c_client *client);
 int msp_sleep(struct msp_state *state, int timeout);
 
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index c3984ea..633a102 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -170,7 +170,7 @@
 	msp_write_dsp(client, 0x000a, src);
 	msp_write_dsp(client, 0x000b, src);
 	msp_write_dsp(client, 0x000c, src);
-	if (state->has_scart23_in_scart2_out)
+	if (state->has_scart2_out)
 		msp_write_dsp(client, 0x0041, src);
 }
 
@@ -228,6 +228,7 @@
 	char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
 		strmode[state->audmode] : "unknown";
 	int src = 0;	/* channel source: FM/AM, nicam or SCART */
+	int audmode = state->audmode;
 
 	if (state->opmode == OPMODE_AUTOSELECT) {
 		/* this method would break everything, let's make sure
@@ -239,11 +240,29 @@
 		return;
 	}
 
+	/* Note: for the C and D revs no NTSC stereo + SAP is possible as
+	   the hardware does not support SAP. So the rxsubchans combination
+	   of STEREO | LANG2 does not occur. */
+
+	/* switch to mono if only mono is available */
+	if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+		audmode = V4L2_TUNER_MODE_MONO;
+	/* if bilingual */
+	else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+		/* and mono or stereo, then fallback to lang1 */
+		if (audmode == V4L2_TUNER_MODE_MONO ||
+		    audmode == V4L2_TUNER_MODE_STEREO)
+			audmode = V4L2_TUNER_MODE_LANG1;
+	}
+	/* if stereo, and audmode is not mono, then switch to stereo */
+	else if (audmode != V4L2_TUNER_MODE_MONO)
+		audmode = V4L2_TUNER_MODE_STEREO;
+
 	/* switch demodulator */
 	switch (state->mode) {
 	case MSP_MODE_FM_TERRA:
 		v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
-		switch (state->audmode) {
+		switch (audmode) {
 		case V4L2_TUNER_MODE_STEREO:
 			msp_write_dsp(client, 0x000e, 0x3001);
 			break;
@@ -257,7 +276,7 @@
 		break;
 	case MSP_MODE_FM_SAT:
 		v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
-		switch (state->audmode) {
+		switch (audmode) {
 		case V4L2_TUNER_MODE_MONO:
 			msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
 			break;
@@ -296,7 +315,8 @@
 	}
 
 	/* switch audio */
-	switch (state->audmode) {
+	v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode);
+	switch (audmode) {
 	case V4L2_TUNER_MODE_STEREO:
 	case V4L2_TUNER_MODE_LANG1_LANG2:
 		src |= 0x0020;
@@ -314,10 +334,6 @@
 			src = 0x0030;
 		break;
 	case V4L2_TUNER_MODE_LANG1:
-		/* switch to stereo for stereo transmission, otherwise
-		   keep first language */
-		if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
-			src |= 0x0020;
 		break;
 	case V4L2_TUNER_MODE_LANG2:
 		src |= 0x0010;
@@ -367,7 +383,7 @@
 		if (val > 32767)
 			val -= 65536;
 		v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
-		if (val > 4096) {
+		if (val > 8192) {
 			rxsubchans = V4L2_TUNER_SUB_STEREO;
 		} else if (val < -4096) {
 			rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
@@ -464,19 +480,22 @@
 		if (state->radio || MSP_MODE_EXTERN == state->mode) {
 			/* no carrier scan, just unmute */
 			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+			state->scan_in_progress = 0;
 			msp_set_audio(client);
 			continue;
 		}
 
-		/* mute */
-		msp_set_mute(client);
+		/* mute audio */
+		state->scan_in_progress = 1;
+		msp_set_audio(client);
+
 		msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
 		val1 = val2 = 0;
 		max1 = max2 = -1;
 		state->watch_stereo = 0;
 		state->nicam_on = 0;
 
-		/* some time for the tuner to sync */
+		/* wait for tuner to settle down after a channel change */
 		if (msp_sleep(state, 200))
 			goto restart;
 
@@ -552,7 +571,6 @@
 				/* B/G NICAM */
 				state->second = msp3400c_carrier_detect_55[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
-				msp3400c_set_carrier(client, state->second, state->main);
 				state->nicam_on = 1;
 				state->watch_stereo = 1;
 			} else {
@@ -563,7 +581,6 @@
 			/* PAL I NICAM */
 			state->second = MSP_CARRIER(6.552);
 			msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
-			msp3400c_set_carrier(client, state->second, state->main);
 			state->nicam_on = 1;
 			state->watch_stereo = 1;
 			break;
@@ -577,13 +594,11 @@
 				/* L NICAM or AM-mono */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
-				msp3400c_set_carrier(client, state->second, state->main);
 				state->watch_stereo = 1;
 			} else if (max2 == 0 && state->has_nicam) {
 				/* D/K NICAM */
 				state->second = msp3400c_carrier_detect_65[max2].cdo;
 				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
-				msp3400c_set_carrier(client, state->second, state->main);
 				state->nicam_on = 1;
 				state->watch_stereo = 1;
 			} else {
@@ -595,25 +610,25 @@
 		no_second:
 			state->second = msp3400c_carrier_detect_main[max1].cdo;
 			msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
-			msp3400c_set_carrier(client, state->second, state->main);
-			state->rxsubchans = V4L2_TUNER_SUB_MONO;
 			break;
 		}
+		msp3400c_set_carrier(client, state->second, state->main);
 
 		/* unmute */
-		msp_set_audio(client);
+		state->scan_in_progress = 0;
 		msp3400c_set_audmode(client);
+		msp_set_audio(client);
 
 		if (msp_debug)
 			msp3400c_print_mode(client);
 
 		/* monitor tv audio mode, the first time don't wait
 		   so long to get a quick stereo/bilingual result */
-		if (msp_sleep(state, 1000))
-			goto restart;
+		count = 3;
 		while (state->watch_stereo) {
-			if (msp_sleep(state, 5000))
+			if (msp_sleep(state, count ? 1000 : 5000))
 				goto restart;
+			if (count) count--;
 			watch_stereo(client);
 		}
 	}
@@ -626,7 +641,7 @@
 {
 	struct i2c_client *client = data;
 	struct msp_state *state = i2c_get_clientdata(client);
-	int val, i, std;
+	int val, i, std, count;
 
 	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
 
@@ -644,16 +659,14 @@
 		if (state->mode == MSP_MODE_EXTERN) {
 			/* no carrier scan needed, just unmute */
 			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+			state->scan_in_progress = 0;
 			msp_set_audio(client);
 			continue;
 		}
 
-		/* put into sane state (and mute) */
-		msp_reset(client);
-
-		/* some time for the tuner to sync */
-		if (msp_sleep(state,200))
-			goto restart;
+		/* mute audio */
+		state->scan_in_progress = 1;
+		msp_set_audio(client);
 
 		/* start autodetect. Note: autodetect is not supported for
 		   NTSC-M and radio, hence we force the standard in those cases. */
@@ -664,6 +677,10 @@
 		state->watch_stereo = 0;
 		state->nicam_on = 0;
 
+		/* wait for tuner to settle down after a channel change */
+		if (msp_sleep(state, 200))
+			goto restart;
+
 		if (msp_debug)
 			v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n",
 			       msp_standard_std_name(std), std);
@@ -693,6 +710,7 @@
 		state->main   = msp_stdlist[i].main;
 		state->second = msp_stdlist[i].second;
 		state->std = val;
+		state->rxsubchans = V4L2_TUNER_SUB_MONO;
 
 		if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
 				(val != 0x0009)) {
@@ -714,20 +732,17 @@
 			else
 				state->mode = MSP_MODE_FM_NICAM1;
 			/* just turn on stereo */
-			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			state->nicam_on = 1;
 			state->watch_stereo = 1;
 			break;
 		case 0x0009:
 			state->mode = MSP_MODE_AM_NICAM;
-			state->rxsubchans = V4L2_TUNER_SUB_MONO;
 			state->nicam_on = 1;
 			state->watch_stereo = 1;
 			break;
 		case 0x0020: /* BTSC */
 			/* The pre-'G' models only have BTSC-mono */
 			state->mode = MSP_MODE_BTSC;
-			state->rxsubchans = V4L2_TUNER_SUB_MONO;
 			break;
 		case 0x0040: /* FM radio */
 			state->mode = MSP_MODE_FM_RADIO;
@@ -737,15 +752,12 @@
 			msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
 			msp3400c_set_carrier(client, MSP_CARRIER(10.7),
 					    MSP_CARRIER(10.7));
-			/* scart routing (this doesn't belong here I think) */
-			msp_set_scart(client,SCART_IN2,0);
 			break;
 		case 0x0002:
 		case 0x0003:
 		case 0x0004:
 		case 0x0005:
 			state->mode = MSP_MODE_FM_TERRA;
-			state->rxsubchans = V4L2_TUNER_SUB_MONO;
 			state->watch_stereo = 1;
 			break;
 		}
@@ -759,20 +771,19 @@
 		if (state->has_i2s_conf)
 			msp_write_dem(client, 0x40, state->i2s_mode);
 
-		/* unmute, restore misc registers */
-		msp_set_audio(client);
-
-		msp_write_dsp(client, 0x13, state->acb);
+		/* unmute */
 		msp3400c_set_audmode(client);
+		state->scan_in_progress = 0;
+		msp_set_audio(client);
 
 		/* monitor tv audio mode, the first time don't wait
 		   so long to get a quick stereo/bilingual result */
-		if (msp_sleep(state, 1000))
-			goto restart;
+		count = 3;
 		while (state->watch_stereo) {
-			watch_stereo(client);
-			if (msp_sleep(state, 5000))
+			if (msp_sleep(state, count ? 1000 : 5000))
 				goto restart;
+			if (count) count--;
+			watch_stereo(client);
 		}
 	}
 	v4l_dbg(1, msp_debug, client, "thread: exit\n");
@@ -829,27 +840,27 @@
 		source = 0; /* mono only */
 		matrix = 0x30;
 		break;
-	case V4L2_TUNER_MODE_LANG1:
-		source = 3; /* stereo or A */
-		matrix = 0x00;
-		break;
 	case V4L2_TUNER_MODE_LANG2:
 		source = 4; /* stereo or B */
 		matrix = 0x10;
 		break;
-	case V4L2_TUNER_MODE_STEREO:
 	case V4L2_TUNER_MODE_LANG1_LANG2:
-	default:
 		source = 1; /* stereo or A|B */
 		matrix = 0x20;
 		break;
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1:
+	default:
+		source = 3; /* stereo or A */
+		matrix = 0x00;
+		break;
 	}
 
-	if (in == MSP_DSP_OUT_TUNER)
+	if (in == MSP_DSP_IN_TUNER)
 		source = (source << 8) | 0x20;
 	/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
 	   instead of 11, 12, 13. So we add one for that msp version. */
-	else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic)
+	else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)
 		source = ((in + 1) << 8) | matrix;
 	else
 		source = (in << 8) | matrix;
@@ -869,7 +880,7 @@
 	msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
 	msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
 	msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
-	if (state->has_scart23_in_scart2_out)
+	if (state->has_scart2_out)
 		msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
 	msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
 }
@@ -887,10 +898,6 @@
 
 	msp_reset(client);
 
-	/* make sure that input/output is muted (paranoid mode) */
-	/* ACB, mute DSP input, mute SCART 1 */
-	msp_write_dsp(client, 0x13, 0x0f20);
-
 	if (state->has_i2s_conf)
 		msp_write_dem(client, 0x40, state->i2s_mode);
 
@@ -1028,7 +1035,7 @@
 
 	if (state->std == 0x20) {
 	       if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
-		   (state->audmode == V4L2_TUNER_MODE_STEREO ||
+		   (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||
 		    state->audmode == V4L2_TUNER_MODE_LANG2)) {
 			msp_write_dem(client, 0x20, 0x21);
 	       } else {
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
new file mode 100644
index 0000000..8637655
--- /dev/null
+++ b/drivers/media/video/pwc/Kconfig
@@ -0,0 +1,28 @@
+config USB_PWC
+	tristate "USB Philips Cameras"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y or M here if you want to use one of these Philips & OEM
+	  webcams:
+	   * Philips PCA645, PCA646
+	   * Philips PCVC675, PCVC680, PCVC690
+	   * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+	   * Askey VC010
+	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+	     and 'Orbit'/'Sphere'
+	   * Samsung MPC-C10, MPC-C30
+	   * Creative Webcam 5, Pro Ex
+	   * SOTEC Afina Eye
+	   * Visionite VCS-UC300, VCS-UM100
+
+	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+	  and never will be, but the 665 and 720/20 are supported by other
+	  drivers.
+
+	  See <file:Documentation/usb/philips.txt> for more information and
+	  installation instructions.
+
+	  The built-in microphone is enabled by selecting USB Audio support.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pwc.
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b050152..dceebc0 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -40,6 +40,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/saa7115.h>
 #include <asm/div64.h>
 
 MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver");
@@ -53,7 +54,7 @@
 MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 static unsigned short normal_i2c[] = {
-		0x4a >>1, 0x48 >>1,	/* SAA7113 */
+		0x4a >> 1, 0x48 >> 1,	/* SAA7113 */
 		0x42 >> 1, 0x40 >> 1,	/* SAA7114 and SAA7115 */
 		I2C_CLIENT_END };
 
@@ -722,16 +723,16 @@
 	100 reserved                    NTSC-Japan (3.58MHz)
 	*/
 	if (state->ident == V4L2_IDENT_SAA7113) {
-		u8 reg =  saa7115_read(client, 0x0e) & 0x8f;
+		u8 reg = saa7115_read(client, 0x0e) & 0x8f;
 
 		if (std == V4L2_STD_PAL_M) {
-			reg|=0x30;
+			reg |= 0x30;
 		} else if (std == V4L2_STD_PAL_N) {
-			reg|=0x20;
+			reg |= 0x20;
 		} else if (std == V4L2_STD_PAL_60) {
-			reg|=0x10;
+			reg |= 0x10;
 		} else if (std == V4L2_STD_NTSC_M_JP) {
-			reg|=0x40;
+			reg |= 0x40;
 		}
 		saa7115_write(client, 0x0e, reg);
 	}
@@ -811,7 +812,7 @@
 	u8 lcr[24];
 	int i, x;
 
-	/* saa7113/71144 doesn't yet support VBI */
+	/* saa7113/7114 doesn't yet support VBI */
 	if (state->ident != V4L2_IDENT_SAA7115)
 		return;
 
@@ -851,7 +852,7 @@
 					case 0:
 						lcr[i] |= 0xf << (4 * x);
 						break;
-					case V4L2_SLICED_TELETEXT_PAL_B:
+					case V4L2_SLICED_TELETEXT_B:
 						lcr[i] |= 1 << (4 * x);
 						break;
 					case V4L2_SLICED_CAPTION_525:
@@ -880,7 +881,7 @@
 static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
 	static u16 lcr2vbi[] = {
-		0, V4L2_SLICED_TELETEXT_PAL_B, 0,	/* 1 */
+		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
 		0, V4L2_SLICED_CAPTION_525,	/* 4 */
 		V4L2_SLICED_WSS_625, 0,		/* 5 */
 		V4L2_SLICED_VPS, 0, 0, 0, 0,	/* 7 */
@@ -1045,7 +1046,7 @@
 	/* decode payloads */
 	switch (id2) {
 	case 1:
-		vbi->type = V4L2_SLICED_TELETEXT_PAL_B;
+		vbi->type = V4L2_SLICED_TELETEXT_B;
 		break;
 	case 4:
 		if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
@@ -1180,6 +1181,46 @@
 		state->radio = 1;
 		break;
 
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+	{
+		struct v4l2_routing *route = arg;
+
+		route->input = state->input;
+		route->output = 0;
+		break;
+	}
+
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+	{
+		struct v4l2_routing *route = arg;
+
+		v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+		/* saa7113 does not have these inputs */
+		if (state->ident == V4L2_IDENT_SAA7113 &&
+		    (route->input == SAA7115_COMPOSITE4 ||
+		     route->input == SAA7115_COMPOSITE5)) {
+			return -EINVAL;
+		}
+		if (route->input > SAA7115_SVIDEO3)
+			return -EINVAL;
+		if (state->input == route->input)
+			break;
+		v4l_dbg(1, debug, client, "now setting %s input\n",
+			(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+		state->input = route->input;
+
+		/* select mode */
+		saa7115_write(client, 0x02,
+			      (saa7115_read(client, 0x02) & 0xf0) |
+			       state->input);
+
+		/* bypass chrominance trap for S-Video modes */
+		saa7115_write(client, 0x09,
+			      (saa7115_read(client, 0x09) & 0x7f) |
+			       (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+		break;
+	}
+
 	case VIDIOC_G_INPUT:
 		*(int *)arg = state->input;
 		break;
@@ -1321,7 +1362,7 @@
 
 	saa7115_write(client, 0, 5);
 	chip_id = saa7115_read(client, 0) & 0x0f;
-	if (chip_id <3 && chip_id > 5) {
+	if (chip_id < 3 && chip_id > 5) {
 		v4l_dbg(1, debug, client, "saa7115 not found\n");
 		kfree(client);
 		return 0;
@@ -1360,7 +1401,7 @@
 	v4l_dbg(1, debug, client, "writing init values\n");
 
 	/* init to 60hz/48khz */
-	if (state->ident==V4L2_IDENT_SAA7113)
+	if (state->ident == V4L2_IDENT_SAA7113)
 		saa7115_writeregs(client, saa7113_init_auto_input);
 	else
 		saa7115_writeregs(client, saa7115_init_auto_input);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 992c717..133f9e5 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -54,6 +54,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/saa7127.h>
 
 static int debug = 0;
 static int test_image = 0;
@@ -222,22 +223,6 @@
 	{ 0, 0 }
 };
 
-/* Enumeration for the Supported input types */
-enum saa7127_input_type {
-	SAA7127_INPUT_TYPE_NORMAL,
-	SAA7127_INPUT_TYPE_TEST_IMAGE
-};
-
-/* Enumeration for the Supported Output signal types */
-enum saa7127_output_type {
-	SAA7127_OUTPUT_TYPE_BOTH,
-	SAA7127_OUTPUT_TYPE_COMPOSITE,
-	SAA7127_OUTPUT_TYPE_SVIDEO,
-	SAA7127_OUTPUT_TYPE_RGB,
-	SAA7127_OUTPUT_TYPE_YUV_C,
-	SAA7127_OUTPUT_TYPE_YUV_V
-};
-
 /*
  **********************************************************************
  *
@@ -561,7 +546,7 @@
 {
 	struct saa7127_state *state = i2c_get_clientdata(client);
 	struct v4l2_format *fmt = arg;
-	int *iarg = arg;
+	struct v4l2_routing *route = arg;
 
 	switch (cmd) {
 	case VIDIOC_S_STD:
@@ -573,15 +558,23 @@
 		*(v4l2_std_id *)arg = state->std;
 		break;
 
-	case VIDIOC_S_INPUT:
-		if (state->input_type == *iarg)
-			break;
-		return saa7127_set_input_type(client, *iarg);
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+		route->input = state->input_type;
+		route->output = state->output_type;
+		break;
 
-	case VIDIOC_S_OUTPUT:
-		if (state->output_type == *iarg)
-			break;
-		return saa7127_set_output_type(client, *iarg);
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+	{
+		int rc = 0;
+
+		if (state->input_type != route->input) {
+			rc = saa7127_set_input_type(client, route->input);
+		}
+		if (rc == 0 && state->output_type != route->output) {
+			rc = saa7127_set_output_type(client, route->output);
+		}
+		return rc;
+	}
 
 	case VIDIOC_STREAMON:
 	case VIDIOC_STREAMOFF:
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 86671a4..e1c1805 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -39,6 +39,7 @@
 	tristate "DVB/ATSC Support for saa7134 based TV cards"
 	depends on VIDEO_SAA7134 && DVB_CORE
 	select VIDEO_BUF_DVB
+	select FW_LOADER
 	---help---
 	  This adds support for DVB cards based on the
 	  Philips saa7134 chip.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 1ba9984..be7b9ee 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -11,9 +11,9 @@
 
 obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
 
-EXTRA_CFLAGS += -I$(src)/..
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
-EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
 extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1
 extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index fdd7f48..e666a44 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -208,7 +208,7 @@
 	[SAA7134_BOARD_FLYTVPLATINUM_FM] = {
 		/* LifeView FlyTV Platinum FM (LR214WF) */
 		/* "Peter Missel <peter.missel@onlinehome.de> */
-		.name           = "LifeView FlyTV Platinum FM",
+		.name           = "LifeView FlyTV Platinum FM / Gold",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
 		.radio_type     = UNSET,
@@ -2660,7 +2660,7 @@
 		.mpeg           = SAA7134_MPEG_DVB,
 		.inputs = {{
 			.name   = name_comp1,
-			.vmux   = 0,
+			.vmux   = 1,
 			.amux   = LINE1,
 		},{
 			.name   = name_svideo,
@@ -2671,7 +2671,7 @@
 	[SAA7134_BOARD_FLYDVBT_LR301] = {
 		/* LifeView FlyDVB-T */
 		/* Giampiero Giancipoli <gianci@libero.it> */
-		.name           = "LifeView FlyDVB-T",
+		.name           = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_ABSENT,
 		.radio_type     = UNSET,
@@ -2808,6 +2808,40 @@
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
 	},
+	[SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+		.name		= "LifeView FlyDVB-T Hybrid Cardbus",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
+			.tv   = 1,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
+		},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3333,6 +3367,30 @@
 		.subdevice    = 0x0005,
 		.driver_data  = SAA7134_BOARD_MD7134_BRIDGE_2,
 	},{
+		.vendor = PCI_VENDOR_ID_PHILIPS,
+		.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor = 0x1489,
+		.subdevice = 0x0301,
+		.driver_data = SAA7134_BOARD_FLYDVBT_LR301,
+	},{
+		.vendor = PCI_VENDOR_ID_PHILIPS,
+		.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor = 0x5168, /* Animation Technologies (LifeView) */
+		.subdevice = 0x0304,
+		.driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x3306,
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	},{
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3462,6 +3520,7 @@
 		saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
 		break;
 	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
 		saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
 		saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00);
 		break;
@@ -3633,6 +3692,7 @@
 		}
 		break;
 	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
 		/* make the tda10046 find its eeprom */
 		{
 		u8 data[] = { 0x3c, 0x33, 0x62};
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index c98571c..13de055 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/dma-mapping.h>
 
 #include "saa7134-reg.h"
 #include "saa7134.h"
@@ -870,7 +871,7 @@
 	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
 	       dev->pci_lat,pci_resource_start(pci_dev,0));
 	pci_set_master(pci_dev);
-	if (!pci_dma_supported(pci_dev,0xffffffff)) {
+	if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) {
 		printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
 		err = -EIO;
 		goto fail1;
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 86cfdb8..222a36c 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1064,6 +1064,10 @@
 		dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
 						    &dev->i2c_adap);
 		break;
+	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+		dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
+						    &dev->i2c_adap);
+		break;
 #endif
 #ifdef HAVE_NXT200X
 	case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 31ba293..353af3a 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -220,6 +220,7 @@
 #define SAA7134_BOARD_AVERMEDIA_A169_B 91
 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92
 #define SAA7134_BOARD_MD7134_BRIDGE_2     93
+#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
new file mode 100644
index 0000000..55f2bc1
--- /dev/null
+++ b/drivers/media/video/sn9c102/Kconfig
@@ -0,0 +1,11 @@
+config USB_SN9C102
+	tristate "USB SN9C10x PC Camera Controller support"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y here if you want support for cameras based on SONiX SN9C101,
+	  SN9C102 or SN9C103 PC Camera Controllers.
+
+	  See <file:Documentation/video4linux/sn9c102.txt> for more info.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sn9c102.
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index df195c9..1013b4d 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -401,7 +401,7 @@
 	}
 	tuner_info("Tuner mode:      %s\n", p);
 	tuner_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
-	tuner_info("Standard:        0x%08llx\n", t->std);
+	tuner_info("Standard:        0x%08lx\n", (unsigned long)t->std);
 	if (t->mode != V4L2_TUNER_RADIO)
 	       return;
 	if (t->has_signal) {
@@ -558,10 +558,10 @@
 
 static inline int check_v4l2(struct tuner *t)
 {
-	if (t->using_v4l2) {
-		tuner_dbg ("ignore v4l1 call\n");
-		return EINVAL;
-	}
+	/* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
+	   TV, v4l1 for radio), until that is fixed this code is disabled.
+	   Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
+	   first. */
 	return 0;
 }
 
@@ -744,6 +744,8 @@
 			switch_v4l2();
 
 			tuner->type = t->mode;
+			if (t->mode == V4L2_TUNER_ANALOG_TV)
+				tuner->capability |= V4L2_TUNER_CAP_NORM;
 			if (t->mode != V4L2_TUNER_RADIO) {
 				tuner->rangelow = tv_range[0] * 16;
 				tuner->rangehigh = tv_range[1] * 16;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 356bff4..c2b7561 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1706,21 +1706,6 @@
 		break;
 	}
 
-	case VIDIOC_S_AUDIO:
-	{
-		struct v4l2_audio *sarg = arg;
-
-		if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4)
-				return -EINVAL;
-		/* There are four inputs: tuner, radio, extern and intern. */
-		chip->input = sarg->index;
-		if (chip->muted)
-			break;
-		chip_write_masked(chip, desc->inputreg,
-				desc->inputmap[chip->input], desc->inputmask);
-		break;
-	}
-
 	case VIDIOC_S_TUNER:
 	{
 		struct v4l2_tuner *vt = arg;
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index e0d2ff8..431c3e2 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -757,9 +757,9 @@
 static int
 tveeprom_attach_adapter (struct i2c_adapter *adapter)
 {
-	if (adapter->id != I2C_HW_B_BT848)
-		return 0;
-	return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
+	return 0;
 }
 
 static int
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 69d0fe1..dab4973 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -53,7 +53,7 @@
 		.minimum = 0,
 		.maximum = 255,
 		.step = 1,
-		.default_value = 0,
+		.default_value = 128,
 		.flags = 0,
 	}, {
 		.id = V4L2_CID_CONTRAST,
@@ -62,7 +62,7 @@
 		.minimum = 0,
 		.maximum = 255,
 		.step = 0x1,
-		.default_value = 0x10,
+		.default_value = 128,
 		.flags = 0,
 	}, {
 		 .id = V4L2_CID_SATURATION,
@@ -71,7 +71,7 @@
 		 .minimum = 0,
 		 .maximum = 255,
 		 .step = 0x1,
-		 .default_value = 0x10,
+		 .default_value = 128,
 		 .flags = 0,
 	}, {
 		.id = V4L2_CID_HUE,
@@ -80,7 +80,7 @@
 		.minimum = -128,
 		.maximum = 127,
 		.step = 0x1,
-		.default_value = 0x10,
+		.default_value = 0,
 		.flags = 0,
 	}
 };
@@ -500,16 +500,21 @@
 
 static struct i2c_vbi_ram_value vbi_ram_default[] =
 {
+	/* FIXME: Current api doesn't handle all VBI types, those not
+	   yet supported are placed under #if 0 */
+#if 0
 	{0x010, /* Teletext, SECAM, WST System A */
 		{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
 		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
 		  0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
 	},
+#endif
 	{0x030, /* Teletext, PAL, WST System B */
-		{V4L2_SLICED_TELETEXT_PAL_B,6,22,1},
+		{V4L2_SLICED_TELETEXT_B,6,22,1},
 		{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
 		  0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
 	},
+#if 0
 	{0x050, /* Teletext, PAL, WST System C */
 		{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
 		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
@@ -535,6 +540,7 @@
 		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
 		  0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
 	},
+#endif
 	{0x0f0, /* Closed Caption, NTSC */
 		{V4L2_SLICED_CAPTION_525,21,21,1},
 		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
@@ -545,6 +551,7 @@
 		{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
 		  0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
 	},
+#if 0
 	{0x130, /* Wide Screen Signal, NTSC C */
 		{V4L2_SLICED_WSS_525,20,20,1},
 		{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
@@ -560,6 +567,7 @@
 		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
 		  0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
 	},
+#endif
 	{0x190, /* Video Program System (VPS), PAL */
 		{V4L2_SLICED_VPS,16,16,0},
 		{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
@@ -850,7 +858,6 @@
 
 	case 0:
 	case VIDIOC_INT_RESET:
-	case DECODER_INIT:
 		tvp5150_reset(c);
 		break;
 	case VIDIOC_S_STD:
@@ -949,99 +956,15 @@
 #endif
 
 	case VIDIOC_LOG_STATUS:
-	case DECODER_DUMP:
 		dump_reg(c);
 		break;
 
-	case DECODER_GET_CAPABILITIES:
+	case VIDIOC_G_TUNER:
 		{
-			struct video_decoder_capability *cap = arg;
+			struct v4l2_tuner *vt = arg;
+			int status = tvp5150_read(c, 0x88);
 
-			cap->flags = VIDEO_DECODER_PAL |
-			    VIDEO_DECODER_NTSC |
-			    VIDEO_DECODER_SECAM |
-			    VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
-			cap->inputs = 3;
-			cap->outputs = 1;
-			break;
-		}
-	case DECODER_GET_STATUS:
-		{
-			int *iarg = arg;
-			int status;
-			int res=0;
-			status = tvp5150_read(c, 0x88);
-			if(status&0x08){
-				res |= DECODER_STATUS_COLOR;
-			}
-			if(status&0x04 && status&0x02){
-				res |= DECODER_STATUS_GOOD;
-			}
-			*iarg=res;
-			break;
-		}
-
-	case DECODER_SET_GPIO:
-		break;
-
-	case DECODER_SET_VBI_BYPASS:
-		break;
-
-	case DECODER_SET_NORM:
-		{
-			int *iarg = arg;
-
-			switch (*iarg) {
-
-			case VIDEO_MODE_NTSC:
-				break;
-
-			case VIDEO_MODE_PAL:
-				break;
-
-			case VIDEO_MODE_SECAM:
-				break;
-
-			case VIDEO_MODE_AUTO:
-				break;
-
-			default:
-				return -EINVAL;
-
-			}
-			decoder->norm = *iarg;
-			break;
-		}
-	case DECODER_SET_INPUT:
-		{
-			int *iarg = arg;
-			if (*iarg < 0 || *iarg > 3) {
-				return -EINVAL;
-			}
-
-			decoder->input = *iarg;
-			tvp5150_selmux(c, decoder->input);
-
-			break;
-		}
-	case DECODER_SET_OUTPUT:
-		{
-			int *iarg = arg;
-
-			/* not much choice of outputs */
-			if (*iarg != 0) {
-				return -EINVAL;
-			}
-			break;
-		}
-	case DECODER_ENABLE_OUTPUT:
-		{
-			int *iarg = arg;
-
-			decoder->enable = (*iarg != 0);
-
-			tvp5150_selmux(c, decoder->input);
-
+			vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0;
 			break;
 		}
 	case VIDIOC_QUERYCTRL:
@@ -1087,35 +1010,6 @@
 			return -EINVAL;
 		}
 
-	case DECODER_SET_PICTURE:
-		{
-			struct video_picture *pic = arg;
-			if (decoder->bright != pic->brightness) {
-				/* We want 0 to 255 we get 0-65535 */
-				decoder->bright = pic->brightness;
-				tvp5150_write(c, TVP5150_BRIGHT_CTL,
-					      decoder->bright >> 8);
-			}
-			if (decoder->contrast != pic->contrast) {
-				/* We want 0 to 255 we get 0-65535 */
-				decoder->contrast = pic->contrast;
-				tvp5150_write(c, TVP5150_CONTRAST_CTL,
-					      decoder->contrast >> 8);
-			}
-			if (decoder->sat != pic->colour) {
-				/* We want 0 to 255 we get 0-65535 */
-				decoder->sat = pic->colour;
-				tvp5150_write(c, TVP5150_SATURATION_CTL,
-					      decoder->contrast >> 8);
-			}
-			if (decoder->hue != pic->hue) {
-				/* We want -128 to 127 we get 0-65535 */
-				decoder->hue = pic->hue;
-				tvp5150_write(c, TVP5150_HUE_CTL,
-					      (decoder->hue - 32768) >> 8);
-			}
-			break;
-		}
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
new file mode 100644
index 0000000..fc52201
--- /dev/null
+++ b/drivers/media/video/upd64031a.c
@@ -0,0 +1,286 @@
+/*
+ * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
+ *
+ * 2003 by T.Adachi <tadachi@tadachi-net.com>
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64031a.h>
+
+// --------------------- read registers functions define -----------------------
+
+/* bit masks */
+#define GR_MODE_MASK              0xc0
+#define DIRECT_3DYCS_CONNECT_MASK 0xc0
+#define SYNC_CIRCUIT_MASK         0xa0
+
+// -----------------------------------------------------------------------------
+
+MODULE_DESCRIPTION("uPD64031A driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+	R00 = 0, R01, R02, R03, R04,
+	R05, R06, R07, R08, R09,
+	R0A, R0B, R0C, R0D, R0E, R0F,
+	/* unused registers
+	 R10, R11, R12, R13, R14,
+	 R15, R16, R17,
+	 */
+	TOT_REGS
+};
+
+struct upd64031a_state {
+	u8 regs[TOT_REGS];
+	u8 gr_mode;
+	u8 direct_3dycs_connect;
+	u8 ext_comp_sync;
+	u8 ext_vert_sync;
+};
+
+static u8 upd64031a_init[] = {
+	0x00, 0xb8, 0x48, 0xd2, 0xe6,
+	0x03, 0x10, 0x0b, 0xaf, 0x7f,
+	0x00, 0x00, 0x1d, 0x5e, 0x00,
+	0xd0
+};
+
+/* ------------------------------------------------------------------------ */
+
+static u8 upd64031a_read(struct i2c_client *client, u8 reg)
+{
+	u8 buf[2];
+
+	if (reg >= sizeof(buf))
+		return 0xff;
+	i2c_master_recv(client, buf, 2);
+	return buf[reg];
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	v4l_dbg(1, debug, client, "writing reg addr: %02X val: %02X\n", reg, val);
+	if (i2c_master_send(client, buf, 2) != 2)
+		v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* The input changed due to new input or channel changed */
+static void upd64031a_change(struct i2c_client *client)
+{
+	struct upd64031a_state *state = i2c_get_clientdata(client);
+	u8 reg = state->regs[R00];
+
+	v4l_dbg(1, debug, client, "changed input or channel\n");
+	upd64031a_write(client, R00, reg | 0x10);
+	upd64031a_write(client, R00, reg & ~0x10);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	struct upd64031a_state *state = i2c_get_clientdata(client);
+	struct v4l2_routing *route = arg;
+
+	switch (cmd) {
+	case VIDIOC_S_FREQUENCY:
+		upd64031a_change(client);
+		break;
+
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+		route->input = (state->gr_mode >> 6) |
+			(state->direct_3dycs_connect >> 4) |
+			(state->ext_comp_sync >> 1) |
+			(state->ext_vert_sync >> 2);
+		route->output = 0;
+		break;
+
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+	{
+		u8 r00, r05, r08;
+
+		state->gr_mode = (route->input & 3) << 6;
+		state->direct_3dycs_connect = (route->input & 0xc) << 4;
+		state->ext_comp_sync = (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
+		state->ext_vert_sync = (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2;
+		r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
+		r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
+			state->ext_comp_sync | state->ext_vert_sync;
+		r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
+			state->direct_3dycs_connect;
+		upd64031a_write(client, R00, r00);
+		upd64031a_write(client, R05, r05);
+		upd64031a_write(client, R08, r08);
+		upd64031a_change(client);
+		break;
+	}
+
+	case VIDIOC_LOG_STATUS:
+		v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n",
+			upd64031a_read(client, 0), upd64031a_read(client, 1));
+		break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	case VIDIOC_INT_G_REGISTER:
+	{
+		struct v4l2_register *reg = arg;
+
+		if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+			return -EINVAL;
+		reg->val = upd64031a_read(client, reg->reg & 0xff);
+		break;
+	}
+
+	case VIDIOC_INT_S_REGISTER:
+	{
+		struct v4l2_register *reg = arg;
+		u8 addr = reg->reg & 0xff;
+		u8 val = reg->val & 0xff;
+
+		if (reg->i2c_id != I2C_DRIVERID_UPD64031A)
+			return -EINVAL;
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		upd64031a_write(client, addr, val);
+		break;
+	}
+#endif
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct upd64031a_state *state;
+	int i;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (client == NULL) {
+		return -ENOMEM;
+	}
+
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &i2c_driver;
+	snprintf(client->name, sizeof(client->name) - 1, "uPD64031A");
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+	state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+	if (state == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, state);
+	memcpy(state->regs, upd64031a_init, sizeof(state->regs));
+	state->gr_mode = UPD64031A_GR_ON << 6;
+	state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
+	state->ext_comp_sync = state->ext_vert_sync = 0;
+	for (i = 0; i < TOT_REGS; i++) {
+		upd64031a_write(client, i, state->regs[i]);
+	}
+
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int upd64031a_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, upd64031a_attach);
+	return 0;
+}
+
+static int upd64031a_detach(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err)
+		return err;
+
+	kfree(client);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "upd64031a",
+	},
+	.id = I2C_DRIVERID_UPD64031A,
+	.attach_adapter = upd64031a_probe,
+	.detach_client  = upd64031a_detach,
+	.command = upd64031a_command,
+};
+
+
+static int __init upd64031a_init_module(void)
+{
+	return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64031a_exit_module(void)
+{
+	i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64031a_init_module);
+module_exit(upd64031a_exit_module);
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
new file mode 100644
index 0000000..c3a7ffe
--- /dev/null
+++ b/drivers/media/video/upd64083.c
@@ -0,0 +1,262 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver
+ *
+ * 2003 by T.Adachi (tadachi@tadachi-net.com)
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/upd64083.h>
+
+MODULE_DESCRIPTION("uPD64083 driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+enum {
+	R00 = 0, R01, R02, R03, R04,
+	R05, R06, R07, R08, R09,
+	R0A, R0B, R0C, R0D, R0E, R0F,
+	R10, R11, R12, R13, R14,
+	R15, R16,
+	TOT_REGS
+};
+
+struct upd64083_state {
+	u8 mode;
+	u8 ext_y_adc;
+	u8 regs[TOT_REGS];
+};
+
+/* Initial values when used in combination with the
+   NEC upd64031a ghost reduction chip. */
+static u8 upd64083_init[] = {
+	0x1f, 0x01, 0xa0, 0x2d, 0x29,  /* we use EXCSS=0 */
+	0x36, 0xdd, 0x05, 0x56, 0x48,
+	0x00, 0x3a, 0xa0, 0x05, 0x08,
+	0x44, 0x60, 0x08, 0x52, 0xf8,
+	0x53, 0x60, 0x10
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_log_status(struct i2c_client *client)
+{
+	u8 buf[7];
+
+	i2c_master_recv(client, buf, 7);
+	v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x "
+		      "SA04=%02x SA05=%02x SA06=%02x\n",
+		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	v4l_dbg(1, debug, client, "writing reg addr: %02x val: %02x\n", reg, val);
+	if (i2c_master_send(client, buf, 2) != 2)
+		v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 upd64083_read(struct i2c_client *client, u8 reg)
+{
+	u8 buf[7];
+
+	if (reg >= sizeof(buf))
+		return 0xff;
+	i2c_master_recv(client, buf, sizeof(buf));
+	return buf[reg];
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	struct upd64083_state *state = i2c_get_clientdata(client);
+	struct v4l2_routing *route = arg;
+
+	switch (cmd) {
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+		route->input = (state->mode >> 6) | (state->ext_y_adc >> 3);
+		route->output = 0;
+		break;
+
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+	{
+		u8 r00, r02;
+
+		if (route->input > 7 || (route->input & 6) == 6)
+			return -EINVAL;
+		state->mode = (route->input & 3) << 6;
+		state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3;
+		r00 = (state->regs[R00] & ~(3 << 6)) | state->mode;
+		r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc;
+		upd64083_write(client, R00, r00);
+		upd64083_write(client, R02, r02);
+		break;
+	}
+
+	case VIDIOC_LOG_STATUS:
+		upd64083_log_status(client);
+		break;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	case VIDIOC_INT_G_REGISTER:
+	{
+		struct v4l2_register *reg = arg;
+
+		if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+			return -EINVAL;
+		reg->val = upd64083_read(client, reg->reg & 0xff);
+		break;
+	}
+
+	case VIDIOC_INT_S_REGISTER:
+	{
+		struct v4l2_register *reg = arg;
+		u8 addr = reg->reg & 0xff;
+		u8 val = reg->val & 0xff;
+
+		if (reg->i2c_id != I2C_DRIVERID_UPD64083)
+			return -EINVAL;
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		upd64083_write(client, addr, val);
+		break;
+	}
+#endif
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct upd64083_state *state;
+	int i;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (client == NULL) {
+		return -ENOMEM;
+	}
+
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &i2c_driver;
+	snprintf(client->name, sizeof(client->name) - 1, "uPD64083");
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+	state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+	if (state == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, state);
+	/* Initially assume that a ghost reduction chip is present */
+	state->mode = 0;  /* YCS mode */
+	state->ext_y_adc = (1 << 5);
+	memcpy(state->regs, upd64083_init, TOT_REGS);
+	for (i = 0; i < TOT_REGS; i++) {
+		upd64083_write(client, i, state->regs[i]);
+	}
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int upd64083_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, upd64083_attach);
+	return 0;
+}
+
+static int upd64083_detach(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err)
+		return err;
+
+	kfree(client);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "upd64083",
+	},
+	.id = I2C_DRIVERID_UPD64083,
+	.attach_adapter = upd64083_probe,
+	.detach_client  = upd64083_detach,
+	.command = upd64083_command,
+};
+
+
+static int __init upd64083_init_module(void)
+{
+	return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit upd64083_exit_module(void)
+{
+	i2c_del_driver(&i2c_driver);
+}
+
+module_init(upd64083_init_module);
+module_exit(upd64083_exit_module);
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
new file mode 100644
index 0000000..08a5d20
--- /dev/null
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -0,0 +1,38 @@
+config VIDEO_USBVIDEO
+	tristate
+
+config USB_VICAM
+	tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
+	depends on USB && VIDEO_DEV && EXPERIMENTAL
+	select VIDEO_USBVIDEO
+	---help---
+	  Say Y here if you have 3com homeconnect camera (vicam).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vicam.
+
+config USB_IBMCAM
+	tristate "USB IBM (Xirlink) C-it Camera support"
+	depends on USB && VIDEO_DEV
+	select VIDEO_USBVIDEO
+	---help---
+	  Say Y here if you want to connect a IBM "C-It" camera, also known as
+	  "Xirlink PC Camera" to your computer's USB port.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmcam.
+
+	  This camera has several configuration options which
+	  can be specified when you load the module. Read
+	  <file:Documentation/video4linux/ibmcam.txt> to learn more.
+
+config USB_KONICAWC
+	tristate "USB Konica Webcam support"
+	depends on USB && VIDEO_DEV
+	select VIDEO_USBVIDEO
+	---help---
+	  Say Y here if you want support for webcams based on a Konica
+	  chipset. This is known to work with the Intel YC76 webcam.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called konicawc.
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
index ed410a5..bb52eb8 100644
--- a/drivers/media/video/usbvideo/Makefile
+++ b/drivers/media/video/usbvideo/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_USB_IBMCAM)        += ibmcam.o usbvideo.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC)      += konicawc.o usbvideo.o
-obj-$(CONFIG_USB_VICAM)         += vicam.o usbvideo.o
-
+obj-$(CONFIG_VIDEO_USBVIDEO)    += usbvideo.o
+obj-$(CONFIG_USB_IBMCAM)        += ibmcam.o ultracam.o
+obj-$(CONFIG_USB_KONICAWC)      += konicawc.o
+obj-$(CONFIG_USB_VICAM)         += vicam.o
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 11a97f3..d330fa9 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -317,6 +317,7 @@
 	[_IOC_NR(TUNER_SET_STANDBY)]           = "TUNER_SET_STANDBY",
 	[_IOC_NR(TDA9887_SET_CONFIG)]          = "TDA9887_SET_CONFIG",
 
+	[_IOC_NR(VIDIOC_INT_S_TUNER_MODE)]     = "VIDIOC_INT_S_TUNER_MODE",
 	[_IOC_NR(VIDIOC_INT_S_REGISTER)]       = "VIDIOC_INT_S_REGISTER",
 	[_IOC_NR(VIDIOC_INT_G_REGISTER)]       = "VIDIOC_INT_G_REGISTER",
 	[_IOC_NR(VIDIOC_INT_RESET)]            = "VIDIOC_INT_RESET",
@@ -325,7 +326,12 @@
 	[_IOC_NR(VIDIOC_INT_S_VBI_DATA)]       = "VIDIOC_INT_S_VBI_DATA",
 	[_IOC_NR(VIDIOC_INT_G_VBI_DATA)]       = "VIDIOC_INT_G_VBI_DATA",
 	[_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)]     = "VIDIOC_INT_G_CHIP_IDENT",
-	[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)]   = "VIDIOC_INT_I2S_CLOCK_FREQ"
+	[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)]   = "VIDIOC_INT_I2S_CLOCK_FREQ",
+	[_IOC_NR(VIDIOC_INT_S_STANDBY)]        = "VIDIOC_INT_S_STANDBY",
+	[_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
+	[_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
+	[_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
+	[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING"
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index d2ca0f0..acc5ea9 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -399,19 +399,25 @@
 int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
 {
 	struct videobuf_queue q;
+	struct videobuf_queue_ops qops;
 
 	q.dev=pci;
-	q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+	qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+	qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+	q.ops = &qops;
 
-	return (videobuf_dma_unmap(&q,dma));
+	return (videobuf_dma_map(&q,dma));
 }
 
 int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
 {
 	struct videobuf_queue q;
+	struct videobuf_queue_ops qops;
 
 	q.dev=pci;
-	q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+	qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+	qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+	q.ops = &qops;
 
 	return (videobuf_dma_unmap(&q,dma));
 }
@@ -923,7 +929,7 @@
 		/* need to capture a new frame */
 		retval = -ENOMEM;
 		q->read_buf = videobuf_alloc(q->msize);
-		dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
+		dprintk(1,"video alloc=0x%p\n", q->read_buf);
 		if (NULL == q->read_buf)
 			goto done;
 		q->read_buf->memory = V4L2_MEMORY_USERPTR;
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
new file mode 100644
index 0000000..a9b59c3
--- /dev/null
+++ b/drivers/media/video/wm8739.c
@@ -0,0 +1,355 @@
+/*
+ * wm8739
+ *
+ * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
+ *
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("wm8739 driver");
+MODULE_AUTHOR("T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+static unsigned short normal_i2c[] = { 0x34 >> 1, 0x36 >> 1, I2C_CLIENT_END };
+
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+I2C_CLIENT_INSMOD;
+
+/* ------------------------------------------------------------------------ */
+
+enum {
+	R0 = 0, R1,
+	R5 = 5, R6, R7, R8, R9, R15 = 15,
+	TOT_REGS
+};
+
+struct wm8739_state {
+	u32 clock_freq;
+	u8 muted;
+	u16 volume;
+	u16 balance;
+	u8 vol_l; 		/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+	u8 vol_r; 		/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_write(struct i2c_client *client, int reg, u16 val)
+{
+	int i;
+
+	if (reg < 0 || reg >= TOT_REGS) {
+		v4l_err(client, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val);
+
+	for (i = 0; i < 3; i++) {
+		if (i2c_smbus_write_byte_data(client, (reg << 1) |
+					(val >> 8), val & 0xff) == 0) {
+			return 0;
+		}
+	}
+	v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+/* write regs to set audio volume etc */
+static void wm8739_set_audio(struct i2c_client *client)
+{
+	struct wm8739_state *state = i2c_get_clientdata(client);
+	u16 mute = state->muted ? 0x80 : 0;
+
+	/* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
+	 * Default setting: 0x17 = 0 dB
+	 */
+	wm8739_write(client, R0, (state->vol_l & 0x1f) | mute);
+	wm8739_write(client, R1, (state->vol_r & 0x1f) | mute);
+}
+
+static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+	struct wm8739_state *state = i2c_get_clientdata(client);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value = state->muted;
+		break;
+
+	case V4L2_CID_AUDIO_VOLUME:
+		ctrl->value = state->volume;
+		break;
+
+	case V4L2_CID_AUDIO_BALANCE:
+		ctrl->value = state->balance;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+	struct wm8739_state *state = i2c_get_clientdata(client);
+	unsigned int work_l, work_r;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		state->muted = ctrl->value;
+		break;
+
+	case V4L2_CID_AUDIO_VOLUME:
+		state->volume = ctrl->value;
+		break;
+
+	case V4L2_CID_AUDIO_BALANCE:
+		state->balance = ctrl->value;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
+	work_l = (min(65536 - state->balance, 32768) * state->volume) / 32768;
+	work_r = (min(state->balance, (u16)32768) * state->volume) / 32768;
+
+	state->vol_l = (long)work_l * 31 / 65535;
+	state->vol_r = (long)work_r * 31 / 65535;
+
+	/* set audio volume etc. */
+	wm8739_set_audio(client);
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct v4l2_queryctrl wm8739_qctrl[] = {
+	{
+		.id            = V4L2_CID_AUDIO_VOLUME,
+		.name          = "Volume",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 58880,
+		.flags         = 0,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.name          = "Mute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.step          = 1,
+		.default_value = 1,
+		.flags         = 0,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_AUDIO_BALANCE,
+		.name          = "Balance",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 32768,
+		.flags         = 0,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	}
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	struct wm8739_state *state = i2c_get_clientdata(client);
+
+	switch (cmd) {
+	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+	{
+		u32 audiofreq = *(u32 *)arg;
+
+		state->clock_freq = audiofreq;
+		wm8739_write(client, R9, 0x000);	/* de-activate */
+		switch (audiofreq) {
+		case 44100:
+			wm8739_write(client, R8, 0x020); /* 256fps, fs=44.1k     */
+			break;
+		case 48000:
+			wm8739_write(client, R8, 0x000); /* 256fps, fs=48k       */
+			break;
+		case 32000:
+			wm8739_write(client, R8, 0x018); /* 256fps, fs=32k       */
+			break;
+		default:
+			break;
+		}
+		wm8739_write(client, R9, 0x001);	/* activate */
+		break;
+	}
+
+	case VIDIOC_G_CTRL:
+		return wm8739_get_ctrl(client, arg);
+
+	case VIDIOC_S_CTRL:
+		return wm8739_set_ctrl(client, arg);
+
+	case VIDIOC_QUERYCTRL:
+	{
+		struct v4l2_queryctrl *qc = arg;
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++)
+			if (qc->id && qc->id == wm8739_qctrl[i].id) {
+				memcpy(qc, &wm8739_qctrl[i], sizeof(*qc));
+				return 0;
+			}
+		return -EINVAL;
+	}
+
+	case VIDIOC_LOG_STATUS:
+		v4l_info(client, "Frequency: %u Hz\n", state->clock_freq);
+		v4l_info(client, "Volume L:  %02x%s\n", state->vol_l & 0x1f,
+				state->muted ? " (muted)" : "");
+		v4l_info(client, "Volume R:  %02x%s\n", state->vol_r & 0x1f,
+				state->muted ? " (muted)" : "");
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static struct i2c_driver i2c_driver;
+
+static int wm8739_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct wm8739_state *state;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &i2c_driver;
+	snprintf(client->name, sizeof(client->name) - 1, "wm8739");
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+	state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL);
+	if (state == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+	state->vol_l = 0x17; /* 0dB */
+	state->vol_r = 0x17; /* 0dB */
+	state->muted = 0;
+	state->balance = 32768;
+	/* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */
+	state->volume = ((long)state->vol_l + 1) * 65535 / 31;
+	state->clock_freq = 48000;
+	i2c_set_clientdata(client, state);
+
+	/* initialize wm8739 */
+	wm8739_write(client, R15, 0x00); /* reset */
+	wm8739_write(client, R5, 0x000); /* filter setting, high path, offet clear */
+	wm8739_write(client, R6, 0x000); /* ADC, OSC, Power Off mode Disable */
+	wm8739_write(client, R7, 0x049); /* Digital Audio interface format */
+					 /* Enable Master mode */
+					 /* 24 bit, MSB first/left justified */
+	wm8739_write(client, R8, 0x000); /* sampling control */
+					 /* normal, 256fs, 48KHz sampling rate */
+	wm8739_write(client, R9, 0x001); /* activate */
+	wm8739_set_audio(client); 	 /* set volume/mute */
+
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int wm8739_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, wm8739_attach);
+	return 0;
+}
+
+static int wm8739_detach(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err)
+		return err;
+
+	kfree(client);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "wm8739",
+	},
+	.id = I2C_DRIVERID_WM8739,
+	.attach_adapter = wm8739_probe,
+	.detach_client  = wm8739_detach,
+	.command = wm8739_command,
+};
+
+
+static int __init wm8739_init_module(void)
+{
+	return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit wm8739_cleanup_module(void)
+{
+	i2c_del_driver(&i2c_driver);
+}
+
+module_init(wm8739_init_module);
+module_exit(wm8739_cleanup_module);
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig
new file mode 100644
index 0000000..c3bf886
--- /dev/null
+++ b/drivers/media/video/zc0301/Kconfig
@@ -0,0 +1,11 @@
+config USB_ZC0301
+	tristate "USB ZC0301 Image Processor and Control Chip support"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y here if you want support for cameras based on the ZC0301
+	  Image Processor and Control Chip.
+
+	  See <file:Documentation/video4linux/zc0301.txt> for more info.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called zc0301.
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 010d4a3..e9716b1 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -366,7 +366,15 @@
 static int
 mptsas_slave_configure(struct scsi_device *sdev)
 {
-	sas_read_port_mode_page(sdev);
+	struct Scsi_Host	*host = sdev->host;
+	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
+
+	/*
+	 * RAID volumes placed beyond the last expected port.
+	 * Ignore sending sas mode pages in that case..
+	 */
+	if (sdev->channel < hd->ioc->num_ports)
+		sas_read_port_mode_page(sdev);
 
 	return mptscsih_slave_configure(sdev);
 }
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 7cc162e..003b077 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -91,4 +91,22 @@
 
 	  If unsure, say N.
 
+config MMC_AT91RM9200
+	tristate "AT91RM9200 SD/MMC Card Interface support"
+	depends on ARCH_AT91RM9200 && MMC
+	help
+	  This selects the AT91RM9200 MCI controller.
+
+	  If unsure, say N.
+
+config MMC_IMX
+	tristate "Motorola i.MX Multimedia Card Interface support"
+	depends on ARCH_IMX && MMC
+	help
+	  This selects the Motorola i.MX Multimedia card Interface.
+	  If you have a i.MX platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c7c34aa..d2957e3 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -17,10 +17,12 @@
 #
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
+obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
 obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_AT91RM9200)	+= at91_mci.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
 
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
new file mode 100644
index 0000000..6061c2d
--- /dev/null
+++ b/drivers/mmc/at91_mci.c
@@ -0,0 +1,988 @@
+/*
+ *  linux/drivers/mmc/at91_mci.c - ATMEL AT91RM9200 MCI Driver
+ *
+ *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
+ *
+ *  Copyright (C) 2006 Malcolm Noyes
+ *
+ * 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 is the AT91RM9200 MCI driver that has been tested with both MMC cards
+   and SD-cards.  Boards that support write protect are now supported.
+   The CCAT91SBC001 board does not support SD cards.
+
+   The three entry points are at91_mci_request, at91_mci_set_ios
+   and at91_mci_get_ro.
+
+   SET IOS
+     This configures the device to put it into the correct mode and clock speed
+     required.
+
+   MCI REQUEST
+     MCI request processes the commands sent in the mmc_request structure. This
+     can consist of a processing command and a stop command in the case of
+     multiple block transfers.
+
+     There are three main types of request, commands, reads and writes.
+
+     Commands are straight forward. The command is submitted to the controller and
+     the request function returns. When the controller generates an interrupt to indicate
+     the command is finished, the response to the command are read and the mmc_request_done
+     function called to end the request.
+
+     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
+     controller to manage the transfers.
+
+     A read is done from the controller directly to the scatterlist passed in from the request.
+     Due to a bug in the controller, when a read is completed, all the words are byte
+     swapped in the scatterlist buffers.
+
+     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
+
+     A write is slightly different in that the bytes to write are read from the scatterlist
+     into a dma memory buffer (this is in case the source buffer should be read only). The
+     entire write buffer is then done from this single dma memory buffer.
+
+     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
+
+   GET RO
+     Gets the status of the write protect pin, if available.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/mmc.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91rm9200_mci.h>
+#include <asm/arch/at91rm9200_pdc.h>
+
+#define DRIVER_NAME "at91_mci"
+
+#undef	SUPPORT_4WIRE
+
+#ifdef CONFIG_MMC_DEBUG
+#define DBG(fmt...)	\
+	printk(fmt)
+#else
+#define DBG(fmt...)	do { } while (0)
+#endif
+
+static struct clk *mci_clk;
+
+#define FL_SENT_COMMAND (1 << 0)
+#define FL_SENT_STOP (1 << 1)
+
+
+
+/*
+ * Read from a MCI register.
+ */
+static inline unsigned long at91_mci_read(unsigned int reg)
+{
+	void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+	return __raw_readl(mci_base + reg);
+}
+
+/*
+ * Write to a MCI register.
+ */
+static inline void at91_mci_write(unsigned int reg, unsigned long value)
+{
+        void __iomem *mci_base = (void __iomem *)AT91_VA_BASE_MCI;
+
+        __raw_writel(value, mci_base + reg);
+}
+
+/*
+ * Low level type for this driver
+ */
+struct at91mci_host
+{
+	struct mmc_host *mmc;
+	struct mmc_command *cmd;
+	struct mmc_request *request;
+
+	struct at91_mmc_data *board;
+	int present;
+
+	/*
+	 * Flag indicating when the command has been sent. This is used to
+	 * work out whether or not to send the stop
+	 */
+	unsigned int flags;
+	/* flag for current bus settings */
+	u32 bus_mode;
+
+	/* DMA buffer used for transmitting */
+	unsigned int* buffer;
+	dma_addr_t physical_address;
+	unsigned int total_length;
+
+	/* Latest in the scatterlist that has been enabled for transfer, but not freed */
+	int in_use_index;
+
+	/* Latest in the scatterlist that has been enabled for transfer */
+	int transfer_index;
+};
+
+/*
+ * Copy from sg to a dma block - used for transfers
+ */
+static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+{
+	unsigned int len, i, size;
+	unsigned *dmabuf = host->buffer;
+
+	size = host->total_length;
+	len = data->sg_len;
+
+	/*
+	 * Just loop through all entries. Size might not
+	 * be the entire list though so make sure that
+	 * we do not transfer too much.
+	 */
+	for (i = 0; i < len; i++) {
+		struct scatterlist *sg;
+		int amount;
+		int index;
+		unsigned int *sgbuffer;
+
+		sg = &data->sg[i];
+
+		sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+		amount = min(size, sg->length);
+		size -= amount;
+		amount /= 4;
+
+		for (index = 0; index < amount; index++)
+			*dmabuf++ = swab32(sgbuffer[index]);
+
+		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+
+		if (size == 0)
+			break;
+	}
+
+	/*
+	 * Check that we didn't get a request to transfer
+	 * more data than can fit into the SG list.
+	 */
+	BUG_ON(size != 0);
+}
+
+/*
+ * Prepare a dma read
+ */
+static void at91mci_pre_dma_read(struct at91mci_host *host)
+{
+	int i;
+	struct scatterlist *sg;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("pre dma read\n");
+
+	cmd = host->cmd;
+	if (!cmd) {
+		DBG("no command\n");
+		return;
+	}
+
+	data = cmd->data;
+	if (!data) {
+		DBG("no data\n");
+		return;
+	}
+
+	for (i = 0; i < 2; i++) {
+		/* nothing left to transfer */
+		if (host->transfer_index >= data->sg_len) {
+			DBG("Nothing left to transfer (index = %d)\n", host->transfer_index);
+			break;
+		}
+
+		/* Check to see if this needs filling */
+		if (i == 0) {
+			if (at91_mci_read(AT91_PDC_RCR) != 0) {
+				DBG("Transfer active in current\n");
+				continue;
+			}
+		}
+		else {
+			if (at91_mci_read(AT91_PDC_RNCR) != 0) {
+				DBG("Transfer active in next\n");
+				continue;
+			}
+		}
+
+		/* Setup the next transfer */
+		DBG("Using transfer index %d\n", host->transfer_index);
+
+		sg = &data->sg[host->transfer_index++];
+		DBG("sg = %p\n", sg);
+
+		sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
+
+		DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+
+		if (i == 0) {
+			at91_mci_write(AT91_PDC_RPR, sg->dma_address);
+			at91_mci_write(AT91_PDC_RCR, sg->length / 4);
+		}
+		else {
+			at91_mci_write(AT91_PDC_RNPR, sg->dma_address);
+			at91_mci_write(AT91_PDC_RNCR, sg->length / 4);
+		}
+	}
+
+	DBG("pre dma read done\n");
+}
+
+/*
+ * Handle after a dma read
+ */
+static void at91mci_post_dma_read(struct at91mci_host *host)
+{
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("post dma read\n");
+
+	cmd = host->cmd;
+	if (!cmd) {
+		DBG("no command\n");
+		return;
+	}
+
+	data = cmd->data;
+	if (!data) {
+		DBG("no data\n");
+		return;
+	}
+
+	while (host->in_use_index < host->transfer_index) {
+		unsigned int *buffer;
+		int index;
+		int len;
+
+		struct scatterlist *sg;
+
+		DBG("finishing index %d\n", host->in_use_index);
+
+		sg = &data->sg[host->in_use_index++];
+
+		DBG("Unmapping page %08X\n", sg->dma_address);
+
+		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+
+		/* Swap the contents of the buffer */
+		buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+		DBG("buffer = %p, length = %d\n", buffer, sg->length);
+
+		data->bytes_xfered += sg->length;
+
+		len = sg->length / 4;
+
+		for (index = 0; index < len; index++) {
+			buffer[index] = swab32(buffer[index]);
+		}
+		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+		flush_dcache_page(sg->page);
+	}
+
+	/* Is there another transfer to trigger? */
+	if (host->transfer_index < data->sg_len)
+		at91mci_pre_dma_read(host);
+	else {
+		at91_mci_write(AT91_MCI_IER, AT91_MCI_RXBUFF);
+		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+	}
+
+	DBG("post dma read done\n");
+}
+
+/*
+ * Handle transmitted data
+ */
+static void at91_mci_handle_transmitted(struct at91mci_host *host)
+{
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+
+	DBG("Handling the transmit\n");
+
+	/* Disable the transfer */
+	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+	/* Now wait for cmd ready */
+	at91_mci_write(AT91_MCI_IDR, AT91_MCI_TXBUFE);
+	at91_mci_write(AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
+	cmd = host->cmd;
+	if (!cmd) return;
+
+	data = cmd->data;
+	if (!data) return;
+
+	data->bytes_xfered = host->total_length;
+}
+
+/*
+ * Enable the controller
+ */
+static void at91_mci_enable(void)
+{
+	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+	at91_mci_write(AT91_MCI_IDR, 0xFFFFFFFF);
+	at91_mci_write(AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
+	at91_mci_write(AT91_MCI_MR, 0x834A);
+	at91_mci_write(AT91_MCI_SDCR, 0x0);
+}
+
+/*
+ * Disable the controller
+ */
+static void at91_mci_disable(void)
+{
+	at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
+}
+
+/*
+ * Send a command
+ * return the interrupts to enable
+ */
+static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+	unsigned int cmdr, mr;
+	unsigned int block_length;
+	struct mmc_data *data = cmd->data;
+
+	unsigned int blocks;
+	unsigned int ier = 0;
+
+	host->cmd = cmd;
+
+	/* Not sure if this is needed */
+#if 0
+	if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
+		DBG("Clearing timeout\n");
+		at91_mci_write(AT91_MCI_ARGR, 0);
+		at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
+		while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
+			/* spin */
+			DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+		}
+	}
+#endif
+	cmdr = cmd->opcode;
+
+	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
+		cmdr |= AT91_MCI_RSPTYP_NONE;
+	else {
+		/* if a response is expected then allow maximum response latancy */
+		cmdr |= AT91_MCI_MAXLAT;
+		/* set 136 bit response for R2, 48 bit response otherwise */
+		if (mmc_resp_type(cmd) == MMC_RSP_R2)
+			cmdr |= AT91_MCI_RSPTYP_136;
+		else
+			cmdr |= AT91_MCI_RSPTYP_48;
+	}
+
+	if (data) {
+		block_length = 1 << data->blksz_bits;
+		blocks = data->blocks;
+
+		/* always set data start - also set direction flag for read */
+		if (data->flags & MMC_DATA_READ)
+			cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
+		else if (data->flags & MMC_DATA_WRITE)
+			cmdr |= AT91_MCI_TRCMD_START;
+
+		if (data->flags & MMC_DATA_STREAM)
+			cmdr |= AT91_MCI_TRTYP_STREAM;
+		if (data->flags & MMC_DATA_MULTI)
+			cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+	}
+	else {
+		block_length = 0;
+		blocks = 0;
+	}
+
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmdr |= AT91_MCI_TRCMD_STOP;
+
+	if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		cmdr |= AT91_MCI_OPDCMD;
+
+	/*
+	 * Set the arguments and send the command
+	 */
+	DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
+		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
+
+	if (!data) {
+		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTDIS | AT91_PDC_RXTDIS);
+		at91_mci_write(AT91_PDC_RPR, 0);
+		at91_mci_write(AT91_PDC_RCR, 0);
+		at91_mci_write(AT91_PDC_RNPR, 0);
+		at91_mci_write(AT91_PDC_RNCR, 0);
+		at91_mci_write(AT91_PDC_TPR, 0);
+		at91_mci_write(AT91_PDC_TCR, 0);
+		at91_mci_write(AT91_PDC_TNPR, 0);
+		at91_mci_write(AT91_PDC_TNCR, 0);
+
+		at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+		at91_mci_write(AT91_MCI_CMDR, cmdr);
+		return AT91_MCI_CMDRDY;
+	}
+
+	mr = at91_mci_read(AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
+	at91_mci_write(AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+
+	/*
+	 * Disable the PDC controller
+	 */
+	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
+
+	if (cmdr & AT91_MCI_TRCMD_START) {
+		data->bytes_xfered = 0;
+		host->transfer_index = 0;
+		host->in_use_index = 0;
+		if (cmdr & AT91_MCI_TRDIR) {
+			/*
+			 * Handle a read
+			 */
+			host->buffer = NULL;
+			host->total_length = 0;
+
+			at91mci_pre_dma_read(host);
+			ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+		}
+		else {
+			/*
+			 * Handle a write
+			 */
+			host->total_length = block_length * blocks;
+			host->buffer = dma_alloc_coherent(NULL,
+						  host->total_length,
+						  &host->physical_address, GFP_KERNEL);
+
+			at91mci_sg_to_dma(host, data);
+
+			DBG("Transmitting %d bytes\n", host->total_length);
+
+			at91_mci_write(AT91_PDC_TPR, host->physical_address);
+			at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
+			ier = AT91_MCI_TXBUFE;
+		}
+	}
+
+	/*
+	 * Send the command and then enable the PDC - not the other way round as
+	 * the data sheet says
+	 */
+
+	at91_mci_write(AT91_MCI_ARGR, cmd->arg);
+	at91_mci_write(AT91_MCI_CMDR, cmdr);
+
+	if (cmdr & AT91_MCI_TRCMD_START) {
+		if (cmdr & AT91_MCI_TRDIR)
+			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTEN);
+		else
+			at91_mci_write(AT91_PDC_PTCR, AT91_PDC_TXTEN);
+	}
+	return ier;
+}
+
+/*
+ * Wait for a command to complete
+ */
+static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
+{
+	unsigned int ier;
+
+	ier = at91_mci_send_command(host, cmd);
+
+	DBG("setting ier to %08X\n", ier);
+
+	/* Stop on errors or the required value */
+	at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
+}
+
+/*
+ * Process the next step in the request
+ */
+static void at91mci_process_next(struct at91mci_host *host)
+{
+	if (!(host->flags & FL_SENT_COMMAND)) {
+		host->flags |= FL_SENT_COMMAND;
+		at91mci_process_command(host, host->request->cmd);
+	}
+	else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
+		host->flags |= FL_SENT_STOP;
+		at91mci_process_command(host, host->request->stop);
+	}
+	else
+		mmc_request_done(host->mmc, host->request);
+}
+
+/*
+ * Handle a command that has been completed
+ */
+static void at91mci_completed_command(struct at91mci_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	unsigned int status;
+
+	at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+
+	cmd->resp[0] = at91_mci_read(AT91_MCI_RSPR(0));
+	cmd->resp[1] = at91_mci_read(AT91_MCI_RSPR(1));
+	cmd->resp[2] = at91_mci_read(AT91_MCI_RSPR(2));
+	cmd->resp[3] = at91_mci_read(AT91_MCI_RSPR(3));
+
+	if (host->buffer) {
+		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
+		host->buffer = NULL;
+	}
+
+	status = at91_mci_read(AT91_MCI_SR);
+
+	DBG("Status = %08X [%08X %08X %08X %08X]\n",
+		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
+			AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
+			AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
+		if ((status & AT91_MCI_RCRCE) &&
+			((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+			cmd->error = MMC_ERR_NONE;
+		}
+		else {
+			if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
+				cmd->error = MMC_ERR_TIMEOUT;
+			else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
+				cmd->error = MMC_ERR_BADCRC;
+			else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
+				cmd->error = MMC_ERR_FIFO;
+			else
+				cmd->error = MMC_ERR_FAILED;
+
+			DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
+				 cmd->error, cmd->opcode, cmd->retries);
+		}
+	}
+	else
+		cmd->error = MMC_ERR_NONE;
+
+	at91mci_process_next(host);
+}
+
+/*
+ * Handle an MMC request
+ */
+static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct at91mci_host *host = mmc_priv(mmc);
+	host->request = mrq;
+	host->flags = 0;
+
+	at91mci_process_next(host);
+}
+
+/*
+ * Set the IOS
+ */
+static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	int clkdiv;
+	struct at91mci_host *host = mmc_priv(mmc);
+	unsigned long at91_master_clock = clk_get_rate(mci_clk);
+
+	DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n",
+		ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
+
+	if (host)
+		host->bus_mode = ios->bus_mode;
+	else
+		printk("MMC: No host for bus_mode\n");
+
+	if (ios->clock == 0) {
+		/* Disable the MCI controller */
+		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIDIS);
+		clkdiv = 0;
+	}
+	else {
+		/* Enable the MCI controller */
+		at91_mci_write(AT91_MCI_CR, AT91_MCI_MCIEN);
+
+		if ((at91_master_clock % (ios->clock * 2)) == 0)
+			clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
+		else
+			clkdiv = (at91_master_clock / ios->clock) / 2;
+
+		DBG("clkdiv = %d. mcck = %ld\n", clkdiv,
+			at91_master_clock / (2 * (clkdiv + 1)));
+	}
+	if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
+		DBG("MMC: Setting controller bus width to 4\n");
+		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
+	}
+	else {
+		DBG("MMC: Setting controller bus width to 1\n");
+		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
+	}
+
+	/* Set the clock divider */
+	at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
+
+	/* maybe switch power to the card */
+	if (host && host->board->vcc_pin) {
+		switch (ios->power_mode) {
+			case MMC_POWER_OFF:
+				at91_set_gpio_output(host->board->vcc_pin, 0);
+				break;
+			case MMC_POWER_UP:
+			case MMC_POWER_ON:
+				at91_set_gpio_output(host->board->vcc_pin, 1);
+				break;
+		}
+	}
+}
+
+/*
+ * Handle an interrupt
+ */
+static irqreturn_t at91_mci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct at91mci_host *host = devid;
+	int completed = 0;
+
+	unsigned int int_status;
+
+	if (host == NULL)
+		return IRQ_HANDLED;
+
+	int_status = at91_mci_read(AT91_MCI_SR);
+	DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
+		int_status & at91_mci_read(AT91_MCI_IMR));
+
+	if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
+		completed = 1;
+
+	int_status &= at91_mci_read(AT91_MCI_IMR);
+
+	if (int_status & AT91_MCI_UNRE)
+		DBG("MMC: Underrun error\n");
+	if (int_status & AT91_MCI_OVRE)
+		DBG("MMC: Overrun error\n");
+	if (int_status & AT91_MCI_DTOE)
+		DBG("MMC: Data timeout\n");
+	if (int_status & AT91_MCI_DCRCE)
+		DBG("MMC: CRC error in data\n");
+	if (int_status & AT91_MCI_RTOE)
+		DBG("MMC: Response timeout\n");
+	if (int_status & AT91_MCI_RENDE)
+		DBG("MMC: Response end bit error\n");
+	if (int_status & AT91_MCI_RCRCE)
+		DBG("MMC: Response CRC error\n");
+	if (int_status & AT91_MCI_RDIRE)
+		DBG("MMC: Response direction error\n");
+	if (int_status & AT91_MCI_RINDE)
+		DBG("MMC: Response index error\n");
+
+	/* Only continue processing if no errors */
+	if (!completed) {
+		if (int_status & AT91_MCI_TXBUFE) {
+			DBG("TX buffer empty\n");
+			at91_mci_handle_transmitted(host);
+		}
+
+		if (int_status & AT91_MCI_RXBUFF) {
+			DBG("RX buffer full\n");
+			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+		}
+
+		if (int_status & AT91_MCI_ENDTX) {
+			DBG("Transmit has ended\n");
+		}
+
+		if (int_status & AT91_MCI_ENDRX) {
+			DBG("Receive has ended\n");
+			at91mci_post_dma_read(host);
+		}
+
+		if (int_status & AT91_MCI_NOTBUSY) {
+			DBG("Card is ready\n");
+			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
+		}
+
+		if (int_status & AT91_MCI_DTIP) {
+			DBG("Data transfer in progress\n");
+		}
+
+		if (int_status & AT91_MCI_BLKE) {
+			DBG("Block transfer has ended\n");
+		}
+
+		if (int_status & AT91_MCI_TXRDY) {
+			DBG("Ready to transmit\n");
+		}
+
+		if (int_status & AT91_MCI_RXRDY) {
+			DBG("Ready to receive\n");
+		}
+
+		if (int_status & AT91_MCI_CMDRDY) {
+			DBG("Command ready\n");
+			completed = 1;
+		}
+	}
+	at91_mci_write(AT91_MCI_IDR, int_status);
+
+	if (completed) {
+		DBG("Completed command\n");
+		at91_mci_write(AT91_MCI_IDR, 0xffffffff);
+		at91mci_completed_command(host);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t at91_mmc_det_irq(int irq, void *_host, struct pt_regs *regs)
+{
+	struct at91mci_host *host = _host;
+	int present = !at91_get_gpio_value(irq);
+
+	/*
+	 * we expect this irq on both insert and remove,
+	 * and use a short delay to debounce.
+	 */
+	if (present != host->present) {
+		host->present = present;
+		DBG("%s: card %s\n", mmc_hostname(host->mmc),
+			present ? "insert" : "remove");
+		if (!present) {
+			DBG("****** Resetting SD-card bus width ******\n");
+			at91_mci_write(AT91_MCI_SDCR, 0);
+		}
+		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+	}
+	return IRQ_HANDLED;
+}
+
+int at91_mci_get_ro(struct mmc_host *mmc)
+{
+	int read_only = 0;
+	struct at91mci_host *host = mmc_priv(mmc);
+
+	if (host->board->wp_pin) {
+		read_only = at91_get_gpio_value(host->board->wp_pin);
+		printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
+				(read_only ? "read-only" : "read-write") );
+	}
+	else {
+		printk(KERN_WARNING "%s: host does not support reading read-only "
+				"switch.  Assuming write-enable.\n", mmc_hostname(mmc));
+	}
+	return read_only;
+}
+
+static struct mmc_host_ops at91_mci_ops = {
+	.request	= at91_mci_request,
+	.set_ios	= at91_mci_set_ios,
+	.get_ro		= at91_mci_get_ro,
+};
+
+/*
+ * Probe for the device
+ */
+static int at91_mci_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct at91mci_host *host;
+	int ret;
+
+	DBG("Probe MCI devices\n");
+	at91_mci_disable();
+	at91_mci_enable();
+
+	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
+	if (!mmc) {
+		DBG("Failed to allocate mmc host\n");
+		return -ENOMEM;
+	}
+
+	mmc->ops = &at91_mci_ops;
+	mmc->f_min = 375000;
+	mmc->f_max = 25000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->buffer = NULL;
+	host->bus_mode = 0;
+	host->board = pdev->dev.platform_data;
+	if (host->board->wire4) {
+#ifdef SUPPORT_4WIRE
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
+#else
+		printk("MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
+#endif
+	}
+
+	/*
+	 * Get Clock
+	 */
+	mci_clk = clk_get(&pdev->dev, "mci_clk");
+	if (!mci_clk) {
+		printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+		return -ENODEV;
+	}
+	clk_enable(mci_clk);			/* Enable the peripheral clock */
+
+	/*
+	 * Allocate the MCI interrupt
+	 */
+	ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host);
+	if (ret) {
+		DBG("Failed to request MCI interrupt\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, mmc);
+
+	/*
+	 * Add host to MMC layer
+	 */
+	if (host->board->det_pin)
+		host->present = !at91_get_gpio_value(host->board->det_pin);
+	else
+		host->present = -1;
+
+	mmc_add_host(mmc);
+
+	/*
+	 * monitor card insertion/removal if we can
+	 */
+	if (host->board->det_pin) {
+		ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
+				SA_SAMPLE_RANDOM, DRIVER_NAME, host);
+		if (ret)
+			DBG("couldn't allocate MMC detect irq\n");
+	}
+
+	DBG(KERN_INFO "Added MCI driver\n");
+
+	return 0;
+}
+
+/*
+ * Remove a device
+ */
+static int at91_mci_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct at91mci_host *host;
+
+	if (!mmc)
+		return -1;
+
+	host = mmc_priv(mmc);
+
+	if (host->present != -1) {
+		free_irq(host->board->det_pin, host);
+		cancel_delayed_work(&host->mmc->detect);
+	}
+
+	mmc_remove_host(mmc);
+	at91_mci_disable();
+	free_irq(AT91_ID_MCI, host);
+	mmc_free_host(mmc);
+
+	clk_disable(mci_clk);				/* Disable the peripheral clock */
+	clk_put(mci_clk);
+
+	platform_set_drvdata(pdev, NULL);
+
+	DBG("Removed\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int at91_mci_resume(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+#else
+#define at91_mci_suspend	NULL
+#define at91_mci_resume		NULL
+#endif
+
+static struct platform_driver at91_mci_driver = {
+	.probe		= at91_mci_probe,
+	.remove		= at91_mci_remove,
+	.suspend	= at91_mci_suspend,
+	.resume		= at91_mci_resume,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_mci_init(void)
+{
+	return platform_driver_register(&at91_mci_driver);
+}
+
+static void __exit at91_mci_exit(void)
+{
+	platform_driver_unregister(&at91_mci_driver);
+}
+
+module_init(at91_mci_init);
+module_exit(at91_mci_exit);
+
+MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
+MODULE_AUTHOR("Nick Randell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
new file mode 100644
index 0000000..ffb7f55
--- /dev/null
+++ b/drivers/mmc/imxmmc.c
@@ -0,0 +1,1096 @@
+/*
+ *  linux/drivers/mmc/imxmmc.c - Motorola i.MX MMCI driver
+ *
+ *  Copyright (C) 2004 Sascha Hauer, Pengutronix <sascha@saschahauer.de>
+ *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ *  derived from pxamci.c by Russell King
+ *
+ * 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.
+ *
+ *  2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Changed to conform redesigned i.MX scatter gather DMA interface
+ *
+ *  2005-11-04 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Updated for 2.6.14 kernel
+ *
+ *  2005-12-13 Jay Monkman <jtm@smoothsmoothie.com>
+ *             Found and corrected problems in the write path
+ *
+ *  2005-12-30 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             The event handling rewritten right way in softirq.
+ *             Added many ugly hacks and delays to overcome SDHC
+ *             deficiencies
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef  DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/protocol.h>
+#include <linux/delay.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/imx-dma.h>
+
+#include "imxmmc.h"
+
+#define DRIVER_NAME "imx-mmc"
+
+#define IMXMCI_INT_MASK_DEFAULT (INT_MASK_BUF_READY | INT_MASK_DATA_TRAN | \
+	              INT_MASK_WRITE_OP_DONE | INT_MASK_END_CMD_RES | \
+		      INT_MASK_AUTO_CARD_DETECT | INT_MASK_DAT0_EN | INT_MASK_SDIO)
+
+struct imxmci_host {
+	struct mmc_host		*mmc;
+	spinlock_t		lock;
+	struct resource		*res;
+	int			irq;
+	imx_dmach_t		dma;
+	unsigned int		clkrt;
+	unsigned int		cmdat;
+	volatile unsigned int	imask;
+	unsigned int		power_mode;
+	unsigned int		present;
+	struct imxmmc_platform_data *pdata;
+
+	struct mmc_request	*req;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	struct timer_list	timer;
+	struct tasklet_struct	tasklet;
+	unsigned int		status_reg;
+	unsigned long		pending_events;
+	/* Next to fields are there for CPU driven transfers to overcome SDHC deficiencies */
+	u16			*data_ptr;
+	unsigned int		data_cnt;
+	atomic_t		stuck_timeout;
+
+	unsigned int		dma_nents;
+	unsigned int		dma_size;
+	unsigned int		dma_dir;
+	int			dma_allocated;
+
+	unsigned char		actual_bus_width;
+};
+
+#define IMXMCI_PEND_IRQ_b	0
+#define IMXMCI_PEND_DMA_END_b	1
+#define IMXMCI_PEND_DMA_ERR_b	2
+#define IMXMCI_PEND_WAIT_RESP_b	3
+#define IMXMCI_PEND_DMA_DATA_b	4
+#define IMXMCI_PEND_CPU_DATA_b	5
+#define IMXMCI_PEND_CARD_XCHG_b	6
+#define IMXMCI_PEND_SET_INIT_b	7
+
+#define IMXMCI_PEND_IRQ_m	(1 << IMXMCI_PEND_IRQ_b)
+#define IMXMCI_PEND_DMA_END_m	(1 << IMXMCI_PEND_DMA_END_b)
+#define IMXMCI_PEND_DMA_ERR_m	(1 << IMXMCI_PEND_DMA_ERR_b)
+#define IMXMCI_PEND_WAIT_RESP_m	(1 << IMXMCI_PEND_WAIT_RESP_b)
+#define IMXMCI_PEND_DMA_DATA_m	(1 << IMXMCI_PEND_DMA_DATA_b)
+#define IMXMCI_PEND_CPU_DATA_m	(1 << IMXMCI_PEND_CPU_DATA_b)
+#define IMXMCI_PEND_CARD_XCHG_m	(1 << IMXMCI_PEND_CARD_XCHG_b)
+#define IMXMCI_PEND_SET_INIT_m	(1 << IMXMCI_PEND_SET_INIT_b)
+
+static void imxmci_stop_clock(struct imxmci_host *host)
+{
+	int i = 0;
+	MMC_STR_STP_CLK &= ~STR_STP_CLK_START_CLK;
+	while(i < 0x1000) {
+	        if(!(i & 0x7f))
+			MMC_STR_STP_CLK |= STR_STP_CLK_STOP_CLK;
+
+		if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)) {
+			/* Check twice before cut */
+			if(!(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN))
+				return;
+		}
+
+		i++;
+	}
+	dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
+}
+
+static void imxmci_start_clock(struct imxmci_host *host)
+{
+	int i = 0;
+	MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
+	while(i < 0x1000) {
+	        if(!(i & 0x7f))
+			MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+		if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) {
+			/* Check twice before cut */
+			if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+				return;
+		}
+
+		i++;
+	}
+	dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+}
+
+static void imxmci_softreset(void)
+{
+	/* reset sequence */
+	MMC_STR_STP_CLK = 0x8;
+	MMC_STR_STP_CLK = 0xD;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+	MMC_STR_STP_CLK = 0x5;
+
+	MMC_RES_TO = 0xff;
+	MMC_BLK_LEN = 512;
+	MMC_NOB = 1;
+}
+
+static int imxmci_busy_wait_for_status(struct imxmci_host *host,
+			unsigned int *pstat, unsigned int stat_mask,
+			int timeout, const char *where)
+{
+	int loops=0;
+	while(!(*pstat & stat_mask)) {
+		loops+=2;
+		if(loops >= timeout) {
+			dev_dbg(mmc_dev(host->mmc), "busy wait timeout in %s, STATUS = 0x%x (0x%x)\n",
+				where, *pstat, stat_mask);
+			return -1;
+		}
+		udelay(2);
+		*pstat |= MMC_STATUS;
+	}
+	if(!loops)
+		return 0;
+
+	dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n",
+		loops, where, *pstat, stat_mask);
+	return loops;
+}
+
+static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
+{
+	unsigned int nob = data->blocks;
+	unsigned int blksz = 1 << data->blksz_bits;
+	unsigned int datasz = nob * blksz;
+	int i;
+
+	if (data->flags & MMC_DATA_STREAM)
+		nob = 0xffff;
+
+	host->data = data;
+	data->bytes_xfered = 0;
+
+	MMC_NOB = nob;
+	MMC_BLK_LEN = blksz;
+
+	/*
+	 * DMA cannot be used for small block sizes, we have to use CPU driven transfers otherwise.
+	 * We are in big troubles for non-512 byte transfers according to note in the paragraph
+	 * 20.6.7 of User Manual anyway, but we need to be able to transfer SCR at least.
+	 * The situation is even more complex in reality. The SDHC in not able to handle wll
+	 * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
+	 * This is required for SCR read at least.
+	 */
+	if (datasz < 64) {
+		host->dma_size = datasz;
+		if (data->flags & MMC_DATA_READ) {
+			host->dma_dir = DMA_FROM_DEVICE;
+
+			/* Hack to enable read SCR */
+			if(datasz < 16) {
+				MMC_NOB = 1;
+				MMC_BLK_LEN = 16;
+			}
+		} else {
+			host->dma_dir = DMA_TO_DEVICE;
+		}
+
+		/* Convert back to virtual address */
+		host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset);
+		host->data_cnt = 0;
+
+		clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+		set_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+		return;
+	}
+
+	if (data->flags & MMC_DATA_READ) {
+		host->dma_dir = DMA_FROM_DEVICE;
+		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+						data->sg_len,  host->dma_dir);
+
+		imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+			host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_READ);
+
+		/*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_READ, IMX_DMA_WIDTH_16, CCR_REN);*/
+		CCR(host->dma) = CCR_DMOD_LINEAR | CCR_DSIZ_32 | CCR_SMOD_FIFO | CCR_SSIZ_16 | CCR_REN;
+	} else {
+		host->dma_dir = DMA_TO_DEVICE;
+
+		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+						data->sg_len,  host->dma_dir);
+
+		imx_dma_setup_sg(host->dma, data->sg, data->sg_len, datasz,
+			host->res->start + MMC_BUFFER_ACCESS_OFS, DMA_MODE_WRITE);
+
+		/*imx_dma_setup_mem2dev_ccr(host->dma, DMA_MODE_WRITE, IMX_DMA_WIDTH_16, CCR_REN);*/
+		CCR(host->dma) = CCR_SMOD_LINEAR | CCR_SSIZ_32 | CCR_DMOD_FIFO | CCR_DSIZ_16 | CCR_REN;
+	}
+
+#if 1	/* This code is there only for consistency checking and can be disabled in future */
+	host->dma_size = 0;
+	for(i=0; i<host->dma_nents; i++)
+		host->dma_size+=data->sg[i].length;
+
+	if (datasz > host->dma_size) {
+		dev_err(mmc_dev(host->mmc), "imxmci_setup_data datasz 0x%x > 0x%x dm_size\n",
+		       datasz, host->dma_size);
+	}
+#endif
+
+	host->dma_size = datasz;
+
+	wmb();
+
+	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+		BLR(host->dma) = 0;	/* burst 64 byte read / 64 bytes write */
+	else
+		BLR(host->dma) = 16;	/* burst 16 byte read / 16 bytes write */
+
+	RSSR(host->dma) = DMA_REQ_SDHC;
+
+	set_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events);
+	clear_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events);
+
+	/* start DMA engine for read, write is delayed after initial response */
+	if (host->dma_dir == DMA_FROM_DEVICE) {
+		imx_dma_enable(host->dma);
+	}
+}
+
+static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat)
+{
+	unsigned long flags;
+	u32 imask;
+
+	WARN_ON(host->cmd != NULL);
+	host->cmd = cmd;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		cmdat |= CMD_DAT_CONT_BUSY;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_R1: /* short CRC, OPCODE */
+	case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1;
+		break;
+	case MMC_RSP_R2: /* long 136 bit + CRC */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2;
+		break;
+	case MMC_RSP_R3: /* short */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3;
+		break;
+	case MMC_RSP_R6: /* short CRC */
+		cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R6;
+		break;
+	default:
+		break;
+	}
+
+	if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) )
+		cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */
+
+	if ( host->actual_bus_width == MMC_BUS_WIDTH_4 )
+		cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+
+	MMC_CMD = cmd->opcode;
+	MMC_ARGH = cmd->arg >> 16;
+	MMC_ARGL = cmd->arg & 0xffff;
+	MMC_CMD_DAT_CONT = cmdat;
+
+	atomic_set(&host->stuck_timeout, 0);
+	set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events);
+
+
+	imask = IMXMCI_INT_MASK_DEFAULT;
+	imask &= ~INT_MASK_END_CMD_RES;
+	if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) {
+		/*imask &= ~INT_MASK_BUF_READY;*/
+		imask &= ~INT_MASK_DATA_TRAN;
+		if ( cmdat & CMD_DAT_CONT_WRITE )
+			imask &= ~INT_MASK_WRITE_OP_DONE;
+		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events))
+			imask &= ~INT_MASK_BUF_READY;
+	}
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->imask = imask;
+	MMC_INT_MASK = host->imask;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n",
+		cmd->opcode, cmd->opcode, imask);
+
+	imxmci_start_clock(host);
+}
+
+static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m |
+			IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m);
+
+	host->imask = IMXMCI_INT_MASK_DEFAULT;
+	MMC_INT_MASK = host->imask;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	host->req = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+	mmc_request_done(host->mmc, req);
+}
+
+static int imxmci_finish_data(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_data *data = host->data;
+	int data_error;
+
+	if(test_and_clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)){
+		imx_dma_disable(host->dma);
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+			     host->dma_dir);
+	}
+
+	if ( stat & STATUS_ERR_MASK ) {
+		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",stat);
+		if(stat & (STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR))
+			data->error = MMC_ERR_BADCRC;
+		else if(stat & STATUS_TIME_OUT_READ)
+			data->error = MMC_ERR_TIMEOUT;
+		else
+			data->error = MMC_ERR_FAILED;
+	} else {
+		data->bytes_xfered = host->dma_size;
+	}
+
+	data_error = data->error;
+
+	host->data = NULL;
+
+	return data_error;
+}
+
+static int imxmci_cmd_done(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_command *cmd = host->cmd;
+	int i;
+	u32 a,b,c;
+	struct mmc_data *data = host->data;
+
+	if (!cmd)
+		return 0;
+
+	host->cmd = NULL;
+
+	if (stat & STATUS_TIME_OUT_RESP) {
+		dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+		cmd->error = MMC_ERR_TIMEOUT;
+	} else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+		dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+		cmd->error = MMC_ERR_BADCRC;
+	}
+
+	if(cmd->flags & MMC_RSP_PRESENT) {
+		if(cmd->flags & MMC_RSP_136) {
+			for (i = 0; i < 4; i++) {
+				u32 a = MMC_RES_FIFO & 0xffff;
+				u32 b = MMC_RES_FIFO & 0xffff;
+				cmd->resp[i] = a<<16 | b;
+			}
+		} else {
+			a = MMC_RES_FIFO & 0xffff;
+			b = MMC_RES_FIFO & 0xffff;
+			c = MMC_RES_FIFO & 0xffff;
+			cmd->resp[0] = a<<24 | b<<8 | c>>8;
+		}
+	}
+
+	dev_dbg(mmc_dev(host->mmc), "RESP 0x%08x, 0x%08x, 0x%08x, 0x%08x, error %d\n",
+		cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3], cmd->error);
+
+	if (data && (cmd->error == MMC_ERR_NONE) && !(stat & STATUS_ERR_MASK)) {
+		if (host->req->data->flags & MMC_DATA_WRITE) {
+
+			/* Wait for FIFO to be empty before starting DMA write */
+
+			stat = MMC_STATUS;
+			if(imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FE,
+				40, "imxmci_cmd_done DMA WR") < 0) {
+				cmd->error = MMC_ERR_FIFO;
+				imxmci_finish_data(host, stat);
+				if(host->req)
+					imxmci_finish_request(host, host->req);
+				dev_warn(mmc_dev(host->mmc), "STATUS = 0x%04x\n",
+				       stat);
+				return 0;
+			}
+
+			if(test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+				imx_dma_enable(host->dma);
+			}
+		}
+	} else {
+		struct mmc_request *req;
+		imxmci_stop_clock(host);
+		req = host->req;
+
+		if(data)
+			imxmci_finish_data(host, stat);
+
+		if( req ) {
+			imxmci_finish_request(host, req);
+		} else {
+			dev_warn(mmc_dev(host->mmc), "imxmci_cmd_done: no request to finish\n");
+		}
+	}
+
+	return 1;
+}
+
+static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
+{
+	struct mmc_data *data = host->data;
+	int data_error;
+
+	if (!data)
+		return 0;
+
+	data_error = imxmci_finish_data(host, stat);
+
+	if (host->req->stop && (data_error == MMC_ERR_NONE)) {
+		imxmci_stop_clock(host);
+		imxmci_start_cmd(host, host->req->stop, 0);
+	} else {
+		struct mmc_request *req;
+		req = host->req;
+		if( req ) {
+			imxmci_finish_request(host, req);
+		} else {
+			dev_warn(mmc_dev(host->mmc), "imxmci_data_done: no request to finish\n");
+		}
+	}
+
+	return 1;
+}
+
+static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat)
+{
+	int i;
+	int burst_len;
+	int flush_len;
+	int trans_done = 0;
+	unsigned int stat = *pstat;
+
+	if(host->actual_bus_width == MMC_BUS_WIDTH_4)
+		burst_len = 16;
+	else
+		burst_len = 64;
+
+	/* This is unfortunately required */
+	dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
+		stat);
+
+	if(host->dma_dir == DMA_FROM_DEVICE) {
+		imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
+				20, "imxmci_cpu_driven_data read");
+
+		while((stat & (STATUS_APPL_BUFF_FF |  STATUS_DATA_TRANS_DONE)) &&
+		      (host->data_cnt < host->dma_size)) {
+			if(burst_len >= host->dma_size - host->data_cnt) {
+				flush_len = burst_len;
+				burst_len = host->dma_size - host->data_cnt;
+				flush_len -= burst_len;
+				host->data_cnt = host->dma_size;
+				trans_done = 1;
+			} else {
+				flush_len = 0;
+				host->data_cnt += burst_len;
+			}
+
+			for(i = burst_len; i>=2 ; i-=2) {
+				*(host->data_ptr++) = MMC_BUFFER_ACCESS;
+				udelay(20);	/* required for clocks < 8MHz*/
+			}
+
+			if(i == 1)
+				*(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
+
+			stat = MMC_STATUS;
+
+			/* Flush extra bytes from FIFO */
+			while(flush_len >= 2){
+				flush_len -= 2;
+				i = MMC_BUFFER_ACCESS;
+				stat = MMC_STATUS;
+				stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
+			}
+
+			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
+				burst_len, stat);
+		}
+	} else {
+		imxmci_busy_wait_for_status(host, &stat,
+				STATUS_APPL_BUFF_FE,
+				20, "imxmci_cpu_driven_data write");
+
+		while((stat & STATUS_APPL_BUFF_FE) &&
+		      (host->data_cnt < host->dma_size)) {
+			if(burst_len >= host->dma_size - host->data_cnt) {
+				burst_len = host->dma_size - host->data_cnt;
+				host->data_cnt = host->dma_size;
+				trans_done = 1;
+			} else {
+				host->data_cnt += burst_len;
+			}
+
+			for(i = burst_len; i>0 ; i-=2)
+				MMC_BUFFER_ACCESS = *(host->data_ptr++);
+
+			stat = MMC_STATUS;
+
+			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data write burst %d STATUS = 0x%x\n",
+				burst_len, stat);
+		}
+	}
+
+	*pstat = stat;
+
+	return trans_done;
+}
+
+static void imxmci_dma_irq(int dma, void *devid, struct pt_regs *regs)
+{
+	struct imxmci_host *host = devid;
+	uint32_t stat = MMC_STATUS;
+
+	atomic_set(&host->stuck_timeout, 0);
+	host->status_reg = stat;
+	set_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+	tasklet_schedule(&host->tasklet);
+}
+
+static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct imxmci_host *host = devid;
+	uint32_t stat = MMC_STATUS;
+	int handled = 1;
+
+	MMC_INT_MASK = host->imask | INT_MASK_SDIO | INT_MASK_AUTO_CARD_DETECT;
+
+	atomic_set(&host->stuck_timeout, 0);
+	host->status_reg = stat;
+	set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+	tasklet_schedule(&host->tasklet);
+
+	return IRQ_RETVAL(handled);;
+}
+
+static void imxmci_tasklet_fnc(unsigned long data)
+{
+	struct imxmci_host *host = (struct imxmci_host *)data;
+	u32 stat;
+	unsigned int data_dir_mask = 0;	/* STATUS_WR_CRC_ERROR_CODE_MASK */
+	int timeout = 0;
+
+	if(atomic_read(&host->stuck_timeout) > 4) {
+		char *what;
+		timeout = 1;
+		stat = MMC_STATUS;
+		host->status_reg = stat;
+		if (test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+				what = "RESP+DMA";
+			else
+				what = "RESP";
+		else
+			if (test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events))
+				if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events))
+					what = "DATA";
+				else
+					what = "DMA";
+			else
+				what = "???";
+
+		dev_err(mmc_dev(host->mmc), "%s TIMEOUT, hardware stucked STATUS = 0x%04x IMASK = 0x%04x\n",
+		       what, stat, MMC_INT_MASK);
+		dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
+		       MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
+		dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n",
+		       host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size);
+	}
+
+	if(!host->present || timeout)
+		host->status_reg = STATUS_TIME_OUT_RESP | STATUS_TIME_OUT_READ |
+				    STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR;
+
+	if(test_bit(IMXMCI_PEND_IRQ_b, &host->pending_events) || timeout) {
+		clear_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+
+		stat = MMC_STATUS;
+		/*
+		 * This is not required in theory, but there is chance to miss some flag
+		 * which clears automatically by mask write, FreeScale original code keeps
+		 * stat from IRQ time so do I
+		 */
+		stat |= host->status_reg;
+
+		if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+			imxmci_busy_wait_for_status(host, &stat,
+					STATUS_END_CMD_RESP | STATUS_ERR_MASK,
+					20, "imxmci_tasklet_fnc resp (ERRATUM #4)");
+		}
+
+		if(stat & (STATUS_END_CMD_RESP | STATUS_ERR_MASK)) {
+			if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+				imxmci_cmd_done(host, stat);
+			if(host->data && (stat & STATUS_ERR_MASK))
+				imxmci_data_done(host, stat);
+		}
+
+		if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) {
+			stat |= MMC_STATUS;
+			if(imxmci_cpu_driven_data(host, &stat)){
+				if(test_and_clear_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events))
+					imxmci_cmd_done(host, stat);
+				atomic_clear_mask(IMXMCI_PEND_IRQ_m|IMXMCI_PEND_CPU_DATA_m,
+							&host->pending_events);
+				imxmci_data_done(host, stat);
+			}
+		}
+	}
+
+	if(test_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events) &&
+	   !test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events)) {
+
+		stat = MMC_STATUS;
+		/* Same as above */
+		stat |= host->status_reg;
+
+		if(host->dma_dir == DMA_TO_DEVICE) {
+			data_dir_mask = STATUS_WRITE_OP_DONE;
+		} else {
+			data_dir_mask = STATUS_DATA_TRANS_DONE;
+		}
+
+		imxmci_busy_wait_for_status(host, &stat,
+				data_dir_mask,
+				50, "imxmci_tasklet_fnc data");
+
+		if(stat & data_dir_mask) {
+			clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events);
+			imxmci_data_done(host, stat);
+		}
+	}
+
+	if(test_and_clear_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events)) {
+
+		if(host->cmd)
+			imxmci_cmd_done(host, STATUS_TIME_OUT_RESP);
+
+		if(host->data)
+			imxmci_data_done(host, STATUS_TIME_OUT_READ |
+					 STATUS_CRC_READ_ERR | STATUS_CRC_WRITE_ERR);
+
+		if(host->req)
+			imxmci_finish_request(host, host->req);
+
+		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+
+	}
+}
+
+static void imxmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+	struct imxmci_host *host = mmc_priv(mmc);
+	unsigned int cmdat;
+
+	WARN_ON(host->req != NULL);
+
+	host->req = req;
+
+	cmdat = 0;
+
+	if (req->data) {
+		imxmci_setup_data(host, req->data);
+
+		cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+		if (req->data->flags & MMC_DATA_WRITE)
+			cmdat |= CMD_DAT_CONT_WRITE;
+
+		if (req->data->flags & MMC_DATA_STREAM) {
+			cmdat |= CMD_DAT_CONT_STREAM_BLOCK;
+		}
+	}
+
+	imxmci_start_cmd(host, req->cmd, cmdat);
+}
+
+#define CLK_RATE 19200000
+
+static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct imxmci_host *host = mmc_priv(mmc);
+	int prescaler;
+
+	dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n",
+		ios->clock, ios->power_mode, ios->vdd,
+		(ios->bus_width==MMC_BUS_WIDTH_4)?4:1);
+
+	if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
+		host->actual_bus_width = MMC_BUS_WIDTH_4;
+		imx_gpio_mode(PB11_PF_SD_DAT3);
+	}else{
+		host->actual_bus_width = MMC_BUS_WIDTH_1;
+		imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+	}
+
+	if ( host->power_mode != ios->power_mode ) {
+		switch (ios->power_mode) {
+		case MMC_POWER_OFF:
+        		break;
+		case MMC_POWER_UP:
+			set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+        		break;
+		case MMC_POWER_ON:
+        		break;
+		}
+		host->power_mode = ios->power_mode;
+	}
+
+	if ( ios->clock ) {
+		unsigned int clk;
+
+		/* The prescaler is 5 for PERCLK2 equal to 96MHz
+		 * then 96MHz / 5 = 19.2 MHz
+		 */
+		clk=imx_get_perclk2();
+		prescaler=(clk+(CLK_RATE*7)/8)/CLK_RATE;
+		switch(prescaler) {
+		case 0:
+		case 1:	prescaler = 0;
+			break;
+		case 2:	prescaler = 1;
+			break;
+		case 3:	prescaler = 2;
+			break;
+		case 4:	prescaler = 4;
+			break;
+		default:
+		case 5:	prescaler = 5;
+			break;
+		}
+
+		dev_dbg(mmc_dev(host->mmc), "PERCLK2 %d MHz -> prescaler %d\n",
+			clk, prescaler);
+
+		for(clk=0; clk<8; clk++) {
+			int x;
+			x = CLK_RATE / (1<<clk);
+			if( x <= ios->clock)
+				break;
+		}
+
+		MMC_STR_STP_CLK |= STR_STP_CLK_ENABLE; /* enable controller */
+
+		imxmci_stop_clock(host);
+		MMC_CLK_RATE = (prescaler<<3) | clk;
+		imxmci_start_clock(host);
+
+		dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE);
+	} else {
+		imxmci_stop_clock(host);
+	}
+}
+
+static struct mmc_host_ops imxmci_ops = {
+	.request	= imxmci_request,
+	.set_ios	= imxmci_set_ios,
+};
+
+static struct resource *platform_device_resource(struct platform_device *dev, unsigned int mask, int nr)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++)
+		if (dev->resource[i].flags == mask && nr-- == 0)
+			return &dev->resource[i];
+	return NULL;
+}
+
+static int platform_device_irq(struct platform_device *dev, int nr)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++)
+		if (dev->resource[i].flags == IORESOURCE_IRQ && nr-- == 0)
+			return dev->resource[i].start;
+	return NO_IRQ;
+}
+
+static void imxmci_check_status(unsigned long data)
+{
+	struct imxmci_host *host = (struct imxmci_host *)data;
+
+	if( host->pdata->card_present() != host->present ) {
+		host->present ^= 1;
+		dev_info(mmc_dev(host->mmc), "card %s\n",
+		      host->present ? "inserted" : "removed");
+
+		set_bit(IMXMCI_PEND_CARD_XCHG_b, &host->pending_events);
+		tasklet_schedule(&host->tasklet);
+	}
+
+	if(test_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events) ||
+	   test_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events)) {
+		atomic_inc(&host->stuck_timeout);
+		if(atomic_read(&host->stuck_timeout) > 4)
+			tasklet_schedule(&host->tasklet);
+	} else {
+		atomic_set(&host->stuck_timeout, 0);
+
+	}
+
+	mod_timer(&host->timer, jiffies + (HZ>>1));
+}
+
+static int imxmci_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct imxmci_host *host = NULL;
+	struct resource *r;
+	int ret = 0, irq;
+
+	printk(KERN_INFO "i.MX mmc driver\n");
+
+	r = platform_device_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_device_irq(pdev, 0);
+	if (!r || irq == NO_IRQ)
+		return -ENXIO;
+
+	r = request_mem_region(r->start, 0x100, "IMXMCI");
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct imxmci_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mmc->ops = &imxmci_ops;
+	mmc->f_min = 150000;
+	mmc->f_max = CLK_RATE/2;
+	mmc->ocr_avail = MMC_VDD_32_33;
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+	/* MMC core transfer sizes tunable parameters */
+	mmc->max_hw_segs = 64;
+	mmc->max_phys_segs = 64;
+	mmc->max_sectors = 64;		/* default 1 << (PAGE_CACHE_SHIFT - 9) */
+	mmc->max_seg_size = 64*512;	/* default PAGE_CACHE_SIZE */
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dma_allocated = 0;
+	host->pdata = pdev->dev.platform_data;
+
+	spin_lock_init(&host->lock);
+	host->res = r;
+	host->irq = irq;
+
+	imx_gpio_mode(PB8_PF_SD_DAT0);
+	imx_gpio_mode(PB9_PF_SD_DAT1);
+	imx_gpio_mode(PB10_PF_SD_DAT2);
+	/* Configured as GPIO with pull-up to ensure right MCC card mode */
+	/* Switched to PB11_PF_SD_DAT3 if 4 bit bus is configured */
+	imx_gpio_mode(GPIO_PORTB | GPIO_IN | GPIO_PUEN | 11);
+	/* imx_gpio_mode(PB11_PF_SD_DAT3); */
+	imx_gpio_mode(PB12_PF_SD_CLK);
+	imx_gpio_mode(PB13_PF_SD_CMD);
+
+	imxmci_softreset();
+
+	if ( MMC_REV_NO != 0x390 ) {
+		dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+		        MMC_REV_NO);
+		goto out;
+	}
+
+	MMC_READ_TO = 0x2db4; /* recommended in data sheet */
+
+	host->imask = IMXMCI_INT_MASK_DEFAULT;
+	MMC_INT_MASK = host->imask;
+
+
+	if(imx_dma_request_by_prio(&host->dma, DRIVER_NAME, DMA_PRIO_LOW)<0){
+		dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+		ret = -EBUSY;
+		goto out;
+	}
+	host->dma_allocated=1;
+	imx_dma_setup_handlers(host->dma, imxmci_dma_irq, NULL, host);
+
+	tasklet_init(&host->tasklet, imxmci_tasklet_fnc, (unsigned long)host);
+	host->status_reg=0;
+	host->pending_events=0;
+
+	ret = request_irq(host->irq, imxmci_irq, 0, DRIVER_NAME, host);
+	if (ret)
+		goto out;
+
+	host->present = host->pdata->card_present();
+	init_timer(&host->timer);
+	host->timer.data = (unsigned long)host;
+	host->timer.function = imxmci_check_status;
+	add_timer(&host->timer);
+	mod_timer(&host->timer, jiffies + (HZ>>1));
+
+	platform_set_drvdata(pdev, mmc);
+
+	mmc_add_host(mmc);
+
+	return 0;
+
+out:
+	if (host) {
+		if(host->dma_allocated){
+			imx_dma_free(host->dma);
+			host->dma_allocated=0;
+		}
+	}
+	if (mmc)
+		mmc_free_host(mmc);
+	release_resource(r);
+	return ret;
+}
+
+static int imxmci_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (mmc) {
+		struct imxmci_host *host = mmc_priv(mmc);
+
+		tasklet_disable(&host->tasklet);
+
+		del_timer_sync(&host->timer);
+		mmc_remove_host(mmc);
+
+		free_irq(host->irq, host);
+		if(host->dma_allocated){
+			imx_dma_free(host->dma);
+			host->dma_allocated=0;
+		}
+
+		tasklet_kill(&host->tasklet);
+
+		release_resource(host->res);
+
+		mmc_free_host(mmc);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int imxmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+	int ret = 0;
+
+	if (mmc)
+		ret = mmc_suspend_host(mmc, state);
+
+	return ret;
+}
+
+static int imxmci_resume(struct platform_device *dev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(dev);
+	struct imxmci_host *host;
+	int ret = 0;
+
+	if (mmc) {
+		host = mmc_priv(mmc);
+		if(host)
+			set_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events);
+		ret = mmc_resume_host(mmc);
+	}
+
+	return ret;
+}
+#else
+#define imxmci_suspend  NULL
+#define imxmci_resume   NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver imxmci_driver = {
+	.probe		= imxmci_probe,
+	.remove		= imxmci_remove,
+	.suspend	= imxmci_suspend,
+	.resume		= imxmci_resume,
+	.driver		= {
+		.name		= DRIVER_NAME,
+	}
+};
+
+static int __init imxmci_init(void)
+{
+	return platform_driver_register(&imxmci_driver);
+}
+
+static void __exit imxmci_exit(void)
+{
+	platform_driver_unregister(&imxmci_driver);
+}
+
+module_init(imxmci_init);
+module_exit(imxmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/imxmmc.h
new file mode 100644
index 0000000..e5339e3
--- /dev/null
+++ b/drivers/mmc/imxmmc.h
@@ -0,0 +1,67 @@
+
+# define __REG16(x)	(*((volatile u16 *)IO_ADDRESS(x)))
+
+#define MMC_STR_STP_CLK  __REG16(IMX_MMC_BASE + 0x00)
+#define MMC_STATUS       __REG16(IMX_MMC_BASE + 0x04)
+#define MMC_CLK_RATE     __REG16(IMX_MMC_BASE + 0x08)
+#define MMC_CMD_DAT_CONT __REG16(IMX_MMC_BASE + 0x0C)
+#define MMC_RES_TO       __REG16(IMX_MMC_BASE + 0x10)
+#define MMC_READ_TO      __REG16(IMX_MMC_BASE + 0x14)
+#define MMC_BLK_LEN      __REG16(IMX_MMC_BASE + 0x18)
+#define MMC_NOB          __REG16(IMX_MMC_BASE + 0x1C)
+#define MMC_REV_NO       __REG16(IMX_MMC_BASE + 0x20)
+#define MMC_INT_MASK     __REG16(IMX_MMC_BASE + 0x24)
+#define MMC_CMD          __REG16(IMX_MMC_BASE + 0x28)
+#define MMC_ARGH         __REG16(IMX_MMC_BASE + 0x2C)
+#define MMC_ARGL         __REG16(IMX_MMC_BASE + 0x30)
+#define MMC_RES_FIFO     __REG16(IMX_MMC_BASE + 0x34)
+#define MMC_BUFFER_ACCESS __REG16(IMX_MMC_BASE + 0x38)
+#define MMC_BUFFER_ACCESS_OFS 0x38
+
+
+#define STR_STP_CLK_ENDIAN              (1<<5)
+#define STR_STP_CLK_RESET               (1<<3)
+#define STR_STP_CLK_ENABLE              (1<<2)
+#define STR_STP_CLK_START_CLK           (1<<1)
+#define STR_STP_CLK_STOP_CLK            (1<<0)
+#define STATUS_CARD_PRESENCE            (1<<15)
+#define STATUS_SDIO_INT_ACTIVE          (1<<14)
+#define STATUS_END_CMD_RESP             (1<<13)
+#define STATUS_WRITE_OP_DONE            (1<<12)
+#define STATUS_DATA_TRANS_DONE          (1<<11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK   (3<<10)
+#define STATUS_CARD_BUS_CLK_RUN         (1<<8)
+#define STATUS_APPL_BUFF_FF             (1<<7)
+#define STATUS_APPL_BUFF_FE             (1<<6)
+#define STATUS_RESP_CRC_ERR             (1<<5)
+#define STATUS_CRC_READ_ERR             (1<<3)
+#define STATUS_CRC_WRITE_ERR            (1<<2)
+#define STATUS_TIME_OUT_RESP            (1<<1)
+#define STATUS_TIME_OUT_READ            (1<<0)
+#define STATUS_ERR_MASK                 0x2f
+#define CLK_RATE_PRESCALER(x)           ((x) & 0x7)
+#define CLK_RATE_CLK_RATE(x)            (((x) & 0x7) << 3)
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF  (1<<12)
+#define CMD_DAT_CONT_STOP_READWAIT      (1<<11)
+#define CMD_DAT_CONT_START_READWAIT     (1<<10)
+#define CMD_DAT_CONT_BUS_WIDTH_1        (0<<8)
+#define CMD_DAT_CONT_BUS_WIDTH_4        (2<<8)
+#define CMD_DAT_CONT_INIT               (1<<7)
+#define CMD_DAT_CONT_BUSY               (1<<6)
+#define CMD_DAT_CONT_STREAM_BLOCK       (1<<5)
+#define CMD_DAT_CONT_WRITE              (1<<4)
+#define CMD_DAT_CONT_DATA_ENABLE        (1<<3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R1 (1)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R2 (2)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R3 (3)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R4 (4)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R5 (5)
+#define CMD_DAT_CONT_RESPONSE_FORMAT_R6 (6)
+#define INT_MASK_AUTO_CARD_DETECT       (1<<6)
+#define INT_MASK_DAT0_EN                (1<<5)
+#define INT_MASK_SDIO                   (1<<4)
+#define INT_MASK_BUF_READY              (1<<3)
+#define INT_MASK_END_CMD_RES            (1<<2)
+#define INT_MASK_WRITE_OP_DONE          (1<<1)
+#define INT_MASK_DATA_TRAN              (1<<0)
+#define INT_ALL                         (0x7f)
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index eb9a882..eb42cb3 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -65,11 +65,6 @@
 	unsigned int		dma_dir;
 };
 
-static inline unsigned int ns_to_clocks(unsigned int ns)
-{
-	return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
-}
-
 static void pxamci_stop_clock(struct pxamci_host *host)
 {
 	if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -113,6 +108,7 @@
 static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
+	unsigned long long clks;
 	unsigned int timeout;
 	u32 dcmd;
 	int i;
@@ -125,7 +121,9 @@
 	writel(nob, host->base + MMC_NOB);
 	writel(1 << data->blksz_bits, host->base + MMC_BLKLEN);
 
-	timeout = ns_to_clocks(data->timeout_ns) + data->timeout_clks;
+	clks = (unsigned long long)data->timeout_ns * CLOCKRATE;
+	do_div(clks, 1000000000UL);
+	timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
 	writel((timeout + 255) / 256, host->base + MMC_RDTO);
 
 	if (data->flags & MMC_DATA_READ) {
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 0f6bb2e..a7ec595 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -200,27 +200,6 @@
 	  provides support for one of those command sets, used on chips
 	  including the AMD Am29LV320.
 
-config MTD_CFI_AMDSTD_RETRY
-	int "Retry failed commands (erase/program)"
-	depends on MTD_CFI_AMDSTD
-	default "0"
-	help
-	  Some chips, when attached to a shared bus, don't properly filter
-	  bus traffic that is destined to other devices.  This broken
-	  behavior causes erase and program sequences to be aborted when
-	  the sequences are mixed with traffic for other devices.
-
-	  SST49LF040 (and related) chips are know to be broken.
-
-config MTD_CFI_AMDSTD_RETRY_MAX
-	int "Max retries of failed commands (erase/program)"
-	depends on MTD_CFI_AMDSTD_RETRY
-	default "0"
-	help
-	  If you have an SST49LF040 (or related chip) then this value should
-	  be set to at least 1.  This can also be adjusted at driver load
-	  time with the retry_cmd_max module parameter.
-
 config MTD_CFI_STAA
 	tristate "Support for ST (Advanced Architecture) flash chips"
 	depends on MTD_GEN_PROBE
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index dd628cb..7fac438 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -129,8 +129,8 @@
 	  allocating space from Linux's available memory. Otherwise, leave
 	  this set to zero. Most people will want to leave this as zero.
 
-config MTD_BLKMTD
-	tristate "MTD emulation using block device"
+config MTD_BLOCK2MTD
+	tristate "MTD using block device"
 	depends on MTD
 	help
 	  This driver allows a block device to appear as an MTD. It would
@@ -141,15 +141,6 @@
 	  Testing MTD users (eg JFFS2) on large media and media that might
 	  be removed during a write (using the floppy drive).
 
-config MTD_BLOCK2MTD
-	tristate "MTD using block device (rewrite)"
-	depends on MTD && EXPERIMENTAL
-	help
-	  This driver is basically the same at MTD_BLKMTD above, but
-	  experienced some interface changes plus serious speedups.  In
-	  the long term, it should replace MTD_BLKMTD.  Right now, you
-	  shouldn't entrust important data to it yet.
-
 comment "Disk-On-Chip Device Drivers"
 
 config MTD_DOC2000
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 7c5ed21..b657367 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -21,7 +21,6 @@
 obj-$(CONFIG_MTD_MS02NV)	+= ms02-nv.o
 obj-$(CONFIG_MTD_MTDRAM)	+= mtdram.o
 obj-$(CONFIG_MTD_LART)		+= lart.o
-obj-$(CONFIG_MTD_BLKMTD)	+= blkmtd.o
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
deleted file mode 100644
index 79f2e1f..0000000
--- a/drivers/mtd/devices/blkmtd.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/*
- * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $
- *
- * blkmtd.c - use a block device as a fake MTD
- *
- * Author: Simon Evans <spse@secret.org.uk>
- *
- * Copyright (C) 2001,2002 Simon Evans
- *
- * Licence: GPL
- *
- * How it works:
- *	The driver uses raw/io to read/write the device and the page
- *	cache to cache access. Writes update the page cache with the
- *	new data and mark it dirty and add the page into a BIO which
- *	is then written out.
- *
- *	It can be loaded Read-Only to prevent erases and writes to the
- *	medium.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/bio.h>
-#include <linux/pagemap.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/mount.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mutex.h>
-
-#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg)
-#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg)
-
-
-/* Default erase size in K, always make it a multiple of PAGE_SIZE */
-#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10)	/* 128KiB */
-#define VERSION "$Revision: 1.27 $"
-
-/* Info for the block device */
-struct blkmtd_dev {
-	struct list_head list;
-	struct block_device *blkdev;
-	struct mtd_info mtd_info;
-	struct mutex wrbuf_mutex;
-};
-
-
-/* Static info about the MTD, used in cleanup_module */
-static LIST_HEAD(blkmtd_device_list);
-
-
-static void blkmtd_sync(struct mtd_info *mtd);
-
-#define MAX_DEVICES 4
-
-/* Module parameters passed by insmod/modprobe */
-static char *device[MAX_DEVICES];    /* the block device to use */
-static int erasesz[MAX_DEVICES];     /* optional default erase size */
-static int ro[MAX_DEVICES];          /* optional read only flag */
-static int sync;
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
-MODULE_DESCRIPTION("Emulate an MTD using a block device");
-module_param_array(device, charp, NULL, 0);
-MODULE_PARM_DESC(device, "block device to use");
-module_param_array(erasesz, int, NULL, 0);
-MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB.");
-module_param_array(ro, bool, NULL, 0);
-MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors");
-module_param(sync, bool, 0);
-MODULE_PARM_DESC(sync, "1=Synchronous writes");
-
-
-/* completion handler for BIO reads */
-static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
-	if (bio->bi_size)
-		return 1;
-
-	complete((struct completion*)bio->bi_private);
-	return 0;
-}
-
-
-/* completion handler for BIO writes */
-static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error)
-{
-	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-
-	if (bio->bi_size)
-		return 1;
-
-	if(!uptodate)
-		err("bi_write_complete: not uptodate\n");
-
-	do {
-		struct page *page = bvec->bv_page;
-		DEBUG(3, "Cleaning up page %ld\n", page->index);
-		if (--bvec >= bio->bi_io_vec)
-			prefetchw(&bvec->bv_page->flags);
-
-		if (uptodate) {
-			SetPageUptodate(page);
-		} else {
-			ClearPageUptodate(page);
-			SetPageError(page);
-		}
-		clear_page_dirty(page);
-		unlock_page(page);
-		page_cache_release(page);
-	} while (bvec >= bio->bi_io_vec);
-
-	complete((struct completion*)bio->bi_private);
-	return 0;
-}
-
-
-/* read one page from the block device */
-static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page)
-{
-	struct bio *bio;
-	struct completion event;
-	int err = -ENOMEM;
-
-	if(PageUptodate(page)) {
-		DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index);
-		unlock_page(page);
-		return 0;
-	}
-
-	ClearPageUptodate(page);
-	ClearPageError(page);
-
-	bio = bio_alloc(GFP_KERNEL, 1);
-	if(bio) {
-		init_completion(&event);
-		bio->bi_bdev = dev->blkdev;
-		bio->bi_sector = page->index << (PAGE_SHIFT-9);
-		bio->bi_private = &event;
-		bio->bi_end_io = bi_read_complete;
-		if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) {
-			submit_bio(READ_SYNC, bio);
-			wait_for_completion(&event);
-			err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
-			bio_put(bio);
-		}
-	}
-
-	if(err)
-		SetPageError(page);
-	else
-		SetPageUptodate(page);
-	flush_dcache_page(page);
-	unlock_page(page);
-	return err;
-}
-
-
-/* write out the current BIO and wait for it to finish */
-static int blkmtd_write_out(struct bio *bio)
-{
-	struct completion event;
-	int err;
-
-	if(!bio->bi_vcnt) {
-		bio_put(bio);
-		return 0;
-	}
-
-	init_completion(&event);
-	bio->bi_private = &event;
-	bio->bi_end_io = bi_write_complete;
-	submit_bio(WRITE_SYNC, bio);
-	wait_for_completion(&event);
-	DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt);
-	err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO;
-	bio_put(bio);
-	return err;
-}
-
-
-/**
- * blkmtd_add_page - add a page to the current BIO
- * @bio: bio to add to (NULL to alloc initial bio)
- * @blkdev: block device
- * @page: page to add
- * @pagecnt: pages left to add
- *
- * Adds a page to the current bio, allocating it if necessary. If it cannot be
- * added, the current bio is written out and a new one is allocated. Returns
- * the new bio to add or NULL on error
- */
-static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev,
-				   struct page *page, int pagecnt)
-{
-
- retry:
-	if(!bio) {
-		bio = bio_alloc(GFP_KERNEL, pagecnt);
-		if(!bio)
-			return NULL;
-		bio->bi_sector = page->index << (PAGE_SHIFT-9);
-		bio->bi_bdev = blkdev;
-	}
-
-	if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) {
-		blkmtd_write_out(bio);
-		bio = NULL;
-		goto retry;
-	}
-	return bio;
-}
-
-
-/**
- * write_pages - write block of data to device via the page cache
- * @dev: device to write to
- * @buf: data source or NULL if erase (output is set to 0xff)
- * @to: offset into output device
- * @len: amount to data to write
- * @retlen: amount of data written
- *
- * Grab pages from the page cache and fill them with the source data.
- * Non page aligned start and end result in a readin of the page and
- * part of the page being modified. Pages are added to the bio and then written
- * out.
- */
-static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to,
-		    size_t len, size_t *retlen)
-{
-	int pagenr, offset;
-	size_t start_len = 0, end_len;
-	int pagecnt = 0;
-	int err = 0;
-	struct bio *bio = NULL;
-	size_t thislen = 0;
-
-	pagenr = to >> PAGE_SHIFT;
-	offset = to & ~PAGE_MASK;
-
-	DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n",
-	      buf, (long)to, len, pagenr, offset);
-
-	/* see if we have to do a partial write at the start */
-	if(offset) {
-		start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len;
-		len -= start_len;
-	}
-
-	/* calculate the length of the other two regions */
-	end_len = len & ~PAGE_MASK;
-	len -= end_len;
-
-	if(start_len)
-		pagecnt++;
-
-	if(len)
-		pagecnt += len >> PAGE_SHIFT;
-
-	if(end_len)
-		pagecnt++;
-
-	mutex_lock(&dev->wrbuf_mutex);
-
-	DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n",
-	      start_len, len, end_len, pagecnt);
-
-	if(start_len) {
-		/* do partial start region */
-		struct page *page;
-
-		DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n",
-		      pagenr, start_len, offset);
-
-		BUG_ON(!buf);
-		page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
-		lock_page(page);
-		if(PageDirty(page)) {
-			err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
-			    to, start_len, len, end_len, pagenr);
-			BUG();
-		}
-		memcpy(page_address(page)+offset, buf, start_len);
-		set_page_dirty(page);
-		SetPageUptodate(page);
-		buf += start_len;
-		thislen = start_len;
-		bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
-		if(!bio) {
-			err = -ENOMEM;
-			err("bio_add_page failed\n");
-			goto write_err;
-		}
-		pagecnt--;
-		pagenr++;
-	}
-
-	/* Now do the main loop to a page aligned, n page sized output */
-	if(len) {
-		int pagesc = len >> PAGE_SHIFT;
-		DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n",
-		      pagenr, pagesc);
-		while(pagesc) {
-			struct page *page;
-
-			/* see if page is in the page cache */
-			DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr);
-			page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr);
-			if(PageDirty(page)) {
-				BUG();
-			}
-			if(!page) {
-				warn("write: cannot grab cache page %d", pagenr);
-				err = -ENOMEM;
-				goto write_err;
-			}
-			if(!buf) {
-				memset(page_address(page), 0xff, PAGE_SIZE);
-			} else {
-				memcpy(page_address(page), buf, PAGE_SIZE);
-				buf += PAGE_SIZE;
-			}
-			bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
-			if(!bio) {
-				err = -ENOMEM;
-				err("bio_add_page failed\n");
-				goto write_err;
-			}
-			pagenr++;
-			pagecnt--;
-			set_page_dirty(page);
-			SetPageUptodate(page);
-			pagesc--;
-			thislen += PAGE_SIZE;
-		}
-	}
-
-	if(end_len) {
-		/* do the third region */
-		struct page *page;
-		DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n",
-		      pagenr, end_len);
-		BUG_ON(!buf);
-		page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
-		lock_page(page);
-		if(PageDirty(page)) {
-			err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n",
-			    to, start_len, len, end_len, pagenr);
-			BUG();
-		}
-		memcpy(page_address(page), buf, end_len);
-		set_page_dirty(page);
-		SetPageUptodate(page);
-		DEBUG(3, "blkmtd: write: writing out partial end\n");
-		thislen += end_len;
-		bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt);
-		if(!bio) {
-			err = -ENOMEM;
-			err("bio_add_page failed\n");
-			goto write_err;
-		}
-		pagenr++;
-	}
-
-	DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt);
- write_err:
-	if(bio)
-		blkmtd_write_out(bio);
-
-	DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err);
-	mutex_unlock(&dev->wrbuf_mutex);
-
-	if(retlen)
-		*retlen = thislen;
-	return err;
-}
-
-
-/* erase a specified part of the device */
-static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-	struct blkmtd_dev *dev = mtd->priv;
-	struct mtd_erase_region_info *einfo = mtd->eraseregions;
-	int numregions = mtd->numeraseregions;
-	size_t from;
-	u_long len;
-	int err = -EIO;
-	size_t retlen;
-
-	instr->state = MTD_ERASING;
-	from = instr->addr;
-	len = instr->len;
-
-	/* check erase region has valid start and length */
-	DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n",
-	      mtd->name+9, from, len);
-	while(numregions) {
-		DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n",
-		      einfo->offset, einfo->erasesize, einfo->numblocks);
-		if(from >= einfo->offset
-		   && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) {
-			if(len == einfo->erasesize
-			   && ( (from - einfo->offset) % einfo->erasesize == 0))
-				break;
-		}
-		numregions--;
-		einfo++;
-	}
-
-	if(!numregions) {
-		/* Not a valid erase block */
-		err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from);
-		instr->state = MTD_ERASE_FAILED;
-		err = -EIO;
-	}
-
-	if(instr->state != MTD_ERASE_FAILED) {
-		/* do the erase */
-		DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len);
-		err = write_pages(dev, NULL, from, len, &retlen);
-		if(err || retlen != len) {
-			err("erase failed err = %d", err);
-			instr->state = MTD_ERASE_FAILED;
-		} else {
-			instr->state = MTD_ERASE_DONE;
-		}
-	}
-
-	DEBUG(3, "blkmtd: erase: checking callback\n");
-	mtd_erase_callback(instr);
-	DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
-	return err;
-}
-
-
-/* read a range of the data via the page cache */
-static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len,
-		       size_t *retlen, u_char *buf)
-{
-	struct blkmtd_dev *dev = mtd->priv;
-	int err = 0;
-	int offset;
-	int pagenr, pages;
-	size_t thislen = 0;
-
-	DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n",
-	      mtd->name+9, from, len, buf);
-
-	if(from > mtd->size)
-		return -EINVAL;
-	if(from + len > mtd->size)
-		len = mtd->size - from;
-
-	pagenr = from >> PAGE_SHIFT;
-	offset = from - (pagenr << PAGE_SHIFT);
-
-	pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT;
-	DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n",
-	      pagenr, offset, pages);
-
-	while(pages) {
-		struct page *page;
-		int cpylen;
-
-		DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr);
-		page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev);
-		if(IS_ERR(page)) {
-			err = -EIO;
-			goto readerr;
-		}
-
-		cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE;
-		if(offset+cpylen > PAGE_SIZE)
-			cpylen = PAGE_SIZE-offset;
-
-		memcpy(buf + thislen, page_address(page) + offset, cpylen);
-		offset = 0;
-		len -= cpylen;
-		thislen += cpylen;
-		pagenr++;
-		pages--;
-		if(!PageDirty(page))
-			page_cache_release(page);
-	}
-
- readerr:
-	if(retlen)
-		*retlen = thislen;
-	DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err);
-	return err;
-}
-
-
-/* write data to the underlying device */
-static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len,
-			size_t *retlen, const u_char *buf)
-{
-	struct blkmtd_dev *dev = mtd->priv;
-	int err;
-
-	if(!len)
-		return 0;
-
-	DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n",
-	      mtd->name+9, to, len, buf);
-
-	if(to >= mtd->size) {
-		return -ENOSPC;
-	}
-
-	if(to + len > mtd->size) {
-		len = mtd->size - to;
-	}
-
-	err = write_pages(dev, buf, to, len, retlen);
-	if(err > 0)
-		err = 0;
-	DEBUG(2, "blkmtd: write: end, err = %d\n", err);
-	return err;
-}
-
-
-/* sync the device - wait until the write queue is empty */
-static void blkmtd_sync(struct mtd_info *mtd)
-{
-	/* Currently all writes are synchronous */
-}
-
-
-static void free_device(struct blkmtd_dev *dev)
-{
-	DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
-	if(dev) {
-		kfree(dev->mtd_info.eraseregions);
-		kfree(dev->mtd_info.name);
-		if(dev->blkdev) {
-			invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
-			close_bdev_excl(dev->blkdev);
-		}
-		kfree(dev);
-	}
-}
-
-
-/* For a given size and initial erase size, calculate the number
- * and size of each erase region. Goes round the loop twice,
- * once to find out how many regions, then allocates space,
- * then round the loop again to fill it in.
- */
-static struct mtd_erase_region_info *calc_erase_regions(
-	size_t erase_size, size_t total_size, int *regions)
-{
-	struct mtd_erase_region_info *info = NULL;
-
-	DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n",
-	      erase_size, total_size, *regions);
-	/* Make any user specified erasesize be a power of 2
-	   and at least PAGE_SIZE */
-	if(erase_size) {
-		int es = erase_size;
-		erase_size = 1;
-		while(es != 1) {
-			es >>= 1;
-			erase_size <<= 1;
-		}
-		if(erase_size < PAGE_SIZE)
-			erase_size = PAGE_SIZE;
-	} else {
-		erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
-	}
-
-	*regions = 0;
-
-	do {
-		int tot_size = total_size;
-		int er_size = erase_size;
-		int count = 0, offset = 0, regcnt = 0;
-
-		while(tot_size) {
-			count = tot_size / er_size;
-			if(count) {
-				tot_size = tot_size % er_size;
-				if(info) {
-					DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n",
-					      offset, er_size, count);
-					(info+regcnt)->offset = offset;
-					(info+regcnt)->erasesize = er_size;
-					(info+regcnt)->numblocks = count;
-					(*regions)++;
-				}
-				regcnt++;
-				offset += (count * er_size);
-			}
-			while(er_size > tot_size)
-				er_size >>= 1;
-		}
-		if(info == NULL) {
-			info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL);
-			if(!info)
-				break;
-		}
-	} while(!(*regions));
-	DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n",
-	      erase_size, total_size, *regions);
-	return info;
-}
-
-
-static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size)
-{
-	struct block_device *bdev;
-	int mode;
-	struct blkmtd_dev *dev;
-
-	if(!devname)
-		return NULL;
-
-	/* Get a handle on the device */
-
-
-#ifdef MODULE
-	mode = (readonly) ? O_RDONLY : O_RDWR;
-	bdev = open_bdev_excl(devname, mode, NULL);
-#else
-	mode = (readonly) ? FMODE_READ : FMODE_WRITE;
-	bdev = open_by_devnum(name_to_dev_t(devname), mode);
-#endif
-	if(IS_ERR(bdev)) {
-		err("error: cannot open device %s", devname);
-		DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev));
-		return NULL;
-	}
-
-	DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n",
-	      MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
-
-	if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
-		err("attempting to use an MTD device as a block device");
-		blkdev_put(bdev);
-		return NULL;
-	}
-
-	dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL);
-	if(dev == NULL) {
-		blkdev_put(bdev);
-		return NULL;
-	}
-
-	memset(dev, 0, sizeof(struct blkmtd_dev));
-	dev->blkdev = bdev;
-	if(!readonly) {
-		mutex_init(&dev->wrbuf_mutex);
-	}
-
-	dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
-
-	/* Setup the MTD structure */
-	/* make the name contain the block device in */
-	dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL);
-	if(dev->mtd_info.name == NULL)
-		goto devinit_err;
-
-	sprintf(dev->mtd_info.name, "blkmtd: %s", devname);
-	dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size,
-							&dev->mtd_info.numeraseregions);
-	if(dev->mtd_info.eraseregions == NULL)
-		goto devinit_err;
-
-	dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize;
-	DEBUG(1, "blkmtd: init: found %d erase regions\n",
-	      dev->mtd_info.numeraseregions);
-
-	if(readonly) {
-		dev->mtd_info.type = MTD_ROM;
-		dev->mtd_info.flags = MTD_CAP_ROM;
-	} else {
-		dev->mtd_info.type = MTD_RAM;
-		dev->mtd_info.flags = MTD_CAP_RAM;
-		dev->mtd_info.erase = blkmtd_erase;
-		dev->mtd_info.write = blkmtd_write;
-		dev->mtd_info.writev = default_mtd_writev;
-		dev->mtd_info.sync = blkmtd_sync;
-	}
-	dev->mtd_info.read = blkmtd_read;
-	dev->mtd_info.readv = default_mtd_readv;
-	dev->mtd_info.priv = dev;
-	dev->mtd_info.owner = THIS_MODULE;
-
-	list_add(&dev->list, &blkmtd_device_list);
-	if (add_mtd_device(&dev->mtd_info)) {
-		/* Device didnt get added, so free the entry */
-		list_del(&dev->list);
-		goto devinit_err;
-	} else {
-		info("mtd%d: [%s] erase_size = %dKiB %s",
-		     dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "),
-		     dev->mtd_info.erasesize >> 10,
-		     readonly ? "(read-only)" : "");
-	}
-
-	return dev;
-
- devinit_err:
-	free_device(dev);
-	return NULL;
-}
-
-
-/* Cleanup and exit - sync the device and kill of the kernel thread */
-static void __devexit cleanup_blkmtd(void)
-{
-	struct list_head *temp1, *temp2;
-
-	/* Remove the MTD devices */
-	list_for_each_safe(temp1, temp2, &blkmtd_device_list) {
-		struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev,
-						    list);
-		blkmtd_sync(&dev->mtd_info);
-		del_mtd_device(&dev->mtd_info);
-		info("mtd%d: [%s] removed", dev->mtd_info.index,
-		     dev->mtd_info.name + strlen("blkmtd: "));
-		list_del(&dev->list);
-		free_device(dev);
-	}
-}
-
-#ifndef MODULE
-
-/* Handle kernel boot params */
-
-
-static int __init param_blkmtd_device(char *str)
-{
-	int i;
-
-	for(i = 0; i < MAX_DEVICES; i++) {
-		device[i] = str;
-		DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]);
-		strsep(&str, ",");
-	}
-	return 1;
-}
-
-
-static int __init param_blkmtd_erasesz(char *str)
-{
-	int i;
-	for(i = 0; i < MAX_DEVICES; i++) {
-		char *val = strsep(&str, ",");
-		if(val)
-			erasesz[i] = simple_strtoul(val, NULL, 0);
-		DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]);
-	}
-
-	return 1;
-}
-
-
-static int __init param_blkmtd_ro(char *str)
-{
-	int i;
-	for(i = 0; i < MAX_DEVICES; i++) {
-		char *val = strsep(&str, ",");
-		if(val)
-			ro[i] = simple_strtoul(val, NULL, 0);
-		DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]);
-	}
-
-	return 1;
-}
-
-
-static int __init param_blkmtd_sync(char *str)
-{
-	if(str[0] == '1')
-		sync = 1;
-	return 1;
-}
-
-__setup("blkmtd_device=", param_blkmtd_device);
-__setup("blkmtd_erasesz=", param_blkmtd_erasesz);
-__setup("blkmtd_ro=", param_blkmtd_ro);
-__setup("blkmtd_sync=", param_blkmtd_sync);
-
-#endif
-
-
-/* Startup */
-static int __init init_blkmtd(void)
-{
-	int i;
-
-	info("version " VERSION);
-	/* Check args - device[0] is the bare minimum*/
-	if(!device[0]) {
-		err("error: missing `device' name\n");
-		return -EINVAL;
-	}
-
-	for(i = 0; i < MAX_DEVICES; i++)
-		add_device(device[i], ro[i], erasesz[i] << 10);
-
-	if(list_empty(&blkmtd_device_list))
-		return -EINVAL;
-
-	return 0;
-}
-
-module_init(init_blkmtd);
-module_exit(cleanup_blkmtd);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 8bbc751..d27f412 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -54,7 +54,7 @@
 #define MAX_PCMCIA_ADDR	0x4000000
 
 struct pcmciamtd_dev {
-	dev_link_t	link;		/* PCMCIA link */
+	struct pcmcia_device	*p_dev;
 	dev_node_t	node;		/* device node */
 	caddr_t		win_base;	/* ioremapped address of PCMCIA window */
 	unsigned int	win_size;	/* size of window */
@@ -111,8 +111,8 @@
 	memreq_t mrq;
 	int ret;
 
-	if(!(dev->link.state & DEV_PRESENT)) {
-		DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
+	if (!pcmcia_dev_present(dev->p_dev)) {
+		DEBUG(1, "device removed");
 		return 0;
 	}
 
@@ -122,7 +122,7 @@
 		      dev->offset, mrq.CardOffset);
 		mrq.Page = 0;
 		if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
-			cs_error(dev->link.handle, MapMemPage, ret);
+			cs_error(dev->p_dev, MapMemPage, ret);
 			return NULL;
 		}
 		dev->offset = mrq.CardOffset;
@@ -238,7 +238,7 @@
 
 /* read/write{8,16} copy_{from,to} routines with direct access */
 
-#define DEV_REMOVED(x)  (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
+#define DEV_REMOVED(x)  (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev)))
 
 static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
 {
@@ -319,7 +319,7 @@
 static void pcmciamtd_set_vpp(struct map_info *map, int on)
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
-	dev_link_t *link = &dev->link;
+	struct pcmcia_device *link = dev->p_dev;
 	modconf_t mod;
 	int ret;
 
@@ -328,9 +328,9 @@
 	mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 
 	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
-	ret = pcmcia_modify_configuration(link->handle, &mod);
+	ret = pcmcia_modify_configuration(link, &mod);
 	if(ret != CS_SUCCESS) {
-		cs_error(link->handle, ModifyConfiguration, ret);
+		cs_error(link, ModifyConfiguration, ret);
 	}
 }
 
@@ -340,7 +340,7 @@
  * still open, this will be postponed until it is closed.
  */
 
-static void pcmciamtd_release(dev_link_t *link)
+static void pcmciamtd_release(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
 
@@ -353,12 +353,11 @@
 		}
 		pcmcia_release_window(link->win);
 	}
-	pcmcia_release_configuration(link->handle);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
 
-static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
+static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name)
 {
 	int rc;
 	tuple_t tuple;
@@ -371,16 +370,16 @@
 	tuple.TupleOffset = 0;
 	tuple.DesiredTuple = RETURN_FIRST_TUPLE;
 
-	rc = pcmcia_get_first_tuple(link->handle, &tuple);
+	rc = pcmcia_get_first_tuple(link, &tuple);
 	while(rc == CS_SUCCESS) {
-		rc = pcmcia_get_tuple_data(link->handle, &tuple);
+		rc = pcmcia_get_tuple_data(link, &tuple);
 		if(rc != CS_SUCCESS) {
-			cs_error(link->handle, GetTupleData, rc);
+			cs_error(link, GetTupleData, rc);
 			break;
 		}
-		rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
+		rc = pcmcia_parse_tuple(link, &tuple, &parse);
 		if(rc != CS_SUCCESS) {
-			cs_error(link->handle, ParseTuple, rc);
+			cs_error(link, ParseTuple, rc);
 			break;
 		}
 
@@ -451,7 +450,7 @@
 			DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
 		}
 
-		rc = pcmcia_get_next_tuple(link->handle, &tuple);
+		rc = pcmcia_get_next_tuple(link, &tuple);
 	}
 	if(!dev->pcmcia_map.size)
 		dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
@@ -488,7 +487,7 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void pcmciamtd_config(dev_link_t *link)
+static int pcmciamtd_config(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
 	struct mtd_info *mtd = NULL;
@@ -504,13 +503,10 @@
 
 	DEBUG(3, "link=0x%p", link);
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	DEBUG(2, "Validating CIS");
-	ret = pcmcia_validate_cis(link->handle, &cisinfo);
+	ret = pcmcia_validate_cis(link, &cisinfo);
 	if(ret != CS_SUCCESS) {
-		cs_error(link->handle, GetTupleData, ret);
+		cs_error(link, GetTupleData, ret);
 	} else {
 		DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
 	}
@@ -538,7 +534,7 @@
 	req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
 	req.Base = 0;
 	req.AccessSpeed = mem_speed;
-	link->win = (window_handle_t)link->handle;
+	link->win = (window_handle_t)link;
 	req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
 	dev->win_size = 0;
 
@@ -546,7 +542,7 @@
 		int ret;
 		DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
 		      req.Size >> 10, req.AccessSpeed);
-		ret = pcmcia_request_window(&link->handle, &req, &link->win);
+		ret = pcmcia_request_window(&link, &req, &link->win);
 		DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
 		if(ret) {
 			req.Size >>= 1;
@@ -562,19 +558,19 @@
 	if(!dev->win_size) {
 		err("Cant allocate memory window");
 		pcmciamtd_release(link);
-		return;
+		return -ENODEV;
 	}
 	DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
 	/* Get write protect status */
-	CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
+	CS_CHECK(GetStatus, pcmcia_get_status(link, &status));
 	DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
 	      status.CardState, (unsigned long)link->win);
 	dev->win_base = ioremap(req.Base, req.Size);
 	if(!dev->win_base) {
 		err("ioremap(%lu, %u) failed", req.Base, req.Size);
 		pcmciamtd_release(link);
-		return;
+		return -ENODEV;
 	}
 	DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
 	      dev, req.Base, dev->win_base, req.Size);
@@ -584,17 +580,14 @@
 	dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
 
 	DEBUG(2, "Getting configuration");
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
+	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
 	DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
 	dev->vpp = (vpp) ? vpp : t.Vpp1;
 	link->conf.Attributes = 0;
-	link->conf.Vcc = t.Vcc;
 	if(setvpp == 2) {
-		link->conf.Vpp1 = dev->vpp;
-		link->conf.Vpp2 = dev->vpp;
+		link->conf.Vpp = dev->vpp;
 	} else {
-		link->conf.Vpp1 = 0;
-		link->conf.Vpp2 = 0;
+		link->conf.Vpp = 0;
 	}
 
 	link->conf.IntType = INT_MEMORY;
@@ -606,9 +599,10 @@
 	link->conf.ConfigIndex = 0;
 	link->conf.Present = t.Present;
 	DEBUG(2, "Setting Configuration");
-	ret = pcmcia_request_configuration(link->handle, &link->conf);
+	ret = pcmcia_request_configuration(link, &link->conf);
 	if(ret != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, ret);
+		cs_error(link, RequestConfiguration, ret);
+		return -ENODEV;
 	}
 
 	if(mem_type == 1) {
@@ -629,7 +623,7 @@
 	if(!mtd) {
 		DEBUG(1, "Cant find an MTD");
 		pcmciamtd_release(link);
-		return;
+		return -ENODEV;
 	}
 
 	dev->mtd_info = mtd;
@@ -654,7 +648,6 @@
 	   use the faster non-remapping read/write functions */
 	if(mtd->size <= dev->win_size) {
 		DEBUG(1, "Using non remapping memory functions");
-		dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
 		dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
 		if (dev->pcmcia_map.bankwidth == 1) {
 			dev->pcmcia_map.read = pcmcia_read8;
@@ -672,19 +665,18 @@
 		dev->mtd_info = NULL;
 		err("Couldnt register MTD device");
 		pcmciamtd_release(link);
-		return;
+		return -ENODEV;
 	}
 	snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
 	info("mtd%d: %s", mtd->index, mtd->name);
-	link->state &= ~DEV_CONFIG_PENDING;
-	link->dev = &dev->node;
-	return;
+	link->dev_node = &dev->node;
+	return 0;
 
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	err("CS Error, exiting");
 	pcmciamtd_release(link);
-	return;
+	return -ENODEV;
 }
 
 
@@ -713,21 +705,18 @@
  * when the device is released.
  */
 
-static void pcmciamtd_detach(struct pcmcia_device *p_dev)
+static void pcmciamtd_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
+	struct pcmciamtd_dev *dev = link->priv;
 
 	DEBUG(3, "link=0x%p", link);
 
-	if(link->state & DEV_CONFIG) {
-		struct pcmciamtd_dev *dev = link->priv;
-		if(dev->mtd_info) {
-			del_mtd_device(dev->mtd_info);
-			info("mtd%d: Removed", dev->mtd_info->index);
-		}
-
-		pcmciamtd_release(link);
+	if(dev->mtd_info) {
+		del_mtd_device(dev->mtd_info);
+		info("mtd%d: Removed", dev->mtd_info->index);
 	}
+
+	pcmciamtd_release(link);
 }
 
 
@@ -736,10 +725,9 @@
  * with Card Services.
  */
 
-static int pcmciamtd_attach(struct pcmcia_device *p_dev)
+static int pcmciamtd_probe(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev;
-	dev_link_t *link;
 
 	/* Create new memory card device */
 	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
@@ -747,20 +735,13 @@
 	DEBUG(1, "dev=0x%p", dev);
 
 	memset(dev, 0, sizeof(*dev));
-	link = &dev->link;
+	dev->p_dev = link;
 	link->priv = dev;
 
 	link->conf.Attributes = 0;
 	link->conf.IntType = INT_MEMORY;
 
-	link->next = NULL;
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	pcmciamtd_config(link);
-
-	return 0;
+	return pcmciamtd_config(link);
 }
 
 static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -794,7 +775,7 @@
 	.drv		= {
 		.name	= "pcmciamtd"
 	},
-	.probe		= pcmciamtd_attach,
+	.probe		= pcmciamtd_probe,
 	.remove		= pcmciamtd_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= pcmciamtd_ids,
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ce99845..066e22b 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -539,8 +539,7 @@
 		unsigned buflen;
 
 		skb = cp->rx_skb[rx_tail].skb;
-		if (!skb)
-			BUG();
+		BUG_ON(!skb);
 
 		desc = &cp->rx_ring[rx_tail];
 		status = le32_to_cpu(desc->opts1);
@@ -723,8 +722,7 @@
 			break;
 
 		skb = cp->tx_skb[tx_tail].skb;
-		if (!skb)
-			BUG();
+		BUG_ON(!skb);
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
 				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
@@ -1550,8 +1548,7 @@
 	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();
+	BUG_ON(i != CP_NUM_STATS);
 
 	pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
 }
@@ -1856,8 +1853,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct cp_private *cp = netdev_priv(dev);
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	iounmap(cp->regs);
 	if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 64e2caf..fabc060 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -765,8 +765,7 @@
 	BUGMSG(D_DURING, "in arcnet_interrupt\n");
 	
 	lp = dev->priv;
-	if (!lp)
-		BUG();
+	BUG_ON(!lp);
 		
 	spin_lock(&lp->lock);
 
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 43150b2..0d45553 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -125,11 +125,11 @@
 	if (!io && !irq && !shmem && !*device && com90xx_skip_probe)
 		return;
 
-	shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long),
+	shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long),
 			 GFP_KERNEL);
 	if (!shmems)
 		return;
-	iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *),
+	iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *),
 			 GFP_KERNEL);
 	if (!iomem) {
 		kfree(shmems);
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 15032f2..3d30668 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2,6 +2,7 @@
  *
  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
  * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
+ * Copyright (C) 2006 Broadcom Corporation.
  *
  * Distribute under GPL.
  */
@@ -28,8 +29,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.97"
-#define DRV_MODULE_RELDATE	"Nov 30, 2005"
+#define DRV_MODULE_VERSION	"1.00"
+#define DRV_MODULE_RELDATE	"Apr 7, 2006"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -136,7 +137,7 @@
 	return readl(bp->regs + reg);
 }
 
-static inline void bw32(const struct b44 *bp, 
+static inline void bw32(const struct b44 *bp,
 			unsigned long reg, unsigned long val)
 {
 	writel(val, bp->regs + reg);
@@ -286,13 +287,13 @@
 	val |= ((u32) data[4]) <<  8;
 	val |= ((u32) data[5]) <<  0;
 	bw32(bp, B44_CAM_DATA_LO, val);
-	val = (CAM_DATA_HI_VALID | 
+	val = (CAM_DATA_HI_VALID |
 	       (((u32) data[0]) << 8) |
 	       (((u32) data[1]) << 0));
 	bw32(bp, B44_CAM_DATA_HI, val);
 	bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
 			    (index << CAM_CTRL_INDEX_SHIFT)));
-	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);	
+	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
 }
 
 static inline void __b44_disable_ints(struct b44 *bp)
@@ -410,25 +411,18 @@
 
 static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
 {
-	u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE |
-				      B44_FLAG_RX_PAUSE);
+	u32 pause_enab = 0;
 
-	if (local & ADVERTISE_PAUSE_CAP) {
-		if (local & ADVERTISE_PAUSE_ASYM) {
-			if (remote & LPA_PAUSE_CAP)
-				pause_enab |= (B44_FLAG_TX_PAUSE |
-					       B44_FLAG_RX_PAUSE);
-			else if (remote & LPA_PAUSE_ASYM)
-				pause_enab |= B44_FLAG_RX_PAUSE;
-		} else {
-			if (remote & LPA_PAUSE_CAP)
-				pause_enab |= (B44_FLAG_TX_PAUSE |
-					       B44_FLAG_RX_PAUSE);
-		}
-	} else if (local & ADVERTISE_PAUSE_ASYM) {
-		if ((remote & LPA_PAUSE_CAP) &&
-		    (remote & LPA_PAUSE_ASYM))
-			pause_enab |= B44_FLAG_TX_PAUSE;
+	/* The driver supports only rx pause by default because
+	   the b44 mac tx pause mechanism generates excessive
+	   pause frames.
+	   Use ethtool to turn on b44 tx pause if necessary.
+	 */
+	if ((local & ADVERTISE_PAUSE_CAP) &&
+	    (local & ADVERTISE_PAUSE_ASYM)){
+		if ((remote & LPA_PAUSE_ASYM) &&
+		    !(remote & LPA_PAUSE_CAP))
+			pause_enab |= B44_FLAG_RX_PAUSE;
 	}
 
 	__b44_set_flow_ctrl(bp, pause_enab);
@@ -608,8 +602,7 @@
 		struct ring_info *rp = &bp->tx_buffers[cons];
 		struct sk_buff *skb = rp->skb;
 
-		if (unlikely(skb == NULL))
-			BUG();
+		BUG_ON(skb == NULL);
 
 		pci_unmap_single(bp->pdev,
 				 pci_unmap_addr(rp, mapping),
@@ -1064,7 +1057,7 @@
 	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
-	
+
 	return 0;
 }
 
@@ -1382,7 +1375,7 @@
 	bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
 	bw32(bp, B44_DMARX_PTR, bp->rx_pending);
-	bp->rx_prod = bp->rx_pending;	
+	bp->rx_prod = bp->rx_pending;
 
 	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
 
@@ -1554,9 +1547,9 @@
 			val |= RXCONFIG_ALLMULTI;
 		else
 			i = __b44_load_mcast(bp, dev);
-		
+
 		for (; i < 64; i++) {
-			__b44_cam_write(bp, zero, i);			
+			__b44_cam_write(bp, zero, i);
 		}
 		bw32(bp, B44_RXCONFIG, val);
         	val = br32(bp, B44_CAM_CTRL);
@@ -1738,7 +1731,7 @@
 	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
-	
+
 	return 0;
 }
 
@@ -1783,7 +1776,7 @@
 	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
-	
+
 	return 0;
 }
 
@@ -1899,7 +1892,7 @@
 	bp->core_unit = ssb_core_unit(bp);
 	bp->dma_offset = SB_PCI_DMA;
 
-	/* XXX - really required? 
+	/* XXX - really required?
 	   bp->flags |= B44_FLAG_BUGGY_TXPTR;
          */
 out:
@@ -1947,7 +1940,7 @@
 		       "aborting.\n");
 		goto err_out_free_res;
 	}
-	
+
 	err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
 	if (err) {
 		printk(KERN_ERR PFX "No usable DMA configuration, "
@@ -2042,9 +2035,9 @@
 
 	pci_save_state(bp->pdev);
 
-	/* Chip reset provides power to the b44 MAC & PCI cores, which 
+	/* Chip reset provides power to the b44 MAC & PCI cores, which
 	 * is necessary for MAC register access.
-	 */ 
+	 */
 	b44_chip_reset(bp);
 
 	printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
@@ -2092,10 +2085,10 @@
 
 	del_timer_sync(&bp->timer);
 
-	spin_lock_irq(&bp->lock); 
+	spin_lock_irq(&bp->lock);
 
 	b44_halt(bp);
-	netif_carrier_off(bp->dev); 
+	netif_carrier_off(bp->dev);
 	netif_device_detach(bp->dev);
 	b44_free_rings(bp);
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2671da2..5ca99e2 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -63,7 +63,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
 	"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile
index 91e9278..54c78d9 100644
--- a/drivers/net/chelsio/Makefile
+++ b/drivers/net/chelsio/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_CHELSIO_T1) += cxgb.o
 
-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS)
+EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS)
 
 
 cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 30ff8ea..4391bf4 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1093,8 +1093,7 @@
 		if (likely(e->DataValid)) {
 			struct freelQ *fl = &sge->freelQ[e->FreelistQid];
 
-			if (unlikely(!e->Sop || !e->Eop))
-				BUG();
+			BUG_ON(!e->Sop || !e->Eop);
 			if (unlikely(e->Offload))
 				unexpected_offload(adapter, fl);
 			else
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 49cd096..c99e878 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -3308,8 +3308,7 @@
 
 	while (poll_dev != &adapter->polling_netdev[i]) {
 		i++;
-		if (unlikely(i == adapter->num_rx_queues))
-			BUG();
+		BUG_ON(i == adapter->num_rx_queues);
 	}
 
 	if (likely(adapter->num_tx_queues == 1)) {
@@ -3769,6 +3768,7 @@
 			ps_page->ps_page[j] = NULL;
 			skb->len += length;
 			skb->data_len += length;
+			skb->truesize += length;
 		}
 
 copydone:
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index aa15691..815436c 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -203,8 +203,7 @@
 	printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
 	       "your slave devices.\n", dev->name);
 
-	if (!list_empty(&eql->queue.all_slaves))
-		BUG();
+	BUG_ON(!list_empty(&eql->queue.all_slaves));
 
 	eql->min_slaves = 1;
 	eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 7627a75..9788b1e 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -105,6 +105,7 @@
  *	0.50: 20 Jan 2006: Add 8021pq tagging support.
  *	0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
  *	0.52: 20 Jan 2006: Add MSI/MSIX support.
+ *	0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -116,7 +117,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.52"
+#define FORCEDETH_VERSION		"0.53"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -160,6 +161,7 @@
 #define DEV_HAS_VLAN            0x0020  /* device supports vlan tagging and striping */
 #define DEV_HAS_MSI             0x0040  /* device supports MSI */
 #define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
+#define DEV_HAS_POWER_CNTRL     0x0100  /* device supports power savings */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -203,6 +205,8 @@
 #define NVREG_MISC1_HD		0x02
 #define NVREG_MISC1_FORCE	0x3b0f3c
 
+	NvRegMacReset = 0x3c,
+#define NVREG_MAC_RESET_ASSERT	0x0F3
 	NvRegTransmitterControl = 0x084,
 #define NVREG_XMITCTL_START	0x01
 	NvRegTransmitterStatus = 0x088,
@@ -326,6 +330,10 @@
 	NvRegMSIXMap0 = 0x3e0,
 	NvRegMSIXMap1 = 0x3e4,
 	NvRegMSIXIrqStatus = 0x3f0,
+
+	NvRegPowerState2 = 0x600,
+#define NVREG_POWERSTATE2_POWERUP_MASK		0x0F11
+#define NVREG_POWERSTATE2_POWERUP_REV_A3	0x0001
 };
 
 /* Big endian: should work, but is untested */
@@ -414,7 +422,8 @@
 #define NV_RX3_VLAN_TAG_MASK	(0x0000FFFF)
 
 /* Miscelaneous hardware related defines: */
-#define NV_PCI_REGSZ		0x270
+#define NV_PCI_REGSZ_VER1      	0x270
+#define NV_PCI_REGSZ_VER2      	0x604
 
 /* various timeout delays: all in usec */
 #define NV_TXRX_RESET_DELAY	4
@@ -431,6 +440,7 @@
 #define NV_MIIBUSY_DELAY	50
 #define NV_MIIPHY_DELAY	10
 #define NV_MIIPHY_DELAYMAX	10000
+#define NV_MAC_RESET_DELAY	64
 
 #define NV_WAKEUPPATTERNS	5
 #define NV_WAKEUPMASKENTRIES	4
@@ -552,6 +562,8 @@
 	u32 desc_ver;
 	u32 txrxctl_bits;
 	u32 vlanctl_bits;
+	u32 driver_data;
+	u32 register_size;
 
 	void __iomem *base;
 
@@ -919,6 +931,24 @@
 	pci_push(base);
 }
 
+static void nv_mac_reset(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+
+	dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
+	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
+	pci_push(base);
+	writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset);
+	pci_push(base);
+	udelay(NV_MAC_RESET_DELAY);
+	writel(0, base + NvRegMacReset);
+	pci_push(base);
+	udelay(NV_MAC_RESET_DELAY);
+	writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
+	pci_push(base);
+}
+
 /*
  * nv_get_stats: dev->get_stats function
  * Get latest stats value from the nic.
@@ -1331,7 +1361,7 @@
 				dev->name, (unsigned long)np->ring_addr,
 				np->next_tx, np->nic_tx);
 		printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
-		for (i=0;i<0x400;i+= 32) {
+		for (i=0;i<=np->register_size;i+= 32) {
 			printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
 					i,
 					readl(base + i + 0), readl(base + i + 4),
@@ -2488,11 +2518,11 @@
 }
 
 #define FORCEDETH_REGS_VER	1
-#define FORCEDETH_REGS_SIZE	0x400 /* 256 32-bit registers */
 
 static int nv_get_regs_len(struct net_device *dev)
 {
-	return FORCEDETH_REGS_SIZE;
+	struct fe_priv *np = netdev_priv(dev);
+	return np->register_size;
 }
 
 static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
@@ -2504,7 +2534,7 @@
 
 	regs->version = FORCEDETH_REGS_VER;
 	spin_lock_irq(&np->lock);
-	for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++)
+	for (i = 0;i <= np->register_size/sizeof(u32); i++)
 		rbuf[i] = readl(base + i*sizeof(u32));
 	spin_unlock_irq(&np->lock);
 }
@@ -2608,6 +2638,8 @@
 	dprintk(KERN_DEBUG "nv_open: begin\n");
 
 	/* 1) erase previous misconfiguration */
+	if (np->driver_data & DEV_HAS_POWER_CNTRL)
+		nv_mac_reset(dev);
 	/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
 	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
 	writel(0, base + NvRegMulticastAddrB);
@@ -2878,6 +2910,7 @@
 	unsigned long addr;
 	u8 __iomem *base;
 	int err, i;
+	u32 powerstate;
 
 	dev = alloc_etherdev(sizeof(struct fe_priv));
 	err = -ENOMEM;
@@ -2910,6 +2943,11 @@
 	if (err < 0)
 		goto out_disable;
 
+	if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL))
+		np->register_size = NV_PCI_REGSZ_VER2;
+	else
+		np->register_size = NV_PCI_REGSZ_VER1;
+
 	err = -EINVAL;
 	addr = 0;
 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
@@ -2918,7 +2956,7 @@
 				pci_resource_len(pci_dev, i),
 				pci_resource_flags(pci_dev, i));
 		if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&
-				pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) {
+				pci_resource_len(pci_dev, i) >= np->register_size) {
 			addr = pci_resource_start(pci_dev, i);
 			break;
 		}
@@ -2929,6 +2967,9 @@
 		goto out_relreg;
 	}
 
+	/* copy of driver data */
+	np->driver_data = id->driver_data;
+
 	/* handle different descriptor versions */
 	if (id->driver_data & DEV_HAS_HIGH_DMA) {
 		/* packet format 3: supports 40-bit addressing */
@@ -2986,7 +3027,7 @@
 	}
 
 	err = -ENOMEM;
-	np->base = ioremap(addr, NV_PCI_REGSZ);
+	np->base = ioremap(addr, np->register_size);
 	if (!np->base)
 		goto out_relreg;
 	dev->base_addr = (unsigned long)np->base;
@@ -3062,6 +3103,20 @@
 	writel(0, base + NvRegWakeUpFlags);
 	np->wolenabled = 0;
 
+	if (id->driver_data & DEV_HAS_POWER_CNTRL) {
+		u8 revision_id;
+		pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
+
+		/* take phy and nic out of low power mode */
+		powerstate = readl(base + NvRegPowerState2);
+		powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
+		if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
+		     id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
+		    revision_id >= 0xA3)
+			powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
+		writel(powerstate, base + NvRegPowerState2);
+	}
+
 	if (np->desc_ver == DESC_VER_1) {
 		np->tx_flags = NV_TX_VALID;
 	} else {
@@ -3223,19 +3278,19 @@
 	},
 	{	/* MCP51 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
 	},
 	{	/* MCP51 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL,
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
 	},
 	{0,},
 };
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 771e25d..218d317 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -210,7 +210,8 @@
 		goto regs_fail;
 	}
 
-	spin_lock_init(&priv->lock);
+	spin_lock_init(&priv->txlock);
+	spin_lock_init(&priv->rxlock);
 
 	platform_set_drvdata(pdev, dev);
 
@@ -515,11 +516,13 @@
 	phy_stop(priv->phydev);
 
 	/* Lock it down */
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
+	spin_lock(&priv->rxlock);
 
 	gfar_halt(dev);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->rxlock);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	/* Free the IRQs */
 	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
@@ -605,14 +608,15 @@
 	tempval |= DMACTRL_INIT_SETTINGS;
 	gfar_write(&priv->regs->dmactrl, tempval);
 
-	/* Clear THLT, so that the DMA starts polling now */
-	gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
-
 	/* Make sure we aren't stopped */
 	tempval = gfar_read(&priv->regs->dmactrl);
 	tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
 	gfar_write(&priv->regs->dmactrl, tempval);
 
+	/* Clear THLT/RHLT, so that the DMA starts polling now */
+	gfar_write(&regs->tstat, TSTAT_CLEAR_THALT);
+	gfar_write(&regs->rstat, RSTAT_CLEAR_RHALT);
+
 	/* Unmask the interrupts we look for */
 	gfar_write(&regs->imask, IMASK_DEFAULT);
 }
@@ -928,12 +932,13 @@
 	struct txfcb *fcb = NULL;
 	struct txbd8 *txbdp;
 	u16 status;
+	unsigned long flags;
 
 	/* Update transmit stats */
 	priv->stats.tx_bytes += skb->len;
 
 	/* Lock priv now */
-	spin_lock_irq(&priv->lock);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	/* Point at the first free tx descriptor */
 	txbdp = priv->cur_tx;
@@ -1004,7 +1009,7 @@
 	gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
 
 	/* Unlock priv */
-	spin_unlock_irq(&priv->lock);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return 0;
 }
@@ -1049,7 +1054,7 @@
 	unsigned long flags;
 	u32 tempval;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 
 	priv->vlgrp = grp;
 
@@ -1076,7 +1081,7 @@
 		gfar_write(&priv->regs->rctrl, tempval);
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 }
 
 
@@ -1085,12 +1090,12 @@
 	struct gfar_private *priv = netdev_priv(dev);
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 
 	if (priv->vlgrp)
 		priv->vlgrp->vlan_devices[vid] = NULL;
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 }
 
 
@@ -1179,7 +1184,7 @@
 	gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
 
 	/* Lock priv */
-	spin_lock(&priv->lock);
+	spin_lock(&priv->txlock);
 	bdp = priv->dirty_tx;
 	while ((bdp->status & TXBD_READY) == 0) {
 		/* If dirty_tx and cur_tx are the same, then either the */
@@ -1224,7 +1229,7 @@
 	else
 		gfar_write(&priv->regs->txic, 0);
 
-	spin_unlock(&priv->lock);
+	spin_unlock(&priv->txlock);
 
 	return IRQ_HANDLED;
 }
@@ -1305,9 +1310,10 @@
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
-
 #ifdef CONFIG_GFAR_NAPI
 	u32 tempval;
+#else
+	unsigned long flags;
 #endif
 
 	/* Clear IEVENT, so rx interrupt isn't called again
@@ -1330,7 +1336,7 @@
 	}
 #else
 
-	spin_lock(&priv->lock);
+	spin_lock_irqsave(&priv->rxlock, flags);
 	gfar_clean_rx_ring(dev, priv->rx_ring_size);
 
 	/* If we are coalescing interrupts, update the timer */
@@ -1341,7 +1347,7 @@
 	else
 		gfar_write(&priv->regs->rxic, 0);
 
-	spin_unlock(&priv->lock);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 #endif
 
 	return IRQ_HANDLED;
@@ -1490,13 +1496,6 @@
 	/* Update the current rxbd pointer to be the next one */
 	priv->cur_rx = bdp;
 
-	/* If no packets have arrived since the
-	 * last one we processed, clear the IEVENT RX and
-	 * BSY bits so that another interrupt won't be
-	 * generated when we set IMASK */
-	if (bdp->status & RXBD_EMPTY)
-		gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
-
 	return howmany;
 }
 
@@ -1516,7 +1515,7 @@
 	rx_work_limit -= howmany;
 	*budget -= howmany;
 
-	if (rx_work_limit >= 0) {
+	if (rx_work_limit > 0) {
 		netif_rx_complete(dev);
 
 		/* Clear the halt bit in RSTAT */
@@ -1533,7 +1532,8 @@
 			gfar_write(&priv->regs->rxic, 0);
 	}
 
-	return (rx_work_limit < 0) ? 1 : 0;
+	/* Return 1 if there's more work to do */
+	return (rx_work_limit > 0) ? 0 : 1;
 }
 #endif
 
@@ -1629,7 +1629,7 @@
 	struct phy_device *phydev = priv->phydev;
 	int new_state = 0;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 	if (phydev->link) {
 		u32 tempval = gfar_read(&regs->maccfg2);
 		u32 ecntrl = gfar_read(&regs->ecntrl);
@@ -1694,7 +1694,7 @@
 	if (new_state && netif_msg_link(priv))
 		phy_print_status(phydev);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 }
 
 /* Update the hash table based on the current list of multicast
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index d37d540..127c98c 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -656,43 +656,62 @@
  * the buffer descriptor determines the actual condition.
  */
 struct gfar_private {
-	/* pointers to arrays of skbuffs for tx and rx */
+	/* Fields controlled by TX lock */
+	spinlock_t txlock;
+
+	/* Pointer to the array of skbuffs */
 	struct sk_buff ** tx_skbuff;
-	struct sk_buff ** rx_skbuff;
 
-	/* indices pointing to the next free sbk in skb arrays */
+	/* next free skb in the array */
 	u16 skb_curtx;
-	u16 skb_currx;
 
-	/* index of the first skb which hasn't been transmitted
-	 * yet. */
+	/* First skb in line to be transmitted */
 	u16 skb_dirtytx;
 
 	/* Configuration info for the coalescing features */
 	unsigned char txcoalescing;
 	unsigned short txcount;
 	unsigned short txtime;
+
+	/* Buffer descriptor pointers */
+	struct txbd8 *tx_bd_base;	/* First tx buffer descriptor */
+	struct txbd8 *cur_tx;	        /* Next free ring entry */
+	struct txbd8 *dirty_tx;		/* First buffer in line
+					   to be transmitted */
+	unsigned int tx_ring_size;
+
+	/* RX Locked fields */
+	spinlock_t rxlock;
+
+	/* skb array and index */
+	struct sk_buff ** rx_skbuff;
+	u16 skb_currx;
+
+	/* RX Coalescing values */
 	unsigned char rxcoalescing;
 	unsigned short rxcount;
 	unsigned short rxtime;
 
-	/* GFAR addresses */
-	struct rxbd8 *rx_bd_base;	/* Base addresses of Rx and Tx Buffers */
-	struct txbd8 *tx_bd_base;
+	struct rxbd8 *rx_bd_base;	/* First Rx buffers */
 	struct rxbd8 *cur_rx;           /* Next free rx ring entry */
-	struct txbd8 *cur_tx;	        /* Next free ring entry */
-	struct txbd8 *dirty_tx;		/* The Ring entry to be freed. */
-	struct gfar __iomem *regs;	/* Pointer to the GFAR memory mapped Registers */
-	u32 __iomem *hash_regs[16];
-	int hash_width;
-	struct net_device_stats stats; /* linux network statistics */
-	struct gfar_extra_stats extra_stats;
-	spinlock_t lock;
+
+	/* RX parameters */
+	unsigned int rx_ring_size;
 	unsigned int rx_buffer_size;
 	unsigned int rx_stash_size;
 	unsigned int rx_stash_index;
-	unsigned int tx_ring_size;
-	unsigned int rx_ring_size;
+
+	struct vlan_group *vlgrp;
+
+	/* Unprotected fields */
+	/* Pointer to the GFAR memory mapped Registers */
+	struct gfar __iomem *regs;
+
+	/* Hash registers and their width */
+	u32 __iomem *hash_regs[16];
+	int hash_width;
+
+	/* global parameters */
 	unsigned int fifo_threshold;
 	unsigned int fifo_starve;
 	unsigned int fifo_starve_off;
@@ -702,13 +721,15 @@
 		extended_hash:1,
 		bd_stash_en:1;
 	unsigned short padding;
-	struct vlan_group *vlgrp;
-	/* Info structure initialized by board setup code */
+
 	unsigned int interruptTransmit;
 	unsigned int interruptReceive;
 	unsigned int interruptError;
+
+	/* info structure initialized by platform code */
 	struct gianfar_platform_data *einfo;
 
+	/* PHY stuff */
 	struct phy_device *phydev;
 	struct mii_bus *mii_bus;
 	int oldspeed;
@@ -716,6 +737,10 @@
 	int oldlink;
 
 	uint32_t msg_enable;
+
+	/* Network Statistics */
+	struct net_device_stats stats;
+	struct gfar_extra_stats extra_stats;
 };
 
 static inline u32 gfar_read(volatile unsigned __iomem *addr)
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 5de7b2e..d69698c 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -455,10 +455,14 @@
 
 		/* Halt TX and RX, and process the frames which
 		 * have already been received */
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
 		gfar_halt(dev);
 		gfar_clean_rx_ring(dev, priv->rx_ring_size);
-		spin_unlock_irqrestore(&priv->lock, flags);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);
 
 		/* Now we take down the rings to rebuild them */
 		stop_gfar(dev);
@@ -488,10 +492,14 @@
 
 		/* Halt TX and RX, and process the frames which
 		 * have already been received */
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
 		gfar_halt(dev);
 		gfar_clean_rx_ring(dev, priv->rx_ring_size);
-		spin_unlock_irqrestore(&priv->lock, flags);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);
 
 		/* Now we take down the rings to rebuild them */
 		stop_gfar(dev);
@@ -523,7 +531,7 @@
 	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
 		return -EOPNOTSUPP;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 	gfar_halt(dev);
 
 	if (data)
@@ -532,7 +540,7 @@
 		dev->features &= ~NETIF_F_IP_CSUM;
 
 	gfar_start(dev);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return 0;
 }
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
index 51ef181..a6d5c43 100644
--- a/drivers/net/gianfar_sysfs.c
+++ b/drivers/net/gianfar_sysfs.c
@@ -82,7 +82,7 @@
 	else
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 
 	/* Set the new stashing value */
 	priv->bd_stash_en = new_setting;
@@ -96,7 +96,7 @@
 
 	gfar_write(&priv->regs->attr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -118,7 +118,7 @@
 	u32 temp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 	if (length > priv->rx_buffer_size)
 		return count;
 
@@ -142,7 +142,7 @@
 
 	gfar_write(&priv->regs->attr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -166,7 +166,7 @@
 	u32 temp;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->rxlock, flags);
 	if (index > priv->rx_stash_size)
 		return count;
 
@@ -180,7 +180,7 @@
 	temp |= ATTRELI_EI(index);
 	gfar_write(&priv->regs->attreli, flags);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->rxlock, flags);
 
 	return count;
 }
@@ -205,7 +205,7 @@
 	if (length > GFAR_MAX_FIFO_THRESHOLD)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_threshold = length;
 
@@ -214,7 +214,7 @@
 	temp |= length;
 	gfar_write(&priv->regs->fifo_tx_thr, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }
@@ -240,7 +240,7 @@
 	if (num > GFAR_MAX_FIFO_STARVE)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_starve = num;
 
@@ -249,7 +249,7 @@
 	temp |= num;
 	gfar_write(&priv->regs->fifo_tx_starve, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }
@@ -274,7 +274,7 @@
 	if (num > GFAR_MAX_FIFO_STARVE_OFF)
 		return count;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->txlock, flags);
 
 	priv->fifo_starve_off = num;
 
@@ -283,7 +283,7 @@
 	temp |= num;
 	gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->txlock, flags);
 
 	return count;
 }
diff --git a/drivers/net/hydra.h b/drivers/net/hydra.h
deleted file mode 100644
index 3741414..0000000
--- a/drivers/net/hydra.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*	$Linux: hydra.h,v 1.0 1994/10/26 02:03:47 cgd Exp $	*/
-
-/*
- * Copyright (c) 1994 Timo Rossi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by  Timo Rossi
- * 4. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * The Hydra Systems card uses the National Semiconductor
- * 8390 NIC (Network Interface Controller) chip, located
- * at card base address + 0xffe1. NIC registers are accessible
- * only at odd byte addresses, so the register offsets must
- * be multiplied by two.
- *
- * Card address PROM is located at card base + 0xffc0 (even byte addresses)
- *
- * RAM starts at the card base address, and is 16K or 64K.
- * The current Amiga NetBSD hydra driver is hardwired for 16K.
- * It seems that the RAM should be accessed as words or longwords only.
- *
- */
-
-/* adapted for Linux by Topi Kanerva 03/29/95
-   with original author's permission          */
-
-#define HYDRA_NIC_BASE 0xffe1
-
-/* Page0 registers */
-
-#define NIC_CR     0       /* Command register   */
-#define NIC_PSTART (1*2)   /* Page start (write) */
-#define NIC_PSTOP  (2*2)   /* Page stop (write)  */
-#define NIC_BNDRY  (3*2)   /* Boundary pointer   */
-#define NIC_TSR    (4*2)   /* Transmit status (read) */
-#define NIC_TPSR   (4*2)   /* Transmit page start (write) */
-#define NIC_NCR    (5*2)   /* Number of collisions, read  */
-#define NIC_TBCR0  (5*2)   /* Transmit byte count low (write)  */
-#define NIC_FIFO   (6*2)   /* FIFO reg. (read)   */
-#define NIC_TBCR1  (6*2)   /* Transmit byte count high (write) */
-#define NIC_ISR    (7*2)   /* Interrupt status register */
-#define NIC_RBCR0  (0xa*2) /* Remote byte count low (write)  */
-#define NIC_RBCR1  (0xb*2) /* Remote byte count high (write) */
-#define NIC_RSR    (0xc*2) /* Receive status (read)  */
-#define NIC_RCR    (0xc*2) /* Receive config (write) */
-#define NIC_CNTR0  (0xd*2) /* Frame alignment error count (read) */
-#define NIC_TCR    (0xd*2) /* Transmit config (write)  */
-#define NIC_CNTR1  (0xe*2) /* CRC error counter (read) */
-#define NIC_DCR    (0xe*2) /* Data config (write) */
-#define NIC_CNTR2  (0xf*2) /* missed packet counter (read) */
-#define NIC_IMR    (0xf*2) /* Interrupt mask reg. (write)  */
-
-/* Page1 registers */
-
-#define NIC_PAR0   (1*2)   /* Physical address */
-#define NIC_PAR1   (2*2)
-#define NIC_PAR2   (3*2)
-#define NIC_PAR3   (4*2)
-#define NIC_PAR4   (5*2)
-#define NIC_PAR5   (6*2)
-#define NIC_CURR   (7*2)   /* Current RX ring-buffer page */
-#define NIC_MAR0   (8*2)   /* Multicast address */
-#define NIC_MAR1   (9*2)
-#define NIC_MAR2   (0xa*2)
-#define NIC_MAR3   (0xb*2)
-#define NIC_MAR4   (0xc*2)
-#define NIC_MAR5   (0xd*2)
-#define NIC_MAR6   (0xe*2)
-#define NIC_MAR7   (0xf*2)
-
-/* Command register definitions */
-
-#define CR_STOP   0x01 /* Stop -- software reset command */
-#define CR_START  0x02 /* Start */
-#define CR_TXP   0x04 /* Transmit packet */
-
-#define CR_RD0    0x08 /* Remote DMA cmd */
-#define CR_RD1    0x10
-#define CR_RD2    0x20
-
-#define CR_NODMA  CR_RD2
-
-#define CR_PS0    0x40 /* Page select */
-#define CR_PS1    0x80
-
-#define CR_PAGE0  0
-#define CR_PAGE1  CR_PS0
-#define CR_PAGE2  CR_PS1
-
-/* Interrupt status reg. definitions */
-
-#define ISR_PRX   0x01 /* Packet received without errors */
-#define ISR_PTX   0x02 /* Packet transmitted without errors */
-#define ISR_RXE   0x04 /* Receive error  */
-#define ISR_TXE   0x08 /* Transmit error */
-#define ISR_OVW   0x10 /* Ring buffer overrun */
-#define ISR_CNT   0x20 /* Counter overflow    */
-#define ISR_RDC   0x40 /* Remote DMA compile */
-#define ISR_RST   0x80 /* Reset status      */
-
-/* Data config reg. definitions */
-
-#define DCR_WTS   0x01 /* Word transfer select  */
-#define DCR_BOS   0x02 /* Byte order select     */
-#define DCR_LAS   0x04 /* Long address select   */
-#define DCR_LS    0x08 /* Loopback select       */
-#define DCR_AR    0x10 /* Auto-init remote      */
-#define DCR_FT0   0x20 /* FIFO threshold select */
-#define DCR_FT1   0x40
-
-/* Transmit config reg. definitions */
-
-#define TCR_CRC  0x01 /* Inhibit CRC */
-#define TCR_LB0  0x02 /* Loopback control */
-#define TCR_LB1  0x04
-#define TCR_ATD  0x08 /* Auto transmit disable */
-#define TCR_OFST 0x10 /* Collision offset enable */
-
-/* Transmit status reg. definitions */
-
-#define TSR_PTX  0x01 /* Packet transmitted */
-#define TSR_COL  0x04 /* Transmit collided */
-#define TSR_ABT  0x08 /* Transmit aborted */
-#define TSR_CRS  0x10 /* Carrier sense lost */
-#define TSR_FU   0x20 /* FIFO underrun */
-#define TSR_CDH  0x40 /* CD Heartbeat */
-#define TSR_OWC  0x80 /* Out of Window Collision */
-
-/* Receiver config register definitions */
-
-#define RCR_SEP  0x01 /* Save errored packets */
-#define RCR_AR   0x02 /* Accept runt packets */
-#define RCR_AB   0x04 /* Accept broadcast */
-#define RCR_AM   0x08 /* Accept multicast */
-#define RCR_PRO  0x10 /* Promiscuous mode */
-#define RCR_MON  0x20 /* Monitor mode */
-
-/* Receiver status register definitions */
-
-#define RSR_PRX  0x01 /* Packet received without error */
-#define RSR_CRC  0x02 /* CRC error */
-#define RSR_FAE  0x04 /* Frame alignment error */
-#define RSR_FO   0x08 /* FIFO overrun */
-#define RSR_MPA  0x10 /* Missed packet */
-#define RSR_PHY  0x20 /* Physical address */
-#define RSR_DIS  0x40 /* Received disabled */
-#define RSR_DFR  0x80 /* Deferring (jabber) */
-
-/* Hydra System card address PROM offset */
-
-#define HYDRA_ADDRPROM 0xffc0
-
-
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ceb98fd..52d0102 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -235,7 +235,7 @@
 
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 		    
-		if(lpar_rc != H_Success) {
+		if(lpar_rc != H_SUCCESS) {
 			pool->free_map[free_index] = index;
 			pool->skbuff[index] = NULL;
 			pool->consumer_index--;
@@ -373,7 +373,7 @@
 
 	lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 		    
-	if(lpar_rc != H_Success) {
+	if(lpar_rc != H_SUCCESS) {
 		ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
 		ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
 	}
@@ -511,7 +511,7 @@
 					 adapter->filter_list_dma,
 					 mac_address);
 
-	if(lpar_rc != H_Success) {
+	if(lpar_rc != H_SUCCESS) {
 		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
 		ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
 				     adapter->buffer_list_dma,
@@ -527,7 +527,7 @@
 		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
 		do {
 			rc = h_free_logical_lan(adapter->vdev->unit_address);
-		} while (H_isLongBusy(rc) || (rc == H_Busy));
+		} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
 
 		ibmveth_cleanup(adapter);
 		return rc;
@@ -556,9 +556,9 @@
 
 	do {
 		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
-	} while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
+	} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
 
-	if(lpar_rc != H_Success)
+	if(lpar_rc != H_SUCCESS)
 	{
 		ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
 				     lpar_rc);
@@ -693,9 +693,9 @@
 					     desc[4].desc,
 					     desc[5].desc,
 					     correlator);
-	} while ((lpar_rc == H_Busy) && (retry_count--));
+	} while ((lpar_rc == H_BUSY) && (retry_count--));
     
-	if(lpar_rc != H_Success && lpar_rc != H_Dropped) {
+	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
 		int i;
 		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
 		for(i = 0; i < 6; i++) {
@@ -786,14 +786,14 @@
 	/* we think we are done - reenable interrupts, then check once more to make sure we are done */
 	lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE);
 
-	ibmveth_assert(lpar_rc == H_Success);
+	ibmveth_assert(lpar_rc == H_SUCCESS);
 
 	netif_rx_complete(netdev);
 
 	if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed))
 	{
 		lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
-		ibmveth_assert(lpar_rc == H_Success);
+		ibmveth_assert(lpar_rc == H_SUCCESS);
 		more_work = 1;
 		goto restart_poll;
 	}
@@ -813,7 +813,7 @@
 
 	if(netif_rx_schedule_prep(netdev)) {
 		lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
-		ibmveth_assert(lpar_rc == H_Success);
+		ibmveth_assert(lpar_rc == H_SUCCESS);
 		__netif_rx_schedule(netdev);
 	}
 	return IRQ_HANDLED;
@@ -835,7 +835,7 @@
 					   IbmVethMcastEnableRecv |
 					   IbmVethMcastDisableFiltering,
 					   0);
-		if(lpar_rc != H_Success) {
+		if(lpar_rc != H_SUCCESS) {
 			ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
 		}
 	} else {
@@ -847,7 +847,7 @@
 					   IbmVethMcastDisableFiltering |
 					   IbmVethMcastClearFilterTable,
 					   0);
-		if(lpar_rc != H_Success) {
+		if(lpar_rc != H_SUCCESS) {
 			ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
 		}
 		/* add the addresses to the filter table */
@@ -858,7 +858,7 @@
 			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 						   IbmVethMcastAddFilter,
 						   mcast_addr);
-			if(lpar_rc != H_Success) {
+			if(lpar_rc != H_SUCCESS) {
 				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
 			}
 		}
@@ -867,7 +867,7 @@
 		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 					   IbmVethMcastEnableFiltering,
 					   0);
-		if(lpar_rc != H_Success) {
+		if(lpar_rc != H_SUCCESS) {
 			ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
 		}
 	}
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6e2ec56..96bdb73 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1,7 +1,7 @@
 /*****************************************************************************
  *
  * Filename:      irda-usb.c
- * Version:       0.9b
+ * Version:       0.10
  * Description:   IrDA-USB Driver
  * Status:        Experimental 
  * Author:        Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
  *	Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
  *      Copyright (C) 2001, Dag Brattli <dag@brattli.net>
  *      Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ *      Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ *      Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ *      Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua>
  *          
  *	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
@@ -61,6 +64,7 @@
 #include <linux/slab.h>
 #include <linux/rtnetlink.h>
 #include <linux/usb.h>
+#include <linux/firmware.h>
 
 #include "irda-usb.h"
 
@@ -78,8 +82,12 @@
 	{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
 	/* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */
 	{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
+	/* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
+	{ USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+	{ USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+	{ USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
-	               USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	  USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 	  .bInterfaceClass = USB_CLASS_APP_SPEC,
 	  .bInterfaceSubClass = USB_CLASS_IRDA,
 	  .driver_info = IUC_DEFAULT, },
@@ -99,6 +107,7 @@
 
 /*------------------------------------------------------------------*/
 
+static void irda_usb_init_qos(struct irda_usb_cb *self) ;
 static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf);
 static void irda_usb_disconnect(struct usb_interface *intf);
 static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
@@ -141,7 +150,24 @@
 				  __u8 *header,
 				  int	force)
 {
-	/* Set the negotiated link speed */
+	/* Here we check if we have an STIR421x chip,
+	 * and if either speed or xbofs (or both) needs
+	 * to be changed.
+	 */
+	if (self->capability & IUC_STIR_4210 &&
+	    ((self->new_speed != -1) || (self->new_xbofs != -1))) {
+
+		/* With STIR421x, speed and xBOFs must be set at the same
+		 * time, even if only one of them changes.
+		 */
+		if (self->new_speed == -1)
+			self->new_speed = self->speed ;
+
+		if (self->new_xbofs == -1)
+			self->new_xbofs = self->xbofs ;
+	}
+
+	/* Set the link speed */
 	if (self->new_speed != -1) {
 		/* Hum... Ugly hack :-(
 		 * Some device are not compliant with the spec and change
@@ -191,7 +217,11 @@
 		        *header = SPEED_4000000;
 			self->new_xbofs = 0;
 			break;
-		}
+		case 16000000:
+			*header = SPEED_16000000;
+  			self->new_xbofs = 0;
+  			break;
+  		}
 	} else
 		/* No change */
 		*header = 0;
@@ -235,6 +265,32 @@
 	}
 }
 
+/*
+*   calculate turnaround time for SigmaTel header
+*/
+static __u8 get_turnaround_time(struct sk_buff *skb)
+{
+	int turnaround_time = irda_get_mtt(skb);
+
+	if ( turnaround_time == 0 )
+		return 0;
+	else if ( turnaround_time <= 10 )
+		return 1;
+	else if ( turnaround_time <= 50 )
+		return 2;
+	else if ( turnaround_time <= 100 )
+		return 3;
+	else if ( turnaround_time <= 500 )
+		return 4;
+	else if ( turnaround_time <= 1000 )
+		return 5;
+	else if ( turnaround_time <= 5000 )
+		return 6;
+	else
+		return 7;
+}
+
+
 /*------------------------------------------------------------------*/
 /*
  * Send a command to change the speed of the dongle
@@ -262,12 +318,18 @@
 	/* Set the new speed and xbofs in this fake frame */
 	irda_usb_build_header(self, frame, 1);
 
+	if ( self->capability & IUC_STIR_4210 ) {
+		if (frame[0] == 0) return ; // do nothing if no change
+		frame[1] = 0; // other parameters don't change here
+		frame[2] = 0;
+	}
+
 	/* Submit the 0 length IrDA frame to trigger new speed settings */
         usb_fill_bulk_urb(urb, self->usbdev,
 		      usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
                       frame, IRDA_USB_SPEED_MTU,
                       speed_bulk_callback, self);
-	urb->transfer_buffer_length = USB_IRDA_HEADER;
+	urb->transfer_buffer_length = self->header_length;
 	urb->transfer_flags = 0;
 
 	/* Irq disabled -> GFP_ATOMIC */
@@ -383,16 +445,35 @@
 	 * allocation will be done lower in skb_push().
 	 * Also, we don't use directly skb_cow(), because it require
 	 * headroom >= 16, which force unnecessary copies - Jean II */
-	if (skb_headroom(skb) < USB_IRDA_HEADER) {
+	if (skb_headroom(skb) < self->header_length) {
 		IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
-		if (skb_cow(skb, USB_IRDA_HEADER)) {
+		if (skb_cow(skb, self->header_length)) {
 			IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
 			goto drop;
 		}
 	}
 
 	/* Change setting for next frame */
-	irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
+
+	if ( self->capability & IUC_STIR_4210 ) {
+		__u8 turnaround_time;
+		__u8* frame;
+		turnaround_time = get_turnaround_time( skb );
+		frame= skb_push(skb, self->header_length);
+		irda_usb_build_header(self, frame, 0);
+		frame[2] = turnaround_time;
+		if ((skb->len != 0) &&
+		    ((skb->len % 128) == 0) &&
+		    ((skb->len % 512) != 0)) {
+			/* add extra byte for special SigmaTel feature */
+			frame[1] = 1;
+			skb_put(skb, 1);
+		} else {
+			frame[1] = 0;
+		}
+	} else {
+		irda_usb_build_header(self, skb_push(skb, self->header_length), 0);
+	}
 
 	/* FIXME: Make macro out of this one */
 	((struct irda_skb_cb *)skb->cb)->context = self;
@@ -795,7 +876,7 @@
 	}
 	
 	/* Check for empty frames */
-	if (urb->actual_length <= USB_IRDA_HEADER) {
+	if (urb->actual_length <= self->header_length) {
 		IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
 		goto done;
 	}
@@ -816,7 +897,11 @@
 	docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
 
 	/* Allocate a new skb */
-	newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+	if ( self->capability & IUC_STIR_4210 )
+		newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
+	else
+		newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+
 	if (!newskb)  {
 		self->stats.rx_dropped++;
 		/* We could deliver the current skb, but this would stall
@@ -845,7 +930,7 @@
 
 	/* Set proper length on skb & remove USB-IrDA header */
 	skb_put(dataskb, urb->actual_length);
-	skb_pull(dataskb, USB_IRDA_HEADER);
+	skb_pull(dataskb, self->header_length);
 
 	/* Ask the networking layer to queue the packet for the IrDA stack */
 	dataskb->dev = self->netdev;
@@ -937,6 +1022,191 @@
 	return 0; /* For now */
 }
 
+
+#define STIR421X_PATCH_PRODUCT_VERSION_STR       "Product Version: "
+#define STIR421X_PATCH_COMPONENT_VERSION_STR     "Component Version: "
+#define STIR421X_PATCH_DATA_TAG_STR              "STMP"
+#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET   512     /* version info is before here */
+#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET     512     /* patch image starts before here */
+#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG    0x1A    /* marks end of patch file header (PC DOS text file EOF character) */
+
+/*
+ * Known firmware patches for STIR421x dongles
+ */
+static char * stir421x_patches[] = {
+	"42101001.sb",
+	"42101002.sb",
+};
+
+static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
+{
+	unsigned int version_offset;
+	unsigned long version_major, version_minor, version_build;
+	unsigned char * version_start;
+	int version_found = 0;
+
+	for (version_offset = 0;
+	     version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
+	     version_offset++) {
+		if (!memcmp(patch + version_offset,
+			    STIR421X_PATCH_PRODUCT_VERSION_STR,
+			    sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
+				    version_found = 1;
+				    version_start = patch +
+					    version_offset +
+					    sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
+				    break;
+		}
+	}
+
+	/* We couldn't find a product version on this patch */
+	if (!version_found)
+		return -EINVAL;
+
+	/* Let's check if the product version is dotted */
+	if (version_start[3] != '.' ||
+	    version_start[7] != '.')
+		return -EINVAL;
+
+	version_major = simple_strtoul(version_start, NULL, 10);
+	version_minor = simple_strtoul(version_start + 4, NULL, 10);
+	version_build = simple_strtoul(version_start + 8, NULL, 10);
+
+	IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
+		   __FUNCTION__,
+		   version_major, version_minor, version_build);
+
+	return (((version_major) << 12) +
+		((version_minor) << 8) +
+		((version_build / 10) << 4) +
+		(version_build % 10));
+
+}
+
+
+static int stir421x_upload_patch (struct irda_usb_cb *self,
+				  unsigned char * patch,
+				  const unsigned int patch_len)
+{
+    int retval = 0;
+    int actual_len;
+    unsigned int i = 0, download_amount = 0;
+    unsigned char * patch_chunk;
+
+    IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
+
+    patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
+    if (patch_chunk == NULL)
+	    return -ENOMEM;
+
+    /* break up patch into 1023-byte sections */
+    for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
+	    download_amount = patch_len - i;
+	    if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
+		    download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
+
+	    /* download the patch section */
+	    memcpy(patch_chunk, patch + i, download_amount);
+
+	    retval = usb_bulk_msg (self->usbdev,
+				   usb_sndbulkpipe (self->usbdev,
+						    self->bulk_out_ep),
+				   patch_chunk, download_amount,
+				   &actual_len, msecs_to_jiffies (500));
+	    IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
+			actual_len);
+	    if (retval == 0)
+		    mdelay(10);
+    }
+
+    kfree(patch_chunk);
+
+    if (i != patch_len) {
+	    IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
+		       __FUNCTION__, i, patch_len);
+	    retval = -EIO;
+    }
+
+    if (retval < 0)
+	    /* todo - mark device as not ready */
+	    IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
+			__FUNCTION__, retval);
+
+    return retval;
+}
+
+
+static int stir421x_patch_device(struct irda_usb_cb *self)
+{
+	unsigned int i, patch_found = 0, data_found = 0, data_offset;
+	int patch_version, ret = 0;
+	const struct firmware *fw_entry;
+
+	for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
+		if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
+			IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
+			continue;
+		}
+
+                /* We found a patch from userspace */
+		patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
+
+		if (patch_version < 0) {
+			/* Couldn't fetch a version, let's move on to the next file */
+			IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
+			ret = patch_version;
+			release_firmware(fw_entry);
+			continue;
+		}
+
+		if (patch_version != self->usbdev->descriptor.bcdDevice) {
+			/* Patch version and device don't match */
+			IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
+				    __FUNCTION__,
+				    patch_version, self->usbdev->descriptor.bcdDevice);
+			ret = -EINVAL;
+			release_firmware(fw_entry);
+			continue;
+		}
+
+		/* If we're here, we've found a correct patch */
+		patch_found = 1;
+		break;
+
+	}
+
+	/* We couldn't find a valid firmware, let's leave */
+	if (!patch_found)
+		return ret;
+
+	/* The actual image starts after the "STMP" keyword */
+	for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
+		if (!memcmp(fw_entry->data + data_offset,
+			    STIR421X_PATCH_DATA_TAG_STR,
+			    sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
+			IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
+				   __FUNCTION__, data_offset);
+			data_found = 1;
+			break;
+		}
+	}
+
+	/* We couldn't find "STMP" from the header */
+	if (!data_found)
+		return -EINVAL;
+
+	/* Let's upload the patch to the target */
+	ret = stir421x_upload_patch(self,
+				    &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
+				    fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
+
+	release_firmware(fw_entry);
+
+	return ret;
+
+}
+
+
 /********************** IRDA DEVICE CALLBACKS **********************/
 /*
  * Main calls from the IrDA/Network subsystem.
@@ -972,6 +1242,11 @@
 		return -1;
 	}
 
+	if(self->needspatch) {
+		IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ;
+		return -EIO ;
+	}
+
 	/* Initialise default speed and xbofs value
 	 * (IrLAP will change that soon) */
 	self->speed = -1;
@@ -1050,7 +1325,7 @@
 	del_timer(&self->rx_defer_timer);
 
 	/* Deallocate all the Rx path buffers (URBs and skb) */
-	for (i = 0; i < IU_MAX_RX_URBS; i++) {
+	for (i = 0; i < self->max_rx_urb; i++) {
 		struct urb *urb = self->rx_urb[i];
 		struct sk_buff *skb = (struct sk_buff *) urb->context;
 		/* Cancel the receive command */
@@ -1426,8 +1701,22 @@
 	spin_lock_init(&self->lock);
 	init_timer(&self->rx_defer_timer);
 
+	self->capability = id->driver_info;
+	self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
+
 	/* Create all of the needed urbs */
-	for (i = 0; i < IU_MAX_RX_URBS; i++) {
+	if (self->capability & IUC_STIR_4210) {
+		self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
+		self->header_length = USB_IRDA_SIGMATEL_HEADER;
+	} else {
+		self->max_rx_urb = IU_MAX_RX_URBS;
+		self->header_length = USB_IRDA_HEADER;
+	}
+
+	self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *),
+				GFP_KERNEL);
+
+	for (i = 0; i < self->max_rx_urb; i++) {
 		self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
 		if (!self->rx_urb[i]) {
 			goto err_out_1;
@@ -1479,17 +1768,28 @@
 		goto err_out_3;
 	}
 
+	self->usbdev = dev;
+
 	/* Find IrDA class descriptor */
 	irda_desc = irda_usb_find_class_desc(intf);
 	ret = -ENODEV;
 	if (irda_desc == NULL)
 		goto err_out_3;
 
+	if (self->needspatch) {
+		ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
+				       0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500));
+		if (ret < 0) {
+			IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
+			goto err_out_3;
+		} else {
+			mdelay(10);
+		}
+	}
+
 	self->irda_desc =  irda_desc;
 	self->present = 1;
 	self->netopen = 0;
-	self->capability = id->driver_info;
-	self->usbdev = dev;
 	self->usbintf = intf;
 
 	/* Allocate the buffer for speed changes */
@@ -1508,8 +1808,32 @@
 
 	IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
 	usb_set_intfdata(intf, self);
+
+	if (self->needspatch) {
+		/* Now we fetch and upload the firmware patch */
+		ret = stir421x_patch_device(self);
+		self->needspatch = (ret < 0);
+		if (ret < 0) {
+			printk("patch_device failed\n");
+			goto err_out_5;
+		}
+
+		/* replace IrDA class descriptor with what patched device is now reporting */
+		irda_desc = irda_usb_find_class_desc (self->usbintf);
+		if (irda_desc == NULL) {
+			ret = -ENODEV;
+			goto err_out_5;
+		}
+		if (self->irda_desc)
+			kfree (self->irda_desc);
+		self->irda_desc = irda_desc;
+		irda_usb_init_qos(self);
+	}
+
 	return 0;
 
+err_out_5:
+	unregister_netdev(self->netdev);
 err_out_4:
 	kfree(self->speed_buff);
 err_out_3:
@@ -1518,7 +1842,7 @@
 err_out_2:
 	usb_free_urb(self->tx_urb);
 err_out_1:
-	for (i = 0; i < IU_MAX_RX_URBS; i++) {
+	for (i = 0; i < self->max_rx_urb; i++) {
 		if (self->rx_urb[i])
 			usb_free_urb(self->rx_urb[i]);
 	}
@@ -1571,7 +1895,7 @@
 		/*netif_device_detach(self->netdev);*/
 		netif_stop_queue(self->netdev);
 		/* Stop all the receive URBs. Must be synchronous. */
-		for (i = 0; i < IU_MAX_RX_URBS; i++)
+		for (i = 0; i < self->max_rx_urb; i++)
 			usb_kill_urb(self->rx_urb[i]);
 		/* Cancel Tx and speed URB.
 		 * Make sure it's synchronous to avoid races. */
@@ -1586,8 +1910,9 @@
 	self->usbintf = NULL;
 
 	/* Clean up our urbs */
-	for (i = 0; i < IU_MAX_RX_URBS; i++)
+	for (i = 0; i < self->max_rx_urb; i++)
 		usb_free_urb(self->rx_urb[i]);
+	kfree(self->rx_urb);
 	/* Clean up Tx and speed URB */
 	usb_free_urb(self->tx_urb);
 	usb_free_urb(self->speed_urb);
@@ -1648,6 +1973,6 @@
  */
 module_param(qos_mtt_bits, int, 0);
 MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
-MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
-MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); 
+MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index 4026af4..d833db5 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
  *
  * Filename:      irda-usb.h
- * Version:       0.9b
+ * Version:       0.10
  * Description:   IrDA-USB Driver
  * Status:        Experimental 
  * Author:        Dag Brattli <dag@brattli.net>
@@ -9,6 +9,9 @@
  *	Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
  *      Copyright (C) 2000, Dag Brattli <dag@brattli.net>
  *      Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+ *      Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com>
+ *      Copyright (C) 2005, Milan Beno <beno@pobox.sk>
+ *      Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua>
  *          
  *	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
@@ -31,6 +34,9 @@
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>      /* struct irlap_cb */
 
+#define PATCH_FILE_SIZE_MAX     65536
+#define PATCH_FILE_SIZE_MIN     80
+
 #define RX_COPY_THRESHOLD 200
 #define IRDA_USB_MAX_MTU 2051
 #define IRDA_USB_SPEED_MTU 64		/* Weird, but work like this */
@@ -79,15 +85,16 @@
 /* Inbound header */
 #define MEDIA_BUSY    0x80
 
-#define SPEED_2400    0x01
-#define SPEED_9600    0x02
-#define SPEED_19200   0x03
-#define SPEED_38400   0x04
-#define SPEED_57600   0x05
-#define SPEED_115200  0x06
-#define SPEED_576000  0x07
-#define SPEED_1152000 0x08
-#define SPEED_4000000 0x09
+#define SPEED_2400     0x01
+#define SPEED_9600     0x02
+#define SPEED_19200    0x03
+#define SPEED_38400    0x04
+#define SPEED_57600    0x05
+#define SPEED_115200   0x06
+#define SPEED_576000   0x07
+#define SPEED_1152000  0x08
+#define SPEED_4000000  0x09
+#define SPEED_16000000 0x0a
 
 /* Basic capabilities */
 #define IUC_DEFAULT	0x00	/* Basic device compliant with 1.0 spec */
@@ -100,11 +107,14 @@
 #define IUC_SMALL_PKT	0x10	/* Device doesn't behave with big Rx packets */
 #define IUC_MAX_WINDOW	0x20	/* Device underestimate the Rx window */
 #define IUC_MAX_XBOFS	0x40	/* Device need more xbofs than advertised */
+#define IUC_STIR_4210	0x80	/* SigmaTel 4210/4220/4116 VFIR */
 
 /* USB class definitions */
-#define USB_IRDA_HEADER   0x01
-#define USB_CLASS_IRDA    0x02 /* USB_CLASS_APP_SPEC subclass */ 
-#define USB_DT_IRDA       0x21
+#define USB_IRDA_HEADER            0x01
+#define USB_CLASS_IRDA             0x02 /* USB_CLASS_APP_SPEC subclass */
+#define USB_DT_IRDA                0x21
+#define USB_IRDA_SIGMATEL_HEADER   0x03
+#define IU_SIGMATEL_MAX_RX_URBS    (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
 
 struct irda_class_desc {
 	__u8  bLength;
@@ -123,6 +133,7 @@
  * (6.2.5, USB-IrDA class spec 1.0) */
 
 #define IU_REQ_GET_CLASS_DESC	0x06
+#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023
 
 struct irda_usb_cb {
 	struct irda_class_desc *irda_desc;
@@ -136,7 +147,8 @@
 	__u16 bulk_out_mtu;		/* Max Tx packet size in bytes */
 	__u8  bulk_int_ep;		/* Interrupt Endpoint assignments */
 
-	struct urb *rx_urb[IU_MAX_RX_URBS];	/* URBs used to receive data frames */
+	__u8  max_rx_urb;
+	struct urb **rx_urb;	        /* URBs used to receive data frames */
 	struct urb *idle_rx_urb;	/* Pointer to idle URB in Rx path */
 	struct urb *tx_urb;		/* URB used to send data frames */
 	struct urb *speed_urb;		/* URB used to send speed commands */
@@ -157,6 +169,9 @@
 	__u32 speed;			/* Current speed */
 	__s32 new_speed;		/* speed we need to set */
 
+	__u8 header_length;             /* USB-IrDA frame header size */
+	int needspatch;        		/* device needs firmware patch */
+
 	struct timer_list rx_defer_timer;	/* Wait for Rx error to clear */
 };
 
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 63d38fb..f530686 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -695,8 +695,7 @@
 		/*
 		 * We must not be transmitting...
 		 */
-		if (si->txskb)
-			BUG();
+		BUG_ON(si->txskb);
 
 		netif_stop_queue(dev);
 
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index ec94ecd..58f76ce 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -11,6 +11,7 @@
  *     Copyright (c) 2002      Daniele Peri
  *     All Rights Reserved.
  *     Copyright (c) 2002      Jean Tourrilhes
+ *     Copyright (c) 2006      Linus Walleij
  *
  *
  * Based on smc-ircc.c:
@@ -61,6 +62,9 @@
 
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
 
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
@@ -100,6 +104,22 @@
 
 /* Types */
 
+#ifdef CONFIG_PCI
+struct smsc_ircc_subsystem_configuration {
+	unsigned short vendor; /* PCI vendor ID */
+	unsigned short device; /* PCI vendor ID */
+	unsigned short subvendor; /* PCI subsystem vendor ID */
+	unsigned short subdevice; /* PCI sybsystem device ID */
+	unsigned short sir_io; /* I/O port for SIR */
+	unsigned short fir_io; /* I/O port for FIR */
+	unsigned char  fir_irq; /* FIR IRQ */
+	unsigned char  fir_dma; /* FIR DMA */
+	unsigned short cfg_base; /* I/O port for chip configuration */
+	int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
+	const char *name;	/* name shown as info */
+};
+#endif
+
 struct smsc_transceiver {
 	char *name;
 	void (*set_for_speed)(int fir_base, u32 speed);
@@ -202,6 +222,18 @@
 static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
 static int __init smsc_superio_fdc(unsigned short cfg_base);
 static int __init smsc_superio_lpc(unsigned short cfg_base);
+#ifdef CONFIG_PCI
+static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
+static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+					 unsigned short port);
+static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+						    unsigned short ircc_fir,
+						    unsigned short ircc_sir,
+						    unsigned char ircc_dma,
+						    unsigned char ircc_irq);
+#endif
 
 /* Transceivers specific functions */
 
@@ -353,6 +385,13 @@
 		return ret;
 	}
 
+#ifdef CONFIG_PCI
+	if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
+		/* Ignore errors from preconfiguration */
+		IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
+	}
+#endif
+
 	dev_count = 0;
 
 	if (ircc_fir > 0 && ircc_sir > 0) {
@@ -2285,6 +2324,490 @@
 	return ret;
 }
 
+/*
+ * Look for some specific subsystem setups that need
+ * pre-configuration not properly done by the BIOS (especially laptops)
+ * This code is based in part on smcinit.c, tosh1800-smcinit.c
+ * and tosh2450-smcinit.c. The table lists the device entries
+ * for ISA bridges with an LPC (Low Pin Count) controller which
+ * handles the communication with the SMSC device. After the LPC
+ * controller is initialized through PCI, the SMSC device is initialized
+ * through a dedicated port in the ISA port-mapped I/O area, this latter
+ * area is used to configure the SMSC device with default
+ * SIR and FIR I/O ports, DMA and IRQ. Different vendors have
+ * used different sets of parameters and different control port
+ * addresses making a subsystem device table necessary.
+ */
+#ifdef CONFIG_PCI
+#define PCIID_VENDOR_INTEL 0x8086
+#define PCIID_VENDOR_ALI 0x10b9
+static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
+	{
+		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+		.device = 0x24cc,
+		.subvendor = 0x103c,
+		.subdevice = 0x088c,
+		/* Quite certain these are the same for nc8000 as for nc6000 */
+		.sir_io = 0x02f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x05,
+		.fir_dma = 0x03,
+		.cfg_base = 0x004e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "HP nc8000",
+	},
+	{
+		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
+		.device = 0x24cc,
+		.subvendor = 0x103c,
+		.subdevice = 0x0890,
+		.sir_io = 0x02f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x05,
+		.fir_dma = 0x03,
+		.cfg_base = 0x004e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "HP nc6000",
+	},
+	{
+		/* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
+		.vendor = PCIID_VENDOR_INTEL,
+		.device = 0x24c0,
+		.subvendor = 0x1179,
+		.subdevice = 0xffff, /* 0xffff is "any" */
+		.sir_io = 0x03f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x07,
+		.fir_dma = 0x01,
+		.cfg_base = 0x002e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
+	},
+	{
+		.vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
+		.device = 0x248c,
+		.subvendor = 0x1179,
+		.subdevice = 0xffff, /* 0xffff is "any" */
+		.sir_io = 0x03f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x03,
+		.fir_dma = 0x03,
+		.cfg_base = 0x002e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "Toshiba laptop with Intel 82801CAM ISA bridge",
+	},
+	{
+		/* 82801DBM (ICH4-M) LPC Interface Bridge */
+		.vendor = PCIID_VENDOR_INTEL,
+		.device = 0x24cc,
+		.subvendor = 0x1179,
+		.subdevice = 0xffff, /* 0xffff is "any" */
+		.sir_io = 0x03f8,
+		.fir_io = 0x0130,
+		.fir_irq = 0x03,
+		.fir_dma = 0x03,
+		.cfg_base = 0x002e,
+		.preconfigure = preconfigure_through_82801,
+		.name = "Toshiba laptop with Intel 8281DBM LPC bridge",
+	},
+	{
+		/* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
+		.vendor = PCIID_VENDOR_ALI,
+		.device = 0x1533,
+		.subvendor = 0x1179,
+		.subdevice = 0xffff, /* 0xffff is "any" */
+		.sir_io = 0x02e8,
+		.fir_io = 0x02f8,
+		.fir_irq = 0x07,
+		.fir_dma = 0x03,
+		.cfg_base = 0x002e,
+		.preconfigure = preconfigure_through_ali,
+		.name = "Toshiba laptop with ALi ISA bridge",
+	},
+	{ } // Terminator
+};
+
+
+/*
+ * This sets up the basic SMSC parameters
+ * (FIR port, SIR port, FIR DMA, FIR IRQ)
+ * through the chip configuration port.
+ */
+static int __init preconfigure_smsc_chip(struct
+					 smsc_ircc_subsystem_configuration
+					 *conf)
+{
+	unsigned short iobase = conf->cfg_base;
+	unsigned char tmpbyte;
+
+	outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
+	outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
+	tmpbyte = inb(iobase +1); // Read device ID
+	IRDA_DEBUG(0,
+		   "Detected Chip id: 0x%02x, setting up registers...\n",
+		   tmpbyte);
+
+	/* Disable UART1 and set up SIR I/O port */
+	outb(0x24, iobase);  // select CR24 - UART1 base addr
+	outb(0x00, iobase + 1); // disable UART1
+	outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase);  // select CR25 - UART2 base addr
+	outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
+	tmpbyte = inb(iobase + 1);
+	if (tmpbyte != (conf->sir_io >> 2) ) {
+		IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
+		IRDA_WARNING("Try to supply ircc_cfg argument.\n");
+		return -ENXIO;
+	}
+
+	/* Set up FIR IRQ channel for UART2 */
+	outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
+	tmpbyte = inb(iobase + 1);
+	tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
+	tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
+	outb(tmpbyte, iobase + 1);
+	tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
+	if (tmpbyte != conf->fir_irq) {
+		IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
+		return -ENXIO;
+	}
+
+	/* Set up FIR I/O port */
+	outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase);  // CR2B - SCE (FIR) base addr
+	outb((conf->fir_io >> 3), iobase + 1);
+	tmpbyte = inb(iobase + 1);
+	if (tmpbyte != (conf->fir_io >> 3) ) {
+		IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
+		return -ENXIO;
+	}
+
+	/* Set up FIR DMA channel */
+	outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase);  // CR2C - SCE (FIR) DMA select
+	outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
+	tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
+	if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
+		IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
+		return -ENXIO;
+	}
+
+	outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase);  // CR0C - UART mode
+	tmpbyte = inb(iobase + 1);
+	tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK |
+		SMSCSIOFLAT_UART2MODE_VAL_IRDA;
+	outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
+
+	outb(LPC47N227_APMBOOTDRIVE_REG, iobase);  // CR07 - Auto Pwr Mgt/boot drive sel
+	tmpbyte = inb(iobase + 1);
+	outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
+
+	/* This one was not part of tosh1800 */
+	outb(0x0a, iobase);  // CR0a - ecp fifo / ir mux
+	tmpbyte = inb(iobase + 1);
+	outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
+
+	outb(LPC47N227_UART12POWER_REG, iobase);  // CR02 - UART 1,2 power
+	tmpbyte = inb(iobase + 1);
+	outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
+
+	outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase);  // CR00 - FDC Power/valid config cycle
+	tmpbyte = inb(iobase + 1);
+	outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
+
+	outb(LPC47N227_CFGEXITKEY, iobase);  // Exit configuration
+
+	return 0;
+}
+
+/* 82801CAM generic registers */
+#define VID 0x00
+#define DID 0x02
+#define PIRQ_A_D_ROUT 0x60
+#define SIRQ_CNTL 0x64
+#define PIRQ_E_H_ROUT 0x68
+#define PCI_DMA_C 0x90
+/* LPC-specific registers */
+#define COM_DEC 0xe0
+#define GEN1_DEC 0xe4
+#define LPC_EN 0xe6
+#define GEN2_DEC 0xec
+/*
+ * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge
+ * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.
+ * They all work the same way!
+ */
+static int __init preconfigure_through_82801(struct pci_dev *dev,
+					     struct
+					     smsc_ircc_subsystem_configuration
+					     *conf)
+{
+	unsigned short tmpword;
+	unsigned char tmpbyte;
+
+	IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n");
+	/*
+	 * Select the range for the COMA COM port (SIR)
+	 * Register COM_DEC:
+	 * Bit 7: reserved
+	 * Bit 6-4, COMB decode range
+	 * Bit 3: reserved
+	 * Bit 2-0, COMA decode range
+	 *
+	 * Decode ranges:
+	 *   000 = 0x3f8-0x3ff (COM1)
+	 *   001 = 0x2f8-0x2ff (COM2)
+	 *   010 = 0x220-0x227
+	 *   011 = 0x228-0x22f
+	 *   100 = 0x238-0x23f
+	 *   101 = 0x2e8-0x2ef (COM4)
+	 *   110 = 0x338-0x33f
+	 *   111 = 0x3e8-0x3ef (COM3)
+	 */
+	pci_read_config_byte(dev, COM_DEC, &tmpbyte);
+	tmpbyte &= 0xf8; /* mask COMA bits */
+	switch(conf->sir_io) {
+	case 0x3f8:
+		tmpbyte |= 0x00;
+		break;
+	case 0x2f8:
+		tmpbyte |= 0x01;
+		break;
+	case 0x220:
+		tmpbyte |= 0x02;
+		break;
+	case 0x228:
+		tmpbyte |= 0x03;
+		break;
+	case 0x238:
+		tmpbyte |= 0x04;
+		break;
+	case 0x2e8:
+		tmpbyte |= 0x05;
+		break;
+	case 0x338:
+		tmpbyte |= 0x06;
+		break;
+	case 0x3e8:
+		tmpbyte |= 0x07;
+		break;
+	default:
+		tmpbyte |= 0x01; /* COM2 default */
+	}
+	IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte);
+	pci_write_config_byte(dev, COM_DEC, tmpbyte);
+
+	/* Enable Low Pin Count interface */
+	pci_read_config_word(dev, LPC_EN, &tmpword);
+	/* These seem to be set up at all times,
+	 * just make sure it is properly set.
+	 */
+	switch(conf->cfg_base) {
+	case 0x04e:
+		tmpword |= 0x2000;
+		break;
+	case 0x02e:
+		tmpword |= 0x1000;
+		break;
+	case 0x062:
+		tmpword |= 0x0800;
+		break;
+	case 0x060:
+		tmpword |= 0x0400;
+		break;
+	default:
+		IRDA_WARNING("Uncommon I/O base address: 0x%04x\n",
+			     conf->cfg_base);
+		break;
+	}
+	tmpword &= 0xfffd; /* disable LPC COMB */
+	tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */
+	IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword);
+	pci_write_config_word(dev, LPC_EN, tmpword);
+
+	/*
+	 * Configure LPC DMA channel
+	 * PCI_DMA_C bits:
+	 * Bit 15-14: DMA channel 7 select
+	 * Bit 13-12: DMA channel 6 select
+	 * Bit 11-10: DMA channel 5 select
+	 * Bit 9-8:   Reserved
+	 * Bit 7-6:   DMA channel 3 select
+	 * Bit 5-4:   DMA channel 2 select
+	 * Bit 3-2:   DMA channel 1 select
+	 * Bit 1-0:   DMA channel 0 select
+	 *  00 = Reserved value
+	 *  01 = PC/PCI DMA
+	 *  10 = Reserved value
+	 *  11 = LPC I/F DMA
+	 */
+	pci_read_config_word(dev, PCI_DMA_C, &tmpword);
+	switch(conf->fir_dma) {
+	case 0x07:
+		tmpword |= 0xc000;
+		break;
+	case 0x06:
+		tmpword |= 0x3000;
+		break;
+	case 0x05:
+		tmpword |= 0x0c00;
+		break;
+	case 0x03:
+		tmpword |= 0x00c0;
+		break;
+	case 0x02:
+		tmpword |= 0x0030;
+		break;
+	case 0x01:
+		tmpword |= 0x000c;
+		break;
+	case 0x00:
+		tmpword |= 0x0003;
+		break;
+	default:
+		break; /* do not change settings */
+	}
+	IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword);
+	pci_write_config_word(dev, PCI_DMA_C, tmpword);
+
+	/*
+	 * GEN2_DEC bits:
+	 * Bit 15-4: Generic I/O range
+	 * Bit 3-1: reserved (read as 0)
+	 * Bit 0: enable GEN2 range on LPC I/F
+	 */
+	tmpword = conf->fir_io & 0xfff8;
+	tmpword |= 0x0001;
+	IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword);
+	pci_write_config_word(dev, GEN2_DEC, tmpword);
+
+	/* Pre-configure chip */
+	return preconfigure_smsc_chip(conf);
+}
+
+/*
+ * Pre-configure a certain port on the ALi 1533 bridge.
+ * This is based on reverse-engineering since ALi does not
+ * provide any data sheet for the 1533 chip.
+ */
+static void __init preconfigure_ali_port(struct pci_dev *dev,
+					 unsigned short port)
+{
+	unsigned char reg;
+	/* These bits obviously control the different ports */
+	unsigned char mask;
+	unsigned char tmpbyte;
+
+	switch(port) {
+	case 0x0130:
+	case 0x0178:
+		reg = 0xb0;
+		mask = 0x80;
+		break;
+	case 0x03f8:
+		reg = 0xb4;
+		mask = 0x80;
+		break;
+	case 0x02f8:
+		reg = 0xb4;
+		mask = 0x30;
+		break;
+	case 0x02e8:
+		reg = 0xb4;
+		mask = 0x08;
+		break;
+	default:
+		IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port);
+		return;
+	}
+
+	pci_read_config_byte(dev, reg, &tmpbyte);
+	/* Turn on the right bits */
+	tmpbyte |= mask;
+	pci_write_config_byte(dev, reg, tmpbyte);
+	IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);
+	return;
+}
+
+static int __init preconfigure_through_ali(struct pci_dev *dev,
+					   struct
+					   smsc_ircc_subsystem_configuration
+					   *conf)
+{
+	/* Configure the two ports on the ALi 1533 */
+	preconfigure_ali_port(dev, conf->sir_io);
+	preconfigure_ali_port(dev, conf->fir_io);
+
+	/* Pre-configure chip */
+	return preconfigure_smsc_chip(conf);
+}
+
+static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
+						    unsigned short ircc_fir,
+						    unsigned short ircc_sir,
+						    unsigned char ircc_dma,
+						    unsigned char ircc_irq)
+{
+	struct pci_dev *dev = NULL;
+	unsigned short ss_vendor = 0x0000;
+	unsigned short ss_device = 0x0000;
+	int ret = 0;
+
+	dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+
+	while (dev != NULL) {
+		struct smsc_ircc_subsystem_configuration *conf;
+
+		/*
+		 * Cache the subsystem vendor/device:
+		 * some manufacturers fail to set this for all components,
+		 * so we save it in case there is just 0x0000 0x0000 on the
+		 * device we want to check.
+		 */
+		if (dev->subsystem_vendor != 0x0000U) {
+			ss_vendor = dev->subsystem_vendor;
+			ss_device = dev->subsystem_device;
+		}
+		conf = subsystem_configurations;
+		for( ; conf->subvendor; conf++) {
+			if(conf->vendor == dev->vendor &&
+			   conf->device == dev->device &&
+			   conf->subvendor == ss_vendor &&
+			   /* Sometimes these are cached values */
+			   (conf->subdevice == ss_device ||
+			    conf->subdevice == 0xffff)) {
+				struct smsc_ircc_subsystem_configuration
+					tmpconf;
+
+				memcpy(&tmpconf, conf,
+				       sizeof(struct smsc_ircc_subsystem_configuration));
+
+				/*
+				 * Override the default values with anything
+				 * passed in as parameter
+				 */
+				if (ircc_cfg != 0)
+					tmpconf.cfg_base = ircc_cfg;
+				if (ircc_fir != 0)
+					tmpconf.fir_io = ircc_fir;
+				if (ircc_sir != 0)
+					tmpconf.sir_io = ircc_sir;
+				if (ircc_dma != 0xff)
+					tmpconf.fir_dma = ircc_dma;
+				if (ircc_irq != 0xff)
+					tmpconf.fir_irq = ircc_irq;
+
+				IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
+				if (conf->preconfigure)
+					ret = conf->preconfigure(dev, &tmpconf);
+				else
+					ret = -ENODEV;
+			}
+		}
+		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+	}
+
+	return ret;
+}
+#endif // CONFIG_PCI
+
 /************************************************
  *
  * Transceivers specific functions
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index f9f77e4..cfd67d8 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -357,18 +357,20 @@
 	if((err = pci_enable_device(pdev)))
 		return err;
 
-	if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+	if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
+	   !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
 		pci_using_dac = 1;
 	} else {
-		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
+		   (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
 			IXGB_ERR("No usable DMA configuration, aborting\n");
-			return err;
+			goto err_dma_mask;
 		}
 		pci_using_dac = 0;
 	}
 
 	if((err = pci_request_regions(pdev, ixgb_driver_name)))
-		return err;
+		goto err_request_regions;
 
 	pci_set_master(pdev);
 
@@ -502,6 +504,9 @@
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_regions(pdev);
+err_request_regions:
+err_dma_mask:
+	pci_disable_device(pdev);
 	return err;
 }
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 9f26613..ea62a3e 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -281,10 +281,16 @@
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
 
-	netif_device_detach(dev);
+	if (!netif_running(dev))
+		return;
+
+	netif_stop_queue(dev);
+
 	eth_port_reset(mp->port_num);
 	eth_port_start(dev);
-	netif_device_attach(dev);
+
+	if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB)
+		netif_wake_queue(dev);
 }
 
 /**
@@ -552,9 +558,9 @@
 #else
 	if (eth_int_cause & ETH_INT_CAUSE_RX)
 		mv643xx_eth_receive_queue(dev, INT_MAX);
+#endif
 	if (eth_int_cause_ext & ETH_INT_CAUSE_TX)
 		mv643xx_eth_free_completed_tx_descs(dev);
-#endif
 
 	/*
 	 * If no real interrupt occured, exit.
@@ -1186,7 +1192,12 @@
 
 	BUG_ON(netif_queue_stopped(dev));
 	BUG_ON(skb == NULL);
-	BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB);
+
+	if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) {
+		printk(KERN_ERR "%s: transmit with queue full\n", dev->name);
+		netif_stop_queue(dev);
+		return 1;
+	}
 
 	if (has_tiny_unaligned_frags(skb)) {
 		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 7826afb..9062775 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -238,7 +238,7 @@
 #define NATSEMI_RX_LIMIT	2046	/* maximum supported by hardware */
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
   KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 08b218c..93c494b 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -226,7 +226,7 @@
 	netdev_boot_setup_check(dev);
 
 #ifdef CONFIG_TOSHIBA_RBTX4938
-	dev->base_addr = 0x07f20280;
+	dev->base_addr = RBTX4938_RTL_8019_BASE;
 	dev->irq = RBTX4938_RTL_8019_IRQ;
 #endif
 	err = do_ne_probe(dev);
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index d11821d..ced9fdb 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -645,9 +645,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (!dev)
-		BUG();
-
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	release_region(dev->base_addr, NE_IO_EXTENT);
 	free_netdev(dev);
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 75b35ad..66e74f7 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -87,6 +87,7 @@
 }
 
 static struct console netconsole = {
+	.name = "netcon",
 	.flags = CON_ENABLED | CON_PRINTBUFFER,
 	.write = write_msg
 };
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 8e9b1a5..706aed7 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -568,8 +568,7 @@
 #endif
 
 	sg = dev->rx_info.descs + (next_empty * DESC_SIZE);
-	if (unlikely(NULL != dev->rx_info.skbs[next_empty]))
-		BUG();
+	BUG_ON(NULL != dev->rx_info.skbs[next_empty]);
 	dev->rx_info.skbs[next_empty] = skb;
 
 	dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index ce90bec..fab9336 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -204,7 +204,7 @@
 #define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */
 
 struct el3_private {
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 	struct net_device_stats stats;
 	u16 advertising, partner;		/* NWay media advertisement */
@@ -225,8 +225,8 @@
 
 /* Index of functions. */
 
-static void tc574_config(dev_link_t *link);
-static void tc574_release(dev_link_t *link);
+static int tc574_config(struct pcmcia_device *link);
+static void tc574_release(struct pcmcia_device *link);
 
 static void mdio_sync(kio_addr_t ioaddr, int bits);
 static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -256,10 +256,9 @@
 	with Card Services.
 */
 
-static int tc574_attach(struct pcmcia_device *p_dev)
+static int tc574_probe(struct pcmcia_device *link)
 {
 	struct el3_private *lp;
-	dev_link_t *link;
 	struct net_device *dev;
 
 	DEBUG(0, "3c574_attach()\n");
@@ -269,8 +268,8 @@
 	if (!dev)
 		return -ENOMEM;
 	lp = netdev_priv(dev);
-	link = &lp->link;
 	link->priv = dev;
+	lp->p_dev = link;
 
 	spin_lock_init(&lp->window_lock);
 	link->io.NumPorts1 = 32;
@@ -280,7 +279,6 @@
 	link->irq.Handler = &el3_interrupt;
 	link->irq.Instance = dev;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
@@ -298,13 +296,7 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	tc574_config(link);
-
-	return 0;
+	return tc574_config(link);
 } /* tc574_attach */
 
 /*
@@ -316,18 +308,16 @@
 
 */
 
-static void tc574_detach(struct pcmcia_device *p_dev)
+static void tc574_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
 	DEBUG(0, "3c574_detach(0x%p)\n", link);
 
-	if (link->dev)
+	if (link->dev_node)
 		unregister_netdev(dev);
 
-	if (link->state & DEV_CONFIG)
-		tc574_release(link);
+	tc574_release(link);
 
 	free_netdev(dev);
 } /* tc574_detach */
@@ -343,9 +333,8 @@
 
 static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
 
-static void tc574_config(dev_link_t *link)
+static int tc574_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	struct net_device *dev = link->priv;
 	struct el3_private *lp = netdev_priv(dev);
 	tuple_t tuple;
@@ -363,30 +352,27 @@
 
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	tuple.TupleData = (cisdata_t *)buf;
 	tuple.TupleDataMax = 64;
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	link->io.IOAddrLines = 16;
 	for (i = j = 0; j < 0x400; j += 0x20) {
 		link->io.BasePort1 = j ^ 0x300;
-		i = pcmcia_request_io(link->handle, &link->io);
+		i = pcmcia_request_io(link, &link->io);
 		if (i == CS_SUCCESS) break;
 	}
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	dev->irq = link->irq.AssignedIRQ;
 	dev->base_addr = link->io.BasePort1;
@@ -397,8 +383,8 @@
 	   the hardware address.  The future products may include a modem chip
 	   and put the address in the CIS. */
 	tuple.DesiredTuple = 0x88;
-	if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
-		pcmcia_get_tuple_data(handle, &tuple);
+	if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+		pcmcia_get_tuple_data(link, &tuple);
 		for (i = 0; i < 3; i++)
 			phys_addr[i] = htons(buf[i]);
 	} else {
@@ -412,9 +398,9 @@
 		}
 	}
 	tuple.DesiredTuple = CISTPL_VERS_1;
-	if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS &&
-		pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS &&
-		pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+	if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS &&
+		pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS &&
+		pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) {
 		cardname = parse.version_1.str + parse.version_1.ofs[1];
 	} else
 		cardname = "3Com 3c574";
@@ -473,13 +459,12 @@
 		}
 	}
 
-	link->state &= ~DEV_CONFIG_PENDING;
-	link->dev = &lp->node;
-	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+	link->dev_node = &lp->node;
+	SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
 	if (register_netdev(dev) != 0) {
 		printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
-		link->dev = NULL;
+		link->dev_node = NULL;
 		goto failed;
 	}
 
@@ -493,13 +478,13 @@
 		   8 << config.u.ram_size, ram_split[config.u.ram_split],
 		   config.u.autoselect ? "autoselect " : "");
 
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 failed:
 	tc574_release(link);
-	return;
+	return -ENODEV;
 
 } /* tc574_config */
 
@@ -509,44 +494,28 @@
 	still open, this will be postponed until it is closed.
 */
 
-static void tc574_release(dev_link_t *link)
+static void tc574_release(struct pcmcia_device *link)
 {
-	DEBUG(0, "3c574_release(0x%p)\n", link);
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int tc574_suspend(struct pcmcia_device *p_dev)
+static int tc574_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int tc574_resume(struct pcmcia_device *p_dev)
+static int tc574_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			tc574_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		tc574_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -757,9 +726,9 @@
 static int el3_open(struct net_device *dev)
 {
 	struct el3_private *lp = netdev_priv(dev);
-	dev_link_t *link = &lp->link;
+	struct pcmcia_device *link = lp->p_dev;
 
-	if (!DEV_OK(link))
+	if (!pcmcia_dev_present(link))
 		return -ENODEV;
 	
 	link->open++;
@@ -1203,11 +1172,11 @@
 {
 	kio_addr_t ioaddr = dev->base_addr;
 	struct el3_private *lp = netdev_priv(dev);
-	dev_link_t *link = &lp->link;
+	struct pcmcia_device *link = lp->p_dev;
 
 	DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
 	
-	if (DEV_OK(link)) {
+	if (pcmcia_dev_present(link)) {
 		unsigned long flags;
 
 		/* Turn off statistics ASAP.  We update lp->stats below. */
@@ -1246,7 +1215,7 @@
 	.drv		= {
 		.name	= "3c574_cs",
 	},
-	.probe		= tc574_attach,
+	.probe		= tc574_probe,
 	.remove		= tc574_detach,
 	.id_table       = tc574_ids,
 	.suspend	= tc574_suspend,
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 3dba508..875a0fe 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -105,7 +105,7 @@
 #define TX_TIMEOUT	((400*HZ)/1000)
 
 struct el3_private {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t 		node;
     struct net_device_stats stats;
     /* For transceiver monitoring */
@@ -142,8 +142,8 @@
 
 /*====================================================================*/
 
-static void tc589_config(dev_link_t *link);
-static void tc589_release(dev_link_t *link);
+static int tc589_config(struct pcmcia_device *link);
+static void tc589_release(struct pcmcia_device *link);
 
 static u16 read_eeprom(kio_addr_t ioaddr, int index);
 static void tc589_reset(struct net_device *dev);
@@ -170,10 +170,9 @@
 
 ======================================================================*/
 
-static int tc589_attach(struct pcmcia_device *p_dev)
+static int tc589_probe(struct pcmcia_device *link)
 {
     struct el3_private *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "3c589_attach()\n");
@@ -183,8 +182,8 @@
     if (!dev)
 	 return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
     link->priv = dev;
+    lp->p_dev = link;
 
     spin_lock_init(&lp->lock);
     link->io.NumPorts1 = 16;
@@ -194,7 +193,6 @@
     link->irq.Handler = &el3_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -213,13 +211,7 @@
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    tc589_config(link);
-
-    return 0;
+    return tc589_config(link);
 } /* tc589_attach */
 
 /*======================================================================
@@ -231,18 +223,16 @@
 
 ======================================================================*/
 
-static void tc589_detach(struct pcmcia_device *p_dev)
+static void tc589_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "3c589_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	tc589_release(link);
+    tc589_release(link);
 
     free_netdev(dev);
 } /* tc589_detach */
@@ -258,9 +248,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void tc589_config(dev_link_t *link)
+static int tc589_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct el3_private *lp = netdev_priv(dev);
     tuple_t tuple;
@@ -275,43 +264,40 @@
     phys_addr = (u16 *)dev->dev_addr;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = (cisdata_t *)buf;
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
     
     /* Is this a 3c562? */
     tuple.DesiredTuple = CISTPL_MANFID;
     tuple.Attributes = TUPLE_RETURN_COMMON;
-    if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
-	(pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+    if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+	(pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
 	if (le16_to_cpu(buf[0]) != MANFID_3COM)
 	    printk(KERN_INFO "3c589_cs: hmmm, is this really a "
 		   "3Com card??\n");
 	multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
     }
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
     /* For the 3c562, the base address must be xx00-xx7f */
     link->io.IOAddrLines = 16;
     for (i = j = 0; j < 0x400; j += 0x10) {
 	if (multi && (j & 0x80)) continue;
 	link->io.BasePort1 = j ^ 0x300;
-	i = pcmcia_request_io(link->handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
 	if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, RequestIO, i);
+	cs_error(link, RequestIO, i);
 	goto failed;
     }
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 	
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
@@ -321,8 +307,8 @@
     /* The 3c589 has an extra EEPROM for configuration info, including
        the hardware address.  The 3c562 puts the address in the CIS. */
     tuple.DesiredTuple = 0x88;
-    if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
-	pcmcia_get_tuple_data(handle, &tuple);
+    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+	pcmcia_get_tuple_data(link, &tuple);
 	for (i = 0; i < 3; i++)
 	    phys_addr[i] = htons(buf[i]);
     } else {
@@ -346,13 +332,12 @@
     else
 	printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
     
-    link->dev = &lp->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &lp->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -366,14 +351,13 @@
     printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
 	   (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
 	   if_names[dev->if_port]);
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     tc589_release(link);
-    return;
-    
+    return -ENODEV;
 } /* tc589_config */
 
 /*======================================================================
@@ -384,44 +368,28 @@
     
 ======================================================================*/
 
-static void tc589_release(dev_link_t *link)
+static void tc589_release(struct pcmcia_device *link)
 {
-    DEBUG(0, "3c589_release(0x%p)\n", link);
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int tc589_suspend(struct pcmcia_device *p_dev)
+static int tc589_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int tc589_resume(struct pcmcia_device *p_dev)
+static int tc589_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			tc589_reset(dev);
-			netif_device_attach(dev);
-		}
+ 	if (link->open) {
+		tc589_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -587,9 +555,9 @@
 static int el3_open(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
     link->open++;
@@ -848,9 +816,9 @@
 {
     struct el3_private *lp = netdev_priv(dev);
     unsigned long flags;
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
-    if (DEV_OK(link)) {
+    if (pcmcia_dev_present(link)) {
     	spin_lock_irqsave(&lp->lock, flags);
 	update_stats(dev);
 	spin_unlock_irqrestore(&lp->lock, flags);
@@ -950,11 +918,11 @@
 static void set_multicast_list(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
     u16 opts = SetRxFilter | RxStation | RxBroadcast;
 
-    if (!(DEV_OK(link))) return;
+    if (!pcmcia_dev_present(link)) return;
     if (dev->flags & IFF_PROMISC)
 	opts |= RxMulticast | RxProm;
     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -965,12 +933,12 @@
 static int el3_close(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
     
     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
 
-    if (DEV_OK(link)) {
+    if (pcmcia_dev_present(link)) {
 	/* Turn off statistics ASAP.  We update lp->stats below. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
 	
@@ -1020,7 +988,7 @@
 	.drv		= {
 		.name	= "3c589_cs",
 	},
-	.probe		= tc589_attach,
+	.probe		= tc589_probe,
 	.remove		= tc589_detach,
         .id_table       = tc589_ids,
 	.suspend	= tc589_suspend,
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 1cc94b2..448a094 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -86,8 +86,8 @@
 
 /*====================================================================*/
 
-static void axnet_config(dev_link_t *link);
-static void axnet_release(dev_link_t *link);
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
 static int axnet_open(struct net_device *dev);
 static int axnet_close(struct net_device *dev);
 static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -117,7 +117,7 @@
 /*====================================================================*/
 
 typedef struct axnet_dev_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t		node;
     caddr_t		base;
     struct timer_list	watchdog;
@@ -142,10 +142,9 @@
 
 ======================================================================*/
 
-static int axnet_attach(struct pcmcia_device *p_dev)
+static int axnet_probe(struct pcmcia_device *link)
 {
     axnet_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "axnet_attach()\n");
@@ -157,7 +156,7 @@
 	return -ENOMEM;
 
     info = PRIV(dev);
-    link = &info->link;
+    info->p_dev = link;
     link->priv = dev;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
@@ -169,13 +168,7 @@
     dev->do_ioctl = &axnet_ioctl;
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    axnet_config(link);
-
-    return 0;
+    return axnet_config(link);
 } /* axnet_attach */
 
 /*======================================================================
@@ -187,18 +180,16 @@
 
 ======================================================================*/
 
-static void axnet_detach(struct pcmcia_device *p_dev)
+static void axnet_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "axnet_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	axnet_release(link);
+    axnet_release(link);
 
     free_netdev(dev);
 } /* axnet_detach */
@@ -209,7 +200,7 @@
 
 ======================================================================*/
 
-static int get_prom(dev_link_t *link)
+static int get_prom(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -263,7 +254,7 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
     if (link->io.NumPorts1 == 32) {
@@ -284,25 +275,23 @@
 	for (j = 0; j < 0x400; j += 0x20) {
 	    link->io.BasePort1 = j ^ 0x300;
 	    link->io.BasePort2 = (j ^ 0x300) + 0x10;
-	    ret = pcmcia_request_io(link->handle, &link->io);
+	    ret = pcmcia_request_io(link, &link->io);
 	    if (ret == CS_SUCCESS) return ret;
 	}
 	return ret;
     } else {
-	return pcmcia_request_io(link->handle, &link->io);
+	return pcmcia_request_io(link, &link->io);
     }
 }
 
-static void axnet_config(dev_link_t *link)
+static int axnet_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     axnet_dev_t *info = PRIV(dev);
     tuple_t tuple;
     cisparse_t parse;
     int i, j, last_ret, last_fn;
     u_short buf[64];
-    config_info_t conf;
 
     DEBUG(0, "axnet_config(0x%p)\n", link);
 
@@ -311,29 +300,22 @@
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     /* don't trust the CIS on this; Linksys got it wrong */
     link->conf.Present = 0x63;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
-
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
 	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 	cistpl_io_t *io = &(parse.cftable_entry.io);
 	
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
 		cfg->index == 0 || cfg->io.nwin == 0)
 	    goto next_entry;
 	
@@ -355,21 +337,21 @@
 	    if (last_ret == CS_SUCCESS) break;
 	}
     next_entry:
-	last_ret = pcmcia_get_next_tuple(handle, &tuple);
+	last_ret = pcmcia_get_next_tuple(link, &tuple);
     }
     if (last_ret != CS_SUCCESS) {
-	cs_error(handle, RequestIO, last_ret);
+	cs_error(link, RequestIO, last_ret);
 	goto failed;
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     
     if (link->io.NumPorts2 == 8) {
 	link->conf.Attributes |= CONF_ENABLE_SPKR;
 	link->conf.Status = CCSR_AUDIO_ENA;
     }
     
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
@@ -406,7 +388,7 @@
        Bit 2 of CCSR is active low. */ 
     if (i == 32) {
 	conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
- 	pcmcia_access_configuration_register(link->handle, &reg);
+ 	pcmcia_access_configuration_register(link, &reg);
 	for (i = 0; i < 32; i++) {
 	    j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
 	    if ((j != 0) && (j != 0xffff)) break;
@@ -414,13 +396,12 @@
     }
 
     info->phy_id = (i < 32) ? i : -1;
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -436,14 +417,13 @@
     } else {
 	printk(KERN_NOTICE "  No MII transceivers found!\n");
     }
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     axnet_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return -ENODEV;
 } /* axnet_config */
 
 /*======================================================================
@@ -454,45 +434,29 @@
 
 ======================================================================*/
 
-static void axnet_release(dev_link_t *link)
+static void axnet_release(struct pcmcia_device *link)
 {
-    DEBUG(0, "axnet_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int axnet_suspend(struct pcmcia_device *p_dev)
+static int axnet_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int axnet_resume(struct pcmcia_device *p_dev)
+static int axnet_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			axnet_reset_8390(dev);
-			AX88190_init(dev, 1);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		axnet_reset_8390(dev);
+		AX88190_init(dev, 1);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -562,11 +526,11 @@
 static int axnet_open(struct net_device *dev)
 {
     axnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
     
     DEBUG(2, "axnet_open('%s')\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
     link->open++;
@@ -588,7 +552,7 @@
 static int axnet_close(struct net_device *dev)
 {
     axnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
 
     DEBUG(2, "axnet_close('%s')\n", dev->name);
 
@@ -833,7 +797,7 @@
 	.drv		= {
 		.name	= "axnet_cs",
 	},
-	.probe		= axnet_attach,
+	.probe		= axnet_probe,
 	.remove		= axnet_detach,
 	.id_table       = axnet_ids,
 	.suspend	= axnet_suspend,
@@ -1596,7 +1560,7 @@
 
 static void ei_rx_overrun(struct net_device *dev)
 {
-	axnet_dev_t *info = (axnet_dev_t *)dev;
+	axnet_dev_t *info = PRIV(dev);
 	long e8390_base = dev->base_addr;
 	unsigned char was_txing, must_resend = 0;
 	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 2827a48..441de82 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -118,8 +118,8 @@
 
 /*====================================================================*/
 
-static void com20020_config(dev_link_t *link);
-static void com20020_release(dev_link_t *link);
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
 
 static void com20020_detach(struct pcmcia_device *p_dev);
 
@@ -138,9 +138,8 @@
 
 ======================================================================*/
 
-static int com20020_attach(struct pcmcia_device *p_dev)
+static int com20020_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     com20020_dev_t *info;
     struct net_device *dev;
     struct arcnet_local *lp;
@@ -148,10 +147,6 @@
     DEBUG(0, "com20020_attach()\n");
 
     /* Create new network device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    if (!link)
-	return -ENOMEM;
-
     info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
     if (!info)
 	goto fail_alloc_info;
@@ -161,7 +156,6 @@
 	goto fail_alloc_dev;
 
     memset(info, 0, sizeof(struct com20020_dev_t));
-    memset(link, 0, sizeof(struct dev_link_t));
     lp = dev->priv;
     lp->timeout = timeout;
     lp->backplane = backplane;
@@ -172,28 +166,23 @@
     /* fill in our module parameters as defaults */
     dev->dev_addr[0] = node;
 
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts1 = 16;
-    link->io.IOAddrLines = 16;
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.NumPorts1 = 16;
+    p_dev->io.IOAddrLines = 16;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.Present = PRESENT_OPTION;
 
-    link->irq.Instance = info->dev = dev;
-    link->priv = info;
+    p_dev->irq.Instance = info->dev = dev;
+    p_dev->priv = info;
 
-    link->state |= DEV_PRESENT;
-    com20020_config(link);
-
-    return 0;
+    return com20020_config(p_dev);
 
 fail_alloc_dev:
     kfree(info);
 fail_alloc_info:
-    kfree(link);
     return -ENOMEM;
 } /* com20020_attach */
 
@@ -206,9 +195,8 @@
 
 ======================================================================*/
 
-static void com20020_detach(struct pcmcia_device *p_dev)
+static void com20020_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct com20020_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
 
@@ -216,7 +204,7 @@
 
     DEBUG(0, "com20020_detach(0x%p)\n", link);
 
-    if (link->dev) {
+    if (link->dev_node) {
 	DEBUG(1,"unregister...\n");
 
 	unregister_netdev(dev);
@@ -229,8 +217,7 @@
 	    free_irq(dev->irq, dev);
     }
 
-    if (link->state & DEV_CONFIG)
-        com20020_release(link);
+    com20020_release(link);
 
     /* Unlink device structure, free bits */
     DEBUG(1,"unlinking...\n");
@@ -245,8 +232,6 @@
 	DEBUG(1,"kfree2...\n");
 	kfree(info);
     }
-    DEBUG(1,"kfree3...\n");
-    kfree(link);
 
 } /* com20020_detach */
 
@@ -261,10 +246,9 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void com20020_config(dev_link_t *link)
+static int com20020_config(struct pcmcia_device *link)
 {
     struct arcnet_local *lp;
-    client_handle_t handle;
     tuple_t tuple;
     cisparse_t parse;
     com20020_dev_t *info;
@@ -273,7 +257,6 @@
     u_char buf[64];
     int ioaddr;
 
-    handle = link->handle;
     info = link->priv;
     dev = info->dev;
 
@@ -286,14 +269,11 @@
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
     i = !CS_SUCCESS;
     if (!link->io.BasePort1)
@@ -301,13 +281,13 @@
 	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
 	{
 	    link->io.BasePort1 = ioaddr;
-	    i = pcmcia_request_io(link->handle, &link->io);
+	    i = pcmcia_request_io(link, &link->io);
 	    if (i == CS_SUCCESS)
 		break;
 	}
     }
     else
-	i = pcmcia_request_io(link->handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
     
     if (i != CS_SUCCESS)
     {
@@ -321,7 +301,7 @@
     DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n",
 	   link->irq.AssignedIRQ,
 	   link->irq.IRQInfo1, link->irq.IRQInfo2);
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     if (i != CS_SUCCESS)
     {
 	DEBUG(1,"arcnet: requestIRQ failed totally!\n");
@@ -330,7 +310,7 @@
 
     dev->irq = link->irq.AssignedIRQ;
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     if (com20020_check(dev))
     {
@@ -342,15 +322,14 @@
     lp->card_name = "PCMCIA COM20020";
     lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     i = com20020_found(dev, 0);	/* calls register_netdev */
     
     if (i != 0) {
 	DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -358,13 +337,14 @@
 
     DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
            dev->name, dev->base_addr, dev->irq);
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     DEBUG(1,"com20020_config failed...\n");
     com20020_release(link);
+    return -ENODEV;
 } /* com20020_config */
 
 /*======================================================================
@@ -375,52 +355,33 @@
 
 ======================================================================*/
 
-static void com20020_release(dev_link_t *link)
+static void com20020_release(struct pcmcia_device *link)
 {
-
-    DEBUG(1,"release...\n");
-
-    DEBUG(0, "com20020_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+	DEBUG(0, "com20020_release(0x%p)\n", link);
+	pcmcia_disable_device(link);
 }
 
-static int com20020_suspend(struct pcmcia_device *p_dev)
+static int com20020_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	com20020_dev_t *info = link->priv;
 	struct net_device *dev = info->dev;
 
-	link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		if (link->open) {
-			netif_device_detach(dev);
-		}
-		pcmcia_release_configuration(link->handle);
-        }
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int com20020_resume(struct pcmcia_device *p_dev)
+static int com20020_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	com20020_dev_t *info = link->priv;
 	struct net_device *dev = info->dev;
 
-	link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			int ioaddr = dev->base_addr;
-			struct arcnet_local *lp = dev->priv;
-			ARCRESET;
-		}
-        }
+	if (link->open) {
+		int ioaddr = dev->base_addr;
+		struct arcnet_local *lp = dev->priv;
+		ARCRESET;
+	}
 
 	return 0;
 }
@@ -436,7 +397,7 @@
 	.drv		= {
 		.name	= "com20020_cs",
 	},
-	.probe		= com20020_attach,
+	.probe		= com20020_probe,
 	.remove		= com20020_detach,
 	.id_table	= com20020_ids,
 	.suspend	= com20020_suspend,
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index b7ac14b..09b1176 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -84,10 +84,10 @@
 /*
     PCMCIA event handlers
  */
-static void fmvj18x_config(dev_link_t *link);
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
-static int fmvj18x_setup_mfc(dev_link_t *link);
-static void fmvj18x_release(dev_link_t *link);
+static int fmvj18x_config(struct pcmcia_device *link);
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
+static int fmvj18x_setup_mfc(struct pcmcia_device *link);
+static void fmvj18x_release(struct pcmcia_device *link);
 static void fmvj18x_detach(struct pcmcia_device *p_dev);
 
 /*
@@ -116,7 +116,7 @@
     driver specific data structure
 */
 typedef struct local_info_t {
-    dev_link_t link;
+	struct pcmcia_device	*p_dev;
     dev_node_t node;
     struct net_device_stats stats;
     long open_time;
@@ -228,10 +228,9 @@
 #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
 #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
 
-static int fmvj18x_attach(struct pcmcia_device *p_dev)
+static int fmvj18x_probe(struct pcmcia_device *link)
 {
     local_info_t *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "fmvj18x_attach()\n");
@@ -241,8 +240,8 @@
     if (!dev)
 	return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
     link->priv = dev;
+    lp->p_dev = link;
 
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 32;
@@ -257,7 +256,6 @@
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The FMVJ18x specific entries in the device structure. */
@@ -274,29 +272,21 @@
 #endif
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    fmvj18x_config(link);
-
-    return 0;
+    return fmvj18x_config(link);
 } /* fmvj18x_attach */
 
 /*====================================================================*/
 
-static void fmvj18x_detach(struct pcmcia_device *p_dev)
+static void fmvj18x_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	fmvj18x_release(link);
+    fmvj18x_release(link);
 
     free_netdev(dev);
 } /* fmvj18x_detach */
@@ -306,7 +296,7 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int mfc_try_io_port(dev_link_t *link)
+static int mfc_try_io_port(struct pcmcia_device *link)
 {
     int i, ret;
     static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
@@ -318,13 +308,13 @@
 	    link->io.NumPorts2 = 0;
 	    printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
 	}
-	ret = pcmcia_request_io(link->handle, &link->io);
+	ret = pcmcia_request_io(link, &link->io);
 	if (ret == CS_SUCCESS) return ret;
     }
     return ret;
 }
 
-static int ungermann_try_io_port(dev_link_t *link)
+static int ungermann_try_io_port(struct pcmcia_device *link)
 {
     int ret;
     kio_addr_t ioaddr;
@@ -334,7 +324,7 @@
     */
     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
 	link->io.BasePort1 = ioaddr;
-	ret = pcmcia_request_io(link->handle, &link->io);
+	ret = pcmcia_request_io(link, &link->io);
 	if (ret == CS_SUCCESS) {
 	    /* calculate ConfigIndex value */
 	    link->conf.ConfigIndex = 
@@ -345,9 +335,8 @@
     return ret;	/* RequestIO failed */
 }
 
-static void fmvj18x_config(dev_link_t *link)
+static int fmvj18x_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
     tuple_t tuple;
@@ -366,42 +355,34 @@
        registers.
     */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = (u_char *)buf;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 
     link->conf.ConfigBase = parse.config.base; 
     link->conf.Present = parse.config.rmask[0];
 
     tuple.DesiredTuple = CISTPL_FUNCE;
     tuple.TupleOffset = 0;
-    if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
 	/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigIndex = parse.cftable_entry.index;
 	tuple.DesiredTuple = CISTPL_MANFID;
-	if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
-	    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+	if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+	    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 	else
 	    buf[0] = 0xffff;
 	switch (le16_to_cpu(buf[0])) {
 	case MANFID_TDK:
 	    cardtype = TDK;
-	    if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) {
-		cs_status_t status;
-		pcmcia_get_status(handle, &status);
-		if (status.CardState & CS_EVENT_3VCARD)
-		    link->conf.Vcc = 33; /* inserted in 3.3V slot */
-	    } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
+	    if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
 			|| le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
 			|| le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
 		/* MultiFunction Card */
@@ -429,8 +410,8 @@
     } else {
 	/* old type card */
 	tuple.DesiredTuple = CISTPL_MANFID;
-	if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS)
-	    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+	if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
+	    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 	else
 	    buf[0] = 0xffff;
 	switch (le16_to_cpu(buf[0])) {
@@ -461,10 +442,10 @@
 	ret = ungermann_try_io_port(link);
 	if (ret != CS_SUCCESS) goto cs_failed;
     } else { 
-	CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
@@ -493,17 +474,17 @@
     case CONTEC:
 	tuple.DesiredTuple = CISTPL_FUNCE;
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 	if (cardtype == MBH10304) {
 	    /* MBH10304's CIS_FUNCE is corrupted */
 	    node_id = &(tuple.TupleData[5]);
 	    card_name = "FMV-J182";
 	} else {
 	    while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
-		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 	    }
 	    node_id = &(tuple.TupleData[2]);
 	    if( cardtype == TDK ) {
@@ -545,13 +526,12 @@
     }
 
     lp->cardtype = cardtype;
-    link->dev = &lp->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &lp->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -564,19 +544,18 @@
     for (i = 0; i < 6; i++)
 	printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
 
-    return;
+    return 0;
     
 cs_failed:
     /* All Card Services errors end up here */
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     fmvj18x_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-
+    return -ENODEV;
 } /* fmvj18x_config */
 /*====================================================================*/
 
-static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
     win_req_t req;
     memreq_t mem;
@@ -587,9 +566,9 @@
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, RequestWindow, i);
+	cs_error(link, RequestWindow, i);
 	return -1;
     }
 
@@ -623,13 +602,13 @@
     iounmap(base);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-	cs_error(link->handle, ReleaseWindow, j);
+	cs_error(link, ReleaseWindow, j);
     return (i != 0x200) ? 0 : -1;
 
 } /* fmvj18x_get_hwinfo */
 /*====================================================================*/
 
-static int fmvj18x_setup_mfc(dev_link_t *link)
+static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
     win_req_t req;
     memreq_t mem;
@@ -642,9 +621,9 @@
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, RequestWindow, i);
+	cs_error(link, RequestWindow, i);
 	return -1;
     }
 
@@ -666,54 +645,35 @@
     iounmap(base);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-	cs_error(link->handle, ReleaseWindow, j);
+	cs_error(link, ReleaseWindow, j);
     return 0;
 
 }
 /*====================================================================*/
 
-static void fmvj18x_release(dev_link_t *link)
+static void fmvj18x_release(struct pcmcia_device *link)
 {
-
-    DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-
-    /* Don't bother checking to see if these succeed or not */
-    pcmcia_release_window(link->win);
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
+	DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+	pcmcia_disable_device(link);
 }
 
-static int fmvj18x_suspend(struct pcmcia_device *p_dev)
+static int fmvj18x_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
-
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int fmvj18x_resume(struct pcmcia_device *p_dev)
+static int fmvj18x_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			fjn_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		fjn_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -751,7 +711,7 @@
 	.drv		= {
 		.name	= "fmvj18x_cs",
 	},
-	.probe		= fmvj18x_attach,
+	.probe		= fmvj18x_probe,
 	.remove		= fmvj18x_detach,
 	.id_table       = fmvj18x_ids,
 	.suspend	= fmvj18x_suspend,
@@ -1148,11 +1108,11 @@
 static int fjn_open(struct net_device *dev)
 {
     struct local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(4, "fjn_open('%s').\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
     
     link->open++;
@@ -1173,7 +1133,7 @@
 static int fjn_close(struct net_device *dev)
 {
     struct local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
 
     DEBUG(4, "fjn_close('%s').\n", dev->name);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b9c7e39..b8fe70b 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -105,15 +105,15 @@
 
 /*====================================================================*/
 
-static void ibmtr_config(dev_link_t *link);
+static int ibmtr_config(struct pcmcia_device *link);
 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
-static void ibmtr_release(dev_link_t *link);
+static void ibmtr_release(struct pcmcia_device *link);
 static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 /*====================================================================*/
 
 typedef struct ibmtr_dev_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     struct net_device	*dev;
     dev_node_t          node;
     window_handle_t     sram_win_handle;
@@ -138,12 +138,11 @@
 
 ======================================================================*/
 
-static int ibmtr_attach(struct pcmcia_device *p_dev)
+static int ibmtr_attach(struct pcmcia_device *link)
 {
     ibmtr_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
-    
+
     DEBUG(0, "ibmtr_attach()\n");
 
     /* Create new token-ring device */
@@ -156,7 +155,7 @@
 	return -ENOMEM;
     }
 
-    link = &info->link;
+    info->p_dev = link;
     link->priv = info;
     info->ti = netdev_priv(dev);
 
@@ -167,21 +166,14 @@
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->irq.Handler = &tok_interrupt;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
     link->irq.Instance = info->dev = dev;
-    
+
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT;
-    ibmtr_config(link);
-
-    return 0;
+    return ibmtr_config(link);
 } /* ibmtr_attach */
 
 /*======================================================================
@@ -193,23 +185,22 @@
 
 ======================================================================*/
 
-static void ibmtr_detach(struct pcmcia_device *p_dev)
+static void ibmtr_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
 
     DEBUG(0, "ibmtr_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
     {
 	struct tok_info *ti = netdev_priv(dev);
 	del_timer_sync(&(ti->tr_timer));
     }
-    if (link->state & DEV_CONFIG)
-        ibmtr_release(link);
+
+    ibmtr_release(link);
 
     free_netdev(dev);
     kfree(info);
@@ -226,9 +217,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ibmtr_config(dev_link_t *link)
+static int ibmtr_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
@@ -246,29 +236,25 @@
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
-
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     link->conf.ConfigIndex = 0x61;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
     /* Try PRIMARY card at 0xA20-0xA23 */
     link->io.BasePort1 = 0xA20;
-    i = pcmcia_request_io(link->handle, &link->io);
+    i = pcmcia_request_io(link, &link->io);
     if (i != CS_SUCCESS) {
 	/* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
 	link->io.BasePort1 = 0xA24;
-	CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
+	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
     dev->base_addr = link->io.BasePort1;
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     dev->irq = link->irq.AssignedIRQ;
     ti->irq = link->irq.AssignedIRQ;
     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
@@ -279,7 +265,7 @@
     req.Base = 0; 
     req.Size = 0x2000;
     req.AccessSpeed = 250;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
 
     mem.CardOffset = mmiobase;
     mem.Page = 0;
@@ -292,7 +278,7 @@
     req.Base = 0;
     req.Size = sramsize * 1024;
     req.AccessSpeed = 250;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle));
 
     mem.CardOffset = srambase;
     mem.Page = 0;
@@ -302,21 +288,20 @@
     ti->sram_virt = ioremap(req.Base, req.Size);
     ti->sram_phys = req.Base;
 
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*  Set up the Token-Ring Controller Configuration Register and
         turn on the card.  Check the "Local Area Network Credit Card
         Adapters Technical Reference"  SC30-3585 for this info.  */
     ibmtr_hw_setup(dev, mmiobase);
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     i = ibmtr_probe_card(dev);
     if (i != 0) {
 	printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -330,12 +315,13 @@
     for (i = 0; i < TR_ALEN; i++)
         printk("%02X", dev->dev_addr[i]);
     printk("\n");
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     ibmtr_release(link);
+    return -ENODEV;
 } /* ibmtr_config */
 
 /*======================================================================
@@ -346,56 +332,41 @@
 
 ======================================================================*/
 
-static void ibmtr_release(dev_link_t *link)
+static void ibmtr_release(struct pcmcia_device *link)
 {
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
-
-    DEBUG(0, "ibmtr_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->win) {
-	struct tok_info *ti = netdev_priv(dev);
-	iounmap(ti->mmio);
-	pcmcia_release_window(link->win);
-	pcmcia_release_window(info->sram_win_handle);
-    }
-
-    link->state &= ~DEV_CONFIG;
-}
-
-static int ibmtr_suspend(struct pcmcia_device *p_dev)
-{
-	dev_link_t *link = dev_to_instance(p_dev);
 	ibmtr_dev_t *info = link->priv;
 	struct net_device *dev = info->dev;
 
-	link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-        }
+	DEBUG(0, "ibmtr_release(0x%p)\n", link);
+
+	if (link->win) {
+		struct tok_info *ti = netdev_priv(dev);
+		iounmap(ti->mmio);
+		pcmcia_release_window(info->sram_win_handle);
+	}
+	pcmcia_disable_device(link);
+}
+
+static int ibmtr_suspend(struct pcmcia_device *link)
+{
+	ibmtr_dev_t *info = link->priv;
+	struct net_device *dev = info->dev;
+
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int ibmtr_resume(struct pcmcia_device *p_dev)
+static int ibmtr_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	ibmtr_dev_t *info = link->priv;
 	struct net_device *dev = info->dev;
 
-	link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			ibmtr_probe(dev);	/* really? */
-			netif_device_attach(dev);
-		}
-        }
+	if (link->open) {
+		ibmtr_probe(dev);	/* really? */
+		netif_device_attach(dev);
+	}
 
 	return 0;
 }
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 787176c..4260c21 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -362,7 +362,7 @@
 } mace_statistics;
 
 typedef struct _mace_private {
-    dev_link_t link;
+	struct pcmcia_device	*p_dev;
     dev_node_t node;
     struct net_device_stats linux_stats; /* Linux statistics counters */
     mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -417,8 +417,8 @@
 Function Prototypes
 ---------------------------------------------------------------------------- */
 
-static void nmclan_config(dev_link_t *link);
-static void nmclan_release(dev_link_t *link);
+static int nmclan_config(struct pcmcia_device *link);
+static void nmclan_release(struct pcmcia_device *link);
 
 static void nmclan_reset(struct net_device *dev);
 static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -443,10 +443,9 @@
 	Services.
 ---------------------------------------------------------------------------- */
 
-static int nmclan_attach(struct pcmcia_device *p_dev)
+static int nmclan_probe(struct pcmcia_device *link)
 {
     mace_private *lp;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "nmclan_attach()\n");
@@ -457,7 +456,7 @@
     if (!dev)
 	    return -ENOMEM;
     lp = netdev_priv(dev);
-    link = &lp->link;
+    lp->p_dev = link;
     link->priv = dev;
     
     spin_lock_init(&lp->bank_lock);
@@ -469,7 +468,6 @@
     link->irq.Handler = &mace_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -489,13 +487,7 @@
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    nmclan_config(link);
-
-    return 0;
+    return nmclan_config(link);
 } /* nmclan_attach */
 
 /* ----------------------------------------------------------------------------
@@ -506,18 +498,16 @@
 	when the device is released.
 ---------------------------------------------------------------------------- */
 
-static void nmclan_detach(struct pcmcia_device *p_dev)
+static void nmclan_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "nmclan_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	nmclan_release(link);
+    nmclan_release(link);
 
     free_netdev(dev);
 } /* nmclan_detach */
@@ -661,9 +651,8 @@
 #define CS_CHECK(fn, ret) \
   do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void nmclan_config(dev_link_t *link)
+static int nmclan_config(struct pcmcia_device *link)
 {
-  client_handle_t handle = link->handle;
   struct net_device *dev = link->priv;
   mace_private *lp = netdev_priv(dev);
   tuple_t tuple;
@@ -679,17 +668,14 @@
   tuple.TupleDataMax = 64;
   tuple.TupleOffset = 0;
   tuple.DesiredTuple = CISTPL_CONFIG;
-  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-  CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+  CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
   link->conf.ConfigBase = parse.config.base;
 
-  /* Configure card */
-  link->state |= DEV_CONFIG;
-
-  CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-  CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+  CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+  CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
   dev->irq = link->irq.AssignedIRQ;
   dev->base_addr = link->io.BasePort1;
 
@@ -700,8 +686,8 @@
   tuple.TupleData = buf;
   tuple.TupleDataMax = 64;
   tuple.TupleOffset = 0;
-  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
   memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
 
   /* Verify configuration by reading the MACE ID. */
@@ -716,8 +702,7 @@
     } else {
       printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"
 	     " be 0x40 0x?9\n", sig[0], sig[1]);
-      link->state &= ~DEV_CONFIG_PENDING;
-      return;
+      return -ENODEV;
     }
   }
 
@@ -730,14 +715,13 @@
   else
     printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
 
-  link->dev = &lp->node;
-  link->state &= ~DEV_CONFIG_PENDING;
-  SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+  link->dev_node = &lp->node;
+  SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
   i = register_netdev(dev);
   if (i != 0) {
     printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
-    link->dev = NULL;
+    link->dev_node = NULL;
     goto failed;
   }
 
@@ -747,14 +731,13 @@
 	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
   for (i = 0; i < 6; i++)
       printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
-  return;
+  return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 failed:
-    nmclan_release(link);
-    return;
-
+	nmclan_release(link);
+	return -ENODEV;
 } /* nmclan_config */
 
 /* ----------------------------------------------------------------------------
@@ -763,46 +746,29 @@
 	net device, and release the PCMCIA configuration.  If the device
 	is still open, this will be postponed until it is closed.
 ---------------------------------------------------------------------------- */
-static void nmclan_release(dev_link_t *link)
+static void nmclan_release(struct pcmcia_device *link)
 {
-
-  DEBUG(0, "nmclan_release(0x%p)\n", link);
-
-  pcmcia_release_configuration(link->handle);
-  pcmcia_release_io(link->handle, &link->io);
-  pcmcia_release_irq(link->handle, &link->irq);
-
-  link->state &= ~DEV_CONFIG;
+	DEBUG(0, "nmclan_release(0x%p)\n", link);
+	pcmcia_disable_device(link);
 }
 
-static int nmclan_suspend(struct pcmcia_device *p_dev)
+static int nmclan_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
-
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int nmclan_resume(struct pcmcia_device *p_dev)
+static int nmclan_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			nmclan_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		nmclan_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -818,7 +784,7 @@
   mace_private *lp = netdev_priv(dev);
 
 #if RESET_XILINX
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = &lp->link;
   conf_reg_t reg;
   u_long OrigCorValue; 
 
@@ -827,7 +793,7 @@
   reg.Action = CS_READ;
   reg.Offset = CISREG_COR;
   reg.Value = 0;
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   OrigCorValue = reg.Value;
 
   /* Reset Xilinx */
@@ -836,12 +802,12 @@
   DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",
 	OrigCorValue);
   reg.Value = COR_SOFT_RESET;
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   /* Need to wait for 20 ms for PCMCIA to finish reset. */
 
   /* Restore original COR configuration index */
   reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
-  pcmcia_access_configuration_register(link->handle, &reg);
+  pcmcia_access_configuration_register(link, &reg);
   /* Xilinx is now completely reset along with the MACE chip. */
   lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
@@ -885,9 +851,9 @@
 {
   kio_addr_t ioaddr = dev->base_addr;
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
-  if (!DEV_OK(link))
+  if (!pcmcia_dev_present(link))
     return -ENODEV;
 
   link->open++;
@@ -908,7 +874,7 @@
 {
   kio_addr_t ioaddr = dev->base_addr;
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
   DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
 
@@ -963,12 +929,12 @@
 static void mace_tx_timeout(struct net_device *dev)
 {
   mace_private *lp = netdev_priv(dev);
-  dev_link_t *link = &lp->link;
+  struct pcmcia_device *link = lp->p_dev;
 
   printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
 #if RESET_ON_TIMEOUT
   printk("resetting card\n");
-  pcmcia_reset_card(link->handle, NULL);
+  pcmcia_reset_card(link, NULL);
 #else /* #if RESET_ON_TIMEOUT */
   printk("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
@@ -1635,7 +1601,7 @@
 	.drv		= {
 		.name	= "nmclan_cs",
 	},
-	.probe		= nmclan_attach,
+	.probe		= nmclan_probe,
 	.remove		= nmclan_detach,
 	.id_table       = nmclan_ids,
 	.suspend	= nmclan_suspend,
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b46e5f7..d090df4 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -103,8 +103,8 @@
 /*====================================================================*/
 
 static void mii_phy_probe(struct net_device *dev);
-static void pcnet_config(dev_link_t *link);
-static void pcnet_release(dev_link_t *link);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
 static int pcnet_open(struct net_device *dev);
 static int pcnet_close(struct net_device *dev);
 static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -113,9 +113,9 @@
 static void ei_watchdog(u_long arg);
 static void pcnet_reset_8390(struct net_device *dev);
 static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
 			      int stop_pg, int cm_offset);
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
 			    int stop_pg);
 
 static void pcnet_detach(struct pcmcia_device *p_dev);
@@ -214,7 +214,7 @@
 static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
 
 typedef struct pcnet_dev_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t		node;
     u_int		flags;
     void		__iomem *base;
@@ -240,10 +240,9 @@
 
 ======================================================================*/
 
-static int pcnet_probe(struct pcmcia_device *p_dev)
+static int pcnet_probe(struct pcmcia_device *link)
 {
     pcnet_dev_t *info;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "pcnet_attach()\n");
@@ -252,7 +251,7 @@
     dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
     if (!dev) return -ENOMEM;
     info = PRIV(dev);
-    link = &info->link;
+    info->p_dev = link;
     link->priv = dev;
 
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -265,13 +264,7 @@
     dev->stop = &pcnet_close;
     dev->set_config = &set_config;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    pcnet_config(link);
-
-    return 0;
+    return pcnet_config(link);
 } /* pcnet_attach */
 
 /*======================================================================
@@ -283,18 +276,16 @@
 
 ======================================================================*/
 
-static void pcnet_detach(struct pcmcia_device *p_dev)
+static void pcnet_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
 	DEBUG(0, "pcnet_detach(0x%p)\n", link);
 
-	if (link->dev)
+	if (link->dev_node)
 		unregister_netdev(dev);
 
-	if (link->state & DEV_CONFIG)
-		pcnet_release(link);
+	pcnet_release(link);
 
 	free_netdev(dev);
 } /* pcnet_detach */
@@ -306,7 +297,7 @@
 
 ======================================================================*/
 
-static hw_info_t *get_hwinfo(dev_link_t *link)
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     win_req_t req;
@@ -318,9 +309,9 @@
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, RequestWindow, i);
+	cs_error(link, RequestWindow, i);
 	return NULL;
     }
 
@@ -343,7 +334,7 @@
     iounmap(virt);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
-	cs_error(link->handle, ReleaseWindow, j);
+	cs_error(link, ReleaseWindow, j);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
 
@@ -355,7 +346,7 @@
 
 ======================================================================*/
 
-static hw_info_t *get_prom(dev_link_t *link)
+static hw_info_t *get_prom(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -409,7 +400,7 @@
 
 ======================================================================*/
 
-static hw_info_t *get_dl10019(dev_link_t *link)
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -431,7 +422,7 @@
 
 ======================================================================*/
 
-static hw_info_t *get_ax88190(dev_link_t *link)
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -464,7 +455,7 @@
 
 ======================================================================*/
 
-static hw_info_t *get_hwired(dev_link_t *link)
+static hw_info_t *get_hwired(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     int i;
@@ -491,7 +482,7 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int try_io_port(dev_link_t *link)
+static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
     if (link->io.NumPorts1 == 32) {
@@ -512,18 +503,17 @@
 	for (j = 0; j < 0x400; j += 0x20) {
 	    link->io.BasePort1 = j ^ 0x300;
 	    link->io.BasePort2 = (j ^ 0x300) + 0x10;
-	    ret = pcmcia_request_io(link->handle, &link->io);
+	    ret = pcmcia_request_io(link, &link->io);
 	    if (ret == CS_SUCCESS) return ret;
 	}
 	return ret;
     } else {
-	return pcmcia_request_io(link->handle, &link->io);
+	return pcmcia_request_io(link, &link->io);
     }
 }
 
-static void pcnet_config(dev_link_t *link)
+static int pcnet_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
     tuple_t tuple;
@@ -531,7 +521,6 @@
     int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int manfid = 0, prodid = 0, has_shmem = 0;
     u_short buf[64];
-    config_info_t conf;
     hw_info_t *hw_info;
 
     DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -541,36 +530,29 @@
     tuple.TupleDataMax = sizeof(buf);
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
-    /* Look up current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    link->conf.Vcc = conf.Vcc;
-
     tuple.DesiredTuple = CISTPL_MANFID;
     tuple.Attributes = TUPLE_RETURN_COMMON;
-    if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
- 	(pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) {
+    if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+ 	(pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
 	manfid = le16_to_cpu(buf[0]);
 	prodid = le16_to_cpu(buf[1]);
     }
     
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
 	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 	cistpl_io_t *io = &(parse.cftable_entry.io);
 	
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-			pcmcia_parse_tuple(handle, &tuple, &parse) != 0 ||
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+			pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
 			cfg->index == 0 || cfg->io.nwin == 0)
 		goto next_entry;
 	
@@ -594,14 +576,14 @@
 	    if (last_ret == CS_SUCCESS) break;
 	}
     next_entry:
-	last_ret = pcmcia_get_next_tuple(handle, &tuple);
+	last_ret = pcmcia_get_next_tuple(link, &tuple);
     }
     if (last_ret != CS_SUCCESS) {
-	cs_error(handle, RequestIO, last_ret);
+	cs_error(link, RequestIO, last_ret);
 	goto failed;
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     
     if (link->io.NumPorts2 == 8) {
 	link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -611,7 +593,7 @@
 	(prodid == PRODID_IBM_HOME_AND_AWAY))
 	link->conf.ConfigIndex |= 0x10;
     
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
     if (info->flags & HAS_MISC_REG) {
@@ -679,9 +661,8 @@
 	    info->eth_phy = 0;
     }
 
-    link->dev = &info->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &info->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
     dev->poll_controller = ei_poll;
@@ -689,7 +670,7 @@
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto failed;
     }
 
@@ -712,14 +693,13 @@
     printk(" hw_addr ");
     for (i = 0; i < 6; i++)
 	printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     pcnet_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
+    return -ENODEV;
 } /* pcnet_config */
 
 /*======================================================================
@@ -730,21 +710,16 @@
 
 ======================================================================*/
 
-static void pcnet_release(dev_link_t *link)
+static void pcnet_release(struct pcmcia_device *link)
 {
-    pcnet_dev_t *info = PRIV(link->priv);
+	pcnet_dev_t *info = PRIV(link->priv);
 
-    DEBUG(0, "pcnet_release(0x%p)\n", link);
+	DEBUG(0, "pcnet_release(0x%p)\n", link);
 
-    if (info->flags & USE_SHMEM) {
-	iounmap(info->base);
-	pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
+	if (info->flags & USE_SHMEM)
+		iounmap(info->base);
 
-    link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
 /*======================================================================
@@ -756,34 +731,24 @@
 
 ======================================================================*/
 
-static int pcnet_suspend(struct pcmcia_device *p_dev)
+static int pcnet_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int pcnet_resume(struct pcmcia_device *p_dev)
+static int pcnet_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			pcnet_reset_8390(dev);
-			NS8390_init(dev, 1);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		pcnet_reset_8390(dev);
+		NS8390_init(dev, 1);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -1023,11 +988,11 @@
 static int pcnet_open(struct net_device *dev)
 {
     pcnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
-    
+    struct pcmcia_device *link = info->p_dev;
+
     DEBUG(2, "pcnet_open('%s')\n", dev->name);
 
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
     link->open++;
@@ -1051,7 +1016,7 @@
 static int pcnet_close(struct net_device *dev)
 {
     pcnet_dev_t *info = PRIV(dev);
-    dev_link_t *link = &info->link;
+    struct pcmcia_device *link = info->p_dev;
 
     DEBUG(2, "pcnet_close('%s')\n", dev->name);
 
@@ -1429,7 +1394,7 @@
 
 /*====================================================================*/
 
-static int setup_dma_config(dev_link_t *link, int start_pg,
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
 			    int stop_pg)
 {
     struct net_device *dev = link->priv;
@@ -1532,7 +1497,7 @@
 
 /*====================================================================*/
 
-static int setup_shmem_window(dev_link_t *link, int start_pg,
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
 			      int stop_pg, int cm_offset)
 {
     struct net_device *dev = link->priv;
@@ -1554,7 +1519,7 @@
     req.Attributes |= WIN_USE_WAIT;
     req.Base = 0; req.Size = window_size;
     req.AccessSpeed = mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
 
     mem.CardOffset = (start_pg << 8) + cm_offset;
     offset = mem.CardOffset % window_size;
@@ -1595,7 +1560,7 @@
     return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     return 1;
 }
@@ -1674,6 +1639,7 @@
 	PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
 	PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
 	PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
 	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 8839c4f..e74bf50 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -49,6 +49,7 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
+#include <pcmcia/ss.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -103,7 +104,7 @@
 #define MEMORY_WAIT_TIME       	8
 
 struct smc_private {
-    dev_link_t			link;
+	struct pcmcia_device	*p_dev;
     spinlock_t			lock;
     u_short			manfid;
     u_short			cardid;
@@ -278,8 +279,8 @@
 /*====================================================================*/
 
 static void smc91c92_detach(struct pcmcia_device *p_dev);
-static void smc91c92_config(dev_link_t *link);
-static void smc91c92_release(dev_link_t *link);
+static int smc91c92_config(struct pcmcia_device *link);
+static void smc91c92_release(struct pcmcia_device *link);
 
 static int smc_open(struct net_device *dev);
 static int smc_close(struct net_device *dev);
@@ -308,10 +309,9 @@
 
 ======================================================================*/
 
-static int smc91c92_attach(struct pcmcia_device *p_dev)
+static int smc91c92_probe(struct pcmcia_device *link)
 {
     struct smc_private *smc;
-    dev_link_t *link;
     struct net_device *dev;
 
     DEBUG(0, "smc91c92_attach()\n");
@@ -321,7 +321,7 @@
     if (!dev)
 	return -ENOMEM;
     smc = netdev_priv(dev);
-    link = &smc->link;
+    smc->p_dev = link;
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
@@ -333,7 +333,6 @@
     link->irq.Handler = &smc_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The SMC91c92-specific entries in the device structure. */
@@ -357,13 +356,7 @@
     smc->mii_if.phy_id_mask = 0x1f;
     smc->mii_if.reg_num_mask = 0x1f;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    smc91c92_config(link);
-
-    return 0;
+    return smc91c92_config(link);
 } /* smc91c92_attach */
 
 /*======================================================================
@@ -375,18 +368,16 @@
 
 ======================================================================*/
 
-static void smc91c92_detach(struct pcmcia_device *p_dev)
+static void smc91c92_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "smc91c92_detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	smc91c92_release(link);
+    smc91c92_release(link);
 
     free_netdev(dev);
 } /* smc91c92_detach */
@@ -414,7 +405,7 @@
 
 /*====================================================================*/
 
-static int first_tuple(client_handle_t handle, tuple_t *tuple,
+static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		cisparse_t *parse)
 {
 	int i;
@@ -425,7 +416,7 @@
 	return pcmcia_parse_tuple(handle, tuple, parse);
 }
 
-static int next_tuple(client_handle_t handle, tuple_t *tuple,
+static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 		cisparse_t *parse)
 {
 	int i;
@@ -447,7 +438,7 @@
 
 ======================================================================*/
 
-static int mhz_3288_power(dev_link_t *link)
+static int mhz_3288_power(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -469,7 +460,7 @@
     return 0;
 }
 
-static int mhz_mfc_config(dev_link_t *link)
+static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -504,7 +495,7 @@
     tuple->TupleDataMax = 255;
     tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
-    i = first_tuple(link->handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
     while (i == CS_SUCCESS) {
@@ -513,11 +504,11 @@
 	for (k = 0; k < 0x400; k += 0x10) {
 	    if (k & 0x80) continue;
 	    link->io.BasePort1 = k ^ 0x300;
-	    i = pcmcia_request_io(link->handle, &link->io);
+	    i = pcmcia_request_io(link, &link->io);
 	    if (i == CS_SUCCESS) break;
 	}
 	if (i == CS_SUCCESS) break;
-	i = next_tuple(link->handle, tuple, parse);
+	i = next_tuple(link, tuple, parse);
     }
     if (i != CS_SUCCESS)
 	goto free_cfg_mem;
@@ -527,7 +518,7 @@
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
     req.Base = req.Size = 0;
     req.AccessSpeed = 0;
-    i = pcmcia_request_window(&link->handle, &req, &link->win);
+    i = pcmcia_request_window(&link, &req, &link->win);
     if (i != CS_SUCCESS)
 	goto free_cfg_mem;
     smc->base = ioremap(req.Base, req.Size);
@@ -546,9 +537,8 @@
     return i;
 }
 
-static int mhz_setup(dev_link_t *link)
+static int mhz_setup(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -571,13 +561,13 @@
     /* Read the station address from the CIS.  It is stored as the last
        (fourth) string in the Version 1 Version/ID tuple. */
     tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
 	rc = -1;
 	goto free_cfg_mem;
     }
     /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
-	first_tuple(handle, tuple, parse);
+    if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+	first_tuple(link, tuple, parse);
     if (parse->version_1.ns > 3) {
 	station_addr = parse->version_1.str + parse->version_1.ofs[3];
 	if (cvt_ascii_address(dev, station_addr) == 0) {
@@ -588,11 +578,11 @@
 
     /* Another possibility: for the EM3288, in a special tuple */
     tuple->DesiredTuple = 0x81;
-    if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
 	rc = -1;
 	goto free_cfg_mem;
     }
-    if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
 	rc = -1;
 	goto free_cfg_mem;
     }
@@ -616,7 +606,7 @@
 
 ======================================================================*/
 
-static void mot_config(dev_link_t *link)
+static void mot_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
@@ -637,7 +627,7 @@
     mdelay(100);
 }
 
-static int mot_setup(dev_link_t *link)
+static int mot_setup(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -671,7 +661,7 @@
 
 /*====================================================================*/
 
-static int smc_config(dev_link_t *link)
+static int smc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
@@ -696,16 +686,16 @@
     tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
     link->io.NumPorts1 = 16;
-    i = first_tuple(link->handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     while (i != CS_NO_MORE_ITEMS) {
 	if (i == CS_SUCCESS) {
 	    link->conf.ConfigIndex = cf->index;
 	    link->io.BasePort1 = cf->io.win[0].base;
 	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-	    i = pcmcia_request_io(link->handle, &link->io);
+	    i = pcmcia_request_io(link, &link->io);
 	    if (i == CS_SUCCESS) break;
 	}
-	i = next_tuple(link->handle, tuple, parse);
+	i = next_tuple(link, tuple, parse);
     }
     if (i == CS_SUCCESS)
 	dev->base_addr = link->io.BasePort1;
@@ -714,9 +704,8 @@
     return i;
 }
 
-static int smc_setup(dev_link_t *link)
+static int smc_setup(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -739,11 +728,11 @@
 
     /* Check for a LAN function extension tuple */
     tuple->DesiredTuple = CISTPL_FUNCE;
-    i = first_tuple(handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     while (i == CS_SUCCESS) {
 	if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
 	    break;
-	i = next_tuple(handle, tuple, parse);
+	i = next_tuple(link, tuple, parse);
     }
     if (i == CS_SUCCESS) {
 	node_id = (cistpl_lan_node_id_t *)parse->funce.data;
@@ -756,7 +745,7 @@
     }
     /* Try the third string in the Version 1 Version/ID tuple. */
     tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
 	rc = -1;
 	goto free_cfg_mem;
     }
@@ -774,7 +763,7 @@
 
 /*====================================================================*/
 
-static int osi_config(dev_link_t *link)
+static int osi_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
@@ -794,22 +783,21 @@
 
     for (i = j = 0; j < 4; j++) {
 	link->io.BasePort2 = com[j];
-	i = pcmcia_request_io(link->handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
 	if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
 	/* Fallback: turn off hard decode */
 	link->conf.ConfigIndex = 0x03;
 	link->io.NumPorts2 = 0;
-	i = pcmcia_request_io(link->handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
     }
     dev->base_addr = link->io.BasePort1 + 0x10;
     return i;
 }
 
-static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
+static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_cfg_mem *cfg_mem;
     tuple_t *tuple;
@@ -830,12 +818,12 @@
 
     /* Read the station address from tuple 0x90, subtuple 0x04 */
     tuple->DesiredTuple = 0x90;
-    i = pcmcia_get_first_tuple(handle, tuple);
+    i = pcmcia_get_first_tuple(link, tuple);
     while (i == CS_SUCCESS) {
-	i = pcmcia_get_tuple_data(handle, tuple);
+	i = pcmcia_get_tuple_data(link, tuple);
 	if ((i != CS_SUCCESS) || (buf[0] == 0x04))
 	    break;
-	i = pcmcia_get_next_tuple(handle, tuple);
+	i = pcmcia_get_next_tuple(link, tuple);
     }
     if (i != CS_SUCCESS) {
 	rc = -1;
@@ -868,56 +856,46 @@
    return rc;
 }
 
-static int smc91c92_suspend(struct pcmcia_device *p_dev)
+static int smc91c92_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int smc91c92_resume(struct pcmcia_device *p_dev)
+static int smc91c92_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct smc_private *smc = netdev_priv(dev);
 	int i;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if ((smc->manfid == MANFID_MEGAHERTZ) &&
-		    (smc->cardid == PRODID_MEGAHERTZ_EM3288))
-			mhz_3288_power(link);
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (smc->manfid == MANFID_MOTOROLA)
-			mot_config(link);
-		if ((smc->manfid == MANFID_OSITECH) &&
-		    (smc->cardid != PRODID_OSITECH_SEVEN)) {
-			/* Power up the card and enable interrupts */
-			set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
-			set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+	if ((smc->manfid == MANFID_MEGAHERTZ) &&
+	    (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+		mhz_3288_power(link);
+	if (smc->manfid == MANFID_MOTOROLA)
+		mot_config(link);
+	if ((smc->manfid == MANFID_OSITECH) &&
+	    (smc->cardid != PRODID_OSITECH_SEVEN)) {
+		/* Power up the card and enable interrupts */
+		set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+		set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+	}
+	if (((smc->manfid == MANFID_OSITECH) &&
+	     (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+	    ((smc->manfid == MANFID_PSION) &&
+	     (smc->cardid == PRODID_PSION_NET100))) {
+		/* Download the Seven of Diamonds firmware */
+		for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+			outb(__Xilinx7OD[i], link->io.BasePort1+2);
+			udelay(50);
 		}
-		if (((smc->manfid == MANFID_OSITECH) &&
-		     (smc->cardid == PRODID_OSITECH_SEVEN)) ||
-		    ((smc->manfid == MANFID_PSION) &&
-		     (smc->cardid == PRODID_PSION_NET100))) {
-			/* Download the Seven of Diamonds firmware */
-			for (i = 0; i < sizeof(__Xilinx7OD); i++) {
-				outb(__Xilinx7OD[i], link->io.BasePort1+2);
-				udelay(50);
-			}
-		}
-		if (link->open) {
-			smc_reset(dev);
-			netif_device_attach(dev);
-		}
+	}
+	if (link->open) {
+		smc_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -931,7 +909,7 @@
 
 ======================================================================*/
 
-static int check_sig(dev_link_t *link)
+static int check_sig(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     kio_addr_t ioaddr = dev->base_addr;
@@ -964,13 +942,15 @@
     }
 
     if (width) {
-	printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
-	smc91c92_suspend(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	pcmcia_request_io(link->handle, &link->io);
-	smc91c92_resume(link->handle);
-	return check_sig(link);
+	    modconf_t mod = {
+		    .Attributes = CONF_IO_CHANGE_WIDTH,
+	    };
+	    printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
+
+	    smc91c92_suspend(link);
+	    pcmcia_modify_configuration(link, &mod);
+	    smc91c92_resume(link);
+	    return check_sig(link);
     }
     return -ENODEV;
 }
@@ -984,11 +964,10 @@
 ======================================================================*/
 
 #define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }
+if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
 
-static void smc91c92_config(dev_link_t *link)
+static int smc91c92_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     struct smc_cfg_mem *cfg_mem;
@@ -1015,21 +994,18 @@
     tuple->TupleDataMax = 64;
 
     tuple->DesiredTuple = CISTPL_CONFIG;
-    i = first_tuple(handle, tuple, parse);
+    i = first_tuple(link, tuple, parse);
     CS_EXIT_TEST(i, ParseTuple, config_failed);
     link->conf.ConfigBase = parse->config.base;
     link->conf.Present = parse->config.rmask[0];
 
     tuple->DesiredTuple = CISTPL_MANFID;
     tuple->Attributes = TUPLE_RETURN_COMMON;
-    if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
 	smc->manfid = parse->manfid.manf;
 	smc->cardid = parse->manfid.card;
     }
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     if ((smc->manfid == MANFID_OSITECH) &&
 	(smc->cardid != PRODID_OSITECH_SEVEN)) {
 	i = osi_config(link);
@@ -1043,9 +1019,9 @@
     }
     CS_EXIT_TEST(i, RequestIO, config_failed);
 
-    i = pcmcia_request_irq(link->handle, &link->irq);
+    i = pcmcia_request_irq(link, &link->irq);
     CS_EXIT_TEST(i, RequestIRQ, config_failed);
-    i = pcmcia_request_configuration(link->handle, &link->conf);
+    i = pcmcia_request_configuration(link, &link->conf);
     CS_EXIT_TEST(i, RequestConfiguration, config_failed);
 
     if (smc->manfid == MANFID_MOTOROLA)
@@ -1124,13 +1100,12 @@
 	SMC_SELECT_BANK(0);
     }
 
-    link->dev = &smc->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &smc->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto config_undo;
     }
 
@@ -1160,15 +1135,14 @@
 	}
     }
     kfree(cfg_mem);
-    return;
+    return 0;
 
 config_undo:
     unregister_netdev(dev);
 config_failed:			/* CS_EXIT_TEST() calls jump to here... */
     smc91c92_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
     kfree(cfg_mem);
-
+    return -ENODEV;
 } /* smc91c92_config */
 
 /*======================================================================
@@ -1179,22 +1153,15 @@
 
 ======================================================================*/
 
-static void smc91c92_release(dev_link_t *link)
+static void smc91c92_release(struct pcmcia_device *link)
 {
-
-    DEBUG(0, "smc91c92_release(0x%p)\n", link);
-
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    if (link->win) {
-	struct net_device *dev = link->priv;
-	struct smc_private *smc = netdev_priv(dev);
-	iounmap(smc->base);
-	pcmcia_release_window(link->win);
-    }
-
-    link->state &= ~DEV_CONFIG;
+	DEBUG(0, "smc91c92_release(0x%p)\n", link);
+	if (link->win) {
+		struct net_device *dev = link->priv;
+		struct smc_private *smc = netdev_priv(dev);
+		iounmap(smc->base);
+	}
+	pcmcia_disable_device(link);
 }
 
 /*======================================================================
@@ -1283,7 +1250,7 @@
 static int smc_open(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    dev_link_t *link = &smc->link;
+    struct pcmcia_device *link = smc->p_dev;
 
 #ifdef PCMCIA_DEBUG
     DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",
@@ -1292,7 +1259,7 @@
 #endif
 
     /* Check that the PCMCIA card is still here. */
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
     /* Physical device present signature. */
     if (check_sig(link) < 0) {
@@ -1320,7 +1287,7 @@
 static int smc_close(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    dev_link_t *link = &smc->link;
+    struct pcmcia_device *link = smc->p_dev;
     kio_addr_t ioaddr = dev->base_addr;
 
     DEBUG(0, "%s: smc_close(), status %4.4x.\n",
@@ -2311,7 +2278,7 @@
 	.drv		= {
 		.name	= "smc91c92_cs",
 	},
-	.probe		= smc91c92_attach,
+	.probe		= smc91c92_probe,
 	.remove		= smc91c92_detach,
 	.id_table       = smc91c92_ids,
 	.suspend	= smc91c92_suspend,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index e8f849e..71f4505 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -289,9 +289,9 @@
  * and ejection events.  They are invoked from the event handler.
  */
 
-static int has_ce2_string(dev_link_t * link);
-static void xirc2ps_config(dev_link_t * link);
-static void xirc2ps_release(dev_link_t * link);
+static int has_ce2_string(struct pcmcia_device * link);
+static int xirc2ps_config(struct pcmcia_device * link);
+static void xirc2ps_release(struct pcmcia_device * link);
 
 /****************
  * The attach() and detach() entry points are used to create and destroy
@@ -313,10 +313,10 @@
 /****************
  * A linked list of "instances" of the device.  Each actual
  * PCMCIA card corresponds to one device instance, and is described
- * by one dev_link_t structure (defined in ds.h).
+ * by one struct pcmcia_device structure (defined in ds.h).
  *
  * You may not want to use a linked list for this -- for example, the
- * memory card driver uses an array of dev_link_t pointers, where minor
+ * memory card driver uses an array of struct pcmcia_device pointers, where minor
  * device numbers are used to derive the corresponding array index.
  */
 
@@ -326,13 +326,13 @@
  * example, ethernet cards, modems).  In other cases, there may be
  * many actual or logical devices (SCSI adapters, memory cards with
  * multiple partitions).  The dev_node_t structures need to be kept
- * in a linked list starting at the 'dev' field of a dev_link_t
+ * in a linked list starting at the 'dev' field of a struct pcmcia_device
  * structure.  We allocate them in the card's private data structure,
  * because they generally can't be allocated dynamically.
  */
 
 typedef struct local_info_t {
-    dev_link_t link;
+	struct pcmcia_device	*p_dev;
     dev_node_t node;
     struct net_device_stats stats;
     int card_type;
@@ -355,7 +355,7 @@
 static struct net_device_stats *do_get_stats(struct net_device *dev);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
-static int set_card_type(dev_link_t *link, const void *s);
+static int set_card_type(struct pcmcia_device *link, const void *s);
 static int do_config(struct net_device *dev, struct ifmap *map);
 static int do_open(struct net_device *dev);
 static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -368,7 +368,7 @@
 
 /*=============== Helper functions =========================*/
 static int
-first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int err;
 
@@ -379,7 +379,7 @@
 }
 
 static int
-next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int err;
 
@@ -553,9 +553,8 @@
  */
 
 static int
-xirc2ps_attach(struct pcmcia_device *p_dev)
+xirc2ps_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     struct net_device *dev;
     local_info_t *local;
 
@@ -566,12 +565,11 @@
     if (!dev)
 	    return -ENOMEM;
     local = netdev_priv(dev);
-    link = &local->link;
+    local->p_dev = link;
     link->priv = dev;
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -593,13 +591,7 @@
     dev->watchdog_timeo = TX_TIMEOUT;
 #endif
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    xirc2ps_config(link);
-
-    return 0;
+    return xirc2ps_config(link);
 } /* xirc2ps_attach */
 
 /****************
@@ -610,18 +602,16 @@
  */
 
 static void
-xirc2ps_detach(struct pcmcia_device *p_dev)
+xirc2ps_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
 
     DEBUG(0, "detach(0x%p)\n", link);
 
-    if (link->dev)
+    if (link->dev_node)
 	unregister_netdev(dev);
 
-    if (link->state & DEV_CONFIG)
-	xirc2ps_release(link);
+    xirc2ps_release(link);
 
     free_netdev(dev);
 } /* xirc2ps_detach */
@@ -645,7 +635,7 @@
  *
  */
 static int
-set_card_type(dev_link_t *link, const void *s)
+set_card_type(struct pcmcia_device *link, const void *s)
 {
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
@@ -714,9 +704,8 @@
  * Returns: true if this is a CE2
  */
 static int
-has_ce2_string(dev_link_t * link)
+has_ce2_string(struct pcmcia_device * link)
 {
-    client_handle_t handle = link->handle;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[256];
@@ -726,7 +715,7 @@
     tuple.TupleDataMax = 254;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_VERS_1;
-    if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) {
+    if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) {
 	if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
 	    return 1;
     }
@@ -738,10 +727,9 @@
  * is received, to configure the PCMCIA socket, and to make the
  * ethernet device available to the system.
  */
-static void
-xirc2ps_config(dev_link_t * link)
+static int
+xirc2ps_config(struct pcmcia_device * link)
 {
-    client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
     tuple_t tuple;
@@ -767,7 +755,7 @@
 
     /* Is this a valid	card */
     tuple.DesiredTuple = CISTPL_MANFID;
-    if ((err=first_tuple(handle, &tuple, &parse))) {
+    if ((err=first_tuple(link, &tuple, &parse))) {
 	printk(KNOT_XIRC "manfid not found in CIS\n");
 	goto failure;
     }
@@ -803,15 +791,15 @@
 
     /* get configuration stuff */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    if ((err=first_tuple(handle, &tuple, &parse)))
+    if ((err=first_tuple(link, &tuple, &parse)))
 	goto cis_error;
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present =    parse.config.rmask[0];
 
     /* get the ethernet address from the CIS */
     tuple.DesiredTuple = CISTPL_FUNCE;
-    for (err = first_tuple(handle, &tuple, &parse); !err;
-			     err = next_tuple(handle, &tuple, &parse)) {
+    for (err = first_tuple(link, &tuple, &parse); !err;
+			     err = next_tuple(link, &tuple, &parse)) {
 	/* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
 	 * the first one with a length of zero the second correct -
 	 * so I skip all entries with length 0 */
@@ -821,8 +809,8 @@
     }
     if (err) { /* not found: try to get the node-id from tuple 0x89 */
 	tuple.DesiredTuple = 0x89;  /* data layout looks like tuple 0x22 */
-	if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 &&
-		(err = pcmcia_get_tuple_data(handle, &tuple)) == 0) {
+	if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 &&
+		(err = pcmcia_get_tuple_data(link, &tuple)) == 0) {
 	    if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
 		memcpy(&parse, buf, 8);
 	    else
@@ -831,8 +819,8 @@
     }
     if (err) { /* another try	(James Lehmer's CE2 version 4.1)*/
 	tuple.DesiredTuple = CISTPL_FUNCE;
-	for (err = first_tuple(handle, &tuple, &parse); !err;
-				 err = next_tuple(handle, &tuple, &parse)) {
+	for (err = first_tuple(link, &tuple, &parse); !err;
+				 err = next_tuple(link, &tuple, &parse)) {
 	    if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
 		&& parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
 		buf[1] = 4;
@@ -853,9 +841,6 @@
     for (i=0; i < 6; i++)
 	dev->dev_addr[i] = node_id->id[i];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     link->io.IOAddrLines =10;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
     link->irq.Attributes = IRQ_HANDLE_PRESENT;
@@ -875,14 +860,14 @@
 	     * Ethernet port */
 	    link->io.NumPorts1 = 16; /* no Mako stuff anymore */
 	    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	    for (err = first_tuple(handle, &tuple, &parse); !err;
-				 err = next_tuple(handle, &tuple, &parse)) {
+	    for (err = first_tuple(link, &tuple, &parse); !err;
+				 err = next_tuple(link, &tuple, &parse)) {
 		if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
 		    for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 			link->conf.ConfigIndex = cf->index ;
 			link->io.BasePort2 = cf->io.win[0].base;
 			link->io.BasePort1 = ioaddr;
-			if (!(err=pcmcia_request_io(link->handle, &link->io)))
+			if (!(err=pcmcia_request_io(link, &link->io)))
 			    goto port_found;
 		    }
 		}
@@ -896,15 +881,15 @@
 	     */
 	    for (pass=0; pass < 2; pass++) {
 		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-		for (err = first_tuple(handle, &tuple, &parse); !err;
-				     err = next_tuple(handle, &tuple, &parse)){
+		for (err = first_tuple(link, &tuple, &parse); !err;
+				     err = next_tuple(link, &tuple, &parse)){
 		    if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8){
 			link->conf.ConfigIndex = cf->index ;
 			link->io.BasePort2 = cf->io.win[0].base;
 			link->io.BasePort1 = link->io.BasePort2
 				    + (pass ? (cf->index & 0x20 ? -24:8)
 					    : (cf->index & 0x20 ?   8:-24));
-			if (!(err=pcmcia_request_io(link->handle, &link->io)))
+			if (!(err=pcmcia_request_io(link, &link->io)))
 			    goto port_found;
 		    }
 		}
@@ -919,12 +904,12 @@
 	link->io.NumPorts1 = 16;
 	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 	    link->io.BasePort1 = ioaddr;
-	    if (!(err=pcmcia_request_io(link->handle, &link->io)))
+	    if (!(err=pcmcia_request_io(link, &link->io)))
 		goto port_found;
 	}
 	link->io.BasePort1 = 0; /* let CS decide */
-	if ((err=pcmcia_request_io(link->handle, &link->io))) {
-	    cs_error(link->handle, RequestIO, err);
+	if ((err=pcmcia_request_io(link, &link->io))) {
+	    cs_error(link, RequestIO, err);
 	    goto config_error;
 	}
     }
@@ -936,8 +921,8 @@
      * Now allocate an interrupt line.	Note that this does not
      * actually assign a handler to the interrupt.
      */
-    if ((err=pcmcia_request_irq(link->handle, &link->irq))) {
-	cs_error(link->handle, RequestIRQ, err);
+    if ((err=pcmcia_request_irq(link, &link->irq))) {
+	cs_error(link, RequestIRQ, err);
 	goto config_error;
     }
 
@@ -945,8 +930,8 @@
      * This actually configures the PCMCIA socket -- setting up
      * the I/O windows and the interrupt mapping.
      */
-    if ((err=pcmcia_request_configuration(link->handle, &link->conf))) {
-	cs_error(link->handle, RequestConfiguration, err);
+    if ((err=pcmcia_request_configuration(link, &link->conf))) {
+	cs_error(link, RequestConfiguration, err);
 	goto config_error;
     }
 
@@ -963,15 +948,15 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_IOBASE_0;
 	reg.Value = link->io.BasePort2 & 0xff;
-	if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
-	    cs_error(link->handle, AccessConfigurationRegister, err);
+	if ((err = pcmcia_access_configuration_register(link, &reg))) {
+	    cs_error(link, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_IOBASE_1;
 	reg.Value = (link->io.BasePort2 >> 8) & 0xff;
-	if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {
-	    cs_error(link->handle, AccessConfigurationRegister, err);
+	if ((err = pcmcia_access_configuration_register(link, &reg))) {
+	    cs_error(link, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
 
@@ -982,15 +967,15 @@
 	req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
 	req.Base = req.Size = 0;
 	req.AccessSpeed = 0;
-	if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) {
-	    cs_error(link->handle, RequestWindow, err);
+	if ((err = pcmcia_request_window(&link, &req, &link->win))) {
+	    cs_error(link, RequestWindow, err);
 	    goto config_error;
 	}
 	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
 	mem.CardOffset = 0x0;
 	mem.Page = 0;
 	if ((err = pcmcia_map_mem_page(link->win, &mem))) {
-	    cs_error(link->handle, MapMemPage, err);
+	    cs_error(link, MapMemPage, err);
 	    goto config_error;
 	}
 
@@ -1050,13 +1035,12 @@
     if (local->dingo)
 	do_reset(dev, 1); /* a kludge to make the cem56 work */
 
-    link->dev = &local->node;
-    link->state &= ~DEV_CONFIG_PENDING;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    link->dev_node = &local->node;
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if ((err=register_netdev(dev))) {
 	printk(KNOT_XIRC "register_netdev() failed\n");
-	link->dev = NULL;
+	link->dev_node = NULL;
 	goto config_error;
     }
 
@@ -1069,17 +1053,16 @@
 	printk("%c%02X", i?':':' ', dev->dev_addr[i]);
     printk("\n");
 
-    return;
+    return 0;
 
   config_error:
-    link->state &= ~DEV_CONFIG_PENDING;
     xirc2ps_release(link);
-    return;
+    return -ENODEV;
 
   cis_error:
     printk(KNOT_XIRC "unable to parse CIS\n");
   failure:
-    link->state &= ~DEV_CONFIG_PENDING;
+    return -ENODEV;
 } /* xirc2ps_config */
 
 /****************
@@ -1088,57 +1071,41 @@
  * still open, this will be postponed until it is closed.
  */
 static void
-xirc2ps_release(dev_link_t *link)
+xirc2ps_release(struct pcmcia_device *link)
 {
+	DEBUG(0, "release(0x%p)\n", link);
 
-    DEBUG(0, "release(0x%p)\n", link);
-
-    if (link->win) {
-	struct net_device *dev = link->priv;
-	local_info_t *local = netdev_priv(dev);
-	if (local->dingo)
-	    iounmap(local->dingo_ccr - 0x0800);
-	pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    link->state &= ~DEV_CONFIG;
-
+	if (link->win) {
+		struct net_device *dev = link->priv;
+		local_info_t *local = netdev_priv(dev);
+		if (local->dingo)
+			iounmap(local->dingo_ccr - 0x0800);
+	}
+	pcmcia_disable_device(link);
 } /* xirc2ps_release */
 
 /*====================================================================*/
 
 
-static int xirc2ps_suspend(struct pcmcia_device *p_dev)
+static int xirc2ps_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open) {
-			netif_device_detach(dev);
-			do_powerdown(dev);
-		}
-		pcmcia_release_configuration(link->handle);
+	if (link->open) {
+		netif_device_detach(dev);
+		do_powerdown(dev);
 	}
 
 	return 0;
 }
 
-static int xirc2ps_resume(struct pcmcia_device *p_dev)
+static int xirc2ps_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			do_reset(dev,1);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		do_reset(dev,1);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -1552,13 +1519,13 @@
 do_open(struct net_device *dev)
 {
     local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(0, "do_open(%p)\n", dev);
 
     /* Check that the PCMCIA card is still here. */
     /* Physical device present signature. */
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
     /* okay */
@@ -1882,7 +1849,7 @@
 {
     kio_addr_t ioaddr = dev->base_addr;
     local_info_t *lp = netdev_priv(dev);
-    dev_link_t *link = &lp->link;
+    struct pcmcia_device *link = lp->p_dev;
 
     DEBUG(0, "do_stop(%p)\n", dev);
 
@@ -1935,7 +1902,7 @@
 	.drv		= {
 		.name	= "xirc2ps_cs",
 	},
-	.probe		= xirc2ps_attach,
+	.probe		= xirc2ps_probe,
 	.remove		= xirc2ps_detach,
 	.id_table       = xirc2ps_ids,
 	.suspend	= xirc2ps_suspend,
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 35dbf05..a70c2b0 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -78,6 +78,8 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */
 	{ PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) },
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 68f9c20..227df98 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -51,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.1"
+#define DRV_VERSION		"1.2"
 #define PFX			DRV_NAME " "
 
 /*
@@ -99,8 +99,6 @@
 static const struct pci_device_id sky2_id_table[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -579,8 +577,8 @@
 	reg = gma_read16(hw, port, GM_PHY_ADDR);
 	gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
 
-	for (i = 0; i < GM_MIB_CNT_SIZE; i++)
-		gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
+	for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4)
+		gma_read16(hw, port, i);
 	gma_write16(hw, port, GM_PHY_ADDR, reg);
 
 	/* transmit control */
@@ -927,8 +925,7 @@
 	skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
 	if (likely(skb)) {
 		unsigned long p	= (unsigned long) skb->data;
-		skb_reserve(skb,
-			((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+		skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p);
 	}
 
 	return skb;
@@ -1688,13 +1685,12 @@
 }
 
 
-#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
 /* Want receive buffer size to be multiple of 64 bits
  * and incl room for vlan and truncation
  */
 static inline unsigned sky2_buf_size(int mtu)
 {
-	return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
+	return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8;
 }
 
 static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2088,6 +2084,20 @@
 	}
 }
 
+/* If idle then force a fake soft NAPI poll once a second
+ * to work around cases where sharing an edge triggered interrupt.
+ */
+static void sky2_idle(unsigned long arg)
+{
+	struct net_device *dev = (struct net_device *) arg;
+
+	local_irq_disable();
+	if (__netif_rx_schedule_prep(dev))
+		__netif_rx_schedule(dev);
+	local_irq_enable();
+}
+
+
 static int sky2_poll(struct net_device *dev0, int *budget)
 {
 	struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
@@ -2095,6 +2105,7 @@
 	int work_done = 0;
 	u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
+ restart_poll:
 	if (unlikely(status & ~Y2_IS_STAT_BMU)) {
 		if (status & Y2_IS_HW_ERR)
 			sky2_hw_intr(hw);
@@ -2125,7 +2136,7 @@
 	}
 
 	if (status & Y2_IS_STAT_BMU) {
-		work_done = sky2_status_intr(hw, work_limit);
+		work_done += sky2_status_intr(hw, work_limit - work_done);
 		*budget -= work_done;
 		dev0->quota -= work_done;
 
@@ -2135,9 +2146,24 @@
 		sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
 	}
 
-	netif_rx_complete(dev0);
+	mod_timer(&hw->idle_timer, jiffies + HZ);
+
+	local_irq_disable();
+	__netif_rx_complete(dev0);
 
 	status = sky2_read32(hw, B0_Y2_SP_LISR);
+
+	if (unlikely(status)) {
+		/* More work pending, try and keep going */
+		if (__netif_rx_schedule_prep(dev0)) {
+			__netif_rx_reschedule(dev0, work_done);
+			status = sky2_read32(hw, B0_Y2_SP_EISR);
+			local_irq_enable();
+			goto restart_poll;
+		}
+	}
+
+	local_irq_enable();
 	return 0;
 }
 
@@ -2155,8 +2181,6 @@
 	prefetch(&hw->st_le[hw->st_idx]);
 	if (likely(__netif_rx_schedule_prep(dev0)))
 		__netif_rx_schedule(dev0);
-	else
-		printk(KERN_DEBUG PFX "irq race detected\n");
 
 	return IRQ_HANDLED;
 }
@@ -2195,7 +2219,7 @@
 }
 
 
-static int sky2_reset(struct sky2_hw *hw)
+static int __devinit sky2_reset(struct sky2_hw *hw)
 {
 	u16 status;
 	u8 t8, pmd_type;
@@ -3278,6 +3302,8 @@
 
 	sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
 
+	setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev);
+
 	pci_set_drvdata(pdev, hw);
 
 	return 0;
@@ -3313,13 +3339,15 @@
 	if (!hw)
 		return;
 
+	del_timer_sync(&hw->idle_timer);
+
+	sky2_write32(hw, B0_IMSK, 0);
 	dev0 = hw->dev[0];
 	dev1 = hw->dev[1];
 	if (dev1)
 		unregister_netdev(dev1);
 	unregister_netdev(dev0);
 
-	sky2_write32(hw, B0_IMSK, 0);
 	sky2_set_power_state(hw, PCI_D3hot);
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 	sky2_write8(hw, B0_CTST, CS_RST_SET);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 62532b4..b026f56 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1375,7 +1375,7 @@
 	GM_PHY_ADDR	= 0x0088,	/* 16 bit r/w	GPHY Address Register */
 /* MIB Counters */
 	GM_MIB_CNT_BASE	= 0x0100,	/* Base Address of MIB Counters */
-	GM_MIB_CNT_SIZE	= 256,
+	GM_MIB_CNT_END	= 0x025C,	/* Last MIB counter */
 };
 
 
@@ -1880,6 +1880,8 @@
 	struct sky2_status_le *st_le;
 	u32		     st_idx;
 	dma_addr_t   	     st_dma;
+
+	struct timer_list    idle_timer;
 	int		     msi_detected;
 	wait_queue_head_t    msi_wait;
 };
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 35b1805..9b7805b 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -335,7 +335,7 @@
 
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
@@ -2122,8 +2122,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct netdev_private *np = netdev_priv(dev);
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 
 	unregister_netdev(dev);
 
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index cb0aba9..046371e 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -275,7 +275,7 @@
 	return 0;
 }
 
-static int bcm5411_suspend(struct mii_phy* phy)
+static int generic_suspend(struct mii_phy* phy)
 {
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
 
@@ -738,7 +738,7 @@
 /* Broadcom BCM 5411 */
 static struct mii_phy_ops bcm5411_phy_ops = {
 	.init		= bcm5411_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -757,7 +757,7 @@
 /* Broadcom BCM 5421 */
 static struct mii_phy_ops bcm5421_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -776,7 +776,7 @@
 /* Broadcom BCM 5421 built-in K2 */
 static struct mii_phy_ops bcm5421k2_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -795,7 +795,7 @@
 /* Broadcom BCM 5462 built-in Vesta */
 static struct mii_phy_ops bcm5462V_phy_ops = {
 	.init		= bcm5421_init,
-	.suspend	= bcm5411_suspend,
+	.suspend	= generic_suspend,
 	.setup_aneg	= bcm54xx_setup_aneg,
 	.setup_forced	= bcm54xx_setup_forced,
 	.poll_link	= genmii_poll_link,
@@ -816,6 +816,7 @@
  * would be useful here) --BenH.
  */
 static struct mii_phy_ops marvell_phy_ops = {
+	.suspend	= generic_suspend,
 	.setup_aneg	= marvell_setup_aneg,
 	.setup_forced	= marvell_setup_forced,
 	.poll_link	= genmii_poll_link,
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 964c096..73e271e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.55"
-#define DRV_MODULE_RELDATE	"Mar 27, 2006"
+#define DRV_MODULE_VERSION	"3.56"
+#define DRV_MODULE_RELDATE	"Apr 1, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -497,18 +497,18 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->indirect_lock, flags);
-	if (tp->write32 != tg3_write_indirect_reg32) {
-		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
-		tw32_f(TG3PCI_MEM_WIN_DATA, val);
-
-		/* Always leave this as zero. */
-		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-	} else {
+	if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
 		/* Always leave this as zero. */
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	} else {
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+		tw32_f(TG3PCI_MEM_WIN_DATA, val);
+
+		/* Always leave this as zero. */
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 	}
 	spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
@@ -518,18 +518,18 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->indirect_lock, flags);
-	if (tp->write32 != tg3_write_indirect_reg32) {
-		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
-		*val = tr32(TG3PCI_MEM_WIN_DATA);
-
-		/* Always leave this as zero. */
-		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
-	} else {
+	if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) {
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 		pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
 		/* Always leave this as zero. */
 		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
+	} else {
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
+		*val = tr32(TG3PCI_MEM_WIN_DATA);
+
+		/* Always leave this as zero. */
+		tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 	}
 	spin_unlock_irqrestore(&tp->indirect_lock, flags);
 }
@@ -2966,9 +2966,7 @@
 		struct sk_buff *skb = ri->skb;
 		int i;
 
-		if (unlikely(skb == NULL))
-			BUG();
-
+		BUG_ON(skb == NULL);
 		pci_unmap_single(tp->pdev,
 				 pci_unmap_addr(ri, mapping),
 				 skb_headlen(skb),
@@ -2979,12 +2977,10 @@
 		sw_idx = NEXT_TX(sw_idx);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			if (unlikely(sw_idx == hw_idx))
-				BUG();
+			BUG_ON(sw_idx == hw_idx);
 
 			ri = &tp->tx_buffers[sw_idx];
-			if (unlikely(ri->skb != NULL))
-				BUG();
+			BUG_ON(ri->skb != NULL);
 
 			pci_unmap_page(tp->pdev,
 				       pci_unmap_addr(ri, mapping),
@@ -4935,9 +4931,8 @@
 {
 	int i;
 
-	if (offset == TX_CPU_BASE &&
-	    (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
-		BUG();
+	BUG_ON(offset == TX_CPU_BASE &&
+	    (tp->tg3_flags2 & TG3_FLG2_5705_PLUS));
 
 	if (offset == RX_CPU_BASE) {
 		for (i = 0; i < 10000; i++) {
@@ -5840,10 +5835,14 @@
 			  GRC_MODE_NO_TX_PHDR_CSUM |
 			  GRC_MODE_NO_RX_PHDR_CSUM);
 	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
-		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
-	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
-		tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
+
+	/* Pseudo-header checksum is done by hardware logic and not
+	 * the offload processers, so make the chip do the pseudo-
+	 * header checksums on receive.  For transmit it is more
+	 * convenient to do the pseudo-header checksum in software
+	 * as Linux does that on transmit for us in all cases.
+	 */
+	tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 
 	tw32(GRC_MODE,
 	     tp->grc_mode |
@@ -8046,9 +8045,13 @@
 		for (i = 0; i < size; i++)
 			csum8 += buf8[i];
 
-		if (csum8 == 0)
-			return 0;
-		return -EIO;
+		if (csum8 == 0) {
+			err = 0;
+			goto out;
+		}
+
+		err = -EIO;
+		goto out;
 	}
 
 	/* Bootstrap checksum at offset 0x10 */
@@ -9543,8 +9546,11 @@
 	tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
 	/* Do not even try poking around in here on Sun parts.  */
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+		/* All SUN chips are built-in LOMs. */
+		tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 		return;
+	}
 
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9642,9 +9648,7 @@
 		    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
 			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 
-		if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
-		    (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
-		    (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
+		if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
 			tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
 		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
@@ -10269,6 +10273,13 @@
 		pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
 	}
 
+	if (tp->write32 == tg3_write_indirect_reg32 ||
+	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+	     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+	      GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
+	    (tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+		tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
+
 	/* Get eeprom hw config before calling tg3_set_power_state().
 	 * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
 	 * determined before calling tg3_set_power_state() so that
@@ -10311,15 +10322,6 @@
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
 		tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
 
-	/* Pseudo-header checksum is done by hardware logic and not
-	 * the offload processers, so make the chip do the pseudo-
-	 * header checksums on receive.  For transmit it is more
-	 * convenient to do the pseudo-header checksum in software
-	 * as Linux does that on transmit for us in all cases.
-	 */
-	tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
-	tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
-
 	/* Derive initial jumbo mode from MTU assigned in
 	 * ether_setup() via the alloc_etherdev() call
 	 */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index c43cc32..8c8b987 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2171,8 +2171,7 @@
 #define TG3_FLAG_PCIX_MODE		0x00020000
 #define TG3_FLAG_PCI_HIGH_SPEED		0x00040000
 #define TG3_FLAG_PCI_32BIT		0x00080000
-#define TG3_FLAG_NO_TX_PSEUDO_CSUM	0x00100000
-#define TG3_FLAG_NO_RX_PSEUDO_CSUM	0x00200000
+#define TG3_FLAG_SRAM_USE_CONFIG	0x00100000
 #define TG3_FLAG_SERDES_WOL_CAP		0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE	0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 9345e68..649d8ea 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -438,8 +438,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	unregister_netdev(dev);
 	release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
 	free_irq(dev->irq, dev);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index 3a25d19..19e6f4d 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -735,8 +735,7 @@
 	struct net_local *tp;
         struct card_info *card;
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 
 	tp = dev->priv;
 	card = tp->tmspriv;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index c1ce87a..d9258d4 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -134,7 +134,7 @@
 #include "typhoon.h"
 #include "typhoon-firmware.h"
 
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index a9b2150..6a23964 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -469,7 +469,7 @@
 	struct sk_buff *tx_skbuff[TX_RING_SIZE];
 	dma_addr_t tx_skbuff_dma[TX_RING_SIZE];
 
-	/* Tx bounce buffers */
+	/* Tx bounce buffers (Rhine-I only) */
 	unsigned char *tx_buf[TX_RING_SIZE];
 	unsigned char *tx_bufs;
 	dma_addr_t tx_bufs_dma;
@@ -1043,7 +1043,8 @@
 		rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC);
 		next += sizeof(struct tx_desc);
 		rp->tx_ring[i].next_desc = cpu_to_le32(next);
-		rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
+		if (rp->quirks & rqRhineI)
+			rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ];
 	}
 	rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma);
 
@@ -1091,7 +1092,7 @@
 }
 
 /* Called after status of force_media possibly changed */
-void rhine_set_carrier(struct mii_if_info *mii)
+static void rhine_set_carrier(struct mii_if_info *mii)
 {
 	if (mii->force_media) {
 		/* autoneg is off: Link is always assumed to be up */
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 883cf7d..b5328b0 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -410,103 +410,6 @@
 
 	  If unsure, say N.
 
-config VENDOR_SANGOMA
-	tristate "Sangoma WANPIPE(tm) multiprotocol cards"
-	depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN
-	---help---
-	  Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA).
-
-	  WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/>
-	  is a family of intelligent multiprotocol WAN adapters with data
-	  transfer rates up to 4Mbps. Cards support:
-
-	  - X.25, Frame Relay, PPP, Cisco HDLC protocols.
-
-	  - API for protocols like HDLC (LAPB), HDLC Streaming, X.25,
-	  Frame Relay and BiSync.
-
-	  - Ethernet Bridging over Frame Relay protocol.
-
-	  - MULTILINK PPP
-
-	  - Async PPP (Modem Dialup)
-
-	  The next questions will ask you about the protocols you want
-	  the driver to support.
-
-	  If you have one or more of these cards, say M to this option;
-	  and read <file:Documentation/networking/wan-router.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called wanpipe.
-
-config WANPIPE_CHDLC
-	bool "WANPIPE Cisco HDLC support"
-	depends on VENDOR_SANGOMA
-	---help---
-	  Connect a WANPIPE card to a leased line using the Cisco HDLC.
-
-	  - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards
-	  which allows user to build applications using the HDLC streaming API.
-
-	  - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1
-	  cards into a single logical channel.
-
-	  Say Y and the Cisco HDLC support, HDLC streaming API and
-	  MULTILINK PPP will be included in the driver.
-
-config WANPIPE_FR
-	bool "WANPIPE Frame Relay support"
-	depends on VENDOR_SANGOMA
-	help
-	  Connect a WANPIPE card to a Frame Relay network, or use Frame Relay
-	  API to develop custom applications.
-
-	  Contains the Ethernet Bridging over Frame Relay feature, where
-	  a WANPIPE frame relay link can be directly connected to the Linux
-	  kernel bridge. The Frame Relay option is supported on S514-PCI
-	  and S508-ISA cards.
-
-	  Say Y and the Frame Relay support will be included in the driver.
-
-config WANPIPE_X25
-	bool "WANPIPE X.25 support"
-	depends on VENDOR_SANGOMA
-	help
-	  Connect a WANPIPE card to an X.25 network.
-
-	  Includes the X.25 API support for custom applications over the
-	  X.25 protocol. The X.25 option is supported on S514-PCI and
-	  S508-ISA cards.
-
-	  Say Y and the X.25 support will be included in the driver.
-
-config WANPIPE_PPP
-	bool "WANPIPE PPP support"
-	depends on VENDOR_SANGOMA
-	help
-	  Connect a WANPIPE card to a leased line using Point-to-Point
-	  Protocol (PPP).
-
-	  The PPP option is supported on S514-PCI/S508-ISA cards.
-
-	  Say Y and the PPP support will be included in the driver.
-
-config WANPIPE_MULTPPP
-	bool "WANPIPE Multi-Port PPP support"
-	depends on VENDOR_SANGOMA
-	help
-	  Connect a WANPIPE card to a leased line using Point-to-Point
-	  Protocol (PPP).
-
-	  Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming
-	  adapter. In this case each Sangoma adapter port can support an
-	  independent PPP connection. For example, a single Quad-Port PCI
-	  adapter can support up to four independent PPP links. The PPP
-	  option is supported on S514-PCI/S508-ISA cards.
-
-	  Say Y and the Multi-Port PPP support will be included in the driver.
-
 config CYCLADES_SYNC
 	tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)"
 	depends on WAN_ROUTER_DRIVERS && (PCI || ISA)
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index ce6c56b..823c6d5 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -5,14 +5,6 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-wanpipe-y			:= sdlamain.o sdla_ft1.o
-wanpipe-$(CONFIG_WANPIPE_X25)	+= sdla_x25.o
-wanpipe-$(CONFIG_WANPIPE_FR)	+= sdla_fr.o
-wanpipe-$(CONFIG_WANPIPE_CHDLC)	+= sdla_chdlc.o
-wanpipe-$(CONFIG_WANPIPE_PPP)	+= sdla_ppp.o
-wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o
-wanpipe-objs			:= $(wanpipe-y)
-
 cyclomx-y                       := cycx_main.o
 cyclomx-$(CONFIG_CYCLOMX_X25)	+= cycx_x25.o
 cyclomx-objs			:= $(cyclomx-y)  
@@ -43,11 +35,6 @@
 
 obj-$(CONFIG_DLCI)		+= dlci.o 
 obj-$(CONFIG_SDLA)		+= sdla.o
-ifeq ($(CONFIG_WANPIPE_MULTPPP),y)
-  obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o	
-else
-  obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o
-endif
 obj-$(CONFIG_CYCLADES_SYNC)	+= cycx_drv.o cyclomx.o
 obj-$(CONFIG_LAPBETHER)		+= lapbether.o
 obj-$(CONFIG_SBNI)		+= sbni.o
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
deleted file mode 100644
index 496d292..0000000
--- a/drivers/net/wan/sdla_chdlc.c
+++ /dev/null
@@ -1,4428 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c	WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: 	Nenad Corbic <ncorbic@sangoma.com>
-*		Gideon Hack  
-*
-* Copyright:	(c) 1995-2001 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Feb 28, 2001  Nenad Corbic	Updated if_tx_timeout() routine for 
-* 				2.4.X kernels.
-* Jan 25, 2001  Nenad Corbic	Added a TTY Sync serial driver over the
-* 				HDLC streaming protocol
-* 				Added a TTY Async serial driver over the
-* 				Async protocol.
-* Dec 15, 2000  Nenad Corbic    Updated for 2.4.X Kernel support
-* Nov 13, 2000  Nenad Corbic    Added true interface type encoding option.
-* 				Tcpdump doesn't support CHDLC inteface
-* 				types, to fix this "true type" option will set
-* 				the interface type to RAW IP mode.
-* Nov 07, 2000  Nenad Corbic	Added security features for UDP debugging:
-*                               Deny all and specify allowed requests.
-* Jun 20, 2000  Nenad Corbic	Fixed the API IP ERROR bug. Caused by the 
-*                               latest update.
-* May 09, 2000	Nenad Corbic	Option to bring down an interface
-*                               upon disconnect.
-* Mar 23, 2000  Nenad Corbic	Improved task queue, bh handling.
-* Mar 16, 2000	Nenad Corbic	Fixed the SLARP Dynamic IP addressing.
-* Mar 06, 2000  Nenad Corbic	Bug Fix: corrupted mbox recovery.
-* Feb 10, 2000  Gideon Hack     Added ASYNC support.
-* Feb 09, 2000  Nenad Corbic    Fixed two shutdown bugs in update() and
-*                               if_stats() functions.
-* Jan 24, 2000  Nenad Corbic    Fixed a startup wanpipe state racing,  
-*                               condition between if_open and isr. 
-* Jan 10, 2000  Nenad Corbic    Added new socket API support.
-* Dev 15, 1999  Nenad Corbic    Fixed up header files for 2.0.X kernels
-* Nov 20, 1999  Nenad Corbic 	Fixed zero length API bug.
-* Sep 30, 1999  Nenad Corbic    Fixed dynamic IP and route setup.
-* Sep 23, 1999  Nenad Corbic    Added SMP support, fixed tracing 
-* Sep 13, 1999  Nenad Corbic	Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.
-* Oct 30, 1998	Jaspreet Singh	Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998	Jaspreet Singh	Added Support for Dual Port CHDLC.
-* Aug 07, 1998	David Fong	Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/if_arp.h>	/* ARPHRD_* defines */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/in.h>		/* sockaddr_in */
-#include <linux/inet.h>	
-#include <linux/if.h>
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h>		/* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h>           	/* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h>    /* Socket Driver common area */
-#include <linux/if_wanpipe.h>		
-
-/* TTY Includes */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP   		0x01
-#define TMR_INT_ENABLED_UPDATE		0x02
-#define TMR_INT_ENABLED_CONFIG		0x10
-
-#define MAX_IP_ERRORS	10
-
-#define TTY_CHDLC_MAX_MTU	2000
-#define	CHDLC_DFLT_DATA_LEN	1500		/* default MTU */
-#define CHDLC_HDR_LEN		1
-
-#define CHDLC_API 0x01
-
-#define PORT(x)   (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF	10
-
-//#define PRINT_DEBUG
-#ifdef PRINT_DEBUG
-#define dbg_printk(format, a...) printk(format, ## a)
-#else
-#define dbg_printk(format, a...)
-#endif  
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following 
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
-	wanpipe_common_t common;
-	sdla_t		*card;
-	int 		TracingEnabled;		/* For enabling Tracing */
-	unsigned long 	curr_trace_addr;	/* Used for Tracing */
-	unsigned long 	start_trace_addr;
-	unsigned long 	end_trace_addr;
-	unsigned long 	base_addr_trace_buffer;
-	unsigned long 	end_addr_trace_buffer;
-	unsigned short 	number_trace_elements;
-	unsigned  	available_buffer_space;
-	unsigned long 	router_start_time;
-	unsigned char 	route_status;
-	unsigned char 	route_removed;
-	unsigned long 	tick_counter;		/* For 5s timeout counter */
-	unsigned long 	router_up_time;
-        u32             IP_address;		/* IP addressing */
-        u32             IP_netmask;
-	u32		ip_local;
-	u32		ip_remote;
-	u32 		ip_local_tmp;
-	u32		ip_remote_tmp;
-	u8		ip_error;
-	u8		config_chdlc;
-	u8 		config_chdlc_timeout;
-	unsigned char  mc;			/* Mulitcast support on/off */
-	unsigned short udp_pkt_lgth;		/* udp packet processing */
-	char udp_pkt_src;
-	char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-	unsigned short timer_int_enabled;
-	char update_comms_stats;		/* updating comms stats */
-
-	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
-	unsigned long  tq_working;
-	volatile int  bh_write;
-	volatile int  bh_read;
-	atomic_t  bh_buff_used;
-	
-	unsigned char interface_down;
-
-	/* Polling work queue entry. Each interface
-         * has its own work queue entry, which is used
-         * to defer events from the interrupt */
-	struct work_struct poll_work;
-	struct timer_list poll_delay_timer;
-
-	u8 gateway;
-	u8 true_if_encoding;
-	//FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE	0x00
-#define ADD_ROUTE	0x01
-#define ROUTE_ADDED	0x02
-#define REMOVE_ROUTE	0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
-   two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
-		     unsigned short type, void* daddr, void* saddr,
-		     unsigned len);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-static struct net_device_stats* if_stats(struct net_device* dev);
-  
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure 	(sdla_t* card, void* data);
-static int chdlc_comm_enable 	(sdla_t* card);
-static int chdlc_read_version 	(sdla_t* card, char* str);
-static int chdlc_set_intr_mode 	(sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-
-static int chdlc_disable_comm_shutdown (sdla_t *card);
-static void if_tx_timeout(struct net_device *dev);
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff( sdla_t* card);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
-        chdlc_private_area_t* chdlc_priv_area);
-static int configure_ip (sdla_t* card);
-static int unconfigure_ip (sdla_t* card);
-static void process_route(sdla_t *card);
-static void port_set_state (sdla_t *card, int);
-static int config_chdlc (sdla_t *card);
-static void disable_comm (sdla_t *card);
-
-static void trigger_chdlc_poll(struct net_device *dev);
-static void chdlc_poll(struct net_device *dev);
-static void chdlc_poll_delay (unsigned long dev_ptr);
-
-
-/* Miscellaneous asynchronous interface Functions */
-static int set_asy_config (sdla_t* card);
-static int asy_comm_enable (sdla_t* card);
-
-/* Interrupt handlers */
-static void wpc_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Bottom half handlers */
-static void chdlc_work(struct net_device *dev);
-static int chdlc_work_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-/* Miscellaneous functions */
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
-				struct sk_buff *skb);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-                                struct sk_buff *skb, struct net_device* dev,
-                                chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,  
-				chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-
-static int  Intr_test_counter;
-
-/* TTY Global Definitions */
-
-#define NR_PORTS 4
-#define WAN_TTY_MAJOR 226
-#define WAN_TTY_MINOR 0
-
-#define WAN_CARD(port) (tty_card_map[port])
-#define MIN_PORT 0
-#define MAX_PORT NR_PORTS-1 
-
-#define CRC_LENGTH 2
-
-static int wanpipe_tty_init(sdla_t *card);
-static void wanpipe_tty_receive(sdla_t *, unsigned, unsigned int);
-static void wanpipe_tty_trigger_poll(sdla_t *card);
-
-static struct tty_driver serial_driver;
-static int tty_init_cnt=0;
-
-static struct serial_state rs_table[NR_PORTS];
-
-static char tty_driver_mode=WANOPT_TTY_SYNC;
-
-static char *opt_decode[] = {"NONE","CRTSCTS","XONXOFF-RX",
-	  	             "CRTSCTS XONXOFF-RX","XONXOFF-TX",
-		             "CRTSCTS XONXOFF-TX","CRTSCTS XONXOFF"};
-static char *p_decode[] = {"NONE","ODD","EVEN"};
-
-static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL};
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup.  At this
- * point adapter is completely initialized and firmware is running.
- *  o read firmware version (to make sure it's alive)
- *  o configure adapter
- *  o initialize protocol-specific fields of the adapter data space.
- *
- * Return:	0	o.k.
- *		< 0	failure.
- */
-int wpc_init (sdla_t* card, wandev_conf_t* conf)
-{
-	unsigned char port_num;
-	int err;
-	unsigned long max_permitted_baud = 0;
-	SHARED_MEMORY_INFO_STRUCT *flags;
-
-	union
-		{
-		char str[80];
-		} u;
-	volatile CHDLC_MAILBOX_STRUCT* mb;
-	CHDLC_MAILBOX_STRUCT* mb1;
-	unsigned long timeout;
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_CHDLC) {
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-				  card->devname, conf->config_id);
-		return -EINVAL;
-	}
-
-	/* Find out which Port to use */
-	if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
-		if (card->next){
-
-			if (conf->comm_port != card->next->u.c.comm_port){
-				card->u.c.comm_port = conf->comm_port;
-			}else{
-				printk(KERN_INFO "%s: ERROR - %s port used!\n",
-        		        	card->wandev.name, PORT(conf->comm_port));
-				return -EINVAL;
-			}
-		}else{
-			card->u.c.comm_port = conf->comm_port;
-		}
-	}else{
-		printk(KERN_INFO "%s: ERROR - Invalid Port Selected!\n",
-                			card->wandev.name);
-		return -EINVAL;
-	}
-	
-
-	/* Initialize protocol-specific fields */
-	if(card->hw.type != SDLA_S514){
-
-		if (card->u.c.comm_port == WANOPT_PRI){	
-			card->mbox  = (void *) card->hw.dpmbase;
-		}else{
-			card->mbox  = (void *) card->hw.dpmbase + 
-				SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
-		}	
-	}else{ 
-		/* for a S514 adapter, set a pointer to the actual mailbox in the */
-		/* allocated virtual memory area */
-		if (card->u.c.comm_port == WANOPT_PRI){
-			card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
-		}else{
-			card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
-		}	
-	}
-
-	mb = mb1 = card->mbox;
-
-	if (!card->configured){
-
-		/* The board will place an 'I' in the return code to indicate that it is
-	   	ready to accept commands.  We expect this to be completed in less
-           	than 1 second. */
-
-		timeout = jiffies;
-		while (mb->return_code != 'I')	/* Wait 1s for board to initialize */
-			if ((jiffies - timeout) > 1*HZ) break;
-
-		if (mb->return_code != 'I') {
-			printk(KERN_INFO
-				"%s: Initialization not completed by adapter\n",
-				card->devname);
-			printk(KERN_INFO "Please contact Sangoma representative.\n");
-			return -EIO;
-		}
-	}
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-
-	if (chdlc_read_version(card, u.str))
-		return -EIO;
-
-	printk(KERN_INFO "%s: Running Cisco HDLC firmware v%s\n",
-		card->devname, u.str); 
-
-	card->isr			= &wpc_isr;
-	card->poll			= NULL;
-	card->exec			= NULL;
-	card->wandev.update		= &update;
- 	card->wandev.new_if		= &new_if;
-	card->wandev.del_if		= NULL;
-	card->wandev.udp_port   	= conf->udp_port;
-	card->disable_comm		= &disable_comm;
-	card->wandev.new_if_cnt = 0;
-
-	/* reset the number of times the 'update()' proc has been called */
-	card->u.c.update_call_count = 0;
-	
-	card->wandev.ttl = conf->ttl;
-	card->wandev.interface = conf->interface; 
-
-	if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
-	    card->hw.type != SDLA_S514){
-		printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
-			card->devname, PORT(card->u.c.comm_port));
-		return -EIO;
-	}
-
-	card->wandev.clocking = conf->clocking;
-
-	port_num = card->u.c.comm_port;
-
-	/* in API mode, we can configure for "receive only" buffering */
-	if(card->hw.type == SDLA_S514) {
-		card->u.c.receive_only = conf->receive_only;
-		if(conf->receive_only) {
-			printk(KERN_INFO
-				"%s: Configured for 'receive only' mode\n",
-                                card->devname);
-		}
-	}
-
-	/* Setup Port Bps */
-
-	if(card->wandev.clocking) {
-		if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-			/* For Primary Port 0 */
-               		max_permitted_baud =
-				(card->hw.type == SDLA_S514) ?
-				PRI_MAX_BAUD_RATE_S514 : 
-				PRI_MAX_BAUD_RATE_S508;
-
-		}else if(port_num == WANOPT_SEC) {
-			/* For Secondary Port 1 */
-                        max_permitted_baud =
-                               (card->hw.type == SDLA_S514) ?
-                                SEC_MAX_BAUD_RATE_S514 :
-                                SEC_MAX_BAUD_RATE_S508;
-                        }
-  
-			if(conf->bps > max_permitted_baud) {
-				conf->bps = max_permitted_baud;
-				printk(KERN_INFO "%s: Baud too high!\n",
-					card->wandev.name);
- 				printk(KERN_INFO "%s: Baud rate set to %lu bps\n", 
-					card->wandev.name, max_permitted_baud);
-			}
-			card->wandev.bps = conf->bps;
-	}else{
-        	card->wandev.bps = 0;
-  	}
-
-	/* Setup the Port MTU */
-	if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
-		/* For Primary Port 0 */
-		card->wandev.mtu =
-			(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
-			min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
-			CHDLC_DFLT_DATA_LEN;
-	} else if(port_num == WANOPT_SEC) { 
-		/* For Secondary Port 1 */
-		card->wandev.mtu =
-			(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
-			min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
-			CHDLC_DFLT_DATA_LEN;
-	}
-
-	/* Set up the interrupt status area */
-	/* Read the CHDLC Configuration and obtain: 
-	 *	Ptr to shared memory infor struct
-         * Use this pointer to calculate the value of card->u.c.flags !
- 	 */
-	mb1->buffer_length = 0;
-	mb1->command = READ_CHDLC_CONFIGURATION;
-	err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
-	if(err != COMMAND_OK) {
-                if(card->hw.type != SDLA_S514)
-                	enable_irq(card->hw.irq);
-
-		chdlc_error(card, err, mb1);
-		return -EIO;
-	}
-
-	if(card->hw.type == SDLA_S514){
-               	card->u.c.flags = (void *)(card->hw.dpmbase +
-               		(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct));
-        }else{
-                card->u.c.flags = (void *)(card->hw.dpmbase +
-                        (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
-	}
-
-	flags = card->u.c.flags;
-	
-	/* This is for the ports link state */
-	card->wandev.state = WAN_DUALPORT;
-	card->u.c.state = WAN_DISCONNECTED;
-
-
-	if (!card->wandev.piggyback){	
-		int err;
-
-		/* Perform interrupt testing */
-		err = intr_test(card);
-
-		if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { 
-			printk(KERN_INFO "%s: Interrupt test failed (%i)\n",
-					card->devname, Intr_test_counter);
-			printk(KERN_INFO "%s: Please choose another interrupt\n",
-					card->devname);
-			return -EIO;
-		}
-		
-		printk(KERN_INFO "%s: Interrupt test passed (%i)\n", 
-				card->devname, Intr_test_counter);
-		card->configured = 1;
-	}
-
-	if ((card->tty_opt=conf->tty) == WANOPT_YES){
-		int err;
-		card->tty_minor = conf->tty_minor;
-
-		/* On ASYNC connections internal clocking 
-		 * is mandatory */
-		if ((card->u.c.async_mode = conf->tty_mode)){
-			card->wandev.clocking = 1;
-		}
-		err=wanpipe_tty_init(card);
-		if (err){
-			return err;
-		}
-	}else{
-	
-
-		if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
-			printk (KERN_INFO "%s: "
-				"Failed to set interrupt triggers!\n",
-				card->devname);
-			return -EIO;	
-        	}
-	
-		/* Mask the Timer interrupt */
-		flags->interrupt_info_struct.interrupt_permission &= 
-			~APP_INT_ON_TIMER;
-	}
-
-	/* If we are using CHDLC in backup mode, this flag will
-	 * indicate not to look for IP addresses in config_chdlc()*/
-	card->u.c.backup = conf->backup;
-	
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3 
- * different locations:
- * 	1) The 'if_stats' recorded for the device.
- * 	2) Communication error statistics on the adapter.
- *      3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we 
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
-	sdla_t* card = wandev->private;
- 	struct net_device* dev;
-        volatile chdlc_private_area_t* chdlc_priv_area;
-        SHARED_MEMORY_INFO_STRUCT *flags;
-	unsigned long timeout;
-
-	/* sanity checks */
-	if((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-	
-	if(wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-
-	/* more sanity checks */
-        if(!card->u.c.flags)
-                return -ENODEV;
-
-	if(test_bit(PERI_CRIT, (void*)&card->wandev.critical))
-                return -EAGAIN;
-
-	if((dev=card->wandev.dev) == NULL)
-		return -ENODEV;
-
-	if((chdlc_priv_area=dev->priv) == NULL)
-		return -ENODEV;
-
-      	flags = card->u.c.flags;
-       	if(chdlc_priv_area->update_comms_stats){
-		return -EAGAIN;
-	}
-			
-	/* we will need 2 timer interrupts to complete the */
-	/* reading of the statistics */
-	chdlc_priv_area->update_comms_stats = 2;
-       	flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
-	chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-  
-	/* wait a maximum of 1 second for the statistics to be updated */ 
-        timeout = jiffies;
-        for(;;) {
-		if(chdlc_priv_area->update_comms_stats == 0)
-			break;
-                if ((jiffies - timeout) > (1 * HZ)){
-    			chdlc_priv_area->update_comms_stats = 0;
- 			chdlc_priv_area->timer_int_enabled &=
-				~TMR_INT_ENABLED_UPDATE; 
- 			return -EAGAIN;
-		}
-        }
-
-	return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return:	0	o.k.
- *		< 0	failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf)
-{
-	sdla_t* card = wandev->private;
-	chdlc_private_area_t* chdlc_priv_area;
-
-
-	printk(KERN_INFO "%s: Configuring Interface: %s\n",
-			card->devname, conf->name);
- 
-	if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-		printk(KERN_INFO "%s: Invalid interface name!\n",
-			card->devname);
-		return -EINVAL;
-	}
-		
-	/* allocate and initialize private data */
-	chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-	
-	if(chdlc_priv_area == NULL) 
-		return -ENOMEM;
-
-	memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
-	chdlc_priv_area->card = card; 
-	chdlc_priv_area->common.sk = NULL;
-	chdlc_priv_area->common.func = NULL;	
-
-	/* initialize data */
-	strcpy(card->u.c.if_name, conf->name);
-
-	if(card->wandev.new_if_cnt > 0) {
-                kfree(chdlc_priv_area);
-		return -EEXIST;
-	}
-
-	card->wandev.new_if_cnt++;
-
-	chdlc_priv_area->TracingEnabled = 0;
-	chdlc_priv_area->route_status = NO_ROUTE;
-	chdlc_priv_area->route_removed = 0;
-
-	card->u.c.async_mode = conf->async_mode;
-	
-	/* setup for asynchronous mode */
-	if(conf->async_mode) {
-		printk(KERN_INFO "%s: Configuring for asynchronous mode\n",
-			wandev->name);
-
-		if(card->u.c.comm_port == WANOPT_PRI) {
-			printk(KERN_INFO
-				"%s:Asynchronous mode on secondary port only\n",
-					wandev->name);
-			kfree(chdlc_priv_area);
-			return -EINVAL;
-		}
-
-	       	if(strcmp(conf->usedby, "WANPIPE") == 0) {
-			printk(KERN_INFO
-                                "%s: Running in WANIPE Async Mode\n",                                        			wandev->name);
-			card->u.c.usedby = WANPIPE;
-		}else{
-			card->u.c.usedby = API;
-		}
-
-		if(!card->wandev.clocking) {
-			printk(KERN_INFO
-				"%s: Asynch. clocking must be 'Internal'\n",
-				wandev->name);
-			kfree(chdlc_priv_area);
-			return -EINVAL;
-		}
-
-		if((card->wandev.bps < MIN_ASY_BAUD_RATE) ||
-			(card->wandev.bps > MAX_ASY_BAUD_RATE)) {
-			printk(KERN_INFO "%s: Selected baud rate is invalid.\n",
-				wandev->name);
-			printk(KERN_INFO "Must be between %u and %u bps.\n",
-				MIN_ASY_BAUD_RATE, MAX_ASY_BAUD_RATE);
-			kfree(chdlc_priv_area);
-			return -EINVAL;
-		}
-
-		card->u.c.api_options = 0;
-                if (conf->asy_data_trans == WANOPT_YES) {
-                        card->u.c.api_options |= ASY_RX_DATA_TRANSPARENT;
-                }
-		
-		card->u.c.protocol_options = 0;
-		if (conf->rts_hs_for_receive == WANOPT_YES) {
-			card->u.c.protocol_options |= ASY_RTS_HS_FOR_RX;
-	        }
-                if (conf->xon_xoff_hs_for_receive == WANOPT_YES) {
-                        card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_RX;
-                }
-                if (conf->xon_xoff_hs_for_transmit == WANOPT_YES) {
-                        card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_TX;
-                }
-                if (conf->dcd_hs_for_transmit == WANOPT_YES) {
-                        card->u.c.protocol_options |= ASY_DCD_HS_FOR_TX;
-                }
-                if (conf->cts_hs_for_transmit == WANOPT_YES) {
-                        card->u.c.protocol_options |= ASY_CTS_HS_FOR_TX;
-                }
-
-		card->u.c.tx_bits_per_char = conf->tx_bits_per_char;
-                card->u.c.rx_bits_per_char = conf->rx_bits_per_char;
-                card->u.c.stop_bits = conf->stop_bits;
-		card->u.c.parity = conf->parity;
-		card->u.c.break_timer = conf->break_timer;
-		card->u.c.inter_char_timer = conf->inter_char_timer;
-		card->u.c.rx_complete_length = conf->rx_complete_length;
-		card->u.c.xon_char = conf->xon_char;
-
-	} else {	/* setup for synchronous mode */
-
-		card->u.c.protocol_options = 0;
-		if (conf->ignore_dcd == WANOPT_YES){
-			card->u.c.protocol_options |= IGNORE_DCD_FOR_LINK_STAT;
-		}
-		if (conf->ignore_cts == WANOPT_YES){
-			card->u.c.protocol_options |= IGNORE_CTS_FOR_LINK_STAT;
-		}
-
-		if (conf->ignore_keepalive == WANOPT_YES) {
-			card->u.c.protocol_options |=
-				IGNORE_KPALV_FOR_LINK_STAT;
-			card->u.c.kpalv_tx  = MIN_Tx_KPALV_TIMER; 
-			card->u.c.kpalv_rx  = MIN_Rx_KPALV_TIMER; 
-			card->u.c.kpalv_err = MIN_KPALV_ERR_TOL; 
-
-		} else {   /* Do not ignore keepalives */
-			card->u.c.kpalv_tx =
-				((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER)
-				>= 0) ?
-	   			min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) :
-				DEFAULT_Tx_KPALV_TIMER;
-
-			card->u.c.kpalv_rx =
-		   		((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER)
-				>= 0) ?
-	   			min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) :
-				DEFAULT_Rx_KPALV_TIMER;
-
-			card->u.c.kpalv_err =
-		   		((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL)
-				>= 0) ?
-	   			min_t(unsigned int, conf->keepalive_err_margin,
-				MAX_KPALV_ERR_TOL) : 
-	   			DEFAULT_KPALV_ERR_TOL;
-		}
-
-		/* Setup slarp timer to control delay between slarps */
-		card->u.c.slarp_timer = 
-			((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ?
-			min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) :
-			DEFAULT_SLARP_REQ_TIMER;
-
-		if (conf->hdlc_streaming == WANOPT_YES) {
-			printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n",
-				wandev->name);
-			card->u.c.protocol_options = HDLC_STREAMING_MODE;
-		}
-
-		if ((chdlc_priv_area->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
-			printk(KERN_INFO 
-				"%s: Enabling, true interface type encoding.\n",
-				card->devname);
-		}
-		
-        	/* Setup wanpipe as a router (WANPIPE) or as an API */
-		if( strcmp(conf->usedby, "WANPIPE") == 0) {
-
-			printk(KERN_INFO "%s: Running in WANPIPE mode!\n",
-				wandev->name);
-			card->u.c.usedby = WANPIPE;
-
-			/* Option to bring down the interface when 
-        		 * the link goes down */
-			if (conf->if_down){
-				set_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down);
-				printk(KERN_INFO 
-				 "%s: Dynamic interface configuration enabled\n",
-				   card->devname);
-			} 
-
-		} else if( strcmp(conf->usedby, "API") == 0) {
-			card->u.c.usedby = API;
-			printk(KERN_INFO "%s: Running in API mode !\n",
-				wandev->name);
-		}
-	}
-
-	/* Tells us that if this interface is a
-         * gateway or not */
-	if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){
-		printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
-			card->devname,card->u.c.if_name);
-	}
-
-	/* Get Multicast Information */
-	chdlc_priv_area->mc = conf->mc;
-
-	/* prepare network device data space for registration */
-	strcpy(dev->name,card->u.c.if_name);
-
-	dev->init = &if_init;
-	dev->priv = chdlc_priv_area;
-
-	/* Initialize the polling work routine */
-	INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev);
-
-	/* Initialize the polling delay timer */
-	init_timer(&chdlc_priv_area->poll_delay_timer);
-	chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev;
-	chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay;
-	
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration.  Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-	struct wan_device* wandev = &card->wandev;
-
-	/* Initialize device driver entry points */
-	dev->open		= &if_open;
-	dev->stop		= &if_close;
-	dev->hard_header	= &if_header;
-	dev->rebuild_header	= &if_rebuild_hdr;
-	dev->hard_start_xmit	= &if_send;
-	dev->get_stats		= &if_stats;
-	dev->tx_timeout		= &if_tx_timeout;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-	
-	/* Initialize media-specific parameters */
-	dev->flags		|= IFF_POINTOPOINT;
-	dev->flags		|= IFF_NOARP;
-
-	/* Enable Mulitcasting if user selected */
-	if (chdlc_priv_area->mc == WANOPT_YES){
-		dev->flags 	|= IFF_MULTICAST;
-	}
-	
-	if (chdlc_priv_area->true_if_encoding){
-		dev->type	= ARPHRD_HDLC; /* This breaks the tcpdump */
-	}else{
-		dev->type	= ARPHRD_PPP;
-	}
-	
-	dev->mtu		= card->wandev.mtu;
-	/* for API usage, add the API header size to the requested MTU size */
-	if(card->u.c.usedby == API) {
-		dev->mtu += sizeof(api_tx_hdr_t);
-	}
- 
-	dev->hard_header_len	= CHDLC_HDR_LEN;
-
-	/* Initialize hardware parameters */
-	dev->irq	= wandev->irq;
-	dev->dma	= wandev->dma;
-	dev->base_addr	= wandev->ioport;
-	dev->mem_start	= wandev->maddr;
-	dev->mem_end	= wandev->maddr + wandev->msize - 1;
-
-	/* Set transmit buffer queue length 
-	 * If too low packets will not be retransmitted 
-         * by stack.
-	 */
-        dev->tx_queue_len = 100;
-	SET_MODULE_OWNER(dev);
-   
-	return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-	struct timeval tv;
-	int err = 0;
-
-	/* Only one open per interface is allowed */
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	/* Initialize the work queue entry */
-	chdlc_priv_area->tq_working=0;
-
-	INIT_WORK(&chdlc_priv_area->common.wanpipe_work,
-			(void *)(void *)chdlc_work, dev);
-
-	/* Allocate and initialize BH circular buffer */
-	/* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
-	chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
-	memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
-	atomic_set(&chdlc_priv_area->bh_buff_used, 0);
- 
-	do_gettimeofday(&tv);
-	chdlc_priv_area->router_start_time = tv.tv_sec;
-
-	netif_start_queue(dev);
-
-	wanpipe_open(card);
-
-	/* TTY is configured during wanpipe_set_termios
-	 * call, not here */
-	if (card->tty_opt)
-		return err;
-	
-	set_bit(0,&chdlc_priv_area->config_chdlc);
-	chdlc_priv_area->config_chdlc_timeout=jiffies;
-
-	/* Start the CHDLC configuration after 1sec delay.
-	 * This will give the interface initilization time
-	 * to finish its configuration */
-	mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ);
-	return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-
-	if (chdlc_priv_area->bh_head){
-		int i;
-		struct sk_buff *skb;
-	
-		for (i=0; i<(MAX_BH_BUFF+1); i++){
-			skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb;
-			if (skb != NULL){
-                		dev_kfree_skb_any(skb);
-			}
-		}
-		kfree(chdlc_priv_area->bh_head);
-		chdlc_priv_area->bh_head=NULL;
-	}
-
-	netif_stop_queue(dev);
-	wanpipe_close(card);
-	del_timer(&chdlc_priv_area->poll_delay_timer);
-	return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	
-	if (card->u.c.comm_enabled){
-		chdlc_disable_comm_shutdown (card);
-	}else{
-		flags->interrupt_info_struct.interrupt_permission = 0;	
-	}
-
-	if (!tty_init_cnt)
-		return;
-
-	if (card->tty_opt){
-		struct serial_state * state;
-		if (!(--tty_init_cnt)){
-			int e1;
-			serial_driver.refcount=0;
-			
-			if ((e1 = tty_unregister_driver(&serial_driver)))
-				printk("SERIAL: failed to unregister serial driver (%d)\n",
-				       e1);
-			printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n",
-					card->devname,WAN_TTY_MAJOR);
-		}
-		card->tty=NULL;
-		tty_card_map[card->tty_minor]=NULL;
-		state = &rs_table[card->tty_minor];
-		memset(state, 0, sizeof(*state));
-	}
-	return;
-}
-
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it.  If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return:	media header length.
- */
-static int if_header(struct sk_buff* skb, struct net_device* dev,
-		     unsigned short type, void* daddr, void* saddr,
-		     unsigned len)
-{
-	skb->protocol = htons(type);
-
-	return CHDLC_HDR_LEN;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
-    	chdlc_private_area_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	
-	/* If our device stays busy for at least 5 seconds then we will
-	 * kick start the device by making dev->tbusy = 0.  We expect
-	 * that our device never stays busy more than 5 seconds. So this                 
-	 * is only used as a last resort.
-	 */
-
-	++card->wandev.stats.collisions;
-
-	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
-	netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Re-build media header.
- *
- * Return:	1	physical address resolved.
- *		0	physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
-	return 1;
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- *   transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return:	0	complete (socket buffer must be freed)
- *		non-0	packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- *    bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- *    protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
-	chdlc_private_area_t *chdlc_priv_area = dev->priv;
-	sdla_t *card = chdlc_priv_area->card;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
-	int udp_type = 0;
-	unsigned long smp_flags;
-	int err=0;
-
-	netif_stop_queue(dev);
-	
-	if (skb == NULL){
-		/* If we get here, some higher layer thinks we've missed an
-		 * tx-done interrupt.
-		 */
-		printk(KERN_INFO "%s: interface %s got kicked!\n",
-			card->devname, dev->name);
-
-		netif_wake_queue(dev);
-		return 0;
-	}
-
-   	if (ntohs(skb->protocol) != htons(PVC_PROT)){
-
-		/* check the udp packet type */
-		
-		udp_type = udp_pkt_type(skb, card);
-
-		if (udp_type == UDP_CPIPE_TYPE){
-                        if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
-                                chdlc_priv_area)){
-	                	chdlc_int->interrupt_permission |=
-					APP_INT_ON_TIMER;
-			}
-			netif_start_queue(dev);
-			return 0;
-		}
-
-		/* check to see if the source IP address is a broadcast or */
-		/* multicast IP address */
-                if(chk_bcast_mcast_addr(card, dev, skb)){
-			++card->wandev.stats.tx_dropped;
-			dev_kfree_skb_any(skb);
-			netif_start_queue(dev);
-			return 0;
-		}
-        }
-
-	/* Lock the 508 Card: SMP is supported */
-      	if(card->hw.type != SDLA_S514){
-		s508_lock(card,&smp_flags);
-	} 
-
-    	if(test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-	
-		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
-					card->wandev.name,card->wandev.critical);
-                ++card->wandev.stats.tx_dropped;
-		netif_start_queue(dev);
-		goto if_send_exit_crit;
-	}
-
-	if(card->u.c.state != WAN_CONNECTED){
-       		++card->wandev.stats.tx_dropped;
-		netif_start_queue(dev);
-		
-	}else if(!skb->protocol){
-        	++card->wandev.stats.tx_errors;
-		netif_start_queue(dev);
-		
-	}else {
-		void* data = skb->data;
-		unsigned len = skb->len;
-		unsigned char attr;
-
-		/* If it's an API packet pull off the API
-		 * header. Also check that the packet size
-		 * is larger than the API header
-	         */
-		if (card->u.c.usedby == API){
-			api_tx_hdr_t* api_tx_hdr;
-
-			/* discard the frame if we are configured for */
-			/* 'receive only' mode or if there is no data */
-			if (card->u.c.receive_only ||
-				(len <= sizeof(api_tx_hdr_t))) {
-				
-				++card->wandev.stats.tx_dropped;
-				netif_start_queue(dev);
-				goto if_send_exit_crit;
-			}
-				
-			api_tx_hdr = (api_tx_hdr_t *)data;
-			attr = api_tx_hdr->attr;
-			data += sizeof(api_tx_hdr_t);
-			len -= sizeof(api_tx_hdr_t);
-		}
-
-		if(chdlc_send(card, data, len)) {
-			netif_stop_queue(dev);
-		}else{
-			++card->wandev.stats.tx_packets;
-                        card->wandev.stats.tx_bytes += len;
-			
-			netif_start_queue(dev);
-			
-		 	dev->trans_start = jiffies;
-		}	
-	}
-
-if_send_exit_crit:
-	
-	if (!(err=netif_queue_stopped(dev))) {
-		dev_kfree_skb_any(skb);
-	}else{
-		chdlc_priv_area->tick_counter = jiffies;
-		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
-	}
-
-	clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
-	if(card->hw.type != SDLA_S514){
-		s508_unlock(card,&smp_flags);
-	}
-	
-	return err;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
-				struct sk_buff *skb)
-{
-	u32 src_ip_addr;
-        u32 broadcast_ip_addr = 0;
-        struct in_device *in_dev;
-
-        /* read the IP source address from the outgoing packet */
-        src_ip_addr = *(u32 *)(skb->data + 12);
-
-	/* read the IP broadcast address for the device */
-        in_dev = dev->ip_ptr;
-        if(in_dev != NULL) {
-                struct in_ifaddr *ifa= in_dev->ifa_list;
-                if(ifa != NULL)
-                        broadcast_ip_addr = ifa->ifa_broadcast;
-                else
-                        return 0;
-        }
- 
-        /* check if the IP Source Address is a Broadcast address */
-        if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
-                printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
-				card->devname);
-                return 1;
-        } 
-
-        /* check if the IP Source Address is a Multicast address */
-        if((ntohl(src_ip_addr) >= 0xE0000001) &&
-		(ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
-                printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
-				card->devname);
-                return 1;
-        }
-
-        return 0;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
-	unsigned short len, udp_length, temp, ip_length;
-	unsigned long ip_temp;
-	int even_bound = 0;
-  	chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-	 
-	/* Set length of packet */
-	len = sizeof(ip_pkt_t)+ 
-	      sizeof(udp_pkt_t)+
-	      sizeof(wp_mgmt_t)+
-	      sizeof(cblock_t)+
-	      sizeof(trace_info_t)+ 
-	      mbox_len;
-
-	/* fill in UDP reply */
-	c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-   
-	/* fill in UDP length */
-	udp_length = sizeof(udp_pkt_t)+ 
-		     sizeof(wp_mgmt_t)+
-		     sizeof(cblock_t)+
-	             sizeof(trace_info_t)+
-		     mbox_len; 
-
- 	/* put it on an even boundary */
-	if ( udp_length & 0x0001 ) {
-		udp_length += 1;
-		len += 1;
-		even_bound = 1;
-	}  
-
-	temp = (udp_length<<8)|(udp_length>>8);
-	c_udp_pkt->udp_pkt.udp_length = temp;
-		 
-	/* swap UDP ports */
-	temp = c_udp_pkt->udp_pkt.udp_src_port;
-	c_udp_pkt->udp_pkt.udp_src_port = 
-			c_udp_pkt->udp_pkt.udp_dst_port; 
-	c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-	/* add UDP pseudo header */
-	temp = 0x1100;
-	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;	
-	temp = (udp_length<<8)|(udp_length>>8);
-	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-		 
-	/* calculate UDP checksum */
-	c_udp_pkt->udp_pkt.udp_checksum = 0;
-	c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
-	/* fill in IP length */
-	ip_length = len;
-	temp = (ip_length<<8)|(ip_length>>8);
-	c_udp_pkt->ip_pkt.total_length = temp;
-  
-	/* swap IP addresses */
-	ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
-	c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
-	c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-	/* fill in IP checksum */
-	c_udp_pkt->ip_pkt.hdr_checksum = 0;
-	c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
-	return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
-	unsigned short temp; 
-	unsigned long sum=0;
-	int i;
-
-	for( i = 0; i <len; i+=2 ) {
-		memcpy(&temp,&data[i],2);
-		sum += (unsigned long)temp;
-	}
-
-	while (sum >> 16 ) {
-		sum = (sum & 0xffffUL) + (sum >> 16);
-	}
-
-	temp = (unsigned short)sum;
-	temp = ~temp;
-
-	if( temp == 0 ) 
-		temp = 0xffff;
-
-	return temp;	
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
-	sdla_t *my_card;
-	chdlc_private_area_t* chdlc_priv_area;
-
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-	my_card = chdlc_priv_area->card;
-	return &my_card->wandev.stats; 
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- *	Put code version as ASCII string in str. 
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int len;
-	char err;
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_CODE_VERSION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	if(err != COMMAND_OK) {
-		chdlc_error(card,err,mb);
-	}
-	else if (str) {  /* is not null */
-		len = mb->buffer_length;
-		memcpy(str, mb->data, len);
-		str[len] = '\0';
-	}
-	return (err);
-}
-
-/*-----------------------------------------------------------------------------
- *  Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
-	int err;
-	CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
-	int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-	
-	mailbox->buffer_length = data_length;  
-	memcpy(mailbox->data, data, data_length);
-	mailbox->command = SET_CHDLC_CONFIGURATION;
-	err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-	
-	if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-                           
-	return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	CHDLC_INT_TRIGGERS_STRUCT* int_data =
-		 (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
-	int err;
-
-	int_data->CHDLC_interrupt_triggers 	= mode;
-	int_data->IRQ				= card->hw.irq;
-	int_data->interrupt_timer               = 1;
-   
-	mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
-	mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK)
-		chdlc_error (card, err, mb);
-	return err;
-}
-
-
-/*===========================================================
- * chdlc_disable_comm_shutdown
- *
- * Shutdown() disables the communications. We must
- * have a sparate functions, because we must not
- * call chdlc_error() hander since the private
- * area has already been replaced */
-
-static int chdlc_disable_comm_shutdown (sdla_t *card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	CHDLC_INT_TRIGGERS_STRUCT* int_data =
-		 (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
-	int err;
-
-	/* Disable Interrutps */
-	int_data->CHDLC_interrupt_triggers 	= 0;
-	int_data->IRQ				= card->hw.irq;
-	int_data->interrupt_timer               = 1;
-   
-	mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
-	mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	/* Disable Communications */
-
-	if (card->u.c.async_mode) {
-		mb->command = DISABLE_ASY_COMMUNICATIONS;
-	}else{
-		mb->command = DISABLE_CHDLC_COMMUNICATIONS;
-	}
-	
-	mb->buffer_length = 0;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	
-	card->u.c.comm_enabled = 0;
-	
-	return 0;
-}
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
-	int err;
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-	mb->buffer_length = 0;
-	mb->command = ENABLE_CHDLC_COMMUNICATIONS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK)
-		chdlc_error(card, err, mb);
-	else
-		card->u.c.comm_enabled = 1;
-	
-	return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
-        int err;
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-        mb->buffer_length = 0;
-        mb->command = READ_COMMS_ERROR_STATS;
-        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-        if (err != COMMAND_OK)
-                chdlc_error(card,err,mb);
-        return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
-        int err;
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-        mb->buffer_length = 0;
-        mb->command = READ_CHDLC_OPERATIONAL_STATS;
-        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-        if (err != COMMAND_OK)
-                chdlc_error(card,err,mb);
-        return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
-	chdlc_private_area_t* chdlc_priv_area)
-{
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-  	COMMS_ERROR_STATS_STRUCT* err_stats;
-        CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
-	/* on the first timer interrupt, read the comms error statistics */
-	if(chdlc_priv_area->update_comms_stats == 2) {
-		if(chdlc_read_comm_err_stats(card))
-			return 1;
-		err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
-		card->wandev.stats.rx_over_errors = 
-				err_stats->Rx_overrun_err_count;
-		card->wandev.stats.rx_crc_errors = 
-				err_stats->CRC_err_count;
-		card->wandev.stats.rx_frame_errors = 
-				err_stats->Rx_abort_count;
-		card->wandev.stats.rx_fifo_errors = 
-				err_stats->Rx_dis_pri_bfrs_full_count; 
-		card->wandev.stats.rx_missed_errors =
-				card->wandev.stats.rx_fifo_errors;
-		card->wandev.stats.tx_aborted_errors =
-				err_stats->sec_Tx_abort_count;
-	}
-
-        /* on the second timer interrupt, read the operational statistics */
-	else {
-        	if(chdlc_read_op_stats(card))
-                	return 1;
-		op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
-		card->wandev.stats.rx_length_errors =
-			(op_stats->Rx_Data_discard_short_count +
-			op_stats->Rx_Data_discard_long_count);
-	}
-
-	return 0;
-}
-
-/*============================================================================
- * Send packet.
- *	Return:	0 - o.k.
- *		1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
-	CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
-	if (txbuf->opp_flag)
-		return 1;
-	
-	sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
-	txbuf->frame_length = len;
-	txbuf->opp_flag = 1;		/* start transmission */
-	
-	/* Update transmit buffer control fields */
-	card->u.c.txbuf = ++txbuf;
-	
-	if ((void*)txbuf > card->u.c.txbuf_last)
-		card->u.c.txbuf = card->u.c.txbuf_base;
-	
-	return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- *	This routine is called whenever firmware command returns non-zero
- *	return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
-	unsigned cmd = mb->command;
-
-	switch (err) {
-
-	case CMD_TIMEOUT:
-		printk(KERN_INFO "%s: command 0x%02X timed out!\n",
-			card->devname, cmd);
-		break;
-
-	case S514_BOTH_PORTS_SAME_CLK_MODE:
-		if(cmd == SET_CHDLC_CONFIGURATION) {
-			printk(KERN_INFO
-			 "%s: Configure both ports for the same clock source\n",
-				card->devname);
-			break;
-		}
-
-	default:
-		printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
-			card->devname, cmd, err);
-	}
-
-	return 0;
-}
-
-
-/********** Bottom Half Handlers ********************************************/
-
-/* NOTE: There is no API, BH support for Kernels lower than 2.2.X.
- *       DO NOT INSERT ANY CODE HERE, NOTICE THE 
- *       PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE
- *       DOING */
-
-static void chdlc_work(struct net_device * dev)
-{
-	chdlc_private_area_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	struct sk_buff *skb;
-
-	if (atomic_read(&chan->bh_buff_used) == 0){
-		clear_bit(0, &chan->tq_working);
-		return;
-	}
-
-	while (atomic_read(&chan->bh_buff_used)){
-
-		skb  = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
-		if (skb != NULL){
-
-			if (chan->common.sk == NULL || chan->common.func == NULL){
-				++card->wandev.stats.rx_dropped;
-				dev_kfree_skb_any(skb);
-				chdlc_work_cleanup(dev);
-				continue;
-			}
-
-			if (chan->common.func(skb,dev,chan->common.sk) != 0){
-				/* Sock full cannot send, queue us for another
-                                 * try */
-				atomic_set(&chan->common.receive_block,1);
-				return;
-			}else{
-				chdlc_work_cleanup(dev);
-			}
-		}else{
-			chdlc_work_cleanup(dev);
-		}
-	}	
-	clear_bit(0, &chan->tq_working);
-
-	return;
-}
-
-static int chdlc_work_cleanup(struct net_device *dev)
-{
-	chdlc_private_area_t* chan = dev->priv;
-
-	((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
-	if (chan->bh_read == MAX_BH_BUFF){
-		chan->bh_read=0;
-	}else{
-		++chan->bh_read;	
-	}
-
-	atomic_dec(&chan->bh_buff_used);
-	return 0;
-}
-
-
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
-	/* Check for full */
-	chdlc_private_area_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-
-	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
-		++card->wandev.stats.rx_dropped;
-		dev_kfree_skb_any(skb);
-		return 1; 
-	}
-
-	((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
-	if (chan->bh_write == MAX_BH_BUFF){
-		chan->bh_write=0;
-	}else{
-		++chan->bh_write;
-	}
-
-	atomic_inc(&chan->bh_buff_used);
-
-	return 0;
-}
-
-/* END OF API BH Support */
-
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-static void wpc_isr (sdla_t* card)
-{
-	struct net_device* dev;
-	SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-	int i;
-	sdla_t *my_card;
-
-
-	/* Check for which port the interrupt has been generated
-	 * Since Secondary Port is piggybacking on the Primary
-         * the check must be done here. 
-	 */
-
-	flags = card->u.c.flags;
-	if (!flags->interrupt_info_struct.interrupt_type){
-		/* Check for a second port (piggybacking) */
-		if ((my_card = card->next)){
-			flags = my_card->u.c.flags;
-			if (flags->interrupt_info_struct.interrupt_type){
-				card = my_card;
-				card->isr(card);
-				return;
-			}
-		}
-	}
-
-	flags = card->u.c.flags;
-	card->in_isr = 1;
-	dev = card->wandev.dev;
-	
-	/* If we get an interrupt with no network device, stop the interrupts
-	 * and issue an error */
-	if (!card->tty_opt && !dev && 
-	    flags->interrupt_info_struct.interrupt_type != 
-	    	COMMAND_COMPLETE_APP_INT_PEND){
-
-		goto isr_done;
-	}
-	
-	/* if critical due to peripheral operations
-	 * ie. update() or getstats() then reset the interrupt and
-	 * wait for the board to retrigger.
-	 */
-	if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
-		printk(KERN_INFO "ISR CRIT TO PERI\n");
-		goto isr_done;
-	}
-
-	/* On a 508 Card, if critical due to if_send 
-         * Major Error !!! */
-	if(card->hw.type != SDLA_S514) {
-		if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-			printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
-				card->devname, card->wandev.critical);
-			card->in_isr = 0;
-			flags->interrupt_info_struct.interrupt_type = 0;
-			return;
-		}
-	}
-
-	switch(flags->interrupt_info_struct.interrupt_type) {
-
-	case RX_APP_INT_PEND:	/* 0x01: receive interrupt */
-		rx_intr(card);
-		break;
-
-	case TX_APP_INT_PEND:	/* 0x02: transmit interrupt */
-		flags->interrupt_info_struct.interrupt_permission &=
-			 ~APP_INT_ON_TX_FRAME;
-
-		if (card->tty_opt){
-			wanpipe_tty_trigger_poll(card);
-			break;
-		}
-
-		if (dev && netif_queue_stopped(dev)){
-			if (card->u.c.usedby == API){
-				netif_start_queue(dev);
-				wakeup_sk_bh(dev);
-			}else{
-				netif_wake_queue(dev);
-			}
-		}
-		break;
-
-	case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
-		++ Intr_test_counter;
-		break;
-
-	case CHDLC_EXCEP_COND_APP_INT_PEND:	/* 0x20 */
-		process_chdlc_exception(card);
-		break;
-
-	case GLOBAL_EXCEP_COND_APP_INT_PEND:
-		process_global_exception(card);
-		break;
-
-	case TIMER_APP_INT_PEND:
-		timer_intr(card);
-		break;
-
-	default:
-		printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", 
-			card->devname,
-			flags->interrupt_info_struct.interrupt_type);
-		printk(KERN_INFO "Code name: ");
-		for(i = 0; i < 4; i ++)
-			printk(KERN_INFO "%c",
-				flags->global_info_struct.codename[i]); 
-		printk(KERN_INFO "\nCode version: ");
-	 	for(i = 0; i < 4; i ++)
-			printk(KERN_INFO "%c", 
-				flags->global_info_struct.codeversion[i]); 
-		printk(KERN_INFO "\n");	
-		break;
-	}
-
-isr_done:
-
-	card->in_isr = 0;
-	flags->interrupt_info_struct.interrupt_type = 0;
-	return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
-	struct net_device *dev;
-	chdlc_private_area_t *chdlc_priv_area;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
-	struct sk_buff *skb;
-	unsigned len;
-	unsigned addr = rxbuf->ptr_data_bfr;
-	void *buf;
-	int i,udp_type;
-
-	if (rxbuf->opp_flag != 0x01) {
-		printk(KERN_INFO 
-			"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", 
-			card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
-                printk(KERN_INFO "Code name: ");
-                for(i = 0; i < 4; i ++)
-                        printk(KERN_INFO "%c",
-                                flags->global_info_struct.codename[i]);
-                printk(KERN_INFO "\nCode version: ");
-                for(i = 0; i < 4; i ++)
-                        printk(KERN_INFO "%c",
-                                flags->global_info_struct.codeversion[i]);
-                printk(KERN_INFO "\n");
-
-
-		/* Bug Fix: Mar 6 2000
-                 * If we get a corrupted mailbox, it measn that driver 
-                 * is out of sync with the firmware. There is no recovery.
-                 * If we don't turn off all interrupts for this card
-                 * the machine will crash. 
-                 */
-		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
-		printk(KERN_INFO "Please contact Sangoma Technologies !\n");
-		chdlc_set_intr_mode(card,0);	
-		return;
-	}
-
-	len  = rxbuf->frame_length;
-
-	if (card->tty_opt){
-
-		if (rxbuf->error_flag){	
-			goto rx_exit;
-		}
-
-		if (len <= CRC_LENGTH){
-			goto rx_exit;
-		}
-		
-		if (!card->u.c.async_mode){
-			len -= CRC_LENGTH;
-		}
-
-		wanpipe_tty_receive(card,addr,len);
-		goto rx_exit;
-	}
-
-	dev = card->wandev.dev;
-
-	if (!dev){
-		goto rx_exit;
-	}
-
-	if (!netif_running(dev))
-		goto rx_exit;
-
-	chdlc_priv_area = dev->priv;
-
-	
-	/* Allocate socket buffer */
-	skb = dev_alloc_skb(len);
-
-	if (skb == NULL) {
-		printk(KERN_INFO "%s: no socket buffers available!\n",
-					card->devname);
-		++card->wandev.stats.rx_dropped;
-		goto rx_exit;
-	}
-
-	/* Copy data to the socket buffer */
-	if((addr + len) > card->u.c.rx_top + 1) {
-		unsigned tmp = card->u.c.rx_top - addr + 1;
-		buf = skb_put(skb, tmp);
-		sdla_peek(&card->hw, addr, buf, tmp);
-		addr = card->u.c.rx_base;
-		len -= tmp;
-	}
-		
-	buf = skb_put(skb, len);
-	sdla_peek(&card->hw, addr, buf, len);
-
-	skb->protocol = htons(ETH_P_IP);
-
-	card->wandev.stats.rx_packets ++;
-	card->wandev.stats.rx_bytes += skb->len;
-	udp_type = udp_pkt_type( skb, card );
-
-	if(udp_type == UDP_CPIPE_TYPE) {
-		if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
-   				      card, skb, dev, chdlc_priv_area)) {
-     		        flags->interrupt_info_struct.
-						interrupt_permission |= 
-							APP_INT_ON_TIMER; 
-		}
-	} else if(card->u.c.usedby == API) {
-
-		api_rx_hdr_t* api_rx_hdr;
-       		skb_push(skb, sizeof(api_rx_hdr_t));
-                api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
-		api_rx_hdr->error_flag = rxbuf->error_flag;
-     		api_rx_hdr->time_stamp = rxbuf->time_stamp;
-
-                skb->protocol = htons(PVC_PROT);
-     		skb->mac.raw  = skb->data;
-		skb->dev      = dev;
-               	skb->pkt_type = WAN_PACKET_DATA;
-
-		bh_enqueue(dev, skb);
-
-		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))
-			wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);
-	}else{
-		/* FIXME: we should check to see if the received packet is a 
-                          multicast packet so that we can increment the multicast 
-                          statistic
-                          ++ chdlc_priv_area->if_stats.multicast;
-		*/
-               	/* Pass it up the protocol stack */
-	
-                skb->dev = dev;
-                skb->mac.raw  = skb->data;
-                netif_rx(skb);
-                dev->last_rx = jiffies;
-	}
-
-rx_exit:
-	/* Release buffer element and calculate a pointer to the next one */
-	rxbuf->opp_flag = 0x00;
-	card->u.c.rxmb = ++ rxbuf;
-	if((void*)rxbuf > card->u.c.rxbuf_last){
-		card->u.c.rxmb = card->u.c.rxbuf_base;
-	}
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- *    1) Processing udp calls from 'cpipemon'.
- *    2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
-        struct net_device* dev;
-        chdlc_private_area_t* chdlc_priv_area = NULL;
-        SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
-        if ((dev = card->wandev.dev)==NULL){
-		flags = card->u.c.flags;
-                flags->interrupt_info_struct.interrupt_permission &=
-                        ~APP_INT_ON_TIMER;
-		return;
-	}
-	
-        chdlc_priv_area = dev->priv;
-
-	if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
-		if (!config_chdlc(card)){
-			chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
-		}
-	}
-
-	/* process a udp call if pending */
-       	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
-               	process_udp_mgmt_pkt(card, dev,
-                       chdlc_priv_area);
-		chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
-        }
-
-	/* read the communications statistics if required */
-	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
-		update_comms_stats(card, chdlc_priv_area);
-                if(!(-- chdlc_priv_area->update_comms_stats)) {
-			chdlc_priv_area->timer_int_enabled &= 
-				~TMR_INT_ENABLED_UPDATE;
-		}
-        }
-
-	/* only disable the timer interrupt if there are no udp or statistic */
-	/* updates pending */
-        if(!chdlc_priv_area->timer_int_enabled) {
-                flags = card->u.c.flags;
-                flags->interrupt_info_struct.interrupt_permission &=
-                        ~APP_INT_ON_TIMER;
-        }
-}
-
-/*------------------------------------------------------------------------------
-  Miscellaneous Functions
-	- set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
-	CHDLC_CONFIGURATION_STRUCT cfg;
-
-	memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
-	if(card->wandev.clocking){
-		cfg.baud_rate = card->wandev.bps;
-	}
-		
-	cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
-		INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
-	cfg.modem_config_options	= 0;
-	cfg.modem_status_timer		= 100;
-
-	cfg.CHDLC_protocol_options	= card->u.c.protocol_options;
-
-	if (card->tty_opt){
-		cfg.CHDLC_API_options	= DISCARD_RX_ERROR_FRAMES;
-	}
-	
-	cfg.percent_data_buffer_for_Tx  = (card->u.c.receive_only) ? 0 : 50;
-	cfg.CHDLC_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |
-		CHDLC_RX_DATA_BYTE_COUNT_STAT);
-	
-	if (card->tty_opt){
-		card->wandev.mtu = TTY_CHDLC_MAX_MTU;
-	}
-	cfg.max_CHDLC_data_field_length	= card->wandev.mtu;
-	cfg.transmit_keepalive_timer	= card->u.c.kpalv_tx;
-	cfg.receive_keepalive_timer	= card->u.c.kpalv_rx;
-	cfg.keepalive_error_tolerance	= card->u.c.kpalv_err;
-	cfg.SLARP_request_timer		= card->u.c.slarp_timer;
-
-	if (cfg.SLARP_request_timer) {
-		cfg.IP_address		= 0;
-		cfg.IP_netmask		= 0;
-		
-	}else if (card->wandev.dev){
-		struct net_device *dev = card->wandev.dev;
-		chdlc_private_area_t *chdlc_priv_area = dev->priv;
-		
-                struct in_device *in_dev = dev->ip_ptr;
-
-		if(in_dev != NULL) {
-			struct in_ifaddr *ifa = in_dev->ifa_list;
-
-			if (ifa != NULL ) {
-				cfg.IP_address	= ntohl(ifa->ifa_local);
-				cfg.IP_netmask	= ntohl(ifa->ifa_mask); 
-				chdlc_priv_area->IP_address = ntohl(ifa->ifa_local);
-				chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); 
-			}
-		}
-
-		/* FIXME: We must re-think this message in next release
-		if((cfg.IP_address & 0x000000FF) > 2) {
-			printk(KERN_WARNING "\n");
-	                printk(KERN_WARNING "  WARNING:%s configured with an\n",
-				card->devname);
-			printk(KERN_WARNING "  invalid local IP address.\n");
-                        printk(KERN_WARNING "  Slarp pragmatics will fail.\n");
-                        printk(KERN_WARNING "  IP address should be of the\n");
-			printk(KERN_WARNING "  format A.B.C.1 or A.B.C.2.\n");
-		}
-		*/		
-	}
-	
-	return chdlc_configure(card, &cfg);
-}
-
-
-/*-----------------------------------------------------------------------------
-   set_asy_config() used to set asynchronous configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_asy_config(sdla_t* card)
-{
-
-        ASY_CONFIGURATION_STRUCT cfg;
- 	CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
-	int err;
-
-	memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT));
-
-	if(card->wandev.clocking)
-		cfg.baud_rate = card->wandev.bps;
-
-	cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
-		INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
-	cfg.modem_config_options	= 0;
-	cfg.asy_API_options 		= card->u.c.api_options;
-	cfg.asy_protocol_options	= card->u.c.protocol_options;
-	cfg.Tx_bits_per_char		= card->u.c.tx_bits_per_char;
-	cfg.Rx_bits_per_char		= card->u.c.rx_bits_per_char;
-	cfg.stop_bits			= card->u.c.stop_bits;
-	cfg.parity			= card->u.c.parity;
-	cfg.break_timer			= card->u.c.break_timer;
-	cfg.asy_Rx_inter_char_timer	= card->u.c.inter_char_timer; 
-	cfg.asy_Rx_complete_length	= card->u.c.rx_complete_length; 
-	cfg.XON_char			= card->u.c.xon_char;
-	cfg.XOFF_char			= card->u.c.xoff_char;
-	cfg.asy_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |
-		CHDLC_RX_DATA_BYTE_COUNT_STAT);
-
-	mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT);
-	memcpy(mailbox->data, &cfg, mailbox->buffer_length);
-	mailbox->command = SET_ASY_CONFIGURATION;
-	err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK) 
-		chdlc_error (card, err, mailbox);
-	return err;
-}
-
-/*============================================================================
- * Enable asynchronous communications.
- */
-
-static int asy_comm_enable (sdla_t* card)
-{
-
-	int err;
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-	mb->buffer_length = 0;
-	mb->command = ENABLE_ASY_COMMUNICATIONS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK && card->wandev.dev)
-		chdlc_error(card, err, mb);
-	
-	if (!err)
-		card->u.c.comm_enabled = 1;
-
-	return err;
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
-	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
-	int err;
-
-	mbox->buffer_length = 0;
-	mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
-	err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
-	if(err != CMD_TIMEOUT ){
-	
-		switch(mbox->return_code) {
-         
-	      	case EXCEP_MODEM_STATUS_CHANGE:
-
-			printk(KERN_INFO "%s: Modem status change\n",
-				card->devname);
-
-			switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
-				case (DCD_HIGH):
-					printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
-					break;
-				case (CTS_HIGH):
-                                        printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); 
-					break;
-                                case ((DCD_HIGH | CTS_HIGH)):
-                                        printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
-                                        break;
-				default:
-                                        printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
-                                        break;
-			}
-			break;
-
-                case EXCEP_TRC_DISABLED:
-                        printk(KERN_INFO "%s: Line trace disabled\n",
-				card->devname);
-                        break;
-
-		case EXCEP_IRQ_TIMEOUT:
-			printk(KERN_INFO "%s: IRQ timeout occurred\n",
-				card->devname); 
-			break;
-
-		case 0x17:
-			if (card->tty_opt){
-				if (card->tty && card->tty_open){ 
-					printk(KERN_INFO 
-						"%s: Modem Hangup Exception: Hanging Up!\n",
-						card->devname);
-					tty_hangup(card->tty);
-				}
-				break;
-			}
-
-			/* If TTY is not used just drop throught */
-			
-                default:
-                        printk(KERN_INFO "%s: Global exception %x\n",
-				card->devname, mbox->return_code);
-                        break;
-                }
-	}
-	return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int err;
-
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_EXCEPTION_CONDITION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if(err != CMD_TIMEOUT) {
-	
-		switch (err) {
-
-		case EXCEP_LINK_ACTIVE:
-			port_set_state(card, WAN_CONNECTED);
-			trigger_chdlc_poll(card->wandev.dev);
-			break;
-
-		case EXCEP_LINK_INACTIVE_MODEM:
-			port_set_state(card, WAN_DISCONNECTED);
-			unconfigure_ip(card);
-			trigger_chdlc_poll(card->wandev.dev);
-			break;
-
-		case EXCEP_LINK_INACTIVE_KPALV:
-			port_set_state(card, WAN_DISCONNECTED);
-			printk(KERN_INFO "%s: Keepalive timer expired.\n",
-				 		card->devname);
-			unconfigure_ip(card);
-			trigger_chdlc_poll(card->wandev.dev);
-			break;
-
-		case EXCEP_IP_ADDRESS_DISCOVERED:
-			if (configure_ip(card)) 
-				return -1;
-			break;
-
-		case EXCEP_LOOPBACK_CONDITION:
-			printk(KERN_INFO "%s: Loopback Condition Detected.\n",
-						card->devname);
-			break;
-
-		case NO_CHDLC_EXCEP_COND_TO_REPORT:
-			printk(KERN_INFO "%s: No exceptions reported.\n",
-						card->devname);
-			break;
-		}
-
-	}
-	return 0;
-}
-
-
-/*============================================================================
- * Configure IP from SLARP negotiation
- * This adds dynamic routes when SLARP has provided valid addresses
- */
-
-static int configure_ip (sdla_t* card)
-{
-	struct net_device *dev = card->wandev.dev;
-        chdlc_private_area_t *chdlc_priv_area;
-        char err;
-
-	if (!dev)
-		return 0;
-
-	chdlc_priv_area = dev->priv;
-	
-	
-        /* set to discover */
-        if(card->u.c.slarp_timer != 0x00) {
-		CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-		CHDLC_CONFIGURATION_STRUCT *cfg;
-
-     		mb->buffer_length = 0;
-		mb->command = READ_CHDLC_CONFIGURATION;
-		err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	
-		if(err != COMMAND_OK) {
-			chdlc_error(card,err,mb);
-			return -1;
-		}
-
-		cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data;
-                chdlc_priv_area->IP_address = cfg->IP_address;
-                chdlc_priv_area->IP_netmask = cfg->IP_netmask;
-
-		/* Set flag to add route */
-		chdlc_priv_area->route_status = ADD_ROUTE;
-
-		/* The idea here is to add the route in the poll routine.
-	   	This way, we aren't in interrupt context when adding routes */
-		trigger_chdlc_poll(dev);
-        }
-
-	return 0;
-}
-
-
-/*============================================================================
- * Un-Configure IP negotiated by SLARP
- * This removes dynamic routes when the link becomes inactive.
- */
-
-static int unconfigure_ip (sdla_t* card)
-{
-	struct net_device *dev = card->wandev.dev;
-	chdlc_private_area_t *chdlc_priv_area;
-
-	if (!dev)
-		return 0;
-
-	chdlc_priv_area= dev->priv;
-	
-	if (chdlc_priv_area->route_status == ROUTE_ADDED) {
-
-		/* Note: If this function is called, the 
-                 * port state has been DISCONNECTED.  This state
-                 * change will trigger a poll_disconnected 
-                 * function, that will check for this condition. 
-		 */
-		chdlc_priv_area->route_status = REMOVE_ROUTE;
-
-	}
-	return 0;
-}
-
-/*============================================================================
- * Routine to add/remove routes 
- * Called like a polling routine when Routes are flagged to be added/removed.
- */
-
-static void process_route (sdla_t *card)
-{
-        struct net_device *dev = card->wandev.dev;
-        unsigned char port_num;
-        chdlc_private_area_t *chdlc_priv_area = NULL;
-	u32 local_IP_addr = 0;
-	u32 remote_IP_addr = 0;
-	u32 IP_netmask, IP_addr;
-        int err = 0;
-	struct in_device *in_dev;
-	mm_segment_t fs;
-	struct ifreq if_info;
-        struct sockaddr_in *if_data1, *if_data2;
-	
-        chdlc_priv_area = dev->priv;
-        port_num = card->u.c.comm_port;
-
-	/* Bug Fix Mar 16 2000
-	 * AND the IP address to the Mask before checking
-         * the last two bits. */
-
-	if((chdlc_priv_area->route_status == ADD_ROUTE) &&
-		((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) {
-
-		printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname);
-
-                if(card->u.c.slarp_timer) {
-			u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
-			printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u received\n",
-				card->devname,
-			       NIPQUAD(addr_net));
-                        printk(KERN_INFO "%s: from remote station.\n",
-				card->devname);
-
-                }else{ 
-			u32 addr_net = htonl(chdlc_priv_area->IP_address);
-
-                        printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issued\n",
-			       card->devname,
-			       NIPQUAD(addr_net));
-                        printk(KERN_INFO "%s: to remote station. Local\n",
-				card->devname);
-			printk(KERN_INFO "%s: IP address must be A.B.C.1\n",
-				card->devname);
-			printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname);
-		}
-
-		/* remove the route due to the IP address error condition */
-		chdlc_priv_area->route_status = REMOVE_ROUTE;
-		err = 1;
-   	}
-
-	/* If we are removing a route with bad IP addressing, then use the */
-	/* locally configured IP addresses */
-        if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) {
-
- 	        /* do not remove a bad route that has already been removed */
-        	if(chdlc_priv_area->route_removed) {
-	                return;
-        	}
-
-                in_dev = dev->ip_ptr;
-
-                if(in_dev != NULL) {
-                        struct in_ifaddr *ifa = in_dev->ifa_list;
-                        if (ifa != NULL ) {
-                                local_IP_addr = ifa->ifa_local;
-                                IP_netmask  = ifa->ifa_mask;
-                        }
-                }
-	}else{ 
-       		/* According to Cisco HDLC, if the point-to-point address is
-		   A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
-		*/
-		IP_netmask = ntohl(chdlc_priv_area->IP_netmask);
-	        remote_IP_addr = ntohl(chdlc_priv_area->IP_address);
-	
-
-		/* If Netmask is 255.255.255.255 the local address
-                 * calculation will fail. Default it back to 255.255.255.0 */
-		if (IP_netmask == 0xffffffff)
-			IP_netmask &= 0x00ffffff;
-
-		/* Bug Fix Mar 16 2000
-		 * AND the Remote IP address with IP netmask, instead
-                 * of static netmask of 255.255.255.0 */
-        	local_IP_addr = (remote_IP_addr & IP_netmask) +
-                	(~remote_IP_addr & ntohl(0x0003));
-
-	        if(!card->u.c.slarp_timer) {
-			IP_addr = local_IP_addr;
-			local_IP_addr = remote_IP_addr;
-			remote_IP_addr = IP_addr;
-       		}
-	}
-
-        fs = get_fs();                  /* Save file system  */
-        set_fs(get_ds());               /* Get user space block */
-
-        /* Setup a structure for adding/removing routes */
-        memset(&if_info, 0, sizeof(if_info));
-        strcpy(if_info.ifr_name, dev->name);
-
-	switch (chdlc_priv_area->route_status) {
-
-	case ADD_ROUTE:
-
-		if(!card->u.c.slarp_timer) {
-			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-			if_data2->sin_addr.s_addr = remote_IP_addr;
-			if_data2->sin_family = AF_INET;
-			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
-		} else { 
-			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
-			if_data1->sin_addr.s_addr = local_IP_addr;
-			if_data1->sin_family = AF_INET;
-			if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){
-				if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-				if_data2->sin_addr.s_addr = remote_IP_addr;
-				if_data2->sin_family = AF_INET;
-				err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
-			}
-		}
-
-               if(err) {
-			printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)\n", 
-				card->devname, NIPQUAD(remote_IP_addr), err);
-		} else {
-			((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED;
-			printk(KERN_INFO "%s: Dynamic route added.\n",
-				card->devname);
-			printk(KERN_INFO "%s:    Local IP addr : %u.%u.%u.%u\n",
-				card->devname, NIPQUAD(local_IP_addr));
-			printk(KERN_INFO "%s:    Remote IP addr: %u.%u.%u.%u\n",
-				card->devname, NIPQUAD(remote_IP_addr));
-			chdlc_priv_area->route_removed = 0;
-		}
-		break;
-
-
-	case REMOVE_ROUTE:
-	
-		/* Change the local ip address of the interface to 0.
-		 * This will also delete the destination route.
-		 */
-		if(!card->u.c.slarp_timer) {
-			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-			if_data2->sin_addr.s_addr = 0;
-			if_data2->sin_family = AF_INET;
-			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
-		} else {
-			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
-			if_data1->sin_addr.s_addr = 0;
-			if_data1->sin_family = AF_INET;
-			err = devinet_ioctl(SIOCSIFADDR,&if_info);
-		
-		}
-		if(err) {
-			printk(KERN_INFO
-				"%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
-					card->devname, NIPQUAD(remote_IP_addr),
-					err);
-		} else {
-			((chdlc_private_area_t *)dev->priv)->route_status =
-				NO_ROUTE;
-                        printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%u\n",
-                                        card->devname, NIPQUAD(local_IP_addr)); 
-			chdlc_priv_area->route_removed = 1;
-		}
-		break;
-	}
-
-        set_fs(fs);                     /* Restore file system */
-
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-			      struct sk_buff *skb, struct net_device* dev,
-			      chdlc_private_area_t* chdlc_priv_area)
-{
-	int udp_pkt_stored = 0;
-
-	if(!chdlc_priv_area->udp_pkt_lgth &&
-	  (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
-        	chdlc_priv_area->udp_pkt_lgth = skb->len;
-		chdlc_priv_area->udp_pkt_src = udp_pkt_src;
-       		memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
-		chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
-		udp_pkt_stored = 1;
-	}
-
-	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		dev_kfree_skb_any(skb);
-	}else{
-                dev_kfree_skb_any(skb);
-	}
-		
-	return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
-				chdlc_private_area_t* chdlc_priv_area ) 
-{
-	unsigned char *buf;
-	unsigned int frames, len;
-	struct sk_buff *new_skb;
-	unsigned short buffer_length, real_len;
-	unsigned long data_ptr;
-	unsigned data_length;
-	int udp_mgmt_req_valid = 1;
-	CHDLC_MAILBOX_STRUCT *mb = card->mbox;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	chdlc_udp_pkt_t *chdlc_udp_pkt;
-	struct timeval tv;
-	int err;
-	char ut_char;
-
-	chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
-	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
-		/* Only these commands are support for remote debugging.
-		 * All others are not */
-		switch(chdlc_udp_pkt->cblock.command) {
-
-			case READ_GLOBAL_STATISTICS:
-			case READ_MODEM_STATUS:  
-			case READ_CHDLC_LINK_STATUS:
-			case CPIPE_ROUTER_UP_TIME:
-			case READ_COMMS_ERROR_STATS:
-			case READ_CHDLC_OPERATIONAL_STATS:
-
-			/* These two commands are executed for
-			 * each request */
-			case READ_CHDLC_CONFIGURATION:
-			case READ_CHDLC_CODE_VERSION:
-				udp_mgmt_req_valid = 1;
-				break;
-			default:
-				udp_mgmt_req_valid = 0;
-				break;
-		} 
-	}
-	
-  	if(!udp_mgmt_req_valid) {
-
-		/* set length to 0 */
-		chdlc_udp_pkt->cblock.buffer_length = 0;
-
-    		/* set return code */
-		chdlc_udp_pkt->cblock.return_code = 0xCD;
-
-		if (net_ratelimit()){	
-			printk(KERN_INFO 
-			"%s: Warning, Illegal UDP command attempted from network: %x\n",
-			card->devname,chdlc_udp_pkt->cblock.command);
-		}
-
-   	} else {
-	   	unsigned long trace_status_cfg_addr = 0;
-		TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
-		TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
-		switch(chdlc_udp_pkt->cblock.command) {
-
-		case CPIPE_ENABLE_TRACING:
-		     if (!chdlc_priv_area->TracingEnabled) {
-
-			/* OPERATE_DATALINE_MONITOR */
-
-			mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
-			mb->command = SET_TRACE_CONFIGURATION;
-
-    			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-				trace_config = TRACE_ACTIVE;
-			/* Trace delay mode is not used because it slows
-			   down transfer and results in a standoff situation
-			   when there is a lot of data */
-
-			/* Configure the Trace based on user inputs */
-			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= 
-					chdlc_udp_pkt->data[0];
-
-			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-			   trace_deactivation_timer = 4000;
-
-
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-			if (err != COMMAND_OK) {
-				chdlc_error(card,err,mb);
-				card->TracingEnabled = 0;
-				chdlc_udp_pkt->cblock.return_code = err;
-				mb->buffer_length = 0;
-				break;
-	    		} 
-
-			/* Get the base address of the trace element list */
-			mb->buffer_length = 0;
-			mb->command = READ_TRACE_CONFIGURATION;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-			if (err != COMMAND_OK) {
-				chdlc_error(card,err,mb);
-				chdlc_priv_area->TracingEnabled = 0;
-				chdlc_udp_pkt->cblock.return_code = err;
-				mb->buffer_length = 0;
-				break;
-	    		} 	
-
-	   		trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
-				mb->data) -> ptr_trace_stat_el_cfg_struct;
-
-			sdla_peek(&card->hw, trace_status_cfg_addr,
-				 &trace_cfg_struct, sizeof(trace_cfg_struct));
-		    
-			chdlc_priv_area->start_trace_addr = trace_cfg_struct.
-				base_addr_trace_status_elements;
-
-			chdlc_priv_area->number_trace_elements = 
-					trace_cfg_struct.number_trace_status_elements;
-
-			chdlc_priv_area->end_trace_addr = (unsigned long)
-					((TRACE_STATUS_ELEMENT_STRUCT *)
-					 chdlc_priv_area->start_trace_addr + 
-					 (chdlc_priv_area->number_trace_elements - 1));
-
-			chdlc_priv_area->base_addr_trace_buffer = 
-					trace_cfg_struct.base_addr_trace_buffer;
-
-			chdlc_priv_area->end_addr_trace_buffer = 
-					trace_cfg_struct.end_addr_trace_buffer;
-
-		    	chdlc_priv_area->curr_trace_addr = 
-					trace_cfg_struct.next_trace_element_to_use;
-
-	    		chdlc_priv_area->available_buffer_space = 2000 - 
-								  sizeof(ip_pkt_t) -
-								  sizeof(udp_pkt_t) -
-							      	  sizeof(wp_mgmt_t) -
-								  sizeof(cblock_t) -
-							          sizeof(trace_info_t);	
-	       	     }
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-		     mb->buffer_length = 0;
-	       	     chdlc_priv_area->TracingEnabled = 1;
-	       	     break;
-	   
-
-		case CPIPE_DISABLE_TRACING:
-		     if (chdlc_priv_area->TracingEnabled) {
-
-			/* OPERATE_DATALINE_MONITOR */
-			mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
-			mb->command = SET_TRACE_CONFIGURATION;
-    			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-				trace_config = TRACE_INACTIVE;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-		     }		
-
-		     chdlc_priv_area->TracingEnabled = 0;
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-		     mb->buffer_length = 0;
-		     break;
-	   
-
-		case CPIPE_GET_TRACE_INFO:
-
-		     if (!chdlc_priv_area->TracingEnabled) {
-			chdlc_udp_pkt->cblock.return_code = 1;
-			mb->buffer_length = 0;
-			break;
-		     }
-
-  		     chdlc_udp_pkt->trace_info.ismoredata = 0x00;
-		     buffer_length = 0;	/* offset of packet already occupied */
-
-		     for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
-			trace_pkt_t *trace_pkt = (trace_pkt_t *)
-				&chdlc_udp_pkt->data[buffer_length];
-
-			sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
-			   	  (unsigned char *)&trace_element_struct,
-			   	  sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
-     			if (trace_element_struct.opp_flag == 0x00) {
-			 	break;
-			}
-
-			/* get pointer to real data */
-			data_ptr = trace_element_struct.ptr_data_bfr;
-
-			/* See if there is actual data on the trace buffer */
-			if (data_ptr){
-				data_length = trace_element_struct.trace_length;
-			}else{
-				data_length = 0;
-				chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-			}
-	
-   			if( (chdlc_priv_area->available_buffer_space - buffer_length)
-				< ( sizeof(trace_pkt_t) + data_length) ) {
-
-                            /* indicate there are more frames on board & exit */
-				chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-                               	break;
-                         }
-
-			trace_pkt->status = trace_element_struct.trace_type;
-
-			trace_pkt->time_stamp =
-				trace_element_struct.trace_time_stamp;
-
-			trace_pkt->real_length =
-				trace_element_struct.trace_length;
-
-			/* see if we can fit the frame into the user buffer */
-			real_len = trace_pkt->real_length;
-
-			if (data_ptr == 0) {
-			     	trace_pkt->data_avail = 0x00;
-			} else {
-				unsigned tmp = 0;
-
-				/* get the data from circular buffer
-				    must check for end of buffer */
-			        trace_pkt->data_avail = 0x01;
-
-				if ((data_ptr + real_len) >
-					     chdlc_priv_area->end_addr_trace_buffer + 1){
-
-				    	tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
-				    	sdla_peek(&card->hw, data_ptr,
-					       	  trace_pkt->data,tmp);
-				    	data_ptr = chdlc_priv_area->base_addr_trace_buffer;
-				}
-	
-		        	sdla_peek(&card->hw, data_ptr,
-					  &trace_pkt->data[tmp], real_len - tmp);
-			}	
-
-			/* zero the opp flag to show we got the frame */
-			ut_char = 0x00;
-			sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
-       			/* now move onto the next frame */
-       			chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
-       			/* check if we went over the last address */
-			if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
-				chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
-       			}
-
-            		if(trace_pkt->data_avail == 0x01) {
-				buffer_length += real_len - 1;
-			}
-	 
-	       	    	/* for the header */
-	            	buffer_length += sizeof(trace_pkt_t);
-
-		     }  /* For Loop */
-
-		     if (frames == chdlc_priv_area->number_trace_elements){
-			chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-	             }
- 		     chdlc_udp_pkt->trace_info.num_frames = frames;
-		 
-    		     mb->buffer_length = buffer_length;
-		     chdlc_udp_pkt->cblock.buffer_length = buffer_length; 
-		 
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK; 
-		     
-		     break;
-
-
-		case CPIPE_FT1_READ_STATUS:
-			((unsigned char *)chdlc_udp_pkt->data )[0] =
-				flags->FT1_info_struct.parallel_port_A_input;
-
-			((unsigned char *)chdlc_udp_pkt->data )[1] =
-				flags->FT1_info_struct.parallel_port_B_input;
-				
-			chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-			chdlc_udp_pkt->cblock.buffer_length = 2;
-			mb->buffer_length = 2;
-			break;
-
-		case CPIPE_ROUTER_UP_TIME:
-			do_gettimeofday( &tv );
-			chdlc_priv_area->router_up_time = tv.tv_sec - 
-					chdlc_priv_area->router_start_time;
-			*(unsigned long *)&chdlc_udp_pkt->data = 
-					chdlc_priv_area->router_up_time;	
-			mb->buffer_length = sizeof(unsigned long);
-			chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long);
-			chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-			break;
-
-   		case FT1_MONITOR_STATUS_CTRL:
-			/* Enable FT1 MONITOR STATUS */
-	        	if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||  
-				(chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-			
-			     	if( rCount++ != 0 ) {
-					chdlc_udp_pkt->cblock.
-					return_code = COMMAND_OK;
-					mb->buffer_length = 1;
-		  			break;
-		    	     	}
-	      		}
-
-	      		/* Disable FT1 MONITOR STATUS */
-	      		if( chdlc_udp_pkt->data[0] == 0) {
-
-	      	   	     	if( --rCount != 0) {
-		  			chdlc_udp_pkt->cblock.
-					return_code = COMMAND_OK;
-					mb->buffer_length = 1;
-		  			break;
-	   	    	     	} 
-	      		} 	
-			goto dflt_1;
-
-		default:
-dflt_1:
-			/* it's a board command */
-			mb->command = chdlc_udp_pkt->cblock.command;
-			mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
-			if (mb->buffer_length) {
-				memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
-							data, mb->buffer_length);
-	      		} 
-			/* run the command on the board */
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-			if (err != COMMAND_OK) {
-				break;
-			}
-
-			/* copy the result back to our buffer */
-	         	memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); 
-			
-			if (mb->buffer_length) {
-	         		memcpy(&chdlc_udp_pkt->data, &mb->data, 
-								mb->buffer_length); 
-	      		}
-
-		} /* end of switch */
-     	} /* end of else */
-
-     	/* Fill UDP TTL */
-	chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; 
-
-     	len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-	
-
-     	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
-
-		/* Must check if we interrupted if_send() routine. The
-		 * tx buffers might be used. If so drop the packet */
-	   	if (!test_bit(SEND_CRIT,&card->wandev.critical)) {
-		
-			if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
-				++ card->wandev.stats.tx_packets;
-				card->wandev.stats.tx_bytes += len;
-			}
-		}
-	} else {	
-	
-		/* Pass it up the stack
-    		   Allocate socket buffer */
-		if ((new_skb = dev_alloc_skb(len)) != NULL) {
-			/* copy data into new_skb */
-
- 	    		buf = skb_put(new_skb, len);
-  	    		memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
-            		/* Decapsulate pkt and pass it up the protocol stack */
-	    		new_skb->protocol = htons(ETH_P_IP);
-            		new_skb->dev = dev;
-	    		new_skb->mac.raw  = new_skb->data;
-	
-			netif_rx(new_skb);
-			dev->last_rx = jiffies;
-		} else {
-	    	
-			printk(KERN_INFO "%s: no socket buffers available!\n",
-					card->devname);
-  		}
-    	}
- 
-	chdlc_priv_area->udp_pkt_lgth = 0;
- 	
-	return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff( sdla_t* card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
-	CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
-	char err;
-	
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_CONFIGURATION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	if(err != COMMAND_OK) {
-		if (card->wandev.dev){
-			chdlc_error(card,err,mb);
-		}
-		return;
-	}
-
-	if(card->hw.type == SDLA_S514) {
-		tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-                (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-                            ptr_CHDLC_Tx_stat_el_cfg_struct));
-        	rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-                (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-                            ptr_CHDLC_Rx_stat_el_cfg_struct));
-
-       		/* Setup Head and Tails for buffers */
-        	card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
-                tx_config->base_addr_Tx_status_elements);
-        	card->u.c.txbuf_last = 
-		(CHDLC_DATA_TX_STATUS_EL_STRUCT *)  
-                card->u.c.txbuf_base +
-		(tx_config->number_Tx_status_elements - 1);
-
-        	card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
-                rx_config->base_addr_Rx_status_elements);
-        	card->u.c.rxbuf_last =
-		(CHDLC_DATA_RX_STATUS_EL_STRUCT *)
-                card->u.c.rxbuf_base +
-		(rx_config->number_Rx_status_elements - 1);
-
- 		/* Set up next pointer to be used */
-        	card->u.c.txbuf = (void *)(card->hw.dpmbase +
-                tx_config->next_Tx_status_element_to_use);
-        	card->u.c.rxmb = (void *)(card->hw.dpmbase +
-                rx_config->next_Rx_status_element_to_use);
-	}
-        else {
-                tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-			(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-			ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
-                rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-			(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-			ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
-                /* Setup Head and Tails for buffers */
-                card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
-		(tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
-                card->u.c.txbuf_last =
-		(CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
-		+ (tx_config->number_Tx_status_elements - 1);
-                card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
-		(rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
-                card->u.c.rxbuf_last = 
-		(CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
-		+ (rx_config->number_Rx_status_elements - 1);
-
-                 /* Set up next pointer to be used */
-                card->u.c.txbuf = (void *)(card->hw.dpmbase +
-		(tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
-                card->u.c.rxmb = (void *)(card->hw.dpmbase +
-		(rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
-        }
-
-        /* Setup Actual Buffer Start and end addresses */
-        card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
-        card->u.c.rx_top  = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int err,i;
-
-	Intr_test_counter = 0;
-	
-	err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
-	if (err == CMD_OK) { 
-		for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {	
-			mb->buffer_length  = 0;
-			mb->command = READ_CHDLC_CODE_VERSION;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-			if (err != CMD_OK) 
-				chdlc_error(card, err, mb);
-		}
-	}
-	else {
-		return err;
-	}
-
-	err = chdlc_set_intr_mode(card, 0);
-
-	if (err != CMD_OK)
-		return err;
-
-	return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
-	 chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
-#ifdef _WAN_UDP_DEBUG
-		printk(KERN_INFO "SIG %s = %s\n\
-				  UPP %x = %x\n\
-				  PRT %x = %x\n\
-				  REQ %i = %i\n\
-				  36 th = %x 37th = %x\n",
-				  chdlc_udp_pkt->wp_mgmt.signature,
-				  UDPMGMT_SIGNATURE,
-				  chdlc_udp_pkt->udp_pkt.udp_dst_port,
-				  ntohs(card->wandev.udp_port),
-				  chdlc_udp_pkt->ip_pkt.protocol,
-				  UDPMGMT_UDP_PROTOCOL,
-				  chdlc_udp_pkt->wp_mgmt.request_reply,
-				  UDPMGMT_REQUEST,
-				  skb->data[36], skb->data[37]);
-#endif	
-		
-	if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
-	   (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
-	   (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
-	   (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
-		return UDP_CPIPE_TYPE;
-
-	}else{ 
-		return UDP_INVALID_TYPE;
-	}
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
-        if (card->u.c.state != state)
-        {
-                switch (state)
-                {
-                case WAN_CONNECTED:
-                        printk (KERN_INFO "%s: Link connected!\n",
-                                card->devname);
-                      	break;
-
-                case WAN_CONNECTING:
-                        printk (KERN_INFO "%s: Link connecting...\n",
-                                card->devname);
-                        break;
-
-                case WAN_DISCONNECTED:
-                        printk (KERN_INFO "%s: Link disconnected!\n",
-                                card->devname);
-                        break;
-                }
-
-                card->wandev.state = card->u.c.state = state;
-		if (card->wandev.dev){
-			struct net_device *dev = card->wandev.dev;
-			chdlc_private_area_t *chdlc_priv_area = dev->priv;
-			chdlc_priv_area->common.state = state;
-		}
-        }
-}
-
-/*===========================================================================
- * config_chdlc
- *
- *	Configure the chdlc protocol and enable communications.		
- *
- *   	The if_open() function binds this function to the poll routine.
- *      Therefore, this function will run every time the chdlc interface
- *      is brought up. We cannot run this function from the if_open 
- *      because if_open does not have access to the remote IP address.
- *      
- *	If the communications are not enabled, proceed to configure
- *      the card and enable communications.
- *
- *      If the communications are enabled, it means that the interface
- *      was shutdown by ether the user or driver. In this case, we 
- *      have to check that the IP addresses have not changed.  If
- *      the IP addresses have changed, we have to reconfigure the firmware
- *      and update the changed IP addresses.  Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
-	struct net_device *dev = card->wandev.dev;
-	chdlc_private_area_t *chdlc_priv_area = dev->priv;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
-	if (card->u.c.comm_enabled){
-
-		/* Jun 20. 2000: NC
-		 * IP addresses are not used in the API mode */
-		
-		if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local ||
-		     chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) && 
-		     card->u.c.usedby == WANPIPE) {
-			
-			/* The IP addersses have changed, we must
-                         * stop the communications and reconfigure
-                         * the card. Reason: the firmware must know
-                         * the local and remote IP addresses. */
-			disable_comm(card);
-			port_set_state(card, WAN_DISCONNECTED);
-			printk(KERN_INFO 
-				"%s: IP addresses changed!\n",
-					card->devname);
-			printk(KERN_INFO 
-				"%s: Restarting communications ...\n",
-					card->devname);
-		}else{ 
-			/* IP addresses are the same and the link is up, 
-                         * we don't have to do anything here. Therefore, exit */
-			return 0;
-		}
-	}
-
-	chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp;
-	chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp;
-
-
-	/* Setup the Board for asynchronous mode */
-	if (card->u.c.async_mode){
-		
-		if (set_asy_config(card)) {
-			printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
-				card->devname);
-			return 0;
-		}
-	}else{
-		/* Setup the Board for CHDLC */
-		if (set_chdlc_config(card)) {
-			printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
-				card->devname);
-			return 0;
-		}
-	}
-
-	/* Set interrupt mode and mask */
-        if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
-                		APP_INT_ON_GLOBAL_EXCEP_COND |
-                		APP_INT_ON_TX_FRAME |
-                		APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
-		printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
-				card->devname);
-		return 0;	
-        }
-	
-
-	/* Mask the Transmit and Timer interrupt */
-	flags->interrupt_info_struct.interrupt_permission &= 
-		~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-	/* In TTY mode, receive interrupt will be enabled during
-	 * wanpipe_tty_open() operation */
-	if (card->tty_opt){
-		flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME;
-	}
-
-	/* Enable communications */
- 	if (card->u.c.async_mode){
-		if (asy_comm_enable(card) != 0) {
-			printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
-					card->devname);
-			flags->interrupt_info_struct.interrupt_permission = 0;
-			card->u.c.comm_enabled=0;
-			chdlc_set_intr_mode(card,0);
-			return 0;
-		}
-        }else{ 
-		if (chdlc_comm_enable(card) != 0) {
-			printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
-					card->devname);
-			flags->interrupt_info_struct.interrupt_permission = 0;
-			card->u.c.comm_enabled=0;
-			chdlc_set_intr_mode(card,0);
-			return 0;
-		}
-	}
-
-	/* Initialize Rx/Tx buffer control fields */
-	init_chdlc_tx_rx_buff(card);
-	port_set_state(card, WAN_CONNECTING);
-	return 0; 
-}
-
-
-/*============================================================
- * chdlc_poll
- *	
- * Rationale:
- * 	We cannot manipulate the routing tables, or
- *      ip addresses withing the interrupt. Therefore
- *      we must perform such actons outside an interrupt 
- *      at a later time. 
- *
- * Description:	
- *	CHDLC polling routine, responsible for 
- *     	shutting down interfaces upon disconnect
- *     	and adding/removing routes. 
- *      
- * Usage:        
- * 	This function is executed for each CHDLC  
- * 	interface through a tq_schedule bottom half.
- *      
- *      trigger_chdlc_poll() function is used to kick
- *      the chldc_poll routine.  
- */
-
-static void chdlc_poll(struct net_device *dev)
-{
-	chdlc_private_area_t *chdlc_priv_area;
-	sdla_t *card;
-	u8 check_gateway=0;	
-	SHARED_MEMORY_INFO_STRUCT* flags;
-
-	
-	if (!dev || (chdlc_priv_area=dev->priv) == NULL)
-		return;
-
-	card = chdlc_priv_area->card;
-	flags = card->u.c.flags;
-	
-	/* (Re)Configuraiton is in progress, stop what you are 
-	 * doing and get out */
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		clear_bit(POLL_CRIT,&card->wandev.critical);
-		return;
-	}
-	
-	/* if_open() function has triggered the polling routine
-	 * to determine the configured IP addresses.  Once the
-	 * addresses are found, trigger the chdlc configuration */
-	if (test_bit(0,&chdlc_priv_area->config_chdlc)){
-
-		chdlc_priv_area->ip_local_tmp  = get_ip_address(dev,WAN_LOCAL_IP);
-		chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-	
-	       /* Jun 20. 2000 Bug Fix
-	 	* Only perform this check in WANPIPE mode, since
-	 	* IP addresses are not used in the API mode. */
-	
-		if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp && 
-		    card->u.c.slarp_timer == 0x00 && 
-		    !card->u.c.backup && 
-		    card->u.c.usedby == WANPIPE){
-
-			if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){
-				printk(KERN_INFO "\n%s: --- WARNING ---\n",
-						card->devname);
-				printk(KERN_INFO 
-				"%s: The local IP address is the same as the\n",
-						card->devname);
-				printk(KERN_INFO 
-				"%s: Point-to-Point IP address.\n",
-						card->devname);
-				printk(KERN_INFO "%s: --- WARNING ---\n\n",
-						card->devname);
-			}else{
-				clear_bit(POLL_CRIT,&card->wandev.critical);
-				chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ;
-				add_timer(&chdlc_priv_area->poll_delay_timer);
-				return;
-			}
-		}
-
-		clear_bit(0,&chdlc_priv_area->config_chdlc);
-		clear_bit(POLL_CRIT,&card->wandev.critical);
-		
-		chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
-		flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
-		return;
-	}
-	/* Dynamic interface implementation, as well as dynamic
-	 * routing.  */
-	
-	switch (card->u.c.state){
-
-	case WAN_DISCONNECTED:
-
-		/* If the dynamic interface configuration is on, and interface 
-		 * is up, then bring down the netowrk interface */
-		
-		if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) && 
-		    !test_bit(DEV_DOWN,  &chdlc_priv_area->interface_down) &&		
-		    card->wandev.dev->flags & IFF_UP){	
-
-			printk(KERN_INFO "%s: Interface %s down.\n",
-				card->devname,card->wandev.dev->name);
-			change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP));
-			set_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
-			chdlc_priv_area->route_status = NO_ROUTE;
-
-		}else{
-			/* We need to check if the local IP address is
-               	  	 * zero. If it is, we shouldn't try to remove it.
-                 	 */
-
-			if (card->wandev.dev->flags & IFF_UP && 
-		    	    get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && 
-		    	    chdlc_priv_area->route_status != NO_ROUTE &&
-			    card->u.c.slarp_timer){
-
-				process_route(card);
-			}
-		}
-		break;
-
-	case WAN_CONNECTED:
-
-		/* In SMP machine this code can execute before the interface
-		 * comes up.  In this case, we must make sure that we do not
-		 * try to bring up the interface before dev_open() is finished */
-
-
-		/* DEV_DOWN will be set only when we bring down the interface
-		 * for the very first time. This way we know that it was us
-		 * that brought the interface down */
-		
-		if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
-		    test_bit(DEV_DOWN,  &chdlc_priv_area->interface_down) &&
-		    !(card->wandev.dev->flags & IFF_UP)){
-			
-			printk(KERN_INFO "%s: Interface %s up.\n",
-				card->devname,card->wandev.dev->name);
-			change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
-			clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
-			check_gateway=1;
-		}
-
-		if (chdlc_priv_area->route_status == ADD_ROUTE && 
-		    card->u.c.slarp_timer){ 
-
-			process_route(card);
-			check_gateway=1;
-		}
-
-		if (chdlc_priv_area->gateway && check_gateway)
-			add_gateway(card,dev);
-
-		break;
-	}	
-
-	clear_bit(POLL_CRIT,&card->wandev.critical);
-}
-
-/*============================================================
- * trigger_chdlc_poll
- *
- * Description:
- * 	Add a chdlc_poll() work entry into the keventd work queue
- *      for a specific dlci/interface.  This will kick
- *      the fr_poll() routine at a later time. 
- *
- * Usage:
- * 	Interrupts use this to defer a taks to 
- *      a polling routine.
- *
- */	
-static void trigger_chdlc_poll(struct net_device *dev)
-{
-	chdlc_private_area_t *chdlc_priv_area;
-	sdla_t *card;
-
-	if (!dev)
-		return;
-	
-	if ((chdlc_priv_area = dev->priv)==NULL)
-		return;
-
-	card = chdlc_priv_area->card;
-	
-	if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
-		return;
-	}
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		return; 
-	}
-	schedule_work(&chdlc_priv_area->poll_work);
-}
-
-
-static void chdlc_poll_delay (unsigned long dev_ptr)
-{
-	struct net_device *dev = (struct net_device *)dev_ptr;
-	trigger_chdlc_poll(dev);
-}
-
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
-	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-        if (card->next){
-        	spin_lock(&card->next->wandev.lock);
-	}
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
-        if (card->next){
-        	spin_unlock(&card->next->wandev.lock);
-        }
-        spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-//*********** TTY SECTION ****************
-
-static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
-{
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
-	chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
-}
-
-static void wanpipe_tty_trigger_poll(sdla_t *card)
-{
-	schedule_work(&card->tty_work);
-}
-
-static void tty_poll_work (void* data)
-{
-	sdla_t *card = (sdla_t*)data;
-	struct tty_struct *tty;
-
-	if ((tty=card->tty)==NULL)
-		return;
-	
-	tty_wakeup(tty);
-#if defined(SERIAL_HAVE_POLL_WAIT)
-	wake_up_interruptible(&tty->poll_wait);
-#endif	
-	return;
-}
-
-static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp)
-{
-	sdla_t *card;
-	unsigned long smp_flags;
-	
-	if (!tty || !tty->driver_data){
-		return;
-	}
-	
-	card = (sdla_t*)tty->driver_data;
-	
-	if (!card)
-		return;
-
-	printk(KERN_INFO "%s: Closing TTY Driver!\n",
-			card->devname);
-
-	/* Sanity Check */
-	if (!card->tty_open)
-		return;
-	
-	wanpipe_close(card);
-	if (--card->tty_open == 0){
-
-		lock_adapter_irq(&card->wandev.lock,&smp_flags);	
-		card->tty=NULL;
-		chdlc_disable_comm_shutdown(card);
-		unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
-		kfree(card->tty_buf);
-		card->tty_buf = NULL;			
-		kfree(card->tty_rx);
-		card->tty_rx = NULL;
-	}
-	return;
-}
-static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
-{
-	unsigned long smp_flags;
-	sdla_t *card;
-	
-	if (!tty){
-		return -ENODEV;
-	}
-	
-	if (!tty->driver_data){
-		int port;
-		port = tty->index;
-		if ((port < 0) || (port >= NR_PORTS)) 
-			return -ENODEV;
-		
-		tty->driver_data = WAN_CARD(port);
-		if (!tty->driver_data)
-			return -ENODEV;
-	}
-
-	card = (sdla_t*)tty->driver_data;
-
-	if (!card){
-		lock_adapter_irq(&card->wandev.lock,&smp_flags);	
-		card->tty=NULL;
-		unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-		return -ENODEV;
-	}
-
-	printk(KERN_INFO "%s: Opening TTY Driver!\n",
-			card->devname);
-
-	if (card->tty_open == 0){
-		lock_adapter_irq(&card->wandev.lock,&smp_flags);	
-		card->tty=tty;
-		unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-
-		if (!card->tty_buf){
-			card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
-			if (!card->tty_buf){
-				card->tty_buf=NULL;
-				card->tty=NULL;
-				return -ENOMEM;	
-			}
-		}
-
-		if (!card->tty_rx){
-			card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
-			if (!card->tty_rx){
-				/* Free the buffer above */
-				kfree(card->tty_buf);
-				card->tty_buf=NULL;
-				card->tty=NULL;
-				return -ENOMEM;	
-			}
-		}
-	}
-
-	++card->tty_open;
-	wanpipe_open(card);
-	return 0;
-}
-
-static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
-	unsigned long smp_flags=0;
-	sdla_t *card=NULL;
-
-	if (!tty){
-		dbg_printk(KERN_INFO "NO TTY in Write\n");
-		return -ENODEV;
-	}
-
-	card = (sdla_t *)tty->driver_data;
-			
-	if (!card){
-		dbg_printk(KERN_INFO "No Card in TTY Write\n");
-		return -ENODEV;
-	}	
-
-	if (count > card->wandev.mtu){
-		dbg_printk(KERN_INFO "Frame too big in Write %i Max: %i\n",
-				count,card->wandev.mtu);
-		return -EINVAL;
-	}
-	
-	if (card->wandev.state != WAN_CONNECTED){
-		dbg_printk(KERN_INFO "Card not connected in TTY Write\n");
-		return -EINVAL;
-	}
-
-	/* Lock the 508 Card: SMP is supported */
-      	if(card->hw.type != SDLA_S514){
-		s508_lock(card,&smp_flags);
-	} 
-	
-	if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
-		printk(KERN_INFO "%s: Critical in TTY Write\n",
-				card->devname);
-		
-		/* Lock the 508 Card: SMP is supported */
-		if(card->hw.type != SDLA_S514)
-			s508_unlock(card,&smp_flags);
-		
-		return -EINVAL; 
-	}
-	
- 	if (chdlc_send(card,(void*)buf,count)){
-		dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n",
-				card->devname);
-		clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
-		wanpipe_tty_trigger_tx_irq(card);
-		
-		if(card->hw.type != SDLA_S514)
-			s508_unlock(card,&smp_flags);
-		return 0;
-	}
-	dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count);
-	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-	
-	if(card->hw.type != SDLA_S514)
-		s508_unlock(card,&smp_flags);
-
-	return count;
-}
-
-static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
-{
-	unsigned offset=0;
-	unsigned olen=len;
-	char fp=0;
-	struct tty_struct *tty;
-	int i;
-	struct tty_ldisc *ld;
-	
-	if (!card->tty_open){
-		dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
-				card->devname);
-		return;
-	}
-	
-	if ((tty=card->tty) == NULL){
-		dbg_printk(KERN_INFO "%s: No TTY on receive\n",
-				card->devname);
-		return;
-	}
-	
-	if (!tty->driver_data){
-		dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receive\n",
-				card->devname);
-		return;
-	}
-	
-
-	if (card->u.c.async_mode){
-		if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){
-			if (net_ratelimit()){
-				printk(KERN_INFO 
-					"%s: Received packet size too big: %i bytes, Max: %i!\n",
-					card->devname,len,TTY_FLIPBUF_SIZE);
-			}
-			return;
-		}
-
-		
-		if((addr + len) > card->u.c.rx_top + 1) {
-			offset = card->u.c.rx_top - addr + 1;
-			
-			sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset);
-			
-			addr = card->u.c.rx_base;
-			len -= offset;
-			
-			tty->flip.char_buf_ptr+=offset;
-			tty->flip.count+=offset;
-			for (i=0;i<offset;i++){
-				*tty->flip.flag_buf_ptr = 0;
-				tty->flip.flag_buf_ptr++;
-			}
-		}
-		
-		sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len);
-			
-		tty->flip.char_buf_ptr+=len;
-		card->tty->flip.count+=len;
-		for (i=0;i<len;i++){
-			*tty->flip.flag_buf_ptr = 0;
-			tty->flip.flag_buf_ptr++;
-		}
-
-		tty->low_latency=1;
-		tty_flip_buffer_push(tty);
-	}else{
-		if (!card->tty_rx){	
-			if (net_ratelimit()){
-				printk(KERN_INFO 
-				"%s: Receive sync buffer not available!\n",
-				 card->devname);
-			}
-			return;
-		}
-	
-		if (len > TTY_CHDLC_MAX_MTU){
-			if (net_ratelimit()){
-				printk(KERN_INFO 
-				"%s: Received packet size too big: %i bytes, Max: %i!\n",
-					card->devname,len,TTY_FLIPBUF_SIZE);
-			}
-			return;
-		}
-
-		
-		if((addr + len) > card->u.c.rx_top + 1) {
-			offset = card->u.c.rx_top - addr + 1;
-			
-			sdla_peek(&card->hw, addr, card->tty_rx, offset);
-			
-			addr = card->u.c.rx_base;
-			len -= offset;
-		}
-		sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
-		ld = tty_ldisc_ref(tty);
-		if (ld) {
-			if (ld->receive_buf)
-				ld->receive_buf(tty,card->tty_rx,&fp,olen);
-			tty_ldisc_deref(ld);
-		}else{
-			if (net_ratelimit()){
-				printk(KERN_INFO 
-					"%s: NO TTY Sync line discipline!\n",
-					card->devname);
-			}
-		}
-	}
-
-	dbg_printk(KERN_INFO "%s: Received Data %i\n",card->devname,olen);
-	return;
-}
-
-#if 0
-static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-#endif
-
-static void wanpipe_tty_stop(struct tty_struct *tty)
-{
-	return;
-}
-
-static void wanpipe_tty_start(struct tty_struct *tty)
-{
-	return;
-}
-
-static int config_tty (sdla_t *card)
-{
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
-	/* Setup the Board for asynchronous mode */
-	if (card->u.c.async_mode){
-		
-		if (set_asy_config(card)) {
-			printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n",
-				card->devname);
-			return -EINVAL;
-		}
-	}else{
-		/* Setup the Board for CHDLC */
-		if (set_chdlc_config(card)) {
-			printk (KERN_INFO "%s: Failed CHDLC configuration!\n",
-				card->devname);
-			return -EINVAL;
-		}
-	}
-
-	/* Set interrupt mode and mask */
-        if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
-                		APP_INT_ON_GLOBAL_EXCEP_COND |
-                		APP_INT_ON_TX_FRAME |
-                		APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
-		printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
-				card->devname);
-		return -EINVAL;	
-        }
-	
-
-	/* Mask the Transmit and Timer interrupt */
-	flags->interrupt_info_struct.interrupt_permission &= 
-		~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-	
-	/* Enable communications */
- 	if (card->u.c.async_mode){
-		if (asy_comm_enable(card) != 0) {
-			printk(KERN_INFO "%s: Failed to enable async commnunication!\n",
-					card->devname);
-			flags->interrupt_info_struct.interrupt_permission = 0;
-			card->u.c.comm_enabled=0;
-			chdlc_set_intr_mode(card,0);
-			return -EINVAL;
-		}
-        }else{ 
-		if (chdlc_comm_enable(card) != 0) {
-			printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
-					card->devname);
-			flags->interrupt_info_struct.interrupt_permission = 0;
-			card->u.c.comm_enabled=0;
-			chdlc_set_intr_mode(card,0);
-			return -EINVAL;
-		}
-	}
-
-	/* Initialize Rx/Tx buffer control fields */
-	init_chdlc_tx_rx_buff(card);
-	port_set_state(card, WAN_CONNECTING);
-	return 0; 
-}
-
-
-static int change_speed(sdla_t *card, struct tty_struct *tty,
-			 struct termios *old_termios)
-{
-	int	baud, ret=0;
-	unsigned cflag; 
-	int	dbits,sbits,parity,handshaking;
-
-	cflag = tty->termios->c_cflag;
-
-	/* There is always one stop bit */
-	sbits=WANOPT_ONE;
-	
-	/* Parity is defaulted to NONE */
-	parity = WANOPT_NONE;
-
-	handshaking=0;
-	
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	      case CS5: dbits = 5; break;
-	      case CS6: dbits = 6; break;
-	      case CS7: dbits = 7; break;
-	      case CS8: dbits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  dbits = 8; break;
-	}
-	
-	/* One more stop bit should be supported, thus increment
-	 * the number of stop bits Max=2 */
-	if (cflag & CSTOPB) {
-		sbits = WANOPT_TWO;
-	}
-	if (cflag & PARENB) {
-		parity = WANOPT_EVEN;
-	}
-	if (cflag & PARODD){
-		parity = WANOPT_ODD;
-	}
-
-	/* Determine divisor based on baud rate */
-	baud = tty_get_baud_rate(tty);
-
-	if (!baud)
-		baud = 9600;	/* B0 transition handled in rs_set_termios */
-
-	if (cflag & CRTSCTS) {
-		handshaking|=ASY_RTS_HS_FOR_RX;
-	}
-	
-	if (I_IGNPAR(tty))
-		parity = WANOPT_NONE;
-
-	if (I_IXOFF(tty)){
-		handshaking|=ASY_XON_XOFF_HS_FOR_RX;
-		handshaking|=ASY_XON_XOFF_HS_FOR_TX;
-	}
-
-	if (I_IXON(tty)){
-		handshaking|=ASY_XON_XOFF_HS_FOR_RX;
-		handshaking|=ASY_XON_XOFF_HS_FOR_TX;
-	}
-
-	if (card->u.c.async_mode){
-		if (card->wandev.bps != baud)
-			ret=1;
-		card->wandev.bps = baud;
-	}
-
-	if (card->u.c.async_mode){
-		if (card->u.c.protocol_options != handshaking)
-			ret=1;
-		card->u.c.protocol_options = handshaking;
-
-		if (card->u.c.tx_bits_per_char != dbits)
-			ret=1;
-		card->u.c.tx_bits_per_char = dbits;
-
-		if (card->u.c.rx_bits_per_char != dbits)
-			ret=1;
-		card->u.c.rx_bits_per_char = dbits;
-		
-		if (card->u.c.stop_bits != sbits)
-			ret=1;
-		card->u.c.stop_bits = sbits;
-
-		if (card->u.c.parity != parity)
-			ret=1;
-		card->u.c.parity = parity;	
-
-		card->u.c.break_timer = 50;
-		card->u.c.inter_char_timer = 10;
-		card->u.c.rx_complete_length = 100;
-		card->u.c.xon_char = 0xFE;
-	}else{
-		card->u.c.protocol_options = HDLC_STREAMING_MODE;
-	}
-	
-	return ret;
-}
-
-	
-static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-	sdla_t *card;
-	int err=1;
-
-	if (!tty){
-		return;
-	}
-
-	card = (sdla_t *)tty->driver_data;
-			
-	if (!card)
-		return;
-
-	if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){
-		unsigned long smp_flags;
-		
-		if (card->u.c.comm_enabled){
-			lock_adapter_irq(&card->wandev.lock,&smp_flags);
-			chdlc_disable_comm_shutdown(card);
-			unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-		}
-		lock_adapter_irq(&card->wandev.lock,&smp_flags);
-		err = config_tty(card);
-		unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-		if (card->u.c.async_mode){
-			printk(KERN_INFO "%s: TTY Async Configuration:\n"
-				 "   Baud        =%i\n"
-				 "   Handshaking =%s\n"
-				 "   Tx Dbits    =%i\n"
-				 "   Rx Dbits    =%i\n"
-				 "   Parity      =%s\n"
-				 "   Stop Bits   =%i\n",
-				 card->devname,
-				 card->wandev.bps,
-				 opt_decode[card->u.c.protocol_options],
-				 card->u.c.tx_bits_per_char,
-				 card->u.c.rx_bits_per_char,
-				 p_decode[card->u.c.parity] ,
-				 card->u.c.stop_bits);
-		}else{
-			printk(KERN_INFO "%s: TTY Sync Configuration:\n"
-				 "   Baud        =%i\n"
-				 "   Protocol    =HDLC_STREAMING\n",
-				 card->devname,card->wandev.bps);
-		}
-		if (!err){
-			port_set_state(card,WAN_CONNECTED);
-		}else{
-			port_set_state(card,WAN_DISCONNECTED);
-		}
-	}
-	return;
-}
-
-static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	sdla_t *card;
-	unsigned long smp_flags=0;
-
-	if (!tty){
-		return;
-	}
-	
-	card = (sdla_t *)tty->driver_data;
-			
-	if (!card)
-		return;
-
-	if (card->wandev.state != WAN_CONNECTED)
-		return;
-
-	if(card->hw.type != SDLA_S514)
-		s508_lock(card,&smp_flags);
-	
-	if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
-		
-		wanpipe_tty_trigger_tx_irq(card);
-
-		if(card->hw.type != SDLA_S514)
-			s508_unlock(card,&smp_flags);
-		return;
-	}
-
-	if (chdlc_send(card,(void*)&ch,1)){
-		wanpipe_tty_trigger_tx_irq(card);
-		dbg_printk("%s: Failed to TX char!\n",card->devname);
-	}
-	
-	dbg_printk("%s: Char TX OK\n",card->devname);
-	
-	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-	
-	if(card->hw.type != SDLA_S514)
-		s508_unlock(card,&smp_flags);
-	
-	return;
-}
-
-static void wanpipe_tty_flush_chars(struct tty_struct *tty)
-{
-	return;
-}
-
-static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
-{
-	if (!tty)
-		return;
-	
-#if defined(SERIAL_HAVE_POLL_WAIT)
-	wake_up_interruptible(&tty->poll_wait);
-#endif
-	tty_wakeup(tty);
-	return;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch)
-{
-	return;
-}
-
-
-static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	return 0;
-}
-
-
-static int wanpipe_tty_write_room(struct tty_struct *tty)
-{
-	sdla_t *card;
-
-	printk(KERN_INFO "TTY Write Room\n");
-	
-	if (!tty){
-		return 0;
-	}
-
-	card = (sdla_t *)tty->driver_data;
-	if (!card)
-		return 0;
-
-	if (card->wandev.state != WAN_CONNECTED)
-		return 0;
-	
-	return SEC_MAX_NO_DATA_BYTES_IN_FRAME;
-}
-
-
-static int set_modem_status(sdla_t *card, unsigned char data)
-{
-	CHDLC_MAILBOX_STRUCT *mb = card->mbox;
-	int err;
-
-	mb->buffer_length=1;
-	mb->command=SET_MODEM_STATUS;
-	mb->data[0]=data;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK) 
-		chdlc_error (card, err, mb);
-	
-	return err;
-}
-
-static void wanpipe_tty_hangup(struct tty_struct *tty)
-{
-	sdla_t *card;
-	unsigned long smp_flags;
-
-	printk(KERN_INFO "TTY Hangup!\n");
-	
-	if (!tty){
-		return;
-	}
-
-	card = (sdla_t *)tty->driver_data;
-	if (!card)
-		return;
-
-	lock_adapter_irq(&card->wandev.lock,&smp_flags);
-	set_modem_status(card,0);
-	unlock_adapter_irq(&card->wandev.lock,&smp_flags);
-	return;
-}
-
-static void wanpipe_tty_break(struct tty_struct *tty, int break_state)
-{
-	return;
-}
-
-static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	return;
-}
-
-static void wanpipe_tty_throttle(struct tty_struct * tty)
-{
-	return;
-}
-
-static void wanpipe_tty_unthrottle(struct tty_struct * tty)
-{
-	return;
-}
-
-int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	return 0;
-}
-
-/*
- * The serial driver boot-time initialization code!
- */
-int wanpipe_tty_init(sdla_t *card)
-{
-	struct serial_state * state;
-	
-	/* Initialize the tty_driver structure */
-
-	if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){
-		printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %i\n",
-				card->devname,card->tty_minor);
-		return -EINVAL;
-	}
-
-	if (WAN_CARD(card->tty_minor)){
-		printk(KERN_INFO "%s: TTY Minor %i, already in use\n",
-				card->devname,card->tty_minor);
-		return -EBUSY;
-	}
-
-	if (tty_init_cnt==0){
-		
-		printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%i\n",
-				card->devname,
-				card->u.c.async_mode ? "ASYNC" : "SYNC",
-				WAN_TTY_MAJOR,MIN_PORT,MAX_PORT);
-		
-		tty_driver_mode = card->u.c.async_mode;
-		
-		memset(&serial_driver, 0, sizeof(struct tty_driver));
-		serial_driver.magic = TTY_DRIVER_MAGIC;
-		serial_driver.owner = THIS_MODULE;
-		serial_driver.driver_name = "wanpipe_tty"; 
-		serial_driver.name = "ttyW";
-		serial_driver.major = WAN_TTY_MAJOR;
-		serial_driver.minor_start = WAN_TTY_MINOR;
-		serial_driver.num = NR_PORTS; 
-		serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-		serial_driver.subtype = SERIAL_TYPE_NORMAL;
-		
-		serial_driver.init_termios = tty_std_termios;
-		serial_driver.init_termios.c_cflag =
-			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-		serial_driver.flags = TTY_DRIVER_REAL_RAW;
-		
-		serial_driver.refcount = 1;	/* !@!@^#^&!! */
-
-		serial_driver.open = wanpipe_tty_open;
-		serial_driver.close = wanpipe_tty_close;
-		serial_driver.write = wanpipe_tty_write;
-		
-		serial_driver.put_char = wanpipe_tty_put_char;
-		serial_driver.flush_chars = wanpipe_tty_flush_chars;
-		serial_driver.write_room = wanpipe_tty_write_room;
-		serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer;
-		serial_driver.flush_buffer = wanpipe_tty_flush_buffer;
-		//serial_driver.ioctl = wanpipe_tty_ioctl;
-		serial_driver.throttle = wanpipe_tty_throttle;
-		serial_driver.unthrottle = wanpipe_tty_unthrottle;
-		serial_driver.send_xchar = wanpipe_tty_send_xchar;
-		serial_driver.set_termios = wanpipe_tty_set_termios;
-		serial_driver.stop = wanpipe_tty_stop;
-		serial_driver.start = wanpipe_tty_start;
-		serial_driver.hangup = wanpipe_tty_hangup;
-		serial_driver.break_ctl = wanpipe_tty_break;
-		serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent;
-		serial_driver.read_proc = wanpipe_tty_read_proc;
-		
-		if (tty_register_driver(&serial_driver)){
-			printk(KERN_INFO "%s: Failed to register serial driver!\n",
-					card->devname);
-		}
-	}
-
-
-	/* The subsequent ports must comply to the initial configuration */
-	if (tty_driver_mode != card->u.c.async_mode){
-		printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!\n",
-				card->devname);
-		printk(KERN_INFO "%s: The TTY driver is configured for %s!\n",
-				card->devname, tty_driver_mode ? "ASYNC" : "SYNC");
-		return -EINVAL;
-	}
-	
-	tty_init_cnt++;
-	
-	printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %i\n",
-			card->devname,
-			tty_driver_mode ? "ASYNC" : "SYNC",
-			card->tty_minor);
-	
-	tty_card_map[card->tty_minor] = card;
-	state = &rs_table[card->tty_minor];
-	
-	state->magic = SSTATE_MAGIC;
-	state->line = 0;
-	state->type = PORT_UNKNOWN;
-	state->custom_divisor = 0;
-	state->close_delay = 5*HZ/10;
-	state->closing_wait = 30*HZ;
-	state->icount.cts = state->icount.dsr = 
-		state->icount.rng = state->icount.dcd = 0;
-	state->icount.rx = state->icount.tx = 0;
-	state->icount.frame = state->icount.parity = 0;
-	state->icount.overrun = state->icount.brk = 0;
-	state->irq = card->wandev.irq; 
-
-	INIT_WORK(&card->tty_work, tty_poll_work, (void*)card);
-	return 0;
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
deleted file mode 100644
index 7f1ce9d..0000000
--- a/drivers/net/wan/sdla_fr.c
+++ /dev/null
@@ -1,5061 +0,0 @@
-/*****************************************************************************
-* sdla_fr.c	WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module.
-*
-* Author(s):	Nenad Corbic  <ncorbic@sangoma.com>
-*		Gideon Hack
-*
-* Copyright:	(c) 1995-2001 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Nov 23, 2000  Nenad Corbic    o Added support for 2.4.X kernels
-* Nov 15, 2000  David Rokavarg  
-*               Nenad Corbic	o Added frame relay bridging support.
-* 				  Original code from Mark Wells and Kristian Hoffmann has
-* 				  been integrated into the frame relay driver.
-* Nov 13, 2000  Nenad Corbic    o Added true interface type encoding option.
-* 				  Tcpdump doesn't support Frame Relay inteface
-* 				  types, to fix this true type option will set
-* 				  the interface type to RAW IP mode.
-* Nov 07, 2000  Nenad Corbic	o Added security features for UDP debugging:
-*                                 Deny all and specify allowed requests.
-* Nov 06, 2000  Nenad Corbic	o Wanpipe interfaces conform to raw packet interfaces.  
-*                                 Moved the if_header into the if_send() routine.
-*                                 The if_header() was breaking the libpcap 
-*                                 support. i.e. support for tcpdump, ethereal ...
-* Oct 12. 2000  Nenad Corbic    o Added error message in fr_configure
-* Jul 31, 2000  Nenad Corbic	o Fixed the Router UP Time.
-* Apr 28, 2000  Nenad Corbic	o Added the option to shutdown an interface
-*                                 when the channel gets disconnected.
-* Apr 28, 2000  Nenad Corbic 	o Added M.Grants patch: disallow duplicate
-*                                 interface setups. 
-* Apr 25, 2000  Nenad Corbic	o Added M.Grants patch: dynamically add/remove 
-*                                 new dlcis/interfaces.
-* Mar 23, 2000  Nenad Corbic 	o Improved task queue, bh handling.
-* Mar 16, 2000	Nenad Corbic	o Added Inverse ARP support
-* Mar 13, 2000  Nenad Corbic	o Added new socket API support.
-* Mar 06, 2000  Nenad Corbic	o Bug Fix: corrupted mbox recovery.
-* Feb 24, 2000  Nenad Corbic    o Fixed up FT1 UDP debugging problem.
-* Dev 15, 1999  Nenad Corbic    o Fixed up header files for 2.0.X kernels
-*
-* Nov 08, 1999  Nenad Corbic    o Combined all debug UDP calls into one function
-*                               o Removed the ARP support. This has to be done
-*                                 in the next version.
-*                               o Only a Node can implement NO signalling.
-*                                 Initialize DLCI during if_open() if NO 
-*				  signalling.
-*				o Took out IPX support, implement in next
-*                                 version
-* Sep 29, 1999  Nenad Corbic	o Added SMP support and changed the update
-*                                 function to use timer interrupt.
-*				o Fixed the CIR bug:  Set the value of BC
-*                                 to CIR when the CIR is enabled.
-*  				o Updated comments, statistics and tracing.
-* Jun 02, 1999	Gideon Hack	o Updated for S514 support.
-* Sep 18, 1998	Jaspreet Singh	o Updated for 2.2.X kernels.
-* Jul 31, 1998	Jaspreet Singh	o Removed wpf_poll routine.  The channel/DLCI 
-*				  status is received through an event interrupt.
-* Jul 08, 1998	David Fong	o Added inverse ARP support.
-* Mar 26, 1997	Jaspreet Singh	o Returning return codes for failed UDP cmds.
-* Jan 28, 1997	Jaspreet Singh  o Improved handling of inactive DLCIs.
-* Dec 30, 1997	Jaspreet Singh	o Replaced dev_tint() with mark_bh(NET_BH)
-* Dec 16, 1997	Jaspreet Singh	o Implemented Multiple IPX support.
-* Nov 26, 1997	Jaspreet Singh	o Improved load sharing with multiple boards
-*				o Added Cli() to protect enabling of interrupts
-*				  while polling is called.
-* Nov 24, 1997	Jaspreet Singh	o Added counters to avoid enabling of interrupts
-*				  when they have been disabled by another
-*				  interface or routine (eg. wpf_poll).
-* Nov 06, 1997	Jaspreet Singh	o Added INTR_TEST_MODE to avoid polling	
-*				  routine disable interrupts during interrupt
-*				  testing.
-* Oct 20, 1997  Jaspreet Singh  o Added hooks in for Router UP time.
-* Oct 16, 1997  Jaspreet Singh  o The critical flag is used to maintain flow
-*                                 control by avoiding RACE conditions.  The
-*                                 cli() and restore_flags() are taken out.
-*                                 The fr_channel structure is appended for 
-*                                 Driver Statistics.
-* Oct 15, 1997  Farhan Thawar    o updated if_send() and receive for IPX
-* Aug 29, 1997  Farhan Thawar    o Removed most of the cli() and sti()
-*                                o Abstracted the UDP management stuff
-*                                o Now use tbusy and critical more intelligently
-* Jul 21, 1997  Jaspreet Singh	 o Can configure T391, T392, N391, N392 & N393
-*				   through router.conf.
-*				 o Protected calls to sdla_peek() by adDing 
-*				   save_flags(), cli() and restore_flags().
-*				 o Added error message for Inactive DLCIs in
-*				   fr_event() and update_chan_state().
-*				 o Fixed freeing up of buffers using kfree() 
-*			           when packets are received.
-* Jul 07, 1997	Jaspreet Singh	 o Added configurable TTL for UDP packets 
-*				 o Added ability to discard multicast and 
-*				   broadcast source addressed packets
-* Jun 27, 1997	Jaspreet Singh	 o Added FT1 monitor capabilities 
-*				   New case (0x44) statement in if_send routine 
-*				   Added a global variable rCount to keep track
-*			 	   of FT1 status enabled on the board.
-* May 29, 1997	Jaspreet Singh	 o Fixed major Flow Control Problem
-*				   With multiple boards a problem was seen where
-*				   the second board always stopped transmitting
-*				   packet after running for a while. The code
-*				   got into a stage where the interrupts were
-*				   disabled and dev->tbusy was set to 1.
-*                  		   This caused the If_send() routine to get into
-*                                  the if clause for it(0,dev->tbusy) 
-*				   forever.
-*				   The code got into this stage due to an 
-*				   interrupt occurring within the if clause for 
-*				   set_bit(0,dev->tbusy).  Since an interrupt 
-*				   disables furhter transmit interrupt and 
-* 				   makes dev->tbusy = 0, this effect was undone 
-*                                  by making dev->tbusy = 1 in the if clause.
-*				   The Fix checks to see if Transmit interrupts
-*				   are disabled then do not make dev->tbusy = 1
-* 	   			   Introduced a global variable: int_occur and
-*				   added tx_int_enabled in the wan_device 
-*				   structure.	
-* May 21, 1997  Jaspreet Singh   o Fixed UDP Management for multiple
-*                                  boards.
-*
-* Apr 25, 1997  Farhan Thawar    o added UDP Management stuff
-*                                o fixed bug in if_send() and tx_intr() to
-*                                  sleep and wakeup all devices
-* Mar 11, 1997  Farhan Thawar   Version 3.1.1
-*                                o fixed (+1) bug in fr508_rx_intr()
-*                                o changed if_send() to return 0 if
-*                                  wandev.critical() is true
-*                                o free socket buffer in if_send() if
-*                                  returning 0 
-*                                o added tx_intr() routine
-* Jan 30, 1997	Gene Kozin	Version 3.1.0
-*				 o implemented exec() entry point
-*				 o fixed a bug causing driver configured as
-*				   a FR switch to be stuck in WAN_
-*				   mode
-* Jan 02, 1997	Gene Kozin	Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/if_arp.h>	/* ARPHRD_* defines */
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <asm/io.h>		/* for inb(), outb(), etc. */
-#include <linux/time.h>	 	/* for do_gettimeofday */	
-#include <linux/in.h>		/* sockaddr_in */
-#include <linux/jiffies.h>	/* time_after() macro */
-#include <asm/errno.h>
-
-#include <linux/ip.h>
-#include <linux/if.h>
-
-#include <linux/if_wanpipe_common.h>	/* Wanpipe Socket */
-#include <linux/if_wanpipe.h>	
-
-#include <linux/sdla_fr.h>		/* frame relay firmware API definitions */
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <net/route.h>          	/* Dynamic Route Creation */
-#include <linux/etherdevice.h>		/* eth_type_trans() used for bridging */
-#include <linux/random.h>
-
-/****** Defines & Macros ****************************************************/
-
-#define	MAX_CMD_RETRY	10		/* max number of firmware retries */
-
-#define	FR_HEADER_LEN	8		/* max encapsulation header size */
-#define	FR_CHANNEL_MTU	1500		/* unfragmented logical channel MTU */
-
-/* Q.922 frame types */
-#define	Q922_UI		0x03		/* Unnumbered Info frame */
-#define	Q922_XID	0xAF		
-
-/* DLCI configured or not */
-#define DLCI_NOT_CONFIGURED	0x00
-#define DLCI_CONFIG_PENDING	0x01
-#define DLCI_CONFIGURED		0x02
-
-/* CIR enabled or not */
-#define CIR_ENABLED	0x00
-#define CIR_DISABLED	0x01
-
-#define FRAME_RELAY_API 1
-#define MAX_BH_BUFF	10
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
- 
-/****** Data Structures *****************************************************/
-
-/* This is an extention of the 'struct device' we create for each network
- * interface to keep the rest of channel-specific data.
- */
-typedef struct fr_channel
-{
-	wanpipe_common_t common;
-	char name[WAN_IFNAME_SZ+1];	/* interface name, ASCIIZ */
-	unsigned dlci_configured  ;	/* check whether configured or not */
-	unsigned cir_status;		/* check whether CIR enabled or not */
-	unsigned dlci;			/* logical channel number */
-	unsigned cir;			/* committed information rate */
-	unsigned bc;			/* committed burst size */
-	unsigned be;			/* excess burst size */
-	unsigned mc;			/* multicast support on or off */
-	unsigned tx_int_status;		/* Transmit Interrupt Status */	
-	unsigned short pkt_length;	/* Packet Length */
-	unsigned long router_start_time;/* Router start time in seconds */
-	unsigned long tick_counter;	/* counter for transmit time out */
-	char dev_pending_devtint;	/* interface pending dev_tint() */
-	void *dlci_int_interface;	/* pointer to the DLCI Interface */ 
-	unsigned long IB_addr;		/* physical address of Interface Byte */
-	unsigned long state_tick;	/* time of the last state change */
-	unsigned char enable_IPX;	/* Enable/Disable the use of IPX */
-	unsigned long network_number;	/* Internal Network Number for IPX*/
-	sdla_t *card;			/* -> owner */
-	unsigned route_flag;		/* Add/Rem dest addr in route tables */
-	unsigned inarp;			/* Inverse Arp Request status */ 
-	long inarp_ready;		/* Ready to send requests */
-	int inarp_interval;		/* Time between InArp Requests */
-	unsigned long inarp_tick;	/* InArp jiffies tick counter */
-	long interface_down;		/* Bring interface down on disconnect */
-	struct net_device_stats ifstats;	/* interface statistics */
-	if_send_stat_t drvstats_if_send;
-        rx_intr_stat_t drvstats_rx_intr;
-        pipe_mgmt_stat_t drvstats_gen;
-	unsigned long router_up_time;
-
-	unsigned short transmit_length;
-	struct sk_buff *delay_skb;
-
-	bh_data_t *bh_head;	  	  /* Circular buffer for chdlc_bh */
-	unsigned long  tq_working;
-	volatile int  bh_write;
-	volatile int  bh_read;
-	atomic_t  bh_buff_used;
-
-	/* Polling task queue. Each interface
-         * has its own task queue, which is used
-         * to defer events from the interrupt */
-	struct work_struct fr_poll_work;
-	struct timer_list fr_arp_timer;
-
-	u32 ip_local;
-	u32 ip_remote;
-	long config_dlci;
-	long unconfig_dlci;
-
-	/* Whether this interface should be setup as a gateway.
-	 * Used by dynamic route setup code */
-	u8  gateway;
-
-	/* True interface type */
-	u8 true_if_encoding;
-	u8 fr_header[FR_HEADER_LEN];
-	char fr_header_len;
-
-} fr_channel_t;
-
-/* Route Flag options */
-#define NO_ROUTE	0x00
-#define ADD_ROUTE 	0x01
-#define ROUTE_ADDED	0x02
-#define REMOVE_ROUTE 	0x03
-#define ARP_REQ		0x04
-
-/* inarp options */
-#define INARP_NONE		0x00
-#define INARP_REQUEST		0x01
-#define INARP_CONFIGURED	0x02
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP   	0x01
-#define TMR_INT_ENABLED_UPDATE 	0x02
-#define TMR_INT_ENABLED_ARP	0x04
-#define TMR_INT_ENABLED_UPDATE_STATE 	0x08
-#define TMR_INT_ENABLED_CONFIG	0x10
-#define TMR_INT_ENABLED_UNCONFIG	0x20
-
-
-typedef struct dlci_status
-{
-	unsigned short dlci	PACKED;
-	unsigned char state	PACKED;
-} dlci_status_t;
-
-typedef struct dlci_IB_mapping
-{
-	unsigned short dlci		PACKED;
-	unsigned long  addr_value	PACKED;
-} dlci_IB_mapping_t;
-
-/* This structure is used for DLCI list Tx interrupt mode.  It is used to
-   enable interrupt bit and set the packet length for transmission
- */
-typedef struct fr_dlci_interface 
-{
-	unsigned char gen_interrupt	PACKED;
-	unsigned short packet_length	PACKED;
-	unsigned char reserved		PACKED;
-} fr_dlci_interface_t; 
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/* variable for keeping track of number of interrupts generated during 
- * interrupt test routine 
- */
-static int Intr_test_counter;
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
-		  wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-static void disable_comm (sdla_t *card);
-
-/* WANPIPE-specific entry points */
-static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr (struct sk_buff *skb);
-
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
-                                struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-
-/* Interrupt handlers */
-static void fr_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void tx_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-static void spur_intr(sdla_t *card);
-
-/* Frame relay firmware interface functions */
-static int fr_read_version(sdla_t *card, char *str);
-static int fr_configure(sdla_t *card, fr_conf_t *conf);
-static int fr_dlci_configure(sdla_t *card, fr_dlc_conf_t *conf, unsigned dlci);
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan);
-static int fr_set_intr_mode (sdla_t *card, unsigned mode, unsigned mtu, unsigned short timeout);
-static int fr_comm_enable(sdla_t *card);
-static void fr_comm_disable(sdla_t *card);
-static int fr_get_err_stats(sdla_t *card);
-static int fr_get_stats(sdla_t *card);
-static int fr_add_dlci(sdla_t *card, int dlci);
-static int fr_activate_dlci(sdla_t *card, int dlci);
-static int fr_delete_dlci (sdla_t* card, int dlci);
-static int fr_issue_isf(sdla_t *card, int isf);
-static int fr_send(sdla_t *card, int dlci, unsigned char attr, int len,
-	void *buf);
-static int fr_send_data_header(sdla_t *card, int dlci, unsigned char attr, int len,
-	void *buf,unsigned char hdr_len);
-static unsigned int fr_send_hdr(sdla_t *card, int dlci, unsigned int offset);
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan);
-static void initialize_rx_tx_buffers (sdla_t *card);
-
-
-/* Firmware asynchronous event handlers */
-static int fr_event(sdla_t *card, int event, fr_mbox_t *mbox);
-static int fr_modem_failure(sdla_t *card, fr_mbox_t *mbox);
-static int fr_dlci_change(sdla_t *card, fr_mbox_t *mbox);
-
-/* Miscellaneous functions */
-static int update_chan_state(struct net_device *dev);
-static void set_chan_state(struct net_device *dev, int state);
-static struct net_device *find_channel(sdla_t *card, unsigned dlci);
-static int is_tx_ready(sdla_t *card, fr_channel_t *chan);
-static unsigned int dec_to_uint(unsigned char *str, int len);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-
-static int intr_test( sdla_t* card );
-static void init_chan_statistics( fr_channel_t* chan );
-static void init_global_statistics( sdla_t* card );
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan );
-static int setup_for_delayed_transmit(struct net_device* dev,
-				      struct sk_buff *skb);
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev);
-static int check_tx_status(sdla_t *card, struct net_device *dev);
-
-/* Frame Relay Socket API */
-static void trigger_fr_bh (fr_channel_t *);
-static void fr_bh(struct net_device *dev);
-static int fr_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-static void trigger_fr_poll(struct net_device *dev);
-static void fr_poll(struct net_device *dev);
-//static void add_gateway(struct net_device *dev);
-
-static void trigger_unconfig_fr(struct net_device *dev);
-static void unconfig_fr (sdla_t *);
-
-static void trigger_config_fr (sdla_t *);
-static void config_fr (sdla_t *);
-
-
-/* Inverse ARP and Dynamic routing functions */
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device *dev);
-int is_arp(void *buf);
-int send_inarp_request(sdla_t *card, struct net_device *dev);
-
-static void trigger_fr_arp(struct net_device *dev);
-static void fr_arp (unsigned long data);
-
-
-/* Udp management functions */
-static int process_udp_mgmt_pkt(sdla_t *card);
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card );
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
-                                struct sk_buff *skb, int dlci);
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket,
-	unsigned long network_number, unsigned char incoming);
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname,
-	unsigned char enable_IPX, unsigned long network_number);
-
-/* Lock Functions: SMP supported */
-void 	s508_s514_unlock(sdla_t *card, unsigned long *smp_flags);
-void 	s508_s514_lock(sdla_t *card, unsigned long *smp_flags);
-
-unsigned short calc_checksum (char *, int);
-static int setup_fr_header(struct sk_buff *skb,
-			   struct net_device* dev, char op_mode);
-
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Frame relay protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup.  At this
- * point adapter is completely initialized and firmware is running.
- *  o read firmware version (to make sure it's alive)
- *  o configure adapter
- *  o initialize protocol-specific fields of the adapter data space.
- *
- * Return:	0	o.k.
- *		< 0	failure.
- */
-int wpf_init(sdla_t *card, wandev_conf_t *conf)
-{
-
-	int err;
-	fr508_flags_t* flags;
-
-	union
-	{
-		char str[80];
-		fr_conf_t cfg;
-	} u;
-
-	fr_buf_info_t* buf_info;
-	int i;
-
-
-	printk(KERN_INFO "\n");
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_FR) {
-		
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-			card->devname, conf->config_id);
-		return -EINVAL;
-	
-	}
-
-	/* Initialize protocol-specific fields of adapter data space */
-	switch (card->hw.fwid) {
-	
-		case SFID_FR508:
-			card->mbox  = (void*)(card->hw.dpmbase + 
-					FR508_MBOX_OFFS);
-			card->flags = (void*)(card->hw.dpmbase + 
-					FR508_FLAG_OFFS);
-			if(card->hw.type == SDLA_S514) {
-				card->mbox += FR_MB_VECTOR;
-                                card->flags += FR_MB_VECTOR;
-			}
-                        card->isr = &fr_isr;
-			break;
-
-		default:
-			return -EINVAL;
-	}
-
-	flags = card->flags;
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-
-	if (fr_read_version(card, NULL) || fr_read_version(card, u.str))
-		return -EIO;
-
-	printk(KERN_INFO "%s: running frame relay firmware v%s\n",
-		card->devname, u.str);
-
-	/* Adjust configuration */
-	conf->mtu += FR_HEADER_LEN;
-	conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ?
-			min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) :
-                        FR_CHANNEL_MTU + FR_HEADER_LEN;
-     
-	conf->bps = min_t(unsigned int, conf->bps, 2048000);
-
-	/* Initialze the configuration structure sent to the board to zero */
-	memset(&u.cfg, 0, sizeof(u.cfg));
-
-	memset(card->u.f.dlci_to_dev_map, 0, sizeof(card->u.f.dlci_to_dev_map));
- 	
-	/* Configure adapter firmware */
-
-	u.cfg.mtu	= conf->mtu;
-	u.cfg.kbps	= conf->bps / 1000;
-
-    	u.cfg.cir_fwd = u.cfg.cir_bwd = 16;
-        u.cfg.bc_fwd  = u.cfg.bc_bwd = 16;
-	
-	u.cfg.options	= 0x0000;
-	printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname);
-	
-	switch (conf->u.fr.signalling) {
-
-		case WANOPT_FR_ANSI:
-			u.cfg.options = 0x0000; 
-			break;		
-	
-		case WANOPT_FR_Q933:	
-			u.cfg.options |= 0x0200; 
-			break;
-	
-		case WANOPT_FR_LMI:	
-			u.cfg.options |= 0x0400; 
-			break;
-
-		case WANOPT_NO:
-			u.cfg.options |= 0x0800; 
-			break;
-		default:
-			printk(KERN_INFO "%s: Illegal Signalling option\n",
-					card->wandev.name);
-			return -EINVAL;
-	}
-
-
-	card->wandev.signalling = conf->u.fr.signalling;
-
-	if (conf->station == WANOPT_CPE) {
-
-
-		if (conf->u.fr.signalling == WANOPT_NO){
-			printk(KERN_INFO 
-				"%s: ERROR - For NO signalling, station must be set to Node!",
-				 	 card->devname);
-			return -EINVAL;
-		}
-
-		u.cfg.station = 0;
-		u.cfg.options |= 0x8000;	/* auto config DLCI */
-		card->u.f.dlci_num  = 0;
-	
-	} else {
-
-		u.cfg.station = 1;	/* switch emulation mode */
-
-		/* For switch emulation we have to create a list of dlci(s)
-		 * that will be sent to be global SET_DLCI_CONFIGURATION 
-		 * command in fr_configure() routine. 
-		 */
-
-		card->u.f.dlci_num  = min_t(unsigned int, max_t(unsigned int, conf->u.fr.dlci_num, 1), 100);
-	
-		for ( i = 0; i < card->u.f.dlci_num; i++) {
-
-			card->u.f.node_dlci[i] = (unsigned short) 
-				conf->u.fr.dlci[i] ? conf->u.fr.dlci[i] : 16;
-	
-		}
-	}
-
-	if (conf->clocking == WANOPT_INTERNAL)
-		u.cfg.port |= 0x0001;
-
-	if (conf->interface == WANOPT_RS232)
-		u.cfg.port |= 0x0002;
-
-	if (conf->u.fr.t391)
-		u.cfg.t391 = min_t(unsigned int, conf->u.fr.t391, 30);
-	else
-		u.cfg.t391 = 5;
-
-	if (conf->u.fr.t392)
-		u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30);
-	else
-		u.cfg.t392 = 15;
-
-	if (conf->u.fr.n391)
-		u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255);
-	else
-		u.cfg.n391 = 2;
-
-	if (conf->u.fr.n392)
-		u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10);
-	else
-		u.cfg.n392 = 3;	
-
-	if (conf->u.fr.n393)
-		u.cfg.n393 = min_t(unsigned int, conf->u.fr.n393, 10);
-	else
-		u.cfg.n393 = 4;
-
-	if (fr_configure(card, &u.cfg))
-		return -EIO;
-
-	if (card->hw.type == SDLA_S514) {
-	
-                buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
-			FR508_RXBC_OFFS);
-
-                card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
-                card->u.f.rxmb_base =
-                        (void*)(buf_info->rse_base + card->hw.dpmbase); 
-
-                card->u.f.rxmb_last =
-                        (void*)(buf_info->rse_base +
-                        (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
-                        card->hw.dpmbase);
-	}else{	
-		buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
-		card->rxmb = (void*)(buf_info->rse_next -
-			FR_MB_VECTOR + card->hw.dpmbase);
-		
-		card->u.f.rxmb_base =
-			(void*)(buf_info->rse_base -
-			FR_MB_VECTOR + card->hw.dpmbase);
-		
-		card->u.f.rxmb_last =
-			(void*)(buf_info->rse_base +
-			(buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
-			FR_MB_VECTOR + card->hw.dpmbase);
-	}
-
-	card->u.f.rx_base = buf_info->buf_base;
-	card->u.f.rx_top  = buf_info->buf_top;
-
-	card->u.f.tx_interrupts_pending = 0;
-
-	card->wandev.mtu	= conf->mtu;
-	card->wandev.bps	= conf->bps;
-	card->wandev.interface	= conf->interface;
-	card->wandev.clocking	= conf->clocking;
-	card->wandev.station	= conf->station;
-	card->poll		= NULL; 
-	card->exec		= &wpf_exec;
-	card->wandev.update	= &update;
-	card->wandev.new_if	= &new_if;
-	card->wandev.del_if	= &del_if;
-	card->wandev.state	= WAN_DISCONNECTED;
-	card->wandev.ttl	= conf->ttl;
-        card->wandev.udp_port 	= conf->udp_port;       
-	card->disable_comm	= &disable_comm;	
-	card->u.f.arp_dev 	= NULL;
-
-	/* Intialize global statistics for a card */
-	init_global_statistics( card );
-
-        card->TracingEnabled          = 0;
-
-	/* Interrupt Test */
-	Intr_test_counter = 0;
-	card->intr_mode = INTR_TEST_MODE;
-	err = intr_test( card );
-
-	printk(KERN_INFO "%s: End of Interrupt Test rc=0x%x  count=%i\n",
-			card->devname,err,Intr_test_counter); 
-	
-	if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
-		printk(KERN_ERR "%s: Interrupt Test Failed, Counter: %i\n", 
-			card->devname, Intr_test_counter);
-		printk(KERN_ERR "Please choose another interrupt\n");
-		err = -EIO;
-		return err;
-	}
-
-	printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n",
-			card->devname, Intr_test_counter);
-
-
-	/* Apr 28 2000. Nenad Corbic
-	 * Enable commnunications here, not in if_open or new_if, since
-         * interfaces come down when the link is disconnected. 
-         */
-	 
-	/* If you enable comms and then set ints, you get a Tx int as you
-	 * perform the SET_INT_TRIGGERS command. So, we only set int
-	 * triggers and then adjust the interrupt mask (to disable Tx ints)
-	 * before enabling comms. 
-	 */	
-        if (fr_set_intr_mode(card, (FR_INTR_RXRDY | FR_INTR_TXRDY |
-		FR_INTR_DLC | FR_INTR_TIMER | FR_INTR_TX_MULT_DLCIs) ,
-		card->wandev.mtu, 0)) {
-		return -EIO;
-	}
-
-	flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER);
- 
-	if (fr_comm_enable(card)) {
-		return -EIO;
-	}	
-	wanpipe_set_state(card, WAN_CONNECTED);
-	spin_lock_init(&card->u.f.if_send_lock);
-	
-	printk(KERN_INFO "\n");
-
-        return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device* wandev)
-{
-	volatile sdla_t* card;
-	unsigned long timeout;
-	fr508_flags_t* flags;
-
-	/* sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-
-	if (wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-
-	card = wandev->private;
-	flags = card->flags;
-
-
-	card->u.f.update_comms_stats = 1;
-	card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
-	flags->imask |= FR_INTR_TIMER;
-       	timeout = jiffies;
-       	for(;;) {
-		if(card->u.f.update_comms_stats == 0)
-			break;
-                if (time_after(jiffies, timeout + 1 * HZ)){
-    			card->u.f.update_comms_stats = 0;
- 			return -EAGAIN;
-		}
-        }
-
-	return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return:	0	o.k.
- *		< 0	failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf)
-{
-	sdla_t* card = wandev->private;
-	fr_channel_t* chan;
-	int dlci = 0;
-	int err = 0;
-
-	
-	if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-		
-		printk(KERN_INFO "%s: Invalid interface name!\n",
-			card->devname);
-		return -EINVAL;
-	}
-
-	/* allocate and initialize private data */
-	chan = kmalloc(sizeof(fr_channel_t), GFP_KERNEL);
-
-	if (chan == NULL)
-		return -ENOMEM;
-
-	memset(chan, 0, sizeof(fr_channel_t));
-	strcpy(chan->name, conf->name);
-	chan->card = card;
-
-	/* verify media address */
-	if (isdigit(conf->addr[0])) {
-
-		dlci = dec_to_uint(conf->addr, 0);
-
-		if (dlci && (dlci <= HIGHEST_VALID_DLCI)) {
-		
-			chan->dlci = dlci;
-		
-		} else {
-		
-			printk(KERN_ERR
-				"%s: Invalid DLCI %u on interface %s!\n",
-				wandev->name, dlci, chan->name);
-			err = -EINVAL;
-		}
-
-	} else {
-		printk(KERN_ERR
-			"%s: Invalid media address on interface %s!\n",
-			wandev->name, chan->name);
-		err = -EINVAL;
-	}
-
-	if ((chan->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){
-		printk(KERN_INFO 
-			"%s: Enabling, true interface type encoding.\n",
-			card->devname);
-	}
-	
-
-
-    /* Setup wanpipe as a router (WANPIPE) even if it is
-	 * a bridged DLCI, or as an API 
-	 */
-        if (strcmp(conf->usedby, "WANPIPE")  == 0  || 
-	    strcmp(conf->usedby, "BRIDGE")   == 0  ||
-	    strcmp(conf->usedby, "BRIDGE_N") == 0){
-		
-		if(strcmp(conf->usedby, "WANPIPE") == 0){
-			chan->common.usedby = WANPIPE;
-			
-	                printk(KERN_INFO "%s: Running in WANPIPE mode.\n", 
-					card->devname);
-			
-		}else if(strcmp(conf->usedby, "BRIDGE") == 0){
-			
-			chan->common.usedby = BRIDGE;
-			
-			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", 
-					card->devname);
-		}else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){
-			
-			chan->common.usedby = BRIDGE_NODE;
-		
-			printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", 
-					card->devname);
-		}
-
-		if (!err){
-			/* Dynamic interface configuration option.
-			 * On disconnect, if the options is selected,
-			 * the interface will be brought down */
-			if (conf->if_down == WANOPT_YES){ 
-				set_bit(DYN_OPT_ON,&chan->interface_down);
-				printk(KERN_INFO 
-				    "%s: Dynamic interface configuration enabled.\n",
-					card->devname);
-			}
-		}
-
-        } else if(strcmp(conf->usedby, "API") == 0){
-
-                chan->common.usedby = API;
-                printk(KERN_INFO "%s: Running in API mode.\n",
-			wandev->name);
-        }
-
-	if (err) {
-		
-		kfree(chan);
-		return err;
-	}
-
-	/* place cir,be,bc and other channel specific information into the
-	 * chan structure 
-         */
-	if (conf->cir) {
-
-		chan->cir = max_t(unsigned int, 1,
-				min_t(unsigned int, conf->cir, 512));
-		chan->cir_status = CIR_ENABLED; 
-
-		
-		/* If CIR is enabled, force BC to equal CIR
-                 * this solves number of potential problems if CIR is 
-                 * set and BC is not 
-		 */
-		chan->bc = chan->cir;
-
-		if (conf->be){
-			chan->be = max_t(unsigned int,
-				       0, min_t(unsigned int, conf->be, 511));
-		}else{	
-			conf->be = 0;
-		}
-
-		printk (KERN_INFO "%s: CIR enabled for DLCI %i \n",
-				wandev->name,chan->dlci);
-		printk (KERN_INFO "%s:     CIR = %i ; BC = %i ; BE = %i\n",
-				wandev->name,chan->cir,chan->bc,chan->be);
-
-
-	}else{
-		chan->cir_status = CIR_DISABLED;
-		printk (KERN_INFO "%s: CIR disabled for DLCI %i\n",
-				wandev->name,chan->dlci);
-	}
-
-	chan->mc = conf->mc;
-
-	if (conf->inarp == WANOPT_YES){
-		printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname);
-		chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE;
-		chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10;
-	}else{
-		printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname);
-		chan->inarp = INARP_NONE;
-		chan->inarp_interval = 10;
-	}
-
-
-	chan->dlci_configured = DLCI_NOT_CONFIGURED;	
-
-
-	/*FIXME: IPX disabled in this WANPIPE version */
-	if (conf->enable_IPX == WANOPT_YES){
-		printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support IPX\n",
-				card->devname);
-		kfree(chan);
-		return -EINVAL;
-	}else{
-		chan->enable_IPX = WANOPT_NO;
-	}	
-
-	if (conf->network_number){
-		chan->network_number = conf->network_number;
-	}else{
-		chan->network_number = 0xDEADBEEF;
-	}
-
-	chan->route_flag = NO_ROUTE;
-	
-	init_chan_statistics(chan);
-
-	chan->transmit_length = 0;
-
-	/* prepare network device data space for registration */
-	strcpy(dev->name,chan->name);
-	
-	dev->init = &if_init;
-	dev->priv = chan;
-
-	/* Initialize FR Polling Task Queue
-         * We need a poll routine for each network
-         * interface. 
-         */
-	INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev);
-
-	init_timer(&chan->fr_arp_timer);
-	chan->fr_arp_timer.data=(unsigned long)dev;
-	chan->fr_arp_timer.function = fr_arp;
-
-	wandev->new_if_cnt++;
-
-	/* Tells us that if this interface is a
-         * gateway or not */
-	if ((chan->gateway = conf->gateway) == WANOPT_YES){
-		printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
-			card->devname,dev->name);
-	}
-
-	/* M. Grant Patch Apr 28 2000 
-         * Disallow duplicate dlci configurations. */
-	if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) {
-		kfree(chan);
-		return -EBUSY;
-	}
-
-	/* Configure this dlci at a later date, when
-         * the interface comes up. i.e. when if_open() 
-         * executes */
-	set_bit(0,&chan->config_dlci);
-	
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
-	fr_channel_t* chan = dev->priv;
-	unsigned long smp_flags=0;
-
-	/* This interface is dead, make sure the 
-	 * ARP timer is stopped */
-	del_timer(&chan->fr_arp_timer);
-	
-	/* If we are a NODE, we must unconfigure this DLCI
-	 * Trigger an unconfigure command that will
-	 * be executed in timer interrupt. We must wait
-	 * for the command to complete. */
-	trigger_unconfig_fr(dev);
-
-	lock_adapter_irq(&wandev->lock, &smp_flags);
-	wandev->new_if_cnt--;
-	unlock_adapter_irq(&wandev->lock, &smp_flags);
-
-	return 0;
-}
-
-
-/*=====================================================================
- * disable_comm
- *
- * Description:
- *	Disable communications.
- * 	This code runs in shutdown (sdlamain.c)
- *      under critical flag. Therefore it is not
- *      necessary to set a critical flag here 
- *
- * Usage:
- * 	Commnunications are disabled only on a card
- *      shutdown.
- */
-
-static void disable_comm (sdla_t *card)
-{
-	printk(KERN_INFO "%s: Disabling Communications!\n",
-			card->devname);
-	fr_comm_disable(card);
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err, len;
-	fr_cmd_t cmd;
-
-	if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
-		return -EFAULT;
-	
-	/* execute command */
-	do
-	{
-		memcpy(&mbox->cmd, &cmd, sizeof(cmd));
-		
-		if (cmd.length){
-			if( copy_from_user((void*)&mbox->data, u_data, cmd.length))
-				return -EFAULT;
-		}
-		
-		if (sdla_exec(mbox))
-			err = mbox->cmd.result;
-
-		else return -EIO;
-	
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	/* return result */
-	if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)))
-		return -EFAULT;
-
-	len = mbox->cmd.length;
-
-	if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len))
-		return -EFAULT;
-	return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration.  Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	struct wan_device* wandev = &card->wandev;
-
-	/* Initialize device driver entry points */
-	dev->open		= &if_open;
-	dev->stop		= &if_close;
-	dev->hard_header	= NULL;
-	dev->rebuild_header	= &if_rebuild_hdr;
-	dev->hard_start_xmit	= &if_send;
-	dev->get_stats		= &if_stats;
-	dev->tx_timeout		= &if_tx_timeout;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-	
-	if (chan->common.usedby == WANPIPE || chan->common.usedby == API){
-
-		/* Initialize media-specific parameters */
-		if (chan->true_if_encoding){
-			dev->type 		= ARPHRD_DLCI;  /* This breaks tcpdump */
-		}else{
-			dev->type		= ARPHRD_PPP; 	/* ARP h/w type */
-		}
-		
-		dev->flags		|= IFF_POINTOPOINT;
-		dev->flags		|= IFF_NOARP;
-
-		/* Enable Multicast addressing */
-		if (chan->mc == WANOPT_YES){
-			dev->flags 	|= IFF_MULTICAST;
-		}
-
-		dev->mtu		= wandev->mtu - FR_HEADER_LEN;
-		/* For an API, the maximum number of bytes that the stack will pass
-		   to the driver is (dev->mtu + dev->hard_header_len). So, adjust the
-		   mtu so that a frame of maximum size can be transmitted by the API. 
-		*/
-		if(chan->common.usedby == API) {
-			dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN);
-		}
-		
-		dev->hard_header_len	= FR_HEADER_LEN;/* media header length */
-		dev->addr_len		= 2; 		/* hardware address length */
-		*(unsigned short*)dev->dev_addr = htons(chan->dlci);
-
-		/* Set transmit buffer queue length */
-        	dev->tx_queue_len = 100;
-
-	}else{
-
-		/* Setup the interface for Bridging */
-		int hw_addr=0;
-		ether_setup(dev);
-		
-		/* Use a random number to generate the MAC address */
-		memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6);
-		get_random_bytes(&hw_addr, sizeof(hw_addr));
-		*(int *)(dev->dev_addr + 2) += hw_addr;
-	}
-		
-	/* Initialize hardware parameters (just for reference) */
-	dev->irq	= wandev->irq;
-	dev->dma	= wandev->dma;
-	dev->base_addr	= wandev->ioport;
-	dev->mem_start	= wandev->maddr;
-	dev->mem_end	= wandev->maddr + wandev->msize - 1;
-	SET_MODULE_OWNER(dev);
-
-	return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o if this is the first open, then enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	int err = 0;
-	struct timeval tv;
-
-	if (netif_running(dev))
-		return -EBUSY;
-	
-	/* Initialize the task queue */
-	chan->tq_working=0;
-
-	INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev);
-
-	/* Allocate and initialize BH circular buffer */
-	chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC);
-	memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF));
-	atomic_set(&chan->bh_buff_used, 0);
-
-	netif_start_queue(dev);
-
-	wanpipe_open(card);
-	do_gettimeofday( &tv );
-	chan->router_start_time = tv.tv_sec;
-	
-	if (test_bit(0,&chan->config_dlci)){
-		trigger_config_fr (card);
-	}else if (chan->inarp == INARP_REQUEST){
-		trigger_fr_arp(dev);
-	}
-	
-	return err;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-
-	if (chan->inarp == INARP_CONFIGURED) {
-		chan->inarp = INARP_REQUEST;
-	}
-
-	netif_stop_queue(dev);
-	wanpipe_close(card);
-
-	return 0;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return:	1	physical address resolved.
- *		0	physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
-	struct net_device *dev = skb->dev;
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-
-	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
-		card->devname, dev->name);
-	return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
-    	fr_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-
-	/* If our device stays busy for at least 5 seconds then we will
-	 * kick start the device by making dev->tbusy = 0.  We expect
-	 * that our device never stays busy more than 5 seconds. So this                 
-	 * is only used as a last resort.
-	 */
-
-	chan->drvstats_if_send.if_send_tbusy++;
-	++chan->ifstats.collisions;
-
-	printk (KERN_INFO "%s: Transmit timed out on %s\n", 
-			card->devname, dev->name);
-	chan->drvstats_if_send.if_send_tbusy_timeout++;
-	netif_wake_queue (dev);
-
-}
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- *   transmit from overlapping.
- * o set critical flag when accessing board.
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return:	0	complete (socket buffer must be freed)
- *		non-0	packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- *    bottom half" (with interrupts enabled).
- * 
- * 2. Using netif_start_queue() and netif_stop_queue()
- *    will inhibit further transmit requests from the protocol stack 
- *    and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
-    	fr_channel_t* chan = dev->priv;
-    	sdla_t* card = chan->card;
-        int err;
-    	unsigned char *sendpacket;
-    	fr508_flags_t* adptr_flags = card->flags;
-	int udp_type;
-	long delay_tx_queued = 0;
-	unsigned long smp_flags=0;
-	unsigned char attr = 0;
-
-	chan->drvstats_if_send.if_send_entry++;
-
-	netif_stop_queue(dev);
-	
-        if (skb == NULL) {             
-		/* if we get here, some higher layer thinks we've missed an
-		 * tx-done interrupt.
-		 */
-		printk(KERN_INFO "%s: interface %s got kicked!\n", 
-			card->devname, dev->name);
-		chan->drvstats_if_send.if_send_skb_null ++;
-
-		netif_wake_queue(dev);
-		return 0;
-	}
-
-	/* If a peripheral task is running just drop packets */
-	if (test_bit(PERI_CRIT, &card->wandev.critical)){
-		
-		printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",
-				card->devname);
-		
-		dev_kfree_skb_any(skb);
-		netif_start_queue(dev);
-		return 0;
-	}
-
-	/* We must set the 'tbusy' flag if we already have a packet queued for
-	   transmission in the transmit interrupt handler. However, we must
-	   ensure that the transmit interrupt does not reset the 'tbusy' flag
-	   just before we set it, as this will result in a "transmit timeout".
-	*/
-	set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
-        if(chan->transmit_length) {
-		netif_stop_queue(dev);
-		chan->tick_counter = jiffies;
- 		clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
-		return 1;
-	}
-       	clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);
- 
-	/* Move the if_header() code to here. By inserting frame
-	 * relay header in if_header() we would break the
-	 * tcpdump and other packet sniffers */
-	chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby);
-	if (chan->fr_header_len < 0 ){
-		++chan->ifstats.tx_dropped;
-		++card->wandev.stats.tx_dropped;
-		
-		dev_kfree_skb_any(skb);
-		netif_start_queue(dev);	
-		return 0;
-	}
-
-	sendpacket = skb->data;
-
-	udp_type = udp_pkt_type(skb, card);
-
-        if(udp_type != UDP_INVALID_TYPE) {
-		if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb,
-                        chan->dlci)) {
-                        adptr_flags->imask |= FR_INTR_TIMER;
-                        if (udp_type == UDP_FPIPE_TYPE){
-                                chan->drvstats_if_send.
-					if_send_PIPE_request ++;
-			}
-                }
-		netif_start_queue(dev);
-		return 0;
-	}
-
-	//FIXME: can we do better than sendpacket[2]?
-  	if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) {
-		
-               	/* check to see if the source IP address is a broadcast or */
-                /* multicast IP address */
-                if(chk_bcast_mcast_addr(card, dev, skb)){
-            		++chan->ifstats.tx_dropped;
-			++card->wandev.stats.tx_dropped;
-                	dev_kfree_skb_any(skb);
-			netif_start_queue(dev);
-			return 0;
-		}
-	}
-
-	
-	/* Lock the S514/S508 card: SMP Supported */
-    	s508_s514_lock(card,&smp_flags);
-
-	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-		
-		chan->drvstats_if_send.if_send_critical_non_ISR ++;
-		chan->ifstats.tx_dropped ++;
-		printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n", 
-				card->devname);
-		goto if_send_start_and_exit;
-	}
-	
-	/* API packet check: minimum packet size must be greater than 
-	 * 16 byte API header */
-	if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) {
-		++chan->ifstats.tx_dropped;
-		++card->wandev.stats.tx_dropped;
-	    
-		
-		goto if_send_start_and_exit;
-
- 	}else{
-		/* During API transmission, get rid of the API header */
-		if (chan->common.usedby == API) {
-			api_tx_hdr_t* api_tx_hdr;
-			api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00];
-			attr = api_tx_hdr->attr;
-			skb_pull(skb,sizeof(api_tx_hdr_t));
-		}
-	}
-
-	if (card->wandev.state != WAN_CONNECTED) {
-		chan->drvstats_if_send.if_send_wan_disconnected ++;
-		++chan->ifstats.tx_dropped;
-        	++card->wandev.stats.tx_dropped;
-	
-	} else if (chan->common.state != WAN_CONNECTED) {
-		chan->drvstats_if_send.if_send_dlci_disconnected ++;
-
-		/* Update the DLCI state in timer interrupt */
-		card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE;	
-		adptr_flags->imask |= FR_INTR_TIMER;
-
-        	++chan->ifstats.tx_dropped;
-        	++card->wandev.stats.tx_dropped;
-		
-	} else if (!is_tx_ready(card, chan)) {
-		/* No tx buffers available, store for delayed transmit */
-		if (!setup_for_delayed_transmit(dev, skb)){
-			set_bit(1,&delay_tx_queued);
-		}
-		chan->drvstats_if_send.if_send_no_bfrs++;
-		
-	} else if (!skb->protocol) {
-		/* No protocols drop packet */
-		chan->drvstats_if_send.if_send_protocol_error ++;
-		++card->wandev.stats.tx_errors;
-	
-	} else if (test_bit(ARP_CRIT,&card->wandev.critical)){
-		/* We are trying to send an ARP Packet, block IP data until
-		 * ARP is sent */
-		++chan->ifstats.tx_dropped;
-        	++card->wandev.stats.tx_dropped;
-		
-	} else {
-		//FIXME: IPX is not implemented in this version of Frame Relay ?
-		if((chan->common.usedby == WANPIPE) &&
-		 	sendpacket[1] == 0x00 &&
-		    	sendpacket[2] == 0x80 &&
-		    	sendpacket[6] == 0x81 &&
-		    	sendpacket[7] == 0x37) {
-			
-			if( chan->enable_IPX ) {
-				switch_net_numbers(sendpacket, 
-						chan->network_number, 0);
-			} else {
-				//FIXME: Take this out when IPX is fixed 
-				printk(KERN_INFO 
-				"%s: WARNING: Unsupported IPX data in send, packet dropped\n",
-					card->devname);
-			}
-			
-		}else{
-        		err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len);
-			if (err) {
-				switch(err) {
-				case FRRES_CIR_OVERFLOW:
-				case FRRES_BUFFER_OVERFLOW:
-                			if (!setup_for_delayed_transmit(dev, skb)){
-						set_bit(1,&delay_tx_queued);
-					}
-           				chan->drvstats_if_send.
-						if_send_adptr_bfrs_full ++;
-					break;
-					
-				case FRRES_TOO_LONG:
-					if (net_ratelimit()){
-						printk(KERN_INFO 
-						"%s: Error: Frame too long, transmission failed %i\n",
-						 card->devname, (unsigned int)skb->len);
-					}
-					/* Drop down to default */
-				default:
-					chan->drvstats_if_send.
-						if_send_dlci_disconnected ++;
-        				++chan->ifstats.tx_dropped;
-        				++card->wandev.stats.tx_dropped;
-					break;
-				}
-			} else {
-				chan->drvstats_if_send.
-					if_send_bfr_passed_to_adptr++;
-				++chan->ifstats.tx_packets;
-				++card->wandev.stats.tx_packets;
-				
-                                chan->ifstats.tx_bytes += skb->len;
-                                card->wandev.stats.tx_bytes += skb->len;
-				dev->trans_start = jiffies;
-			}
-		}
-	}
-
-if_send_start_and_exit:
-
-	netif_start_queue(dev);
-	
-	/* If we queued the packet for transmission, we must not
-	 * deallocate it. The packet is unlinked from the IP stack
-	 * not copied. Therefore, we must keep the original packet */
-	if (!test_bit(1,&delay_tx_queued)) {
-                dev_kfree_skb_any(skb);
-	}else{
-		adptr_flags->imask |= FR_INTR_TXRDY;
-		card->u.f.tx_interrupts_pending ++;
-	}
-
-        clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
-
-	s508_s514_unlock(card,&smp_flags);
-
-	return 0;
-}
-
-
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- */
-static int setup_for_delayed_transmit(struct net_device* dev,
-				      struct sk_buff *skb)
-{
-        fr_channel_t* chan = dev->priv;
-        sdla_t* card = chan->card;
-        fr_dlci_interface_t* dlci_interface;
-	int len = skb->len;
-
-	/* Check that the dlci is properly configured,
-         * before using tx interrupt */
-	if (!chan->dlci_int_interface){
-		if (net_ratelimit()){ 
-			printk(KERN_INFO 
-				"%s: ERROR on DLCI %i: Not configured properly !\n",
-					card->devname, chan->dlci);
-			printk(KERN_INFO "%s: Please contact Sangoma Technologies\n",
-					card->devname);
-		}
-		return 1;
-	}
-		
-	dlci_interface = chan->dlci_int_interface;
-
-        if(chan->transmit_length) {
-                printk(KERN_INFO "%s: Big mess in setup_for_del...\n",
-				card->devname);
-                return 1;
-        }
-
-	if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) {
-		//FIXME: increment some statistic */
-		return 1;
-	}
-
-        chan->transmit_length = len;
-	chan->delay_skb = skb;
-        
-        dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
-        dlci_interface->packet_length = len;
-
-	/* Turn on TX interrupt at the end of if_send */
-	return 0;
-}
-
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- * Return 0 if not broadcast/multicast address, otherwise return 1.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
-                                struct sk_buff *skb)
-{
-        u32 src_ip_addr;
-        u32 broadcast_ip_addr = 0;
-        struct in_device *in_dev;
-        fr_channel_t* chan = dev->priv;
- 
-        /* read the IP source address from the outgoing packet */
-        src_ip_addr = *(u32 *)(skb->data + 14);
-
-        /* read the IP broadcast address for the device */
-        in_dev = dev->ip_ptr;
-        if(in_dev != NULL) {
-                struct in_ifaddr *ifa= in_dev->ifa_list;
-                if(ifa != NULL)
-                        broadcast_ip_addr = ifa->ifa_broadcast;
-                else
-                        return 0;
-        }
-
-        /* check if the IP Source Address is a Broadcast address */
-        if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
-                printk(KERN_INFO
-                        "%s: Broadcast Source Address silently discarded\n",
-                        card->devname);
-                return 1;
-        }
-
-        /* check if the IP Source Address is a Multicast address */
-        if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) &&
-                (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
-                printk(KERN_INFO
-                        "%s: Multicast Source Address silently discarded\n",
-                        card->devname);
-                return 1;
-        }
-
-        return 0;
-}
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len ) 
-{
-	unsigned short len, udp_length, temp, ip_length;
-	unsigned long ip_temp;
-	int even_bound = 0;
-
-  
-	fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data; 
-
-	/* Set length of packet */
-	len = //sizeof(fr_encap_hdr_t)+
-	      sizeof(ip_pkt_t)+ 
-	      sizeof(udp_pkt_t)+
-	      sizeof(wp_mgmt_t)+
-	      sizeof(cblock_t)+
-	      mbox_len;
- 
-
-	/* fill in UDP reply */
-	fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-  
-	/* fill in UDP length */
-	udp_length = sizeof(udp_pkt_t)+ 
-		     sizeof(wp_mgmt_t)+
-		     sizeof(cblock_t)+
-		     mbox_len; 
-
-
-	/* put it on an even boundary */
-	if ( udp_length & 0x0001 ) {
-		udp_length += 1;
-		len += 1;
-		even_bound = 1;
-	}
-
-	temp = (udp_length<<8)|(udp_length>>8);
-	fr_udp_pkt->udp_pkt.udp_length = temp;
-	 
-	/* swap UDP ports */
-	temp = fr_udp_pkt->udp_pkt.udp_src_port;
-	fr_udp_pkt->udp_pkt.udp_src_port = 
-			fr_udp_pkt->udp_pkt.udp_dst_port; 
-	fr_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
-	/* add UDP pseudo header */
-	temp = 0x1100;
-	*((unsigned short *)
-		(fr_udp_pkt->data+mbox_len+even_bound)) = temp;	
-	temp = (udp_length<<8)|(udp_length>>8);
-	*((unsigned short *)
-		(fr_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-		 
-	/* calculate UDP checksum */
-	fr_udp_pkt->udp_pkt.udp_checksum = 0;
-
-	fr_udp_pkt->udp_pkt.udp_checksum = 
-		calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/],
-			      udp_length+UDP_OFFSET);
-
-	/* fill in IP length */
-	ip_length = udp_length + sizeof(ip_pkt_t);
-	temp = (ip_length<<8)|(ip_length>>8);
-	fr_udp_pkt->ip_pkt.total_length = temp;
-  
-	/* swap IP addresses */
-	ip_temp = fr_udp_pkt->ip_pkt.ip_src_address;
-	fr_udp_pkt->ip_pkt.ip_src_address = 
-				fr_udp_pkt->ip_pkt.ip_dst_address;
-	fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-		 
-	/* fill in IP checksum */
-	fr_udp_pkt->ip_pkt.hdr_checksum = 0;
-	fr_udp_pkt->ip_pkt.hdr_checksum = 
-		calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0],
-		      	      sizeof(ip_pkt_t));
-
-	return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
-	unsigned short temp; 
-	unsigned long sum=0;
-	int i;
-
-	for( i = 0; i <len; i+=2 ) {
-		memcpy(&temp,&data[i],2);
-		sum += (unsigned long)temp;
-	}
-
-	while (sum >> 16 ) {
-		sum = (sum & 0xffffUL) + (sum >> 16);
-	}
-
-	temp = (unsigned short)sum;
-	temp = ~temp;
-
-	if( temp == 0 ) 
-		temp = 0xffff;
-
-	return temp;	
-}
-
-/*
-   If incoming is 0 (outgoing)- if the net numbers is ours make it 0
-   if incoming is 1 - if the net number is 0 make it ours 
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
-	unsigned long pnetwork_number;
-
-	pnetwork_number = (unsigned long)((sendpacket[14] << 24) + 
-			  (sendpacket[15] << 16) + (sendpacket[16] << 8) + 
-			  sendpacket[17]);
-
-	if (!incoming) {
-		/* If the destination network number is ours, make it 0 */
-		if( pnetwork_number == network_number) {
-			sendpacket[14] = sendpacket[15] = sendpacket[16] = 
-					 sendpacket[17] = 0x00;
-		}
-	} else {
-		/* If the incoming network is 0, make it ours */
-		if( pnetwork_number == 0) {
-			sendpacket[14] = (unsigned char)(network_number >> 24);
-			sendpacket[15] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[16] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[17] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-
-
-	pnetwork_number = (unsigned long)((sendpacket[26] << 24) + 
-			  (sendpacket[27] << 16) + (sendpacket[28] << 8) + 
-			  sendpacket[29]);
-
-	if( !incoming ) {
-		/* If the source network is ours, make it 0 */
-		if( pnetwork_number == network_number) {
-			sendpacket[26] = sendpacket[27] = sendpacket[28] = 
-					 sendpacket[29] = 0x00;
-		}
-	} else {
-		/* If the source network is 0, make it ours */
-		if( pnetwork_number == 0 ) {
-			sendpacket[26] = (unsigned char)(network_number >> 24);
-			sendpacket[27] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[28] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[29] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
-	fr_channel_t* chan = dev->priv;
-	
-	if(chan == NULL)
-		return NULL;
-
-	return &chan->ifstats;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * fr_isr:	S508 frame relay interrupt service routine.
- *
- * Description:
- *	Frame relay main interrupt service route. This
- *      function check the interrupt type and takes
- *      the appropriate action.
- */
-static void fr_isr (sdla_t* card)
-{
-	fr508_flags_t* flags = card->flags;
-	char *ptr = &flags->iflag;
-	int i,err;
-	fr_mbox_t* mbox = card->mbox;
-
-	/* This flag prevents nesting of interrupts.  See sdla_isr() routine
-         * in sdlamain.c.  */
-	card->in_isr = 1;
-	
-	++card->statistics.isr_entry;
-
-
-	/* All peripheral (configuraiton, re-configuration) events
-	 * take presidence over the ISR.  Thus, retrigger */
-	if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
-		++card->statistics.isr_already_critical;
-		goto fr_isr_exit;
-	}
-	
-        if(card->hw.type != SDLA_S514) {
-		if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-                        printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n",
-                                card->devname);
-			++card->statistics.isr_already_critical;
-			goto fr_isr_exit;
-		}
-	}
-
-	switch (flags->iflag) {
-
-                case FR_INTR_RXRDY:  /* receive interrupt */
-	    		++card->statistics.isr_rx;
-          		rx_intr(card);
-            		break;
-
-
-                case FR_INTR_TXRDY:  /* transmit interrupt */
-	    		++ card->statistics.isr_tx; 
-			tx_intr(card); 
-            		break;
-
-                case FR_INTR_READY:  	
-	    		Intr_test_counter++;
-			++card->statistics.isr_intr_test;
-	    		break;	
-
-                case FR_INTR_DLC: /* Event interrupt occurred */
-			mbox->cmd.command = FR_READ_STATUS;
-			mbox->cmd.length = 0;
-			err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-			if (err)
-				fr_event(card, err, mbox);
-			break;
-
-                case FR_INTR_TIMER:  /* Timer interrupt */
-			timer_intr(card);
-			break;
-	
-		default:
-	    		++card->statistics.isr_spurious;
-            		spur_intr(card);
-	    		printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n", 
-				card->devname, flags->iflag);
-	    
-			printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- 	    		for(i = 0; i < 8; i ++)
-				printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
-	   	 	printk(KERN_INFO "\n");	
-            
-			break;
-    	}
-
-fr_isr_exit:
-	
-	card->in_isr = 0;
-	flags->iflag = 0;
-	return;
-}
-
-
-
-/*===========================================================
- * rx_intr	Receive interrupt handler.
- *
- * Description
- * 	Upon receiveing an interrupt: 
- *	1. Check that the firmware is in sync with 
- *     	   the driver. 
- *      2. Find an appropriate network interface
- *         based on the received dlci number.
- *	3. Check that the netowrk interface exists
- *         and that it's setup properly.
- *	4. Copy the data into an skb buffer.
- *	5. Check the packet type and take
- *         appropriate acton: UPD, API, ARP or Data.
- */
-
-static void rx_intr (sdla_t* card)
-{
-	fr_rx_buf_ctl_t* frbuf = card->rxmb;
-	fr508_flags_t* flags = card->flags;
-	fr_channel_t* chan;
-	char *ptr = &flags->iflag;
-	struct sk_buff* skb;
-	struct net_device* dev;
-	void* buf;
-	unsigned dlci, len, offs, len_incl_hdr;
-	int i, udp_type;	
-
-
-	/* Check that firmware buffers are in sync */
-	if (frbuf->flag != 0x01) {
-
-		printk(KERN_INFO 
-			"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", 
-			card->devname, (unsigned)frbuf, frbuf->flag);
-      
-		printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- 		for(i = 0; i < 8; i ++)
-			printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
-		printk(KERN_INFO "\n");
-	
-		++card->statistics.rx_intr_corrupt_rx_bfr;
-
-		/* Bug Fix: Mar 6 2000
-                 * If we get a corrupted mailbox, it means that driver 
-                 * is out of sync with the firmware. There is no recovery.
-                 * If we don't turn off all interrupts for this card
-                 * the machine will crash. 
-                 */
-		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
-		printk(KERN_INFO "Please contact Sangoma Technologies !\n");
-		fr_set_intr_mode(card, 0, 0, 0);	
-		return;
-	}
-
-	len  = frbuf->length;
-	dlci = frbuf->dlci;
-	offs = frbuf->offset;
-
-	/* Find the network interface for this packet */
-	dev = find_channel(card, dlci);
-   
-
-	/* Check that the network interface is active and
-         * properly setup */
-	if (dev == NULL) {
-   		if( net_ratelimit()) { 
-			printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
-                                                card->devname, dlci);
-		}
-		++card->statistics.rx_intr_on_orphaned_DLCI; 
-		++card->wandev.stats.rx_dropped;
-		goto rx_done;
-	}
-
-	if ((chan = dev->priv) == NULL){
-		if( net_ratelimit()) { 
-			printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",
-                                                card->devname, dlci);
-		}
-		++card->statistics.rx_intr_on_orphaned_DLCI; 
-		++card->wandev.stats.rx_dropped;
-		goto rx_done;
-	}
-
-	skb = dev_alloc_skb(len); 
-
-	if (!netif_running(dev) || (skb == NULL)){
-
-		++chan->ifstats.rx_dropped;
-	
-		if(skb == NULL) {
-			if (net_ratelimit()) { 
-				printk(KERN_INFO 
-					"%s: no socket buffers available!\n", 
-						card->devname);
-			}
-			chan->drvstats_rx_intr.rx_intr_no_socket ++;
-		} 
-
-		if (!netif_running(dev)){
-			chan->drvstats_rx_intr.
-				rx_intr_dev_not_started ++;
-			if (skb){
-				dev_kfree_skb_any(skb);
-			}
-		}
-		goto rx_done;
-	}
-
-	/* Copy data from the board into the socket buffer */
-	if ((offs + len) > card->u.f.rx_top + 1) {
-		unsigned tmp = card->u.f.rx_top - offs + 1;
-
-		buf = skb_put(skb, tmp);
-		sdla_peek(&card->hw, offs, buf, tmp);
-		offs = card->u.f.rx_base;
-		len -= tmp;
-	}
-
-	buf = skb_put(skb, len);
-	sdla_peek(&card->hw, offs, buf, len);
-
-
-	/* We got the packet from the bard. 
-         * Check the packet type and take appropriate action */
-
-	udp_type = udp_pkt_type( skb, card );
-
-	if(udp_type != UDP_INVALID_TYPE) {
-
-		/* UDP Debug packet received, store the
-		 * packet and handle it in timer interrupt */
-
-		skb_pull(skb, 1); 
-		if (wanrouter_type_trans(skb, dev)){ 
-			if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){
-
-				flags->imask |= FR_INTR_TIMER;
-
-				if (udp_type == UDP_FPIPE_TYPE){
-					++chan->drvstats_rx_intr.rx_intr_PIPE_request;
-				}
-			}
-		}
-
-	}else if (chan->common.usedby == API) {
-
-		/* We are in API mode. 
-                 * Add an API header to the RAW packet
-                 * and queue it into a circular buffer.
-                 * Then kick the fr_bh() bottom half handler */
-
-		api_rx_hdr_t* api_rx_hdr;
-		chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++;
-		chan->ifstats.rx_packets ++;
-		card->wandev.stats.rx_packets ++;
-
-		chan->ifstats.rx_bytes += skb->len;
-		card->wandev.stats.rx_bytes += skb->len;
-
-		skb_push(skb, sizeof(api_rx_hdr_t));
-		api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];
-		api_rx_hdr->attr = frbuf->attr;
-		api_rx_hdr->time_stamp = frbuf->tmstamp;
-
-		skb->protocol = htons(ETH_P_IP);
-		skb->mac.raw  = skb->data;
-		skb->dev      = dev;
-		skb->pkt_type = WAN_PACKET_DATA;
-
-		bh_enqueue(dev, skb);
-
-		trigger_fr_bh(chan);
-
-	}else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){
-
-		//FIXME: Frame Relay IPX is not supported, Yet !
-		//if (chan->enable_IPX) {
-		//	fr_send(card, dlci, 0, skb->len,skb->data);
-		//}
-		dev_kfree_skb_any(skb);
-
-	} else if (is_arp(skb->data)) {
-
-		/* ARP support enabled Mar 16 2000 
-		 * Process incoming ARP reply/request, setup
-		 * dynamic routes. */ 
-
-		if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) {
-			if (net_ratelimit()){  
-				printk (KERN_INFO 
-				   "%s: Error processing ARP Packet.\n", 
-					card->devname);
-			}
-		}
-		dev_kfree_skb_any(skb);
-
-	} else if (skb->data[0] != 0x03) {
-
-		if (net_ratelimit()) { 
-			printk(KERN_INFO "%s: Non IETF packet discarded.\n", 
-				card->devname);
-		}
-		dev_kfree_skb_any(skb);
-
-	} else {
-
-		len_incl_hdr = skb->len;
-		/* Decapsulate packet and pass it up the
-		   protocol stack */
-		skb->dev = dev;
-		
-		if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){
-		
-			/* Make sure it's an Ethernet frame, otherwise drop it */
-			if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) {
-				skb_pull(skb, 8);
-				skb->protocol=eth_type_trans(skb,dev);
-			}else{
-				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
-				++chan->ifstats.rx_errors;
-				++card->wandev.stats.rx_errors;
-				goto rx_done;
-			}
-		}else{
-		
-			/* remove hardware header */
-			buf = skb_pull(skb, 1); 
-			
-			if (!wanrouter_type_trans(skb, dev)) {
-				
-				/* can't decapsulate packet */
-				dev_kfree_skb_any(skb);
-
-				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;
-				++chan->ifstats.rx_errors;
-				++card->wandev.stats.rx_errors;
-				goto rx_done;	
-			}
-			skb->mac.raw = skb->data;
-		} 
-		
-
-		/* Send a packet up the IP stack */
-		skb->dev->last_rx = jiffies;
-		netif_rx(skb);
-		++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack;
-		++chan->ifstats.rx_packets;
-		++card->wandev.stats.rx_packets;
-
-		chan->ifstats.rx_bytes += len_incl_hdr;
-		card->wandev.stats.rx_bytes += len_incl_hdr;
-	}
-
-rx_done:
-
-       	/* Release buffer element and calculate a pointer to the next one */ 
-       	frbuf->flag = 0;
-	card->rxmb = ++frbuf;
-	if ((void*)frbuf > card->u.f.rxmb_last)
-		card->rxmb = card->u.f.rxmb_base;
-
-}
-
-/*==================================================================
- * tx_intr:	Transmit interrupt handler.
- *
- * Rationale:
- *      If the board is busy transmitting, if_send() will
- *      buffers a single packet and turn on
- *      the tx interrupt. Tx interrupt will be called
- *      by the board, once the firmware can send more
- *      data. Thus, no polling is required.	 
- *
- * Description:
- *	Tx interrupt is called for each 
- *      configured dlci channel. Thus: 
- * 	1. Obtain the netowrk interface based on the
- *         dlci number.
- *      2. Check that network interface is up and
- *         properly setup.
- * 	3. Check for a buffered packet.
- *      4. Transmit the packet.
- *	5. If we are in WANPIPE mode, mark the 
- *         NET_BH handler. 
- *      6. If we are in API mode, kick
- *         the AF_WANPIPE socket for more data. 
- *	   
- */
-static void tx_intr(sdla_t *card)
-{
-        fr508_flags_t* flags = card->flags;
-        fr_tx_buf_ctl_t* bctl;
-        struct net_device* dev;
-        fr_channel_t* chan;
-
-        if(card->hw.type == SDLA_S514){
-                bctl = (void*)(flags->tse_offs + card->hw.dpmbase);
-        }else{
-                bctl = (void*)(flags->tse_offs - FR_MB_VECTOR +
-                        card->hw.dpmbase);
-	}
-
-        /* Find the structure and make it unbusy */
-        dev = find_channel(card, flags->dlci);
-	if (dev == NULL){
-		printk(KERN_INFO "NO DEV IN TX Interrupt\n");	
-		goto end_of_tx_intr;
-	}
-
-        if ((chan = dev->priv) == NULL){
-		printk(KERN_INFO "NO CHAN IN TX Interrupt\n");	
-		goto end_of_tx_intr;
-	}
-
-        if(!chan->transmit_length || !chan->delay_skb) {
-                printk(KERN_INFO "%s: tx int error - transmit length zero\n",
-				card->wandev.name);
-                goto end_of_tx_intr;
-        }
-
-	/* If the 'if_send()' procedure is currently checking the 'tbusy'
-	   status, then we cannot transmit. Instead, we configure the microcode
-	   so as to re-issue this transmit interrupt at a later stage. 
-	*/
-	if (test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
-
-		fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface;
-		bctl->flag = 0xA0;
-		dlci_interface->gen_interrupt |= FR_INTR_TXRDY;
-		return;
-
- 	}else{
-        	bctl->dlci = flags->dlci;
-	        bctl->length = chan->transmit_length+chan->fr_header_len;
-        	sdla_poke(&card->hw, 
-		          fr_send_hdr(card,bctl->dlci,bctl->offset), 
-			  chan->delay_skb->data,
- 	              	  chan->delay_skb->len);
-	        bctl->flag = 0xC0;
-
-		++chan->ifstats.tx_packets;
-		++card->wandev.stats.tx_packets;
-		chan->ifstats.tx_bytes += chan->transmit_length;
-		card->wandev.stats.tx_bytes += chan->transmit_length;
-
-		/* We must free an sk buffer, which we used
-		 * for delayed transmission; Otherwise, the sock
-		 * will run out of memory */
-                dev_kfree_skb_any(chan->delay_skb);
-
-		chan->delay_skb = NULL;				
-        	chan->transmit_length = 0;
-
-		dev->trans_start = jiffies;
-
-		if (netif_queue_stopped(dev)){
-			/* If using API, than wakeup socket BH handler */
-			if (chan->common.usedby == API){
-				netif_start_queue(dev);
-				wakeup_sk_bh(dev);
-			}else{
-				netif_wake_queue(dev);
-			}
-		}
-	}
-
-end_of_tx_intr:
-
- 	/* if any other interfaces have transmit interrupts pending, 
-	 * do not disable the global transmit interrupt */
-	if(!(-- card->u.f.tx_interrupts_pending))
-       	        flags->imask &= ~FR_INTR_TXRDY;
-
-
-}
-
-
-/*============================================================================
- * timer_intr:	Timer interrupt handler.
- *
- * Rationale:
- *	All commans must be executed within the timer
- *      interrupt since no two commands should execute
- *      at the same time.
- *
- * Description:
- *	The timer interrupt is used to:
- *    	1. Processing udp calls from 'fpipemon'.
- *    	2. Processing update calls from /proc file system
- *   	3. Reading board-level statistics for 
- *         updating the proc file system.
- *    	4. Sending inverse ARP request packets.
- *	5. Configure a dlci/channel.
- *	6. Unconfigure a dlci/channel. (Node only)
- */
-
-static void timer_intr(sdla_t *card)
-{
-	fr508_flags_t* flags = card->flags;
-
-	/* UDP Debuging: fpipemon call */
-        if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) {
-		if(card->u.f.udp_type == UDP_FPIPE_TYPE) {
-                    	if(process_udp_mgmt_pkt(card)) {
-		                card->u.f.timer_int_enabled &=
-					~TMR_INT_ENABLED_UDP;
-			}
-		}
-        }
-
-	/* /proc update call : triggered from update() */
-	if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
-		fr_get_err_stats(card);
-		fr_get_stats(card);
-		card->u.f.update_comms_stats = 0;
-		card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
-	}
-
-	/* Update the channel state call.  This is call is
-         * triggered by if_send() function */
-	if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE_STATE){
-		struct net_device *dev;
-		if (card->wandev.state == WAN_CONNECTED){
-			for (dev = card->wandev.dev; dev;
-			     dev = *((struct net_device **)dev->priv)){
-				fr_channel_t *chan = dev->priv;	
-				if (chan->common.state != WAN_CONNECTED){
-					update_chan_state(dev);
-				}
-			}
-		}
-		card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE_STATE;
-	}
-
-	/* configure a dlci/channel */
-	if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_CONFIG){
-		config_fr(card);
-		card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
-	}
-
-	/* unconfigure a dlci/channel */
-	if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG){
-		unconfig_fr(card);
-		card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
-	}
-
-	
-	/* Transmit ARP packets */
-	if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_ARP){
-		int i=0;
-		struct net_device *dev;
-
-		if (card->u.f.arp_dev == NULL)
-			card->u.f.arp_dev = card->wandev.dev;
-
-		dev = card->u.f.arp_dev;
-
-		for (;;){ 
-
-			fr_channel_t *chan = dev->priv;
-
-			/* If the interface is brought down cancel sending In-ARPs */
-			if (!(dev->flags&IFF_UP)){
-				clear_bit(0,&chan->inarp_ready);	
-			}
-
-			if (test_bit(0,&chan->inarp_ready)){
-
-				if (check_tx_status(card,dev)){
-					set_bit(ARP_CRIT,&card->wandev.critical);
-					break;
-				}
-
-				if (!send_inarp_request(card,dev)){
-					trigger_fr_arp(dev);
-					chan->inarp_tick = jiffies;
-				}
-
-				clear_bit(0,&chan->inarp_ready);
-				dev = move_dev_to_next(card,dev);
-				break;
-			}
-			dev = move_dev_to_next(card,dev);
-
-			if (++i == card->wandev.new_if_cnt){
-				card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_ARP;
-				break;
-			}
-		}
-		card->u.f.arp_dev = dev;
-	}
-
-        if(!card->u.f.timer_int_enabled)
-                flags->imask &= ~FR_INTR_TIMER;
-}
-
-
-/*============================================================================
- * spur_intr:	Spurious interrupt handler.
- * 
- * Description:
- *  	We don't know this interrupt.
- *      Print a warning.
- */
-
-static void spur_intr (sdla_t* card)
-{
-	if (net_ratelimit()){ 
-		printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
-	}
-}
-
-
-//FIXME: Fix the IPX in next version
-/*===========================================================================
- *  Return 0 for non-IPXWAN packet
- *         1 for IPXWAN packet or IPX is not enabled!
- *  FIXME: Use a IPX structure here not offsets
- */
-static int handle_IPXWAN(unsigned char *sendpacket, 
-			 char *devname, unsigned char enable_IPX, 
-			 unsigned long network_number)
-{
-	int i;
-
-	if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 &&
-	    sendpacket[6] == 0x81 && sendpacket[7] == 0x37) { 
-
-		/* It's an IPX packet */
-		if (!enable_IPX){
-			/* Return 1 so we don't pass it up the stack. */
-			//FIXME: Take this out when IPX is fixed
-			if (net_ratelimit()){ 
-				printk (KERN_INFO 
-				"%s: WARNING: Unsupported IPX packet received and dropped\n",
-					devname);
-			}
-			return 1;
-		}
-	} else {
-		/* It's not IPX so return and pass it up the stack. */
-		return 0;
-	}
-
-	if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04){
-		/* It's IPXWAN */
-
-		if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00){
-
-			/* It's a timer request packet */
-			printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",
-					devname);
-
-			/* Go through the routing options and answer no to every
-			 * option except Unnumbered RIP/SAP
-			 */
-			for(i = 49; sendpacket[i] == 0x00; i += 5){
-				/* 0x02 is the option for Unnumbered RIP/SAP */
-				if( sendpacket[i + 4] != 0x02){
-					sendpacket[i + 1] = 0;
-				}
-			}
-
-			/* Skip over the extended Node ID option */
-			if( sendpacket[i] == 0x04 ){
-				i += 8;
-			}
-
-			/* We also want to turn off all header compression opt.
-			 */
-			for(; sendpacket[i] == 0x80 ;){
-				sendpacket[i + 1] = 0;
-				i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
-			}
-
-			/* Set the packet type to timer response */
-			sendpacket[42] = 0x01;
-
-			printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",
-					devname);
-
-		} else if( sendpacket[42] == 0x02 ){
-
-			/* This is an information request packet */
-			printk(KERN_INFO 
-				"%s: Received IPXWAN Information Request packet\n",
-						devname);
-
-			/* Set the packet type to information response */
-			sendpacket[42] = 0x03;
-
-			/* Set the router name */
-			sendpacket[59] = 'F';
-			sendpacket[60] = 'P';
-			sendpacket[61] = 'I';
-			sendpacket[62] = 'P';
-			sendpacket[63] = 'E';
-			sendpacket[64] = '-';
-			sendpacket[65] = CVHexToAscii(network_number >> 28);
-			sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24);
-			sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20);
-			sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16);
-			sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12);
-			sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8);
-			sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4);
-			sendpacket[72] = CVHexToAscii(network_number & 0x0000000F);
-			for(i = 73; i < 107; i+= 1)
-			{
-				sendpacket[i] = 0;
-			}
-
-			printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",
-					devname);
-		} else {
-
-			printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
-			return 0;
-		}
-
-		/* Set the WNodeID to our network address */
-		sendpacket[43] = (unsigned char)(network_number >> 24);
-		sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16);
-		sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8);
-		sendpacket[46] = (unsigned char)(network_number & 0x000000FF);
-
-		return 1;
-	}
-
-	/* If we get here, it's an IPX-data packet so it'll get passed up the 
-	 * stack.
-	 * switch the network numbers 
-	 */
-	switch_net_numbers(sendpacket, network_number ,1);
-	return 0;
-}
-/*============================================================================
- * process_route
- * 
- * Rationale:
- *	If the interface goes down, or we receive an ARP request,
- *      we have to change the network interface ip addresses.
- * 	This cannot be done within the interrupt.
- *
- * Description:
- *
- * 	This routine is called as a polling routine to dynamically 
- *	add/delete routes negotiated by inverse ARP.  It is in this 
- *    	"task" because we don't want routes to be added while in 
- *      interrupt context.
- *
- * Usage:
- *	This function is called by fr_poll() polling funtion.
- */
-
-static void process_route(struct net_device *dev)
-{
-	fr_channel_t *chan = dev->priv;
-	sdla_t *card = chan->card;
-
-	struct ifreq if_info;
-	struct sockaddr_in *if_data;
-	mm_segment_t fs = get_fs();
-	u32 ip_tmp;
-	int err;
-
-
-	switch(chan->route_flag){
-
-	case ADD_ROUTE:
-				
-		/* Set remote addresses */
-		memset(&if_info, 0, sizeof(if_info));
-		strcpy(if_info.ifr_name, dev->name);
-
-		set_fs(get_ds());     /* get user space block */ 
-		
-		if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-		if_data->sin_addr.s_addr = chan->ip_remote;
-		if_data->sin_family = AF_INET;
-		err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
-		set_fs(fs);           /* restore old block */
-
-		if (err) {
-			printk(KERN_INFO 
-				"%s: Route Add failed.  Error: %d\n", 
-					card->devname,err);
-			printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				chan->name, NIPQUAD(chan->ip_remote));
-
-		}else {
-			printk(KERN_INFO "%s: Route Added Successfully: %u.%u.%u.%u\n",
-				card->devname,NIPQUAD(chan->ip_remote));
-			chan->route_flag = ROUTE_ADDED;
-		}
-		break;
-
-	case REMOVE_ROUTE:
-
-		/* Set remote addresses */
-		memset(&if_info, 0, sizeof(if_info));
-		strcpy(if_info.ifr_name, dev->name);
-
-		ip_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);	
-
-		set_fs(get_ds());     /* get user space block */ 
-		
-		if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-		if_data->sin_addr.s_addr = 0;
-		if_data->sin_family = AF_INET;
-		err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
-		set_fs(fs);    
-		
-		if (err) {
-			printk(KERN_INFO 
-				"%s: Deleting of route failed.  Error: %d\n", 
-					card->devname,err);
-			printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n",
-				dev->name,NIPQUAD(chan->ip_remote) );
-
-		} else {
-			printk(KERN_INFO "%s: Route Removed Sucessfuly: %u.%u.%u.%u\n", 
-				card->devname,NIPQUAD(ip_tmp));
-			chan->route_flag = NO_ROUTE;
-		}
-		break;
-
-	} /* Case Statement */
-
-}
-
-
-
-/****** Frame Relay Firmware-Specific Functions *****************************/
-
-/*============================================================================
- * Read firmware code version.
- * o fill string str with firmware version info. 
- */
-static int fr_read_version (sdla_t* card, char* str)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->cmd.command = FR_READ_CODE_VERSION;
-		mbox->cmd.length = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	if (!err && str) {
-		int len = mbox->cmd.length;
-		memcpy(str, mbox->data, len);
-	        str[len] = '\0';
-	}
-	return err;
-}
-
-/*============================================================================
- * Set global configuration.
- */
-static int fr_configure (sdla_t* card, fr_conf_t *conf)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int dlci_num = card->u.f.dlci_num;
-	int err, i;
-
-	do
-	{
-		memcpy(mbox->data, conf, sizeof(fr_conf_t));
-
-		if (dlci_num) for (i = 0; i < dlci_num; ++i)
-			((fr_conf_t*)mbox->data)->dlci[i] = 
-					card->u.f.node_dlci[i]; 
-		
-		mbox->cmd.command = FR_SET_CONFIG;
-		mbox->cmd.length =
-			sizeof(fr_conf_t) + dlci_num * sizeof(short);
-
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	/*NC Oct 12 2000 */
-	if (err != CMD_OK){
-		printk(KERN_ERR "%s: Frame Relay Configuration Failed: rc=0x%x\n",
-				card->devname,err);
-	}
-	
-	return err;
-}
-
-/*============================================================================
- * Set DLCI configuration.
- */
-static int fr_dlci_configure (sdla_t* card, fr_dlc_conf_t *conf, unsigned dlci)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memcpy(mbox->data, conf, sizeof(fr_dlc_conf_t));
-		mbox->cmd.dlci = (unsigned short) dlci; 
-		mbox->cmd.command = FR_SET_CONFIG;
-		mbox->cmd.length = sizeof(fr_dlc_conf_t);
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry--);
-	
-	return err;
-}
-/*============================================================================
- * Set interrupt mode.
- */
-static int fr_set_intr_mode (sdla_t* card, unsigned mode, unsigned mtu,
-	unsigned short timeout)
-{
-	fr_mbox_t* mbox = card->mbox;
-	fr508_intr_ctl_t* ictl = (void*)mbox->data;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(ictl, 0, sizeof(fr508_intr_ctl_t));
-		ictl->mode   = mode;
-		ictl->tx_len = mtu;
-		ictl->irq    = card->hw.irq;
-
-		/* indicate timeout on timer */
-		if (mode & 0x20) ictl->timeout = timeout; 
-
-		mbox->cmd.length = sizeof(fr508_intr_ctl_t);
-		mbox->cmd.command = FR_SET_INTR_MODE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int fr_comm_enable (sdla_t* card)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->cmd.command = FR_COMM_ENABLE;
-		mbox->cmd.length = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-/*============================================================================
- * fr_comm_disable 
- *
- * Warning: This functin is called by the shutdown() procedure. It is void
- *          since dev->priv are has already been deallocated and no
- *          error checking is possible using fr_event() function.
- */
-static void fr_comm_disable (sdla_t* card)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do {
-	mbox->cmd.command = FR_SET_MODEM_STATUS;
-	mbox->cmd.length = 1;
-	mbox->data[0] = 0;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry--);
-	
-	retry = MAX_CMD_RETRY;
-	
-	do
-	{
-		mbox->cmd.command = FR_COMM_DISABLE;
-		mbox->cmd.length = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry--);
-
-	return;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics. 
- */
-static int fr_get_err_stats (sdla_t* card)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-
-	do
-	{
-		mbox->cmd.command = FR_READ_ERROR_STATS;
-		mbox->cmd.length = 0;
-		mbox->cmd.dlci = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if (!err) {
-		fr_comm_stat_t* stats = (void*)mbox->data;
-		card->wandev.stats.rx_over_errors    = stats->rx_overruns;
-		card->wandev.stats.rx_crc_errors     = stats->rx_bad_crc;
-		card->wandev.stats.rx_missed_errors  = stats->rx_aborts;
-		card->wandev.stats.rx_length_errors  = stats->rx_too_long;
-		card->wandev.stats.tx_aborted_errors = stats->tx_aborts;
-	
-	}
-
-	return err;
-}
-
-/*============================================================================
- * Get statistics. 
- */
-static int fr_get_stats (sdla_t* card)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-
-	do
-	{
-		mbox->cmd.command = FR_READ_STATISTICS;
-		mbox->cmd.length = 0;
-		mbox->cmd.dlci = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if (!err) {
-		fr_link_stat_t* stats = (void*)mbox->data;
-		card->wandev.stats.rx_frame_errors = stats->rx_bad_format;
-		card->wandev.stats.rx_dropped =
-			stats->rx_dropped + stats->rx_dropped2;
-	}
-
-	return err;
-}
-
-/*============================================================================
- * Add DLCI(s) (Access Node only!).
- * This routine will perform the ADD_DLCIs command for the specified DLCI.
- */
-static int fr_add_dlci (sdla_t* card, int dlci)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		unsigned short* dlci_list = (void*)mbox->data;
-
-		mbox->cmd.length  = sizeof(short);
-		dlci_list[0] = dlci;
-		mbox->cmd.command = FR_ADD_DLCI;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-/*============================================================================
- * Activate DLCI(s) (Access Node only!). 
- * This routine will perform the ACTIVATE_DLCIs command with a DLCI number. 
- */
-static int fr_activate_dlci (sdla_t* card, int dlci)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		unsigned short* dlci_list = (void*)mbox->data;
-
-		mbox->cmd.length  = sizeof(short);
-		dlci_list[0] = dlci;
-		mbox->cmd.command = FR_ACTIVATE_DLCI;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-/*============================================================================
- * Delete DLCI(s) (Access Node only!). 
- * This routine will perform the DELETE_DLCIs command with a DLCI number. 
- */
-static int fr_delete_dlci (sdla_t* card, int dlci)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		unsigned short* dlci_list = (void*)mbox->data;
-
-		mbox->cmd.length  = sizeof(short);
-		dlci_list[0] = dlci;
-		mbox->cmd.command = FR_DELETE_DLCI;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-
-
-/*============================================================================
- * Issue in-channel signalling frame. 
- */
-static int fr_issue_isf (sdla_t* card, int isf)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->data[0] = isf;
-		mbox->cmd.length  = 1;
-		mbox->cmd.command = FR_ISSUE_IS_FRAME;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-	
-	return err;
-}
-
-
-static unsigned int fr_send_hdr (sdla_t*card, int dlci, unsigned int offset)
-{
-	struct net_device *dev = find_channel(card,dlci);	
-	fr_channel_t *chan;
-
-	if (!dev || !(chan=dev->priv))
-		return offset;
-	
-	if (chan->fr_header_len){
-		sdla_poke(&card->hw, offset, chan->fr_header, chan->fr_header_len);
-	}
-	
-	return offset+chan->fr_header_len;
-}
-
-/*============================================================================
- * Send a frame on a selected DLCI.  
- */
-static int fr_send_data_header (sdla_t* card, int dlci, unsigned char attr, int len,
-	void *buf, unsigned char hdr_len)
-{
-	fr_mbox_t* mbox = card->mbox + 0x800;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->cmd.dlci    = dlci;
-		mbox->cmd.attr    = attr;
-		mbox->cmd.length  = len+hdr_len;
-		mbox->cmd.command = FR_WRITE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if (!err) {
-		fr_tx_buf_ctl_t* frbuf;
- 
-               	if(card->hw.type == SDLA_S514)
-			frbuf = (void*)(*(unsigned long*)mbox->data +
-                        	card->hw.dpmbase);
-		else
-			frbuf = (void*)(*(unsigned long*)mbox->data -
-                        	FR_MB_VECTOR + card->hw.dpmbase);
-
-		sdla_poke(&card->hw, fr_send_hdr(card,dlci,frbuf->offset), buf, len);
-		frbuf->flag = 0x01;
-	}
-
-	return err;
-}
-
-static int fr_send (sdla_t* card, int dlci, unsigned char attr, int len,
-	void *buf)
-{
-	fr_mbox_t* mbox = card->mbox + 0x800;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->cmd.dlci    = dlci;
-		mbox->cmd.attr    = attr;
-		mbox->cmd.length  = len;
-		mbox->cmd.command = FR_WRITE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if (!err) {
-		fr_tx_buf_ctl_t* frbuf;
- 
-               	if(card->hw.type == SDLA_S514)
-			frbuf = (void*)(*(unsigned long*)mbox->data +
-                        	card->hw.dpmbase);
-		else
-			frbuf = (void*)(*(unsigned long*)mbox->data -
-                        	FR_MB_VECTOR + card->hw.dpmbase);
-
-		sdla_poke(&card->hw, frbuf->offset, buf, len);
-		frbuf->flag = 0x01;
-	}
-
-	return err;
-}
-
-
-/****** Firmware Asynchronous Event Handlers ********************************/
-
-/*============================================================================
- * Main asyncronous event/error handler.
- *	This routine is called whenever firmware command returns non-zero
- *	return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
-{
-	fr508_flags_t* flags = card->flags;
-	char *ptr = &flags->iflag;
-	int i;
-
-	switch (event) {
-
-		case FRRES_MODEM_FAILURE:
-			return fr_modem_failure(card, mbox);
-
-		case FRRES_CHANNEL_DOWN: {
-			struct net_device *dev;
-
-			/* Remove all routes from associated DLCI's */
-			for (dev = card->wandev.dev; dev;
-			     dev = *((struct net_device **)dev->priv)) {
-				fr_channel_t *chan = dev->priv;
-				if (chan->route_flag == ROUTE_ADDED) {
-					chan->route_flag = REMOVE_ROUTE;
-				}
-
-				if (chan->inarp == INARP_CONFIGURED) {
-					chan->inarp = INARP_REQUEST;
-				}
-
-				/* If the link becomes disconnected then,
-                                 * all channels will be disconnected
-                                 * as well.
-                                 */
-				set_chan_state(dev,WAN_DISCONNECTED);
-			}
-				
-			wanpipe_set_state(card, WAN_DISCONNECTED);
-			return 1;
-			}
-
-		case FRRES_CHANNEL_UP: {
-			struct net_device *dev;
-
-			/* FIXME: Only startup devices that are on the list */
-			
-			for (dev = card->wandev.dev; dev;
-			     dev = *((struct net_device **)dev->priv)) {
-				
-				set_chan_state(dev,WAN_CONNECTED);
-			}
-
-			wanpipe_set_state(card, WAN_CONNECTED);
-			return 1;
-			}
-
-		case FRRES_DLCI_CHANGE:
-			return fr_dlci_change(card, mbox);
-
-		case FRRES_DLCI_MISMATCH:
-			printk(KERN_INFO "%s: DLCI list mismatch!\n", 
-				card->devname);
-			return 1;
-
-		case CMD_TIMEOUT:
-			printk(KERN_ERR "%s: command 0x%02X timed out!\n",
-				card->devname, mbox->cmd.command);
-			printk(KERN_INFO "%s: ID Bytes = ",card->devname);
- 	    		for(i = 0; i < 8; i ++)
-				printk(KERN_INFO "0x%02X ", *(ptr + 0x18 + i));
-	   	 	printk(KERN_INFO "\n");	
-            
-			break;
-
-		case FRRES_DLCI_INACTIVE:
-			break;
- 
-		case FRRES_CIR_OVERFLOW:
-			break;
-			
-		case FRRES_BUFFER_OVERFLOW:
-			break; 
-			
-		default:
-			printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
-				, card->devname, mbox->cmd.command, event);
-	}
-
-	return 0;
-}
-
-/*============================================================================
- * Handle modem error.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_modem_failure (sdla_t *card, fr_mbox_t* mbox)
-{
-	printk(KERN_INFO "%s: physical link down! (modem error 0x%02X)\n",
-		card->devname, mbox->data[0]);
-
-	switch (mbox->cmd.command){
-		case FR_WRITE:
-	
-		case FR_READ:
-			return 0;
-	}
-	
-	return 1;
-}
-
-/*============================================================================
- * Handle DLCI status change.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
-{
-	dlci_status_t* status = (void*)mbox->data;
-	int cnt = mbox->cmd.length / sizeof(dlci_status_t);
-	fr_channel_t *chan;
-	struct net_device* dev2;
-	
-
-	for (; cnt; --cnt, ++status) {
-
-		unsigned short dlci= status->dlci;
-		struct net_device* dev = find_channel(card, dlci);
-		
-		if (dev == NULL){
-			printk(KERN_INFO 
-				"%s: CPE contains unconfigured DLCI= %d\n", 
-				card->devname, dlci); 	
-
-                      printk(KERN_INFO
-                                "%s: unconfigured DLCI %d reported by network\n"
-                                , card->devname, dlci);
- 
-		}else{
-			if (status->state == FR_LINK_INOPER) {
-				printk(KERN_INFO
-					"%s: DLCI %u is inactive!\n",
-					card->devname, dlci);
-
-				if (dev && netif_running(dev))
-					set_chan_state(dev, WAN_DISCONNECTED);
-			}
-	
-			if (status->state & FR_DLCI_DELETED) {
-
-				printk(KERN_INFO
-					"%s: DLCI %u has been deleted!\n",
-					card->devname, dlci);
-
-				if (dev && netif_running(dev)){
-
-					fr_channel_t *chan = dev->priv;
-
-					if (chan->route_flag == ROUTE_ADDED) {
-						chan->route_flag = REMOVE_ROUTE;
-						/* The state change will trigger
-                                                 * the fr polling routine */
-					}
-
-					if (chan->inarp == INARP_CONFIGURED) {
-						chan->inarp = INARP_REQUEST;
-					}
-
-					set_chan_state(dev, WAN_DISCONNECTED);
-				}
-
-			} else if (status->state & FR_DLCI_ACTIVE) {
-
-				chan = dev->priv;
-			
-				/* This flag is used for configuring specific 
-				   DLCI(s) when they become active.
-			 	*/ 
-				chan->dlci_configured = DLCI_CONFIG_PENDING;
-	
-				set_chan_state(dev, WAN_CONNECTED);
-		
-			}
-		}
-	}
-	
-	for (dev2 = card->wandev.dev; dev2;
-	     dev2 = *((struct net_device **)dev2->priv)){
-		
-		chan = dev2->priv;
-	
-		if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
-			if (fr_init_dlci(card, chan)){
-				return 1;
-			}
-		}
-
-	}
-	return 1;
-}
-
-
-static int fr_init_dlci (sdla_t *card, fr_channel_t *chan)
-{
-	fr_dlc_conf_t cfg;
-	
-	memset(&cfg, 0, sizeof(cfg));
-
-	if ( chan->cir_status == CIR_DISABLED) {
-
-		cfg.cir_fwd = cfg.cir_bwd  = 16;
-		cfg.bc_fwd = cfg.bc_bwd = 16;
-		cfg.conf_flags = 0x0001;	
-
-	}else if (chan->cir_status == CIR_ENABLED) {
-	
-		cfg.cir_fwd = cfg.cir_bwd = chan->cir;
-		cfg.bc_fwd  = cfg.bc_bwd  = chan->bc;
-		cfg.be_fwd  = cfg.be_bwd  = chan->be;
-		cfg.conf_flags = 0x0000;
-	}
-	
-	if (fr_dlci_configure( card, &cfg , chan->dlci)){
-		printk(KERN_INFO 
-			"%s: DLCI Configure failed for %d\n",
-				card->devname, chan->dlci);
-		return 1;	
-	}
-	
-	chan->dlci_configured = DLCI_CONFIGURED;
-
-	/* Read the interface byte mapping into the channel 
-	 * structure.
-	 */
-	read_DLCI_IB_mapping( card, chan );
-
-	return 0;
-}
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Update channel state. 
- */
-static int update_chan_state(struct net_device* dev)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		mbox->cmd.command = FR_LIST_ACTIVE_DLCI;
-		mbox->cmd.length = 0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if (!err) {
-		
-		unsigned short* list = (void*)mbox->data;
-		int cnt = mbox->cmd.length / sizeof(short);
-		
-		err=1;
-		
-		for (; cnt; --cnt, ++list) {
-
-			if (*list == chan->dlci) {
- 				set_chan_state(dev, WAN_CONNECTED);
-
-
-				/* May 23 2000. NC
-				 * When a dlci is added or restarted,
-                                 * the dlci_int_interface pointer must
-				 * be reinitialized.  */
-				if (!chan->dlci_int_interface){
-					err=fr_init_dlci (card,chan);
-				}
-				break;
-			}
-		}
-	}
-
-	return err;
-}
-
-/*============================================================================
- * Set channel state.
- */
-static void set_chan_state(struct net_device* dev, int state)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-
-	if (chan->common.state != state) {
-
-		switch (state) {
-
-			case WAN_CONNECTED:
-				printk(KERN_INFO
-					"%s: Interface %s: DLCI %d connected\n",
-					card->devname, dev->name, chan->dlci);
-
-				/* If the interface was previoulsy down,
-                                 * bring it up, since the channel is active */
-
-				trigger_fr_poll (dev);
-				trigger_fr_arp  (dev);
-				break;
-
-			case WAN_CONNECTING:
-				printk(KERN_INFO 
-				      "%s: Interface %s: DLCI %d connecting\n",
-					card->devname, dev->name, chan->dlci);
-				break;
-
-			case WAN_DISCONNECTED:
-				printk (KERN_INFO 
-				    "%s: Interface %s: DLCI %d disconnected!\n",
-					card->devname, dev->name, chan->dlci);
-			
-				/* If the interface is up, bring it down,
-                                 * since the channel is now disconnected */
-				trigger_fr_poll (dev);
-				break;
-		}
-
-		chan->common.state = state;
-	}
-
-	chan->state_tick = jiffies;
-}
-
-/*============================================================================
- * Find network device by its channel number.
- *
- * We need this critical flag because we change
- * the dlci_to_dev_map outside the interrupt.
- *
- * NOTE: del_if() functions updates this array, it uses
- *       the spin locks to avoid corruption.
- */
-static struct net_device* find_channel(sdla_t* card, unsigned dlci)
-{
-	if(dlci > HIGHEST_VALID_DLCI)
-		return NULL;
-
-	return(card->u.f.dlci_to_dev_map[dlci]);
-}
-
-/*============================================================================
- * Check to see if a frame can be sent. If no transmit buffers available,
- * enable transmit interrupts.
- *
- * Return:	1 - Tx buffer(s) available
- *		0 - no buffers available
- */
-static int is_tx_ready (sdla_t* card, fr_channel_t* chan)
-{
-	unsigned char sb;
-
-        if(card->hw.type == SDLA_S514)
-		return 1;
-
-	sb = inb(card->hw.port);
-	if (sb & 0x02) 
-		return 1;
-
-	return 0;
-}
-
-/*============================================================================
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
-	unsigned val;
-
-	if (!len) 
-		len = strlen(str);
-
-	for (val = 0; len && isdigit(*str); ++str, --len)
-		val = (val * 10) + (*str - (unsigned)'0');
-
-	return val;
-}
-
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
-                                struct sk_buff *skb, int dlci)
-{
-        int udp_pkt_stored = 0;
-	
-	struct net_device *dev = find_channel(card, dlci);
-	fr_channel_t *chan;
-	
-	if (!dev || !(chan=dev->priv))
-		return 1;
-	
-        if(!card->u.f.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
-                card->u.f.udp_pkt_lgth = skb->len + chan->fr_header_len;
-                card->u.f.udp_type = udp_type;
-                card->u.f.udp_pkt_src = udp_pkt_src;
-                card->u.f.udp_dlci = dlci;
-                memcpy(card->u.f.udp_pkt_data, skb->data, skb->len);
-                card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UDP;
-                udp_pkt_stored = 1;
-
-        }else{
-                printk(KERN_INFO "ERROR: UDP packet not stored for DLCI %d\n", 
-							dlci);
-	}
-
-        if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                dev_kfree_skb_any(skb);
-	}else{
-                dev_kfree_skb_any(skb);
-	}
-		
-        return(udp_pkt_stored);
-}
-
-
-/*==============================================================================
- * Process UDP call of type FPIPE8ND
- */
-static int process_udp_mgmt_pkt(sdla_t* card)
-{
-
-	int c_retry = MAX_CMD_RETRY;
-	unsigned char *buf;
-	unsigned char frames;
-	unsigned int len;
-	unsigned short buffer_length;
-	struct sk_buff *new_skb;
-	fr_mbox_t* mbox = card->mbox;
-	int err;
-	struct timeval tv;
-	int udp_mgmt_req_valid = 1;
-        struct net_device* dev;
-        fr_channel_t* chan;
-        fr_udp_pkt_t *fr_udp_pkt;
-	unsigned short num_trc_els;
-	fr_trc_el_t* ptr_trc_el;
-	fr_trc_el_t trc_el;
-	fpipemon_trc_t* fpipemon_trc;
-
-	char udp_pkt_src = card->u.f.udp_pkt_src; 
-	int dlci = card->u.f.udp_dlci;
-
-	/* Find network interface for this packet */
-	dev = find_channel(card, dlci);
-	if (!dev){
-		card->u.f.udp_pkt_lgth = 0;
-		return 1;
-	}
-        if ((chan = dev->priv) == NULL){
-		card->u.f.udp_pkt_lgth = 0;
-		return 1;
-	}
-
-	/* If the UDP packet is from the network, we are going to have to 
-	   transmit a response. Before doing so, we must check to see that
-	   we are not currently transmitting a frame (in 'if_send()') and
-	   that we are not already in a 'delayed transmit' state.
-	*/
-	if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-		if (check_tx_status(card,dev)){
-			card->u.f.udp_pkt_lgth = 0;
-			return 1;
-		}
-        }
-
-        fr_udp_pkt = (fr_udp_pkt_t *)card->u.f.udp_pkt_data;
-
-	if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-	
-		switch(fr_udp_pkt->cblock.command) {
-
-			case FR_READ_MODEM_STATUS:
-			case FR_READ_STATUS:
-			case FPIPE_ROUTER_UP_TIME:
-			case FR_READ_ERROR_STATS:
-			case FPIPE_DRIVER_STAT_GEN:
-			case FR_READ_STATISTICS:
-			case FR_READ_ADD_DLC_STATS:
-			case FR_READ_CONFIG:
-			case FR_READ_CODE_VERSION:
-				udp_mgmt_req_valid = 1;
-				break;
-			default:
-				udp_mgmt_req_valid = 0;
-				break;
-		}
-	}
-
-	if(!udp_mgmt_req_valid) {
-		/* set length to 0 */
-		fr_udp_pkt->cblock.length = 0;
-		/* set return code */
-		fr_udp_pkt->cblock.result = 0xCD; 
-		
-		chan->drvstats_gen.UDP_PIPE_mgmt_direction_err ++;
-
-		if (net_ratelimit()){	
-			printk(KERN_INFO 
-			"%s: Warning, Illegal UDP command attempted from network: %x\n",
-			card->devname,fr_udp_pkt->cblock.command);
-		}
-		
-	} else {   
-           
-		switch(fr_udp_pkt->cblock.command) {
-
-		case FPIPE_ENABLE_TRACING:
-			if(!card->TracingEnabled) {
-				do {
-                       			mbox->cmd.command = FR_SET_TRACE_CONFIG;
-                       			mbox->cmd.length = 1;
-                     			mbox->cmd.dlci = 0x00;
-                   			mbox->data[0] = fr_udp_pkt->data[0] | 
-						RESET_TRC;
-                    			err = sdla_exec(mbox) ? 
-					     		mbox->cmd.result : CMD_TIMEOUT;
-                       		} while (err && c_retry-- && fr_event(card, err,
-					 mbox));
-
-                        	if(err) {
-					card->TracingEnabled = 0;
-					/* set the return code */
-					fr_udp_pkt->cblock.result =
-  						mbox->cmd.result;
-					mbox->cmd.length = 0;
-					break;
-				}
-
-				sdla_peek(&card->hw, NO_TRC_ELEMENTS_OFF,
-						&num_trc_els, 2);
-				sdla_peek(&card->hw, BASE_TRC_ELEMENTS_OFF,
-						&card->u.f.trc_el_base, 4);
-				card->u.f.curr_trc_el = card->u.f.trc_el_base;
-             			card->u.f.trc_el_last = card->u.f.curr_trc_el +
-							((num_trc_els - 1) * 
-							sizeof(fr_trc_el_t));
-   
-				/* Calculate the maximum trace data area in */
-				/* the UDP packet */
-				card->u.f.trc_bfr_space=(MAX_LGTH_UDP_MGNT_PKT -
-					//sizeof(fr_encap_hdr_t) -
-					sizeof(ip_pkt_t) -
-					sizeof(udp_pkt_t) -
-					sizeof(wp_mgmt_t) -
-					sizeof(cblock_t));
-
-				/* set return code */
-				fr_udp_pkt->cblock.result = 0;
-			
-			} else {
-                        	/* set return code to line trace already 
-				   enabled */
-				fr_udp_pkt->cblock.result = 1;
-                    	}
-
-			mbox->cmd.length = 0;
-			card->TracingEnabled = 1;
-			break;
-
-
-                case FPIPE_DISABLE_TRACING:
-			if(card->TracingEnabled) {
-			
-				do {
-					mbox->cmd.command = FR_SET_TRACE_CONFIG;
-					mbox->cmd.length = 1;
-					mbox->cmd.dlci = 0x00;
-					mbox->data[0] = ~ACTIVATE_TRC;
-					err = sdla_exec(mbox) ? 
-							mbox->cmd.result : CMD_TIMEOUT;
-				} while (err && c_retry-- && fr_event(card, err, mbox));
-                    	}
-
-                    	/* set return code */
-			fr_udp_pkt->cblock.result = 0;
-			mbox->cmd.length = 0;
-			card->TracingEnabled = 0;
-			break;
-
-                case FPIPE_GET_TRACE_INFO:
-
-		        /* Line trace cannot be performed on the 502 */
-                        if(!card->TracingEnabled) {
-                                /* set return code */
-                                fr_udp_pkt->cblock.result = 1;
-                                mbox->cmd.length = 0;
-                                break;
-                        }
-
-			ptr_trc_el = (void *)card->u.f.curr_trc_el;
-
-                        buffer_length = 0;
-			fr_udp_pkt->data[0x00] = 0x00;
-
-                        for(frames = 0; frames < MAX_FRMS_TRACED; frames ++) {
-
-                                sdla_peek(&card->hw, (unsigned long)ptr_trc_el,
-					  (void *)&trc_el.flag,
-					  sizeof(fr_trc_el_t));
-                                if(trc_el.flag == 0x00) {
-                                        break;
-				}
-                                if((card->u.f.trc_bfr_space - buffer_length)
-                                        < sizeof(fpipemon_trc_hdr_t)) { 
-                                        fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
-                                        break;
-                                }
-
-				fpipemon_trc = 
-					(fpipemon_trc_t *)&fr_udp_pkt->data[buffer_length]; 
-				fpipemon_trc->fpipemon_trc_hdr.status =
-					trc_el.attr;
-                            	fpipemon_trc->fpipemon_trc_hdr.tmstamp =
-					trc_el.tmstamp;
-                            	fpipemon_trc->fpipemon_trc_hdr.length = 
-					trc_el.length;
-
-                                if(!trc_el.offset || !trc_el.length) {
-
-                                     	fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
-
- 				}else if((trc_el.length + sizeof(fpipemon_trc_hdr_t) + 1) >
-					(card->u.f.trc_bfr_space - buffer_length)){
-
-                                        fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00;
-                                    	fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
- 
-                                }else {
-                                        fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x01;
-                                        sdla_peek(&card->hw, trc_el.offset,
-                           			  fpipemon_trc->data,
-						  trc_el.length);
-				}			
-
-                                trc_el.flag = 0x00;
-                                sdla_poke(&card->hw, (unsigned long)ptr_trc_el,
-					  &trc_el.flag, 1);
-                               
-				ptr_trc_el ++;
-				if((void *)ptr_trc_el > card->u.f.trc_el_last)
-					ptr_trc_el = (void*)card->u.f.trc_el_base;
-
-				buffer_length += sizeof(fpipemon_trc_hdr_t);
-                               	if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
-                               		buffer_length += trc_el.length;
-                               	}
-
-				if(fr_udp_pkt->data[0x00] & MORE_TRC_DATA) {
-					break;
-				}
-                        }
-                      
-			if(frames == MAX_FRMS_TRACED) {
-                        	fr_udp_pkt->data[0x00] |= MORE_TRC_DATA;
-			}
-             
-			card->u.f.curr_trc_el = (void *)ptr_trc_el;
-
-                        /* set the total number of frames passed */
-			fr_udp_pkt->data[0x00] |=
-				((frames << 1) & (MAX_FRMS_TRACED << 1));
-
-                        /* set the data length and return code */
-			fr_udp_pkt->cblock.length = mbox->cmd.length = buffer_length;
-                        fr_udp_pkt->cblock.result = 0;
-                        break;
-
-                case FPIPE_FT1_READ_STATUS:
-			sdla_peek(&card->hw, 0xF020,
-				&fr_udp_pkt->data[0x00] , 2);
-			fr_udp_pkt->cblock.length = mbox->cmd.length = 2;
-			fr_udp_pkt->cblock.result = 0;
-			break;
-
-		case FPIPE_FLUSH_DRIVER_STATS:
-			init_chan_statistics(chan);
-			init_global_statistics(card);
-			mbox->cmd.length = 0;
-			break;
-		
-		case FPIPE_ROUTER_UP_TIME:
-			do_gettimeofday(&tv);
-			chan->router_up_time = tv.tv_sec - 
-						chan->router_start_time;
-    	                *(unsigned long *)&fr_udp_pkt->data =
-    				chan->router_up_time;	
-			mbox->cmd.length = fr_udp_pkt->cblock.length = 4;
-			fr_udp_pkt->cblock.result = 0;
-			break;
-
-		case FPIPE_DRIVER_STAT_IFSEND:
-			memcpy(fr_udp_pkt->data,
-				&chan->drvstats_if_send.if_send_entry,
-				sizeof(if_send_stat_t));
-			mbox->cmd.length = fr_udp_pkt->cblock.length =sizeof(if_send_stat_t);	
-			fr_udp_pkt->cblock.result = 0;
-			break;
-	
-		case FPIPE_DRIVER_STAT_INTR:
-
-			memcpy(fr_udp_pkt->data,
-                                &card->statistics.isr_entry,
-                                sizeof(global_stats_t));
-
-                        memcpy(&fr_udp_pkt->data[sizeof(global_stats_t)],
-                                &chan->drvstats_rx_intr.rx_intr_no_socket,
-                                sizeof(rx_intr_stat_t));
-
-			mbox->cmd.length = fr_udp_pkt->cblock.length = 
-					sizeof(global_stats_t) +
-					sizeof(rx_intr_stat_t);
-			fr_udp_pkt->cblock.result = 0;
-			break;
-
-		case FPIPE_DRIVER_STAT_GEN:
-                        memcpy(fr_udp_pkt->data,
-                                &chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err,
-                                sizeof(pipe_mgmt_stat_t));
-
-                        memcpy(&fr_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
-                               &card->statistics, sizeof(global_stats_t));
-
-                        mbox->cmd.length = fr_udp_pkt->cblock.length = sizeof(global_stats_t)+
-                                                     sizeof(rx_intr_stat_t);
-			fr_udp_pkt->cblock.result = 0;
-                        break;
-
-
-		case FR_FT1_STATUS_CTRL:
-			if(fr_udp_pkt->data[0] == 1) {
-				if(rCount++ != 0 ){
-					fr_udp_pkt->cblock.result = 0;
-					mbox->cmd.length = 1;
-					break;
-				} 
-			}
-           
-			/* Disable FT1 MONITOR STATUS */
-                        if(fr_udp_pkt->data[0] == 0) {
-				if( --rCount != 0) {
-                                        fr_udp_pkt->cblock.result = 0;
-					mbox->cmd.length = 1;
-					break;
-				} 
-			}  
-			goto udp_mgmt_dflt;
-
-			
-		default:
-udp_mgmt_dflt:
- 			do {
-				memcpy(&mbox->cmd,
-					&fr_udp_pkt->cblock.command,
-					sizeof(fr_cmd_t));
-				if(mbox->cmd.length) {
-					memcpy(&mbox->data,
-						(char *)fr_udp_pkt->data,
-						mbox->cmd.length);
-				}
- 				
-				err = sdla_exec(mbox) ? mbox->cmd.result : 
-					CMD_TIMEOUT;
-			} while (err && c_retry-- && fr_event(card, err, mbox));
-
-			if(!err)
-				chan->drvstats_gen.
-					UDP_PIPE_mgmt_adptr_cmnd_OK ++;
-			else
-                                chan->drvstats_gen.
-					UDP_PIPE_mgmt_adptr_cmnd_timeout ++;
-
-       	                /* copy the result back to our buffer */
-			memcpy(&fr_udp_pkt->cblock.command,
-				&mbox->cmd, sizeof(fr_cmd_t));
-
-                       	if(mbox->cmd.length) {
-                               	memcpy(&fr_udp_pkt->data,
-					&mbox->data, mbox->cmd.length);
-			}
-		} 
-        }
-   
-        /* Fill UDP TTL */
-        fr_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-        len = reply_udp(card->u.f.udp_pkt_data, mbox->cmd.length);
-
-        if(udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
-		chan->fr_header_len=2;
-		chan->fr_header[0]=Q922_UI;
-		chan->fr_header[1]=NLPID_IP;
-			
-		err = fr_send_data_header(card, dlci, 0, len, 
-			card->u.f.udp_pkt_data,chan->fr_header_len);
-		if (err){ 
-			chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_passed ++;
-		}else{
-			chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_failed ++;
-		}
-		
-	} else {
-		/* Allocate socket buffer */
-		if((new_skb = dev_alloc_skb(len)) != NULL) {
-
-			/* copy data into new_skb */
-			buf = skb_put(new_skb, len);
-			memcpy(buf, card->u.f.udp_pkt_data, len);
-        
-			chan->drvstats_gen.
-				UDP_PIPE_mgmt_passed_to_stack ++;
-			new_skb->dev = dev;
-			new_skb->protocol = htons(ETH_P_IP);
-			new_skb->mac.raw = new_skb->data;
-			netif_rx(new_skb);
-            	
-		} else {
-			chan->drvstats_gen.UDP_PIPE_mgmt_no_socket ++;
-			printk(KERN_INFO 
-			"%s: UDP mgmt cmnd, no socket buffers available!\n", 
-			card->devname);
-            	}
-        }
-
-	card->u.f.udp_pkt_lgth = 0;
-
-	return 1;
-}
-
-/*==============================================================================
- * Send Inverse ARP Request
- */
-
-int send_inarp_request(sdla_t *card, struct net_device *dev)
-{
-	int err=0;
-
-	arphdr_1490_t *ArpPacket;
-	arphdr_fr_t *arphdr;
-	fr_channel_t *chan = dev->priv;
-	struct in_device *in_dev;
-
-	in_dev = dev->ip_ptr;
-
-	if(in_dev != NULL ) {	
-
-		ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC);
-		/* SNAP Header indicating ARP */
-		ArpPacket->control	= 0x03;
-		ArpPacket->pad		= 0x00;
-		ArpPacket->NLPID	= 0x80;
-		ArpPacket->OUI[0]	= 0;
-		ArpPacket->OUI[1]	= 0;
-		ArpPacket->OUI[2]	= 0;
-		ArpPacket->PID		= 0x0608;
-
-		arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet
-
-		/* InARP request */		
-		arphdr->ar_hrd = 0x0F00;	/* Frame Relay HW type */
-		arphdr->ar_pro = 0x0008;	/* IP Protocol	       */
-		arphdr->ar_hln = 2;		/* HW addr length      */
-		arphdr->ar_pln = 4;		/* IP addr length      */
-		arphdr->ar_op = htons(0x08);	/* InARP Request       */
-		arphdr->ar_sha = 0; 		/* src HW DLCI - Doesn't matter */
-		if(in_dev->ifa_list != NULL)
-			arphdr->ar_sip = in_dev->ifa_list->ifa_local;  /* Local Address       */else
-			arphdr->ar_sip = 0;
-		arphdr->ar_tha = 0; 		/* dst HW DLCI - Doesn't matter */
-		arphdr->ar_tip = 0;		/* Remote Address -- what we want */
-
-		err = fr_send(card, chan->dlci, 0, sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t),
-		   			(void *)ArpPacket);
-
-		if (!err){
-			printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n", 
-				card->devname, chan->dlci);
-			clear_bit(ARP_CRIT,&card->wandev.critical);
-		}
-
-		kfree(ArpPacket);
-	}else{
-		printk(KERN_INFO "%s: INARP ERROR: %s doesn't have a local IP address!\n",
-				card->devname,dev->name);
-		return 1;
-	}
-
-	return 0;
-}
-	
-
-/*==============================================================================
- * Check packet for ARP Type
- */
-
-int is_arp(void *buf)
-{
-	arphdr_1490_t *arphdr = (arphdr_1490_t *)buf;
-	
-	if (arphdr->pad   == 0x00  &&
-	    arphdr->NLPID == 0x80  &&
-	    arphdr->PID   == 0x0608) 
-		return 1;
-	else return 0;
-}
-
-/*==============================================================================
- * Process ARP Packet Type
- */
-
-int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device* dev)
-{
-
-
-	arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */
-	fr_rx_buf_ctl_t* frbuf = card->rxmb;
-	struct in_device *in_dev;
-	fr_channel_t *chan = dev->priv;		
-	
-	/* Before we transmit ARP packet, we must check 
-	 * to see that we are not currently transmitting a 
-	 * frame (in 'if_send()') and that we are not 
-	 * already in a 'delayed transmit' state. */
-	if (check_tx_status(card,dev)){
-		if (net_ratelimit()){ 	
-			printk(KERN_INFO "%s: Disabling comminication to process ARP\n",
-					card->devname);
-		}
-		set_bit(ARP_CRIT,&card->wandev.critical);
-		return 0;
-	}
-
-	in_dev = dev->ip_ptr;
-
-	/* Check that IP addresses exist for our network address */
-	if (in_dev == NULL || in_dev->ifa_list == NULL) 
-		return -1;
-
-	switch (ntohs(arphdr->ar_op)) {
-
-	case 0x08:  // Inverse ARP request  -- Send Reply, add route.
-			
-		/* Check for valid Address */
-		printk(KERN_INFO "%s: Recvd PtP addr -InArp Req: %u.%u.%u.%u\n", 
-			card->devname, NIPQUAD(arphdr->ar_sip));
-
-
-		/* Check that the network address is the same as ours, only
-                 * if the netowrk mask is not 255.255.255.255. Otherwise
-                 * this check would not make sense */
-
-		if (in_dev->ifa_list->ifa_mask != 0xFFFFFFFF && 
-		    (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != 
-		    (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)){
-			printk(KERN_INFO 
-				"%s: Invalid PtP address. %u.%u.%u.%u  InARP ignored.\n", 
-					card->devname,NIPQUAD(arphdr->ar_sip));
-
-			printk(KERN_INFO "%s: mask %u.%u.%u.%u\n", 
-				card->devname, NIPQUAD(in_dev->ifa_list->ifa_mask));
-				printk(KERN_INFO "%s: local %u.%u.%u.%u\n", 
-				card->devname,NIPQUAD(in_dev->ifa_list->ifa_local));
-			return -1;
-		}
-
-		if (in_dev->ifa_list->ifa_local == arphdr->ar_sip){
-			printk(KERN_INFO 
-				"%s: Local addr = PtP addr.  InARP ignored.\n", 
-					card->devname);
-			return -1;
-		}
-	
-		arphdr->ar_op = htons(0x09);	/* InARP Reply */
-
-		/* Set addresses */
-		arphdr->ar_tip = arphdr->ar_sip;
-		arphdr->ar_sip = in_dev->ifa_list->ifa_local;
-
-		chan->ip_local = in_dev->ifa_list->ifa_local;
-		chan->ip_remote = arphdr->ar_sip;
-
-		fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket);
-
-		if (test_bit(ARP_CRIT,&card->wandev.critical)){
-			if (net_ratelimit()){ 	
-				printk(KERN_INFO "%s: ARP Processed Enabling Communication!\n",
-					card->devname);
-			}
-		}
-		clear_bit(ARP_CRIT,&card->wandev.critical);
-		
-		chan->ip_local = in_dev->ifa_list->ifa_local;
-		chan->ip_remote = arphdr->ar_sip;
-
-		/* Add Route Flag */
-		/* The route will be added in the polling routine so
-		   that it is not interrupt context. */
-
-		chan->route_flag = ADD_ROUTE;
-		trigger_fr_poll (dev);
-
-		break;
-
-	case 0x09:  // Inverse ARP reply
-
-		/* Check for valid Address */
-		printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", 
-				card->devname, NIPQUAD(arphdr->ar_sip));
-
-
-		/* Compare network addresses, only if network mask
-                 * is not 255.255.255.255  It would not make sense
-                 * to perform this test if the mask was all 1's */
-
-		if (in_dev->ifa_list->ifa_mask != 0xffffffff &&
-		    (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != 
-			(in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)) {
-
-			printk(KERN_INFO "%s: Invalid PtP address.  InARP ignored.\n", 
-					card->devname);
-			return -1;
-		}
-
-		/* Make sure that the received IP address is not
-                 * the same as our own local address */
-		if (in_dev->ifa_list->ifa_local == arphdr->ar_sip) {
-			printk(KERN_INFO "%s: Local addr = PtP addr.  InARP ignored.\n", 
-				card->devname);
-			return -1;
-		}			
-
-		chan->ip_local  = in_dev->ifa_list->ifa_local;
-		chan->ip_remote = arphdr->ar_sip;
-
-		/* Add Route Flag */
-		/* The route will be added in the polling routine so
-		   that it is not interrupt context. */
-
-		chan->route_flag = ADD_ROUTE;
-		chan->inarp = INARP_CONFIGURED;
-		trigger_fr_poll(dev);
-		
-		break;
-	default:
-		break; // ARP's and RARP's -- Shouldn't happen.
-	}
-
-	return 0;	
-}
-
-
-/*============================================================
- * trigger_fr_arp
- *
- * Description:
- * 	Add an fr_arp() task into a arp
- *      timer handler for a specific dlci/interface.  
- *      This will kick the fr_arp() routine 
- *      within the specified time interval. 
- *
- * Usage:
- * 	This timer is used to send ARP requests at
- *      certain time intervals. 
- * 	Called by an interrupt to request an action
- *      at a later date.
- */	
-
-static void trigger_fr_arp(struct net_device *dev)
-{
-	fr_channel_t* chan = dev->priv;
-
-	mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ);
-	return;
-}
-
-
-
-/*==============================================================================
- * ARP Request Action
- *
- *	This funciton is called by timer interrupt to send an arp request
- *      to the remote end.
- */
-
-static void fr_arp (unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	fr_channel_t *chan = dev->priv;
-	volatile sdla_t *card = chan->card;
-	fr508_flags_t* flags = card->flags;
-
-	/* Send ARP packets for all devs' until
-         * ARP state changes to CONFIGURED */
-
-	if (chan->inarp == INARP_REQUEST &&
-	    chan->common.state == WAN_CONNECTED && 
-	    card->wandev.state == WAN_CONNECTED){
-		set_bit(0,&chan->inarp_ready);
-		card->u.f.timer_int_enabled |= TMR_INT_ENABLED_ARP;
-		flags->imask |= FR_INTR_TIMER;	
-	}
- 
-	return;
-}
-	
-
-/*==============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR_
- * TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card )
-{
-	fr_mbox_t* mb = card->mbox;
-	int err,i;
-
-        err = fr_set_intr_mode(card, FR_INTR_READY, card->wandev.mtu, 0 );
-	
-	if (err == CMD_OK) {
-
-		for ( i = 0; i < MAX_INTR_TEST_COUNTER; i++ ) {
- 			/* Run command READ_CODE_VERSION */
-			mb->cmd.length  = 0;
-			mb->cmd.command = FR_READ_CODE_VERSION;
-			err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-			if (err != CMD_OK) 
-				fr_event(card, err, mb);
-		}
-	
-	} else {
-		return err;	
-	}
-
-	err = fr_set_intr_mode( card, 0, card->wandev.mtu, 0 );
-
-	if( err != CMD_OK ) 
-		return err;
-
-	return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. FPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
-	fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)skb->data;
-
-	/* Quick HACK */
-	
-	
-        if((fr_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
-		(fr_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
-		(fr_udp_pkt->udp_pkt.udp_dst_port == 
-		ntohs(card->wandev.udp_port)) &&
-		(fr_udp_pkt->wp_mgmt.request_reply == 
-		UDPMGMT_REQUEST)) {
-                        if(!strncmp(fr_udp_pkt->wp_mgmt.signature,
-                                UDPMGMT_FPIPE_SIGNATURE, 8)){
-                                return UDP_FPIPE_TYPE;
-			}
-	}
-        return UDP_INVALID_TYPE;
-}
-
-
-/*==============================================================================
- * Initializes the Statistics values in the fr_channel structure.
- */
-void init_chan_statistics( fr_channel_t* chan)
-{
-        memset(&chan->drvstats_if_send.if_send_entry, 0,
-		sizeof(if_send_stat_t));
-        memset(&chan->drvstats_rx_intr.rx_intr_no_socket, 0,
-                sizeof(rx_intr_stat_t));
-        memset(&chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, 0,
-                sizeof(pipe_mgmt_stat_t));
-}
-	
-/*==============================================================================
- * Initializes the Statistics values in the Sdla_t structure.
- */
-void init_global_statistics( sdla_t* card )
-{
-	/* Intialize global statistics for a card */
-        memset(&card->statistics.isr_entry, 0, sizeof(global_stats_t));
-}
-
-static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan )
-{
-	fr_mbox_t* mbox = card->mbox;
-	int retry = MAX_CMD_RETRY;	
-	dlci_IB_mapping_t* result; 
-	int err, counter, found;	
-
-	do {
-		mbox->cmd.command = FR_READ_DLCI_IB_MAPPING;
-		mbox->cmd.length = 0;	
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && fr_event(card, err, mbox));
-
-	if( mbox->cmd.result != 0){
-		printk(KERN_INFO "%s: Read DLCI IB Mapping failed\n", 
-			chan->name);
-	}
-
-	counter = mbox->cmd.length / sizeof(dlci_IB_mapping_t);
-	result = (void *)mbox->data;
-	
-	found = 0;
-	for (; counter; --counter, ++result) {
-		if ( result->dlci == chan->dlci ) {
-			chan->IB_addr = result->addr_value;
-			if(card->hw.type == SDLA_S514){
-	             		chan->dlci_int_interface =
-					(void*)(card->hw.dpmbase +
-					chan->IB_addr);
-       			}else{ 
-				chan->dlci_int_interface = 
-					(void*)(card->hw.dpmbase + 
-					(chan->IB_addr & 0x00001FFF));
-
-			}
-			found = 1;
-			break;	
-		} 
-	}
-	if (!found)
-		printk( KERN_INFO "%s: DLCI %d not found by IB MAPPING cmd\n", 
-		card->devname, chan->dlci);
-}
-
-
-
-void s508_s514_lock(sdla_t *card, unsigned long *smp_flags)
-{
-	if (card->hw.type != SDLA_S514){
-
-		spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-	}else{
-		spin_lock(&card->u.f.if_send_lock);
-	}
-	return;
-}
-
-
-void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
-	if (card->hw.type != SDLA_S514){
-
-		spin_unlock_irqrestore (&card->wandev.lock, *smp_flags);
-	}else{
-		spin_unlock(&card->u.f.if_send_lock);
-	}
-	return;
-}
-
-
-
-/*----------------------------------------------------------------------
-                  RECEIVE INTERRUPT: BOTTOM HALF HANDLERS 
- ----------------------------------------------------------------------*/
-
-
-/*========================================================
- * bh_enqueue
- *
- * Description:
- *	Insert a received packet into a circular
- *      rx queue.  This packet will be picked up 
- *      by fr_bh() and sent up the stack to the
- *      user.
- *       	
- * Usage: 
- *	This function is called by rx interrupt,
- *      in API mode.
- *
- */
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
-	/* Check for full */
-	fr_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-
-
-	if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){
-		++card->wandev.stats.rx_dropped;
-		dev_kfree_skb_any(skb);
-		return 1; 
-	}
-
-	((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
-	if (chan->bh_write == (MAX_BH_BUFF-1)){
-		chan->bh_write=0;
-	}else{
-		++chan->bh_write;
-	}
-
-	atomic_inc(&chan->bh_buff_used);
-
-	return 0;
-}
-
-
-/*========================================================
- * trigger_fr_bh
- *
- * Description:
- * 	Kick the fr_bh() handler
- *
- * Usage:
- *	rx interrupt calls this function during
- *      the API mode. 
- */
-
-static void trigger_fr_bh (fr_channel_t *chan)
-{
-	if (!test_and_set_bit(0,&chan->tq_working)){
-		wanpipe_queue_work(&chan->common.wanpipe_work);
-	}
-}
-
-
-/*========================================================
- * fr_bh
- *
- * Description:
- *	Frame relay receive BH handler. 
- *	Dequeue data from the BH circular 
- *	buffer and pass it up the API sock.
- *       	
- * Rationale: 
- *	This fuction is used to offload the 
- *	rx_interrupt during API operation mode.  
- *	The fr_bh() function executes for each 
- *	dlci/interface.  
- * 
- *      Once receive interrupt copies data from the
- *      card into an skb buffer, the skb buffer
- *  	is appended to a circular BH buffer.
- *  	Then the interrupt kicks fr_bh() to finish the
- *      job at a later time (not within the interrupt).
- *       
- * Usage:
- * 	Interrupts use this to defer a task to 
- *      a polling routine.
- *
- */	
-
-static void fr_bh(struct net_device * dev)
-{
-	fr_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	struct sk_buff *skb;
-
-	if (atomic_read(&chan->bh_buff_used) == 0){
-		clear_bit(0, &chan->tq_working);
-		return;
-	}
-
-	while (atomic_read(&chan->bh_buff_used)){
-
-		if (chan->common.sk == NULL || chan->common.func == NULL){
-			clear_bit(0, &chan->tq_working);
-			return;
-		}
-
-		skb  = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
-		if (skb != NULL){
-
-			if (chan->common.sk == NULL || chan->common.func == NULL){
-				++card->wandev.stats.rx_dropped;
-				++chan->ifstats.rx_dropped;
-				dev_kfree_skb_any(skb);
-				fr_bh_cleanup(dev);
-				continue;
-			}
-
-			if (chan->common.func(skb,dev,chan->common.sk) != 0){
-				/* Sock full cannot send, queue us for
-                                 * another try */
-				atomic_set(&chan->common.receive_block,1);
-				return;
-			}else{
-				fr_bh_cleanup(dev);
-			}
-		}else{
-			fr_bh_cleanup(dev);
-		}
-	}	
-	clear_bit(0, &chan->tq_working);
-
-	return;
-}
-
-static int fr_bh_cleanup(struct net_device *dev)
-{
-	fr_channel_t* chan = dev->priv;
-
-	((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
-	if (chan->bh_read == (MAX_BH_BUFF-1)){
-		chan->bh_read=0;
-	}else{
-		++chan->bh_read;	
-	}
-
-	atomic_dec(&chan->bh_buff_used);
-	return 0;
-}
-
-
-/*----------------------------------------------------------------------
-               POLL BH HANDLERS AND KICK ROUTINES 
- ----------------------------------------------------------------------*/
-
-/*============================================================
- * trigger_fr_poll
- *
- * Description:
- * 	Add a fr_poll() task into a tq_scheduler bh handler
- *      for a specific dlci/interface.  This will kick
- *      the fr_poll() routine at a later time. 
- *
- * Usage:
- * 	Interrupts use this to defer a taks to 
- *      a polling routine.
- *
- */	
-static void trigger_fr_poll(struct net_device *dev)
-{
-	fr_channel_t* chan = dev->priv;
-	schedule_work(&chan->fr_poll_work);
-	return;
-}
-
-
-/*============================================================
- * fr_poll
- *	
- * Rationale:
- * 	We cannot manipulate the routing tables, or
- *      ip addresses withing the interrupt. Therefore
- *      we must perform such actons outside an interrupt 
- *      at a later time. 
- *
- * Description:	
- *	Frame relay polling routine, responsible for 
- *     	shutting down interfaces upon disconnect
- *     	and adding/removing routes. 
- *      
- * Usage:        
- * 	This function is executed for each frame relay
- * 	dlci/interface through a tq_schedule bottom half.
- *      
- *      trigger_fr_poll() function is used to kick
- *      the fr_poll routine.  
- */
-
-static void fr_poll(struct net_device *dev)
-{
-
-	fr_channel_t* chan;
-	sdla_t *card;
-	u8 check_gateway=0;
-
-	if (!dev || (chan = dev->priv) == NULL)
-		return;
-
-	card = chan->card;
-	
-	/* (Re)Configuraiton is in progress, stop what you are 
-	 * doing and get out */
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		return;
-	}
-
-	switch (chan->common.state){
-
-	case WAN_DISCONNECTED:
-
-		if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
-		    !test_bit(DEV_DOWN, &chan->interface_down) &&
-		    dev->flags&IFF_UP){
-
-			printk(KERN_INFO "%s: Interface %s is Down.\n", 
-				card->devname,dev->name);
-			change_dev_flags(dev,dev->flags&~IFF_UP);
-			set_bit(DEV_DOWN, &chan->interface_down);
-			chan->route_flag = NO_ROUTE;
-			
-		}else{
-			if (chan->inarp != INARP_NONE)
-				process_route(dev);	
-		}
-		break;
-
-	case WAN_CONNECTED:
-
-		if (test_bit(DYN_OPT_ON,&chan->interface_down) &&
-		    test_bit(DEV_DOWN, &chan->interface_down) &&
-		    !(dev->flags&IFF_UP)){
-
-			printk(KERN_INFO "%s: Interface %s is Up.\n", 
-					card->devname,dev->name);
-
-			change_dev_flags(dev,dev->flags|IFF_UP);
-			clear_bit(DEV_DOWN, &chan->interface_down);
-			check_gateway=1;
-		}
-
-		if (chan->inarp != INARP_NONE){
-			process_route(dev);
-			check_gateway=1;
-		}
-
-		if (chan->gateway && check_gateway)
-			add_gateway(card,dev);
-
-		break;
-
-	}
-
-	return;	
-}
-
-/*==============================================================
- * check_tx_status
- *
- * Rationale:
- *	We cannot transmit from an interrupt while
- *      the if_send is transmitting data.  Therefore,
- *      we must check whether the tx buffers are
- *      begin used, before we transmit from an
- *      interrupt.	
- * 
- * Description:	
- *	Checks whether it's safe to use the transmit 
- *      buffers. 
- *
- * Usage:
- * 	ARP and UDP handling routines use this function
- *      because, they need to transmit data during
- *      an interrupt.
- */
-
-static int check_tx_status(sdla_t *card, struct net_device *dev)
-{
-
-	if (card->hw.type == SDLA_S514){
-		if (test_bit(SEND_CRIT, (void*)&card->wandev.critical) ||
-			test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) {
-			return 1;
-		}
-	}
-
-	if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending))
-     		return 1; 
-
-	return 0;
-}
-
-/*===============================================================
- * move_dev_to_next
- *  
- * Description:
- *	Move the dev pointer to the next location in the
- *      link list.  Check if we are at the end of the 
- *      list, if so start from the begining.
- *
- * Usage:
- * 	Timer interrupt uses this function to efficiently
- *      step through the devices that need to send ARP data.
- *
- */
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
-	if (card->wandev.new_if_cnt != 1){
-		if (!*((struct net_device **)dev->priv))
-			return card->wandev.dev;
-		else
-			return *((struct net_device **)dev->priv);
-	}
-	return dev;
-}
-
-/*==============================================================
- * trigger_config_fr
- *
- * Rationale:
- *	All commands must be performed inside of a  
- *      interrupt.   
- *
- * Description:
- *	Kick the config_fr() routine throught the
- *      timer interrupt.
- */
-
-
-static void trigger_config_fr (sdla_t *card)
-{
-	fr508_flags_t* flags = card->flags;
-
-	card->u.f.timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
-	flags->imask |= FR_INTR_TIMER;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- * 	All commands must be performed inside of a  
- *      interrupt.  
- &
- * Description:	
- * 	Configure a DLCI. This function is executed
- *      by a timer_interrupt.  The if_open() function
- *      triggers it.
- *
- * Usage:
- *	new_if() collects all data necessary to
- *      configure the DLCI. It sets the chan->dlci_ready 
- *      bit.  When the if_open() function is executed
- *      it checks this bit, and if its set it triggers
- *      the timer interrupt to execute the config_fr()
- *      function.
- */
-
-static void config_fr (sdla_t *card)
-{
-	struct net_device *dev;
-	fr_channel_t *chan;
-
-	for (dev = card->wandev.dev; dev;
-	     dev = *((struct net_device **)dev->priv)) {
-	
-		if ((chan=dev->priv) == NULL)
-			continue;
-		
-		if (!test_bit(0,&chan->config_dlci))
-			continue;
-
-		clear_bit(0,&chan->config_dlci);
-
-		/* If signalling is set to NO, then setup 
-        	 * DLCI addresses right away.  Don't have to wait for
-		 * link to connect. 
-		 */
-		if (card->wandev.signalling == WANOPT_NO){
-			printk(KERN_INFO "%s: Signalling set to NO: Mapping DLCI's\n",
-					card->wandev.name);
-			if (fr_init_dlci(card,chan)){
-				printk(KERN_INFO "%s: ERROR: Failed to configure DLCI %i !\n",
-					card->devname, chan->dlci);
-				return;
-			}
-		}
-
-		if (card->wandev.station == WANOPT_CPE) {
-	
-			update_chan_state(dev);	
-			
-			/* CPE: issue full status enquiry */
-			fr_issue_isf(card, FR_ISF_FSE);
-
-		} else {	
-			/* FR switch: activate DLCI(s) */
-	
-			/* For Switch emulation we have to ADD and ACTIVATE
-			 * the DLCI(s) that were configured with the SET_DLCI_
-			 * CONFIGURATION command. Add and Activate will fail if
-			 * DLCI specified is not included in the list.
-			 *
-			 * Also If_open is called once for each interface. But
-			 * it does not get in here for all the interface. So
-		 	 * we have to pass the entire list of DLCI(s) to add 
-			 * activate routines.  
-			 */ 
-			
-			if (!check_dlci_config (card, chan)){
-				fr_add_dlci(card, chan->dlci);
-				fr_activate_dlci(card, chan->dlci);
-			}
-		}
-
-		card->u.f.dlci_to_dev_map[chan->dlci] = dev;
-	}
-	return;
-}
-
-
-/*==============================================================
- * config_fr
- *
- * Rationale:
- *	All commands must be executed during an interrupt.
- * 
- * Description:	
- *	Trigger uncofig_fr() function through 
- *      the timer interrupt.
- *
- */
-
-static void trigger_unconfig_fr(struct net_device *dev)
-{
-	fr_channel_t *chan = dev->priv;
-	volatile sdla_t *card = chan->card;
-	unsigned long timeout;
-	fr508_flags_t* flags = card->flags;
-	int reset_critical=0;
-	
-	if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
-		clear_bit(PERI_CRIT,(void*)&card->wandev.critical);
-		reset_critical=1;
-	}
-		
-	/* run unconfig_dlci() function 
-         * throught the timer interrupt */
-	set_bit(0,(void*)&chan->unconfig_dlci);
-	card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UNCONFIG;
-	flags->imask |= FR_INTR_TIMER;
-
-	/* Wait for the command to complete */
-	timeout = jiffies;
-     	for(;;) {
-
-		if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG))
-			break;
-
-             	if (time_after(jiffies, timeout + 1 * HZ)){
-    			card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG;
-			printk(KERN_INFO "%s: Failed to delete DLCI %i\n",
-				card->devname,chan->dlci);
- 			break;
-		}
-	}
-
-	if (reset_critical){
-		set_bit(PERI_CRIT,(void*)&card->wandev.critical);
-	}
-}
-
-/*==============================================================
- * unconfig_fr
- *
- * Rationale:
- *	All commands must be executed during an interrupt.
- * 
- * Description:	
- *	Remove the dlci from firmware.
- *	This funciton is used in NODE shutdown.
- */
-
-static void unconfig_fr (sdla_t *card)
-{
-	struct net_device *dev;
-	fr_channel_t *chan;
-
-	for (dev = card->wandev.dev; dev;
-	     dev = *((struct net_device **)dev->priv)){
-	
-		if ((chan=dev->priv) == NULL)
-			continue;
-		
-		if (!test_bit(0,&chan->unconfig_dlci))
-			continue;
-
-		clear_bit(0,&chan->unconfig_dlci);
-
-		if (card->wandev.station == WANOPT_NODE){
-			printk(KERN_INFO "%s: Unconfiguring DLCI %i\n",
-					card->devname,chan->dlci);
-			fr_delete_dlci(card,chan->dlci);
-		}
-		card->u.f.dlci_to_dev_map[chan->dlci] = NULL;
-	}
-}
-
-static int setup_fr_header(struct sk_buff *skb, struct net_device* dev,
-			   char op_mode)
-{
-	fr_channel_t *chan=dev->priv;
-
-	if (op_mode == WANPIPE) {
-		chan->fr_header[0]=Q922_UI;
-		
-		switch (htons(skb->protocol)){
-		case ETH_P_IP:
-			chan->fr_header[1]=NLPID_IP;
-			break;
-		default:
-			return -EINVAL;
-		}
-			
-		return 2;
-	}
-
-	/* If we are in bridging mode, we must apply
-	 * an Ethernet header
-	 */
-	if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) {
-		/* Encapsulate the packet as a bridged Ethernet frame. */
-#ifdef DEBUG
-		printk(KERN_INFO "%s: encapsulating skb for frame relay\n", 
-			dev->name);
-#endif
-		chan->fr_header[0] = 0x03;
-		chan->fr_header[1] = 0x00;
-		chan->fr_header[2] = 0x80;
-		chan->fr_header[3] = 0x00;
-		chan->fr_header[4] = 0x80;
-		chan->fr_header[5] = 0xC2;
-		chan->fr_header[6] = 0x00;
-		chan->fr_header[7] = 0x07;
-
-		/* Yuck. */
-		skb->protocol = ETH_P_802_3;
-		return 8;
-	}
-		
-	return 0;
-}
-
-
-static int check_dlci_config (sdla_t *card, fr_channel_t *chan)
-{
-	fr_mbox_t* mbox = card->mbox;
-	int err=0;
-	fr_conf_t *conf=NULL;
-	unsigned short dlci_num = chan->dlci;
-	int dlci_offset=0;
-	struct net_device *dev = NULL;
-	
-	mbox->cmd.command = FR_READ_CONFIG;
-	mbox->cmd.length = 0;
-	mbox->cmd.dlci = dlci_num; 	
-
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	
-	if (err == CMD_OK){
-		return 0;
-	}
-
-	for (dev = card->wandev.dev; dev;
-	     dev=*((struct net_device **)dev->priv))
-		set_chan_state(dev,WAN_DISCONNECTED);
-	
-	printk(KERN_INFO "DLCI %i Not configured, configuring\n",dlci_num);
-	
-	mbox->cmd.command = FR_COMM_DISABLE;
-	mbox->cmd.length = 0;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err != CMD_OK){
-		fr_event(card, err, mbox);
-		return 2;
-	}
-
-	printk(KERN_INFO "Disabled Communications \n");
-	
-	mbox->cmd.command = FR_READ_CONFIG;
-	mbox->cmd.length = 0;
-	mbox->cmd.dlci = 0; 	
-
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	
-	if (err != CMD_OK){
-		fr_event(card, err, mbox);
-		return 2;
-	}
-	
-	conf = (fr_conf_t *)mbox->data;
-
-	dlci_offset=0;
-	for (dev = card->wandev.dev; dev;
-	     dev = *((struct net_device **)dev->priv)) {
-		fr_channel_t *chan_tmp = dev->priv;
-		conf->dlci[dlci_offset] = chan_tmp->dlci;		
-		dlci_offset++;
-	}
-	
-	printk(KERN_INFO "Got Fr configuration Buffer Length is %x Dlci %i Dlci Off %i\n",
-		mbox->cmd.length,
-		mbox->cmd.length > 0x20 ? conf->dlci[0] : -1, 
-		dlci_offset );
-	
-	mbox->cmd.length = 0x20 + dlci_offset*2;
-
-	mbox->cmd.command = FR_SET_CONFIG;
-	mbox->cmd.dlci = 0; 
-
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK){
-		fr_event(card, err, mbox);
-		return 2;
-	}
-
-	initialize_rx_tx_buffers (card);
-
-	
-	printk(KERN_INFO "Configuraiton Succeded for new DLCI %i\n",dlci_num);
-
-	if (fr_comm_enable (card)){
-		return 2;
-	}
-
-	printk(KERN_INFO "Enabling Communications \n");
-
-	for (dev = card->wandev.dev; dev;
-	     dev = *((struct net_device **)dev->priv)) {
-		fr_channel_t *chan_tmp = dev->priv;
-		fr_init_dlci(card,chan_tmp);
-		fr_add_dlci(card, chan_tmp->dlci);
-		fr_activate_dlci(card, chan_tmp->dlci);
-	}
-
-	printk(KERN_INFO "END OF CONFIGURAITON %i\n",dlci_num);
-	
-	return 1;
-}
-
-static void initialize_rx_tx_buffers (sdla_t *card)
-{
-	fr_buf_info_t* buf_info;
-	
-	if (card->hw.type == SDLA_S514) {
-	
-                buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR +
-			FR508_RXBC_OFFS);
-
-                card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase);
-
-                card->u.f.rxmb_base =
-                        (void*)(buf_info->rse_base + card->hw.dpmbase); 
-
-                card->u.f.rxmb_last =
-                        (void*)(buf_info->rse_base +
-                        (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) +
-                        card->hw.dpmbase);
-	}else{	
-		buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS);
-
-		card->rxmb = (void*)(buf_info->rse_next -
-			FR_MB_VECTOR + card->hw.dpmbase);
-		
-		card->u.f.rxmb_base =
-			(void*)(buf_info->rse_base -
-			FR_MB_VECTOR + card->hw.dpmbase);
-		
-		card->u.f.rxmb_last =
-			(void*)(buf_info->rse_base +
-			(buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) -
-			FR_MB_VECTOR + card->hw.dpmbase);
-	}
-
-	card->u.f.rx_base = buf_info->buf_base;
-	card->u.f.rx_top  = buf_info->buf_top;
-
-	card->u.f.tx_interrupts_pending = 0;
-
-	return;
-}
-
-	
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c
deleted file mode 100644
index 9d6528a..0000000
--- a/drivers/net/wan/sdla_ft1.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*****************************************************************************
-* sdla_chdlc.c	WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
-*
-* Authors: 	Nenad Corbic <ncorbic@sangoma.com>
-*		Gideon Hack  
-*
-* Copyright:	(c) 1995-1999 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Sep 30, 1999  Nenad Corbic    Fixed dynamic IP and route setup.
-* Sep 23, 1999  Nenad Corbic    Added SMP support, fixed tracing 
-* Sep 13, 1999  Nenad Corbic	Split up Port 0 and 1 into separate devices.
-* Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.
-* Oct 30, 1998	Jaspreet Singh	Added Support for CHDLC API (HDLC STREAMING).
-* Oct 28, 1998	Jaspreet Singh	Added Support for Dual Port CHDLC.
-* Aug 07, 1998	David Fong	Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>		/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/if_arp.h>	/* ARPHRD_* defines */
-#include <linux/jiffies.h>	/* time_after() macro */
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <linux/in.h>		/* sockaddr_in */
-#include <linux/inet.h>	
-#include <linux/if.h>
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h>		/* CHDLC firmware API definitions */
-
-/****** Defines & Macros ****************************************************/
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP   	0x0001
-#define TMR_INT_ENABLED_UPDATE	0x0002
- 
-#define	CHDLC_DFLT_DATA_LEN	1500		/* default MTU */
-#define CHDLC_HDR_LEN		1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define WANPIPE 0x00
-#define API	0x01
-#define CHDLC_API 0x01
-
-#define PORT(x)   (x == 0 ? "PRIMARY" : "SECONDARY" )
-
- 
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following 
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
-	struct net_device *slave;
-	sdla_t		*card;
-	int 		TracingEnabled;		/* For enabling Tracing */
-	unsigned long 	curr_trace_addr;	/* Used for Tracing */
-	unsigned long 	start_trace_addr;
-	unsigned long 	end_trace_addr;
-	unsigned long 	base_addr_trace_buffer;
-	unsigned long 	end_addr_trace_buffer;
-	unsigned short 	number_trace_elements;
-	unsigned  	available_buffer_space;
-	unsigned long 	router_start_time;
-	unsigned char 	route_status;
-	unsigned char 	route_removed;
-	unsigned long 	tick_counter;		/* For 5s timeout counter */
-	unsigned long 	router_up_time;
-        u32             IP_address;		/* IP addressing */
-        u32             IP_netmask;
-	unsigned char  mc;			/* Mulitcast support on/off */
-	unsigned short udp_pkt_lgth;		/* udp packet processing */
-	char udp_pkt_src;
-	char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-	unsigned short timer_int_enabled;
-	char update_comms_stats;		/* updating comms stats */
-	//FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE	0x00
-#define ADD_ROUTE	0x01
-#define ROUTE_ADDED	0x02
-#define REMOVE_ROUTE	0x03
-
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup.  At this
- * point adapter is completely initialized and firmware is running.
- *  o read firmware version (to make sure it's alive)
- *  o configure adapter
- *  o initialize protocol-specific fields of the adapter data space.
- *
- * Return:	0	o.k.
- *		< 0	failure.
- */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf)
-{
-	unsigned char port_num;
-	int err;
-
-	union
-		{
-		char str[80];
-		} u;
-	volatile CHDLC_MAILBOX_STRUCT* mb;
-	CHDLC_MAILBOX_STRUCT* mb1;
-	unsigned long timeout;
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_CHDLC) {
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-				  card->devname, conf->config_id);
-		return -EINVAL;
-	}
-
-	/* Use primary port */
-	card->u.c.comm_port = 0;
-	
-
-	/* Initialize protocol-specific fields */
-	if(card->hw.type != SDLA_S514){
-		card->mbox  = (void *) card->hw.dpmbase;
-	}else{ 
-		card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
-	}
-
-	mb = mb1 = card->mbox;
-
-	if (!card->configured){
-
-		/* The board will place an 'I' in the return code to indicate that it is
-	   	ready to accept commands.  We expect this to be completed in less
-           	than 1 second. */
-
-		timeout = jiffies;
-		while (mb->return_code != 'I')	/* Wait 1s for board to initialize */
-			if (time_after(jiffies, timeout + 1*HZ)) break;
-
-		if (mb->return_code != 'I') {
-			printk(KERN_INFO
-				"%s: Initialization not completed by adapter\n",
-				card->devname);
-			printk(KERN_INFO "Please contact Sangoma representative.\n");
-			return -EIO;
-		}
-	}
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-
-	if (chdlc_read_version(card, u.str))
-		return -EIO;
-
-	printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
-		card->devname, u.str); 
-
-	card->isr			= NULL;
-	card->poll			= NULL;
-	card->exec			= &wpft1_exec;
-	card->wandev.update		= NULL;
- 	card->wandev.new_if		= NULL;
-	card->wandev.del_if		= NULL;
-	card->wandev.state		= WAN_DUALPORT;
-	card->wandev.udp_port   	= conf->udp_port;
-
-	card->wandev.new_if_cnt = 0;
-
-	/* This is for the ports link state */
-	card->u.c.state = WAN_DISCONNECTED;
-	
-	/* reset the number of times the 'update()' proc has been called */
-	card->u.c.update_call_count = 0;
-	
-	card->wandev.ttl = 0x7F;
-	card->wandev.interface = 0; 
-
-	card->wandev.clocking = 0;
-
-	port_num = card->u.c.comm_port;
-
-	/* Setup Port Bps */
-
-       	card->wandev.bps = 0;
-
-	card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
-
-	/* Set up the interrupt status area */
-	/* Read the CHDLC Configuration and obtain: 
-	 *	Ptr to shared memory infor struct
-         * Use this pointer to calculate the value of card->u.c.flags !
- 	 */
-	mb1->buffer_length = 0;
-	mb1->command = READ_CHDLC_CONFIGURATION;
-	err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
-	if(err != COMMAND_OK) {
-		chdlc_error(card, err, mb1);
-		return -EIO;
-	}
-
-	if(card->hw.type == SDLA_S514){
-               	card->u.c.flags = (void *)(card->hw.dpmbase +
-               		(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct));
-        }else{
-                card->u.c.flags = (void *)(card->hw.dpmbase +
-                        (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
-	}
-
-	card->wandev.state = WAN_FT1_READY;
-	printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
-
-	return 0;
-}
-
-static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
-{
-	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
-	int len;
-
-	if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
-		return -EFAULT;
-	}
-
-	len = mbox->buffer_length;
-
-	if (len) {
-		if( copy_from_user((void*)&mbox->data, u_data, len)){
-			return -EFAULT;
-		}
-	}
-
-	/* execute command */
-	if (!sdla_exec(mbox)){
-		return -EIO;
-	}
-
-	/* return result */
-	if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
-		return -EFAULT;
-	}
-
-	len = mbox->buffer_length;
-
-	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
-		return -EFAULT;
-	}
-
-	return 0;
-
-}
-
-/*============================================================================
- * Read firmware code version.
- *	Put code version as ASCII string in str. 
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int len;
-	char err;
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_CODE_VERSION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	if(err != COMMAND_OK) {
-		chdlc_error(card,err,mb);
-	}
-	else if (str) {  /* is not null */
-		len = mb->buffer_length;
-		memcpy(str, mb->data, len);
-		str[len] = '\0';
-	}
-	return (err);
-}
-
-/*============================================================================
- * Firmware error handler.
- *	This routine is called whenever firmware command returns non-zero
- *	return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
-	unsigned cmd = mb->command;
-
-	switch (err) {
-
-	case CMD_TIMEOUT:
-		printk(KERN_ERR "%s: command 0x%02X timed out!\n",
-			card->devname, cmd);
-		break;
-
-	case S514_BOTH_PORTS_SAME_CLK_MODE:
-		if(cmd == SET_CHDLC_CONFIGURATION) {
-			printk(KERN_INFO
-			 "%s: Configure both ports for the same clock source\n",
-				card->devname);
-			break;
-		}
-
-	default:
-		printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
-			card->devname, cmd, err);
-	}
-
-	return 0;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
deleted file mode 100644
index a4b489c..0000000
--- a/drivers/net/wan/sdla_ppp.c
+++ /dev/null
@@ -1,3430 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.c	WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module.
-*
-* Author: 	Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright:	(c) 1995-2001 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Feb 28, 2001  Nenad Corbic	o Updated if_tx_timeout() routine for 
-* 				  2.4.X kernels.
-* Nov 29, 2000  Nenad Corbic	o Added the 2.4.x kernel support:
-* 				  get_ip_address() function has moved
-* 				  into the ppp_poll() routine. It cannot
-* 				  be called from an interrupt.
-* Nov 07, 2000  Nenad Corbic	o Added security features for UDP debugging:
-*                                 Deny all and specify allowed requests.
-* May 02, 2000  Nenad Corbic	o Added the dynamic interface shutdown
-*                                 option. When the link goes down, the
-*                                 network interface IFF_UP flag is reset.
-* Mar 06, 2000  Nenad Corbic	o Bug Fix: corrupted mbox recovery.
-* Feb 25, 2000  Nenad Corbic    o Fixed the FT1 UDP debugger problem.
-* Feb 09, 2000  Nenad Coribc    o Shutdown bug fix. update() was called
-*                                 with NULL dev pointer: no check.
-* Jan 24, 2000  Nenad Corbic    o Disabled use of CMD complete inter.
-* Dev 15, 1999  Nenad Corbic    o Fixed up header files for 2.0.X kernels
-* Oct 25, 1999  Nenad Corbic    o Support for 2.0.X kernels
-*                                 Moved dynamic route processing into 
-*                                 a polling routine.
-* Oct 07, 1999  Nenad Corbic    o Support for S514 PCI card.  
-*               Gideon Hack     o UPD and Updates executed using timer interrupt
-* Sep 10, 1999  Nenad Corbic    o Fixed up the /proc statistics
-* Jul 20, 1999  Nenad Corbic    o Remove the polling routines and use 
-*                                 interrupts instead.
-* Sep 17, 1998	Jaspreet Singh	o Updates for 2.2.X Kernels.
-* Aug 13, 1998	Jaspreet Singh	o Improved Line Tracing.
-* Jun 22, 1998	David Fong	o Added remote IP address assignment
-* Mar 15, 1998	Alan Cox	o 2.1.8x basic port.
-* Apr 16, 1998	Jaspreet Singh	o using htons() for the IPX protocol.
-* Dec 09, 1997	Jaspreet Singh	o Added PAP and CHAP.
-*				o Implemented new routines like 
-*				  ppp_set_inbnd_auth(), ppp_set_outbnd_auth(),
-*				  tokenize() and strstrip().
-* Nov 27, 1997	Jaspreet Singh	o Added protection against enabling of irqs 
-*				  while they have been disabled.
-* Nov 24, 1997  Jaspreet Singh  o Fixed another RACE condition caused by
-*                                 disabling and enabling of irqs.
-*                               o Added new counters for stats on disable/enable
-*                                 IRQs.
-* Nov 10, 1997	Jaspreet Singh	o Initialized 'skb->mac.raw' to 'skb->data'
-*				  before every netif_rx().
-*				o Free up the device structure in del_if().
-* Nov 07, 1997	Jaspreet Singh	o Changed the delay to zero for Line tracing
-*				  command.
-* Oct 20, 1997 	Jaspreet Singh	o Added hooks in for Router UP time.
-* Oct 16, 1997	Jaspreet Singh  o The critical flag is used to maintain flow
-*				  control by avoiding RACE conditions.  The 
-*				  cli() and restore_flags() are taken out.
-*				  A new structure, "ppp_private_area", is added 
-*				  to provide Driver Statistics.   
-* Jul 21, 1997 	Jaspreet Singh	o Protected calls to sdla_peek() by adding 
-*				  save_flags(), cli() and restore_flags().
-* Jul 07, 1997	Jaspreet Singh  o Added configurable TTL for UDP packets
-*				o Added ability to discard mulitcast and
-*				  broacast source addressed packets.
-* Jun 27, 1997 	Jaspreet Singh	o Added FT1 monitor capabilities
-*				  New case (0x25) statement in if_send routine.
-*				  Added a global variable rCount to keep track
-*				  of FT1 status enabled on the board.
-* May 22, 1997	Jaspreet Singh	o Added change in the PPP_SET_CONFIG command for
-*				508 card to reflect changes in the new 
-*				ppp508.sfm for supporting:continous transmission
-*				of Configure-Request packets without receiving a
-*				reply 				
-*				OR-ed 0x300 to conf_flags 
-*			        o Changed connect_tmout from 900 to 0
-* May 21, 1997	Jaspreet Singh  o Fixed UDP Management for multiple boards
-* Apr 25, 1997  Farhan Thawar    o added UDP Management stuff
-* Mar 11, 1997  Farhan Thawar   Version 3.1.1
-*                                o fixed (+1) bug in rx_intr()
-*                                o changed if_send() to return 0 if
-*                                  wandev.critical() is true
-*                                o free socket buffer in if_send() if
-*                                  returning 0 
-* Jan 15, 1997	Gene Kozin	Version 3.1.0
-*				 o implemented exec() entry point
-* Jan 06, 1997	Gene Kozin	Initial version.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/if_arp.h>	/* ARPHRD_* defines */
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <linux/in.h>		/* sockaddr_in */
-#include <linux/jiffies.h>	/* time_after() macro */
-
-
-#include <asm/uaccess.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-
-#include <linux/if.h>
-#include <linux/sdla_ppp.h>		/* PPP firmware API definitions */
-#include <linux/sdlasfm.h>		/* S514 Type Definition */
-/****** Defines & Macros ****************************************************/
-
-#define	PPP_DFLT_MTU	1500		/* default MTU */
-#define	PPP_MAX_MTU	4000		/* maximum MTU */
-#define PPP_HDR_LEN	1
-
-#define MAX_IP_ERRORS 100 
-
-#define	CONNECT_TIMEOUT	(90*HZ)		/* link connection timeout */
-#define	HOLD_DOWN_TIME	(5*HZ)		/* link hold down time : Changed from 30 to 5 */
-
-/* For handle_IPXWAN() */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/* Macro for enabling/disabling debugging comments */
-//#define NEX_DEBUG
-#ifdef NEX_DEBUG
-#define NEX_PRINTK(format, a...) printk(format, ## a)
-#else
-#define NEX_PRINTK(format, a...)
-#endif /* NEX_DEBUG */ 
-
-#define DCD(a)   ( a & 0x08 ? "HIGH" : "LOW" )
-#define CTS(a)   ( a & 0x20 ? "HIGH" : "LOW" )
-#define LCP(a)   ( a == 0x09 ? "OPEN" : "CLOSED" )
-#define IP(a)    ( a == 0x09 ? "ENABLED" : "DISABLED" )
-
-#define TMR_INT_ENABLED_UPDATE  	0x01
-#define TMR_INT_ENABLED_PPP_EVENT	0x02
-#define TMR_INT_ENABLED_UDP		0x04
-#define TMR_INT_ENABLED_CONFIG		0x20
-
-/* Set Configuraton Command Definitions */
-#define PERCENT_TX_BUFF			60
-#define TIME_BETWEEN_CONF_REQ  		30
-#define TIME_BETWEEN_PAP_CHAP_REQ	30
-#define WAIT_PAP_CHAP_WITHOUT_REPLY     300
-#define WAIT_AFTER_DCD_CTS_LOW          5
-#define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10
-#define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900
-#define MAX_CONF_REQ_WITHOUT_REPLY      10
-#define MAX_TERM_REQ_WITHOUT_REPLY      2
-#define NUM_CONF_NAK_WITHOUT_REPLY      5
-#define NUM_AUTH_REQ_WITHOUT_REPLY      10
-
-#define END_OFFSET 0x1F0
-
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following 
- * structure will incorporate the card structure along with PPP specific data
- */
-  
-typedef struct ppp_private_area
-{
-	struct net_device *slave;
-	sdla_t* card;	
-	unsigned long router_start_time;	/*router start time in sec */
-	unsigned long tick_counter;		/*used for 5 second counter*/
-	unsigned mc;				/*multicast support on or off*/
-	unsigned char enable_IPX;
-	unsigned long network_number;
-	unsigned char pap;
-	unsigned char chap;
-	unsigned char sysname[31];		/* system name for in-bnd auth*/
-	unsigned char userid[511];		/* list of user ids */
-	unsigned char passwd[511];		/* list of passwords */
-	unsigned protocol;			/* SKB Protocol */
-	u32 ip_local;				/* Local IP Address */
-	u32 ip_remote;				/* remote IP Address */
-
-	u32 ip_local_tmp;
-	u32 ip_remote_tmp;
-	
-	unsigned char timer_int_enabled;	/* Who enabled the timer inter*/
-	unsigned char update_comms_stats;	/* Used by update function */
-	unsigned long curr_trace_addr;		/* Trace information */
-	unsigned long start_trace_addr;
-	unsigned long end_trace_addr;
-
-	unsigned char interface_down;		/* Brind down interface when channel 
-                                                   goes down */
-	unsigned long config_wait_timeout;	/* After if_open() if in dynamic if mode,
-						   wait a few seconds before configuring */
-	
-	unsigned short udp_pkt_lgth;
-	char  udp_pkt_src;
-      	char  udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
-	/* PPP specific statistics */
-
-	if_send_stat_t if_send_stat;
-	rx_intr_stat_t rx_intr_stat;
-	pipe_mgmt_stat_t pipe_mgmt_stat;
-
-	unsigned long router_up_time; 
-
-	/* Polling work queue entry. Each interface
-         * has its own work queue entry, which is used
-         * to defer events from the interrupt */
-	struct work_struct poll_work;
-	struct timer_list poll_delay_timer;
-
-	u8 gateway;
-	u8 config_ppp;
-	u8 ip_error;
-	
-}ppp_private_area_t;
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device *wandev);
-static int new_if(struct wan_device *wandev, struct net_device *dev,
-		  wanif_conf_t *conf);
-static int del_if(struct wan_device *wandev, struct net_device *dev);
-
-/* WANPIPE-specific entry points */
-static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data);
-
-/* Network device interface */
-static int if_init(struct net_device *dev);
-static int if_open(struct net_device *dev);
-static int if_close(struct net_device *dev);
-static int if_header(struct sk_buff *skb, struct net_device *dev,
-		     unsigned short type, 
-		     void *daddr, void *saddr, unsigned len);
-
-static void if_tx_timeout(struct net_device *dev);
-
-static int if_rebuild_hdr(struct sk_buff *skb);
-static struct net_device_stats *if_stats(struct net_device *dev);
-static int if_send(struct sk_buff *skb, struct net_device *dev);
-
-
-/* PPP firmware interface functions */
-static int ppp_read_version(sdla_t *card, char *str);
-static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area);
-static int ppp_configure(sdla_t *card, void *data);
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode);
-static int ppp_comm_enable(sdla_t *card);
-static int ppp_comm_disable(sdla_t *card);
-static int ppp_comm_disable_shutdown(sdla_t *card);
-static int ppp_get_err_stats(sdla_t *card);
-static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto);
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb);
-
-static void wpp_isr(sdla_t *card);
-static void rx_intr(sdla_t *card);
-static void event_intr(sdla_t *card);
-static void timer_intr(sdla_t *card);
-
-/* Background polling routines */
-static void process_route(sdla_t *card);
-static void retrigger_comm(sdla_t *card);
-
-/* Miscellaneous functions */
-static int read_info( sdla_t *card );
-static int read_connection_info (sdla_t *card);
-static void remove_route( sdla_t *card );
-static int config508(struct net_device *dev, sdla_t *card);
-static void show_disc_cause(sdla_t * card, unsigned cause);
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, 
-				ppp_private_area_t *ppp_priv_area);
-static void init_ppp_tx_rx_buff( sdla_t *card );
-static int intr_test( sdla_t *card );
-static int udp_pkt_type( struct sk_buff *skb , sdla_t *card);
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area);
-static void init_global_statistics( sdla_t *card );
-static int tokenize(char *str, char **tokens);
-static char* strstrip(char *str, char *s);
-static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev,
-				struct sk_buff *skb);
-
-static int config_ppp (sdla_t *);
-static void ppp_poll(struct net_device *dev);
-static void trigger_ppp_poll(struct net_device *dev);
-static void ppp_poll_delay (unsigned long dev_ptr);
-
-
-static int Read_connection_info;
-static int Intr_test_counter;
-static unsigned short available_buffer_space;
-
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, 
-			       unsigned char incoming);
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_PX, 
-			 unsigned long network_number, unsigned short proto);
-
-/* Lock Functions */
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-                                struct sk_buff *skb, struct net_device* dev,
-                                ppp_private_area_t* ppp_priv_area );
-static unsigned short calc_checksum (char *data, int len);
-static void disable_comm (sdla_t *card);
-static int detect_and_fix_tx_bug (sdla_t *card);
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * PPP protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup.  At this
- * point adapter is completely initialized and firmware is running.
- *  o read firmware version (to make sure it's alive)
- *  o configure adapter
- *  o initialize protocol-specific fields of the adapter data space.
- *
- * Return:	0	o.k.
- *		< 0	failure.
- */
-int wpp_init(sdla_t *card, wandev_conf_t *conf)
-{
-	ppp_flags_t *flags;
-	union
-	{
-		char str[80];
-	} u;
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_PPP) {
-		
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-			card->devname, conf->config_id);
-		return -EINVAL;
-
-	}
-
-	/* Initialize miscellaneous pointers to structures on the adapter */
-	switch (card->hw.type) {
-
-		case SDLA_S508:
-			card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS);
-			card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS);
-			break;
-		
-		case SDLA_S514:
-			card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS);
-			card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS);
-			break;
-
-		default:
-			return -EINVAL;
-
-	}
-	flags = card->flags;
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-	if (ppp_read_version(card, NULL) || ppp_read_version(card, u.str))
-		return -EIO;
-	
-	printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); 
-	/* Adjust configuration and set defaults */
-	card->wandev.mtu = (conf->mtu) ?
-		min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU;
-
-	card->wandev.bps	= conf->bps;
-	card->wandev.interface	= conf->interface;
-	card->wandev.clocking	= conf->clocking;
-	card->wandev.station	= conf->station;
-	card->isr		= &wpp_isr;
-	card->poll		= NULL; 
-	card->exec		= &wpp_exec;
-	card->wandev.update	= &update;
-	card->wandev.new_if	= &new_if;
-	card->wandev.del_if	= &del_if;
-        card->wandev.udp_port   = conf->udp_port;
-	card->wandev.ttl	= conf->ttl;
-	card->wandev.state      = WAN_DISCONNECTED;
-	card->disable_comm	= &disable_comm;
-	card->irq_dis_if_send_count = 0;
-        card->irq_dis_poll_count = 0;
-	card->u.p.authenticator = conf->u.ppp.authenticator;
-	card->u.p.ip_mode 	= conf->u.ppp.ip_mode ?
-				 conf->u.ppp.ip_mode : WANOPT_PPP_STATIC;
-        card->TracingEnabled    = 0;
-	Read_connection_info    = 1;
-
-	/* initialize global statistics */
-	init_global_statistics( card );
-
-
-
-	if (!card->configured){
-		int err;
-
-		Intr_test_counter = 0;
-		err = intr_test(card);
-
-		if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
-			printk("%s: Interrupt Test Failed, Counter: %i\n", 
-				card->devname, Intr_test_counter);
-			printk( "%s: Please choose another interrupt\n",card->devname);
-			return -EIO;
-		}
-		
-		printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", 
-			card->devname, Intr_test_counter);
-		card->configured = 1;
-	}
-
-	ppp_set_intr_mode(card, PPP_INTR_TIMER); 
-
-	/* Turn off the transmit and timer interrupt */
-	flags->imask &= ~PPP_INTR_TIMER;
-
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update(struct wan_device *wandev)
-{
-	sdla_t* card = wandev->private;
- 	struct net_device* dev;
-        volatile ppp_private_area_t *ppp_priv_area;
-	ppp_flags_t *flags = card->flags;
-	unsigned long timeout;
-
-	/* sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-	
-	if (wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-	
-	/* Shutdown bug fix. This function can be
-         * called with NULL dev pointer during
-         * shutdown 
-	 */
-	if ((dev=card->wandev.dev) == NULL){
-		return -ENODEV;
-	}
-
-	if ((ppp_priv_area=dev->priv) == NULL){
-		return -ENODEV;
-	}
-	
-	ppp_priv_area->update_comms_stats = 2;
-	ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
-	flags->imask |= PPP_INTR_TIMER;	
-	
-	/* wait a maximum of 1 second for the statistics to be updated */ 
-        timeout = jiffies;
-        for(;;) {
-		if(ppp_priv_area->update_comms_stats == 0){
-			break;
-		}
-                if (time_after(jiffies, timeout + 1 * HZ)){
-    			ppp_priv_area->update_comms_stats = 0;
- 			ppp_priv_area->timer_int_enabled &=
-				~TMR_INT_ENABLED_UPDATE; 
- 			return -EAGAIN;
-		}
-        }
-
-	return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return:	0	o.k.
- *		< 0	failure (channel will not be created)
- */
-static int new_if(struct wan_device *wandev, struct net_device *dev,
-		  wanif_conf_t *conf)
-{
-	sdla_t *card = wandev->private;
-	ppp_private_area_t *ppp_priv_area;
-
-	if (wandev->ndev)
-		return -EEXIST;
-	
-
-	printk(KERN_INFO "%s: Configuring Interface: %s\n",
-			card->devname, conf->name);
-
-	if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-
-		printk(KERN_INFO "%s: Invalid interface name!\n",
-			card->devname);
-		return -EINVAL;
-
-	}
-
-	/* allocate and initialize private data */
-	ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL);
-	
-	if( ppp_priv_area == NULL )
-		return	-ENOMEM;
-	
-	memset(ppp_priv_area, 0, sizeof(ppp_private_area_t));
-	
-	ppp_priv_area->card = card; 
-	
-	/* initialize data */
-	strcpy(card->u.p.if_name, conf->name);
-
-	/* initialize data in ppp_private_area structure */
-	
-	init_ppp_priv_struct( ppp_priv_area );
-
-	ppp_priv_area->mc = conf->mc;
-	ppp_priv_area->pap = conf->pap;
-	ppp_priv_area->chap = conf->chap;
-
-	/* Option to bring down the interface when 
-         * the link goes down */
-	if (conf->if_down){
-		set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down);
-		printk("%s: Dynamic interface configuration enabled\n",
-			card->devname);
-	} 
-
-	/* If no user ids are specified */
-	if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){
-		kfree(ppp_priv_area);
-		return -EINVAL;
-	}
-
-	/* If no passwords are specified */
-	if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){
-		kfree(ppp_priv_area);
-		return -EINVAL;
-	}
-
-	if(strlen(conf->sysname) > 31){
-		kfree(ppp_priv_area);
-		return -EINVAL;
-	}
-
-	/* If no system name is specified */
-	if(!strlen(conf->sysname) && (card->u.p.authenticator)){
-		kfree(ppp_priv_area);
-		return -EINVAL;
-	}
-
-	/* copy the data into the ppp private structure */
-	memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid));
-	memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd));
-	memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname));
-
-	
-	ppp_priv_area->enable_IPX = conf->enable_IPX;
-	if (conf->network_number){
-		ppp_priv_area->network_number = conf->network_number;
-	}else{
-		ppp_priv_area->network_number = 0xDEADBEEF;
-	}
-
-	/* Tells us that if this interface is a
-         * gateway or not */
-	if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){
-		printk(KERN_INFO "%s: Interface %s is set as a gateway.\n",
-			card->devname,card->u.p.if_name);
-	}
-
-	/* prepare network device data space for registration */
- 	strcpy(dev->name,card->u.p.if_name);
-	
-	dev->init = &if_init;
-	dev->priv = ppp_priv_area;
-	dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu);
-
-	/* Initialize the polling work routine */
-	INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev);
-
-	/* Initialize the polling delay timer */
-	init_timer(&ppp_priv_area->poll_delay_timer);
-	ppp_priv_area->poll_delay_timer.data = (unsigned long)dev;
-	ppp_priv_area->poll_delay_timer.function = ppp_poll_delay;
-	
-	
-	/* Since we start with dummy IP addresses we can say
-	 * that route exists */
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device *wandev, struct net_device *dev)
-{
-	return 0;
-}
-
-static void disable_comm (sdla_t *card)
-{
-	ppp_comm_disable_shutdown(card);
-	return;
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-
-//FIXME: Why do we need this ????
-static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data)
-{
-	ppp_mbox_t *mbox = card->mbox;
-	int len;
-
-	if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)))
-		return -EFAULT;
-
-	len = mbox->cmd.length;
-
-	if (len) {
-
-		if( copy_from_user((void*)&mbox->data, u_data, len))
-			return -EFAULT;
-
-	}
-
-	/* execute command */
-	if (!sdla_exec(mbox))
-		return -EIO;
-
-	/* return result */
-	if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t)))
-		return -EFAULT;
-	len = mbox->cmd.length;
-
-	if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
-		return -EFAULT;
-
-	return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration.  Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t *card = ppp_priv_area->card;
-	struct wan_device *wandev = &card->wandev;
-
-	/* Initialize device driver entry points */
-	dev->open		= &if_open;
-	dev->stop		= &if_close;
-	dev->hard_header	= &if_header;
-	dev->rebuild_header	= &if_rebuild_hdr;
-	dev->hard_start_xmit	= &if_send;
-	dev->get_stats		= &if_stats;
-	dev->tx_timeout		= &if_tx_timeout;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-
-	/* Initialize media-specific parameters */
-	dev->type		= ARPHRD_PPP;	/* ARP h/w type */
-	dev->flags		|= IFF_POINTOPOINT;
-	dev->flags		|= IFF_NOARP;
-
-	/* Enable Mulitcasting if specified by user*/
-	if (ppp_priv_area->mc == WANOPT_YES){
-		dev->flags	|= IFF_MULTICAST;
-	}
-
-	dev->mtu		= wandev->mtu;
-	dev->hard_header_len	= PPP_HDR_LEN;	/* media header length */
-
-	/* Initialize hardware parameters (just for reference) */
-	dev->irq		= wandev->irq;
-	dev->dma		= wandev->dma;
-	dev->base_addr		= wandev->ioport;
-	dev->mem_start		= wandev->maddr;
-	dev->mem_end		= wandev->maddr + wandev->msize - 1;
-
-        /* Set transmit buffer queue length */
-        dev->tx_queue_len = 100;
-	SET_MODULE_OWNER(dev);
-   
-	return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t *card = ppp_priv_area->card;
-	struct timeval tv;
-	//unsigned long smp_flags;
-
-	if (netif_running(dev))
-		return -EBUSY;
-
-	wanpipe_open(card);
-
-	netif_start_queue(dev);
-	
-	do_gettimeofday( &tv );
-	ppp_priv_area->router_start_time = tv.tv_sec;
-
-	/* We cannot configure the card here because we don't
-	 * have access to the interface IP addresses.
-         * Once the interface initilization is complete, we will be
-         * able to access the IP addresses.  Therefore,
-         * configure the ppp link in the poll routine */
-	set_bit(0,&ppp_priv_area->config_ppp);
-	ppp_priv_area->config_wait_timeout=jiffies;
-
-	/* Start the PPP configuration after 1sec delay.
-	 * This will give the interface initilization time
-	 * to finish its configuration */
-	mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ);
-	return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last open, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t *card = ppp_priv_area->card;
-
-	netif_stop_queue(dev);
-	wanpipe_close(card);
-
-	del_timer (&ppp_priv_area->poll_delay_timer);
-	return 0;
-}
-
-/*============================================================================
- * Build media header.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it.  If packet type is not
- * supported, set skb->protocol to 0 and discard packet later.
- *
- * Return:	media header length.
- */
-static int if_header(struct sk_buff *skb, struct net_device *dev,
-	unsigned short type, void *daddr, void *saddr, unsigned len)
-{
-	switch (type)
-	{
-		case ETH_P_IP:
-		case ETH_P_IPX:
-			skb->protocol = htons(type);
-			break;
-
-		default:
-			skb->protocol = 0;
-	}
-
-	return PPP_HDR_LEN;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return:	1	physical address resolved.
- *		0	physical address not resolved
- */
-static int if_rebuild_hdr (struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t *card = ppp_priv_area->card;
-
-	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
-		card->devname, dev->name);
-	return 1;
-}
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
-    	ppp_private_area_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	
-	/* If our device stays busy for at least 5 seconds then we will
-	 * kick start the device by making dev->tbusy = 0.  We expect
-	 * that our device never stays busy more than 5 seconds. So this                 
-	 * is only used as a last resort.
-	 */
-
-	++ chan->if_send_stat.if_send_tbusy;
-	++card->wandev.stats.collisions;
-
-	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
-	++chan->if_send_stat.if_send_tbusy_timeout;
-	netif_wake_queue (dev);
-}
-
-
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- *   transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return:	0	complete (socket buffer must be freed)
- *		non-0	packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- *    bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- *    protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send (struct sk_buff *skb, struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t *card = ppp_priv_area->card;
-	unsigned char *sendpacket;
-	unsigned long smp_flags;
-	ppp_flags_t *flags = card->flags;
-	int udp_type;
-	int err=0;
-	
-	++ppp_priv_area->if_send_stat.if_send_entry;
-
-	netif_stop_queue(dev);
-	
-	if (skb == NULL) {
-
-		/* If we get here, some higher layer thinks we've missed an
-		 * tx-done interrupt.
-		 */
-		printk(KERN_INFO "%s: interface %s got kicked!\n",
-			card->devname, dev->name);
-		
-		++ppp_priv_area->if_send_stat.if_send_skb_null;
-	
-		netif_wake_queue(dev);
-		return 0;
-	}
-
-	sendpacket = skb->data;
-
-	udp_type = udp_pkt_type( skb, card );
-
-
-	if (udp_type == UDP_PTPIPE_TYPE){
-		if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
-                	              ppp_priv_area)){
-	               	flags->imask |= PPP_INTR_TIMER;
-		}
-		++ppp_priv_area->if_send_stat.if_send_PIPE_request;
-		netif_start_queue(dev);
-		return 0;
-	}
-
-	/* Check for broadcast and multicast addresses 
-	 * If found, drop (deallocate) a packet and return.
-	 */
-	if(chk_bcast_mcast_addr(card, dev, skb)){
-		++card->wandev.stats.tx_dropped;
-		dev_kfree_skb_any(skb);
-		netif_start_queue(dev);
-		return 0;
-	}
-
-
- 	if(card->hw.type != SDLA_S514){
-		s508_lock(card,&smp_flags);
-	}
-
-    	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-
-		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
-				card->wandev.name,card->wandev.critical);
-		
-		++card->wandev.stats.tx_dropped;
-		++ppp_priv_area->if_send_stat.if_send_critical_non_ISR;
-		netif_start_queue(dev);
-		goto if_send_exit_crit;
-	}
-
-	if (card->wandev.state != WAN_CONNECTED) {
-
-		++ppp_priv_area->if_send_stat.if_send_wan_disconnected;
-        	++card->wandev.stats.tx_dropped;
-		netif_start_queue(dev);
-		
-     	} else if (!skb->protocol) {
-		++ppp_priv_area->if_send_stat.if_send_protocol_error;
-        	++card->wandev.stats.tx_errors;
-		netif_start_queue(dev);
-		
-	} else {
-
-		/*If it's IPX change the network numbers to 0 if they're ours.*/
-		if( skb->protocol == htons(ETH_P_IPX) ) {
-			if(ppp_priv_area->enable_IPX) {
-				switch_net_numbers( skb->data, 
-					ppp_priv_area->network_number, 0);
-			} else {
-				++card->wandev.stats.tx_dropped;
-				netif_start_queue(dev);
-				goto if_send_exit_crit;
-			}
-		}
-
-		if (ppp_send(card, skb->data, skb->len, skb->protocol)) {
-			netif_stop_queue(dev);
-			++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full;
-			++ppp_priv_area->if_send_stat.if_send_tx_int_enabled;
-		} else {
-			++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr;
-			++card->wandev.stats.tx_packets;
-			card->wandev.stats.tx_bytes += skb->len;
-			netif_start_queue(dev);
-			dev->trans_start = jiffies;
-		}
-    	}
-	
-if_send_exit_crit:
-	
-	if (!(err=netif_queue_stopped(dev))){
-      		dev_kfree_skb_any(skb);
-	}else{
-		ppp_priv_area->tick_counter = jiffies;
-		flags->imask |= PPP_INTR_TXRDY;	/* unmask Tx interrupts */
-	}
-	
-	clear_bit(SEND_CRIT,&card->wandev.critical);
-	if(card->hw.type != SDLA_S514){	
-		s508_unlock(card,&smp_flags);
-	}
-
-	return err;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-                                struct sk_buff *skb, struct net_device* dev,
-                                ppp_private_area_t* ppp_priv_area )
-{
-	int udp_pkt_stored = 0;
-
-	if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){
-        	ppp_priv_area->udp_pkt_lgth = skb->len;
-		ppp_priv_area->udp_pkt_src = udp_pkt_src;
-       		memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len);
-		ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP;
-		ppp_priv_area->protocol = skb->protocol;
-		udp_pkt_stored = 1;
-	}else{
-		if (skb->len > MAX_LGTH_UDP_MGNT_PKT){
-			printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n",
-				card->devname, skb->len);
-		}else{
-			printk(KERN_INFO "%s: PIPEMON UPD request already pending\n",
-				card->devname);
-		}
-		ppp_priv_area->udp_pkt_lgth = 0;
-	}
-
-	if(udp_pkt_src == UDP_PKT_FRM_STACK){
-		dev_kfree_skb_any(skb);
-	}else{
-                dev_kfree_skb_any(skb);
-	}
-
-	return(udp_pkt_stored);
-}
-
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len ) 
-{
-	unsigned short len, udp_length, temp, ip_length;
-	unsigned long ip_temp;
-	int even_bound = 0;
-	ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data;
- 
-	/* Set length of packet */
-	len = sizeof(ip_pkt_t)+ 
-	      sizeof(udp_pkt_t)+
-	      sizeof(wp_mgmt_t)+
-	      sizeof(cblock_t)+
-	      mbox_len;
-
-	/* fill in UDP reply */
-  	p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; 
-
-	/* fill in UDP length */
-	udp_length = sizeof(udp_pkt_t)+ 
-		     sizeof(wp_mgmt_t)+
-		     sizeof(cblock_t)+
-		     mbox_len; 
-  
- 
-	/* put it on an even boundary */
-	if ( udp_length & 0x0001 ) {
-		udp_length += 1;
-		len += 1;
-		even_bound=1;
-	} 
-	
-	temp = (udp_length<<8)|(udp_length>>8);
-	p_udp_pkt->udp_pkt.udp_length = temp;		
-
- 
-	/* swap UDP ports */
-	temp = p_udp_pkt->udp_pkt.udp_src_port;
-	p_udp_pkt->udp_pkt.udp_src_port = 
-			p_udp_pkt->udp_pkt.udp_dst_port; 
-	p_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-	/* add UDP pseudo header */
-	temp = 0x1100;
-	*((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp;
-	temp = (udp_length<<8)|(udp_length>>8);
-	*((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp;
- 
-	/* calculate UDP checksum */
-	p_udp_pkt->udp_pkt.udp_checksum = 0;
-	p_udp_pkt->udp_pkt.udp_checksum = 
-		calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
-	/* fill in IP length */
-	ip_length = udp_length + sizeof(ip_pkt_t);
-	temp = (ip_length<<8)|(ip_length>>8);
-  	p_udp_pkt->ip_pkt.total_length = temp;
- 
-	/* swap IP addresses */
-	ip_temp = p_udp_pkt->ip_pkt.ip_src_address;
-	p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address;
-	p_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-	/* fill in IP checksum */
-	p_udp_pkt->ip_pkt.hdr_checksum = 0;
-	p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
-	return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
-	unsigned short temp; 
-	unsigned long sum=0;
-	int i;
-
-	for( i = 0; i <len; i+=2 ) {
-		memcpy(&temp,&data[i],2);
-		sum += (unsigned long)temp;
-	}
-
-	while (sum >> 16 ) {
-		sum = (sum & 0xffffUL) + (sum >> 16);
-	}
-
-	temp = (unsigned short)sum;
-	temp = ~temp;
-
-	if( temp == 0 ) 
-		temp = 0xffff;
-
-	return temp;	
-}
-
-/*
-   If incoming is 0 (outgoing)- if the net numbers is ours make it 0
-   if incoming is 1 - if the net number is 0 make it ours 
-
-*/
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
-	unsigned long pnetwork_number;
-
-	pnetwork_number = (unsigned long)((sendpacket[6] << 24) + 
-			  (sendpacket[7] << 16) + (sendpacket[8] << 8) + 
-			  sendpacket[9]);
-
-	if (!incoming) {
-		//If the destination network number is ours, make it 0
-		if( pnetwork_number == network_number) {
-			sendpacket[6] = sendpacket[7] = sendpacket[8] = 
-					 sendpacket[9] = 0x00;
-		}
-	} else {
-		//If the incoming network is 0, make it ours
-		if( pnetwork_number == 0) {
-			sendpacket[6] = (unsigned char)(network_number >> 24);
-			sendpacket[7] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[8] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[9] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-
-
-	pnetwork_number = (unsigned long)((sendpacket[18] << 24) + 
-			  (sendpacket[19] << 16) + (sendpacket[20] << 8) + 
-			  sendpacket[21]);
-
-	if( !incoming ) {
-		//If the source network is ours, make it 0
-		if( pnetwork_number == network_number) {
-			sendpacket[18] = sendpacket[19] = sendpacket[20] = 
-					 sendpacket[21] = 0x00;
-		}
-	} else {
-		//If the source network is 0, make it ours
-		if( pnetwork_number == 0 ) {
-			sendpacket[18] = (unsigned char)(network_number >> 24);
-			sendpacket[19] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[20] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[21] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-} /* switch_net_numbers */
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct net_device_stats.
- */
-static struct net_device_stats *if_stats(struct net_device *dev)
-{
-
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	sdla_t* card;
-	
-	if( ppp_priv_area == NULL )
-		return NULL;
-
-	card = ppp_priv_area->card;
-	return &card->wandev.stats;
-}
-
-/****** PPP Firmware Interface Functions ************************************/
-
-/*============================================================================
- * Read firmware code version.
- *	Put code version as ASCII string in str. 
- */
-static int ppp_read_version(sdla_t *card, char *str)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.command = PPP_READ_CODE_VERSION;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK)
- 
-		ppp_error(card, err, mb);
-
-	else if (str) {
-
-		int len = mb->cmd.length;
-
-		memcpy(str, mb->data, len);
-		str[len] = '\0';
-
-	}
-
-	return err;
-}
-/*===========================================================================
- * Set Out-Bound Authentication.
-*/
-static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	memset(&mb->data, 0, (strlen(ppp_priv_area->userid) + 
-					strlen(ppp_priv_area->passwd) + 2 ) );
-	memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid));
-	memcpy((mb->data + strlen(ppp_priv_area->userid) + 1), 
-		ppp_priv_area->passwd, strlen(ppp_priv_area->passwd));	
-	
-	mb->cmd.length  = strlen(ppp_priv_area->userid) + 
-					strlen(ppp_priv_area->passwd) + 2 ;
-	
-	mb->cmd.command = PPP_SET_OUTBOUND_AUTH;
-
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK)
-		ppp_error(card, err, mb);
-
-	return err;
-}
-
-/*===========================================================================
- * Set In-Bound Authentication.
-*/
-static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err, i;
-	char* user_tokens[32];
-	char* pass_tokens[32];
-	int userids, passwds;
-	int add_ptr;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	memset(&mb->data, 0, 1008);
-	memcpy(mb->data, ppp_priv_area->sysname, 
-						strlen(ppp_priv_area->sysname));
-	
-	/* Parse the userid string and the password string and build a string
-	   to copy it to the data area of the command structure.   The string
-	   will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2
-	   ....<NULL> " 
-	 */
-	userids = tokenize( ppp_priv_area->userid, user_tokens);
-	passwds = tokenize( ppp_priv_area->passwd, pass_tokens);
-	
-	if (userids != passwds){
-		printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname);
-		return 1;	
-	}
-
-	add_ptr = strlen(ppp_priv_area->sysname) + 1;
-	for (i=0; i<userids; i++){
-		memcpy((mb->data + add_ptr), user_tokens[i], 
-							strlen(user_tokens[i]));
-		memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1), 
-					pass_tokens[i], strlen(pass_tokens[i]));
-		add_ptr = add_ptr + strlen(user_tokens[i]) + 1 + 
-						strlen(pass_tokens[i]) + 1;
-	}
-
-	mb->cmd.length  = add_ptr + 1;
-	mb->cmd.command = PPP_SET_INBOUND_AUTH;
-
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK)
-		ppp_error(card, err, mb);
-
-	return err;
-}
-
-
-/*============================================================================
- * Tokenize string.
- *      Parse a string of the following syntax:
- *              <arg1>,<arg2>,...
- *      and fill array of tokens with pointers to string elements.
- *
- */
-static int tokenize (char *str, char **tokens)
-{
-        int cnt = 0;
-
-        tokens[0] = strsep(&str, "/");
-        while (tokens[cnt] && (cnt < 32 - 1))
-        {
-                tokens[cnt] = strstrip(tokens[cnt], " \t");
-                tokens[++cnt] = strsep(&str, "/");
-        }
-	return cnt;
-}
-
-/*============================================================================
- * Strip leading and trailing spaces off the string str.
- */
-static char* strstrip (char *str, char* s)
-{
-        char *eos = str + strlen(str);          /* -> end of string */
-
-        while (*str && strchr(s, *str))
-                ++str                           /* strip leading spaces */
-        ;
-        while ((eos > str) && strchr(s, *(eos - 1)))
-                --eos                           /* strip trailing spaces */
-        ;
-        *eos = '\0';
-        return str;
-}
-/*============================================================================
- * Configure PPP firmware.
- */
-static int ppp_configure(sdla_t *card, void *data)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int data_len = sizeof(ppp508_conf_t); 
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	memcpy(mb->data, data, data_len);
-	mb->cmd.length  = data_len;
-	mb->cmd.command = PPP_SET_CONFIG;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK) 
-		ppp_error(card, err, mb);
-	
-	return err;
-}
-
-/*============================================================================
- * Set interrupt mode.
- */
-static int ppp_set_intr_mode(sdla_t *card, unsigned char mode)
-{
-	ppp_mbox_t *mb = card->mbox;
-        ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	ppp_intr_data->i_enable = mode;
-
-	ppp_intr_data->irq = card->hw.irq;
-	mb->cmd.length = 2;
-
-       /* If timer has been enabled, set the timer delay to 1sec */
-       if (mode & 0x80){
-       		ppp_intr_data->timer_len = 250; //5;//100; //250;
-                mb->cmd.length = 4;
-        }
-	
-	mb->cmd.command = PPP_SET_INTR_FLAGS;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-	
-	if (err != CMD_OK) 
-		ppp_error(card, err, mb);
- 		
-
-	return err;
-}
-
-/*============================================================================
- * Enable communications.
- */
-static int ppp_comm_enable(sdla_t *card)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.command = PPP_COMM_ENABLE;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-	
-	if (err != CMD_OK) 
-		ppp_error(card, err, mb);
-	else	
-		card->u.p.comm_enabled = 1;	
-
-	return err;
-}
-
-/*============================================================================
- * Disable communications.
- */
-static int ppp_comm_disable(sdla_t *card)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.command = PPP_COMM_DISABLE;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-	if (err != CMD_OK) 
-		ppp_error(card, err, mb);
-	else
-		card->u.p.comm_enabled = 0;
-
-	return err;
-}
-
-static int ppp_comm_disable_shutdown(sdla_t *card)
-{
-	ppp_mbox_t *mb = card->mbox;
-	ppp_intr_info_t *ppp_intr_data;
-	int err;
-
-	if (!mb){
-		return 1;
-	}
-	
-	ppp_intr_data = (ppp_intr_info_t *) &mb->data[0];
-	
-	/* Disable all interrupts */
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	ppp_intr_data->i_enable = 0;
-
-	ppp_intr_data->irq = card->hw.irq;
-	mb->cmd.length = 2;
-
-	mb->cmd.command = PPP_SET_INTR_FLAGS;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	/* Disable communicatinons */
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.command = PPP_COMM_DISABLE;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	card->u.p.comm_enabled = 0;
-
-	return 0;
-}
-
-
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int ppp_get_err_stats(sdla_t *card)
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.command = PPP_READ_ERROR_STATS;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-	
-	if (err == CMD_OK) {
-		
-		ppp_err_stats_t* stats = (void*)mb->data;
-		card->wandev.stats.rx_over_errors    = stats->rx_overrun;
-		card->wandev.stats.rx_crc_errors     = stats->rx_bad_crc;
-		card->wandev.stats.rx_missed_errors  = stats->rx_abort;
-		card->wandev.stats.rx_length_errors  = stats->rx_lost;
-		card->wandev.stats.tx_aborted_errors = stats->tx_abort;
-	
-	} else 
-		ppp_error(card, err, mb);
-	
-	return err;
-}
-
-/*============================================================================
- * Send packet.
- *	Return:	0 - o.k.
- *		1 - no transmit buffers available
- */
-static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto)
-{
-	ppp_buf_ctl_t *txbuf = card->u.p.txbuf;
-
-	if (txbuf->flag)
-                return 1;
-	
-	sdla_poke(&card->hw, txbuf->buf.ptr, data, len);
-
-	txbuf->length = len;		/* frame length */
-	
-	if (proto == htons(ETH_P_IPX))
-		txbuf->proto = 0x01;	/* protocol ID */
-	else
-		txbuf->proto = 0x00;	/* protocol ID */
-	
-	txbuf->flag = 1;		/* start transmission */
-
-	/* Update transmit buffer control fields */
-	card->u.p.txbuf = ++txbuf;
-
-	if ((void*)txbuf > card->u.p.txbuf_last)
-		card->u.p.txbuf = card->u.p.txbuf_base;
-
-	return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- *	This routine is called whenever firmware command returns non-zero
- *	return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb)
-{
-	unsigned cmd = mb->cmd.command;
-
-	switch (err) {
-
-		case CMD_TIMEOUT:
-			printk(KERN_ERR "%s: command 0x%02X timed out!\n",
-				card->devname, cmd);
-			break;
-
-		default:
-			printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n"
-				, card->devname, cmd, err);
-	}
-
-	return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * PPP interrupt service routine.
- */
-static void wpp_isr (sdla_t *card)
-{
-	ppp_flags_t *flags = card->flags;
-	char *ptr = &flags->iflag;
-	struct net_device *dev = card->wandev.dev;
-	int i;
-
-	card->in_isr = 1;
-	++card->statistics.isr_entry;
-
-	if (!dev && flags->iflag != PPP_INTR_CMD){
-		card->in_isr = 0;
-		flags->iflag = 0;
-		return;
-	}
-	
-	if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
-		card->in_isr = 0;
-		flags->iflag = 0;
-		return;
-	}
-	
-	
-	if(card->hw.type != SDLA_S514){
-		if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {
-			++card->statistics.isr_already_critical;
-			printk (KERN_INFO "%s: Critical while in ISR!\n",
-					card->devname);
-			card->in_isr = 0;
-			flags->iflag = 0;
-			return;
-		}
-	}
-
-	switch (flags->iflag) {
-
-		case PPP_INTR_RXRDY:	/* receive interrupt  0x01  (bit 0)*/
-			++card->statistics.isr_rx;
-			rx_intr(card);
-			break;
-
-		case PPP_INTR_TXRDY:	/* transmit interrupt  0x02 (bit 1)*/
-			++card->statistics.isr_tx;
-			flags->imask &= ~PPP_INTR_TXRDY;
-			netif_wake_queue(dev);
-			break;
-
-		case PPP_INTR_CMD:      /* interface command completed */
-			++Intr_test_counter;
-			++card->statistics.isr_intr_test;
-			break;
-
-		case PPP_INTR_MODEM:    /* modem status change (DCD, CTS) 0x04 (bit 2)*/
-		case PPP_INTR_DISC:  	/* Data link disconnected 0x10  (bit 4)*/	
-		case PPP_INTR_OPEN:   	/* Data link open 0x20  (bit 5)*/
-		case PPP_INTR_DROP_DTR:	/* DTR drop timeout expired  0x40 bit 6 */
-			event_intr(card);
-			break;
-	
-		case PPP_INTR_TIMER:
-			timer_intr(card);
-			break;	 
-
-		default:	/* unexpected interrupt */
-			++card->statistics.isr_spurious;
-			printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", 
-				card->devname, flags->iflag);
-			printk(KERN_INFO "%s: ID Bytes = ",card->devname);
-	 		for(i = 0; i < 8; i ++)
-				printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
-			printk(KERN_INFO "\n");	
-	}
-	
-	card->in_isr = 0;
-	flags->iflag = 0;
-	return;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr(sdla_t *card)
-{
-	ppp_buf_ctl_t *rxbuf = card->rxmb;
-	struct net_device *dev = card->wandev.dev;
-	ppp_private_area_t *ppp_priv_area;
-	struct sk_buff *skb;
-	unsigned len;
-	void *buf;
-	int i;
-        ppp_flags_t *flags = card->flags;
-        char *ptr = &flags->iflag;
-	int udp_type;
-	
-
-	if (rxbuf->flag != 0x01) {
-
-		printk(KERN_INFO 
-			"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", 
-			card->devname, (unsigned)rxbuf, rxbuf->flag);
-	
-		printk(KERN_INFO "%s: ID Bytes = ",card->devname);
-	 	
-		for(i = 0; i < 8; i ++)
-			printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));
-		printk(KERN_INFO "\n");	
-		
-		++card->statistics.rx_intr_corrupt_rx_bfr;
-
-
-		/* Bug Fix: Mar 6 2000
-                 * If we get a corrupted mailbox, it means that driver 
-                 * is out of sync with the firmware. There is no recovery.
-                 * If we don't turn off all interrupts for this card
-                 * the machine will crash. 
-                 */
-		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
-		printk(KERN_INFO "Please contact Sangoma Technologies !\n");
-		ppp_set_intr_mode(card,0);
-		return;
-	}
-      
-	if (dev && netif_running(dev) && dev->priv){
-	
-		len  = rxbuf->length;
-		ppp_priv_area = dev->priv;
-
-		/* Allocate socket buffer */
-		skb = dev_alloc_skb(len);
-
-		if (skb != NULL) {
-		
-			/* Copy data to the socket buffer */
-			unsigned addr = rxbuf->buf.ptr;
-
-			if ((addr + len) > card->u.p.rx_top + 1) {
-			
-				unsigned tmp = card->u.p.rx_top - addr + 1;
-				buf = skb_put(skb, tmp);
-				sdla_peek(&card->hw, addr, buf, tmp);
-				addr = card->u.p.rx_base;
-				len -= tmp;
-			}
-			buf = skb_put(skb, len);
-			sdla_peek(&card->hw, addr, buf, len);
-
-			/* Decapsulate packet */
-        		switch (rxbuf->proto) {
-	
-				case 0x00:
-					skb->protocol = htons(ETH_P_IP);
-					break;
-
-				case 0x01:
-					skb->protocol = htons(ETH_P_IPX);
-					break;
-			}
-
-			udp_type = udp_pkt_type( skb, card );
-
-			if (udp_type == UDP_PTPIPE_TYPE){
-
-				/* Handle a UDP Request in Timer Interrupt */
-				if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev,
-                	              			ppp_priv_area)){
-	               			flags->imask |= PPP_INTR_TIMER;
-				}
-				++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request;
-
-
-			} else if (handle_IPXWAN(skb->data,card->devname, 
-						 ppp_priv_area->enable_IPX, 
-						 ppp_priv_area->network_number, 
-						 skb->protocol)) {
-			
-				/* Handle an IPXWAN packet */
-				if( ppp_priv_area->enable_IPX) {
-					
-					/* Make sure we are not already sending */
-					if (!test_bit(SEND_CRIT, &card->wandev.critical)){
-					 	ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX));
-					}
-					dev_kfree_skb_any(skb);
-
-				} else {
-					++card->wandev.stats.rx_dropped;
-				}
-			} else {
-				/* Pass data up the protocol stack */
-	    			skb->dev = dev;
-				skb->mac.raw  = skb->data;
-
-			    	++card->wandev.stats.rx_packets;
-				card->wandev.stats.rx_bytes += skb->len;
-		    		++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack;	
-				netif_rx(skb);
-				dev->last_rx = jiffies;
-			}
-
-		} else {
-	
-			if (net_ratelimit()){
-				printk(KERN_INFO "%s: no socket buffers available!\n",
-					card->devname);
-			}
-			++card->wandev.stats.rx_dropped;
-			++ppp_priv_area->rx_intr_stat.rx_intr_no_socket;
-		}
-
-	} else {
-		++card->statistics.rx_intr_dev_not_started;
-	}
-
-	/* Release buffer element and calculate a pointer to the next one */
-	rxbuf->flag = 0x00;
-	card->rxmb = ++rxbuf;
-	if ((void*)rxbuf > card->u.p.rxbuf_last)
-		card->rxmb = card->u.p.rxbuf_base;
-}
-
-
-void event_intr (sdla_t *card)
-{
-
- 	struct net_device* dev = card->wandev.dev;
-        ppp_private_area_t* ppp_priv_area = dev->priv;
-	volatile ppp_flags_t *flags = card->flags;
-
-	switch (flags->iflag){
-
-		case PPP_INTR_MODEM:    /* modem status change (DCD, CTS) 0x04  (bit 2)*/
-
-			if (net_ratelimit()){
-				printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n",
-					card->devname, DCD(flags->mstatus), CTS(flags->mstatus));
-			}
-			break;
-
-		case PPP_INTR_DISC:  	/* Data link disconnected 0x10  (bit 4)*/	
-
-			NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n",
-					       flags->disc_cause);
-
-			if (flags->disc_cause &
-				(PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP |
-				PPP_REMOTE_TERMINATION)) {
-
-				if (card->u.p.ip_mode == WANOPT_PPP_PEER) { 
-					set_bit(0,&Read_connection_info);
-				}
-				wanpipe_set_state(card, WAN_DISCONNECTED);
-
-				show_disc_cause(card, flags->disc_cause);
-				ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
-				flags->imask |= PPP_INTR_TIMER;
-				trigger_ppp_poll(dev);
-			}
-			break;
-
-		case PPP_INTR_OPEN:   	/* Data link open 0x20  (bit 5)*/
-
-			NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n",
-					card->devname,LCP(flags->lcp_state),
-					IP(flags->ip_state));
-
-			if (flags->lcp_state == 0x09 && 
-                           (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){
-
-                                /* Initialize the polling timer and set the state
-                                 * to WAN_CONNNECTED */
-
-
-				/* BUG FIX: When the protocol restarts, during heavy 
-                                 * traffic, board tx buffers and driver tx buffers
-                                 * can go out of sync.  This checks the condition
-                                 * and if the tx buffers are out of sync, the 
-                                 * protocols are restarted. 
-                                 * I don't know why the board tx buffer is out
-                                 * of sync. It could be that a packets is tx
-                                 * while the link is down, but that is not 
-                                 * possible. The other possiblility is that the
-                                 * firmware doesn't reinitialize properly.
-                                 * FIXME: A better fix should be found.
-                                 */ 
-				if (detect_and_fix_tx_bug(card)){
-
-					ppp_comm_disable(card);
-
-					wanpipe_set_state(card, WAN_DISCONNECTED);
-
-					ppp_priv_area->timer_int_enabled |= 
-						TMR_INT_ENABLED_PPP_EVENT;
-					flags->imask |= PPP_INTR_TIMER;
-					break;	
-				}
-
-				card->state_tick = jiffies;
-				wanpipe_set_state(card, WAN_CONNECTED);
-
-				NEX_PRINTK(KERN_INFO "CON: L Tx: %lx  B Tx: %lx || L Rx %lx B Rx %lx\n",
-					(unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next,
-					(unsigned long)card->rxmb, *card->u.p.rxbuf_next);
-
-				/* Tell timer interrupt that PPP event occurred */
-				ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
-				flags->imask |= PPP_INTR_TIMER;
-
-				/* If we are in PEER mode, we must first obtain the
-				 * IP information and then go into the poll routine */
-				if (card->u.p.ip_mode != WANOPT_PPP_PEER){	
-					trigger_ppp_poll(dev);
-				}
-			}
-                   	break;
-
-		case PPP_INTR_DROP_DTR:		/* DTR drop timeout expired  0x40 bit 6 */
-
-			NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n"); 
-
-			if (card->u.p.ip_mode == WANOPT_PPP_PEER) { 
-				set_bit(0,&Read_connection_info);
-			}
-		
-			wanpipe_set_state(card, WAN_DISCONNECTED);
-
-			show_disc_cause(card, flags->disc_cause);
-			ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT;
-			flags->imask |= PPP_INTR_TIMER;
-			trigger_ppp_poll(dev);
-			break;
-		
-		default:
-			printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname);
-	}
-}
-
-
-
-/* TIMER INTERRUPT */
-
-void timer_intr (sdla_t *card)
-{
-
-        struct net_device* dev = card->wandev.dev;
-        ppp_private_area_t* ppp_priv_area = dev->priv;
-	ppp_flags_t *flags = card->flags;
-
-
-	if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){
-		if (!config_ppp(card)){
-			ppp_priv_area->timer_int_enabled &= 
-					~TMR_INT_ENABLED_CONFIG;	
-		}
-	}
-
-	/* Update statistics */
-	if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){
-		ppp_get_err_stats(card);
-                if(!(--ppp_priv_area->update_comms_stats)){
-			ppp_priv_area->timer_int_enabled &= 
-				~TMR_INT_ENABLED_UPDATE;
-		}
-	}
-
-	/* PPIPEMON UDP request */
-
-	if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){
-		process_udp_mgmt_pkt(card,dev, ppp_priv_area);
-		ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
-	}
-
-	/* PPP Event */
-	if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){
-
-		if (card->wandev.state == WAN_DISCONNECTED){
-			retrigger_comm(card);
-		}
-
-		/* If the state is CONNECTING, it means that communicatins were
-	 	 * enabled. When the remote side enables its comminication we
-	 	 * should get an interrupt PPP_INTR_OPEN, thus turn off polling 
-		 */
-
-		else if (card->wandev.state == WAN_CONNECTING){
-			/* Turn off the timer interrupt */
-			ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
-		}
-
-		/* If state is connected and we are in PEER mode 
-	 	 * poll for an IP address which will be provided by remote end.
-	 	 */
-		else if ((card->wandev.state == WAN_CONNECTED && 
-		  	  card->u.p.ip_mode == WANOPT_PPP_PEER) && 
-		  	  test_bit(0,&Read_connection_info)){
-
-			card->state_tick = jiffies;
-			if (read_connection_info (card)){
-				printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n",
-					card->devname);
-			}else{
-				clear_bit(0,&Read_connection_info);
-				set_bit(1,&Read_connection_info);
-				trigger_ppp_poll(dev);
-			}
-		}else{
-			//FIXME Put the comment back int
-			ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT;
-		}
-
-	}/* End of PPP_EVENT */
-
-
-	/* Only disable the timer interrupt if there are no udp, statistic */
-	/* updates or events pending */
-        if(!ppp_priv_area->timer_int_enabled) {
-                flags->imask &= ~PPP_INTR_TIMER;
-        }
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
-	int i;
-
-	if( proto == htons(ETH_P_IPX) ) {
-		//It's an IPX packet
-		if(!enable_IPX) {
-			//Return 1 so we don't pass it up the stack.
-			return 1;
-		}
-	} else {
-		//It's not IPX so pass it up the stack.
-		return 0;
-	}
-
-	if( sendpacket[16] == 0x90 &&
-	    sendpacket[17] == 0x04)
-	{
-		//It's IPXWAN
-
-		if( sendpacket[2] == 0x02 &&
-		    sendpacket[34] == 0x00)
-		{
-			//It's a timer request packet
-			printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
-			//Go through the routing options and answer no to every
-			//option except Unnumbered RIP/SAP
-			for(i = 41; sendpacket[i] == 0x00; i += 5)
-			{
-				//0x02 is the option for Unnumbered RIP/SAP
-				if( sendpacket[i + 4] != 0x02)
-				{
-					sendpacket[i + 1] = 0;
-				}
-			}
-
-			//Skip over the extended Node ID option
-			if( sendpacket[i] == 0x04 )
-			{
-				i += 8;
-			}
-
-			//We also want to turn off all header compression opt.
-			for(; sendpacket[i] == 0x80 ;)
-			{
-				sendpacket[i + 1] = 0;
-				i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
-			}
-
-			//Set the packet type to timer response
-			sendpacket[34] = 0x01;
-
-			printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
-		}
-		else if( sendpacket[34] == 0x02 )
-		{
-			//This is an information request packet
-			printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
-			//Set the packet type to information response
-			sendpacket[34] = 0x03;
-
-			//Set the router name
-			sendpacket[51] = 'P';
-			sendpacket[52] = 'T';
-			sendpacket[53] = 'P';
-			sendpacket[54] = 'I';
-			sendpacket[55] = 'P';
-			sendpacket[56] = 'E';
-			sendpacket[57] = '-';
-			sendpacket[58] = CVHexToAscii(network_number >> 28);
-			sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
-			sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
-			sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
-			sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
-			sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
-			sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
-			sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
-			for(i = 66; i < 99; i+= 1)
-			{
-				sendpacket[i] = 0;
-			}
-
-			printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
-		}
-		else
-		{
-			printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
-			return 0;
-		}
-
-		//Set the WNodeID to our network address
-		sendpacket[35] = (unsigned char)(network_number >> 24);
-		sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
-		sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
-		sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
-		return 1;
-	} else {
-		//If we get here it's an IPX-data packet, so it'll get passed up the stack.
-
-		//switch the network numbers
-		switch_net_numbers(sendpacket, network_number, 1);	
-		return 0;
-	}
-}
-
-/****** Background Polling Routines  ****************************************/
-
-/* All polling functions are invoked by the TIMER interrupt in the wpp_isr 
- * routine.  
- */
-
-/*============================================================================
- * Monitor active link phase.
- */
-static void process_route (sdla_t *card)
-{
-	ppp_flags_t *flags = card->flags;
-	struct net_device *dev = card->wandev.dev;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	
-	if ((card->u.p.ip_mode == WANOPT_PPP_PEER) &&
-	    (flags->ip_state == 0x09)){ 
-
-		/* We get ip_local from the firmware in PEER mode.
-	         * Therefore, if ip_local is 0, we failed to obtain
-         	 * the remote IP address. */
-		if (ppp_priv_area->ip_local == 0) 
-			return;
-		
-		printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname);
-		if (read_info( card )) {
-   			printk(KERN_INFO 
-				"%s: An error occurred in IP assignment.\n", 
-				card->devname);
-		} else {
-			struct in_device *in_dev = dev->ip_ptr;
-			if (in_dev != NULL ) {
-				struct in_ifaddr *ifa = in_dev->ifa_list;
-
-				printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", 
-					card->devname, NIPQUAD(ifa->ifa_local));
-				printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n", 
-						card->devname, NIPQUAD(ifa->ifa_address));
-			}else{
-				printk(KERN_INFO 
-				"%s: Error: Failed to add a route for PPP interface %s\n",
-					card->devname,dev->name);	
-			}
-		}
-	}
-}
-
-/*============================================================================
- * Monitor physical link disconnected phase.
- *  o if interface is up and the hold-down timeout has expired, then retry
- *    connection.
- */
-static void retrigger_comm(sdla_t *card)
-{
-	struct net_device *dev = card->wandev.dev;
-
-	if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) {
-
-		wanpipe_set_state(card, WAN_CONNECTING);
-
-		if(ppp_comm_enable(card) == CMD_OK){
-			init_ppp_tx_rx_buff( card );
-		}	         
-	}
-}
-
-/****** Miscellaneous Functions *********************************************/
-
-/*============================================================================
- * Configure S508 adapter.
- */
-static int config508(struct net_device *dev, sdla_t *card)
-{
-	ppp508_conf_t cfg;
-	struct in_device *in_dev = dev->ip_ptr;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-
-	/* Prepare PPP configuration structure */
-	memset(&cfg, 0, sizeof(ppp508_conf_t));
-
-	if (card->wandev.clocking)
-		cfg.line_speed = card->wandev.bps;
-
-	if (card->wandev.interface == WANOPT_RS232)
-		cfg.conf_flags |= INTERFACE_LEVEL_RS232;
-
-
-        cfg.conf_flags 	|= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/
-	cfg.txbuf_percent	= PERCENT_TX_BUFF;	/* % of Tx bufs */
-	cfg.mtu_local		= card->wandev.mtu;
-	cfg.mtu_remote		= card->wandev.mtu;                  /*    Default   */
-	cfg.restart_tmr		= TIME_BETWEEN_CONF_REQ;  	     /*    30 = 3sec */
-	cfg.auth_rsrt_tmr	= TIME_BETWEEN_PAP_CHAP_REQ;         /*    30 = 3sec */
-	cfg.auth_wait_tmr	= WAIT_PAP_CHAP_WITHOUT_REPLY;       /*   300 = 30s  */
-	cfg.mdm_fail_tmr	= WAIT_AFTER_DCD_CTS_LOW;            /*     5 = 0.5s */
-	cfg.dtr_drop_tmr	= TIME_DCD_CTS_LOW_AFTER_LNK_DOWN;   /*    10 = 1s   */
-	cfg.connect_tmout	= WAIT_DCD_HIGH_AFTER_ENABLE_COMM;   /*   900 = 90s  */
-	cfg.conf_retry		= MAX_CONF_REQ_WITHOUT_REPLY;        /*    10 = 1s   */
-	cfg.term_retry		= MAX_TERM_REQ_WITHOUT_REPLY;	     /*     2 times  */
-	cfg.fail_retry		= NUM_CONF_NAK_WITHOUT_REPLY;        /*     5 times  */
-	cfg.auth_retry		= NUM_AUTH_REQ_WITHOUT_REPLY;        /*     10 times */   
-
-
-	if( !card->u.p.authenticator ) {
-		printk(KERN_INFO "%s: Device is not configured as an authenticator\n", 
-				card->devname);
-		cfg.auth_options = NO_AUTHENTICATION;
-	}else{
-		printk(KERN_INFO "%s: Device is configured as an authenticator\n", 
-				card->devname);
-		cfg.auth_options = INBOUND_AUTH;
-	}
-
-	if( ppp_priv_area->pap == WANOPT_YES){
-		cfg.auth_options |=PAP_AUTH;
-		printk(KERN_INFO "%s: Pap enabled\n", card->devname);
-	}
-	if( ppp_priv_area->chap == WANOPT_YES){
-		cfg.auth_options |= CHAP_AUTH;
-		printk(KERN_INFO "%s: Chap enabled\n", card->devname);
-	}
-
-
-	if (ppp_priv_area->enable_IPX == WANOPT_YES){
-		printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname);
-		cfg.ipx_options		= ENABLE_IPX | ROUTING_PROT_DEFAULT;
-	}else{
-		cfg.ipx_options 	= DISABLE_IPX;
-	}
-
-	switch (card->u.p.ip_mode) {
-	
-		case WANOPT_PPP_STATIC:
-
-			printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname);
-			cfg.ip_options		= L_AND_R_IP_NO_ASSIG | 
-							    ENABLE_IP;
-			cfg.ip_local		= in_dev->ifa_list->ifa_local;
-			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-			/* Debugging code used to check that IP addresses
-                         * obtained from the kernel are correct */
-
-                        NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
-					NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
-			break;
-
-		case WANOPT_PPP_HOST:
-
-			printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname);
-			cfg.ip_options		= L_IP_LOCAL_ASSIG |
-						  R_IP_LOCAL_ASSIG | 
-						  ENABLE_IP;
-			cfg.ip_local		= in_dev->ifa_list->ifa_local;
-			cfg.ip_remote		= in_dev->ifa_list->ifa_address;
-			/* Debugging code used to check that IP addresses
-                         * obtained from the kernel are correct */
-                        NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n",
-					NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name);
-			
-			break;
-	
-		case WANOPT_PPP_PEER:
-
-			printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname);
-			cfg.ip_options		= L_IP_REMOTE_ASSIG | 
-						  R_IP_REMOTE_ASSIG | 
-							  ENABLE_IP;
-			cfg.ip_local		= 0x00;
-			cfg.ip_remote		= 0x00;
-			break;
-
-		default:
-			printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
-					card->devname);
-			printk(KERN_INFO "%s:        PPP IP Modes: STATIC, PEER or HOST\n",
-					card->devname);	
-			return 1;
-	}
-
-	return ppp_configure(card, &cfg);
-}
-
-/*============================================================================
- * Show disconnection cause.
- */
-static void show_disc_cause(sdla_t *card, unsigned cause)
-{
-	if (cause & 0x0802) 
-
-		printk(KERN_INFO "%s: link terminated by peer\n", 
-			card->devname);
-
-	else if (cause & 0x0004) 
-
-		printk(KERN_INFO "%s: link terminated by user\n", 
-			card->devname);
-
-	else if (cause & 0x0008) 
-
-		printk(KERN_INFO "%s: authentication failed\n", card->devname);
-	
-	else if (cause & 0x0010) 
-
-		printk(KERN_INFO 
-			"%s: authentication protocol negotiation failed\n", 
-			card->devname);
-
-	else if (cause & 0x0020) 
-		
-		printk(KERN_INFO
-		"%s: peer's request for authentication rejected\n",
-		card->devname);
-
-	else if (cause & 0x0040) 
-	
-		printk(KERN_INFO "%s: MRU option rejected by peer\n", 
-		card->devname);
-
-	else if (cause & 0x0080) 
-	
-		printk(KERN_INFO "%s: peer's MRU was too small\n", 
-		card->devname);
-
-	else if (cause & 0x0100) 
-
-		printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n",
-		card->devname);
-
-	else if (cause & 0x0200) 
-		
-		printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n"
-		, card->devname);
-
-	else if (cause & 0x0400) 
-
-		printk(KERN_INFO 
-			"%s: failed to negotiate peer's IPXCP options\n",
-			card->devname);
-}
-
-/*=============================================================================
- * Process UDP call of type PTPIPEAB.
- */
-static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, 
-				 ppp_private_area_t *ppp_priv_area ) 
-{
-	unsigned char buf2[5];
-	unsigned char *buf;
-	unsigned int frames, len;
-	struct sk_buff *new_skb;
-	unsigned short data_length, buffer_length, real_len;
-	unsigned long data_ptr;
-	int udp_mgmt_req_valid = 1;
-	ppp_mbox_t *mbox = card->mbox;
-	struct timeval tv;
-	int err;
-	ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data;
-
-	memcpy(&buf2, &card->wandev.udp_port, 2 );
-
-
-	if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
-		switch(ppp_udp_pkt->cblock.command) {
-
-			case PPIPE_GET_IBA_DATA:
-			case PPP_READ_CONFIG:
-			case PPP_GET_CONNECTION_INFO:
-			case PPIPE_ROUTER_UP_TIME:
-			case PPP_READ_STATISTICS:
-			case PPP_READ_ERROR_STATS:
-			case PPP_READ_PACKET_STATS:
-			case PPP_READ_LCP_STATS:
-			case PPP_READ_IPCP_STATS:
-			case PPP_READ_IPXCP_STATS:
-			case PPP_READ_PAP_STATS:
-			case PPP_READ_CHAP_STATS:
-			case PPP_READ_CODE_VERSION:
-				udp_mgmt_req_valid = 1;
-				break;
-			   
-			default:
-				udp_mgmt_req_valid = 0;
-				break;
-		} 
-	}
-	
-  	if(!udp_mgmt_req_valid) {
-	    
-		/* set length to 0 */
-    		ppp_udp_pkt->cblock.length = 0x00;
-
-    		/* set return code */
-    		ppp_udp_pkt->cblock.result = 0xCD; 
-		++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
-	
-		if (net_ratelimit()){	
-			printk(KERN_INFO 
-			"%s: Warning, Illegal UDP command attempted from network: %x\n",
-			card->devname,ppp_udp_pkt->cblock.command);
-		}
-   	} else {
-		/* Initialize the trace element */
-		trace_element_t trace_element;		    
-
-		switch (ppp_udp_pkt->cblock.command){
-
-		/* PPIPE_ENABLE_TRACING */
-    		case PPIPE_ENABLE_TRACING:
-			if (!card->TracingEnabled) {
-    			
-				/* OPERATE_DATALINE_MONITOR */
-    				mbox->cmd.command = PPP_DATALINE_MONITOR;
-    				mbox->cmd.length = 0x01;
-    				mbox->data[0] = ppp_udp_pkt->data[0];
-	    			err = sdla_exec(mbox) ? 
-					mbox->cmd.result : CMD_TIMEOUT;
-	   
-				if (err != CMD_OK) { 
-	        			
-					ppp_error(card, err, mbox);
-	        			card->TracingEnabled = 0;
-	        		
-					/* set the return code */
-
-		        		ppp_udp_pkt->cblock.result = mbox->cmd.result;
-	        			mbox->cmd.length = 0;
-	        			break;
-	    			} 
-
-				sdla_peek(&card->hw, 0xC000, &buf2, 2);
-		    
-				ppp_priv_area->curr_trace_addr = 0;
-		    		memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2);
-		    		ppp_priv_area->start_trace_addr = 
-						ppp_priv_area->curr_trace_addr;
-				ppp_priv_area->end_trace_addr = 
-					ppp_priv_area->start_trace_addr + END_OFFSET;
-		    	
-				/* MAX_SEND_BUFFER_SIZE - 28 (IP header) 
-				   - 32 (ppipemon CBLOCK) */
-		    		available_buffer_space = MAX_LGTH_UDP_MGNT_PKT - 
-							 sizeof(ip_pkt_t)-
-							 sizeof(udp_pkt_t)-
-							 sizeof(wp_mgmt_t)-
-							 sizeof(cblock_t);
-	       	  	}
-	       	  	ppp_udp_pkt->cblock.result = 0;
-	       	  	mbox->cmd.length = 0;
-	       	  	card->TracingEnabled = 1;
-	       	  	break;
-	   
-		/* PPIPE_DISABLE_TRACING */
-		case PPIPE_DISABLE_TRACING:
-	      		
-			if(card->TracingEnabled) {
-		   	
-				/* OPERATE_DATALINE_MONITOR */
-		    		mbox->cmd.command = 0x33;
-		    		mbox->cmd.length = 1;
-		    		mbox->data[0] = 0x00;
-		    		err = sdla_exec(mbox) ? 
-					mbox->cmd.result : CMD_TIMEOUT;
-	       	  
-			} 
-		
-			/*set return code*/
-			ppp_udp_pkt->cblock.result = 0;
-			mbox->cmd.length = 0;
-			card->TracingEnabled = 0;
-			break;
-	   
-		/* PPIPE_GET_TRACE_INFO */
-		case PPIPE_GET_TRACE_INFO:
-
-			if(!card->TracingEnabled) {
-				/* set return code */
-	    			ppp_udp_pkt->cblock.result = 1;
-	    			mbox->cmd.length = 0;
-			}		    
-
-			buffer_length = 0;
-			
-			/* frames < 62, where 62 is the number of trace
-			   information elements.  There is in total 496
-			   bytes of space and each trace information
-			   element is 8 bytes. 
-			 */
-			for ( frames=0; frames<62; frames++) {
-	
-				trace_pkt_t *trace_pkt = (trace_pkt_t *)
-					&ppp_udp_pkt->data[buffer_length];
-	
-				/* Read the whole trace packet */
-				sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr, 
-					  &trace_element, sizeof(trace_element_t));
-	
-				/* no data on board so exit */
-				if( trace_element.opp_flag == 0x00 ) 
-					break;
-	      
-				data_ptr = trace_element.trace_data_ptr;
-
-				/* See if there is actual data on the trace buffer */
-				if (data_ptr){
-					data_length = trace_element.trace_length;
-				}else{
-					data_length = 0;
-					ppp_udp_pkt->data[0] |= 0x02;
-				}
-
-				//FIXME: Do we need this check
-				if ((available_buffer_space - buffer_length) 
-				     < (sizeof(trace_element_t)+1)){
-					
-					/*indicate we have more frames 
-					 * on board and exit 
-					 */
-					ppp_udp_pkt->data[0] |= 0x02;
-					break;
-				}
-				
-				trace_pkt->status = trace_element.trace_type;
-				trace_pkt->time_stamp = trace_element.trace_time_stamp;
-				trace_pkt->real_length = trace_element.trace_length;
-
-				real_len = trace_element.trace_length;	
-				
-				if(data_ptr == 0){
-					trace_pkt->data_avail = 0x00;
-				}else{
-					/* we can take it next time */
-					if ((available_buffer_space - buffer_length)<
-						(real_len + sizeof(trace_pkt_t))){
-					
-						ppp_udp_pkt->data[0] |= 0x02;
-						break;
-					} 
-					trace_pkt->data_avail = 0x01;
-				
-					/* get the data */
-					sdla_peek(&card->hw, data_ptr, 
-						  &trace_pkt->data,
-						  real_len);
-				}	
-				/* zero the opp flag to 
-				   show we got the frame */
-				buf2[0] = 0x00;
-				sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr,
-					  &buf2, 1);
-
-				/* now move onto the next 
-				   frame */
-				ppp_priv_area->curr_trace_addr += 8;
-
-				/* check if we passed the last address */
-				if ( ppp_priv_area->curr_trace_addr >= 
-					ppp_priv_area->end_trace_addr){
-
-					ppp_priv_area->curr_trace_addr = 
-						ppp_priv_area->start_trace_addr;
-				}
- 
-				/* update buffer length and make sure its even */ 
-
-				if ( trace_pkt->data_avail == 0x01 ) {
-					buffer_length += real_len - 1;
-				}
- 
-				/* for the header */
-				buffer_length += 8;
-
-				if( buffer_length & 0x0001 )
-					buffer_length += 1;
-			}
-
-			/* ok now set the total number of frames passed
-			   in the high 5 bits */
-			ppp_udp_pkt->data[0] |= (frames << 2);
-	 
-			/* set the data length */
-			mbox->cmd.length = buffer_length;
-			ppp_udp_pkt->cblock.length = buffer_length;
-	 
-			/* set return code */
-			ppp_udp_pkt->cblock.result = 0;
-	      	  	break;
-
-   		/* PPIPE_GET_IBA_DATA */
-		case PPIPE_GET_IBA_DATA:
-	        
-			mbox->cmd.length = 0x09;
-		
-			sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data, 
-					mbox->cmd.length);
-	        
-			/* set the length of the data */
-			ppp_udp_pkt->cblock.length = 0x09;
-
-			/* set return code */
-			ppp_udp_pkt->cblock.result = 0x00;
-			ppp_udp_pkt->cblock.result = 0;
-			break;
-
-		/* PPIPE_FT1_READ_STATUS */
-		case PPIPE_FT1_READ_STATUS:
-			sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2);
-			ppp_udp_pkt->cblock.length = mbox->cmd.length = 2;
-			ppp_udp_pkt->cblock.result = 0;
-			break;
-		
-		case PPIPE_FLUSH_DRIVER_STATS:   
-			init_ppp_priv_struct( ppp_priv_area );
-			init_global_statistics( card );
-			mbox->cmd.length = 0;
-			ppp_udp_pkt->cblock.result = 0;
-			break;
-
-		
-		case PPIPE_ROUTER_UP_TIME:
-
-			do_gettimeofday( &tv );
-			ppp_priv_area->router_up_time = tv.tv_sec - 
-					ppp_priv_area->router_start_time;
-			*(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time;
-			mbox->cmd.length = 4;
-			ppp_udp_pkt->cblock.result = 0;
-			break;
-
-				/* PPIPE_DRIVER_STATISTICS */   
-		case PPIPE_DRIVER_STAT_IFSEND:
-			memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat, 
-				sizeof(if_send_stat_t));
-
-
-			ppp_udp_pkt->cblock.result = 0;
-			ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t);
-			mbox->cmd.length = sizeof(if_send_stat_t);	
-			break;
-
-		case PPIPE_DRIVER_STAT_INTR:
-			memcpy(&ppp_udp_pkt->data, &card->statistics, 
-				sizeof(global_stats_t));
-
-			memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t),
-				&ppp_priv_area->rx_intr_stat,
-				sizeof(rx_intr_stat_t));
-
-			ppp_udp_pkt->cblock.result = 0;
-			ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
-						     sizeof(rx_intr_stat_t);
-			mbox->cmd.length = ppp_udp_pkt->cblock.length;
-			break;
-
-		case PPIPE_DRIVER_STAT_GEN:
-			memcpy( &ppp_udp_pkt->data,
-				&ppp_priv_area->pipe_mgmt_stat,
-				sizeof(pipe_mgmt_stat_t));
-
-			memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t), 
-			       &card->statistics, sizeof(global_stats_t));
-
-			ppp_udp_pkt->cblock.result = 0;
-			ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+
-						     sizeof(rx_intr_stat_t);
-			mbox->cmd.length = ppp_udp_pkt->cblock.length;
-			break;
-
-
-		/* FT1 MONITOR STATUS */
-   		case FT1_MONITOR_STATUS_CTRL:
-	
-			/* Enable FT1 MONITOR STATUS */
-	        	if( ppp_udp_pkt->data[0] == 1) {
-			
-				if( rCount++ != 0 ) {
-		        		ppp_udp_pkt->cblock.result = 0;
-	          			mbox->cmd.length = 1;
-		  			break;
-		    		}	
-	      		}
-
-	      		/* Disable FT1 MONITOR STATUS */
-	      		if( ppp_udp_pkt->data[0] == 0) {
-
-	      	   		if( --rCount != 0) {
-		  			ppp_udp_pkt->cblock.result = 0;
-		  			mbox->cmd.length = 1;
-		  			break;
-	   	    		} 
-	      		} 	
-			goto udp_dflt_cmd;
-			
-		/* WARNING: FIXME: This should be fixed.
-		 * The FT1 Status Ctrl doesn't have a break
-                 * statment.  Thus, no code must be inserted
-                 * HERE: between default and above case statement */
-
-		default:
-udp_dflt_cmd:
-	        
-			/* it's a board command */
-			mbox->cmd.command = ppp_udp_pkt->cblock.command;
-			mbox->cmd.length = ppp_udp_pkt->cblock.length;
- 
-			if(mbox->cmd.length) {
-				memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data,
-				       mbox->cmd.length);
-	      		} 
-	          
-			/* run the command on the board */
-			err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-		
-			if (err != CMD_OK) {
-		
-		    		ppp_error(card, err, mbox);
-		    		++ppp_priv_area->pipe_mgmt_stat.
-					 UDP_PIPE_mgmt_adptr_cmnd_timeout;
-				break;
-			}
-	          
-		  	++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
-		
-			/* copy the result back to our buffer */
-			memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t));
-	          
-			if(mbox->cmd.length) {
-				memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length);
-			} 
-
-		} /* end of switch */
-     	} /* end of else */
-
-     	/* Fill UDP TTL */
-     	ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl; 
-     	len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length);
-
-     	if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
-		/* Make sure we are not already sending */
-		if (!test_bit(SEND_CRIT,&card->wandev.critical)){
-			++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr;
-			ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol);
-		}
-
-	} else {	
-	
-		/* Pass it up the stack
-    		   Allocate socket buffer */
-		if ((new_skb = dev_alloc_skb(len)) != NULL) {
-	    	
-			/* copy data into new_skb */
-
-  	    		buf = skb_put(new_skb, len);
-  	    		memcpy(buf,ppp_priv_area->udp_pkt_data, len);
-
-	    		++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-			
-            		/* Decapsulate packet and pass it up the protocol 
-			   stack */
-	    		new_skb->protocol = htons(ETH_P_IP);
-            		new_skb->dev = dev;
-	    		new_skb->mac.raw  = new_skb->data;
-			netif_rx(new_skb);
-			dev->last_rx = jiffies;
-		
-		} else {
-	    	
-			++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
-			printk(KERN_INFO "no socket buffers available!\n");
-  		}
-    	}	
-
-	ppp_priv_area->udp_pkt_lgth = 0;
-	
-	return; 
-}
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area )
-{
-
-	memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t));
-	memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t));
-	memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t));	
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
-	memset(&card->statistics, 0, sizeof(global_stats_t));
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-static void init_ppp_tx_rx_buff( sdla_t *card )
-{
-	ppp508_buf_info_t* info;
-
-	if (card->hw.type == SDLA_S514) {
-		
-		info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS);
-
-       		card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
-			info->txb_ptr);
-
-                card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
-                        (info->txb_num - 1);
-
-                card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
-                        info->rxb_ptr);
-
-                card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
-                        (info->rxb_num - 1);
-
-	} else {
-		
-		info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS);
-
-		card->u.p.txbuf_base = (void*)(card->hw.dpmbase +
-			(info->txb_ptr - PPP508_MB_VECT));
-
-		card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base +
-			(info->txb_num - 1);
-
-		card->u.p.rxbuf_base = (void*)(card->hw.dpmbase +
-			(info->rxb_ptr - PPP508_MB_VECT));
-
-		card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base +
-			(info->rxb_num - 1);
-	}
-
-	card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt; 
-	card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr;
-
-	card->u.p.rx_base = info->rxb_base;
-        card->u.p.rx_top  = info->rxb_end;
-      
-	card->u.p.txbuf = card->u.p.txbuf_base;
-	card->rxmb = card->u.p.rxbuf_base;
-
-}
-
-/*=============================================================================
- * Read Connection Information (ie for Remote IP address assginment).
- * Called when ppp interface connected.
- */
-static int read_info( sdla_t *card )
-{
-	struct net_device *dev = card->wandev.dev;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	int err;
-
-	struct ifreq if_info;
-	struct sockaddr_in *if_data1, *if_data2;
-	mm_segment_t fs;
-
-	/* Set Local and remote addresses */
-	memset(&if_info, 0, sizeof(if_info));
-	strcpy(if_info.ifr_name, dev->name);
-
-
-	fs = get_fs();
-	set_fs(get_ds());     /* get user space block */ 
-
-	/* Change the local and remote ip address of the interface.
-	 * This will also add in the destination route.
-	 */	
-	if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
-	if_data1->sin_addr.s_addr = ppp_priv_area->ip_local;
-	if_data1->sin_family = AF_INET;
-	err = devinet_ioctl( SIOCSIFADDR, &if_info );
-	if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
-	if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote;
-	if_data2->sin_family = AF_INET;
-	err = devinet_ioctl( SIOCSIFDSTADDR, &if_info );
-
-	set_fs(fs);           /* restore old block */
-	
-	if (err) {
-		printk (KERN_INFO "%s: Adding of route failed: %i\n",
-			card->devname,err);
-		printk (KERN_INFO "%s:	Local : %u.%u.%u.%u\n",
-			card->devname,NIPQUAD(ppp_priv_area->ip_local));
-		printk (KERN_INFO "%s:	Remote: %u.%u.%u.%u\n",
-			card->devname,NIPQUAD(ppp_priv_area->ip_remote));
-	}
-	return err;
-}
-
-/*=============================================================================
- * Remove Dynamic Route.
- * Called when ppp interface disconnected.
- */
-
-static void remove_route( sdla_t *card )
-{
-
-	struct net_device *dev = card->wandev.dev;
-	long ip_addr;
-	int err;
-
-        mm_segment_t fs;
-	struct ifreq if_info;
-	struct sockaddr_in *if_data1;
-        struct in_device *in_dev = dev->ip_ptr;
-        struct in_ifaddr *ifa = in_dev->ifa_list;	
-
-	ip_addr = ifa->ifa_local;
-
-	/* Set Local and remote addresses */
-	memset(&if_info, 0, sizeof(if_info));
-	strcpy(if_info.ifr_name, dev->name);
-
-	fs = get_fs();
-       	set_fs(get_ds());     /* get user space block */ 
-
-	/* Change the local ip address of the interface to 0.
-	 * This will also delete the destination route.
-	 */	
-	if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
-	if_data1->sin_addr.s_addr = 0;
-	if_data1->sin_family = AF_INET;
-	err = devinet_ioctl( SIOCSIFADDR, &if_info );
-
-        set_fs(fs);           /* restore old block */
-
-	
-	if (err) {
-		printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n",
-			 card->devname, err);
-		return;
-	}else{
-		printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n",
-			card->devname, NIPQUAD(ip_addr));
-	}
-	return;
-}
-
-/*=============================================================================
- * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t *card )
-{
-	ppp_mbox_t *mb = card->mbox;
-	int err,i;
-
-	err = ppp_set_intr_mode( card, 0x08 );
-	
-	if (err == CMD_OK) { 
-		
-		for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {	
-			/* Run command READ_CODE_VERSION */
-			memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-			mb->cmd.length  = 0;
-			mb->cmd.command = PPP_READ_CODE_VERSION;
-			err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-			if (err != CMD_OK) 
-				ppp_error(card, err, mb);
-		}
-	}
-	else return err;
-
-	err = ppp_set_intr_mode( card, 0 );
-	if (err != CMD_OK) 
-		return err;
-
-	return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t *card )
-{
-	unsigned char *sendpacket;
-	unsigned char buf2[5]; 
-	ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data; 
-	
-	sendpacket = skb->data;
-	memcpy(&buf2, &card->wandev.udp_port, 2);
-	
-	if( 	ppp_udp_pkt->ip_pkt.ver_inet_hdr_length  == 0x45 &&        /* IP packet */ 
-		sendpacket[9]  == 0x11 &&        /* UDP packet */
-		sendpacket[22] == buf2[1] &&     /* UDP Port */
-		sendpacket[23] == buf2[0] &&
-		sendpacket[36] == 0x01 ) {
-	
-		if (    sendpacket[28] == 0x50 &&    /* PTPIPEAB: Signature */ 
-			sendpacket[29] == 0x54 &&      
-			sendpacket[30] == 0x50 &&      
-			sendpacket[31] == 0x49 &&      
-			sendpacket[32] == 0x50 &&      
-			sendpacket[33] == 0x45 &&      
-			sendpacket[34] == 0x41 &&      
-			sendpacket[35] == 0x42 ){ 
-
-			return UDP_PTPIPE_TYPE;
-	
-		} else if(sendpacket[28] == 0x44 &&  /* DRVSTATS: Signature */
-			sendpacket[29] == 0x52 &&      
-      			sendpacket[30] == 0x56 &&      
-      			sendpacket[31] == 0x53 &&      
-      			sendpacket[32] == 0x54 &&      
-      			sendpacket[33] == 0x41 &&      
-      			sendpacket[34] == 0x54 &&      
-      			sendpacket[35] == 0x53 ){
-	
-			return UDP_DRVSTATS_TYPE;
-
-		} else
-			return UDP_INVALID_TYPE;
-
-	} else
-		return UDP_INVALID_TYPE;
-
-}
-
-/*============================================================================
- * Check to see if the packet to be transmitted contains a broadcast or
- * multicast source IP address.
- */
-
-static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev,
-				struct sk_buff *skb)
-{
-	u32 src_ip_addr;
-        u32 broadcast_ip_addr = 0;
-        struct in_device *in_dev;
-
-        /* read the IP source address from the outgoing packet */
-        src_ip_addr = *(u32 *)(skb->data + 12);
-
-	/* read the IP broadcast address for the device */
-        in_dev = dev->ip_ptr;
-        if(in_dev != NULL) {
-                struct in_ifaddr *ifa= in_dev->ifa_list;
-                if(ifa != NULL)
-                        broadcast_ip_addr = ifa->ifa_broadcast;
-                else
-                        return 0;
-        }
- 
-        /* check if the IP Source Address is a Broadcast address */
-        if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {
-                printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n",
-				card->devname);
-                return 1;
-        } 
-
-        /* check if the IP Source Address is a Multicast address */
-        if((ntohl(src_ip_addr) >= 0xE0000001) &&
-		(ntohl(src_ip_addr) <= 0xFFFFFFFE)) {
-                printk(KERN_INFO "%s: Multicast Source Address silently discarded\n",
-				card->devname);
-                return 1;
-        }
-
-        return 0;
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
-	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
-        spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-static int read_connection_info (sdla_t *card)
-{
-	ppp_mbox_t *mb = card->mbox;
-	struct net_device *dev = card->wandev.dev;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-	ppp508_connect_info_t *ppp508_connect_info;
-	int err;
-
-	memset(&mb->cmd, 0, sizeof(ppp_cmd_t));
-	mb->cmd.length  = 0;
-	mb->cmd.command = PPP_GET_CONNECTION_INFO;
-	err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK) { 
-		ppp_error(card, err, mb);
-		ppp_priv_area->ip_remote = 0;
-		ppp_priv_area->ip_local = 0;
-	}
-	else {
-		ppp508_connect_info = (ppp508_connect_info_t *)mb->data;
-		ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote;
-		ppp_priv_area->ip_local = ppp508_connect_info->ip_local;
-
-		NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n",
-				ppp_priv_area->ip_remote,
-				ppp_priv_area->ip_local);
-	}
-
-	return err;
-}
-
-/*===============================================================================
- * config_ppp
- *
- *	Configure the ppp protocol and enable communications.		
- *
- *   	The if_open function binds this function to the poll routine.
- *      Therefore, this function will run every time the ppp interface
- *      is brought up.  
- *      
- *	If the communications are not enabled, proceed to configure
- *      the card and enable communications.
- *
- *      If the communications are enabled, it means that the interface
- *      was shutdown by ether the user or driver. In this case, we 
- *      have to check that the IP addresses have not changed.  If
- *      the IP addresses changed, we have to reconfigure the firmware
- *      and update the changed IP addresses.  Otherwise, just exit.
- */
-static int config_ppp (sdla_t *card)
-{
-
-	struct net_device *dev = card->wandev.dev;
-	ppp_flags_t *flags = card->flags;
-	ppp_private_area_t *ppp_priv_area = dev->priv;
-
-	if (card->u.p.comm_enabled){
-
-		if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local ||
-		    ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){
-			
-			/* The IP addersses have changed, we must
-                         * stop the communications and reconfigure
-                         * the card. Reason: the firmware must know
-                         * the local and remote IP addresses. */
-			disable_comm(card);
-			wanpipe_set_state(card, WAN_DISCONNECTED);
-			printk(KERN_INFO 
-				"%s: IP addresses changed!\n",
-					card->devname);
-			printk(KERN_INFO "%s: Restarting communications ...\n",
-					card->devname);
-		}else{ 
-			/* IP addresses are the same and the link is up, 
-                         * we don't have to do anything here. Therefore, exit */
-			return 0;
-		}
-	}
-
-	/* Record the new IP addreses */
-	ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp;
-	ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp;
-
-	if (config508(dev, card)){
-		printk(KERN_INFO "%s: Failed to configure PPP device\n",
-			card->devname);
-		return 0;
-	}
-
-	if (ppp_set_intr_mode(card, PPP_INTR_RXRDY|
-			    		PPP_INTR_TXRDY|
-				    	PPP_INTR_MODEM|
-				    	PPP_INTR_DISC |
-				    	PPP_INTR_OPEN |
-				    	PPP_INTR_DROP_DTR |
-					PPP_INTR_TIMER)) {
-
-		printk(KERN_INFO "%s: Failed to configure board interrupts !\n", 
-			card->devname);
-		return 0;
-	}
-
-        /* Turn off the transmit and timer interrupt */
-	flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ;
-
-
-	/* If you are not the authenticator and any one of the protocol is 
-	 * enabled then we call the set_out_bound_authentication.
-	 */
-	if ( !card->u.p.authenticator  && (ppp_priv_area->pap || ppp_priv_area->chap)) {
-		if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){
-			printk(KERN_INFO "%s: Outbound authentication failed !\n",
-				card->devname);
-			return 0;
-		}
-	} 
-	
-	/* If you are the authenticator and any one of the protocol is enabled
-	 * then we call the set_in_bound_authentication.
-	 */
-	if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){
-		if (ppp_set_inbnd_auth(card, ppp_priv_area)){
-			printk(KERN_INFO "%s: Inbound authentication failed !\n",
-				card->devname);	
-			return 0;
-		}
-	}
-
-	/* If we fail to enable communications here it's OK,
-	 * since the DTR timer will cause a disconnected, which
-	 * will retrigger communication in timer_intr() */
-	if (ppp_comm_enable(card) == CMD_OK) {
-		wanpipe_set_state(card, WAN_CONNECTING);
-		init_ppp_tx_rx_buff(card);
-	}
-
-	return 0; 
-}
-
-/*============================================================
- * ppp_poll
- *	
- * Rationale:
- * 	We cannot manipulate the routing tables, or
- *      ip addresses withing the interrupt. Therefore
- *      we must perform such actons outside an interrupt 
- *      at a later time. 
- *
- * Description:	
- *	PPP polling routine, responsible for 
- *     	shutting down interfaces upon disconnect
- *     	and adding/removing routes. 
- *      
- * Usage:        
- * 	This function is executed for each ppp  
- * 	interface through a tq_schedule bottom half.
- *      
- *      trigger_ppp_poll() function is used to kick
- *      the ppp_poll routine.  
- */
-static void ppp_poll(struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area; 	
-	sdla_t *card;
-	u8 check_gateway=0;
-	ppp_flags_t *flags;
-
-	if (!dev || (ppp_priv_area = dev->priv) == NULL)
-		return;
-
-	card = ppp_priv_area->card;
-	flags = card->flags;
-
-	/* Shutdown is in progress, stop what you are 
-	 * doing and get out */
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		clear_bit(POLL_CRIT,&card->wandev.critical);
-		return;
-	}
-
-	/* if_open() function has triggered the polling routine
-	 * to determine the configured IP addresses.  Once the
-	 * addresses are found, trigger the chdlc configuration */
-	if (test_bit(0,&ppp_priv_area->config_ppp)){
-
-		ppp_priv_area->ip_local_tmp  = get_ip_address(dev,WAN_LOCAL_IP);
-		ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
-		if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp && 
-	            card->u.p.ip_mode == WANOPT_PPP_HOST){
-			
-			if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){
-				printk(KERN_INFO "\n%s: --- WARNING ---\n",
-						card->devname);
-				printk(KERN_INFO "%s: The local IP address is the same as the\n",
-						card->devname);
-				printk(KERN_INFO "%s: Point-to-Point IP address.\n",
-						card->devname);
-				printk(KERN_INFO "%s: --- WARNING ---\n\n",
-						card->devname);
-			}else{
-				clear_bit(POLL_CRIT,&card->wandev.critical);
-				ppp_priv_area->poll_delay_timer.expires = jiffies+HZ;
-				add_timer(&ppp_priv_area->poll_delay_timer);
-				return;
-			}
-		}
-
-		ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
-		flags->imask |= PPP_INTR_TIMER;	
-		ppp_priv_area->ip_error=0;	
-		
-		clear_bit(0,&ppp_priv_area->config_ppp);
-		clear_bit(POLL_CRIT,&card->wandev.critical);
-		return;
-	}
-
-	/* Dynamic interface implementation, as well as dynamic
-	 * routing.  */
-	
-	switch (card->wandev.state) {
-	
-	case WAN_DISCONNECTED:
-
-		/* If the dynamic interface configuration is on, and interface 
-		 * is up, then bring down the netowrk interface */
-
-		if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
-		    !test_bit(DEV_DOWN,&ppp_priv_area->interface_down)	&&	
-		    card->wandev.dev->flags & IFF_UP){	
-
-			printk(KERN_INFO "%s: Interface %s down.\n",
-				card->devname,card->wandev.dev->name);
-			change_dev_flags(card->wandev.dev,
-					(card->wandev.dev->flags&~IFF_UP));
-			set_bit(DEV_DOWN,&ppp_priv_area->interface_down);
-		}else{
-			/* We need to check if the local IP address is
-               	   	 * zero. If it is, we shouldn't try to remove it.
-                 	 * For some reason the kernel crashes badly if 
-                 	 * we try to remove the route twice */
-
-			if (card->wandev.dev->flags & IFF_UP && 
-		    	    get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
-		    	    card->u.p.ip_mode == WANOPT_PPP_PEER){
-
-				remove_route(card);
-			}
-		}
-		break;
-
-	case WAN_CONNECTED:
-		
-		/* In SMP machine this code can execute before the interface
-		 * comes up.  In this case, we must make sure that we do not
-		 * try to bring up the interface before dev_open() is finished */
-
-
-		/* DEV_DOWN will be set only when we bring down the interface
-		 * for the very first time. This way we know that it was us
-		 * that brought the interface down */
-		
-		if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) &&
-	            test_bit(DEV_DOWN,  &ppp_priv_area->interface_down) &&
- 		    !(card->wandev.dev->flags & IFF_UP)){
-			
-			printk(KERN_INFO "%s: Interface %s up.\n",
-				card->devname,card->wandev.dev->name);
-			
-			change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
-			clear_bit(DEV_DOWN,&ppp_priv_area->interface_down);
-			check_gateway=1;
-		}
-
-		if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && 
-		    test_bit(1,&Read_connection_info)) { 
-			
-			process_route(card);
-			clear_bit(1,&Read_connection_info);
-			check_gateway=1;
-		}
-
-		if (ppp_priv_area->gateway && check_gateway)
-			add_gateway(card,dev);
-
-		break;
-	}
-	clear_bit(POLL_CRIT,&card->wandev.critical);
-	return;
-}
-
-/*============================================================
- * trigger_ppp_poll
- *
- * Description:
- * 	Add a ppp_poll() task into a tq_scheduler bh handler
- *      for a specific interface.  This will kick
- *      the ppp_poll() routine at a later time. 
- *
- * Usage:
- * 	Interrupts use this to defer a taks to 
- *      a polling routine.
- *
- */	
-
-static void trigger_ppp_poll(struct net_device *dev)
-{
-	ppp_private_area_t *ppp_priv_area;
-	if ((ppp_priv_area=dev->priv) != NULL){ 	
-		
-		sdla_t *card = ppp_priv_area->card;
-
-		if (test_bit(PERI_CRIT,&card->wandev.critical)){
-			return;
-		}
-		
-		if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
-			return;
-		}
-
-		schedule_work(&ppp_priv_area->poll_work);
-	}
-	return;
-}
-
-static void ppp_poll_delay (unsigned long dev_ptr)
-{
-	struct net_device *dev = (struct net_device *)dev_ptr;
-	trigger_ppp_poll(dev);
-}
-
-/*============================================================
- * detect_and_fix_tx_bug
- *
- * Description:
- *	On connect, if the board tx buffer ptr is not the same
- *      as the driver tx buffer ptr, we found a firmware bug.
- *      Report the bug to the above layer.  To fix the
- *      error restart communications again.
- *
- * Usage:
- *
- */	
-
-static int detect_and_fix_tx_bug (sdla_t *card)
-{
-	if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){
-		NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n");
-		return 1;
-	}
-	return 0;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
deleted file mode 100644
index 63f846d..0000000
--- a/drivers/net/wan/sdla_x25.c
+++ /dev/null
@@ -1,5497 +0,0 @@
-/*****************************************************************************
-* sdla_x25.c	WANPIPE(tm) Multiprotocol WAN Link Driver.  X.25 module.
-*
-* Author:	Nenad Corbic	<ncorbic@sangoma.com>
-*
-* Copyright:	(c) 1995-2001 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Apr 03, 2001  Nenad Corbic	 o Fixed the rx_skb=NULL bug in x25 in rx_intr().
-* Dec 26, 2000  Nenad Corbic	 o Added a new polling routine, that uses
-*                                  a kernel timer (more efficient).
-* Dec 25, 2000  Nenad Corbic	 o Updated for 2.4.X kernel
-* Jul 26, 2000  Nenad Corbic	 o Increased the local packet buffering
-* 				   for API to 4096+header_size. 
-* Jul 17, 2000  Nenad Corbic	 o Fixed the x25 startup bug. Enable 
-* 				   communications only after all interfaces
-* 				   come up.  HIGH SVC/PVC is used to calculate
-* 				   the number of channels.
-*                                  Enable protocol only after all interfaces
-*                                  are enabled.
-* Jul 10, 2000	Nenad Corbic	 o Fixed the M_BIT bug. 
-* Apr 25, 2000  Nenad Corbic	 o Pass Modem messages to the API.
-*                                  Disable idle timeout in X25 API.
-* Apr 14, 2000  Nenad Corbic	 o Fixed: Large LCN number support.
-*                                  Maximum LCN number is 4095.
-*                                  Maximum number of X25 channels is 255.
-* Apr 06, 2000  Nenad Corbic	 o Added SMP Support.
-* Mar 29, 2000  Nenad Corbic	 o Added support for S514 PCI Card
-* Mar 23, 2000  Nenad Corbic	 o Improved task queue, BH handling.
-* Mar 14, 2000  Nenad Corbic  	 o Updated Protocol Violation handling
-*                                  routines.  Bug Fix.
-* Mar 10, 2000  Nenad Corbic	 o Bug Fix: corrupted mbox recovery.
-* Mar 09, 2000  Nenad Corbic     o Fixed the auto HDLC bug.
-* Mar 08, 2000	Nenad Corbic     o Fixed LAPB HDLC startup problems.
-*                                  Application must bring the link up 
-*                                  before tx/rx, and bring the 
-*                                  link down on close().
-* Mar 06, 2000	Nenad Corbic	 o Added an option for logging call setup 
-*                                  information. 
-* Feb 29, 2000  Nenad Corbic 	 o Added support for LAPB HDLC API
-* Feb 25, 2000  Nenad Corbic     o Fixed the modem failure handling.
-*                                  No Modem OOB message will be passed 
-*                                  to the user.
-* Feb 21, 2000  Nenad Corbic 	 o Added Xpipemon Debug Support
-* Dec 30, 1999 	Nenad Corbic	 o Socket based X25API 
-* Sep 17, 1998	Jaspreet Singh	 o Updates for 2.2.X  kernel
-* Mar 15, 1998	Alan Cox	 o 2.1.x porting
-* Dec 19, 1997	Jaspreet Singh	 o Added multi-channel IPX support
-* Nov 27, 1997	Jaspreet Singh	 o Added protection against enabling of irqs
-*				   when they are disabled.
-* Nov 17, 1997  Farhan Thawar    o Added IPX support
-*				 o Changed if_send() to now buffer packets when
-*				   the board is busy
-*				 o Removed queueing of packets via the polling
-*				   routing
-*				 o Changed if_send() critical flags to properly
-*				   handle race conditions
-* Nov 06, 1997  Farhan Thawar    o Added support for SVC timeouts
-*				 o Changed PVC encapsulation to ETH_P_IP
-* Jul 21, 1997  Jaspreet Singh	 o Fixed freeing up of buffers using kfree()
-*				   when packets are received.
-* Mar 11, 1997  Farhan Thawar   Version 3.1.1
-*                                o added support for V35
-*                                o changed if_send() to return 0 if
-*                                  wandev.critical() is true
-*                                o free socket buffer in if_send() if
-*                                  returning 0
-*                                o added support for single '@' address to
-*                                  accept all incoming calls
-*                                o fixed bug in set_chan_state() to disconnect
-* Jan 15, 1997	Gene Kozin	Version 3.1.0
-*				 o implemented exec() entry point
-* Jan 07, 1997	Gene Kozin	Initial version.
-*****************************************************************************/
-
-/*======================================================
- * 	Includes 
- *=====================================================*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/ctype.h>
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/workqueue.h>
-#include <linux/jiffies.h>	/* time_after() macro */
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <asm/atomic.h>
-#include <linux/delay.h>	/* Experimental delay */
-
-#include <asm/uaccess.h>
-
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/sdla_x25.h>	/* X.25 firmware API definitions */
-#include <linux/if_wanpipe_common.h>
-#include <linux/if_wanpipe.h>
-
-
-/*======================================================
- * 	Defines & Macros 
- *=====================================================*/
-
-
-#define	CMD_OK		0		/* normal firmware return code */
-#define	CMD_TIMEOUT	0xFF		/* firmware command timed out */
-#define	MAX_CMD_RETRY	10		/* max number of firmware retries */
-
-#define	X25_CHAN_MTU	4096		/* unfragmented logical channel MTU */
-#define	X25_HRDHDR_SZ	7		/* max encapsulation header size */
-#define	X25_CONCT_TMOUT	(90*HZ)		/* link connection timeout */
-#define	X25_RECON_TMOUT	(10*HZ)		/* link connection timeout */
-#define	CONNECT_TIMEOUT	(90*HZ)		/* link connection timeout */
-#define	HOLD_DOWN_TIME	(30*HZ)		/* link hold down time */
-#define MAX_BH_BUFF	10
-#define M_BIT		0x01	
-
-//#define PRINT_DEBUG 1
-#ifdef PRINT_DEBUG
-#define DBG_PRINTK(format, a...) printk(format, ## a)
-#else
-#define DBG_PRINTK(format, a...)
-#endif  
-
-#define TMR_INT_ENABLED_POLL_ACTIVE      0x01
-#define TMR_INT_ENABLED_POLL_CONNECT_ON  0x02
-#define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04
-#define TMR_INT_ENABLED_POLL_DISCONNECT  0x08
-#define TMR_INT_ENABLED_CMD_EXEC	 0x10
-#define TMR_INT_ENABLED_UPDATE		 0x20
-#define TMR_INT_ENABLED_UDP_PKT		 0x40
-
-#define MAX_X25_ADDR_SIZE	16
-#define MAX_X25_DATA_SIZE 	129
-#define MAX_X25_FACL_SIZE	110
-
-#define TRY_CMD_AGAIN	2
-#define DELAY_RESULT    1
-#define RETURN_RESULT   0
-
-#define DCD(x) (x & 0x03 ? "HIGH" : "LOW")
-#define CTS(x) (x & 0x05 ? "HIGH" : "LOW")
-
-
-/* Driver will not write log messages about 
- * modem status if defined.*/
-#define MODEM_NOT_LOG 1
-
-/*==================================================== 
- * 	For IPXWAN 
- *===================================================*/
-
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-
-/*====================================================
- *           MEMORY DEBUGGING FUNCTION
- *====================================================
-
-#define KMEM_SAFETYZONE 8
-
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
-	int i = 0;
-	void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
-	char * c1 = v;	
-	c1 += sizeof(unsigned int);
-	*((unsigned int *)v) = size;
-
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
-		c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
-		c1 += 8;
-	}
-	c1 += size;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
-		c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
-		c1 += 8;
-	}
-	v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
-	printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
-	return v;
-}
-static void dbg_kfree(void * v, int line) {
-	unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
-	unsigned int size = *sp;
-	char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
-	int i = 0;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
-		    || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
-			printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
-			printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-			                c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-		}
-		c1 += 8;
-	}
-	c1 += size;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
-		    || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
-		   ) {
-			printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
-			printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-			                c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-		}
-		c1 += 8;
-	}
-	printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
-	v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
-	kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-
-==============================================================*/
-
-
-
-/*===============================================
- * 	Data Structures 
- *===============================================*/
-
-
-/*========================================================
- * Name: 	x25_channel
- *
- * Purpose:	To hold private informaton for each  
- *              logical channel.
- *		
- * Rationale:  	Per-channel debugging is possible if each 
- *              channel has its own private area.
- *	
- * Assumptions:
- *
- * Description:	This is an extention of the struct net_device
- *              we create for each network interface to keep 
- *              the rest of X.25 channel-specific data. 
- *
- * Construct:	Typedef
- */
-typedef struct x25_channel
-{
-	wanpipe_common_t common;	/* common area for x25api and socket */
-	char name[WAN_IFNAME_SZ+1];	/* interface name, ASCIIZ */
-	char addr[WAN_ADDRESS_SZ+1];	/* media address, ASCIIZ */
-	unsigned tx_pkt_size;
-	unsigned short protocol;	/* ethertype, 0 - multiplexed */
-	char drop_sequence;		/* mark sequence for dropping */
-	unsigned long state_tick;	/* time of the last state change */
-	unsigned idle_timeout;		/* sec, before disconnecting */
-	unsigned long i_timeout_sofar;  /* # of sec's we've been idle */
-	unsigned hold_timeout;		/* sec, before re-connecting */
-	unsigned long tick_counter;	/* counter for transmit time out */
-	char devtint;			/* Weather we should dev_tint() */
-	struct sk_buff* rx_skb;		/* receive socket buffer */
-	struct sk_buff* tx_skb;		/* transmit socket buffer */
-
-	bh_data_t *bh_head;	  	  /* Circular buffer for x25api_bh */
-	unsigned long  tq_working;
-	volatile int  bh_write;
-	volatile int  bh_read;
-	atomic_t  bh_buff_used;
-
-	sdla_t* card;			/* -> owner */
-	struct net_device *dev;		/* -> bound devce */
-
-	int ch_idx;
-	unsigned char enable_IPX;
-	unsigned long network_number;
-	struct net_device_stats ifstats;	/* interface statistics */
-	unsigned short transmit_length;
-	unsigned short tx_offset;
-	char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)];
-
-	if_send_stat_t   if_send_stat;
-        rx_intr_stat_t   rx_intr_stat;
-        pipe_mgmt_stat_t pipe_mgmt_stat;    
-
-	unsigned long router_start_time; /* Router start time in seconds */
-	unsigned long router_up_time;
-	
-} x25_channel_t;
-
-/* FIXME Take this out */
-
-#ifdef NEX_OLD_CALL_INFO
-typedef struct x25_call_info
-{
-	char dest[17];			PACKED;/* ASCIIZ destination address */
-	char src[17];			PACKED;/* ASCIIZ source address */
-	char nuser;			PACKED;/* number of user data bytes */
-	unsigned char user[127];	PACKED;/* user data */
-	char nfacil;			PACKED;/* number of facilities */
-	struct
-	{
-		unsigned char code;     PACKED;
-		unsigned char parm;     PACKED;
-	} facil[64];			        /* facilities */
-} x25_call_info_t;
-#else
-typedef struct x25_call_info
-{
-	char dest[MAX_X25_ADDR_SIZE]		PACKED;/* ASCIIZ destination address */
-	char src[MAX_X25_ADDR_SIZE]		PACKED;/* ASCIIZ source address */
-	unsigned char nuser			PACKED;
-	unsigned char user[MAX_X25_DATA_SIZE]	PACKED;/* user data */
-	unsigned char nfacil			PACKED;
-	unsigned char facil[MAX_X25_FACL_SIZE]	PACKED;
-	unsigned short lcn             		PACKED;
-} x25_call_info_t;
-#endif
-
-
-  
-/*===============================================
- *	Private Function Prototypes
- *==============================================*/
-
-
-/*================================================= 
- * WAN link driver entry points. These are 
- * called by the WAN router module.
- */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-static void disable_comm (sdla_t* card);
-static void disable_comm_shutdown(sdla_t *card);
-
-
-
-/*================================================= 
- *	WANPIPE-specific entry points 
- */
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);
-static void x25api_bh(struct net_device *dev);
-static int x25api_bh_cleanup(struct net_device *dev);
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);
-
-
-/*=================================================  
- * 	Network device interface 
- */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_header(struct sk_buff* skb, struct net_device* dev,
-	unsigned short type, void* daddr, void* saddr, unsigned len);
-static int if_rebuild_hdr (struct sk_buff* skb);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats *if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/*=================================================  
- * 	Interrupt handlers 
- */
-static void wpx_isr	(sdla_t *);
-static void rx_intr	(sdla_t *);
-static void tx_intr	(sdla_t *);
-static void status_intr	(sdla_t *);
-static void event_intr	(sdla_t *);
-static void spur_intr	(sdla_t *);
-static void timer_intr  (sdla_t *);
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev);
-static struct net_device *move_dev_to_next(sdla_t *card,
-					   struct net_device *dev);
-
-/*=================================================  
- *	Background polling routines 
- */
-static void wpx_poll (sdla_t* card);
-static void poll_disconnected (sdla_t* card);
-static void poll_connecting (sdla_t* card);
-static void poll_active (sdla_t* card);
-static void trigger_x25_poll(sdla_t *card);
-static void x25_timer_routine(unsigned long data);
-
-
-
-/*=================================================  
- *	X.25 firmware interface functions 
- */
-static int x25_get_version (sdla_t* card, char* str);
-static int x25_configure (sdla_t* card, TX25Config* conf);
-static int hdlc_configure (sdla_t* card, TX25Config* conf);
-static int set_hdlc_level (sdla_t* card);
-static int x25_get_err_stats (sdla_t* card);
-static int x25_get_stats (sdla_t* card);
-static int x25_set_intr_mode (sdla_t* card, int mode);
-static int x25_close_hdlc (sdla_t* card);
-static int x25_open_hdlc (sdla_t* card);
-static int x25_setup_hdlc (sdla_t* card);
-static int x25_set_dtr (sdla_t* card, int dtr);
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan);
-static int x25_place_call (sdla_t* card, x25_channel_t* chan);
-static int x25_accept_call (sdla_t* card, int lcn, int qdm);
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn);
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf);
-static int x25_fetch_events (sdla_t* card);
-static int x25_error (sdla_t* card, int err, int cmd, int lcn);
-
-/*=================================================  
- *	X.25 asynchronous event handlers 
- */
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-
-
-/*=================================================  
- *	Miscellaneous functions 
- */
-static int connect (sdla_t* card);
-static int disconnect (sdla_t* card);
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
-					 unsigned lcn);
-static int chan_connect(struct net_device* dev);
-static int chan_disc(struct net_device* dev);
-static void set_chan_state(struct net_device* dev, int state);
-static int chan_send(struct net_device *dev, void* buff, unsigned data_len,
-		     unsigned char tx_intr);
-static unsigned char bps_to_speed_code (unsigned long bps);
-static unsigned int dec_to_uint (unsigned char* str, int len);
-static unsigned int hex_to_uint (unsigned char*, int);
-static void parse_call_info (unsigned char*, x25_call_info_t*);
-static struct net_device *find_channel(sdla_t *card, unsigned lcn);
-static void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn);
-static void setup_for_delayed_transmit(struct net_device *dev,
-				       void *buf, unsigned len);
-
-
-/*=================================================  
- *      X25 API Functions 
- */
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
-				    struct sk_buff **);
-static void timer_intr_exec(sdla_t *, unsigned char);
-static int execute_delayed_cmd(sdla_t *card, struct net_device *dev,
-			       mbox_cmd_t *usr_cmd, char bad_cmd);
-static int api_incoming_call (sdla_t*, TX25Mbox *, int);
-static int alloc_and_init_skb_buf (sdla_t *,struct sk_buff **, int);
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
-				    TX25Mbox* mbox);
-static int clear_confirm_event (sdla_t *, TX25Mbox*);
-static void send_oob_msg (sdla_t *card, struct net_device *dev, TX25Mbox *mbox);
-static int timer_intr_cmd_exec(sdla_t *card);
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox);
-static int check_bad_command(sdla_t *card, struct net_device *dev);
-static int channel_disconnect(sdla_t* card, struct net_device *dev);
-static void hdlc_link_down (sdla_t*);
-
-/*=================================================
- *     XPIPEMON Functions
- */
-static int process_udp_mgmt_pkt(sdla_t *);
-static int udp_pkt_type( struct sk_buff *, sdla_t*);
-static int reply_udp( unsigned char *, unsigned int); 
-static void init_x25_channel_struct( x25_channel_t *);
-static void init_global_statistics( sdla_t *);
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t *card,
-			      struct net_device *dev,
-			      struct sk_buff *skb, int lcn);
-static unsigned short calc_checksum (char *, int);
-
-
-
-/*================================================= 
- *	IPX functions 
- */
-static void switch_net_numbers(unsigned char *, unsigned long, unsigned char);
-static int handle_IPXWAN(unsigned char *, char *, unsigned char , 
-			 unsigned long , unsigned short );
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-static void S508_S514_lock(sdla_t *, unsigned long *);
-static void S508_S514_unlock(sdla_t *, unsigned long *);
-
-
-/*=================================================  
- * 	Global Variables 
- *=================================================*/
-
-
-
-/*================================================= 
- *	Public Functions 
- *=================================================*/
-
-
-
-
-/*===================================================================
- * wpx_init:	X.25 Protocol Initialization routine.
- *
- * Purpose:	To initialize the protocol/firmware.
- * 
- * Rationale:	This function is called by setup() function, in
- *              sdlamain.c, to dynamically setup the x25 protocol.
- *		This is the first protocol specific function, which
- *              executes once on startup.
- *                
- * Description:	This procedure initializes the x25 firmware and
- *    		sets up the mailbox, transmit and receive buffer
- *              pointers. It also initializes all debugging structures
- *              and sets up the X25 environment.
- *
- *		Sets up hardware options defined by user in [wanpipe#] 
- *		section of wanpipe#.conf configuration file. 
- *
- * 		At this point adapter is completely initialized 
- *      	and X.25 firmware is running.
- *  		o read firmware version (to make sure it's alive)
- *  		o configure adapter
- *  		o initialize protocol-specific fields of the 
- *                adapter data space.
- *
- * Called by:	setup() function in sdlamain.c
- *
- * Assumptions:	None
- *
- * Warnings:	None
- *
- * Return: 	0	o.k.
- *	 	< 0	failure.
- */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf)
-{
-	union{
-		char str[80];
-		TX25Config cfg;
-	} u;
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_X25){
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-			card->devname, conf->config_id)
-		;
-		return -EINVAL;
-	}
-
-	/* Initialize protocol-specific fields */
-	card->mbox  = (void*)(card->hw.dpmbase + X25_MBOX_OFFS);
-	card->rxmb  = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS);
-	card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS);
-
-	/* Initialize for S514 Card */
-	if(card->hw.type == SDLA_S514) {
-		card->mbox += X25_MB_VECTOR;
-		card->flags += X25_MB_VECTOR;
-		card->rxmb += X25_MB_VECTOR;
-	}
-
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-	if (x25_get_version(card, NULL) || x25_get_version(card, u.str))
-		return -EIO;
-
-
-	/* X25 firmware can run ether in X25 or LAPB HDLC mode.
-         * Check the user defined option and configure accordingly */
-	if (conf->u.x25.LAPB_hdlc_only == WANOPT_YES){
-		if (set_hdlc_level(card) != CMD_OK){
-			return -EIO;	
-		}else{
-			printk(KERN_INFO "%s: running LAP_B HDLC firmware v%s\n",
-				card->devname, u.str);
-		}
-		card->u.x.LAPB_hdlc = 1;
-	}else{
-		printk(KERN_INFO "%s: running X.25 firmware v%s\n",
-				card->devname, u.str);
-		card->u.x.LAPB_hdlc = 0;
-	}
-
-	/* Configure adapter. Here we set resonable defaults, then parse
-	 * device configuration structure and set configuration options.
-	 * Most configuration options are verified and corrected (if
-	 * necessary) since we can't rely on the adapter to do so.
-	 */
-	memset(&u.cfg, 0, sizeof(u.cfg));
-	u.cfg.t1		= 3;
-	u.cfg.n2		= 10;
-	u.cfg.autoHdlc		= 1;		/* automatic HDLC connection */
-	u.cfg.hdlcWindow	= 7;
-	u.cfg.pktWindow		= 2;
-	u.cfg.station		= 1;		/* DTE */
-	u.cfg.options		= 0x0090;	/* disable D-bit pragmatics */
-	u.cfg.ccittCompat	= 1988;
-	u.cfg.t10t20		= 30;
-	u.cfg.t11t21		= 30;
-	u.cfg.t12t22		= 30;
-	u.cfg.t13t23		= 30;
-	u.cfg.t16t26		= 30;
-	u.cfg.t28		= 30;
-	u.cfg.r10r20		= 5;
-	u.cfg.r12r22		= 5;
-	u.cfg.r13r23		= 5;
-	u.cfg.responseOpt	= 1;		/* RR's after every packet */
-
-	if (card->u.x.LAPB_hdlc){
-		u.cfg.hdlcMTU = 1027;
-	}
-
-	if (conf->u.x25.x25_conf_opt){
-		u.cfg.options = conf->u.x25.x25_conf_opt;
-	}
-
-	if (conf->clocking != WANOPT_EXTERNAL)
-		u.cfg.baudRate = bps_to_speed_code(conf->bps);
-
-	if (conf->station != WANOPT_DTE){
-		u.cfg.station = 0;		/* DCE mode */
-	}
-
-        if (conf->interface != WANOPT_RS232 ){
-	        u.cfg.hdlcOptions |= 0x80;      /* V35 mode */
-	} 
-
-	/* adjust MTU */
-	if (!conf->mtu || (conf->mtu >= 1024))
-		card->wandev.mtu = 1024;
-	else if (conf->mtu >= 512)
-		card->wandev.mtu = 512;
-	else if (conf->mtu >= 256)
-		card->wandev.mtu = 256;
-	else if (conf->mtu >= 128)
-		card->wandev.mtu = 128;
-	else 
-		card->wandev.mtu = 64;
-
-	u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu;
-
-	if (conf->u.x25.hi_pvc){
-		card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM);
-		card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
-	}
-
-	if (conf->u.x25.hi_svc){
-		card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM);
-		card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
-	}
-
-	/* Figure out the total number of channels to configure */
-	card->u.x.num_of_ch = 0;
-	if (card->u.x.hi_svc != 0){
-		card->u.x.num_of_ch = (card->u.x.hi_svc - card->u.x.lo_svc) + 1;
-	}
-	if (card->u.x.hi_pvc != 0){
-		card->u.x.num_of_ch += (card->u.x.hi_pvc - card->u.x.lo_pvc) + 1;
-	}
-
-	if (card->u.x.num_of_ch == 0){
-		printk(KERN_INFO "%s: ERROR, Minimum number of PVC/SVC channels is 1 !\n"
-				 "%s: Please set the Lowest/Highest PVC/SVC values !\n",
-				 card->devname,card->devname);
-		return -ECHRNG;
-	}
-	
-	u.cfg.loPVC = card->u.x.lo_pvc;
-	u.cfg.hiPVC = card->u.x.hi_pvc;
-	u.cfg.loTwoWaySVC = card->u.x.lo_svc;
-	u.cfg.hiTwoWaySVC = card->u.x.hi_svc;
-
-	if (conf->u.x25.hdlc_window)
-		u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
-	if (conf->u.x25.pkt_window)
-		u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7);
-
-	if (conf->u.x25.t1)
-		u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
-	if (conf->u.x25.t2)
-		u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29);
-	if (conf->u.x25.t4)
-		u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240);
-	if (conf->u.x25.n2)
-		u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
-
-	if (conf->u.x25.t10_t20)
-		u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255);
-	if (conf->u.x25.t11_t21)
-		u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255);
-	if (conf->u.x25.t12_t22)
-		u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255);
-	if (conf->u.x25.t13_t23)	
-		u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255);
-	if (conf->u.x25.t16_t26)
-		u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255);
-	if (conf->u.x25.t28)
-		u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255);
-
-	if (conf->u.x25.r10_r20)
-		u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250);
-	if (conf->u.x25.r12_r22)
-		u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250);
-	if (conf->u.x25.r13_r23)
-		u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250);
-
-
-	if (conf->u.x25.ccitt_compat)
-		u.cfg.ccittCompat = conf->u.x25.ccitt_compat;
-
-	/* initialize adapter */
-	if (card->u.x.LAPB_hdlc){
-		if (hdlc_configure(card, &u.cfg) != CMD_OK)
-			return -EIO;
-	}else{
-		if (x25_configure(card, &u.cfg) != CMD_OK)
-			return -EIO;
-	}
-
-	if ((x25_close_hdlc(card) != CMD_OK) ||		/* close HDLC link */
-	    (x25_set_dtr(card, 0) != CMD_OK))		/* drop DTR */
-		return -EIO;
-
-	/* Initialize protocol-specific fields of adapter data space */
-	card->wandev.bps	= conf->bps;
-	card->wandev.interface	= conf->interface;
-	card->wandev.clocking	= conf->clocking;
-	card->wandev.station	= conf->station;
-	card->isr		= &wpx_isr;
-	card->poll		= NULL; //&wpx_poll;
-	card->disable_comm	= &disable_comm;
-	card->exec		= &wpx_exec;
-	card->wandev.update	= &update;
-	card->wandev.new_if	= &new_if;
-	card->wandev.del_if	= &del_if;
-
-	/* WARNING: This function cannot exit with an error
-	 *          after the change of state */
-	card->wandev.state	= WAN_DISCONNECTED;
-	
-	card->wandev.enable_tx_int = 0;
-	card->irq_dis_if_send_count = 0;
-        card->irq_dis_poll_count = 0;
-	card->u.x.tx_dev = NULL;
-	card->u.x.no_dev = 0;
-
-
-	/* Configure for S514 PCI Card */
-	if (card->hw.type == SDLA_S514) {
-		card->u.x.hdlc_buf_status = 
-			(volatile unsigned char *)
-				(card->hw.dpmbase + X25_MB_VECTOR+ X25_MISC_HDLC_BITS);
-	}else{
-		card->u.x.hdlc_buf_status = 
-			(volatile unsigned char *)(card->hw.dpmbase + X25_MISC_HDLC_BITS); 
-	}
-
-	card->u.x.poll_device=NULL;
-	card->wandev.udp_port = conf->udp_port;
-
-	/* Enable or disable call setup logging */
-	if (conf->u.x25.logging == WANOPT_YES){
-		printk(KERN_INFO "%s: Enabling Call Logging.\n",
-			card->devname);
-		card->u.x.logging = 1;
-	}else{	
-		card->u.x.logging = 0;
-	}
-
-	/* Enable or disable modem status reporting */
-	if (conf->u.x25.oob_on_modem == WANOPT_YES){
-		printk(KERN_INFO "%s: Enabling OOB on Modem change.\n",
-			card->devname);
-		card->u.x.oob_on_modem = 1;
-	}else{
-		card->u.x.oob_on_modem = 0;
-	}
-	
-	init_global_statistics(card);	
-
-	INIT_WORK(&card->u.x.x25_poll_work, (void *)wpx_poll, card);
-
-	init_timer(&card->u.x.x25_timer);
-	card->u.x.x25_timer.data = (unsigned long)card;
-	card->u.x.x25_timer.function = x25_timer_routine;
-	
-	return 0;
-}
-
-/*=========================================================
- *	WAN Device Driver Entry Points 
- *========================================================*/
-
-/*============================================================
- * Name:	update(),  Update device status & statistics.
- *
- * Purpose:	To provide debugging and statitical
- *              information to the /proc file system.
- *              /proc/net/wanrouter/wanpipe#
- *              	
- * Rationale:	The /proc file system is used to collect
- *              information about the kernel and drivers.
- *              Using the /proc file system the user
- *              can see exactly what the sangoma drivers are
- *              doing. And in what state they are in. 
- *                
- * Description: Collect all driver statistical information
- *              and pass it to the top laywer. 
- *		
- *		Since we have to execute a debugging command, 
- *              to obtain firmware statitics, we trigger a 
- *              UPDATE function within the timer interrtup.
- *              We wait until the timer update is complete.
- *              Once complete return the appropriate return
- *              code to indicate that the update was successful.
- *              
- * Called by:	device_stat() in wanmain.c
- *
- * Assumptions:	
- *
- * Warnings:	This function will degrade the performance
- *              of the router, since it uses the mailbox. 
- *
- * Return: 	0 	OK
- * 		<0	Failed (or busy).
- */
-
-static int update(struct wan_device* wandev)
-{
-	volatile sdla_t* card;
-	TX25Status* status;
-	unsigned long timeout;
-
-	/* sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-
-	if (wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-
-	if (test_bit(SEND_CRIT, (void*)&wandev->critical))
-		return -EAGAIN;
-
-	if (!wandev->dev)
-		return -ENODEV;
-	
-	card = wandev->private;
-	status = card->flags;
-
-	card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
-	status->imask |= INTR_ON_TIMER;
-	timeout = jiffies;	
-
-	for (;;){
-		if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){	
-			break;
-		}
-		if (time_after(jiffies, timeout + 1*HZ)){
-			card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
-			return -EAGAIN;
-		}
-	}
-	return 0;
-}
-
-
-/*===================================================================
- * Name:	new_if
- *
- * Purpose:	To allocate and initialize resources for a 
- *              new logical channel.  
- * 
- * Rationale:	A new channel can be added dynamically via
- *              ioctl call.
- *                
- * Description:	Allocate a private channel structure, x25_channel_t.
- *		Parse the user interface options from wanpipe#.conf 
- *		configuration file. 
- *		Bind the private are into the network device private
- *              area pointer (dev->priv).
- *		Prepare the network device structure for registration.
- *
- * Called by:	ROUTER_IFNEW Ioctl call, from wanrouter_ioctl() 
- *              (wanmain.c)
- *
- * Assumptions: None
- *
- * Warnings:	None
- *
- * Return: 	0 	Ok
- *		<0 	Failed (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf)
-{
-	sdla_t* card = wandev->private;
-	x25_channel_t* chan;
-	int err = 0;
-
-	if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)){
-		printk(KERN_INFO "%s: invalid interface name!\n",
-			card->devname);
-		return -EINVAL;
-	}
-
-	if(card->wandev.new_if_cnt++ > 0 && card->u.x.LAPB_hdlc) {
-		printk(KERN_INFO "%s: Error: Running LAPB HDLC Mode !\n",
-						card->devname);
-		printk(KERN_INFO 
-			"%s: Maximum number of network interfaces must be one !\n",
-						card->devname);
-		return -EEXIST;
-	}
-
-	/* allocate and initialize private data */
-	chan = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC);
-	if (chan == NULL){
-		return -ENOMEM;
-	}
-	
-	memset(chan, 0, sizeof(x25_channel_t));
-
-	/* Bug Fix: Seg Err on PVC startup
-	 * It must be here since bind_lcn_to_dev expects 
-	 * it bellow */
-	dev->priv = chan;
-	
-	strcpy(chan->name, conf->name);
-	chan->card = card;
-	chan->dev = dev;
-	chan->common.sk = NULL;
-	chan->common.func = NULL;
-	chan->common.rw_bind = 0;
-	chan->tx_skb = chan->rx_skb = NULL;
-
-	/* verify media address */
-	if (conf->addr[0] == '@'){		/* SVC */
-		chan->common.svc = 1;
-		strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
-
-		/* Set channel timeouts (default if not specified) */
-		chan->idle_timeout = (conf->idle_timeout) ? 
-					conf->idle_timeout : 90;
-		chan->hold_timeout = (conf->hold_timeout) ? 
-					conf->hold_timeout : 10;
-
-	}else if (isdigit(conf->addr[0])){	/* PVC */
-		int lcn = dec_to_uint(conf->addr, 0);
-
-		if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){
-			bind_lcn_to_dev (card, dev, lcn);
-		}else{
-			printk(KERN_ERR
-				"%s: PVC %u is out of range on interface %s!\n",
-				wandev->name, lcn, chan->name);
-			err = -EINVAL;
-		}
-	}else{
-		printk(KERN_ERR
-			"%s: invalid media address on interface %s!\n",
-			wandev->name, chan->name);
-		err = -EINVAL;
-	}
-
-	if(strcmp(conf->usedby, "WANPIPE") == 0){
-                printk(KERN_INFO "%s: Running in WANPIPE mode %s\n",
-			wandev->name, chan->name);
-                chan->common.usedby = WANPIPE;
-		chan->protocol = htons(ETH_P_IP);
-
-        }else if(strcmp(conf->usedby, "API") == 0){
-		chan->common.usedby = API;
-                printk(KERN_INFO "%s: Running in API mode %s\n",
-			wandev->name, chan->name);
-		chan->protocol = htons(X25_PROT);
-	}
-
-
-	if (err){
-		kfree(chan);
-		dev->priv = NULL;
-		return err;
-	}
-	
-	chan->enable_IPX = conf->enable_IPX;
-	
-	if (chan->enable_IPX)
-		chan->protocol = htons(ETH_P_IPX);
-	
-	if (conf->network_number)
-		chan->network_number = conf->network_number;
-	else
-		chan->network_number = 0xDEADBEEF;
-
-	/* prepare network device data space for registration */
-	strcpy(dev->name,chan->name);
-
-	dev->init = &if_init;
-
-	init_x25_channel_struct(chan);
-
-	return 0;
-}
-
-/*===================================================================
- * Name:	del_if(),  Remove a logical channel.	 
- *
- * Purpose:	To dynamically remove a logical channel.
- * 
- * Rationale:	Each logical channel should be dynamically
- *              removable. This functin is called by an 
- *              IOCTL_IFDEL ioctl call or shutdown(). 
- *                
- * Description: Do nothing.
- *
- * Called by:	IOCTL_IFDEL : wanrouter_ioctl() from wanmain.c
- *              shutdown() from sdlamain.c
- *
- * Assumptions: 
- *
- * Warnings:
- *
- * Return: 	0 Ok. Void function.
- */
-
-//FIXME Del IF Should be taken out now.
-
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
-	return 0;
-}
-
-
-/*============================================================
- * Name:	wpx_exec
- *
- * Description:	Execute adapter interface command.
- * 		This option is currently dissabled.
- *===========================================================*/
-
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
-        return 0;
-}
-
-/*============================================================
- * Name:	disable_comm	
- *
- * Description:	Disable communications during shutdown.
- *              Dont check return code because there is 
- *              nothing we can do about it.  
- *
- * Warning:	Dev and private areas are gone at this point.
- *===========================================================*/
-
-static void disable_comm(sdla_t* card)
-{
-	disable_comm_shutdown(card);
-	del_timer(&card->u.x.x25_timer);
-	return;
-}
-
-
-/*============================================================
- *	Network Device Interface 
- *===========================================================*/
-
-/*===================================================================
- * Name:	if_init(),   Netowrk Interface Initialization 	 
- *
- * Purpose:	To initialize a network interface device structure.
- * 
- * Rationale:	During network interface startup, the if_init
- *              is called by the kernel to initialize the
- *              netowrk device structure.  Thus a driver
- *              can customze a network device. 
- *                
- * Description:	Initialize the netowrk device call back
- *              routines.  This is where we tell the kernel
- *              which function to use when it wants to send
- *              via our interface. 
- *		Furthermore, we initialize the device flags, 
- *              MTU and physical address of the board.
- *
- * Called by:	Kernel (/usr/src/linux/net/core/dev.c)
- * 		(dev->init())
- *
- * Assumptions: None
- *	
- * Warnings:	None
- *
- * Return: 	0 	Ok : Void function.
- */
-static int if_init(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	struct wan_device* wandev = &card->wandev;
-
-	/* Initialize device driver entry points */
-	dev->open		= &if_open;
-	dev->stop		= &if_close;
-	dev->hard_header	= &if_header;
-	dev->rebuild_header	= &if_rebuild_hdr;
-	dev->hard_start_xmit	= &if_send;
-	dev->get_stats		= &if_stats;
-	dev->tx_timeout		= &if_tx_timeout;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-
-	/* Initialize media-specific parameters */
-	dev->type		= ARPHRD_PPP;		/* ARP h/w type */
-	dev->flags		|= IFF_POINTOPOINT;
-	dev->flags		|= IFF_NOARP;
-
-	if (chan->common.usedby == API){
-		dev->mtu	= X25_CHAN_MTU+sizeof(x25api_hdr_t);
-	}else{
-		dev->mtu	= card->wandev.mtu; 	
-	}
-	
-	dev->hard_header_len	= X25_HRDHDR_SZ; /* media header length */
-	dev->addr_len		= 2;		/* hardware address length */
-	
-	if (!chan->common.svc){
-		*(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
-	}
-	
-	/* Initialize hardware parameters (just for reference) */
-	dev->irq	= wandev->irq;
-	dev->dma	= wandev->dma;
-	dev->base_addr	= wandev->ioport;
-	dev->mem_start	= (unsigned long)wandev->maddr;
-	dev->mem_end	= wandev->maddr + wandev->msize - 1;
-
-        /* Set transmit buffer queue length */
-        dev->tx_queue_len = 100;
-	SET_MODULE_OWNER(dev);
-
-	/* FIXME Why are we doing this */
-	set_chan_state(dev, WAN_DISCONNECTED);
-	return 0;
-}
-
-
-/*===================================================================
- * Name:	if_open(),   Open/Bring up the Netowrk Interface 
- *
- * Purpose:	To bring up a network interface.
- * 
- * Rationale:	
- *                
- * Description:	Open network interface.
- * 		o prevent module from unloading by incrementing use count
- * 		o if link is disconnected then initiate connection
- *
- * Called by:	Kernel (/usr/src/linux/net/core/dev.c)
- * 		(dev->open())
- *
- * Assumptions: None
- *	
- * Warnings:	None
- *
- * Return: 	0 	Ok
- * 		<0 	Failure: Interface will not come up.
- */
-
-static int if_open(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	struct timeval tv;
-	unsigned long smp_flags;
-	
-	if (netif_running(dev))
-		return -EBUSY;
-
-	chan->tq_working = 0;
-
-	/* Initialize the workqueue */
-	INIT_WORK(&chan->common.wanpipe_work, (void *)x25api_bh, dev);
-
-	/* Allocate and initialize BH circular buffer */
-	/* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */
-	chan->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC);
-
-	if (chan->bh_head == NULL){
-		printk(KERN_INFO "%s: ERROR, failed to allocate memory ! BH_BUFFERS !\n",
-				card->devname);
-
-		return -ENOBUFS;
-	}
-	memset(chan->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1)));
-	atomic_set(&chan->bh_buff_used, 0);
-
-	/* Increment the number of interfaces */
-	++card->u.x.no_dev;
-	
-	wanpipe_open(card);
-
-	/* LAPB protocol only uses one interface, thus
-	 * start the protocol after it comes up. */
-	if (card->u.x.LAPB_hdlc){
-		if (card->open_cnt == 1){
-			TX25Status* status = card->flags;
-			S508_S514_lock(card, &smp_flags);
-			x25_set_intr_mode(card, INTR_ON_TIMER); 
-			status->imask &= ~INTR_ON_TIMER;
-			S508_S514_unlock(card, &smp_flags);
-		}
-	}else{
-		/* X25 can have multiple interfaces thus, start the 
-		 * protocol once all interfaces are up */
-
-		//FIXME: There is a bug here. If interface is
-		//brought down and up, it will try to enable comm.
-		if (card->open_cnt == card->u.x.num_of_ch){
-
-			S508_S514_lock(card, &smp_flags);
-			connect(card);
-			S508_S514_unlock(card, &smp_flags);
-
-			mod_timer(&card->u.x.x25_timer, jiffies + HZ);
-		}
-	}
-	/* Device is not up until the we are in connected state */
-	do_gettimeofday( &tv );
-	chan->router_start_time = tv.tv_sec;
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-/*===================================================================
- * Name:	if_close(),   Close/Bring down the Netowrk Interface 
- *
- * Purpose:	To bring down a network interface.
- * 
- * Rationale:	
- *                
- * Description:	Close network interface.
- * 		o decrement use module use count
- *
- * Called by:	Kernel (/usr/src/linux/net/core/dev.c)
- * 		(dev->close())
- *		ifconfig <name> down: will trigger the kernel
- *              which will call this function.
- *
- * Assumptions: None
- *	
- * Warnings:	None
- *
- * Return: 	0 	Ok
- * 		<0 	Failure: Interface will not exit properly.
- */
-static int if_close(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	unsigned long smp_flags;
-	
-	netif_stop_queue(dev);
-
-	if ((chan->common.state == WAN_CONNECTED) || 
-	    (chan->common.state == WAN_CONNECTING)){
-		S508_S514_lock(card, &smp_flags);
-		chan_disc(dev);
-		S508_S514_unlock(card, &smp_flags);
-	}
-
-	wanpipe_close(card);
-
-	S508_S514_lock(card, &smp_flags);
-	if (chan->bh_head){
-		int i;
-		struct sk_buff *skb;
-	
-		for (i=0; i<(MAX_BH_BUFF+1); i++){
-			skb = ((bh_data_t *)&chan->bh_head[i])->skb;
-			if (skb != NULL){
-                		dev_kfree_skb_any(skb);
-			}
-		}
-		kfree(chan->bh_head);
-		chan->bh_head=NULL;
-	}
-	S508_S514_unlock(card, &smp_flags);
-
-	/* If this is the last close, disconnect physical link */
-	if (!card->open_cnt){
-		S508_S514_lock(card, &smp_flags);
-		disconnect(card);
-		x25_set_intr_mode(card, 0);
-		S508_S514_unlock(card, &smp_flags);
-	}
-	
-	/* Decrement the number of interfaces */
-	--card->u.x.no_dev;
-	return 0;
-}
-
-/*======================================================================
- * 	Build media header.
- * 	o encapsulate packet according to encapsulation type.
- *
- * 	The trick here is to put packet type (Ethertype) into 'protocol' 
- *      field of the socket buffer, so that we don't forget it.  
- *      If encapsulation fails, set skb->protocol to 0 and discard 
- *      packet later.
- *
- * 	Return:		media header length.
- *======================================================================*/
-
-static int if_header(struct sk_buff* skb, struct net_device* dev,
-		     unsigned short type, void* daddr, void* saddr,
-		     unsigned len)
-{
-	x25_channel_t* chan = dev->priv;
-	int hdr_len = dev->hard_header_len;
-	
-	skb->protocol = htons(type);
-	if (!chan->protocol){
-		hdr_len = wanrouter_encapsulate(skb, dev, type);
-		if (hdr_len < 0){
-			hdr_len = 0;
-			skb->protocol = htons(0);
-		}
-	}
-	return hdr_len;
-}
-
-/*===============================================================
- * 	Re-build media header.
- *
- * 	Return:		1	physical address resolved.
- *			0	physical address not resolved
- *==============================================================*/
-
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
-	struct net_device *dev = skb->dev; 
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-
-	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
-		card->devname, dev->name);
-	return 1;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
-    	x25_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-
-	/* If our device stays busy for at least 5 seconds then we will
-	 * kick start the device by making dev->tbusy = 0.  We expect
-	 * that our device never stays busy more than 5 seconds. So this                 
-	 * is only used as a last resort.
-	 */
-
-	++chan->if_send_stat.if_send_tbusy_timeout;
-	printk (KERN_INFO "%s: Transmit timed out on %s\n", 
-			card->devname, dev->name);
-	netif_wake_queue (dev);
-}
-
-
-/*=========================================================================
- * 	Send a packet on a network interface.
- * 	o set tbusy flag (marks start of the transmission).
- * 	o check link state. If link is not up, then drop the packet.
- * 	o check channel status. If it's down then initiate a call.
- * 	o pass a packet to corresponding WAN device.
- * 	o free socket buffer
- *
- * 	Return:	0	complete (socket buffer must be freed)
- *		non-0	packet may be re-transmitted (tbusy must be set)
- *
- * 	Notes:
- * 	1. This routine is called either by the protocol stack or by the "net
- *    	bottom half" (with interrupts enabled).
- * 	2. Setting tbusy flag will inhibit further transmit requests from the
- *    	protocol stack and can be used for flow control with protocol layer.
- *
- *========================================================================*/
-
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	TX25Status* status = card->flags;
-	int udp_type;
-	unsigned long smp_flags=0;
-
-	++chan->if_send_stat.if_send_entry;
-
-	netif_stop_queue(dev);
-
-	/* No need to check frame length, since socket code
-         * will perform the check for us */
-
-	chan->tick_counter = jiffies;
-	
-	/* Critical region starts here */
-	S508_S514_lock(card, &smp_flags);
-	
-	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-		printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical);
-		goto if_send_crit_exit;
-	}
-	
-	udp_type = udp_pkt_type(skb, card);
-
-        if(udp_type != UDP_INVALID_TYPE) {
-
-                if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, dev, skb,
-                        chan->common.lcn)) {
-
-                        status->imask |= INTR_ON_TIMER;
-                        if (udp_type == UDP_XPIPE_TYPE){
-                                chan->if_send_stat.if_send_PIPE_request++;
-			}
-               	}
-		netif_start_queue(dev);
-		clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-		S508_S514_unlock(card, &smp_flags);
-		return 0;
-	}
-
-	if (chan->transmit_length){
-		//FIXME: This check doesn't make sense any more
-		if (chan->common.state != WAN_CONNECTED){
-			chan->transmit_length=0;
-			atomic_set(&chan->common.driver_busy,0);
-		}else{
-			netif_stop_queue(dev);
-			++card->u.x.tx_interrupts_pending;
-		        status->imask |= INTR_ON_TX_FRAME;
-			clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-			S508_S514_unlock(card, &smp_flags);
-			return 1;
-		}
-	}
-
-	if (card->wandev.state != WAN_CONNECTED){
-		++chan->ifstats.tx_dropped;
-		++card->wandev.stats.tx_dropped;
-		++chan->if_send_stat.if_send_wan_disconnected;	
-		
-	}else if ( chan->protocol && (chan->protocol != skb->protocol)){
-		printk(KERN_INFO
-			"%s: unsupported Ethertype 0x%04X on interface %s!\n",
-			chan->name, htons(skb->protocol), dev->name);
-		
-		printk(KERN_INFO "PROTO %Xn", htons(chan->protocol));
-		++chan->ifstats.tx_errors;
-		++chan->ifstats.tx_dropped;
-		++card->wandev.stats.tx_dropped;
-		++chan->if_send_stat.if_send_protocol_error;
-		
-	}else switch (chan->common.state){
-
-		case WAN_DISCONNECTED:
-			/* Try to establish connection. If succeded, then start
-			 * transmission, else drop a packet.
-			 */
-			if (chan->common.usedby == API){
-				++chan->ifstats.tx_dropped;
-				++card->wandev.stats.tx_dropped;
-				break;
-			}else{
-				if (chan_connect(dev) != 0){
-					++chan->ifstats.tx_dropped;
-					++card->wandev.stats.tx_dropped;
-					break;
-				}
-			}
-			/* fall through */
-
-		case WAN_CONNECTED:
-			if( skb->protocol == htons(ETH_P_IPX)) {
-				if(chan->enable_IPX) {
-					switch_net_numbers( skb->data, 
-						chan->network_number, 0);
-				} else {
-					++card->wandev.stats.tx_dropped;
-					++chan->ifstats.tx_dropped;
-					++chan->if_send_stat.if_send_protocol_error;
-					goto if_send_crit_exit;
-				}
-			}
-			/* We never drop here, if cannot send than, copy
-	                 * a packet into a transmit buffer 
-                         */
-			chan_send(dev, skb->data, skb->len, 0);
-			break;
-
-		default:
-			++chan->ifstats.tx_dropped;	
-			++card->wandev.stats.tx_dropped;
-			break;
-	}
-
-
-if_send_crit_exit:
-	
-       	dev_kfree_skb_any(skb);
-
-	netif_start_queue(dev);
-	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-	S508_S514_unlock(card, &smp_flags);
-	return 0;
-}
-
-/*============================================================================
- * Setup so that a frame can be transmitted on the occurrence of a transmit
- * interrupt.
- *===========================================================================*/
-
-static void setup_for_delayed_transmit(struct net_device* dev, void* buf,
-				       unsigned len)
-{
-        x25_channel_t* chan = dev->priv;
-        sdla_t* card = chan->card;
-	TX25Status* status = card->flags;
-
-	++chan->if_send_stat.if_send_adptr_bfrs_full;
-
-        if(chan->transmit_length) {
-                printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n",
-				card->devname);
-                return;
-        }
-
-	if (chan->common.usedby == API){
-		if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) {
-			++chan->ifstats.tx_dropped;	
-			++card->wandev.stats.tx_dropped;
-			printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
-				card->devname);
-			return;
-		}
-	}else{
-		if (len > X25_MAX_DATA) {
-			++chan->ifstats.tx_dropped;	
-			++card->wandev.stats.tx_dropped;
-			printk(KERN_INFO "%s: Length is too big for delayed transmit\n",
-				card->devname);
-			return;
-		}
-	}
-
-        chan->transmit_length = len;
-	atomic_set(&chan->common.driver_busy,1);
-        memcpy(chan->transmit_buffer, buf, len);
-
-	++chan->if_send_stat.if_send_tx_int_enabled;
-
-	/* Enable Transmit Interrupt */
-	++card->u.x.tx_interrupts_pending;
-        status->imask |= INTR_ON_TX_FRAME;
-}
-
-
-/*===============================================================
- * net_device_stats
- *
- * 	Get ethernet-style interface statistics.
- * 	Return a pointer to struct enet_statistics.
- *
- *==============================================================*/
-static struct net_device_stats *if_stats(struct net_device* dev)
-{
-	x25_channel_t *chan = dev->priv;
-
-	if(chan == NULL)
-		return NULL;
-
-	return &chan->ifstats;
-}
-
-
-/*
- *	Interrupt Handlers 
- */
-
-/*
- * X.25 Interrupt Service Routine.
- */
-
-static void wpx_isr (sdla_t* card)
-{
-	TX25Status* status = card->flags;
-
-	card->in_isr = 1;
-	++card->statistics.isr_entry;
-
-	if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){
-		card->in_isr=0;
-		status->iflags = 0;
-		return;
-	}
-	
-	if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- 		printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n", 
-			card->devname, card->wandev.critical, status->iflags);
-		card->in_isr = 0;
-		status->iflags = 0;
-		return;
-	}
-
-	/* For all interrupts set the critical flag to CRITICAL_RX_INTR.
-         * If the if_send routine is called with this flag set it will set
-         * the enable transmit flag to 1. (for a delayed interrupt)
-         */
-	switch (status->iflags){
-
-		case RX_INTR_PENDING:		/* receive interrupt */
-			rx_intr(card);
-			break;
-
-		case TX_INTR_PENDING:		/* transmit interrupt */
-			tx_intr(card);
-			break;
-
-		case MODEM_INTR_PENDING:	/* modem status interrupt */
-			status_intr(card);
-			break;
-
-		case X25_ASY_TRANS_INTR_PENDING:	/* network event interrupt */
-			event_intr(card);
-			break;
-
-		case TIMER_INTR_PENDING:
-			timer_intr(card);
-			break;
-
-		default:		/* unwanted interrupt */
-			spur_intr(card);
-	}
-
-	card->in_isr = 0;
-	status->iflags = 0;	/* clear interrupt condition */
-}
-
-/*
- * 	Receive interrupt handler.
- * 	This routine handles fragmented IP packets using M-bit according to the
- * 	RFC1356.
- * 	o map ligical channel number to network interface.
- * 	o allocate socket buffer or append received packet to the existing one.
- * 	o if M-bit is reset (i.e. it's the last packet in a sequence) then 
- *   	decapsulate packet and pass socket buffer to the protocol stack.
- *
- * 	Notes:
- * 	1. When allocating a socket buffer, if M-bit is set then more data is
- *    	coming and we have to allocate buffer for the maximum IP packet size
- *    	expected on this channel.
- * 	2. If something goes wrong and X.25 packet has to be dropped (e.g. no
- *    	socket buffers available) the whole packet sequence must be discarded.
- */
-
-static void rx_intr (sdla_t* card)
-{
-	TX25Mbox* rxmb = card->rxmb;
-	unsigned lcn = rxmb->cmd.lcn;
-	struct net_device* dev = find_channel(card,lcn);
-	x25_channel_t* chan;
-	struct sk_buff* skb=NULL;
-
-	if (dev == NULL){
-		/* Invalid channel, discard packet */
-		printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
-			card->devname, lcn);
-		return;
-	}
-
-	chan = dev->priv;
-	chan->i_timeout_sofar = jiffies;
-
-
-	/* Copy the data from the board, into an
-         * skb buffer 
-	 */
-	if (wanpipe_pull_data_in_skb(card,dev,&skb)){
-		++chan->ifstats.rx_dropped;
-		++card->wandev.stats.rx_dropped;
-		++chan->rx_intr_stat.rx_intr_no_socket;
-		++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-		return;
-	}
-
-	dev->last_rx = jiffies;		/* timestamp */
-
-
-	/* ------------ API ----------------*/
-
-	if (chan->common.usedby == API){
-
-		if (bh_enqueue(dev, skb)){
-			++chan->ifstats.rx_dropped;
-			++card->wandev.stats.rx_dropped;
-			++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-			dev_kfree_skb_any(skb);
-			return;
-		}		
-
-		++chan->ifstats.rx_packets;
-		chan->ifstats.rx_bytes += skb->len;
-		
-
-		chan->rx_skb = NULL;
-		if (!test_and_set_bit(0, &chan->tq_working)){
-			wanpipe_queue_work(&chan->common.wanpipe_work);
-		}
-		return;
-	}
-
-
-	/* ------------- WANPIPE -------------------*/
-	
-	/* set rx_skb to NULL so we won't access it later when kernel already owns it */
-	chan->rx_skb=NULL;
-	
-	/* Decapsulate packet, if necessary */
-	if (!skb->protocol && !wanrouter_type_trans(skb, dev)){
-		/* can't decapsulate packet */
-                dev_kfree_skb_any(skb);
-		++chan->ifstats.rx_errors;
-		++chan->ifstats.rx_dropped;
-		++card->wandev.stats.rx_dropped;
-		++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-
-	}else{
-		if( handle_IPXWAN(skb->data, chan->name, 
-				  chan->enable_IPX, chan->network_number, 
-				  skb->protocol)){
-
-			if( chan->enable_IPX ){
-				if(chan_send(dev, skb->data, skb->len,0)){
-					chan->tx_skb = skb;
-				}else{
-                                        dev_kfree_skb_any(skb);
-					++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-				}
-			}else{
-				/* increment IPX packet dropped statistic */
-				++chan->ifstats.rx_dropped;
-				++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-			}
-		}else{
-			skb->mac.raw = skb->data;
-			chan->ifstats.rx_bytes += skb->len;
-			++chan->ifstats.rx_packets;
-			++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
-			netif_rx(skb);
-		}
-	}
-	
-	return;
-}
-
-
-static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev,
-				    struct sk_buff **skb)
-{
-	void *bufptr;
-	TX25Mbox* rxmb = card->rxmb;
-	unsigned len = rxmb->cmd.length;	/* packet length */
-	unsigned qdm = rxmb->cmd.qdm;		/* Q,D and M bits */
-	x25_channel_t *chan = dev->priv;
-	struct sk_buff *new_skb = *skb;
-
-	if (chan->common.usedby == WANPIPE){
-		if (chan->drop_sequence){
-			if (!(qdm & 0x01)){ 
-				chan->drop_sequence = 0;
-			}
-			return 1;
-		}
-		new_skb = chan->rx_skb;
-	}else{
-		/* Add on the API header to the received
-                 * data 
-		 */
-		len += sizeof(x25api_hdr_t);
-	}
-
-	if (new_skb == NULL){
-		int bufsize;
-
-		if (chan->common.usedby == WANPIPE){
-			bufsize = (qdm & 0x01) ? dev->mtu : len;
-		}else{
-			bufsize = len;
-		}
-
-		/* Allocate new socket buffer */
-		new_skb = dev_alloc_skb(bufsize + dev->hard_header_len);
-		if (new_skb == NULL){
-			printk(KERN_INFO "%s: no socket buffers available!\n",
-				card->devname);
-			chan->drop_sequence = 1;	/* set flag */
-			++chan->ifstats.rx_dropped;
-			return 1;
-		}
-	}
-
-	if (skb_tailroom(new_skb) < len){
-		/* No room for the packet. Call off the whole thing! */
-                dev_kfree_skb_any(new_skb);
-		if (chan->common.usedby == WANPIPE){
-			chan->rx_skb = NULL;
-			if (qdm & 0x01){ 
-				chan->drop_sequence = 1;
-			}
-		}
-
-		printk(KERN_INFO "%s: unexpectedly long packet sequence "
-			"on interface %s!\n", card->devname, dev->name);
-		++chan->ifstats.rx_length_errors;
-		return 1;
-	}
-
-	bufptr = skb_put(new_skb,len);
-
-
-	if (chan->common.usedby == API){
-		/* Fill in the x25api header 
-		 */
-		x25api_t * api_data = (x25api_t*)bufptr;
-		api_data->hdr.qdm = rxmb->cmd.qdm;
-		api_data->hdr.cause = rxmb->cmd.cause;
-		api_data->hdr.diagn = rxmb->cmd.diagn;
-		api_data->hdr.length = rxmb->cmd.length;
-		memcpy(api_data->data, rxmb->data, rxmb->cmd.length);
-	}else{
-		memcpy(bufptr, rxmb->data, len);
-	}
-
-	new_skb->dev = dev;
-
-	if (chan->common.usedby == API){
-		new_skb->mac.raw = new_skb->data;
-		new_skb->protocol = htons(X25_PROT);
-		new_skb->pkt_type = WAN_PACKET_DATA;
-	}else{
-		new_skb->protocol = chan->protocol;
-		chan->rx_skb = new_skb;
-	}
-
-	/* If qdm bit is set, more data is coming 
-         * thus, exit and wait for more data before
-         * sending the packet up. (Used by router only) 
-	 */
-	if ((qdm & 0x01) && (chan->common.usedby == WANPIPE)) 
-		return 1;	
-
-	*skb = new_skb; 
-
-	return 0;
-}
-
-/*===============================================================
- * tx_intr
- *  
- * 	Transmit interrupt handler.
- *	For each dev, check that there is something to send.
- *	If data available, transmit. 	
- *
- *===============================================================*/
-
-static void tx_intr (sdla_t* card)
-{
-	struct net_device *dev;
-	TX25Status* status = card->flags;
-	unsigned char more_to_tx=0;
-	x25_channel_t *chan=NULL;
-	int i=0;	
-
-	if (card->u.x.tx_dev == NULL){
-		card->u.x.tx_dev = card->wandev.dev;
-	}
-
-	dev = card->u.x.tx_dev;
-
-	for (;;){
-
-		chan = dev->priv;
-		if (chan->transmit_length){
-			/* Device was set to transmit, check if the TX
-                         * buffers are available 
-			 */		
-			if (chan->common.state != WAN_CONNECTED){
-				chan->transmit_length = 0;
-				atomic_set(&chan->common.driver_busy,0);
-				chan->tx_offset=0;
-				if (netif_queue_stopped(dev)){
-					if (chan->common.usedby == API){
-						netif_start_queue(dev);
-						wakeup_sk_bh(dev);
-					}else{
-						netif_wake_queue(dev);
-					}
-				}
-				dev = move_dev_to_next(card,dev);
-				break;
-			}				
-
-			if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) && 
-			     (*card->u.x.hdlc_buf_status & 0x40) ){
-				/* Tx buffer available, we can send */
-				
-				if (tx_intr_send(card, dev)){
-					more_to_tx=1;
-				}
-
-				/* If more than one interface present, move the
-                                 * device pointer to the next interface, so on the 
-                                 * next TX interrupt we will try sending from it. 
-                                 */
-				dev = move_dev_to_next(card,dev);
-				break;
-			}else{
-				/* Tx buffers not available, but device set
-                                 * the TX interrupt.  Set more_to_tx and try  
-                                 * to transmit for other devices.
-				 */
-				more_to_tx=1;
-				dev = move_dev_to_next(card,dev);
-			}
-
-		}else{
-			/* This device was not set to transmit,
-                         * go to next 
-			 */
-			dev = move_dev_to_next(card,dev);
-		}	
-
-		if (++i == card->u.x.no_dev){
-			if (!more_to_tx){
-				DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n",
-					card->devname);
-			}
-			break;
-		}
-
-	} //End of FOR
-
-	card->u.x.tx_dev = dev;
-	
-	if (!more_to_tx){
-		/* if any other interfaces have transmit interrupts pending, */
-		/* do not disable the global transmit interrupt */
-		if (!(--card->u.x.tx_interrupts_pending)){
-			status->imask &= ~INTR_ON_TX_FRAME;
-		}
-	}
-	return;
-}
-
-/*===============================================================
- * move_dev_to_next
- *  
- *
- *===============================================================*/
-
-
-struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev)
-{
-	if (card->u.x.no_dev != 1){
-		if (!*((struct net_device **)dev->priv))
-			return card->wandev.dev;
-		else
-			return *((struct net_device **)dev->priv);
-	}
-	return dev;
-}
-
-/*===============================================================
- *  tx_intr_send
- *  
- *
- *===============================================================*/
-
-static int tx_intr_send(sdla_t *card, struct net_device *dev)
-{
-	x25_channel_t* chan = dev->priv; 
-
-	if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){
-		 
-                /* Packet was split up due to its size, do not disable
-                 * tx_intr 
-                 */
-		return 1;
-	}
-
-	chan->transmit_length=0;
-	atomic_set(&chan->common.driver_busy,0);
-	chan->tx_offset=0;
-
-	/* If we are in API mode, wakeup the 
-         * sock BH handler, not the NET_BH */
-	if (netif_queue_stopped(dev)){
-		if (chan->common.usedby == API){
-			netif_start_queue(dev);
-			wakeup_sk_bh(dev);
-		}else{
-			netif_wake_queue(dev);
-		}
-	}
-	return 0;
-}
-
-
-/*===============================================================
- * timer_intr
- *  
- * 	Timer interrupt handler.
- *	Check who called the timer interrupt and perform
- *      action accordingly.
- *
- *===============================================================*/
-
-static void timer_intr (sdla_t *card)
-{
-	TX25Status* status = card->flags;
-
-	if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){
-
-		if (timer_intr_cmd_exec(card) == 0){
-			card->u.x.timer_int_enabled &=
-				~TMR_INT_ENABLED_CMD_EXEC;
-		}
-
-	}else  if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) {
-
-		if ((*card->u.x.hdlc_buf_status & 0x40) && 
-		    card->u.x.udp_type == UDP_XPIPE_TYPE){
-
-                    	if(process_udp_mgmt_pkt(card)) {
-		                card->u.x.timer_int_enabled &= 
-					~TMR_INT_ENABLED_UDP_PKT;
-			}
-		}
-
-	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) {
-
-		struct net_device *dev = card->u.x.poll_device;
-		x25_channel_t *chan = NULL;
-
-		if (!dev){
-			card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
-			return;
-		}
-		chan = dev->priv;
-
-		printk(KERN_INFO 
-			"%s: Closing down Idle link %s on LCN %d\n",
-					card->devname,chan->name,chan->common.lcn); 
-		chan->i_timeout_sofar = jiffies;
-		chan_disc(dev);	
-         	card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;
-		card->u.x.poll_device=NULL;
-
-	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) {
-
-		wanpipe_set_state(card, WAN_CONNECTED);
-		if (card->u.x.LAPB_hdlc){
-			struct net_device *dev = card->wandev.dev;
-			set_chan_state(dev,WAN_CONNECTED);
-			send_delayed_cmd_result(card,dev,card->mbox);	
-		}
-
-		/* 0x8F enable all interrupts */
-		x25_set_intr_mode(card, INTR_ON_RX_FRAME|	
-					INTR_ON_TX_FRAME|
-					INTR_ON_MODEM_STATUS_CHANGE|
-					//INTR_ON_COMMAND_COMPLETE|
-					X25_ASY_TRANS_INTR_PENDING |
-					INTR_ON_TIMER |
-					DIRECT_RX_INTR_USAGE
-				); 
-
-		status->imask &= ~INTR_ON_TX_FRAME;	/* mask Tx interrupts */
-		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON;
-
-	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) {
-
-		//printk(KERN_INFO "Poll connect, Turning OFF\n");
-		disconnect(card);
-		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF;
-
-	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) {
-
-		//printk(KERN_INFO "POll disconnect, trying to connect\n");
-		connect(card);
-		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT;
-
-	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){
-
-		if (*card->u.x.hdlc_buf_status & 0x40){
-			x25_get_err_stats(card);
-			x25_get_stats(card);
-			card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;
-		}
-	}
-
-	if(!card->u.x.timer_int_enabled){
-		//printk(KERN_INFO "Turning Timer Off \n");
-                status->imask &= ~INTR_ON_TIMER;	
-	}
-}
-
-/*====================================================================
- * 	Modem status interrupt handler.
- *===================================================================*/
-static void status_intr (sdla_t* card)
-{
-
-	/* Added to avoid Modem status message flooding */
-	static TX25ModemStatus last_stat;
-
-	TX25Mbox* mbox = card->mbox;
-	TX25ModemStatus *modem_status;
-	struct net_device *dev;
-	x25_channel_t *chan;
-	int err;
-
-	memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-	mbox->cmd.command = X25_READ_MODEM_STATUS;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err){ 
-		x25_error(card, err, X25_READ_MODEM_STATUS, 0);
-	}else{
-	
-		modem_status = (TX25ModemStatus*)mbox->data;	
-	
-           	/* Check if the last status was the same
-           	 * if it was, do NOT print message again */
-	
-		if (last_stat.status != modem_status->status){
-
-	     		printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n",
-				card->devname,DCD(modem_status->status),CTS(modem_status->status));
-
-			last_stat.status = modem_status->status;
-		
-			if (card->u.x.oob_on_modem){
-
-				mbox->cmd.pktType = mbox->cmd.command;
-				mbox->cmd.result = 0x08;
-
-				/* Send a OOB to all connected sockets */
-				for (dev = card->wandev.dev; dev;
-				     dev = *((struct net_device**)dev->priv)) {
-					chan=dev->priv;
-					if (chan->common.usedby == API){
-						send_oob_msg(card,dev,mbox);				
-					}
-				}
-
-				/* The modem OOB message will probably kill the
-				 * the link. If we don't clear the flag here,
-				 * a deadlock could occur */ 
-				if (atomic_read(&card->u.x.command_busy)){
-					atomic_set(&card->u.x.command_busy,0);
-				}
-			}
-		}
-	}
-
-	memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-	mbox->cmd.command = X25_HDLC_LINK_STATUS;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err){ 
-		x25_error(card, err, X25_HDLC_LINK_STATUS, 0);
-	}
-
-}
-
-/*====================================================================
- * 	Network event interrupt handler.
- *===================================================================*/
-static void event_intr (sdla_t* card)
-{
-	x25_fetch_events(card);
-}
-
-/*====================================================================
- * 	Spurious interrupt handler.
- * 	o print a warning
- * 	o	 
- *====================================================================*/
-
-static void spur_intr (sdla_t* card)
-{
-	printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
-}
-
-
-/*
- *	Background Polling Routines  
- */
-
-/*====================================================================
- * 	Main polling routine.
- * 	This routine is repeatedly called by the WANPIPE 'thread' to allow for
- * 	time-dependent housekeeping work.
- *
- * 	Notes:
- * 	1. This routine may be called on interrupt context with all interrupts
- *    	enabled. Beware!
- *====================================================================*/
-
-static void wpx_poll (sdla_t *card)
-{
-	if (!card->wandev.dev){
-		goto wpx_poll_exit;
-	}
-
-	if (card->open_cnt != card->u.x.num_of_ch){
-		goto wpx_poll_exit;
-	}
-	
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		goto wpx_poll_exit;
-	}
-
-	if (test_bit(SEND_CRIT,&card->wandev.critical)){
-		goto wpx_poll_exit;
-	}
-
-	switch(card->wandev.state){
-		case WAN_CONNECTED:
-			poll_active(card);
-			break;
-
-		case WAN_CONNECTING:
-			poll_connecting(card);
-			break;
-
-		case WAN_DISCONNECTED:
-			poll_disconnected(card);
-			break;
-	}
-
-wpx_poll_exit:
-	clear_bit(POLL_CRIT,&card->wandev.critical);
-	return;
-}
-
-static void trigger_x25_poll(sdla_t *card)
-{
-	schedule_work(&card->u.x.x25_poll_work);
-}
-
-/*====================================================================
- * 	Handle physical link establishment phase.
- * 	o if connection timed out, disconnect the link.
- *===================================================================*/
-
-static void poll_connecting (sdla_t* card)
-{
-	volatile TX25Status* status = card->flags;
-
-	if (status->gflags & X25_HDLC_ABM){
-
-		timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_ON);
-
-	}else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT){
-
-		timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_OFF);
-
-	}
-}
-
-/*====================================================================
- * 	Handle physical link disconnected phase.
- * 	o if hold-down timeout has expired and there are open interfaces, 
- *	connect link.
- *===================================================================*/
-
-static void poll_disconnected (sdla_t* card)
-{
-	struct net_device *dev; 
-	x25_channel_t *chan;
-	TX25Status* status = card->flags;
-
-	if (!card->u.x.LAPB_hdlc && card->open_cnt && 
-	    ((jiffies - card->state_tick) > HOLD_DOWN_TIME)){
-		timer_intr_exec(card, TMR_INT_ENABLED_POLL_DISCONNECT);
-	}
-
-
-	if ((dev=card->wandev.dev) == NULL)
-		return;
-
-	if ((chan=dev->priv) == NULL)
-		return;
-
-	if (chan->common.usedby == API && 
-	    atomic_read(&chan->common.command) && 
-	    card->u.x.LAPB_hdlc){
-
-		if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) 
-			card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
-		if (!(status->imask & INTR_ON_TIMER))
-			status->imask |= INTR_ON_TIMER;
-	}	
-
-}
-
-/*====================================================================
- * 	Handle active link phase.
- * 	o fetch X.25 asynchronous events.
- * 	o kick off transmission on all interfaces.
- *===================================================================*/
-
-static void poll_active (sdla_t* card)
-{
-	struct net_device* dev;
-	TX25Status* status = card->flags;
-
-	for (dev = card->wandev.dev; dev;
-	     dev = *((struct net_device **)dev->priv)){
-		x25_channel_t* chan = dev->priv;
-
-		/* If SVC has been idle long enough, close virtual circuit */
-		if ( chan->common.svc && 
-		     chan->common.state == WAN_CONNECTED &&
-		     chan->common.usedby == WANPIPE ){
-		
-			if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout ){
-				/* Close svc */
-				card->u.x.poll_device=dev;
-				timer_intr_exec	(card, TMR_INT_ENABLED_POLL_ACTIVE);
-			}
-		}
-
-#ifdef PRINT_DEBUG
-		chan->ifstats.tx_compressed = atomic_read(&chan->common.command);
-		chan->ifstats.tx_errors = chan->common.state;
-		chan->ifstats.rx_fifo_errors = atomic_read(&card->u.x.command_busy);
-		++chan->ifstats.tx_bytes;
-
-		chan->ifstats.rx_fifo_errors=atomic_read(&chan->common.disconnect);
-		chan->ifstats.multicast=atomic_read(&chan->bh_buff_used);
-		chan->ifstats.rx_length_errors=*card->u.x.hdlc_buf_status;
-#endif	
-
-		if (chan->common.usedby == API && 
-		    atomic_read(&chan->common.command) && 
-	            !card->u.x.LAPB_hdlc){
-
-			if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) 
-				card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
-			if (!(status->imask & INTR_ON_TIMER))
-				status->imask |= INTR_ON_TIMER;
-		}	
-
-		if ((chan->common.usedby == API) && 
-		     atomic_read(&chan->common.disconnect)){
-
-			if (chan->common.state == WAN_DISCONNECTED){
-				atomic_set(&chan->common.disconnect,0);
-				return;
-			}
-
-			atomic_set(&chan->common.command,X25_CLEAR_CALL);
-			if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) 
-				card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC;
-
-			if (!(status->imask & INTR_ON_TIMER))
-				status->imask |= INTR_ON_TIMER;
-		}
-	}
-}
-
-static void timer_intr_exec(sdla_t *card, unsigned char TYPE)
-{
-	TX25Status* status = card->flags;
-	card->u.x.timer_int_enabled |= TYPE;
-	if (!(status->imask & INTR_ON_TIMER))
-		status->imask |= INTR_ON_TIMER;
-}
-
-
-/*==================================================================== 
- * SDLA Firmware-Specific Functions 
- *
- *  Almost all X.25 commands can unexpetedly fail due to so called 'X.25
- *  asynchronous events' such as restart, interrupt, incoming call request,
- *  call clear request, etc.  They can't be ignored and have to be delt with
- *  immediately.  To tackle with this problem we execute each interface 
- *  command in a loop until good return code is received or maximum number 
- *  of retries is reached.  Each interface command returns non-zero return 
- *  code, an asynchronous event/error handler x25_error() is called.
- *====================================================================*/
-
-/*====================================================================
- * 	Read X.25 firmware version.
- *		Put code version as ASCII string in str. 
- *===================================================================*/
-
-static int x25_get_version (sdla_t* card, char* str)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_READ_CODE_VERSION;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- &&
-		 x25_error(card, err, X25_READ_CODE_VERSION, 0));
-
-	if (!err && str)
-	{
-		int len = mbox->cmd.length;
-
-		memcpy(str, mbox->data, len);
-		str[len] = '\0';
-	}
-	return err;
-}
-
-/*====================================================================
- * 	Configure adapter.
- *===================================================================*/
-
-static int x25_configure (sdla_t* card, TX25Config* conf)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
-		mbox->cmd.length  = sizeof(TX25Config);
-		mbox->cmd.command = X25_SET_CONFIGURATION;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
-	return err;
-}
-
-/*====================================================================
- * 	Configure adapter for HDLC only.
- *===================================================================*/
-
-static int hdlc_configure (sdla_t* card, TX25Config* conf)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
-		mbox->cmd.length  = sizeof(TX25Config);
-		mbox->cmd.command = X25_HDLC_SET_CONFIG;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
-
-	return err;
-}
-
-static int set_hdlc_level (sdla_t* card)
-{
-
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = SET_PROTOCOL_LEVEL;
-		mbox->cmd.length = 1;
-		mbox->data[0] = HDLC_LEVEL; //| DO_HDLC_LEVEL_ERROR_CHECKING; 	
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, SET_PROTOCOL_LEVEL, 0));
-
-	return err;
-}
-
-
-
-/*====================================================================
- * Get communications error statistics.
- *====================================================================*/
-
-static int x25_get_err_stats (sdla_t* card)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_HDLC_READ_COMM_ERR;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0));
-	
-	if (!err)
-	{
-		THdlcCommErr* stats = (void*)mbox->data;
-
-		card->wandev.stats.rx_over_errors    = stats->rxOverrun;
-		card->wandev.stats.rx_crc_errors     = stats->rxBadCrc;
-		card->wandev.stats.rx_missed_errors  = stats->rxAborted;
-		card->wandev.stats.tx_aborted_errors = stats->txAborted;
-	}
-	return err;
-}
-
-/*====================================================================
- * 	Get protocol statistics.
- *===================================================================*/
-
-static int x25_get_stats (sdla_t* card)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_READ_STATISTICS;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0)) ;
-	
-	if (!err)
-	{
-		TX25Stats* stats = (void*)mbox->data;
-
-		card->wandev.stats.rx_packets = stats->rxData;
-		card->wandev.stats.tx_packets = stats->txData;
-	}
-	return err;
-}
-
-/*====================================================================
- * 	Close HDLC link.
- *===================================================================*/
-
-static int x25_close_hdlc (sdla_t* card)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_HDLC_LINK_CLOSE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0));
-	
-	return err;
-}
-
-
-/*====================================================================
- * 	Open HDLC link.
- *===================================================================*/
-
-static int x25_open_hdlc (sdla_t* card)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_HDLC_LINK_OPEN;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0));
-
-	return err;
-}
-
-/*=====================================================================
- * Setup HDLC link.
- *====================================================================*/
-static int x25_setup_hdlc (sdla_t* card)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_HDLC_LINK_SETUP;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0));
-	
-	return err;
-}
-
-/*====================================================================
- * Set (raise/drop) DTR.
- *===================================================================*/
-
-static int x25_set_dtr (sdla_t* card, int dtr)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->data[0] = 0;
-		mbox->data[2] = 0;
-		mbox->data[1] = dtr ? 0x02 : 0x01;
-		mbox->cmd.length  = 3;
-		mbox->cmd.command = X25_SET_GLOBAL_VARS;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0));
-	
-	return err;
-}
-
-/*====================================================================
- * 	Set interrupt mode.
- *===================================================================*/
-
-static int x25_set_intr_mode (sdla_t* card, int mode)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->data[0] = mode;
-		if (card->hw.fwid == SFID_X25_508){
-			mbox->data[1] = card->hw.irq;
-			mbox->data[2] = 2;
-			mbox->cmd.length = 3;
-		}else {
-		 	mbox->cmd.length  = 1;
-		}
-		mbox->cmd.command = X25_SET_INTERRUPT_MODE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0));
-	
-	return err;
-}
-
-/*====================================================================
- * 	Read X.25 channel configuration.
- *===================================================================*/
-
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int lcn = chan->common.lcn;
-	int err;
-
-	do{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.lcn     = lcn;
-		mbox->cmd.command = X25_READ_CHANNEL_CONFIG;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn));
-
-	if (!err)
-	{
-		TX25Status* status = card->flags;
-
-		/* calculate an offset into the array of status bytes */
-		if (card->u.x.hi_svc <= X25_MAX_CHAN){ 
-
-			chan->ch_idx = lcn - 1;
-
-		}else{
-			int offset;
-
-			/* FIX: Apr 14 2000 : Nenad Corbic
-			 * The data field was being compared to 0x1F using
-                         * '&&' instead of '&'. 
-			 * This caused X25API to fail for LCNs greater than 255.
-			 */
-			switch (mbox->data[0] & 0x1F)
-			{
-				case 0x01: 
-					offset = status->pvc_map; break;
-				case 0x03: 
-					offset = status->icc_map; break;
-				case 0x07: 
-					offset = status->twc_map; break;
-				case 0x0B: 
-					offset = status->ogc_map; break;
-				default: 
-					offset = 0;
-			}
-			chan->ch_idx = lcn - 1 - offset;
-		}
-
-		/* get actual transmit packet size on this channel */
-		switch(mbox->data[1] & 0x38)
-		{
-			case 0x00: 
-				chan->tx_pkt_size = 16; 
-				break;
-			case 0x08: 
-				chan->tx_pkt_size = 32; 
-				break;
-			case 0x10: 
-				chan->tx_pkt_size = 64; 
-				break;
-			case 0x18: 
-				chan->tx_pkt_size = 128; 
-				break;
-			case 0x20: 
-				chan->tx_pkt_size = 256; 
-				break;
-			case 0x28: 
-				chan->tx_pkt_size = 512; 
-				break;
-			case 0x30: 
-				chan->tx_pkt_size = 1024; 
-				break;
-		}
-		if (card->u.x.logging)
-			printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n",
-				card->devname, lcn, chan->tx_pkt_size);
-	}
-	return err;
-}
-
-/*====================================================================
- * 	Place X.25 call.
- *====================================================================*/
-
-static int x25_place_call (sdla_t* card, x25_channel_t* chan)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-	char str[64];
-
-
-	if (chan->protocol == htons(ETH_P_IP)){
-		sprintf(str, "-d%s -uCC", chan->addr);
-	
-	}else if (chan->protocol == htons(ETH_P_IPX)){
-		sprintf(str, "-d%s -u800000008137", chan->addr);
-	
-	}
-	
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		strcpy(mbox->data, str);
-		mbox->cmd.length  = strlen(str);
-		mbox->cmd.command = X25_PLACE_CALL;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0));
-
-	if (!err){
-		bind_lcn_to_dev (card, chan->dev, mbox->cmd.lcn);
-	}
-	return err;
-}
-
-/*====================================================================
- * 	Accept X.25 call.
- *====================================================================*/
-
-static int x25_accept_call (sdla_t* card, int lcn, int qdm)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.lcn     = lcn;
-		mbox->cmd.qdm     = qdm;
-		mbox->cmd.command = X25_ACCEPT_CALL;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn));
-	
-	return err;
-}
-
-/*====================================================================
- * 	Clear X.25 call.
- *====================================================================*/
-
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.lcn     = lcn;
-		mbox->cmd.cause   = cause;
-		mbox->cmd.diagn   = diagn;
-		mbox->cmd.command = X25_CLEAR_CALL;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn));
-	
-	return err;
-}
-
-/*====================================================================
- * 	Send X.25 data packet.
- *====================================================================*/
-
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf)
-{
-	TX25Mbox* mbox = card->mbox;
-  	int retry = MAX_CMD_RETRY;
-	int err;
-	unsigned char cmd;
-		
-	if (card->u.x.LAPB_hdlc)
-		cmd = X25_HDLC_WRITE;
-	else
-		cmd = X25_WRITE;
-
-	do
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		memcpy(mbox->data, buf, len);
-		mbox->cmd.length  = len;
-		mbox->cmd.lcn     = lcn;
-
-		if (card->u.x.LAPB_hdlc){
-			mbox->cmd.pf = qdm;
-		}else{			
-			mbox->cmd.qdm = qdm;
-		}
-
-		mbox->cmd.command = cmd;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	} while (err && retry-- && x25_error(card, err, cmd , lcn));
-
-
-	/* If buffers are busy the return code for LAPB HDLC is
-         * 1. The above functions are looking for return code
-         * of X25RES_NOT_READY if busy. */
-
-	if (card->u.x.LAPB_hdlc && err == 1){
-		err = X25RES_NOT_READY;
-	}
-
-	return err;
-}
-
-/*====================================================================
- * 	Fetch X.25 asynchronous events.
- *===================================================================*/
-
-static int x25_fetch_events (sdla_t* card)
-{
-	TX25Status* status = card->flags;
-	TX25Mbox* mbox = card->mbox;
-	int err = 0;
-
-	if (status->gflags & 0x20)
-	{
-		memset(&mbox->cmd, 0, sizeof(TX25Cmd));
-		mbox->cmd.command = X25_IS_DATA_AVAILABLE;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- 		if (err) x25_error(card, err, X25_IS_DATA_AVAILABLE, 0);
-	}
-	return err;
-}
-
-/*====================================================================
- * 	X.25 asynchronous event/error handler.
- *		This routine is called each time interface command returns 
- *		non-zero return code to handle X.25 asynchronous events and 
- *		common errors. Return non-zero to repeat command or zero to 
- *		cancel it.
- *
- * 	Notes:
- * 	1. This function may be called recursively, as handling some of the
- *    	asynchronous events (e.g. call request) requires execution of the
- *    	interface command(s) that, in turn, may also return asynchronous
- *    	events.  To avoid re-entrancy problems we copy mailbox to dynamically
- *    	allocated memory before processing events.
- *====================================================================*/
-
-static int x25_error (sdla_t* card, int err, int cmd, int lcn)
-{
-	int retry = 1;
-	unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length;
-	TX25Mbox* mb;
-
-	mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC);
-	if (mb == NULL)
-	{
-		printk(KERN_ERR "%s: x25_error() out of memory!\n",
-			card->devname);
-		return 0;
-	}
-	memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen);
-	switch (err){
-
-	case X25RES_ASYNC_PACKET:	/* X.25 asynchronous packet was received */
-
-		mb->data[dlen] = '\0';
-
-		switch (mb->cmd.pktType & 0x7F){
-
-		case ASE_CALL_RQST:		/* incoming call */
-			retry = incoming_call(card, cmd, lcn, mb);
-			break;
-
-		case ASE_CALL_ACCEPTED:		/* connected */
-			retry = call_accepted(card, cmd, lcn, mb);
-			break;
-
-		case ASE_CLEAR_RQST:		/* call clear request */
-			retry = call_cleared(card, cmd, lcn, mb);
-			break;
-
-		case ASE_RESET_RQST:		/* reset request */
-			printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
-				"Cause:0x%02X Diagn:0x%02X\n",
-				card->devname, mb->cmd.lcn, mb->cmd.cause,
-				mb->cmd.diagn);
-			api_oob_event (card,mb);
-			break;
-
-		case ASE_RESTART_RQST:		/* restart request */
-			retry = restart_event(card, cmd, lcn, mb);
-			break;
-
-		case ASE_CLEAR_CONFRM:
-			if (clear_confirm_event (card,mb))
-				break;
-
-			/* I use the goto statement here so if 
-	                 * somebody inserts code between the
-        	         * case and default, we will not have
-                	 * ghost problems */
-
-			goto dflt_1;
-
-		default:
-dflt_1:
-			printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! "
-				"Cause:0x%02X Diagn:0x%02X\n",
-				card->devname, mb->cmd.pktType,
-				mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn);
-		}
-		break;
-
-	case X25RES_PROTO_VIOLATION:	/* X.25 protocol violation indication */
-
-		/* Bug Fix: Mar 14 2000
-                 * The Protocol violation error conditions were  
-                 * not handled previously */
-
-		switch (mb->cmd.pktType & 0x7F){
-
-		case PVE_CLEAR_RQST:	/* Clear request */		
-			retry = call_cleared(card, cmd, lcn, mb);
-			break;	
-
-		case PVE_RESET_RQST:	/* Reset request */
-			printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
-				"Cause:0x%02X Diagn:0x%02X\n",
-				card->devname, mb->cmd.lcn, mb->cmd.cause,
-				mb->cmd.diagn);
-			api_oob_event (card,mb);
-			break;
-
-		case PVE_RESTART_RQST:	/* Restart request */
-			retry = restart_event(card, cmd, lcn, mb);
-			break;
-
-		default :
-			printk(KERN_INFO
-				"%s: X.25 protocol violation on LCN %d! "
-				"Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n",
-				card->devname, mb->cmd.lcn,
-				mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn);
-			api_oob_event(card,mb);
-		}
-		break;
-
-	case 0x42:	/* X.25 timeout */
-		retry = timeout_event(card, cmd, lcn, mb);
-		break;
-
-	case 0x43:	/* X.25 retry limit exceeded */
-		printk(KERN_INFO
-			"%s: exceeded X.25 retry limit on LCN %d! "
-			"Packet:0x%02X Diagn:0x%02X\n", card->devname,
-			mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn)
-		;
-		break;
-
-	case 0x08:	/* modem failure */
-#ifndef MODEM_NOT_LOG
-		printk(KERN_INFO "%s: modem failure!\n", card->devname);
-#endif /* MODEM_NOT_LOG */
-		api_oob_event(card,mb);
-		break;
-
-	case 0x09:	/* N2 retry limit */
-		printk(KERN_INFO "%s: exceeded HDLC retry limit!\n",
-			card->devname);
-		api_oob_event(card,mb);
-		break;
-
-	case 0x06:	/* unnumbered frame was received while in ABM */
-		printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n",
-			card->devname, mb->data[0]);
-		api_oob_event(card,mb);
-		break;
-
-	case CMD_TIMEOUT:
-		printk(KERN_ERR "%s: command 0x%02X timed out!\n",
-			card->devname, cmd)
-		;
-		retry = 0;	/* abort command */
-		break;
-
-	case X25RES_NOT_READY:
-		retry = 1;
-		break;
-
-	case 0x01:
-		if (card->u.x.LAPB_hdlc)
-			break;
-
-		if (mb->cmd.command == 0x16)
-			break;
-		/* I use the goto statement here so if 
-                 * somebody inserts code between the
-                 * case and default, we will not have
-                 * ghost problems */
-		goto dflt_2;
-
-	default:
-dflt_2:
-		printk(KERN_INFO "%s: command 0x%02X returned 0x%02X! Lcn %i\n",
-			card->devname, cmd, err, mb->cmd.lcn)
-		;
-		retry = 0;	/* abort command */
-	}
-	kfree(mb);
-	return retry;
-}
-
-/*==================================================================== 
- *	X.25 Asynchronous Event Handlers
- * 	These functions are called by the x25_error() and should return 0, if
- * 	the command resulting in the asynchronous event must be aborted.
- *====================================================================*/
-
-
-
-/*====================================================================
- *Handle X.25 incoming call request.
- *	RFC 1356 establishes the following rules:
- *	1. The first octet in the Call User Data (CUD) field of the call
- *     	   request packet contains NLPID identifying protocol encapsulation
- * 	2. Calls MUST NOT be accepted unless router supports requested
- *   	   protocol encapsulation.
- *	3. A diagnostic code 249 defined by ISO/IEC 8208 may be used 
- *	   when clearing a call because protocol encapsulation is not 
- *	   supported.
- *	4. If an incoming call is received while a call request is 
- *	   pending (i.e. call collision has occurred), the incoming call 
- *	   shall be rejected and call request shall be retried.
- *====================================================================*/
-
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
-	struct wan_device* wandev = &card->wandev;
-	int new_lcn = mb->cmd.lcn;
-	struct net_device* dev = get_dev_by_lcn(wandev, new_lcn);
-	x25_channel_t* chan = NULL;
-	int accept = 0;		/* set to '1' if o.k. to accept call */
-	unsigned int user_data;
-	x25_call_info_t* info;
-	
-	/* Make sure there is no call collision */
-	if (dev != NULL)
-	{
-		printk(KERN_INFO
-			"%s: X.25 incoming call collision on LCN %d!\n",
-			card->devname, new_lcn);
-
-		x25_clear_call(card, new_lcn, 0, 0);
-		return 1;
-	}
-
-	/* Make sure D bit is not set in call request */
-//FIXME: THIS IS NOT TURE !!!! TAKE IT OUT
-//	if (mb->cmd.qdm & 0x02)
-//	{
-//		printk(KERN_INFO
-//			"%s: X.25 incoming call on LCN %d with D-bit set!\n",
-//			card->devname, new_lcn);
-//
-//		x25_clear_call(card, new_lcn, 0, 0);
-//		return 1;
-//	}
-
-	/* Parse call request data */
-	info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC);
-	if (info == NULL)
-	{
-		printk(KERN_ERR
-			"%s: not enough memory to parse X.25 incoming call "
-			"on LCN %d!\n", card->devname, new_lcn);
-		x25_clear_call(card, new_lcn, 0, 0);
-		return 1;
-	}
- 
-	parse_call_info(mb->data, info);
-
-	if (card->u.x.logging)
-		printk(KERN_INFO "\n%s: X.25 incoming call on LCN %d!\n",
-			card->devname, new_lcn);
-
-	/* Conver the first two ASCII characters into an
-         * interger. Used to check the incoming protocol 
-         */
-	user_data = hex_to_uint(info->user,2);
-
-	/* Find available channel */
-	for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
-		chan = dev->priv;
-
-		if (chan->common.usedby == API)
-			continue;
-
-		if (!chan->common.svc || (chan->common.state != WAN_DISCONNECTED))
-			continue;
-
-		if (user_data == NLPID_IP && chan->protocol != htons(ETH_P_IP)){
-			printk(KERN_INFO "IP packet but configured for IPX : %x, %x\n",
-				       htons(chan->protocol), info->user[0]);
-			continue;
-		}
-	
-		if (user_data == NLPID_SNAP && chan->protocol != htons(ETH_P_IPX)){
-			printk(KERN_INFO "IPX packet but configured for IP: %x\n",
-				       htons(chan->protocol));
-			continue;
-		}
-		if (strcmp(info->src, chan->addr) == 0)
-			break;
-
-	        /* If just an '@' is specified, accept all incoming calls */
-	        if (strcmp(chan->addr, "") == 0)
-	                break;
-	}
-
-	if (dev == NULL){
-
-		/* If the call is not for any WANPIPE interfaces
-                 * check to see if there is an API listening queue
-                 * waiting for data. If there is send the packet
-                 * up the stack.
-                 */
-		if (card->sk != NULL && card->func != NULL){
-			if (api_incoming_call(card,mb,new_lcn)){
-				x25_clear_call(card, new_lcn, 0, 0);
-			}
-			accept = 0;
-		}else{
-			printk(KERN_INFO "%s: no channels available!\n",
-				card->devname);
-			
-			x25_clear_call(card, new_lcn, 0, 0);
-		}
-
-	}else if (info->nuser == 0){
-
-		printk(KERN_INFO
-			"%s: no user data in incoming call on LCN %d!\n",
-			card->devname, new_lcn)
-		;
-		x25_clear_call(card, new_lcn, 0, 0);
-
-	}else switch (info->user[0]){
-
-		case 0:		/* multiplexed */
-			chan->protocol = htons(0);
-			accept = 1;
-			break;
-
-		case NLPID_IP:	/* IP datagrams */
-			accept = 1;
-			break;
-
-		case NLPID_SNAP: /* IPX datagrams */
-			accept = 1;
-			break;
-
-		default:
-			printk(KERN_INFO
-				"%s: unsupported NLPID 0x%02X in incoming call "
-				"on LCN %d!\n", card->devname, info->user[0], new_lcn);
-			x25_clear_call(card, new_lcn, 0, 249);
-	}
-	
-	if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK)){
-
-		bind_lcn_to_dev (card, chan->dev, new_lcn);
-		
-		if (x25_get_chan_conf(card, chan) == CMD_OK)
-			set_chan_state(dev, WAN_CONNECTED);
-		else 
-			x25_clear_call(card, new_lcn, 0, 0);
-	}
-	kfree(info);
-	return 1;
-}
-
-/*====================================================================
- * 	Handle accepted call.
- *====================================================================*/
-
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
-	unsigned new_lcn = mb->cmd.lcn;
-	struct net_device* dev = find_channel(card, new_lcn);
-	x25_channel_t* chan;
-
-	if (dev == NULL){
-		printk(KERN_INFO
-			"%s: clearing orphaned connection on LCN %d!\n",
-			card->devname, new_lcn);
-		x25_clear_call(card, new_lcn, 0, 0);
-		return 1;
-	}
-
-	if (card->u.x.logging)	
-		printk(KERN_INFO "%s: X.25 call accepted on Dev %s and LCN %d!\n",
-			card->devname, dev->name, new_lcn);
-
-	/* Get channel configuration and notify router */
-	chan = dev->priv;
-	if (x25_get_chan_conf(card, chan) != CMD_OK)
-	{
-		x25_clear_call(card, new_lcn, 0, 0);
-		return 1;
-	}
-
-	set_chan_state(dev, WAN_CONNECTED);
-
-	if (chan->common.usedby == API){
-		send_delayed_cmd_result(card,dev,mb);
-		bind_lcn_to_dev (card, dev, new_lcn);
-	}
-
-	return 1;
-}
-
-/*====================================================================
- * 	Handle cleared call.
- *====================================================================*/
-
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
-	unsigned new_lcn = mb->cmd.lcn;
-	struct net_device* dev = find_channel(card, new_lcn);
-	x25_channel_t *chan;
-	unsigned char old_state;
-
-	if (card->u.x.logging){
-		printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "
-		"Diagn:0x%02X\n",
-		card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn);
-	}
-
-	if (dev == NULL){ 
-		printk(KERN_INFO "%s: X.25 clear request : No device for clear\n",
-				card->devname);
-		return 1;
-	}
-
-	chan=dev->priv;
-
-	old_state = chan->common.state;
-
-	set_chan_state(dev, WAN_DISCONNECTED);
-
-	if (chan->common.usedby == API){
-
-		switch (old_state){
-		
-		case WAN_CONNECTING:
-			send_delayed_cmd_result(card,dev,mb);
-			break;
-		case WAN_CONNECTED:
-			send_oob_msg(card,dev,mb);				
-			break;
-		}
-	}
-	
-	return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1;
-}
-
-/*====================================================================
- * 	Handle X.25 restart event.
- *====================================================================*/
-
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
-	struct wan_device* wandev = &card->wandev;
-	struct net_device* dev;
-	x25_channel_t *chan;
-	unsigned char old_state;
-
-	printk(KERN_INFO
-		"%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",
-		card->devname, mb->cmd.cause, mb->cmd.diagn);
-
-	/* down all logical channels */
-	for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) {
-		chan=dev->priv;
-		old_state = chan->common.state;
-
-		set_chan_state(dev, WAN_DISCONNECTED);
-
-		if (chan->common.usedby == API){
-			switch (old_state){
-		
-			case WAN_CONNECTING:
-				send_delayed_cmd_result(card,dev,mb);
-				break;
-			case WAN_CONNECTED:
-				send_oob_msg(card,dev,mb);				
-				break;
-			}
-		}
-	}
-	return (cmd == X25_WRITE) ? 0 : 1;
-}
-
-/*====================================================================
- * Handle timeout event.
- *====================================================================*/
-
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
-	unsigned new_lcn = mb->cmd.lcn;
-
-	if (mb->cmd.pktType == 0x05)	/* call request time out */
-	{
-		struct net_device* dev = find_channel(card,new_lcn);
-
-		printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",
-			card->devname, new_lcn);
-
-		if (dev){
-			x25_channel_t *chan = dev->priv;
-			set_chan_state(dev, WAN_DISCONNECTED);
-
-			if (chan->common.usedby == API){
-				send_delayed_cmd_result(card,dev,card->mbox);
-			}
-		}
-	}else{ 
-		printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n",
-		card->devname, mb->cmd.pktType, new_lcn);
-	}
-	return 1;
-}
-
-/* 
- *	Miscellaneous 
- */
-
-/*====================================================================
- * 	Establish physical connection.
- * 	o open HDLC and raise DTR
- *
- * 	Return:		0	connection established
- *			1	connection is in progress
- *			<0	error
- *===================================================================*/
-
-static int connect (sdla_t* card)
-{
-	TX25Status* status = card->flags;
-
-	if (x25_open_hdlc(card) || x25_setup_hdlc(card))
-		return -EIO;
-
-	wanpipe_set_state(card, WAN_CONNECTING);
-
-	x25_set_intr_mode(card, INTR_ON_TIMER); 
-	status->imask &= ~INTR_ON_TIMER;
-
-	return 1;
-}
-
-/*
- * 	Tear down physical connection.
- * 	o close HDLC link
- * 	o drop DTR
- *
- * 	Return:		0
- *			<0	error
- */
-
-static int disconnect (sdla_t* card)
-{
-	wanpipe_set_state(card, WAN_DISCONNECTED);
-	x25_set_intr_mode(card, INTR_ON_TIMER);	/* disable all interrupt except timer */
-	x25_close_hdlc(card);			/* close HDLC link */
-	x25_set_dtr(card, 0);			/* drop DTR */
-	return 0;
-}
-
-/*
- * Find network device by its channel number.
- */
-
-static struct net_device* get_dev_by_lcn(struct wan_device* wandev,
-					 unsigned lcn)
-{
-	struct net_device* dev;
-
-	for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv))
-		if (((x25_channel_t*)dev->priv)->common.lcn == lcn) 
-			break;
-	return dev;
-}
-
-/*
- * 	Initiate connection on the logical channel.
- * 	o for PVC we just get channel configuration
- * 	o for SVCs place an X.25 call
- *
- * 	Return:		0	connected
- *			>0	connection in progress
- *			<0	failure
- */
-
-static int chan_connect(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-
-	if (chan->common.svc && chan->common.usedby == WANPIPE){
-		if (!chan->addr[0]){
-			printk(KERN_INFO "%s: No Destination Address\n",
-					card->devname);
-			return -EINVAL;	/* no destination address */
-		}
-		printk(KERN_INFO "%s: placing X.25 call to %s ...\n",
-			card->devname, chan->addr);
-
-		if (x25_place_call(card, chan) != CMD_OK)
-			return -EIO;
-
-		set_chan_state(dev, WAN_CONNECTING);
-		return 1;
-	}else{
-		if (x25_get_chan_conf(card, chan) != CMD_OK)
-			return -EIO;
-
-		set_chan_state(dev, WAN_CONNECTED);
-	}
-	return 0;
-}
-
-/*
- * 	Disconnect logical channel.
- * 	o if SVC then clear X.25 call
- */
-
-static int chan_disc(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-
-	if (chan->common.svc){ 
-		x25_clear_call(chan->card, chan->common.lcn, 0, 0);
-
-		/* For API we disconnect on clear
-                 * confirmation. 
-                 */
-		if (chan->common.usedby == API)
-			return 0;
-	}
-
-	set_chan_state(dev, WAN_DISCONNECTED);
-	
-	return 0;
-}
-
-/*
- * 	Set logical channel state.
- */
-
-static void set_chan_state(struct net_device* dev, int state)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	if (chan->common.state != state)
-	{
-		switch (state)
-		{
-			case WAN_CONNECTED:
-				if (card->u.x.logging){
-					printk (KERN_INFO 
-						"%s: interface %s connected, lcn %i !\n", 
-						card->devname, dev->name,chan->common.lcn);
-				}
-				*(unsigned short*)dev->dev_addr = htons(chan->common.lcn);
-				chan->i_timeout_sofar = jiffies;
-
-				/* LAPB is PVC Based */
-				if (card->u.x.LAPB_hdlc)
-					chan->common.svc=0;
-				break;
-
-			case WAN_CONNECTING:
-				if (card->u.x.logging){
-					printk (KERN_INFO 
-						"%s: interface %s connecting, lcn %i ...\n", 
-						card->devname, dev->name, chan->common.lcn);
-				}
-				break;
-
-			case WAN_DISCONNECTED:
-				if (card->u.x.logging){
-					printk (KERN_INFO 
-						"%s: interface %s disconnected, lcn %i !\n", 
-						card->devname, dev->name,chan->common.lcn);
-				}
-				atomic_set(&chan->common.disconnect,0);
-				
-				if (chan->common.svc) {
-					*(unsigned short*)dev->dev_addr = 0;
-					card->u.x.svc_to_dev_map[(chan->common.lcn%X25_MAX_CHAN)]=NULL;
-		                	chan->common.lcn = 0;
-				}
-
-				if (chan->transmit_length){
-					chan->transmit_length=0;
-					atomic_set(&chan->common.driver_busy,0);
-					chan->tx_offset=0;
-					if (netif_queue_stopped(dev)){
-						netif_wake_queue(dev);
-					}
-				}
-				atomic_set(&chan->common.command,0);
-				break;
-
-			case WAN_DISCONNECTING:
-				if (card->u.x.logging){
-					printk (KERN_INFO 
-					"\n%s: interface %s disconnecting, lcn %i ...\n", 
-					card->devname, dev->name,chan->common.lcn);
-				}
-				atomic_set(&chan->common.disconnect,0);
-				break;
-		}
-		chan->common.state = state;
-	}
-	chan->state_tick = jiffies;
-	restore_flags(flags);
-}
-
-/*
- * 	Send packet on a logical channel.
- *		When this function is called, tx_skb field of the channel data 
- *		space points to the transmit socket buffer.  When transmission 
- *		is complete, release socket buffer and reset 'tbusy' flag.
- *
- * 	Return:		0	- transmission complete
- *			1	- busy
- *
- * 	Notes:
- * 	1. If packet length is greater than MTU for this channel, we'll fragment
- *    	the packet into 'complete sequence' using M-bit.
- * 	2. When transmission is complete, an event notification should be issued
- *    	to the router.
- */
-
-static int chan_send(struct net_device* dev, void* buff, unsigned data_len,
-		     unsigned char tx_intr)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	TX25Status* status = card->flags;
-	unsigned len=0, qdm=0, res=0, orig_len = 0;
-	void *data;
-
-	/* Check to see if channel is ready */
-	if ((!(status->cflags[chan->ch_idx] & 0x40) && !card->u.x.LAPB_hdlc)  || 
-             !(*card->u.x.hdlc_buf_status & 0x40)){ 
-            
-		if (!tx_intr){
-			setup_for_delayed_transmit (dev, buff, data_len);
-			return 0;
-		}else{
-			/* By returning 0 to tx_intr the packet will be dropped */
-			++card->wandev.stats.tx_dropped;
-			++chan->ifstats.tx_dropped;
-			printk(KERN_INFO "%s: ERROR, Tx intr could not send, dropping %s:\n", 
-				card->devname,dev->name);
-			++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
-			return 0;
-		}
-	}
-
-	if (chan->common.usedby == API){
-		/* Remove the API Header */
-		x25api_hdr_t *api_data = (x25api_hdr_t *)buff;
-
-		/* Set the qdm bits from the packet header 
-                 * User has the option to set the qdm bits
-                 */
-		qdm = api_data->qdm;
-
-		orig_len = len = data_len - sizeof(x25api_hdr_t);
-		data = (unsigned char*)buff + sizeof(x25api_hdr_t);
-	}else{
-		data = buff;
-		orig_len = len = data_len;
-	}	
-
-	if (tx_intr){
-		/* We are in tx_intr, minus the tx_offset from 
-                 * the total length. The tx_offset part of the
-		 * data has already been sent. Also, move the 
-		 * data pointer to proper offset location.
-                 */
-		len -= chan->tx_offset;
-		data = (unsigned char*)data + chan->tx_offset;
-	}
-		
-	/* Check if the packet length is greater than MTU
-         * If YES: Cut the len to MTU and set the M bit 
-         */
-	if (len > chan->tx_pkt_size && !card->u.x.LAPB_hdlc){
-		len = chan->tx_pkt_size;
-		qdm |= M_BIT;		
-	} 
-
-
-	/* Pass only first three bits of the qdm byte to the send
-         * routine. In case user sets any other bit which might
-         * cause errors. 
-         */
-
-	switch(x25_send(card, chan->common.lcn, (qdm&0x07), len, data)){
-		case 0x00:	/* success */
-			chan->i_timeout_sofar = jiffies;
-
-			dev->trans_start=jiffies;
-			
-			if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){
-				if (!tx_intr){
-					/* The M bit was set, which means that part of the
-                                         * packet has been sent. Copy the packet into a buffer
-				         * and set the offset to len, so on next tx_inter 
-					 * the packet will be sent using the below offset.
-					 */
-					chan->tx_offset += len;
-
-					++chan->ifstats.tx_packets;
-					chan->ifstats.tx_bytes += len;
-					
-					if (chan->tx_offset < orig_len){
-						setup_for_delayed_transmit (dev, buff, data_len);
-					}
-					res=0;
-				}else{
-					/* We are already in tx_inter, thus data is already
-                                         * in the buffer. Update the offset and wait for
-                                         * next tx_intr. We add on to the offset, since data can
-                                         * be X number of times larger than max data size.
-					 */
-					++chan->ifstats.tx_packets;
-					chan->ifstats.tx_bytes += len;
-					
-					++chan->if_send_stat.if_send_bfr_passed_to_adptr;
-					chan->tx_offset += len;
-
-					/* The user can set the qdm bit as well.
-                                         * If the entire packet was sent and qdm is still
-                                         * set, than it's the user who has set the M bit. In that,
-                                         * case indicate that the packet was send by returning 
-					 * 0 and wait for a new packet. Otherwise, wait for next
-                                         * tx interrupt to send the rest of the packet */
-
-					if (chan->tx_offset < orig_len){
-						res=1;
-					}else{	
-						res=0;
-					}
-				}
-			}else{
-				++chan->ifstats.tx_packets;
-				chan->ifstats.tx_bytes += len;
-				++chan->if_send_stat.if_send_bfr_passed_to_adptr;
-				res=0;
-			}
-			break;
-
-		case 0x33:	/* Tx busy */
-			if (tx_intr){
-				printk(KERN_INFO "%s: Tx_intr: Big Error dropping packet %s\n",
-						card->devname,dev->name);
-				++chan->ifstats.tx_dropped;
-				++card->wandev.stats.tx_dropped;
-				++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
-				res=0;
-			}else{
-				DBG_PRINTK(KERN_INFO 
-					"%s: Send: Big Error should have tx: storring %s\n",
-						card->devname,dev->name);
-				setup_for_delayed_transmit (dev, buff, data_len);	
-				res=1;
-			}
-			break;
-
-		default:	/* failure */
-			++chan->ifstats.tx_errors;
-			if (tx_intr){
-				printk(KERN_INFO "%s: Tx_intr: Failure to send, dropping %s\n",
-					card->devname,dev->name);
-				++chan->ifstats.tx_dropped;
-				++card->wandev.stats.tx_dropped;
-				++chan->if_send_stat.if_send_bfr_not_passed_to_adptr;
-				res=0;
-			}else{
-				DBG_PRINTK(KERN_INFO "%s: Send: Failure to send !!!, storing %s\n",
-					card->devname,dev->name);			
-				setup_for_delayed_transmit (dev, buff, data_len);
-				res=1;
-			}
-			break;	
-	}
-	return res;
-}
-
-
-/*
- * 	Parse X.25 call request data and fill x25_call_info_t structure.
- */
-
-static void parse_call_info (unsigned char* str, x25_call_info_t* info)
-{
-	memset(info, 0, sizeof(x25_call_info_t));
-	for (; *str; ++str)
-	{
-		int i;
-		unsigned char ch;
-
-		if (*str == '-') switch (str[1]) {
-
-			/* Take minus 2 off the maximum size so that 
-                         * last byte is 0. This way we can use string
-                         * manipulaton functions on call information.
-                         */
-
-			case 'd':	/* destination address */
-				for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
-					ch = str[2+i];
-					if (isspace(ch)) break;
-					info->dest[i] = ch;
-				}
-				break;
-
-			case 's':	/* source address */
-				for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){
-					ch = str[2+i];
-					if (isspace(ch)) break;
-					info->src[i] = ch;
-				}
-				break;
-
-			case 'u':	/* user data */
-				for (i = 0; i < (MAX_X25_DATA_SIZE-2); ++i){
-					ch = str[2+i];
-					if (isspace(ch)) break;
-					info->user[i] = ch; 
-				}
-				info->nuser = i;
-				break;
-
-			case 'f':	/* facilities */
-				for (i = 0; i < (MAX_X25_FACL_SIZE-2); ++i){
-					ch = str[2+i];
-					if (isspace(ch)) break;
-					info->facil[i] = ch;
-				}
-				info->nfacil = i;
-				break;
-		}
-	}
-}
-
-/*
- * 	Convert line speed in bps to a number used by S502 code.
- */
-
-static unsigned char bps_to_speed_code (unsigned long bps)
-{
-	unsigned char	number;
-
-	if (bps <= 1200)        number = 0x01;
-	else if (bps <= 2400)   number = 0x02;
-	else if (bps <= 4800)   number = 0x03;
-	else if (bps <= 9600)   number = 0x04;
-	else if (bps <= 19200)  number = 0x05;
-	else if (bps <= 38400)  number = 0x06;
-	else if (bps <= 45000)  number = 0x07;
-	else if (bps <= 56000)  number = 0x08;
-	else if (bps <= 64000)  number = 0x09;
-	else if (bps <= 74000)  number = 0x0A;
-	else if (bps <= 112000) number = 0x0B;
-	else if (bps <= 128000) number = 0x0C;
-	else number = 0x0D;
-
-	return number;
-}
-
-/*
- * 	Convert decimal string to unsigned integer.
- * 	If len != 0 then only 'len' characters of the string are converted.
- */
-
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
-	unsigned val;
-
-	if (!len) 
-		len = strlen(str);
-
-	for (val = 0; len && isdigit(*str); ++str, --len)
-		val = (val * 10) + (*str - (unsigned)'0');
-	
-	return val;
-}
-
-/*
- * 	Convert hex string to unsigned integer.
- * 	If len != 0 then only 'len' characters of the string are conferted.
- */
-
-static unsigned int hex_to_uint (unsigned char* str, int len)
-{
-	unsigned val, ch;
-
-	if (!len) 
-		len = strlen(str);
-
-	for (val = 0; len; ++str, --len)
-	{
-		ch = *str;
-		if (isdigit(ch))
-			val = (val << 4) + (ch - (unsigned)'0');
-		else if (isxdigit(ch))
-			val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
-		else break;
-	}
-	return val;
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
-	int i;
-
-	if( proto == ETH_P_IPX) {
-		/* It's an IPX packet */
-		if(!enable_IPX) {
-			/* Return 1 so we don't pass it up the stack. */
-			return 1;
-		}
-	} else {
-		/* It's not IPX so pass it up the stack.*/ 
-		return 0;
-	}
-
-	if( sendpacket[16] == 0x90 &&
-	    sendpacket[17] == 0x04)
-	{
-		/* It's IPXWAN  */
-
-		if( sendpacket[2] == 0x02 &&
-		    sendpacket[34] == 0x00)
-		{
-			/* It's a timer request packet */
-			printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
-			/* Go through the routing options and answer no to every
-			 * option except Unnumbered RIP/SAP
-			 */
-			for(i = 41; sendpacket[i] == 0x00; i += 5)
-			{
-				/* 0x02 is the option for Unnumbered RIP/SAP */
-				if( sendpacket[i + 4] != 0x02)
-				{
-					sendpacket[i + 1] = 0;
-				}
-			}
-
-			/* Skip over the extended Node ID option */
-			if( sendpacket[i] == 0x04 )
-			{
-				i += 8;
-			}
-
-			/* We also want to turn off all header compression opt. 			 */ 
-			for(; sendpacket[i] == 0x80 ;)
-			{
-				sendpacket[i + 1] = 0;
-				i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
-			}
-
-			/* Set the packet type to timer response */
-			sendpacket[34] = 0x01;
-
-			printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
-		}
-		else if( sendpacket[34] == 0x02 )
-		{
-			/* This is an information request packet */
-			printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
-			/* Set the packet type to information response */
-			sendpacket[34] = 0x03;
-
-			/* Set the router name */
-			sendpacket[51] = 'X';
-			sendpacket[52] = 'T';
-			sendpacket[53] = 'P';
-			sendpacket[54] = 'I';
-			sendpacket[55] = 'P';
-			sendpacket[56] = 'E';
-			sendpacket[57] = '-';
-			sendpacket[58] = CVHexToAscii(network_number >> 28);
-			sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
-			sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
-			sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
-			sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
-			sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
-			sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
-			sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
-			for(i = 66; i < 99; i+= 1)
-			{
-				sendpacket[i] = 0;
-			}
-
-			printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
-		}
-		else
-		{
-			printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
-			return 0;
-		}
-
-		/* Set the WNodeID to our network address */
-		sendpacket[35] = (unsigned char)(network_number >> 24);
-		sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
-		sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
-		sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
-		return 1;
-	} else {
-		/*If we get here it's an IPX-data packet, so it'll get passed up the stack.
-		 */
-		/* switch the network numbers */
-		switch_net_numbers(sendpacket, network_number, 1);	
-		return 0;
-	}
-}
-
-/*
- *  	If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- *  	if incoming is 1 - if the net number is 0 make it ours 
- */
-
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
-	unsigned long pnetwork_number;
-
-	pnetwork_number = (unsigned long)((sendpacket[6] << 24) + 
-			  (sendpacket[7] << 16) + (sendpacket[8] << 8) + 
-			  sendpacket[9]);
-	
-
-	if (!incoming) {
-		/*If the destination network number is ours, make it 0 */
-		if( pnetwork_number == network_number) {
-			sendpacket[6] = sendpacket[7] = sendpacket[8] = 
-					 sendpacket[9] = 0x00;
-		}
-	} else {
-		/* If the incoming network is 0, make it ours */
-		if( pnetwork_number == 0) {
-			sendpacket[6] = (unsigned char)(network_number >> 24);
-			sendpacket[7] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[8] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[9] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-
-
-	pnetwork_number = (unsigned long)((sendpacket[18] << 24) + 
-			  (sendpacket[19] << 16) + (sendpacket[20] << 8) + 
-			  sendpacket[21]);
-	
-	
-	if( !incoming ) {
-		/* If the source network is ours, make it 0 */
-		if( pnetwork_number == network_number) {
-			sendpacket[18] = sendpacket[19] = sendpacket[20] = 
-				 sendpacket[21] = 0x00;
-		}
-	} else {
-		/* If the source network is 0, make it ours */
-		if( pnetwork_number == 0 ) {
-			sendpacket[18] = (unsigned char)(network_number >> 24);
-			sendpacket[19] = (unsigned char)((network_number & 
-					 0x00FF0000) >> 16);
-			sendpacket[20] = (unsigned char)((network_number & 
-					 0x0000FF00) >> 8);
-			sendpacket[21] = (unsigned char)(network_number & 
-					 0x000000FF);
-		}
-	}
-} /* switch_net_numbers */
-
-
-
-
-/********************* X25API SPECIFIC FUNCTIONS ****************/
-
-
-/*===============================================================
- *  find_channel
- *
- *	Manages the lcn to device map. It increases performance
- *      because it eliminates the need to search through the link  
- *      list for a device which is bounded to a specific lcn.
- *
- *===============================================================*/
-
-
-struct net_device *find_channel(sdla_t *card, unsigned lcn)
-{
-	if (card->u.x.LAPB_hdlc){
-
-		return card->wandev.dev;
-
-	}else{
-		/* We don't know whether the incoming lcn
-                 * is a PVC or an SVC channel. But we do know that
-                 * the lcn cannot be for both the PVC and the SVC
-                 * channel.
-
-		 * If the lcn number is greater or equal to 255, 
-                 * take the modulo 255 of that number. We only have
-                 * 255 locations, thus higher numbers must be mapped
-                 * to a number between 0 and 245. 
-
-		 * We must separate pvc's and svc's since two don't
-                 * have to be contiguous.  Meaning pvc's can start
-                 * from 1 to 10 and svc's can start from 256 to 266.
-                 * But 256%255 is 1, i.e. CONFLICT.
-		 */
-
-
-		/* Highest LCN number must be less or equal to 4096 */
-		if ((lcn <= MAX_LCN_NUM) && (lcn > 0)){
-
-			if (lcn < X25_MAX_CHAN){
-				if (card->u.x.svc_to_dev_map[lcn])
-					return card->u.x.svc_to_dev_map[lcn];
-
-				if (card->u.x.pvc_to_dev_map[lcn])
-					return card->u.x.pvc_to_dev_map[lcn];
-			
-			}else{
-				int new_lcn = lcn%X25_MAX_CHAN;
-				if (card->u.x.svc_to_dev_map[new_lcn])
-					return card->u.x.svc_to_dev_map[new_lcn];
-
-				if (card->u.x.pvc_to_dev_map[new_lcn])
-					return card->u.x.pvc_to_dev_map[new_lcn];
-			}
-		}
-		return NULL;
-	}
-}
-
-void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn)
-{
-	x25_channel_t *chan = dev->priv;
-
-	/* Modulo the lcn number by X25_MAX_CHAN (255)
-	 * because the lcn number can be greater than 255 
-         *
-	 * We need to split svc and pvc since they don't have
-         * to be contigous. 
-	 */
-
-	if (chan->common.svc){
-		card->u.x.svc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
-	}else{
-		card->u.x.pvc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev;
-	}
-	chan->common.lcn = lcn;
-}
-
-
-
-/*===============================================================
- * x25api_bh 
- *
- *
- *==============================================================*/
-
-static void x25api_bh(struct net_device* dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t* card = chan->card;
-	struct sk_buff *skb;
-
-	if (atomic_read(&chan->bh_buff_used) == 0){
-		printk(KERN_INFO "%s: BH Buffer Empty in BH\n",
-				card->devname);
-		clear_bit(0, &chan->tq_working);
-		return;
-	}
-
-	while (atomic_read(&chan->bh_buff_used)){
-
-		/* If the sock is in the process of unlinking the
-		 * driver from the socket, we must get out. 
-		 * This never happends but is a sanity check. */
-		if (test_bit(0,&chan->common.common_critical)){
-			clear_bit(0, &chan->tq_working);
-			return;
-		}
-		
-		/* If LAPB HDLC, do not drop packets if socket is
-                 * not connected.  Let the buffer fill up and
-                 * turn off rx interrupt */
-		if (card->u.x.LAPB_hdlc){
-			if (chan->common.sk == NULL || chan->common.func == NULL){
-				clear_bit(0, &chan->tq_working);			
-				return;
-			}
-		}
-
-		skb  = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;
-
-		if (skb == NULL){
-			printk(KERN_INFO "%s: BH Skb empty for read %i\n",
-					card->devname,chan->bh_read);
-		}else{
-			
-			if (chan->common.sk == NULL || chan->common.func == NULL){
-				printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n",
-						card->devname);
-				dev_kfree_skb_any(skb);
-				x25api_bh_cleanup(dev);
-				++chan->ifstats.rx_dropped;
-				++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;
-				continue;
-			}
-
-
-			if (chan->common.func(skb,dev,chan->common.sk) != 0){
-				/* Sock full cannot send, queue us for another
-                                 * try 
-				 */
-				printk(KERN_INFO "%s: BH: !!! Packet failed to send !!!!! \n",
-						card->devname);
-				atomic_set(&chan->common.receive_block,1);
-				return;
-			}else{
-				x25api_bh_cleanup(dev);
-				++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;
-			}
-		}
-	}	
-	clear_bit(0, &chan->tq_working);
-
-	return;
-}
-
-/*===============================================================
- * x25api_bh_cleanup 
- *
- *
- *==============================================================*/
-
-static int x25api_bh_cleanup(struct net_device *dev)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	TX25Status* status = card->flags;
-
-
-	((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;
-
-	if (chan->bh_read == MAX_BH_BUFF){
-		chan->bh_read=0;
-	}else{
-		++chan->bh_read;	
-	}
-
-	/* If the Receive interrupt was off, it means
-         * that we filled up our circular buffer. Check    
-         * that we have space in the buffer. If so 
-         * turn the RX interrupt back on. 
-	 */
-	if (!(status->imask & INTR_ON_RX_FRAME)){
-		if (atomic_read(&chan->bh_buff_used) < (MAX_BH_BUFF+1)){
-			printk(KERN_INFO "%s: BH: Turning on the interrupt\n",
-					card->devname);
-			status->imask |= INTR_ON_RX_FRAME;
-		}
-	}	
-
-	atomic_dec(&chan->bh_buff_used);
-	return 0;
-}
-
-
-/*===============================================================
- * bh_enqueue 
- *
- *
- *==============================================================*/
-
-static int bh_enqueue(struct net_device *dev, struct sk_buff *skb)
-{
-	x25_channel_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	TX25Status* status = card->flags;
-
-	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
-		printk(KERN_INFO "%s: Bottom half buffer FULL\n",
-				card->devname);
-		return 1; 
-	}
-
-	((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;
-
-	if (chan->bh_write == MAX_BH_BUFF){
-		chan->bh_write=0;
-	}else{
-		++chan->bh_write;
-	}
-
-	atomic_inc(&chan->bh_buff_used);
-
-	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){
-		printk(KERN_INFO "%s: Buffer is now full, Turning off RX Intr\n",
-				card->devname);
-		status->imask &= ~INTR_ON_RX_FRAME;
-	}
-
-	return 0;
-}
-
-
-/*===============================================================
- * timer_intr_cmd_exec
- *  
- *	Called by timer interrupt to execute a command
- *===============================================================*/
-
-static int timer_intr_cmd_exec (sdla_t* card)
-{
-	struct net_device *dev;
-	unsigned char more_to_exec=0;
-	volatile x25_channel_t *chan=NULL;
-	int i=0,bad_cmd=0,err=0;	
-
-	if (card->u.x.cmd_dev == NULL){
-		card->u.x.cmd_dev = card->wandev.dev;
-	}
-
-	dev = card->u.x.cmd_dev;
-
-	for (;;){
-
-		chan = dev->priv;
-		
-		if (atomic_read(&chan->common.command)){ 
-
-			bad_cmd = check_bad_command(card,dev);
-
-			if ((!chan->common.mbox || atomic_read(&chan->common.disconnect)) && 
-			     !bad_cmd){
-
-				/* Socket has died or exited, We must bring the
-                                 * channel down before anybody else tries to 
-                                 * use it */
-				err = channel_disconnect(card,dev);
-			}else{
-			        err = execute_delayed_cmd(card, dev,
-							 (mbox_cmd_t*)chan->common.mbox,
-							  bad_cmd);
-			}
-
-			switch (err){
-
-			case RETURN_RESULT:
-
-				/* Return the result to the socket without
-                                 * delay. NO_WAIT Command */	
-				atomic_set(&chan->common.command,0);
-				if (atomic_read(&card->u.x.command_busy))
-					atomic_set(&card->u.x.command_busy,0);
-
-				send_delayed_cmd_result(card,dev,card->mbox);
-
-				more_to_exec=0;
-				break;
-			case DELAY_RESULT:
-		
-				/* Wait for the remote to respond, before
-                                 * sending the result up to the socket.
-                                 * WAIT command */
-				if (atomic_read(&card->u.x.command_busy))
-					atomic_set(&card->u.x.command_busy,0);
-				
-				atomic_set(&chan->common.command,0);
-				more_to_exec=0;
-				break;
-			default:
-
-				/* If command could not be executed for
-                                 * some reason (i.e return code 0x33 busy)
-                                 * set the more_to_exec bit which will
-                                 * indicate that this command must be exectued
-                                 * again during next timer interrupt 
-				 */
-				more_to_exec=1;
-				if (atomic_read(&card->u.x.command_busy) == 0)
-					atomic_set(&card->u.x.command_busy,1);
-				break;
-			}
-
-			bad_cmd=0;
-
-			/* If flags is set, there are no hdlc buffers,
-                         * thus, wait for the next pass and try the
-                         * same command again. Otherwise, start searching 
-                         * from next device on the next pass. 
-			 */
-			if (!more_to_exec){
-				dev = move_dev_to_next(card,dev);
-			}
-			break;
-		}else{
-			/* This device has nothing to execute,
-                         * go to next. 
-			 */
-			if (atomic_read(&card->u.x.command_busy))
-					atomic_set(&card->u.x.command_busy,0);
-			dev = move_dev_to_next(card,dev);
-		}	
-
-		if (++i == card->u.x.no_dev){
-			if (!more_to_exec){
-				DBG_PRINTK(KERN_INFO "%s: Nothing to execute in Timer\n",
-					card->devname);
-				if (atomic_read(&card->u.x.command_busy)){
-					atomic_set(&card->u.x.command_busy,0);
-				}
-			}
-			break;
-		}
-
-	} //End of FOR
-
-	card->u.x.cmd_dev = dev;
-	
-	if (more_to_exec){
-		/* If more commands are pending, do not turn off timer 
-                 * interrupt */
-		return 1;
-	}else{
-		/* No more commands, turn off timer interrupt */
-		return 0;
-	}	
-}
-
-/*===============================================================
- * execute_delayed_cmd 
- *
- *	Execute an API command which was passed down from the
- *      sock.  Sock is very limited in which commands it can
- *      execute.  Wait and No Wait commands are supported.  
- *      Place Call, Clear Call and Reset wait commands, where
- *      Accept Call is a no_wait command.
- *
- *===============================================================*/
-
-static int execute_delayed_cmd(sdla_t* card, struct net_device *dev,
-			       mbox_cmd_t *usr_cmd, char bad_cmd)
-{
-	TX25Mbox* mbox = card->mbox;
-	int err;
-	x25_channel_t *chan = dev->priv;
-	int delay=RETURN_RESULT;
-
-	if (!(*card->u.x.hdlc_buf_status & 0x40) && !bad_cmd){
-		return TRY_CMD_AGAIN;
-	}
-
-	/* This way a command is guaranteed to be executed for
-         * a specific lcn, the network interface is bound to. */
-	usr_cmd->cmd.lcn = chan->common.lcn;
-	
-
-	/* If channel is pvc, instead of place call
-         * run x25_channel configuration. If running LAPB HDLC
-         * enable communications. 
-         */
-	if ((!chan->common.svc) && (usr_cmd->cmd.command == X25_PLACE_CALL)){
-
-		if (card->u.x.LAPB_hdlc){
-			DBG_PRINTK(KERN_INFO "LAPB: Connecting\n");
-			connect(card);
-			set_chan_state(dev,WAN_CONNECTING);
-			return DELAY_RESULT;
-		}else{
-			DBG_PRINTK(KERN_INFO "%s: PVC is CONNECTING\n",card->devname);
-			if (x25_get_chan_conf(card, chan) == CMD_OK){
-				set_chan_state(dev, WAN_CONNECTED);
-			}else{ 
-				set_chan_state(dev, WAN_DISCONNECTED);
-			}
-			return RETURN_RESULT;
-		}
-	}
-
-	/* Copy the socket mbox command onto the board */
-
-	memcpy(&mbox->cmd, &usr_cmd->cmd, sizeof(TX25Cmd));
-	if (usr_cmd->cmd.length){
-		memcpy(mbox->data, usr_cmd->data, usr_cmd->cmd.length);
-	}
-
-	/* Check if command is bad. We need to copy the cmd into
-         * the buffer regardless since we return the, mbox to
-         * the user */
-	if (bad_cmd){
-		mbox->cmd.result=0x01;
-		return RETURN_RESULT;
-	}
-
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	if (err != CMD_OK && err != X25RES_NOT_READY)
-		x25_error(card, err, usr_cmd->cmd.command, usr_cmd->cmd.lcn);
-
-	if (mbox->cmd.result == X25RES_NOT_READY){
-		return TRY_CMD_AGAIN;
-	}
-
-	switch (mbox->cmd.command){
-
-	case X25_PLACE_CALL:
-		
-		switch (mbox->cmd.result){
-
-		case CMD_OK:
-
-			/* Check if Place call is a wait command or a 
-               	  	 * no wait command */
-			if (atomic_read(&chan->common.command) & 0x80)
- 				delay=RETURN_RESULT;
-			else
-				delay=DELAY_RESULT;
-		
-
-			DBG_PRINTK(KERN_INFO "\n%s: PLACE CALL Binding dev %s to lcn %i\n",
-					card->devname,dev->name, mbox->cmd.lcn);
-		
-			bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
-			set_chan_state(dev, WAN_CONNECTING);
-			break;
-
-
-		default:
-			delay=RETURN_RESULT;
-			set_chan_state(dev, WAN_DISCONNECTED);
-			break;
-		}
-		break;
-
-	case X25_ACCEPT_CALL: 
-		
-		switch (mbox->cmd.result){
-
-		case CMD_OK:
-
-			DBG_PRINTK(KERN_INFO "\n%s: ACCEPT Binding dev %s to lcn %i\n",
-				card->devname,dev->name,mbox->cmd.lcn);
-
-			bind_lcn_to_dev (card, dev, mbox->cmd.lcn);
-
-			if (x25_get_chan_conf(card, chan) == CMD_OK){
-
-				set_chan_state(dev, WAN_CONNECTED);
-				delay=RETURN_RESULT;
-
-			}else{ 
-				if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
-					/* if clear is successful, wait for clear confirm 
-					 */ 
-					delay=DELAY_RESULT;
-				}else{
-					/* Do not change the state here. If we fail 
-					 * the accept the return code is send up 
-					 *the stack, which will ether retry
-                               	  	 * or clear the call 
-					 */
-					DBG_PRINTK(KERN_INFO 
-						"%s: ACCEPT: STATE MAY BE CURRUPTED 2 !!!!!\n",
-						card->devname);
-					delay=RETURN_RESULT;
-				}
-			}
-			break;
-
-
-		case X25RES_ASYNC_PACKET:
-			delay=TRY_CMD_AGAIN;
-			break;
-
-		default: 
-			DBG_PRINTK(KERN_INFO "%s: ACCEPT FAILED\n",card->devname);
-			if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){
-				delay=DELAY_RESULT;
-			}else{
-				/* Do not change the state here. If we fail the accept. The
-                                 * return code is send up the stack, which will ether retry
-                                 * or clear the call */
-				DBG_PRINTK(KERN_INFO 
-					"%s: ACCEPT: STATE MAY BE CORRUPTED 1 !!!!!\n",
-						card->devname);
-				delay=RETURN_RESULT;
-			}
-		}
-		break;
-
-	case X25_CLEAR_CALL:
-
-		switch (mbox->cmd.result){
-
-		case CMD_OK:
-			DBG_PRINTK(KERN_INFO 
-					"CALL CLEAR OK: Dev %s Mbox Lcn %i  Chan Lcn %i\n",
-					dev->name,mbox->cmd.lcn,chan->common.lcn);
-			set_chan_state(dev, WAN_DISCONNECTING);
-			delay = DELAY_RESULT;
-			break;
-
-		case X25RES_CHANNEL_IN_USE:
-		case X25RES_ASYNC_PACKET:
-			delay = TRY_CMD_AGAIN;
-			break;
-			
-		case X25RES_LINK_NOT_IN_ABM:
-		case X25RES_INVAL_LCN:
-		case X25RES_INVAL_STATE:
-			set_chan_state(dev, WAN_DISCONNECTED);
-			delay = RETURN_RESULT;
-			break;
-		
-		default:
-			/* If command did not execute because of user
-                         * fault, do not change the state. This will
-                         * signal the socket that clear command failed.
-                         * User can retry or close the socket.
-                         * When socket gets killed, it will set the 
-                         * chan->disconnect which will signal
-                         * driver to clear the call */
-			printk(KERN_INFO "%s: Clear Command Failed, Rc %x\n",
-				card->devname,mbox->cmd.command); 
-			delay = RETURN_RESULT;
-		}
-		break;
-	}	
-
-	return delay;
-}
-
-/*===============================================================
- * api_incoming_call 
- *
- *	Pass an incoming call request up the listening
- *      sock.  If the API sock is not listening reject the
- *      call.
- *
- *===============================================================*/
-
-static int api_incoming_call (sdla_t* card, TX25Mbox *mbox, int lcn)
-{
-	struct sk_buff *skb;
-	int len = sizeof(TX25Cmd)+mbox->cmd.length;
-
-	if (alloc_and_init_skb_buf(card, &skb, len)){
-		printk(KERN_INFO "%s: API incoming call, no memory\n",card->devname);
-		return 1;
-	}
-
-	memcpy(skb_put(skb,len),&mbox->cmd,len);
-
-	skb->mac.raw = skb->data;
-	skb->protocol = htons(X25_PROT);
-	skb->pkt_type = WAN_PACKET_ASYNC;
-
-	if (card->func(skb,card->sk) < 0){
-		printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname);
-                dev_kfree_skb_any(skb);
-		return 1;
-	}
-
-	return 0;
-}
-
-/*===============================================================
- * send_delayed_cmd_result
- *
- *	Wait commands like PLEACE CALL or CLEAR CALL must wait
- *      until the result arrives. This function passes
- *      the result to a waiting sock. 
- *
- *===============================================================*/
-static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev,
-				    TX25Mbox* mbox)
-{
-	x25_channel_t *chan = dev->priv;
-	mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
-	struct sk_buff *skb;
-	int len=sizeof(unsigned char);
-
-	atomic_set(&chan->common.command,0);
-
-	/* If the sock is in the process of unlinking the
-	 * driver from the socket, we must get out. 
-	 * This never happends but is a sanity check. */
-	if (test_bit(0,&chan->common.common_critical)){
-		return;
-	}
-
-	if (!usr_cmd || !chan->common.sk || !chan->common.func){
-		DBG_PRINTK(KERN_INFO "Delay result: Sock not bounded sk: %u, func: %u, mbox: %u\n",
-			(unsigned int)chan->common.sk,
-			(unsigned int)chan->common.func,
-			(unsigned int)usr_cmd); 
-		return;
-	}
-
-	memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); 
-	if (mbox->cmd.length > 0){
-		memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
-	}
-
-	if (alloc_and_init_skb_buf(card,&skb,len)){
-		printk(KERN_INFO "Delay result: No sock buffers\n");
-		return;
-	}
-
-	memcpy(skb_put(skb,len),&mbox->cmd.command,len);
-	
-	skb->mac.raw = skb->data;
-	skb->pkt_type = WAN_PACKET_CMD;
-			
-	chan->common.func(skb,dev,chan->common.sk);
-}
-
-/*===============================================================
- * clear_confirm_event
- *
- * 	Pass the clear confirmation event up the sock. The
- *      API will disconnect only after the clear confirmation
- *      has been received. 
- *
- *      Depending on the state, clear confirmation could 
- *      be an OOB event, or a result of an API command.
- *===============================================================*/
-
-static int clear_confirm_event (sdla_t *card, TX25Mbox* mb)
-{
-	struct net_device *dev;
-	x25_channel_t *chan;
-	unsigned char old_state;	
-
-	dev = find_channel(card,mb->cmd.lcn);
-	if (!dev){
-		DBG_PRINTK(KERN_INFO "%s: *** GOT CLEAR BUT NO DEV %i\n",
-				card->devname,mb->cmd.lcn);
-		return 0;
-	}
-
-	chan=dev->priv;
-	DBG_PRINTK(KERN_INFO "%s: GOT CLEAR CONFIRM %s:  Mbox lcn %i  Chan lcn %i\n",
-			card->devname, dev->name, mb->cmd.lcn, chan->common.lcn);
-
-	/* If not API fall through to default. 
-	 * If API, send the result to a waiting
-         * socket.
-	 */
-	
-	old_state = chan->common.state;
-	set_chan_state(dev, WAN_DISCONNECTED);
-
-	if (chan->common.usedby == API){
-		switch (old_state) {
-
-		case WAN_DISCONNECTING:
-		case WAN_CONNECTING:
-			send_delayed_cmd_result(card,dev,mb);
-			break;
-		case WAN_CONNECTED:
-			send_oob_msg(card,dev,mb);
-			break;
-		}
-		return 1;
-	}
-
-	return 0;
-}
-
-/*===============================================================
- * send_oob_msg
- *
- *    Construct an NEM Message and pass it up the connected
- *    sock. If the sock is not bounded discard the NEM.
- *
- *===============================================================*/
-
-static void send_oob_msg(sdla_t *card, struct net_device *dev, TX25Mbox *mbox)
-{
-	x25_channel_t *chan = dev->priv;
-	mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox;
-	struct sk_buff *skb;
-	int len=sizeof(x25api_hdr_t)+mbox->cmd.length;
-	x25api_t *api_hdr;
-
-	/* If the sock is in the process of unlinking the
-	 * driver from the socket, we must get out. 
-	 * This never happends but is a sanity check. */
-	if (test_bit(0,&chan->common.common_critical)){
-		return;
-	}
-
-	if (!usr_cmd || !chan->common.sk || !chan->common.func){
-		DBG_PRINTK(KERN_INFO "OOB MSG: Sock not bounded\n"); 
-		return;
-	}
-
-	memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); 
-	if (mbox->cmd.length > 0){
-		memcpy(usr_cmd->data, mbox->data, mbox->cmd.length);
-	}
-
-	if (alloc_and_init_skb_buf(card,&skb,len)){
-		printk(KERN_INFO "%s: OOB MSG: No sock buffers\n",card->devname);
-		return;
-	}
-
-	api_hdr = (x25api_t*)skb_put(skb,len); 
-	api_hdr->hdr.pktType = mbox->cmd.pktType & 0x7F;
-	api_hdr->hdr.qdm     = mbox->cmd.qdm;
-	api_hdr->hdr.cause   = mbox->cmd.cause;
-	api_hdr->hdr.diagn   = mbox->cmd.diagn;
-	api_hdr->hdr.length  = mbox->cmd.length;
-	api_hdr->hdr.result  = mbox->cmd.result;
-	api_hdr->hdr.lcn     = mbox->cmd.lcn;
-
-	if (mbox->cmd.length > 0){
-		memcpy(api_hdr->data,mbox->data,mbox->cmd.length);
-	}
-	
-	skb->mac.raw = skb->data;
-	skb->pkt_type = WAN_PACKET_ERR;
-			
-	if (chan->common.func(skb,dev,chan->common.sk) < 0){
-		if (bh_enqueue(dev,skb)){
-			printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname);
-                	dev_kfree_skb_any(skb);
-		}
-	}
-
-	DBG_PRINTK(KERN_INFO "%s: OOB MSG OK, %s, lcn %i\n",
-			card->devname, dev->name, mbox->cmd.lcn);
-}	
-
-/*===============================================================
- *  alloc_and_init_skb_buf 
- *
- *	Allocate and initialize an skb buffer. 
- *
- *===============================================================*/
-
-static int alloc_and_init_skb_buf (sdla_t *card, struct sk_buff **skb, int len)
-{
-	struct sk_buff *new_skb = *skb;
-
-	new_skb = dev_alloc_skb(len + X25_HRDHDR_SZ);
-	if (new_skb == NULL){
-		printk(KERN_INFO "%s: no socket buffers available!\n",
-			card->devname);
-		return 1;
-	}
-
-	if (skb_tailroom(new_skb) < len){
-		/* No room for the packet. Call off the whole thing! */
-                dev_kfree_skb_any(new_skb);
-		printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n"
-			,card->devname);
-		*skb = NULL;
-		return 1;
-	}
-
-	*skb = new_skb;
-	return 0;
-
-}
-
-/*===============================================================
- *  api_oob_event 
- *
- *	Send an OOB event up to the sock 
- *
- *===============================================================*/
-
-static void api_oob_event (sdla_t *card,TX25Mbox *mbox)
-{
-	struct net_device *dev = find_channel(card, mbox->cmd.lcn);
-	x25_channel_t *chan;
-
-	if (!dev)
-		return;
-
-	chan=dev->priv;
-
-	if (chan->common.usedby == API)
-		send_oob_msg(card,dev,mbox);
-	
-}
-
-
-
-
-static int channel_disconnect(sdla_t* card, struct net_device *dev)
-{
-
-	int err;
-	x25_channel_t *chan = dev->priv;
-
-	DBG_PRINTK(KERN_INFO "%s: TIMER: %s, Device down disconnecting\n",
-				card->devname,dev->name);
-
-	if (chan->common.svc){
-		err = x25_clear_call(card,chan->common.lcn,0,0);
-	}else{
-		/* If channel is PVC or LAPB HDLC, there is no call
-                 * to be cleared, thus drop down to the default
-                 * area 
-	         */
-		err = 1;
-	}
-
-	switch (err){
-	
-		case X25RES_CHANNEL_IN_USE:	
-		case X25RES_NOT_READY:
-			err = TRY_CMD_AGAIN;
-			break;
-		case CMD_OK:
-			DBG_PRINTK(KERN_INFO "CALL CLEAR OK: Dev %s Chan Lcn %i\n",
-						dev->name,chan->common.lcn);
-
-			set_chan_state(dev,WAN_DISCONNECTING);
-			atomic_set(&chan->common.command,0);
-			err = DELAY_RESULT;
-			break;
-		default:
-			/* If LAPB HDLC protocol, bring the whole link down
-                         * once the application terminates 
-			 */
-
-			set_chan_state(dev,WAN_DISCONNECTED);
-
-			if (card->u.x.LAPB_hdlc){
-				DBG_PRINTK(KERN_INFO "LAPB: Disconnecting Link\n");
-				hdlc_link_down (card);
-			}
-			atomic_set(&chan->common.command,0);
-			err = RETURN_RESULT;
-			break;
-	}
-
-	return err;
-}
-
-static void hdlc_link_down (sdla_t *card)
-{
-	TX25Mbox* mbox = card->mbox;
-	int retry = 5;
-	int err=0;
-
-	do {
-		memset(mbox,0,sizeof(TX25Mbox));
-		mbox->cmd.command = X25_HDLC_LINK_DISC;
-		mbox->cmd.length = 1;
-		mbox->data[0]=0;
-		err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-
-	} while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_DISC, 0));
-
-	if (err)
-		printk(KERN_INFO "%s: Hdlc Link Down Failed %x\n",card->devname,err);
-
-	disconnect (card);
-	
-}
-
-static int check_bad_command(sdla_t* card, struct net_device *dev)
-{
-	x25_channel_t *chan = dev->priv;
-	int bad_cmd = 0;
-
-	switch (atomic_read(&chan->common.command)&0x7F){
-
-		case X25_PLACE_CALL:
-			if (chan->common.state != WAN_DISCONNECTED)
-				bad_cmd=1;
-			break;
-		case X25_CLEAR_CALL:
-			if (chan->common.state == WAN_DISCONNECTED)
-				bad_cmd=1;
-			break;
-		case X25_ACCEPT_CALL:
-			if (chan->common.state != WAN_CONNECTING)
-				bad_cmd=1;
-			break;
-		case X25_RESET:
-			if (chan->common.state != WAN_CONNECTED)
-				bad_cmd=1;
-			break;
-		default:
-			bad_cmd=1;
-			break;
-	}
-
-	if (bad_cmd){
-		printk(KERN_INFO "%s: Invalid State, BAD Command %x, dev %s, lcn %i, st %i\n", 
-			card->devname,atomic_read(&chan->common.command),dev->name, 
-			chan->common.lcn, chan->common.state);
-	}
-
-	return bad_cmd;
-}
-
-
-
-/*************************** XPIPEMON FUNCTIONS **************************/
-
-/*==============================================================================
- * Process UDP call of type XPIPE
- */
-
-static int process_udp_mgmt_pkt(sdla_t *card)
-{
-	int            c_retry = MAX_CMD_RETRY;
-	unsigned int   len;
-	struct sk_buff *new_skb;
-	TX25Mbox       *mbox = card->mbox;
-	int            err;
-	int            udp_mgmt_req_valid = 1;
-	struct net_device *dev;
-        x25_channel_t  *chan;
-	unsigned short lcn;
-	struct timeval tv;
-	
-
-	x25_udp_pkt_t *x25_udp_pkt;
-	x25_udp_pkt = (x25_udp_pkt_t *)card->u.x.udp_pkt_data;
-
-	dev = card->u.x.udp_dev;
-	chan = dev->priv;
-	lcn = chan->common.lcn;
-
-	switch(x25_udp_pkt->cblock.command) {
-            
-		/* XPIPE_ENABLE_TRACE */
-		case XPIPE_ENABLE_TRACING:
-
-		/* XPIPE_GET_TRACE_INFO */
-		case XPIPE_GET_TRACE_INFO:
- 
-		/* SET FT1 MODE */
-		case XPIPE_SET_FT1_MODE:
-           
-			if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-                    		++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err;
-				udp_mgmt_req_valid = 0;
-				break;
-			}
-
-		/* XPIPE_FT1_READ_STATUS */
-		case XPIPE_FT1_READ_STATUS:
-
-		/* FT1 MONITOR STATUS */
-		case XPIPE_FT1_STATUS_CTRL:
-			if(card->hw.fwid !=  SFID_X25_508) {
-				++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_type_err;
-				udp_mgmt_req_valid = 0;
-				break;
-			}
-		default:
-			break;
-       	}
-
-	if(!udp_mgmt_req_valid) {
-           	/* set length to 0 */
-		x25_udp_pkt->cblock.length = 0;
-		/* set return code */
-		x25_udp_pkt->cblock.result = (card->hw.fwid != SFID_X25_508) ? 0x1F : 0xCD;
-		
-	} else {   
-        
-		switch (x25_udp_pkt->cblock.command) {
-    
-	
-		case XPIPE_FLUSH_DRIVER_STATS:
-			init_x25_channel_struct(chan);
-			init_global_statistics(card);
-			mbox->cmd.length = 0;
-			break;
-
-
-		case XPIPE_DRIVER_STAT_IFSEND:
-			memcpy(x25_udp_pkt->data, &chan->if_send_stat, sizeof(if_send_stat_t));
-			mbox->cmd.length = sizeof(if_send_stat_t);
-			x25_udp_pkt->cblock.length =  mbox->cmd.length;	
-			break;
-	
-		case XPIPE_DRIVER_STAT_INTR:
-			memcpy(&x25_udp_pkt->data[0], &card->statistics, sizeof(global_stats_t));
-                        memcpy(&x25_udp_pkt->data[sizeof(global_stats_t)],
-                                &chan->rx_intr_stat, sizeof(rx_intr_stat_t));
-			
-			mbox->cmd.length = sizeof(global_stats_t) +
-					sizeof(rx_intr_stat_t);
-			x25_udp_pkt->cblock.length =  mbox->cmd.length;
-			break;
-
-		case XPIPE_DRIVER_STAT_GEN:
-                        memcpy(x25_udp_pkt->data,
-                                &chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,
-                                sizeof(pipe_mgmt_stat_t));
-
-                        memcpy(&x25_udp_pkt->data[sizeof(pipe_mgmt_stat_t)],
-                               &card->statistics, sizeof(global_stats_t));
-
-                        x25_udp_pkt->cblock.result = 0;
-                        x25_udp_pkt->cblock.length = sizeof(global_stats_t)+
-                                                     sizeof(rx_intr_stat_t);
-                        mbox->cmd.length = x25_udp_pkt->cblock.length;
-                        break;
-
-		case XPIPE_ROUTER_UP_TIME:
-			do_gettimeofday(&tv);
-			chan->router_up_time = tv.tv_sec - chan->router_start_time;
-    	                *(unsigned long *)&x25_udp_pkt->data = chan->router_up_time;	
-			x25_udp_pkt->cblock.length = mbox->cmd.length = 4;
-			x25_udp_pkt->cblock.result = 0;
-			break;
-	
-		default :
-
-			do {
-				memcpy(&mbox->cmd, &x25_udp_pkt->cblock.command, sizeof(TX25Cmd));
-				if(mbox->cmd.length){ 
-					memcpy(&mbox->data, 
-					       (char *)x25_udp_pkt->data, 
-					       mbox->cmd.length);
-				}	
-		
-				err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-			} while (err && c_retry-- && x25_error(card, err, mbox->cmd.command, 0));
-
-
-			if ( err == CMD_OK || 
-			    (err == 1 && 
-			     (mbox->cmd.command == 0x06 || 
-			      mbox->cmd.command == 0x16)  ) ){
-
-				++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK;
-			} else {
-				++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_timeout;
-			}
-
-			  /* copy the result back to our buffer */
-			memcpy(&x25_udp_pkt->cblock.command, &mbox->cmd, sizeof(TX25Cmd));
-
-      	         	if(mbox->cmd.length) {
-        	               memcpy(&x25_udp_pkt->data, &mbox->data, mbox->cmd.length);
-			}
-			break;
-
-		} //switch
-
-        }
-    
-        /* Fill UDP TTL */
-
-	x25_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
-        len = reply_udp(card->u.x.udp_pkt_data, mbox->cmd.length);
-
-
-        if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-		
-		err = x25_send(card, lcn, 0, len, card->u.x.udp_pkt_data);
-		if (!err) 
-			++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_passed;
-		else
-			++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_failed;
-	
-	} else {
-
-		/* Allocate socket buffer */
-		if((new_skb = dev_alloc_skb(len)) != NULL) {
-			void *buf;
-
-			/* copy data into new_skb */
-			buf = skb_put(new_skb, len);
-			memcpy(buf, card->u.x.udp_pkt_data, len);
-        
-			/* Decapsulate packet and pass it up the protocol 
-			   stack */
-			new_skb->dev = dev;
-	
-			if (chan->common.usedby == API)
-                        	new_skb->protocol = htons(X25_PROT);
-			else 
-				new_skb->protocol = htons(ETH_P_IP);
-	
-                        new_skb->mac.raw = new_skb->data;
-
-			netif_rx(new_skb);
-			++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack;
-            	
-		} else {
-			++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket;
-			printk(KERN_INFO 
-			"%s: UDP mgmt cmnd, no socket buffers available!\n", 
-			card->devname);
-            	}
-        }
-
-	card->u.x.udp_pkt_lgth = 0;
-
-	return 1;
-}
-
-
-/*==============================================================================
- * Determine what type of UDP call it is. DRVSTATS or XPIPE8ND ?
- */
-static int udp_pkt_type( struct sk_buff *skb, sdla_t* card )
-{
-	x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)skb->data;
-
-        if((x25_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
-		(x25_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) &&
-		(x25_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
-		(x25_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-
-                        if(!strncmp(x25_udp_pkt->wp_mgmt.signature,
-                                UDPMGMT_XPIPE_SIGNATURE, 8)){
-                                return UDP_XPIPE_TYPE;
-			}else{
-				printk(KERN_INFO "%s: UDP Packet, Failed Signature !\n",
-					card->devname);
-			}
-	}
-
-        return UDP_INVALID_TYPE;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return nothing.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len ) 
-{
-	unsigned short len, udp_length, temp, ip_length;
-	unsigned long ip_temp;
-	int even_bound = 0;
-
-  
-	x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)data; 
-
-	/* Set length of packet */
-	len = sizeof(ip_pkt_t)+ 
-	      sizeof(udp_pkt_t)+
-	      sizeof(wp_mgmt_t)+
-	      sizeof(cblock_t)+
-	      mbox_len;
- 
-
-	/* fill in UDP reply */
-	x25_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-  
-	/* fill in UDP length */
-	udp_length = sizeof(udp_pkt_t)+ 
-		     sizeof(wp_mgmt_t)+
-		     sizeof(cblock_t)+
-		     mbox_len; 
-
-
-	/* put it on an even boundary */
-	if ( udp_length & 0x0001 ) {
-		udp_length += 1;
-		len += 1;
-		even_bound = 1;
-	}
-
-	temp = (udp_length<<8)|(udp_length>>8);
-	x25_udp_pkt->udp_pkt.udp_length = temp;
-	 
-	/* swap UDP ports */
-	temp = x25_udp_pkt->udp_pkt.udp_src_port;
-	x25_udp_pkt->udp_pkt.udp_src_port = 
-			x25_udp_pkt->udp_pkt.udp_dst_port; 
-	x25_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-
-
-	/* add UDP pseudo header */
-	temp = 0x1100;
-	*((unsigned short *)
-		(x25_udp_pkt->data+mbox_len+even_bound)) = temp;	
-	temp = (udp_length<<8)|(udp_length>>8);
-	*((unsigned short *)
-		(x25_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-		 
-	/* calculate UDP checksum */
-	x25_udp_pkt->udp_pkt.udp_checksum = 0;
-
-	x25_udp_pkt->udp_pkt.udp_checksum = 
-		calc_checksum(&data[UDP_OFFSET], udp_length+UDP_OFFSET);
-
-	/* fill in IP length */
-	ip_length = len;
-	temp = (ip_length<<8)|(ip_length>>8);
-	x25_udp_pkt->ip_pkt.total_length = temp;
-  
-	/* swap IP addresses */
-	ip_temp = x25_udp_pkt->ip_pkt.ip_src_address;
-	x25_udp_pkt->ip_pkt.ip_src_address = 
-				x25_udp_pkt->ip_pkt.ip_dst_address;
-	x25_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-		 
-	/* fill in IP checksum */
-	x25_udp_pkt->ip_pkt.hdr_checksum = 0;
-	x25_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data, sizeof(ip_pkt_t));
-
-	return len;
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
-	unsigned short temp; 
-	unsigned long sum=0;
-	int i;
-
-	for( i = 0; i <len; i+=2 ) {
-		memcpy(&temp,&data[i],2);
-		sum += (unsigned long)temp;
-	}
-
-	while (sum >> 16 ) {
-		sum = (sum & 0xffffUL) + (sum >> 16);
-	}
-
-	temp = (unsigned short)sum;
-	temp = ~temp;
-
-	if( temp == 0 ) 
-		temp = 0xffff;
-
-	return temp;	
-}
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card,
-			      struct net_device *dev, struct sk_buff *skb,
-			      int lcn)
-{
-        int udp_pkt_stored = 0;
-
-        if(!card->u.x.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){
-                card->u.x.udp_pkt_lgth = skb->len;
-                card->u.x.udp_type = udp_type;
-                card->u.x.udp_pkt_src = udp_pkt_src;
-                card->u.x.udp_lcn = lcn;
-		card->u.x.udp_dev = dev;
-                memcpy(card->u.x.udp_pkt_data, skb->data, skb->len);
-                card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UDP_PKT;
-                udp_pkt_stored = 1;
-
-        }else{
-                printk(KERN_INFO "%s: ERROR: UDP packet not stored for LCN %d\n", 
-							card->devname,lcn);
-	}
-
-        if(udp_pkt_src == UDP_PKT_FRM_STACK){
-                dev_kfree_skb_any(skb);
-	}else{
-                dev_kfree_skb_any(skb);
-	}
-
-        return(udp_pkt_stored);
-}
-
-
-
-/*=============================================================================
- * Initial the ppp_private_area structure.
- */
-static void init_x25_channel_struct( x25_channel_t *chan )
-{
-	memset(&chan->if_send_stat.if_send_entry,0,sizeof(if_send_stat_t));
-	memset(&chan->rx_intr_stat.rx_intr_no_socket,0,sizeof(rx_intr_stat_t));
-	memset(&chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,0,sizeof(pipe_mgmt_stat_t));
-}
-
-/*============================================================================
- * Initialize Global Statistics
- */
-static void init_global_statistics( sdla_t *card )
-{
-	memset(&card->statistics.isr_entry,0,sizeof(global_stats_t));
-}
-
-
-/*===============================================================
- * SMP Support
- * ==============================================================*/
-
-static void S508_S514_lock(sdla_t *card, unsigned long *smp_flags)
-{
-	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-}
-static void S508_S514_unlock(sdla_t *card, unsigned long *smp_flags)
-{
-	spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-/*===============================================================
- * x25_timer_routine
- *
- * 	A more efficient polling routine.  Each half a second
- * 	queue a polling task. We want to do the polling in a 
- * 	task not timer, because timer runs in interrupt time.
- *
- * 	FIXME Polling should be rethinked.
- *==============================================================*/
-
-static void x25_timer_routine(unsigned long data)
-{
-	sdla_t *card = (sdla_t*)data;
-
-	if (!card->wandev.dev){
-		printk(KERN_INFO "%s: Stopping the X25 Poll Timer: No Dev.\n",
-				card->devname);
-		return;
-	}
-
-	if (card->open_cnt != card->u.x.num_of_ch){
-		printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Interface down.\n",
-				card->devname);
-		return;
-	}
-
-	if (test_bit(PERI_CRIT,&card->wandev.critical)){
-		printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Shutting down.\n",
-				card->devname);
-		return;
-	}
-	
-	if (!test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
-		trigger_x25_poll(card);
-	}
-	
-	card->u.x.x25_timer.expires=jiffies+(HZ>>1);
-	add_timer(&card->u.x.x25_timer);
-	return;
-}
-
-void disable_comm_shutdown(sdla_t *card)
-{
-	TX25Mbox* mbox = card->mbox;
-	int err;
-
-	/* Turn of interrutps */
-	mbox->data[0] = 0;
-	if (card->hw.fwid == SFID_X25_508){
-		mbox->data[1] = card->hw.irq;
-		mbox->data[2] = 2;
-		mbox->cmd.length = 3;
-	}else {
-	 	mbox->cmd.length  = 1;
-	}
-	mbox->cmd.command = X25_SET_INTERRUPT_MODE;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err)
-		printk(KERN_INFO "INTERRUPT OFF FAIED %x\n",err);
-
-	/* Bring down HDLC */
-	mbox->cmd.command = X25_HDLC_LINK_CLOSE;
-	mbox->cmd.length  = 0;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err)
-		printk(KERN_INFO "LINK CLOSED FAILED %x\n",err);
-
-
-	/* Brind down DTR */
-	mbox->data[0] = 0;
-	mbox->data[2] = 0;
-	mbox->data[1] = 0x01;
-	mbox->cmd.length  = 3;
-	mbox->cmd.command = X25_SET_GLOBAL_VARS;
-	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
-	if (err)
-		printk(KERN_INFO "DTR DOWN FAILED %x\n",err);
-
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
deleted file mode 100644
index 032c0f8..0000000
--- a/drivers/net/wan/sdladrv.c
+++ /dev/null
@@ -1,2314 +0,0 @@
-/*****************************************************************************
-* sdladrv.c	SDLA Support Module.  Main module.
-*
-*		This module is a library of common hardware-specific functions
-*		used by all Sangoma drivers.
-*
-* Author:	Gideon Hack	
-*
-* Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Mar 20, 2001  Nenad Corbic	Added the auto_pci_cfg filed, to support
-*                               the PCISLOT #0. 
-* Apr 04, 2000  Nenad Corbic	Fixed the auto memory detection code.
-*                               The memory test at address 0xC8000.
-* Mar 09, 2000  Nenad Corbic 	Added Gideon's Bug Fix: clear pci
-*                               interrupt flags on initial load.
-* Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.
-*				Updates for Linux 2.2.X kernels.	
-* Sep 17, 1998	Jaspreet Singh	Updates for linux 2.2.X kernels
-* Dec 20, 1996	Gene Kozin	Version 3.0.0. Complete overhaul.
-* Jul 12, 1996	Gene Kozin	Changes for Linux 2.0 compatibility.
-* Jun 12, 1996	Gene Kozin 	Added support for S503 card.
-* Apr 30, 1996	Gene Kozin	SDLA hardware interrupt is acknowledged before
-*				calling protocolspecific ISR.
-*				Register I/O ports with Linux kernel.
-*				Miscellaneous bug fixes.
-* Dec 20, 1995	Gene Kozin	Fixed a bug in interrupt routine.
-* Oct 14, 1995	Gene Kozin	Initial version.
-*****************************************************************************/
-
-/*****************************************************************************
- * Notes:
- * ------
- * 1. This code is ment to be system-independent (as much as possible).  To
- *    achive this, various macros are used to hide system-specific interfaces.
- *    To compile this code, one of the following constants must be defined:
- *
- *	Platform	Define
- *	--------	------
- *	Linux		_LINUX_
- *	SCO Unix	_SCO_UNIX_
- *
- * 2. Supported adapter types:
- *
- *	S502A
- *	ES502A (S502E)
- *	S503
- *	S507
- *	S508 (S509)
- *
- * 3. S502A Notes:
- *
- *	There is no separate DPM window enable/disable control in S502A.  It
- *	opens immediately after a window number it written to the HMCR
- *	register.  To close the window, HMCR has to be written a value
- *	????1111b (e.g. 0x0F or 0xFF).
- *
- *	S502A DPM window cannot be located at offset E000 (e.g. 0xAE000).
- *
- *	There should be a delay of ??? before reading back S502A status
- *	register.
- *
- * 4. S502E Notes:
- *
- *	S502E has a h/w bug: although default IRQ line state is HIGH, enabling
- *	interrupts by setting bit 1 of the control register (BASE) to '1'
- *	causes it to go LOW! Therefore, disabling interrupts by setting that
- *	bit to '0' causes low-to-high transition on IRQ line (ghosty
- *	interrupt). The same occurs when disabling CPU by resetting bit 0 of
- *	CPU control register (BASE+3) - see the next note.
- *
- *	S502E CPU and DPM control is limited:
- *
- *	o CPU cannot be stopped independently. Resetting bit 0 of the CPUi
- *	  control register (BASE+3) shuts the board down entirely, including
- *	  DPM;
- *
- *	o DPM access cannot be controlled dynamically. Ones CPU is started,
- *	  bit 1 of the control register (BASE) is used to enable/disable IRQ,
- *	  so that access to shared memory cannot be disabled while CPU is
- *	  running.
- ****************************************************************************/
-
-#define	_LINUX_
-
-#if	defined(_LINUX_)	/****** Linux *******************************/
-
-#include <linux/config.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/module.h>	/* support for loadable modules */
-#include <linux/jiffies.h>	/* for jiffies, HZ, etc. */
-#include <linux/sdladrv.h>	/* API definitions */
-#include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
-#include <linux/sdlapci.h>	/* SDLA PCI hardware definitions */
-#include <linux/pci.h>		/* PCI defines and function prototypes */
-#include <asm/io.h>		/* for inb(), outb(), etc. */
-
-#define _INB(port)		(inb(port))
-#define _OUTB(port, byte)	(outb((byte),(port)))
-#define	SYSTEM_TICK		jiffies
-
-#include <linux/init.h>
-
-
-#elif	defined(_SCO_UNIX_)	/****** SCO Unix ****************************/
-
-#if	!defined(INKERNEL)
-#error	This code MUST be compiled in kernel mode!
-#endif
-#include <sys/sdladrv.h>	/* API definitions */
-#include <sys/sdlasfm.h>	/* SDLA firmware module definitions */
-#include <sys/inline.h>		/* for inb(), outb(), etc. */
-#define _INB(port)		(inb(port))
-#define _OUTB(port, byte)	(outb((port),(byte)))
-#define	SYSTEM_TICK		lbolt
-
-#else
-#error	Unknown system type!
-#endif
-
-#define	MOD_VERSION	3
-#define	MOD_RELEASE	0
-
-#define	SDLA_IODELAY	100	/* I/O Rd/Wr delay, 10 works for 486DX2-66 */
-#define	EXEC_DELAY	20	/* shared memory access delay, mks */
-#define	EXEC_TIMEOUT	(HZ*2)	/* command timeout, in ticks */
-
-/* I/O port address range */
-#define S502A_IORANGE	3
-#define S502E_IORANGE	4
-#define S503_IORANGE	3
-#define S507_IORANGE	4
-#define S508_IORANGE	4
-
-/* Maximum amount of memory */
-#define S502_MAXMEM	0x10000L
-#define S503_MAXMEM	0x10000L
-#define S507_MAXMEM	0x40000L
-#define S508_MAXMEM	0x40000L
-
-/* Minimum amount of memory */
-#define S502_MINMEM	0x8000L
-#define S503_MINMEM	0x8000L
-#define S507_MINMEM	0x20000L
-#define S508_MINMEM	0x20000L
-#define NO_PORT         -1
-
-
-
-
-
-/****** Function Prototypes *************************************************/
-
-/* Hardware-specific functions */
-static int sdla_detect	(sdlahw_t* hw);
-static int sdla_autodpm	(sdlahw_t* hw);
-static int sdla_setdpm	(sdlahw_t* hw);
-static int sdla_load	(sdlahw_t* hw, sfm_t* sfm, unsigned len);
-static int sdla_init	(sdlahw_t* hw);
-static unsigned long sdla_memtest (sdlahw_t* hw);
-static int sdla_bootcfg	(sdlahw_t* hw, sfm_info_t* sfminfo);
-static unsigned char make_config_byte (sdlahw_t* hw);
-static int sdla_start	(sdlahw_t* hw, unsigned addr);
-
-static int init_s502a	(sdlahw_t* hw);
-static int init_s502e	(sdlahw_t* hw);
-static int init_s503	(sdlahw_t* hw);
-static int init_s507	(sdlahw_t* hw);
-static int init_s508	(sdlahw_t* hw);
-            
-static int detect_s502a	(int port);
-static int detect_s502e	(int port);
-static int detect_s503	(int port);
-static int detect_s507	(int port);
-static int detect_s508	(int port);
-static int detect_s514  (sdlahw_t* hw);
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);
-
-/* Miscellaneous functions */
-static void peek_by_4 (unsigned long src, void* buf, unsigned len);
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len);
-static int calibrate_delay (int mks);
-static int get_option_index (unsigned* optlist, unsigned optval);
-static unsigned check_memregion (void* ptr, unsigned len);
-static unsigned	test_memregion (void* ptr, unsigned len);
-static unsigned short checksum (unsigned char* buf, unsigned len);
-static int init_pci_slot(sdlahw_t *);
-
-static int pci_probe(sdlahw_t *hw);
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-static struct pci_device_id sdladrv_pci_tbl[] = {
-	{ V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
-	{ }			/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-/* private data */
-static char modname[]	= "sdladrv";
-static char fullname[]	= "SDLA Support Module";
-static char copyright[]	= "(c) 1995-1999 Sangoma Technologies Inc.";
-static unsigned	exec_idle;
-
-/* Hardware configuration options.
- * These are arrays of configuration options used by verification routines.
- * The first element of each array is its size (i.e. number of options).
- */
-static unsigned	s502_port_options[] =
-	{ 4, 0x250, 0x300, 0x350, 0x360 }
-;
-static unsigned	s503_port_options[] =
-	{ 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 }
-;
-static unsigned	s508_port_options[] =
-	{ 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 }
-;
-
-static unsigned s502a_irq_options[] = { 0 };
-static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };
-static unsigned s503_irq_options[]  = { 5, 2, 3, 4, 5, 7 };
-static unsigned s508_irq_options[]  = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };
-
-static unsigned s502a_dpmbase_options[] =
-{
-	28,
-	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,
-	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,
-	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,
-	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,
-};
-static unsigned s507_dpmbase_options[] =
-{
-	32,
-	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
-	0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
-	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
-	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-static unsigned s508_dpmbase_options[] =	/* incl. S502E and S503 */
-{
-	32,
-	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
-	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
-	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
-	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
-};
-
-/*
-static unsigned	s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };
-static unsigned	s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };
-static unsigned	s508_dpmsize_options[] = { 1, 0x2000 };
-*/
-
-static unsigned	s502a_pclk_options[] = { 2, 3600, 7200 };
-static unsigned	s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };
-static unsigned	s503_pclk_options[]  = { 3, 7200, 8000, 10000 };
-static unsigned	s507_pclk_options[]  = { 1, 12288 };
-static unsigned	s508_pclk_options[]  = { 1, 16000 };
-
-/* Host memory control register masks */
-static unsigned char s502a_hmcr[] =
-{
-	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C,	/* A0000 - AC000 */
-	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C,	/* C0000 - CC000 */
-	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C,	/* D0000 - DC000 */
-	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C,	/* E0000 - EC000 */
-};
-static unsigned char s502e_hmcr[] =
-{
-	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,	/* A0000 - AE000 */
-	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E,	/* C0000 - CE000 */
-	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* D0000 - DE000 */
-	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E,	/* E0000 - EE000 */
-};
-static unsigned char s507_hmcr[] =
-{
-	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* A0000 - AE000 */
-	0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E,	/* B0000 - BE000 */
-	0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E,	/* C0000 - CE000 */
-	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,	/* E0000 - EE000 */
-};
-static unsigned char s508_hmcr[] =
-{
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* A0000 - AE000 */
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,	/* C0000 - CE000 */
-	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	/* D0000 - DE000 */
-	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,	/* E0000 - EE000 */
-};
-
-static unsigned char s507_irqmask[] =
-{
-	0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0
-};
-
-static int pci_slot_ar[MAX_S514_CARDS];
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o initialize static data
- * o calibrate SDLA shared memory access delay.
- *
- * Return:	0	Ok
- *		< 0	error.
- * Context:	process
- */
-
-static int __init sdladrv_init(void)
-{
-	int i=0;
-
-	printk(KERN_INFO "%s v%u.%u %s\n",
-		fullname, MOD_VERSION, MOD_RELEASE, copyright);
-	exec_idle = calibrate_delay(EXEC_DELAY);
-#ifdef WANDEBUG	
-	printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);
-#endif	
-
-	/* Initialize the PCI Card array, which
-         * will store flags, used to mark 
-         * card initialization state */
-	for (i=0; i<MAX_S514_CARDS; i++)
-		pci_slot_ar[i] = 0xFF;
-
-	return 0;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o release all remaining system resources
- */
-static void __exit sdladrv_cleanup(void)
-{
-}
-
-module_init(sdladrv_init);
-module_exit(sdladrv_cleanup);
-
-/******* Kernel APIs ********************************************************/
-
-/*============================================================================
- * Set up adapter.
- * o detect adapter type
- * o verify hardware configuration options
- * o check for hardware conflicts
- * o set up adapter shared memory
- * o test adapter memory
- * o load firmware
- * Return:	0	ok.
- *		< 0	error
- */
-
-EXPORT_SYMBOL(sdla_setup);
-
-int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
-{
-	unsigned* irq_opt	= NULL;	/* IRQ options */
-	unsigned* dpmbase_opt	= NULL;	/* DPM window base options */
-	unsigned* pclk_opt	= NULL;	/* CPU clock rate options */
-	int err=0;
-
-	if (sdla_detect(hw)) {
-                if(hw->type != SDLA_S514)
-                        printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",
-                        modname, hw->port);
-		return -EINVAL;
-	}
-
-	if(hw->type != SDLA_S514) {
-                printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",
-                modname, hw->type, hw->port);
-
-                hw->dpmsize = SDLA_WINDOWSIZE;
-                switch (hw->type) {
-                case SDLA_S502A:
-                        hw->io_range    = S502A_IORANGE;
-                        irq_opt         = s502a_irq_options;
-                        dpmbase_opt     = s502a_dpmbase_options;
-                        pclk_opt        = s502a_pclk_options;
-                        break;
-
-                case SDLA_S502E:
-                        hw->io_range    = S502E_IORANGE;
-                        irq_opt         = s502e_irq_options;
-                        dpmbase_opt     = s508_dpmbase_options;
-                        pclk_opt        = s502e_pclk_options;
-                        break;
-
-                case SDLA_S503:
-                        hw->io_range    = S503_IORANGE;
-                        irq_opt         = s503_irq_options;
-                        dpmbase_opt     = s508_dpmbase_options;
-                        pclk_opt        = s503_pclk_options;
-                        break;
-
-                case SDLA_S507:
-                        hw->io_range    = S507_IORANGE;
-                        irq_opt         = s508_irq_options;
-                        dpmbase_opt     = s507_dpmbase_options;
-                        pclk_opt        = s507_pclk_options;
-                        break;
-
-                case SDLA_S508:
-                        hw->io_range    = S508_IORANGE;
-                        irq_opt         = s508_irq_options;
-                        dpmbase_opt     = s508_dpmbase_options;
-                        pclk_opt        = s508_pclk_options;
-                        break;
-                }
-
-                /* Verify IRQ configuration options */
-                if (!get_option_index(irq_opt, hw->irq)) {
-                        printk(KERN_INFO "%s: IRQ %d is invalid!\n",
-                        	modname, hw->irq);
-                      return -EINVAL;
-                } 
-
-                /* Verify CPU clock rate configuration options */
-                if (hw->pclk == 0)
-                        hw->pclk = pclk_opt[1];  /* use default */
-        
-                else if (!get_option_index(pclk_opt, hw->pclk)) {
-                        printk(KERN_INFO "%s: CPU clock %u is invalid!\n",
-				modname, hw->pclk);
-                        return -EINVAL;
-                } 
-                printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",
-			modname, hw->pclk);
-
-                /* Setup adapter dual-port memory window and test memory */
-                if (hw->dpmbase == 0) {
-                        err = sdla_autodpm(hw);
-                        if (err) {
-                                printk(KERN_INFO
-				"%s: can't find available memory region!\n",
-					modname);
-                                return err;
-                        }
-                }
-                else if (!get_option_index(dpmbase_opt,
-			virt_to_phys(hw->dpmbase))) {
-                        printk(KERN_INFO
-				"%s: memory address 0x%lX is invalid!\n",
-				modname, virt_to_phys(hw->dpmbase));
-                        return -EINVAL;
-                }               
-                else if (sdla_setdpm(hw)) {
-                        printk(KERN_INFO
-			"%s: 8K memory region at 0x%lX is not available!\n",
-				modname, virt_to_phys(hw->dpmbase));
-                        return -EINVAL;
-                } 
-                printk(KERN_INFO
-			"%s: dual-port memory window is set at 0x%lX.\n",
-				modname, virt_to_phys(hw->dpmbase));
-
-
-		/* If we find memory in 0xE**** Memory region, 
-                 * warn the user to disable the SHADOW RAM.  
-                 * Since memory corruption can occur if SHADOW is
-                 * enabled. This can causes random crashes ! */
-		if (virt_to_phys(hw->dpmbase) >= 0xE0000){
-			printk(KERN_WARNING "\n%s: !!!!!!!!  WARNING !!!!!!!!\n",modname);
-			printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",
-						modname, virt_to_phys(hw->dpmbase));
-			printk(KERN_WARNING "         Please disable the SHADOW RAM, otherwise\n");
-			printk(KERN_WARNING "         your system might crash randomly from time to time !\n");
-			printk(KERN_WARNING "%s: !!!!!!!!  WARNING !!!!!!!!\n\n",modname);
-		}
-        }
-
-	else {
-		hw->memory = test_memregion((void*)hw->dpmbase, 
-			MAX_SIZEOF_S514_MEMORY);
-		if(hw->memory < (256 * 1024)) {
-			printk(KERN_INFO
-				"%s: error in testing S514 memory (0x%lX)\n",
-				modname, hw->memory);
-			sdla_down(hw);
-			return -EINVAL;
-		}
-	}
-    
-	printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",
-		modname, hw->memory / 1024);
-
-	/* Load firmware. If loader fails then shut down adapter */
-	err = sdla_load(hw, sfm, len);
-	if (err) sdla_down(hw);		/* shutdown adapter */
-
-	return err;
-} 
-
-/*============================================================================
- * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
- */
-
-EXPORT_SYMBOL(sdla_down);
-
-int sdla_down (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int i;
-        unsigned char CPU_no;
-        u32 int_config, int_status;
-
-        if(!port && (hw->type != SDLA_S514))
-                return -EFAULT;
-
-	switch (hw->type) {
-	case SDLA_S502A:
-		_OUTB(port, 0x08);		/* halt CPU */
-		_OUTB(port, 0x08);
-		_OUTB(port, 0x08);
-		hw->regs[0] = 0x08;
-		_OUTB(port + 1, 0xFF);		/* close memory window */
-		hw->regs[1] = 0xFF;
-		break;
-
-	case SDLA_S502E:
-		_OUTB(port + 3, 0);		/* stop CPU */
-		_OUTB(port, 0);			/* reset board */
-		for (i = 0; i < S502E_IORANGE; ++i)
-			hw->regs[i] = 0
-		;
-		break;
-
-	case SDLA_S503:
-	case SDLA_S507:
-	case SDLA_S508:
-		_OUTB(port, 0);			/* reset board logic */
-		hw->regs[0] = 0;
-		break;
-
-	case SDLA_S514:
-		/* halt the adapter */
-                *(char *)hw->vector = S514_CPU_HALT;
-        	CPU_no = hw->S514_cpu_no[0];
-
-		/* disable the PCI IRQ and disable memory access */
-                pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
-	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
-                pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);
-		read_S514_int_stat(hw, &int_status);
-		S514_intack(hw, int_status);
-		if(CPU_no == S514_CPU_A)
-                        pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,
-				PCI_CPU_A_MEM_DISABLE);
-		else
-                        pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
-				PCI_CPU_B_MEM_DISABLE);
-
-		/* free up the allocated virtual memory */
- 		iounmap((void *)hw->dpmbase);
-        	iounmap((void *)hw->vector);
- 		break;
-
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*============================================================================
- * Map shared memory window into SDLA address space.
- */
-
-EXPORT_SYMBOL(sdla_mapmem);
-
-int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
-{
-	unsigned port = hw->port;
-	register int tmp;
-
-	switch (hw->type) {
-	case SDLA_S502A:
-	case SDLA_S502E:
-		if (addr < S502_MAXMEM)	{ /* verify parameter */
-			tmp = addr >> 13;	/* convert to register mask */
-			_OUTB(port + 2, tmp);
-			hw->regs[2] = tmp;
-		}
-		else return -EINVAL;
-		break;
-
-	case SDLA_S503:
-		if (addr < S503_MAXMEM)	{ /* verify parameter */
-			tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);
-			_OUTB(port, tmp);
-			hw->regs[0] = tmp;
-		}
-		else return -EINVAL;
-		break;
-
-	case SDLA_S507:
-		if (addr < S507_MAXMEM) {
-			if (!(_INB(port) & 0x02))
-				return -EIO;
-			tmp = addr >> 13;	/* convert to register mask */
-			_OUTB(port + 2, tmp);
-			hw->regs[2] = tmp;
-		}
-		else return -EINVAL;
-		break;
-
-	case SDLA_S508:
-		if (addr < S508_MAXMEM) {
-			tmp = addr >> 13;	/* convert to register mask */
-			_OUTB(port + 2, tmp);
-			hw->regs[2] = tmp;
-		}
-		else return -EINVAL;
-		break;
-
-	case SDLA_S514:
-		return 0;
-
- 	default:
-		return -EINVAL;
-	}
-	hw->vector = addr & 0xFFFFE000L;
-	return 0;
-}
-
-/*============================================================================
- * Enable interrupt generation.
- */
-
-static int sdla_inten (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	switch (hw->type) {
-	case SDLA_S502E:
-		/* Note thar interrupt control operations on S502E are allowed
-		 * only if CPU is enabled (bit 0 of status register is set).
-		 */
-		if (_INB(port) & 0x01) {
-			_OUTB(port, 0x02);	/* bit1 = 1, bit2 = 0 */
-			_OUTB(port, 0x06);	/* bit1 = 1, bit2 = 1 */
-			hw->regs[0] = 0x06;
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S503:
-		tmp = hw->regs[0] | 0x04;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;		/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-		if (!(_INB(port) & 0x02))		/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S508:
-		tmp = hw->regs[0] | 0x10;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;		/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-		if (!(_INB(port + 1) & 0x10))		/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S502A:
-	case SDLA_S507:
-		break;
-
-        case SDLA_S514:
-                break;
-
-	default:
-		return -EINVAL;
-
-	}
-	return 0;
-}
-
-/*============================================================================
- * Disable interrupt generation.
- */
-
-#if 0
-int sdla_intde (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	switch (hw->type) {
-	case SDLA_S502E:
-		/* Notes:
-		 *  1) interrupt control operations are allowed only if CPU is
-		 *     enabled (bit 0 of status register is set).
-		 *  2) disabling interrupts using bit 1 of control register
-		 *     causes IRQ line go high, therefore we are going to use
-		 *     0x04 instead: lower it to inhibit interrupts to PC.
-		 */
-		if (_INB(port) & 0x01) {
-			_OUTB(port, hw->regs[0] & ~0x04);
-			hw->regs[0] &= ~0x04;
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S503:
-		tmp = hw->regs[0] & ~0x04;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;			/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-		if (_INB(port) & 0x02)			/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S508:
-		tmp = hw->regs[0] & ~0x10;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;			/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-		if (_INB(port) & 0x10)			/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S502A:
-	case SDLA_S507:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-#endif  /*  0  */
-
-/*============================================================================
- * Acknowledge SDLA hardware interrupt.
- */
-
-static int sdla_intack (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp;
-
-	switch (hw->type) {
-	case SDLA_S502E:
-		/* To acknoledge hardware interrupt we have to toggle bit 3 of
-		 * control register: \_/
-		 * Note that interrupt control operations on S502E are allowed
-		 * only if CPU is enabled (bit 1 of status register is set).
-		 */
-		if (_INB(port) & 0x01) {
-			tmp = hw->regs[0] & ~0x04;
-			_OUTB(port, tmp);
-			tmp |= 0x04;
-			_OUTB(port, tmp);
-			hw->regs[0] = tmp;
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S503:
-		if (_INB(port) & 0x04) {
-			tmp = hw->regs[0] & ~0x08;
-			_OUTB(port, tmp);
-			tmp |= 0x08;
-			_OUTB(port, tmp);
-			hw->regs[0] = tmp;
-		}
-		break;
-
-	case SDLA_S502A:
-	case SDLA_S507:
-	case SDLA_S508:
-	break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-
-/*============================================================================
- * Acknowledge S514 hardware interrupt.
- */
-
-EXPORT_SYMBOL(S514_intack);
-
-void S514_intack (sdlahw_t* hw, u32 int_status)
-{
-        pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Read the S514 hardware interrupt status.
- */
-
-EXPORT_SYMBOL(read_S514_int_stat);
-
-void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
-{
-	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
-}
-
-
-/*============================================================================
- * Generate an interrupt to adapter's CPU.
- */
-
-#if 0
-int sdla_intr (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-
-	switch (hw->type) {
-	case SDLA_S502A:
-		if (!(_INB(port) & 0x40)) {
-			_OUTB(port, 0x10);		/* issue NMI to CPU */
-			hw->regs[0] = 0x10;
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S507:
-		if ((_INB(port) & 0x06) == 0x06) {
-			_OUTB(port + 3, 0);
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S508:
-		if (_INB(port + 1) & 0x02) {
-			_OUTB(port, 0x08);
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S502E:
-	case SDLA_S503:
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-#endif  /*  0  */
-
-/*============================================================================
- * Execute Adapter Command.
- * o Set exec flag.
- * o Busy-wait until flag is reset.
- * o Return number of loops made, or 0 if command timed out.
- */
-
-EXPORT_SYMBOL(sdla_exec);
-
-int sdla_exec (void* opflag)
-{
-	volatile unsigned char* flag = opflag;
-	unsigned long tstop;
-	int nloops;
-
-	if(readb(flag) != 0x00) {
-		printk(KERN_INFO
-			"WANPIPE: opp flag set on entry to sdla_exec\n");
-		return 0;
-	}
-	
-	writeb(0x01, flag);
-
-	tstop = SYSTEM_TICK + EXEC_TIMEOUT;
-
-	for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {
-		unsigned delay = exec_idle;
-		while (-- delay);			/* delay */
-		if (SYSTEM_TICK > tstop) return 0;	/* time is up! */
-	}
-	return nloops;
-}
-
-/*============================================================================
- * Read absolute adapter memory.
- * Transfer data from adapter's memory to data buffer.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_peek);
-
-int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
-	if (addr + len > hw->memory)	/* verify arguments */
-		return -EINVAL;
-
-        if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */
-                peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
-                return 0;
-	}
-
-        else {				/* copy data for the S508 adapter */
-	        unsigned long oldvec = hw->vector;
-        	unsigned winsize = hw->dpmsize;
-	        unsigned curpos, curlen;   /* current offset and block size */
-        	unsigned long curvec;      /* current DPM window vector */
-	        int err = 0;
-
-                while (len && !err) {
-                        curpos = addr % winsize;  /* current window offset */
-                        curvec = addr - curpos;   /* current window vector */
-                        curlen = (len > (winsize - curpos)) ?
-				(winsize - curpos) : len;
-                        /* Relocate window and copy block of data */
-                        err = sdla_mapmem(hw, curvec);
-                        peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
-				curlen);
-                        addr       += curlen;
-                        buf         = (char*)buf + curlen;
-                        len        -= curlen;
-                }
-
-                /* Restore DPM window position */
-                sdla_mapmem(hw, oldvec);
-                return err;
-        }
-}
-
-
-/*============================================================================
- * Read data from adapter's memory to a data buffer in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void peek_by_4 (unsigned long src, void* buf, unsigned len)
-{
-
-        /* byte copy data until we get to a 4-byte boundary */
-        while (len && (src & 0x03)) {
-                *(char *)buf ++ = readb(src ++);
-                len --;
-        }
-
-        /* copy data in 4-byte chunks */
-        while (len >= 4) {
-                *(unsigned long *)buf = readl(src);
-                buf += 4;
-                src += 4;
-                len -= 4;
-        }
-
-        /* byte copy any remaining data */
-        while (len) {
-                *(char *)buf ++ = readb(src ++);
-                len --;
-        }
-}
-
-
-/*============================================================================
- * Write Absolute Adapter Memory.
- * Transfer data from data buffer to adapter's memory.
- *
- * Note:
- * Care should be taken when crossing dual-port memory window boundary.
- * This function is not atomic, so caller must disable interrupt if
- * interrupt routines are accessing adapter shared memory.
- */
-
-EXPORT_SYMBOL(sdla_poke);
- 
-int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
-{
-
-	if (addr + len > hw->memory)	/* verify arguments */
-		return -EINVAL;
-   
-        if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */
-                poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
-                return 0;
-	}
-	
-	else {				/* copy data for the S508 adapter */
-    		unsigned long oldvec = hw->vector;
-	        unsigned winsize = hw->dpmsize;
-        	unsigned curpos, curlen;     /* current offset and block size */
-        	unsigned long curvec;        /* current DPM window vector */
-        	int err = 0;
-
-		while (len && !err) {
-                        curpos = addr % winsize;    /* current window offset */
-                        curvec = addr - curpos;     /* current window vector */
-                        curlen = (len > (winsize - curpos)) ?
-				(winsize - curpos) : len;
-                        /* Relocate window and copy block of data */
-                        sdla_mapmem(hw, curvec);
-                        poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
-				curlen);
-	                addr       += curlen;
-                        buf         = (char*)buf + curlen;
-                        len        -= curlen;
-                }
-
-                /* Restore DPM window position */
-                sdla_mapmem(hw, oldvec);
-                return err;
-        }
-}
-
-
-/*============================================================================
- * Write from a data buffer to adapter's memory in 4-byte chunks.
- * Note that we ensure that the SDLA memory address is on a 4-byte boundary
- * before we begin moving the data in 4-byte chunks.
-*/
-
-static void poke_by_4 (unsigned long dest, void* buf, unsigned len)
-{
-
-        /* byte copy data until we get to a 4-byte boundary */
-        while (len && (dest & 0x03)) {
-                writeb (*(char *)buf ++, dest ++);
-                len --;
-        }
-
-        /* copy data in 4-byte chunks */
-        while (len >= 4) {
-                writel (*(unsigned long *)buf, dest);
-                dest += 4;
-                buf += 4;
-                len -= 4;
-        }
-
-        /* byte copy any remaining data */
-        while (len) {
-                writeb (*(char *)buf ++ , dest ++);
-                len --;
-        }
-}
-
-
-#ifdef	DONT_COMPIPLE_THIS
-#endif	/* DONT_COMPIPLE_THIS */
-
-/****** Hardware-Specific Functions *****************************************/
-
-/*============================================================================
- * Detect adapter type.
- * o if adapter type is specified then call detection routine for that adapter
- *   type.  Otherwise call detection routines for every adapter types until
- *   adapter is detected.
- *
- * Notes:
- * 1) Detection tests are destructive! Adapter will be left in shutdown state
- *    after the test.
- */
-static int sdla_detect (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int err = 0;
-
-	if (!port && (hw->type != SDLA_S514))
-		return -EFAULT;
-
-    	switch (hw->type) {
-	case SDLA_S502A:
-		if (!detect_s502a(port)) err = -ENODEV;
-		break;
-
-	case SDLA_S502E:
-		if (!detect_s502e(port)) err = -ENODEV;
-		break;
-
-	case SDLA_S503:
-		if (!detect_s503(port)) err = -ENODEV;
-		break;
-
-	case SDLA_S507:
-		if (!detect_s507(port)) err = -ENODEV;
-		break;
-
-	case SDLA_S508:
-		if (!detect_s508(port)) err = -ENODEV;
-		break;
-
-	case SDLA_S514:
-                if (!detect_s514(hw)) err = -ENODEV;
-		break;
-
-	default:
-		if (detect_s502a(port))
-			hw->type = SDLA_S502A;
-		else if (detect_s502e(port))
-			hw->type = SDLA_S502E;
-		else if (detect_s503(port))
-			hw->type = SDLA_S503;
-		else if (detect_s507(port))
-			hw->type = SDLA_S507;
-		else if (detect_s508(port))
-			hw->type = SDLA_S508;
-		else err = -ENODEV;
-	}
-	return err;
-}
-
-/*============================================================================
- * Autoselect memory region. 
- * o try all available DMP address options from the top down until success.
- */
-static int sdla_autodpm (sdlahw_t* hw)
-{
-	int i, err = -EINVAL;
-	unsigned* opt;
-
-	switch (hw->type) {
-	case SDLA_S502A:
-		opt = s502a_dpmbase_options;
-		break;
-
-	case SDLA_S502E:
-	case SDLA_S503:
-	case SDLA_S508:
-		opt = s508_dpmbase_options;
-		break;
-
-	case SDLA_S507:
-		opt = s507_dpmbase_options;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Start testing from 8th position, address
-         * 0xC8000 from the 508 address table. 
-         * We don't want to test A**** addresses, since
-         * they are usually used for Video */
-	for (i = 8; i <= opt[0] && err; i++) {
-		hw->dpmbase = phys_to_virt(opt[i]);
-		err = sdla_setdpm(hw);
-	}
-	return err;
-}
-
-/*============================================================================
- * Set up adapter dual-port memory window. 
- * o shut down adapter
- * o make sure that no physical memory exists in this region, i.e entire
- *   region reads 0xFF and is not writable when adapter is shut down.
- * o initialize adapter hardware
- * o make sure that region is usable with SDLA card, i.e. we can write to it
- *   when adapter is configured.
- */
-static int sdla_setdpm (sdlahw_t* hw)
-{
-	int err;
-
-	/* Shut down card and verify memory region */
-	sdla_down(hw);
-	if (check_memregion(hw->dpmbase, hw->dpmsize))
-		return -EINVAL;
-
-	/* Initialize adapter and test on-board memory segment by segment.
-	 * If memory size appears to be less than shared memory window size,
-	 * assume that memory region is unusable.
-	 */
-	err = sdla_init(hw);
-	if (err) return err;
-
-	if (sdla_memtest(hw) < hw->dpmsize) {	/* less than window size */
-		sdla_down(hw);
-		return -EIO;
-	}
-	sdla_mapmem(hw, 0L);	/* set window vector at bottom */
-	return 0;
-}
-
-/*============================================================================
- * Load adapter from the memory image of the SDLA firmware module. 
- * o verify firmware integrity and compatibility
- * o start adapter up
- */
-static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len)
-{
-
-	int i;
-
-	/* Verify firmware signature */
-	if (strcmp(sfm->signature, SFM_SIGNATURE)) {
-		printk(KERN_INFO "%s: not SDLA firmware!\n",
-			modname);
-		return -EINVAL;
-	}
-
-	/* Verify firmware module format version */
-	if (sfm->version != SFM_VERSION) {
-		printk(KERN_INFO
-			"%s: firmware format %u rejected! Expecting %u.\n",
-			modname, sfm->version, SFM_VERSION);
-		return -EINVAL;
-	}
-
-	/* Verify firmware module length and checksum */
-	if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||
-		(checksum((void*)&sfm->info,
-		sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {
-		printk(KERN_INFO "%s: firmware corrupted!\n", modname);
-		return -EINVAL;
-	}
-
-	/* Announce */
-	printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,
-		(sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",
-		sfm->info.codeid);
-
-	if(hw->type == SDLA_S514)
-		printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",
-			modname, hw->S514_cpu_no[0]);
-
-	/* Scan through the list of compatible adapters and make sure our
-	 * adapter type is listed.
-	 */
-	for (i = 0;
-	     (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);
-	     ++i);
-	
-	if (i == SFM_MAX_SDLA) {
-		printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",
-			modname, hw->type);
-		return -EINVAL;
-	}
-
-
-	/* Make sure there is enough on-board memory */
-	if (hw->memory < sfm->info.memsize) {
-		printk(KERN_INFO
-			"%s: firmware needs %lu bytes of on-board memory!\n",
-			modname, sfm->info.memsize);
-		return -EINVAL;
-	}
-
-	/* Move code onto adapter */
-	if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {
-		printk(KERN_INFO "%s: failed to load code segment!\n",
-			modname);
-		return -EIO;
-	}
-
-	/* Prepare boot-time configuration data and kick-off CPU */
-	sdla_bootcfg(hw, &sfm->info);
-	if (sdla_start(hw, sfm->info.startoffs)) {
-		printk(KERN_INFO "%s: Damn... Adapter won't start!\n",
-			modname);
-		return -EIO;
-	}
-
-	/* position DPM window over the mailbox and enable interrupts */
-        if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {
-		printk(KERN_INFO "%s: adapter hardware failure!\n",
-			modname);
-		return -EIO;
-	}
-	hw->fwid = sfm->info.codeid;		/* set firmware ID */
-	return 0;
-}
-
-/*============================================================================
- * Initialize SDLA hardware: setup memory window, IRQ, etc.
- */
-static int sdla_init (sdlahw_t* hw)
-{
-	int i;
-
-	for (i = 0; i < SDLA_MAXIORANGE; ++i)
-		hw->regs[i] = 0;
-
-	switch (hw->type) {
-	case SDLA_S502A: return init_s502a(hw);
-	case SDLA_S502E: return init_s502e(hw);
-	case SDLA_S503:  return init_s503(hw);
-	case SDLA_S507:  return init_s507(hw);
-	case SDLA_S508:  return init_s508(hw);
-	}
-	return -EINVAL;
-}
-
-/*============================================================================
- * Test adapter on-board memory.
- * o slide DPM window from the bottom up and test adapter memory segment by
- *   segment.
- * Return adapter memory size.
- */
-static unsigned long sdla_memtest (sdlahw_t* hw)
-{
-	unsigned long memsize;
-	unsigned winsize;
-
-	for (memsize = 0, winsize = hw->dpmsize;
-	     !sdla_mapmem(hw, memsize) &&
-		(test_memregion(hw->dpmbase, winsize) == winsize)
-	     ;
-	     memsize += winsize)
-	;
-	hw->memory = memsize;
-	return memsize;
-}
-
-/*============================================================================
- * Prepare boot-time firmware configuration data.
- * o position DPM window
- * o initialize configuration data area
- */
-static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
-{
-	unsigned char* data;
-
-	if (!sfminfo->datasize) return 0;	/* nothing to do */
-
-	if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
-		return -EIO;
-
-	if(hw->type == SDLA_S514)
-                data = (void*)(hw->dpmbase + sfminfo->dataoffs);
-        else
-                data = (void*)((u8 *)hw->dpmbase +
-                        (sfminfo->dataoffs - hw->vector));
-
-	memset_io (data, 0, sfminfo->datasize);
-
-	writeb (make_config_byte(hw), &data[0x00]);
-
-	switch (sfminfo->codeid) {
-	case SFID_X25_502:
-	case SFID_X25_508:
-                writeb (3, &data[0x01]);        /* T1 timer */
-                writeb (10, &data[0x03]);       /* N2 */
-                writeb (7, &data[0x06]);        /* HDLC window size */
-                writeb (1, &data[0x0B]);        /* DTE */
-                writeb (2, &data[0x0C]);        /* X.25 packet window size */
-                writew (128, &data[0x0D]);	/* default X.25 data size */
-                writew (128, &data[0x0F]);	/* maximum X.25 data size */
-		break;
-	}
-	return 0;
-}
-
-/*============================================================================
- * Prepare configuration byte identifying adapter type and CPU clock rate.
- */
-static unsigned char make_config_byte (sdlahw_t* hw)
-{
-	unsigned char byte = 0;
-
-	switch (hw->pclk) {
-		case 5000:  byte = 0x01; break;
-		case 7200:  byte = 0x02; break;
-		case 8000:  byte = 0x03; break;
-		case 10000: byte = 0x04; break;
-		case 16000: byte = 0x05; break;
-	}
-
-	switch (hw->type) {
-		case SDLA_S502E: byte |= 0x80; break;
-		case SDLA_S503:  byte |= 0x40; break;
-	}
-	return byte;
-}
-
-/*============================================================================
- * Start adapter's CPU.
- * o calculate a pointer to adapter's cold boot entry point
- * o position DPM window
- * o place boot instruction (jp addr) at cold boot entry point
- * o start CPU
- */
-static int sdla_start (sdlahw_t* hw, unsigned addr)
-{
-	unsigned port = hw->port;
-	unsigned char *bootp;
-	int err, tmp, i;
-
-	if (!port && (hw->type != SDLA_S514)) return -EFAULT;
-
- 	switch (hw->type) {
-	case SDLA_S502A:
-		bootp = hw->dpmbase;
-		bootp += 0x66;
-		break;
-
-	case SDLA_S502E:
-	case SDLA_S503:
-	case SDLA_S507:
-	case SDLA_S508:
-	case SDLA_S514:
-		bootp = hw->dpmbase;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	err = sdla_mapmem(hw, 0);
-	if (err) return err;
-
-      	writeb (0xC3, bootp);   /* Z80: 'jp' opcode */
-	bootp ++;
-	writew (addr, bootp);
-
-	switch (hw->type) {
-	case SDLA_S502A:
-		_OUTB(port, 0x10);		/* issue NMI to CPU */
-		hw->regs[0] = 0x10;
-		break;
-
-	case SDLA_S502E:
-		_OUTB(port + 3, 0x01);		/* start CPU */
-		hw->regs[3] = 0x01;
-		for (i = 0; i < SDLA_IODELAY; ++i);
-		if (_INB(port) & 0x01) {	/* verify */
-			/*
-			 * Enabling CPU changes functionality of the
-			 * control register, so we have to reset its
-			 * mirror.
-			 */
-			_OUTB(port, 0);		/* disable interrupts */
-			hw->regs[0] = 0;
-		}
-		else return -EIO;
-		break;
-
-	case SDLA_S503:
-		tmp = hw->regs[0] | 0x09;	/* set bits 0 and 3 */
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;		/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);
-		if (!(_INB(port) & 0x01))	/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S507:
-		tmp = hw->regs[0] | 0x02;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;		/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);
-		if (!(_INB(port) & 0x04))	/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S508:
-		tmp = hw->regs[0] | 0x02;
-		_OUTB(port, tmp);
-		hw->regs[0] = tmp;	/* update mirror */
-		for (i = 0; i < SDLA_IODELAY; ++i);
-		if (!(_INB(port + 1) & 0x02))	/* verify */
-			return -EIO;
-		break;
-
-	case SDLA_S514:
-		writeb (S514_CPU_START, hw->vector);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*============================================================================
- * Initialize S502A adapter.
- */
-static int init_s502a (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	if (!detect_s502a(port))
-		return -ENODEV;
-
-	hw->regs[0] = 0x08;
-	hw->regs[1] = 0xFF;
-
-	/* Verify configuration options */
-	i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
-	if (i == 0)
-		return -EINVAL;
-
-	tmp = s502a_hmcr[i - 1];
-	switch (hw->dpmsize) {
-	case 0x2000:
-		tmp |= 0x01;
-		break;
-
-	case 0x10000L:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Setup dual-port memory window (this also enables memory access) */
-	_OUTB(port + 1, tmp);
-	hw->regs[1] = tmp;
-	hw->regs[0] = 0x08;
-	return 0;
-}
-
-/*============================================================================
- * Initialize S502E adapter.
- */
-static int init_s502e (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	if (!detect_s502e(port))
-		return -ENODEV;
-
-	/* Verify configuration options */
-	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
-	if (i == 0)
-		return -EINVAL;
-
-	tmp = s502e_hmcr[i - 1];
-	switch (hw->dpmsize) {
-	case 0x2000:
-		tmp |= 0x01;
-		break;
-
-	case 0x10000L:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Setup dual-port memory window */
-	_OUTB(port + 1, tmp);
-	hw->regs[1] = tmp;
-
-	/* Enable memory access */
-	_OUTB(port, 0x02);
-	hw->regs[0] = 0x02;
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	return (_INB(port) & 0x02) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S503 adapter.
- * ---------------------------------------------------------------------------
- */
-static int init_s503 (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	if (!detect_s503(port))
-		return -ENODEV;
-
-	/* Verify configuration options */
-	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
-	if (i == 0)
-		return -EINVAL;
-
-	tmp = s502e_hmcr[i - 1];
-	switch (hw->dpmsize) {
-	case 0x2000:
-		tmp |= 0x01;
-		break;
-
-	case 0x10000L:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Setup dual-port memory window */
-	_OUTB(port + 1, tmp);
-	hw->regs[1] = tmp;
-
-	/* Enable memory access */
-	_OUTB(port, 0x02);
-	hw->regs[0] = 0x02;	/* update mirror */
-	return 0;
-}
-
-/*============================================================================
- * Initialize S507 adapter.
- */
-static int init_s507 (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	if (!detect_s507(port))
-		return -ENODEV;
-
-	/* Verify configuration options */
-	i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
-	if (i == 0)
-		return -EINVAL;
-
-	tmp = s507_hmcr[i - 1];
-	switch (hw->dpmsize) {
-	case 0x2000:
-		tmp |= 0x01;
-		break;
-
-	case 0x10000L:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Enable adapter's logic */
-	_OUTB(port, 0x01);
-	hw->regs[0] = 0x01;
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (!(_INB(port) & 0x20))
-		return -EIO;
-
-	/* Setup dual-port memory window */
-	_OUTB(port + 1, tmp);
-	hw->regs[1] = tmp;
-
-	/* Enable memory access */
-	tmp = hw->regs[0] | 0x04;
-	if (hw->irq) {
-		i = get_option_index(s508_irq_options, hw->irq);
-		if (i) tmp |= s507_irqmask[i - 1];
-	}
-	_OUTB(port, tmp);
-	hw->regs[0] = tmp;		/* update mirror */
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	return (_INB(port) & 0x08) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Initialize S508 adapter.
- */
-static int init_s508 (sdlahw_t* hw)
-{
-	unsigned port = hw->port;
-	int tmp, i;
-
-	if (!detect_s508(port))
-		return -ENODEV;
-
-	/* Verify configuration options */
-	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
-	if (i == 0)
-		return -EINVAL;
-
-	/* Setup memory configuration */
-	tmp = s508_hmcr[i - 1];
-	_OUTB(port + 1, tmp);
-	hw->regs[1] = tmp;
-
-	/* Enable memory access */
-	_OUTB(port, 0x04);
-	hw->regs[0] = 0x04;		/* update mirror */
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	return (_INB(port + 1) & 0x04) ? 0 : -EIO;
-}
-
-/*============================================================================
- * Detect S502A adapter.
- *	Following tests are used to detect S502A adapter:
- *	1. All registers other than status (BASE) should read 0xFF
- *	2. After writing 00001000b to control register, status register should
- *	   read 01000000b.
- *	3. After writing 0 to control register, status register should still
- *	   read  01000000b.
- *	4. After writing 00000100b to control register, status register should
- *	   read 01000100b.
- *	Return 1 if detected o.k. or 0 if failed.
- *	Note:	This test is destructive! Adapter will be left in shutdown
- *		state after the test.
- */
-static int detect_s502a (int port)
-{
-	int i, j;
-
-	if (!get_option_index(s502_port_options, port))
-		return 0;
-	
-	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
-		if (_INB(port + j) != 0xFF)
-			return 0;
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	}
-
-	_OUTB(port, 0x08);			/* halt CPU */
-	_OUTB(port, 0x08);
-	_OUTB(port, 0x08);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0x40)
-		return 0;
-	_OUTB(port, 0x00);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0x40)
-		return 0;
-	_OUTB(port, 0x04);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0x44)
-		return 0;
-
-	/* Reset adapter */
-	_OUTB(port, 0x08);
-	_OUTB(port, 0x08);
-	_OUTB(port, 0x08);
-	_OUTB(port + 1, 0xFF);
-	return 1;
-}
-
-/*============================================================================
- * Detect S502E adapter.
- *	Following tests are used to verify adapter presence:
- *	1. All registers other than status (BASE) should read 0xFF.
- *	2. After writing 0 to CPU control register (BASE+3), status register
- *	   (BASE) should read 11111000b.
- *	3. After writing 00000100b to port BASE (set bit 2), status register
- *	   (BASE) should read 11111100b.
- *	Return 1 if detected o.k. or 0 if failed.
- *	Note:	This test is destructive! Adapter will be left in shutdown
- *		state after the test.
- */
-static int detect_s502e (int port)
-{
-	int i, j;
-
-	if (!get_option_index(s502_port_options, port))
-		return 0;
-	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
-		if (_INB(port + j) != 0xFF)
-			return 0;
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	}
-
-	_OUTB(port + 3, 0);			/* CPU control reg. */
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0xF8)			/* read status */
-		return 0;
-	_OUTB(port, 0x04);			/* set bit 2 */
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0xFC)			/* verify */
-		return 0;
-
-	/* Reset adapter */
-	_OUTB(port, 0);
-	return 1;
-}
-
-/*============================================================================
- * Detect s503 adapter.
- *	Following tests are used to verify adapter presence:
- *	1. All registers other than status (BASE) should read 0xFF.
- *	2. After writing 0 to control register (BASE), status register (BASE)
- *	   should read 11110000b.
- *	3. After writing 00000100b (set bit 2) to control register (BASE),
- *	   status register should read 11110010b.
- *	Return 1 if detected o.k. or 0 if failed.
- *	Note:	This test is destructive! Adapter will be left in shutdown
- *		state after the test.
- */
-static int detect_s503 (int port)
-{
-	int i, j;
-
-	if (!get_option_index(s503_port_options, port))
-		return 0;
-	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
-		if (_INB(port + j) != 0xFF)
-			return 0;
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	}
-
-	_OUTB(port, 0);				/* reset control reg.*/
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0xF0)			/* read status */
-		return 0;
-	_OUTB(port, 0x04);			/* set bit 2 */
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if (_INB(port) != 0xF2)			/* verify */
-		return 0;
-
-	/* Reset adapter */
-	_OUTB(port, 0);
-	return 1;
-}
-
-/*============================================================================
- * Detect s507 adapter.
- *	Following tests are used to detect s507 adapter:
- *	1. All ports should read the same value.
- *	2. After writing 0x00 to control register, status register should read
- *	   ?011000?b.
- *	3. After writing 0x01 to control register, status register should read
- *	   ?011001?b.
- *	Return 1 if detected o.k. or 0 if failed.
- *	Note:	This test is destructive! Adapter will be left in shutdown
- *		state after the test.
- */
-static int detect_s507 (int port)
-{
-	int tmp, i, j;
-
-	if (!get_option_index(s508_port_options, port))
-		return 0;
-	tmp = _INB(port);
-	for (j = 1; j < S507_IORANGE; ++j) {
-		if (_INB(port + j) != tmp)
-			return 0;
-		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	}
-
-	_OUTB(port, 0x00);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if ((_INB(port) & 0x7E) != 0x30)
-		return 0;
-	_OUTB(port, 0x01);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if ((_INB(port) & 0x7E) != 0x32)
-		return 0;
-
-	/* Reset adapter */
-	_OUTB(port, 0x00);
-	return 1;
-}
-
-/*============================================================================
- * Detect s508 adapter.
- *	Following tests are used to detect s508 adapter:
- *	1. After writing 0x00 to control register, status register should read
- *	   ??000000b.
- *	2. After writing 0x10 to control register, status register should read
- *	   ??010000b
- *	Return 1 if detected o.k. or 0 if failed.
- *	Note:	This test is destructive! Adapter will be left in shutdown
- *		state after the test.
- */
-static int detect_s508 (int port)
-{
-	int i;
-
-	if (!get_option_index(s508_port_options, port))
-		return 0;
-	_OUTB(port, 0x00);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if ((_INB(port + 1) & 0x3F) != 0x00)
-		return 0;
-	_OUTB(port, 0x10);
-	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
-	if ((_INB(port + 1) & 0x3F) != 0x10)
-		return 0;
-
-	/* Reset adapter */
-	_OUTB(port, 0x00);
-	return 1;
-}
-
-/*============================================================================
- * Detect s514 PCI adapter.
- *      Return 1 if detected o.k. or 0 if failed.
- *      Note:   This test is destructive! Adapter will be left in shutdown
- *              state after the test.
- */
-static int detect_s514 (sdlahw_t* hw)
-{
-	unsigned char CPU_no, slot_no, auto_slot_cfg;
-	int number_S514_cards = 0;
-	u32 S514_mem_base_addr = 0;
-	u32 ut_u32;
-	struct pci_dev *pci_dev;
-
-
-#ifndef CONFIG_PCI
-        printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);
-        return 0;
-#endif
-
-	/*
-	The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the
-	slot number defined in 'router.conf' via the 'port' definition.
-	*/
-	CPU_no = hw->S514_cpu_no[0];
-	slot_no = hw->S514_slot_no;
-	auto_slot_cfg = hw->auto_pci_cfg;
-
-	if (auto_slot_cfg){
-		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",
-		modname, CPU_no);
-
-	}else{
-		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",
-		modname, CPU_no, slot_no);
-	}
-	
-	/* check to see that CPU A or B has been selected in 'router.conf' */
-	switch(CPU_no) {
-		case S514_CPU_A:
-		case S514_CPU_B:
-			break;
-	
-		default:
-			printk(KERN_INFO "%s: S514 CPU definition invalid.\n", 
-				modname);
-			printk(KERN_INFO "Must be 'A' or 'B'\n");
-			return 0;
-	}
-
-	number_S514_cards = find_s514_adapter(hw, 0);
-	if(!number_S514_cards)
-		return 0;
-
-	/* we are using a single S514 adapter with a slot of 0 so re-read the */	
-	/* location of this adapter */
-	if((number_S514_cards == 1) && auto_slot_cfg) {	
-        	number_S514_cards = find_s514_adapter(hw, 1);
-		if(!number_S514_cards) {
-			printk(KERN_INFO "%s: Error finding PCI card\n",
-				modname);
-			return 0;
-		}
-	}
-
-	pci_dev = hw->pci_dev;
-	/* read the physical memory base address */
-	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
-		(pci_dev->resource[1].start) :
-		(pci_dev->resource[2].start);
-	
-	printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
-		modname, S514_mem_base_addr);
-	if(!S514_mem_base_addr) {
-		if(CPU_no == S514_CPU_B)
-			printk(KERN_INFO "%s: CPU #B not present on the card\n", 				modname);
-		else
-			printk(KERN_INFO "%s: No PCI memory allocated to card\n",				modname);
-		return 0;
-	}
-
-	/* enable the PCI memory */
-	pci_read_config_dword(pci_dev, 
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		&ut_u32);
-	pci_write_config_dword(pci_dev,
-		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
-		(ut_u32 | PCI_MEMORY_ENABLE));
-
-	/* check the IRQ allocated and enable IRQ usage */
-	if(!(hw->irq = pci_dev->irq)) {
-		printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
-			modname);
-                return 0;
-	}
-
-	/* BUG FIX : Mar 6 2000
- 	 * On a initial loading of the card, we must check
-         * and clear PCI interrupt bits, due to a reset
-         * problem on some other boards.  i.e. An interrupt
-         * might be pending, even after system bootup, 
-         * in which case, when starting wanrouter the machine
-         * would crash. 
-	 */
-	if (init_pci_slot(hw))
-		return 0;
-
-        pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);
-        ut_u32 |= (CPU_no == S514_CPU_A) ?
-                PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
-        pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
-
-	printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
-		modname, hw->irq);
-
-	/* map the physical PCI memory to virtual memory */
-	hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
-		(unsigned long)MAX_SIZEOF_S514_MEMORY);
-    	/* map the physical control register memory to virtual memory */
-	hw->vector = (unsigned long)ioremap(
-		(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
-		(unsigned long)16);
-     
-        if(!hw->dpmbase || !hw->vector) {
-		printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",
-			modname);
-                return 0;
-	}
-
-	/* halt the adapter */
-	writeb (S514_CPU_HALT, hw->vector);	
-
-	return 1;
-}
-
-/*============================================================================
- * Find the S514 PCI adapter in the PCI bus.
- *      Return the number of S514 adapters found (0 if no adapter found).
- */
-static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card)
-{
-        unsigned char slot_no;
-        int number_S514_cards = 0;
-	char S514_found_in_slot = 0;
-        u16 PCI_subsys_vendor;
-
-        struct pci_dev *pci_dev = NULL;
- 
-       slot_no = hw->S514_slot_no;
-  
-	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
-        	!= NULL) {
-                
-		pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
-                        &PCI_subsys_vendor);
-                
-		if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                	continue;
-        	
-		hw->pci_dev = pci_dev;
-		
-		if(find_first_S514_card)
-			return(1);
-		
-                number_S514_cards ++;
-                
-		printk(KERN_INFO
-			"%s: S514 card found, slot #%d (devfn 0x%X)\n",
-                        modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
-			pci_dev->devfn);
-		
-		if (hw->auto_pci_cfg){
-			hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);
-			slot_no = hw->S514_slot_no;
-			
-		}else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){
-                        S514_found_in_slot = 1;
-                        break;
-                }
-        }
-
-	/* if no S514 adapter has been found, then exit */
-        if (!number_S514_cards) {
-                printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
-                return 0;
-        }
-        /* if more than one S514 card has been found, then the user must have */        /* defined a slot number so that the correct adapter is used */
-        else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {
-                printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"
-				 "%s:        More than one S514 adapter found.\n"
-				 "%s:        Disable the Autodetect feature and supply\n"
-				 "%s:        the PCISLOT numbers for each card.\n",
-                        modname,modname,modname,modname);
-                return 0;
-        }
-        /* if the user has specified a slot number and the S514 adapter has */
-        /* not been found in that slot, then exit */
-        else if (!hw->auto_pci_cfg && !S514_found_in_slot) {
-                printk(KERN_INFO
-			"%s: Error, S514 card not found in specified slot #%d\n",
-                        modname, slot_no);
-                return 0;
-        }
-
-	return (number_S514_cards);
-}
-
-
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Calibrate SDLA memory access delay.
- * Count number of idle loops made within 1 second and then calculate the
- * number of loops that should be made to achive desired delay.
- */
-static int calibrate_delay (int mks)
-{
-	unsigned int delay;
-	unsigned long stop;
-
-	for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);
-	return (delay/(1000000L/mks) + 1);
-}
-
-/*============================================================================
- * Get option's index into the options list.
- *	Return option's index (1 .. N) or zero if option is invalid.
- */
-static int get_option_index (unsigned* optlist, unsigned optval)
-{
-	int i;
-
-	for (i = 1; i <= optlist[0]; ++i)
-		if ( optlist[i] == optval)
-			return i;
-	return 0;
-}
-
-/*============================================================================
- * Check memory region to see if it's available. 
- * Return:	0	ok.
- */
-static unsigned check_memregion (void* ptr, unsigned len)
-{
-	volatile unsigned char* p = ptr;
-
-        for (; len && (readb (p) == 0xFF); --len, ++p) {
-                writeb (0, p);          /* attempt to write 0 */
-                if (readb(p) != 0xFF) { /* still has to read 0xFF */
-                        writeb (0xFF, p);/* restore original value */
-                        break;          /* not good */
-                }
-        }
-
-	return len;
-}
-
-/*============================================================================
- * Test memory region.
- * Return:	size of the region that passed the test.
- * Note:	Region size must be multiple of 2 !
- */
-static unsigned test_memregion (void* ptr, unsigned len)
-{
-	volatile unsigned short* w_ptr;
-	unsigned len_w = len >> 1;	/* region len in words */
-	unsigned i;
-
-        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
-                writew (0xAA55, w_ptr);
-        
-	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
-                if (readw (w_ptr) != 0xAA55) {
-                        len_w = i;
-                        break;
-                }
-
-        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
-                writew (0x55AA, w_ptr);
-        
-        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
-                if (readw(w_ptr) != 0x55AA) {
-                        len_w = i;
-                        break;
-                }
-        
-        for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
-		writew (0, w_ptr);
-
-        return len_w << 1;
-}
-
-/*============================================================================
- * Calculate 16-bit CRC using CCITT polynomial.
- */
-static unsigned short checksum (unsigned char* buf, unsigned len)
-{
-	unsigned short crc = 0;
-	unsigned mask, flag;
-
-	for (; len; --len, ++buf) {
-		for (mask = 0x80; mask; mask >>= 1) {
-			flag = (crc & 0x8000);
-			crc <<= 1;
-			crc |= ((*buf & mask) ? 1 : 0);
-			if (flag) crc ^= 0x1021;
-		}
-	}
-	return crc;
-}
-
-static int init_pci_slot(sdlahw_t *hw)
-{
-
-	u32 int_status;
-	int volatile found=0;
-	int i=0;
-
-	/* Check if this is a very first load for a specific
-         * pci card. If it is, clear the interrput bits, and
-         * set the flag indicating that this card was initialized.
-	 */
-	
-	for (i=0; (i<MAX_S514_CARDS) && !found; i++){
-		if (pci_slot_ar[i] == hw->S514_slot_no){
-			found=1;
-			break;
-		}
-		if (pci_slot_ar[i] == 0xFF){
-			break;
-		}
-	}
-
-	if (!found){
-		read_S514_int_stat(hw,&int_status);
-		S514_intack(hw,int_status);
-		if (i == MAX_S514_CARDS){
-			printk(KERN_INFO "%s: Critical Error !!!\n",modname);
-			printk(KERN_INFO 
-				"%s: Number of Sangoma PCI cards exceeded maximum limit.\n",
-					modname);
-			printk(KERN_INFO "Please contact Sangoma Technologies\n");
-			return 1;
-		}
-		pci_slot_ar[i] = hw->S514_slot_no;
-	}
-	return 0;
-}
-
-static int pci_probe(sdlahw_t *hw)
-{
-
-        unsigned char slot_no;
-        int number_S514_cards = 0;
-        u16 PCI_subsys_vendor;
-	u16 PCI_card_type;
-
-        struct pci_dev *pci_dev = NULL;
-	struct pci_bus *bus = NULL;
- 
-       slot_no = 0;
-  
-	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
-        	!= NULL) {
-		
-                pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
-                        &PCI_subsys_vendor);
-		
-                if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
-                	continue;
-
-		pci_read_config_word(pci_dev, PCI_CARD_TYPE,
-                        &PCI_card_type);
-	
-		bus = pci_dev->bus;
-		
-		/* A dual cpu card can support up to 4 physical connections,
-		 * where a single cpu card can support up to 2 physical
-		 * connections.  The FT1 card can only support a single 
-		 * connection, however we cannot distinguish between a Single
-		 * CPU card and an FT1 card. */
-		if (PCI_card_type == S514_DUAL_CPU){
-                	number_S514_cards += 4;
-			 printk(KERN_INFO
-				"wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
-                        	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
-				pci_dev->irq);
-		}else{
-			number_S514_cards += 2;
-			printk(KERN_INFO
-				"wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
-                        	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
-				pci_dev->irq);
-		}
-        }
-
-	return number_S514_cards;
-
-}
-
-
-
-EXPORT_SYMBOL(wanpipe_hw_probe);
-
-unsigned wanpipe_hw_probe(void)
-{
-	sdlahw_t hw;
-	unsigned* opt = s508_port_options; 
-	unsigned cardno=0;
-	int i;
-	
-	memset(&hw, 0, sizeof(hw));
-	
-	for (i = 1; i <= opt[0]; i++) {
-		if (detect_s508(opt[i])){
-			/* S508 card can support up to two physical links */
-			cardno+=2;
-			printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);
-		}
-	}
-
-      #ifdef CONFIG_PCI
-	hw.S514_slot_no = 0;
-	cardno += pci_probe(&hw);
-      #else
-	printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");
-	printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");
-      #endif
-
-	return cardno;
-}
-
-/****** End *****************************************************************/
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
deleted file mode 100644
index 7a8b22a..0000000
--- a/drivers/net/wan/sdlamain.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/****************************************************************************
-* sdlamain.c	WANPIPE(tm) Multiprotocol WAN Link Driver.  Main module.
-*
-* Author:	Nenad Corbic	<ncorbic@sangoma.com>
-*		Gideon Hack	
-*
-* Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Dec 22, 2000  Nenad Corbic	Updated for 2.4.X kernels.
-* 				Removed the polling routine.
-* Nov 13, 2000  Nenad Corbic	Added hw probing on module load and dynamic
-* 				device allocation. 
-* Nov 7,  2000  Nenad Corbic	Fixed the Multi-Port PPP for kernels
-*                               2.2.16 and above.
-* Aug 2,  2000  Nenad Corbic	Block the Multi-Port PPP from running on
-*  			        kernels 2.2.16 or greater.  The SyncPPP 
-*  			        has changed.
-* Jul 25, 2000  Nenad Corbic	Updated the Piggiback support for MultPPPP.
-* Jul 13, 2000	Nenad Corbic	Added Multi-PPP support.
-* Feb 02, 2000  Nenad Corbic    Fixed up piggyback probing and selection.
-* Sep 23, 1999  Nenad Corbic    Added support for SMP
-* Sep 13, 1999  Nenad Corbic	Each port is treated as a separate device.
-* Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.
-*				Updates for Linux 2.2.X kernels.
-* Sep 17, 1998	Jaspreet Singh	Updated for 2.1.121+ kernel
-* Nov 28, 1997	Jaspreet Singh	Changed DRV_RELEASE to 1
-* Nov 10, 1997	Jaspreet Singh	Changed sti() to restore_flags();
-* Nov 06, 1997 	Jaspreet Singh	Changed DRV_VERSION to 4 and DRV_RELEASE to 0
-* Oct 20, 1997 	Jaspreet Singh	Modified sdla_isr routine so that card->in_isr
-*				assignments are taken out and placed in the
-*				sdla_ppp.c, sdla_fr.c and sdla_x25.c isr
-*				routines. Took out 'wandev->tx_int_enabled' and
-*				replaced it with 'wandev->enable_tx_int'. 
-* May 29, 1997	Jaspreet Singh	Flow Control Problem
-*				added "wandev->tx_int_enabled=1" line in the
-*				init module. This line initializes the flag for 
-*				preventing Interrupt disabled with device set to
-*				busy
-* Jan 15, 1997	Gene Kozin	Version 3.1.0
-*				 o added UDP management stuff
-* Jan 02, 1997	Gene Kozin	Initial version.
-*****************************************************************************/
-
-#include <linux/config.h>	/* OS configuration options */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/init.h>
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/module.h>	/* support for loadable modules */
-#include <linux/ioport.h>	/* request_region(), release_region() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/rcupdate.h>
-
-#include <linux/in.h>
-#include <asm/io.h>		/* phys_to_virt() */
-#include <linux/pci.h>
-#include <linux/sdlapci.h>
-#include <linux/if_wanpipe_common.h>
-
-#include <asm/uaccess.h>	/* kernel <-> user copy */
-#include <linux/inetdevice.h>
-
-#include <linux/ip.h>
-#include <net/route.h>
- 
-#define KMEM_SAFETYZONE 8
-
-
-#ifndef CONFIG_WANPIPE_FR
-  #define wpf_init(a,b) (-EPROTONOSUPPORT) 
-#endif
-
-#ifndef CONFIG_WANPIPE_CHDLC
- #define wpc_init(a,b) (-EPROTONOSUPPORT) 
-#endif
-
-#ifndef CONFIG_WANPIPE_X25
- #define wpx_init(a,b) (-EPROTONOSUPPORT) 
-#endif
- 
-#ifndef CONFIG_WANPIPE_PPP
- #define wpp_init(a,b) (-EPROTONOSUPPORT) 
-#endif
-
-#ifndef CONFIG_WANPIPE_MULTPPP 
- #define wsppp_init(a,b) (-EPROTONOSUPPORT) 
-#endif
- 
- 
-/***********FOR DEBUGGING PURPOSES*********************************************
-static void * dbg_kmalloc(unsigned int size, int prio, int line) {
-	int i = 0;
-	void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio);
-	char * c1 = v;	
-	c1 += sizeof(unsigned int);
-	*((unsigned int *)v) = size;
-
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D';
-		c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F';
-		c1 += 8;
-	}
-	c1 += size;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G';
-		c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L';
-		c1 += 8;
-	}
-	v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8;
-	printk(KERN_INFO "line %d  kmalloc(%d,%d) = %p\n",line,size,prio,v);
-	return v;
-}
-static void dbg_kfree(void * v, int line) {
-	unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8));
-	unsigned int size = *sp;
-	char * c1 = ((char *)v) - KMEM_SAFETYZONE*8;
-	int i = 0;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		if (   c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D'
-		    || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') {
-			printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v);
-			printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-			                c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-		}
-		c1 += 8;
-	}
-	c1 += size;
-	for (i = 0; i < KMEM_SAFETYZONE; i++) {
-		if (   c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G'
-		    || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L'
-		   ) {
-			printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v);
-			printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8,
-			                c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] );
-		}
-		c1 += 8;
-	}
-	printk(KERN_INFO "line %d  kfree(%p)\n",line,v);
-	v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8);
-	kfree(v);
-}
-
-#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)
-#define kfree(x) dbg_kfree(x,__LINE__)
-******************************************************************************/
-
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef	_DEBUG_
-#define	STATIC
-#else
-#define	STATIC		static
-#endif
-
-#define	DRV_VERSION	5		/* version number */
-#define	DRV_RELEASE	0		/* release (minor version) number */
-#define	MAX_CARDS	16		/* max number of adapters */
-
-#ifndef	CONFIG_WANPIPE_CARDS		/* configurable option */
-#define	CONFIG_WANPIPE_CARDS 1
-#endif
-
-#define	CMD_OK		0		/* normal firmware return code */
-#define	CMD_TIMEOUT	0xFF		/* firmware command timed out */
-#define	MAX_CMD_RETRY	10		/* max number of firmware retries */
-/****** Function Prototypes *************************************************/
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
- 
-/* WAN link driver entry points */
-static int setup(struct wan_device* wandev, wandev_conf_t* conf);
-static int shutdown(struct wan_device* wandev);
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg);
-
-/* IOCTL handlers */
-static int ioctl_dump	(sdla_t* card, sdla_dump_t* u_dump);
-static int ioctl_exec	(sdla_t* card, sdla_exec_t* u_exec, int);
-
-/* Miscellaneous functions */
-STATIC irqreturn_t sdla_isr	(int irq, void* dev_id, struct pt_regs *regs);
-static void release_hw  (sdla_t *card);
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*);
-
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-/* private data */
-static char drvname[]	= "wanpipe";
-static char fullname[]	= "WANPIPE(tm) Multiprotocol Driver";
-static char copyright[]	= "(c) 1995-2000 Sangoma Technologies Inc.";
-static int ncards; 
-static sdla_t* card_array;		/* adapter data space */
-
-/* Wanpipe's own workqueue, used for all API's.
- * All protocol specific tasks will be inserted
- * into the "wanpipe_wq" workqueue. 
-
- * The kernel workqueue mechanism will execute
- * all pending tasks in the "wanpipe_wq" workqueue.
- */
-
-struct workqueue_struct *wanpipe_wq;
-DECLARE_WORK(wanpipe_work, NULL, NULL);
-
-static int wanpipe_bh_critical;
-
-/******* Kernel Loadable Module Entry Points ********************************/
-
-/*============================================================================
- * Module 'insert' entry point.
- * o print announcement
- * o allocate adapter data space
- * o initialize static data
- * o register all cards with WAN router
- * o calibrate SDLA shared memory access delay.
- *
- * Return:	0	Ok
- *		< 0	error.
- * Context:	process
- */
- 
-static int __init wanpipe_init(void)
-{
-	int cnt, err = 0;
-
-	printk(KERN_INFO "%s v%u.%u %s\n",
-		fullname, DRV_VERSION, DRV_RELEASE, copyright);
-
-	wanpipe_wq = create_workqueue("wanpipe_wq");
-	if (!wanpipe_wq)
-		return -ENOMEM;
-
-	/* Probe for wanpipe cards and return the number found */
-	printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n");
-	ncards = wanpipe_hw_probe();
-	if (ncards){
-		printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards);
-	}else{
-		printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n");
-		destroy_workqueue(wanpipe_wq);
-		return -ENODEV;
-	}
-	
-	/* Verify number of cards and allocate adapter data space */
-	card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL);
-	if (card_array == NULL) {
-		destroy_workqueue(wanpipe_wq);
-		return -ENOMEM;
-	}
-
-	memset(card_array, 0, sizeof(sdla_t) * ncards);
-
-	/* Register adapters with WAN router */
-	for (cnt = 0; cnt < ncards; ++ cnt) {
-		sdla_t* card = &card_array[cnt];
-		struct wan_device* wandev = &card->wandev;
-
-		card->next = NULL;
-		sprintf(card->devname, "%s%d", drvname, cnt + 1);
-		wandev->magic    = ROUTER_MAGIC;
-		wandev->name     = card->devname;
-		wandev->private  = card;
-		wandev->enable_tx_int = 0;
-		wandev->setup    = &setup;
-		wandev->shutdown = &shutdown;
-		wandev->ioctl    = &ioctl;
-		err = register_wan_device(wandev);
-		if (err) {
-			printk(KERN_INFO
-				"%s: %s registration failed with error %d!\n",
-				drvname, card->devname, err);
-			break;
-		}
-	}
-	if (cnt){
-		ncards = cnt;	/* adjust actual number of cards */
-	}else {
-		kfree(card_array);
-		destroy_workqueue(wanpipe_wq);
-		printk(KERN_INFO "IN Init Module: NO Cards registered\n");
-		err = -ENODEV;
-	}
-
-	return err;
-}
-
-/*============================================================================
- * Module 'remove' entry point.
- * o unregister all adapters from the WAN router
- * o release all remaining system resources
- */
-static void __exit wanpipe_cleanup(void)
-{
-	int i;
-
-	if (!ncards)
-		return;
-		
-	for (i = 0; i < ncards; ++i) {
-		sdla_t* card = &card_array[i];
-		unregister_wan_device(card->devname);
-	}
-	destroy_workqueue(wanpipe_wq);
-	kfree(card_array);
-
-	printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
-}
-
-module_init(wanpipe_init);
-module_exit(wanpipe_cleanup);
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Setup/configure WAN link driver.
- * o check adapter state
- * o make sure firmware is present in configuration
- * o make sure I/O port and IRQ are specified
- * o make sure I/O region is available
- * o allocate interrupt vector
- * o setup SDLA hardware
- * o call appropriate routine to perform protocol-specific initialization
- * o mark I/O region as used
- * o if this is the first active card, then schedule background task
- *
- * This function is called when router handles ROUTER_SETUP IOCTL. The
- * configuration structure is in kernel memory (including extended data, if
- * any).
- */
- 
-static int setup(struct wan_device* wandev, wandev_conf_t* conf)
-{
-	sdla_t* card;
-	int err = 0;
-	int irq=0;
-
-	/* Sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){
-		printk(KERN_INFO 
-		      "%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n",
-		      wandev->name,
-		      (unsigned int)wandev,(unsigned int)wandev->private,
-		      (unsigned int)conf); 
-		return -EFAULT;
-	}
-
-	printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name);
-
-	card = wandev->private;
-	if (wandev->state != WAN_UNCONFIGURED){
-		printk(KERN_INFO "%s: failed sdlamain setup, busy!\n",
-			wandev->name);
-		return -EBUSY;		/* already configured */
-	}
-
-	printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name);
-
-	/* Initialize the counters for each wandev 
-	 * Used for counting number of times new_if and 
-         * del_if get called.
-	 */
-	wandev->del_if_cnt = 0;
-	wandev->new_if_cnt = 0;
-	wandev->config_id  = conf->config_id;
-
-	if (!conf->data_size || (conf->data == NULL)) {
-		printk(KERN_INFO
-			"%s: firmware not found in configuration data!\n",
-			wandev->name);
-		return -EINVAL;
-	}
-
-	/* Check for resource conflicts and setup the
-	 * card for piggibacking if necessary */
-	if(!conf->S514_CPU_no[0]) {
-		if ((err=check_s508_conflicts(card,conf,&irq)) != 0){
-			return err;
-		}
-	}else {
-		if ((err=check_s514_conflicts(card,conf,&irq)) != 0){
-			return err;
-		}
-	}
-
-	/* If the current card has already been configured
-         * or it's a piggyback card, do not try to allocate
-         * resources.
-	 */
-	if (!card->wandev.piggyback && !card->configured){
-
-		/* Configure hardware, load firmware, etc. */
-		memset(&card->hw, 0, sizeof(sdlahw_t));
-
-		/* for an S514 adapter, pass the CPU number and the slot number read */
-		/* from 'router.conf' to the 'sdla_setup()' function via the 'port' */
-		/* parameter */
-		if (conf->S514_CPU_no[0]){
-
-			card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0];
-			card->hw.S514_slot_no = conf->PCI_slot_no;
-			card->hw.auto_pci_cfg = conf->auto_pci_cfg;
-
-			if (card->hw.auto_pci_cfg == WANOPT_YES){
-				printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n",
-				card->devname, card->hw.S514_cpu_no[0]);
-			}else{
-				printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n",
-				card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no);
-			}
-
-		}else{
-			/* 508 Card io port and irq initialization */
-			card->hw.port = conf->ioport;
-			card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
-		}
-
-
-		/* Compute the virtual address of the card in kernel space */
-		if(conf->maddr){
-			card->hw.dpmbase = phys_to_virt(conf->maddr);
-		}else{	
-			card->hw.dpmbase = (void *)conf->maddr;
-		}
-			
-		card->hw.dpmsize = SDLA_WINDOWSIZE;
-		
-		/* set the adapter type if using an S514 adapter */
-		card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0]; 
-		card->hw.pclk = conf->hw_opt[1];
-
-		err = sdla_setup(&card->hw, conf->data, conf->data_size);
-		if (err){
-			printk(KERN_INFO "%s: Hardware setup Failed %i\n",
-					card->devname,err);
-			return err;
-		}
-
-	        if(card->hw.type != SDLA_S514)
-			irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */
-		else
-			irq = card->hw.irq;
-
-		/* request an interrupt vector - note that interrupts may be shared */
-		/* when using the S514 PCI adapter */
-		
-       		if(request_irq(irq, sdla_isr, 
-		      (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0, 
-		       wandev->name, card)){
-
-			printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq);
-			return -EINVAL;
-		}
-
-	}else{
-		printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n",
-			wandev->name,card->configured,card->wandev.piggyback);
-	} 
-
-
-	if (!card->configured){
-
-		/* Initialize the Spin lock */
-		printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name);
-
-		/* Piggyback spin lock has already been initialized,
-		 * in check_s514/s508_conflicts() */
-		if (!card->wandev.piggyback){
-			spin_lock_init(&card->wandev.lock);
-		}
-		
-		/* Intialize WAN device data space */
-		wandev->irq       = irq;
-		wandev->dma       = 0;
-		if(card->hw.type != SDLA_S514){ 
-			wandev->ioport = card->hw.port;
-		}else{
-			wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0];
-			wandev->S514_slot_no = card->hw.S514_slot_no;
-		}
-		wandev->maddr     = (unsigned long)card->hw.dpmbase;
-		wandev->msize     = card->hw.dpmsize;
-		wandev->hw_opt[0] = card->hw.type;
-		wandev->hw_opt[1] = card->hw.pclk;
-		wandev->hw_opt[2] = card->hw.memory;
-		wandev->hw_opt[3] = card->hw.fwid;
-	}
-
-	/* Protocol-specific initialization */
-	switch (card->hw.fwid) {
-
-	case SFID_X25_502:
-	case SFID_X25_508:
-		printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n",
-				card->devname);
-		err = wpx_init(card, conf);
-		break;
-	case SFID_FR502:
-	case SFID_FR508:
-		printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n",
-				card->devname);
-		err = wpf_init(card, conf);
-		break;
-	case SFID_PPP502:
-	case SFID_PPP508:
-		printk(KERN_INFO "%s: Starting PPP Protocol Init.\n",
-				card->devname);
-		err = wpp_init(card, conf);
-		break;
-		
-	case SFID_CHDLC508:
-	case SFID_CHDLC514:
-		if (conf->ft1){		
-			printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n",
-				card->devname);
-			err = wpft1_init(card, conf);
-			break;
-			
-		}else if (conf->config_id == WANCONFIG_MPPP){
-			printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n",
-					card->devname);
-			err = wsppp_init(card,conf);
-			break;
-
-		}else{
-			printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n",
-					card->devname);
-			err = wpc_init(card, conf);
-			break;
-		}
-	default:
-		printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n",
-			wandev->name,card->hw.fwid,SFID_CHDLC508);
-		err = -EPROTONOSUPPORT;
-	}
-
-	if (err != 0){
-		if (err == -EPROTONOSUPPORT){
-			printk(KERN_INFO 
-				"%s: Error, Protocol selected has not been compiled!\n",
-					card->devname);
-			printk(KERN_INFO 
-				"%s:        Re-configure the kernel and re-build the modules!\n",
-					card->devname);
-		}
-		
-		release_hw(card);
-		wandev->state = WAN_UNCONFIGURED;
-		return err;
-	}
-
-
-  	/* Reserve I/O region and schedule background task */
-        if(card->hw.type != SDLA_S514 && !card->wandev.piggyback)
-		if (!request_region(card->hw.port, card->hw.io_range, 
-				wandev->name)) {
-			printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port);
-			release_hw(card);
-			wandev->state = WAN_UNCONFIGURED;
-			return -EBUSY;
-	  }
-
-	/* Only use the polling routine for the X25 protocol */
-	
-	card->wandev.critical=0;
-	return 0;
-}
-
-/*================================================================== 
- * configure_s508_card
- * 
- * For a S508 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same IO port as a previously loaded S508
- * card.
- */ 
-
-static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq)
-{
-	unsigned long smp_flags;
-	int i;
-	
-	if (conf->ioport <= 0) {
-		printk(KERN_INFO
-		"%s: can't configure without I/O port address!\n",
-		card->wandev.name);
-		return -EINVAL;
-	}
-
-	if (conf->irq <= 0) {
-		printk(KERN_INFO "%s: can't configure without IRQ!\n",
-		card->wandev.name);
-		return -EINVAL;
-	}
-
-	if (test_bit(0,&card->configured))
-		return 0;
-
-
-	/* Check for already loaded card with the same IO port and IRQ 
-	 * If found, copy its hardware configuration and use its
-	 * resources (i.e. piggybacking)
-	 */
-	
-	for (i = 0; i < ncards; i++) {
-		sdla_t *nxt_card = &card_array[i];
-
-		/* Skip the current card ptr */
-		if (nxt_card == card)	
-			continue;
-
-
-		/* Find a card that is already configured with the
-		 * same IO Port */
-		if ((nxt_card->hw.type == SDLA_S508) &&
-		    (nxt_card->hw.port == conf->ioport) && 
-		    (nxt_card->next == NULL)){
-			
-			/* We found a card the card that has same configuration
-			 * as us. This means, that we must setup this card in 
-			 * piggibacking mode. However, only CHDLC and MPPP protocol
-			 * support this setup */
-		
-			if ((conf->config_id == WANCONFIG_CHDLC || 
-			     conf->config_id == WANCONFIG_MPPP) &&
-			    (nxt_card->wandev.config_id == WANCONFIG_CHDLC || 
-			     nxt_card->wandev.config_id == WANCONFIG_MPPP)){ 
-				
-				*irq = nxt_card->hw.irq;
-				memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-			
-				/* The master could already be running, we must
-				 * set this as a critical area */
-				lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
-
-				nxt_card->next = card;
-				card->next = nxt_card;
-
-				card->wandev.piggyback = WANOPT_YES;
-
-				/* We must initialise the piggiback spin lock here
-				 * since isr will try to lock card->next if it
-				 * exists */
-				spin_lock_init(&card->wandev.lock);
-				
-				unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags);
-				break;
-			}else{
-				/* Trying to run piggibacking with a wrong protocol */
-				printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n"
-						 "%s:        This protocol doesn't support\n"
-						 "%s:        multi-port operation!\n",
-						 card->devname,nxt_card->hw.port,
-						 card->devname,card->devname);
-				return -EEXIST;
-			}
-		}
-	}
-	
-
-	/* Make sure I/O port region is available only if we are the
-	 * master device.  If we are running in piggybacking mode, 
-	 * we will use the resources of the master card. */
-	if (!card->wandev.piggyback) {
-		struct resource *rr =
-			request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain");
-		release_region(conf->ioport, SDLA_MAXIORANGE);
-
-		if (!rr) {
-			printk(KERN_INFO
-				"%s: I/O region 0x%X - 0x%X is in use!\n",
-				card->wandev.name, conf->ioport,
-				conf->ioport + SDLA_MAXIORANGE - 1);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-/*================================================================== 
- * configure_s514_card
- * 
- * For a S514 adapter, check for a possible configuration error in that
- * we are loading an adapter in the same slot as a previously loaded S514
- * card.
- */ 
-
-
-static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq)
-{
-	unsigned long smp_flags;
-	int i;
-	
-	if (test_bit(0,&card->configured))
-		return 0;
-
-	
-	/* Check for already loaded card with the same IO port and IRQ 
-	 * If found, copy its hardware configuration and use its
-	 * resources (i.e. piggybacking)
-	 */
-
-	for (i = 0; i < ncards; i ++) {
-	
-		sdla_t* nxt_card = &card_array[i];
-		if(nxt_card == card)
-			continue;
-		
-		if((nxt_card->hw.type == SDLA_S514) &&
-		   (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) &&
-		   (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&&
-		   (nxt_card->next == NULL)){
-
-
-			if ((conf->config_id == WANCONFIG_CHDLC || 
-			     conf->config_id == WANCONFIG_MPPP) &&
-			    (nxt_card->wandev.config_id == WANCONFIG_CHDLC || 
-			     nxt_card->wandev.config_id == WANCONFIG_MPPP)){ 
-				
-				*irq = nxt_card->hw.irq;
-				memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t));
-	
-				/* The master could already be running, we must
-				 * set this as a critical area */
-				lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
-				nxt_card->next = card;
-				card->next = nxt_card;
-
-				card->wandev.piggyback = WANOPT_YES;
-
-				/* We must initialise the piggiback spin lock here
-				 * since isr will try to lock card->next if it
-				 * exists */
-				spin_lock_init(&card->wandev.lock);
-
-				unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags);
-
-			}else{
-				/* Trying to run piggibacking with a wrong protocol */
-				printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n"
-						 "%s:        This protocol doesn't support\n"
-						 "%s:        multi-port operation!\n",
-						 card->devname,
-						 conf->S514_CPU_no[0],conf->PCI_slot_no,
-						 card->devname,card->devname);
-				return -EEXIST;
-			}
-		}
-	}
-
-	return 0;
-}
-
-
-
-/*============================================================================
- * Shut down WAN link driver. 
- * o shut down adapter hardware
- * o release system resources.
- *
- * This function is called by the router when device is being unregistered or
- * when it handles ROUTER_DOWN IOCTL.
- */
-static int shutdown(struct wan_device* wandev)
-{
-	sdla_t *card;
-	int err=0;
-	
-	/* sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL)){
-		return -EFAULT;
-	}
-		
-	if (wandev->state == WAN_UNCONFIGURED){
-		return 0;
-	}
-
-	card = wandev->private;
-
-	if (card->tty_opt){
-		if (card->tty_open){
-			printk(KERN_INFO 
-				"%s: Shutdown Failed: TTY is still open\n",
-				  card->devname);
-			return -EBUSY;
-		}
-	}
-	
-	wandev->state = WAN_UNCONFIGURED;
-
-	set_bit(PERI_CRIT,(void*)&wandev->critical);
-	
-	/* In case of piggibacking, make sure that 
-         * we never try to shutdown both devices at the same
-         * time, because they depend on one another */
-	
-	if (card->disable_comm){
-		card->disable_comm(card);
-	}
-
-	/* Release Resources */
-	release_hw(card);
-
-        /* only free the allocated I/O range if not an S514 adapter */
-	if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){
-              	release_region(card->hw.port, card->hw.io_range);
-	}
-
-	if (!card->configured){
-		memset(&card->hw, 0, sizeof(sdlahw_t));
-	      	if (card->next){
-			memset(&card->next->hw, 0, sizeof(sdlahw_t));
-		}
-	}
-	
-
-	clear_bit(PERI_CRIT,(void*)&wandev->critical);
-	return err;
-}
-
-static void release_hw (sdla_t *card)
-{
-	sdla_t *nxt_card;
-
-	
-	/* Check if next device exists */
-	if (card->next){
-		nxt_card = card->next;
-		/* If next device is down then release resources */
-		if (nxt_card->wandev.state == WAN_UNCONFIGURED){
-			if (card->wandev.piggyback){
-				/* If this device is piggyback then use
-                                 * information of the master device 
-				 */
-				printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname);
-				sdla_down(&card->next->hw);
-       				free_irq(card->wandev.irq, card->next);
-				card->configured = 0;
-				card->next->configured = 0;
-				card->wandev.piggyback = 0;
-			}else{
-				/* Master device shutting down */
-				printk(KERN_INFO "%s: Master shutting down\n",card->devname);
-				sdla_down(&card->hw);
-				free_irq(card->wandev.irq, card);
-				card->configured = 0;
-				card->next->configured = 0;
-			}
-		}else{
-			printk(KERN_INFO "%s: Device still running %i\n",
-				nxt_card->devname,nxt_card->wandev.state);
-
-			card->configured = 1;
-		}
-	}else{
-		printk(KERN_INFO "%s: Master shutting down\n",card->devname);
-		sdla_down(&card->hw);
-       		free_irq(card->wandev.irq, card);
-		card->configured = 0;
-	}
-	return;
-}
-
-
-/*============================================================================
- * Driver I/O control. 
- * o verify arguments
- * o perform requested action
- *
- * This function is called when router handles one of the reserved user
- * IOCTLs.  Note that 'arg' stil points to user address space.
- */
-static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg)
-{
-	sdla_t* card;
-	int err;
-
-	/* sanity checks */
-	if ((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-	if (wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-
-	card = wandev->private;
-
-	if(card->hw.type != SDLA_S514){
-		disable_irq(card->hw.irq);
-	}
-
-	if (test_bit(SEND_CRIT, (void*)&wandev->critical)) {
-		return -EAGAIN;
-	}
-	
-	switch (cmd) {
-	case WANPIPE_DUMP:
-		err = ioctl_dump(wandev->private, (void*)arg);
-		break;
-
-	case WANPIPE_EXEC:
-		err = ioctl_exec(wandev->private, (void*)arg, cmd);
-		break;
-	default:
-		err = -EINVAL;
-	}
- 
-	return err;
-}
-
-/****** Driver IOCTL Handlers ***********************************************/
-
-/*============================================================================
- * Dump adapter memory to user buffer.
- * o verify request structure
- * o copy request structure to kernel data space
- * o verify length/offset
- * o verify user buffer
- * o copy adapter memory image to user buffer
- *
- * Note: when dumping memory, this routine switches curent dual-port memory
- *	 vector, so care must be taken to avoid racing conditions.
- */
-static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
-{
-	sdla_dump_t dump;
-	unsigned winsize;
-	unsigned long oldvec;	/* DPM window vector */
-	unsigned long smp_flags;
-	int err = 0;
-
-	if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)))
-		return -EFAULT;
-		
-	if ((dump.magic != WANPIPE_MAGIC) ||
-	    (dump.offset + dump.length > card->hw.memory))
-		return -EINVAL;
-	
-	winsize = card->hw.dpmsize;
-
-	if(card->hw.type != SDLA_S514) {
-
-		lock_adapter_irq(&card->wandev.lock, &smp_flags);
-		
-                oldvec = card->hw.vector;
-                while (dump.length) {
-			/* current offset */				
-                        unsigned pos = dump.offset % winsize;
-			/* current vector */
-                        unsigned long vec = dump.offset - pos;
-                        unsigned len = (dump.length > (winsize - pos)) ?
-                        	(winsize - pos) : dump.length;
-			/* relocate window */
-                        if (sdla_mapmem(&card->hw, vec) != 0) {
-                                err = -EIO;
-                                break;
-                        }
-			
-                        if(copy_to_user((void *)dump.ptr,
-                                (u8 *)card->hw.dpmbase + pos, len)){ 
-				
-				unlock_adapter_irq(&card->wandev.lock, &smp_flags);
-				return -EFAULT;
-			}
-
-                        dump.length     -= len;
-                        dump.offset     += len;
-                        dump.ptr         = (char*)dump.ptr + len;
-                }
-		
-                sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
-		unlock_adapter_irq(&card->wandev.lock, &smp_flags);
-        
-	}else {
-
-               if(copy_to_user((void *)dump.ptr,
-			       (u8 *)card->hw.dpmbase + dump.offset, dump.length)){
-			return -EFAULT;
-		}
-	}
-
-	return err;
-}
-
-/*============================================================================
- * Execute adapter firmware command.
- * o verify request structure
- * o copy request structure to kernel data space
- * o call protocol-specific 'exec' function
- */
-static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd)
-{
-	sdla_exec_t exec;
-	int err=0;
-
-	if (card->exec == NULL && cmd == WANPIPE_EXEC){
-		return -ENODEV;
-	}
-
-	if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)))
-		return -EFAULT;
-
-	if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL))
-		return -EINVAL;
-
-	switch (cmd) {
-		case WANPIPE_EXEC:	
-			err = card->exec(card, exec.cmd, exec.data);
-			break;
-	}	
-	return err;
-}
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * SDLA Interrupt Service Routine.
- * o acknowledge SDLA hardware interrupt.
- * o call protocol-specific interrupt service routine, if any.
- */
-STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs)
-{
-#define	card	((sdla_t*)dev_id)
-
-	if(card->hw.type == SDLA_S514) {	/* handle interrrupt on S514 */
-                u32 int_status;
-                unsigned char CPU_no = card->hw.S514_cpu_no[0];
-                unsigned char card_found_for_IRQ;
-		u8 IRQ_count = 0;
-
-		for(;;) {
-
-			read_S514_int_stat(&card->hw, &int_status);
-
-			/* check if the interrupt is for this device */
- 			if(!((unsigned char)int_status &
-				(IRQ_CPU_A | IRQ_CPU_B)))
-                	        return IRQ_HANDLED;
-
-			/* if the IRQ is for both CPUs on the same adapter, */
-			/* then alter the interrupt status so as to handle */
-			/* one CPU at a time */
-			if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B))
-				== (IRQ_CPU_A | IRQ_CPU_B)) {
-				int_status &= (CPU_no == S514_CPU_A) ?
-					~IRQ_CPU_B : ~IRQ_CPU_A;
-			}
- 
-			card_found_for_IRQ = 0;
-
-	             	/* check to see that the CPU number for this device */
-			/* corresponds to the interrupt status read */
-                	switch (CPU_no) {
-                        	case S514_CPU_A:
-                                	if((unsigned char)int_status &
-						IRQ_CPU_A)
-                                        card_found_for_IRQ = 1;
-                                break;
-
-	                        case S514_CPU_B:
-        	                        if((unsigned char)int_status &
-						IRQ_CPU_B)
-                                        card_found_for_IRQ = 1;
-                                break;
-                	}
-
-			/* exit if the interrupt is for another CPU on the */
-			/* same IRQ */
-			if(!card_found_for_IRQ)
-				return IRQ_HANDLED;
-
-       	 		if (!card || 
-			   (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){
-					printk(KERN_INFO
-						"Received IRQ %d for CPU #%c\n",
-						irq, CPU_no);
-					printk(KERN_INFO
-						"IRQ for unconfigured adapter\n");
-					S514_intack(&card->hw, int_status);
-					return IRQ_HANDLED;
-       			}
-
-	        	if (card->in_isr) {
-        	       		printk(KERN_INFO
-					"%s: interrupt re-entrancy on IRQ %d\n",
-                       			card->devname, card->wandev.irq);
-				S514_intack(&card->hw, int_status);
- 				return IRQ_HANDLED;
-       			}
-
-			spin_lock(&card->wandev.lock);
-			if (card->next){
-				spin_lock(&card->next->wandev.lock);
-			}
-				
-	               	S514_intack(&card->hw, int_status);
-       			if (card->isr)
-				card->isr(card);
-
-			if (card->next){
-				spin_unlock(&card->next->wandev.lock);
-			}
-			spin_unlock(&card->wandev.lock);
-
-			/* handle a maximum of two interrupts (one for each */
-			/* CPU on the adapter) before returning */  
-			if((++ IRQ_count) == 2)
-				return IRQ_HANDLED;
-		}
-	}
-
-	else {			/* handle interrupt on S508 adapter */
-
-		if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured))
-			return IRQ_HANDLED;
-
-		if (card->in_isr) {
-			printk(KERN_INFO
-				"%s: interrupt re-entrancy on IRQ %d!\n",
-				card->devname, card->wandev.irq);
-			return IRQ_HANDLED;
-		}
-
-		spin_lock(&card->wandev.lock);
-		if (card->next){
-			spin_lock(&card->next->wandev.lock);
-		}
-	
-		sdla_intack(&card->hw);
-		if (card->isr)
-			card->isr(card);
-		
-		if (card->next){
-			spin_unlock(&card->next->wandev.lock);
-		}
-		spin_unlock(&card->wandev.lock);
-
-	}
-        return IRQ_HANDLED;
-#undef	card
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being open.  The only reason we need this, is because we
- * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_open (sdla_t* card)
-{
-	++card->open_cnt;
-}
-
-/*============================================================================
- * This routine is called by the protocol-specific modules when network
- * interface is being closed.  The only reason we need this, is because we
- * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's
- * defined more than once into the same kernel module.
- */
-void wanpipe_close (sdla_t* card)
-{
-	--card->open_cnt;
-}
-
-/*============================================================================
- * Set WAN device state.
- */
-void wanpipe_set_state (sdla_t* card, int state)
-{
-	if (card->wandev.state != state) {
-		switch (state) {
-		case WAN_CONNECTED:
-			printk (KERN_INFO "%s: link connected!\n",
-				card->devname);
-			break;
-
-		case WAN_CONNECTING:
-			printk (KERN_INFO "%s: link connecting...\n",
-				card->devname);
-			break;
-
-		case WAN_DISCONNECTED:
-			printk (KERN_INFO "%s: link disconnected!\n",
-				card->devname);
-			break;
-		}
-		card->wandev.state = state;
-	}
-	card->state_tick = jiffies;
-}
-
-sdla_t * wanpipe_find_card (char *name)
-{
-	int cnt;
-	for (cnt = 0; cnt < ncards; ++ cnt) {
-		sdla_t* card = &card_array[cnt];
-		if (!strcmp(card->devname,name))
-			return card;
-	}
-	return NULL;
-}
-
-sdla_t * wanpipe_find_card_num (int num)
-{
-	if (num < 1 || num > ncards)
-		return NULL;	
-	num--;
-	return &card_array[num];
-}
-
-/*
- * @work_pointer:	work_struct to be done;
- * 			should already have PREPARE_WORK() or
- * 			  INIT_WORK() done on it by caller;
- */
-void wanpipe_queue_work (struct work_struct *work_pointer)
-{
-	if (test_and_set_bit(1, (void*)&wanpipe_bh_critical))
-		printk(KERN_INFO "CRITICAL IN QUEUING WORK\n");
-
-	queue_work(wanpipe_wq, work_pointer);
-	clear_bit(1,(void*)&wanpipe_bh_critical);
-}
-
-void wakeup_sk_bh(struct net_device *dev)
-{
-	wanpipe_common_t *chan = dev->priv;
-
-	if (test_bit(0,&chan->common_critical))
-		return;
-	
-	if (chan->sk && chan->tx_timer){
-		chan->tx_timer->expires=jiffies+1;
-		add_timer(chan->tx_timer);
-	}
-}
-
-int change_dev_flags(struct net_device *dev, unsigned flags)
-{
-	struct ifreq if_info;
-	mm_segment_t fs = get_fs();
-	int err;
-
-	memset(&if_info, 0, sizeof(if_info));
-	strcpy(if_info.ifr_name, dev->name);
-	if_info.ifr_flags = flags;	
-
-	set_fs(get_ds());     /* get user space block */ 
-	err = devinet_ioctl(SIOCSIFFLAGS, &if_info);
-	set_fs(fs);
-
-	return err;
-}
-
-unsigned long get_ip_address(struct net_device *dev, int option)
-{
-	
-	struct in_ifaddr *ifaddr;
-	struct in_device *in_dev;
-	unsigned long addr = 0;
-
-	rcu_read_lock();
-	if ((in_dev = __in_dev_get_rcu(dev)) == NULL){
-		goto out;
-	}
-
-	if ((ifaddr = in_dev->ifa_list)== NULL ){
-		goto out;
-	}
-	
-	switch (option){
-
-	case WAN_LOCAL_IP:
-		addr = ifaddr->ifa_local;
-		break;
-	
-	case WAN_POINTOPOINT_IP:
-		addr = ifaddr->ifa_address;
-		break;	
-
-	case WAN_NETMASK_IP:
-		addr = ifaddr->ifa_mask;
-		break;
-
-	case WAN_BROADCAST_IP:
-		addr = ifaddr->ifa_broadcast;
-		break;
-	default:
-		break;
-	}
-
-out:
-	rcu_read_unlock();
-	return addr;
-}	
-
-void add_gateway(sdla_t *card, struct net_device *dev)
-{
-	mm_segment_t oldfs;
-	struct rtentry route;
-	int res;
-
-	memset((char*)&route,0,sizeof(struct rtentry));
-
-	((struct sockaddr_in *)
-		&(route.rt_dst))->sin_addr.s_addr = 0;
-	((struct sockaddr_in *)
-		&(route.rt_dst))->sin_family = AF_INET;
-
-	((struct sockaddr_in *)
-		&(route.rt_genmask))->sin_addr.s_addr = 0;
-	((struct sockaddr_in *) 
-		&(route.rt_genmask)) ->sin_family = AF_INET;
-
-
-	route.rt_flags = 0;  
-	route.rt_dev = dev->name;
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	res = ip_rt_ioctl(SIOCADDRT,&route);
-	set_fs(oldfs);
-
-	if (res == 0){
-		printk(KERN_INFO "%s: Gateway added for %s\n",
-			card->devname,dev->name);
-	}
-
-	return;
-}
-
-MODULE_LICENSE("GPL");
-
-/****** End *********************************************************/
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
deleted file mode 100644
index 812a118..0000000
--- a/drivers/net/wan/wanpipe_multppp.c
+++ /dev/null
@@ -1,2358 +0,0 @@
-/*****************************************************************************
-* wanpipe_multppp.c Multi-Port PPP driver module.
-*
-* Authors: 	Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright:	(c) 1995-2001 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Dec 15 2000   Updated for 2.4.X kernel
-* Nov 15 2000   Fixed the SyncPPP support for kernels 2.2.16 and higher.
-*   		The pppstruct has changed.
-* Jul 13 2000	Using the kernel Syncppp module on top of RAW Wanpipe CHDLC
-*  		module.
-*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>	/* printk(), and other useful stuff */
-#include <linux/stddef.h>	/* offsetof(), etc. */
-#include <linux/errno.h>	/* return codes */
-#include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/slab.h>	/* kmalloc(), kfree() */
-#include <linux/wanrouter.h>	/* WAN router definitions */
-#include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
-#include <linux/if_arp.h>	/* ARPHRD_* defines */
-#include <linux/jiffies.h>	/* time_after() macro */
-
-#include <linux/in.h>		/* sockaddr_in */
-#include <linux/inet.h>	
-#include <linux/if.h>
-#include <asm/byteorder.h>	/* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h>		/* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h>           	/* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h>    /* Socket Driver common area */
-#include <linux/if_wanpipe.h>		
-
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <net/syncppp.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef	_DEBUG_
-#define	STATIC
-#else
-#define	STATIC		static
-#endif
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP   	0x01
-#define TMR_INT_ENABLED_UPDATE	0x02
-#define TMR_INT_ENABLED_CONFIG  0x04
- 
-#define	CHDLC_DFLT_DATA_LEN	1500		/* default MTU */
-#define CHDLC_HDR_LEN		1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define CHDLC_API 0x01
-
-#define PORT(x)   (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF	10
-
-#define CRC_LENGTH 	2 
-#define PPP_HEADER_LEN 	4
- 
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following 
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
-	void *if_ptr;				/* General Pointer used by SPPP */
-	wanpipe_common_t common;
-	sdla_t		*card;
-	int 		TracingEnabled;		/* For enabling Tracing */
-	unsigned long 	curr_trace_addr;	/* Used for Tracing */
-	unsigned long 	start_trace_addr;
-	unsigned long 	end_trace_addr;
-	unsigned long 	base_addr_trace_buffer;
-	unsigned long 	end_addr_trace_buffer;
-	unsigned short 	number_trace_elements;
-	unsigned  	available_buffer_space;
-	unsigned long 	router_start_time;
-	unsigned char 	route_status;
-	unsigned char 	route_removed;
-	unsigned long 	tick_counter;		/* For 5s timeout counter */
-	unsigned long 	router_up_time;
-        u32             IP_address;		/* IP addressing */
-        u32             IP_netmask;
-	unsigned char  mc;			/* Mulitcast support on/off */
-	unsigned short udp_pkt_lgth;		/* udp packet processing */
-	char udp_pkt_src;
-	char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-	unsigned short timer_int_enabled;
-	char update_comms_stats;		/* updating comms stats */
-
-	//FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE	0x00
-#define ADD_ROUTE	0x01
-#define ROUTE_ADDED	0x02
-#define REMOVE_ROUTE	0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
-   two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
-		  wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-
-/* Network device interface */
-static int if_init(struct net_device* dev);
-static int if_open(struct net_device* dev);
-static int if_close(struct net_device* dev);
-static int if_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure 	(sdla_t* card, void* data);
-static int chdlc_comm_enable 	(sdla_t* card);
-static int chdlc_comm_disable 	(sdla_t* card);
-static int chdlc_read_version 	(sdla_t* card, char* str);
-static int chdlc_set_intr_mode 	(sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int config_chdlc (sdla_t *card);
-
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
-        chdlc_private_area_t* chdlc_priv_area);
-static void port_set_state (sdla_t *card, int);
-
-/* Interrupt handlers */
-static void wsppp_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Miscellaneous functions */
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-			      struct sk_buff *skb, struct net_device* dev,
-			      chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,  
-				chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-static void send_ppp_term_request(struct net_device *dev);
-
-
-static int  Intr_test_counter;
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup.  At this
- * point adapter is completely initialized and firmware is running.
- *  o read firmware version (to make sure it's alive)
- *  o configure adapter
- *  o initialize protocol-specific fields of the adapter data space.
- *
- * Return:	0	o.k.
- *		< 0	failure.
- */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf)
-{
-	unsigned char port_num;
-	int err;
-	unsigned long max_permitted_baud = 0;
-	SHARED_MEMORY_INFO_STRUCT *flags;
-
-	union
-		{
-		char str[80];
-		} u;
-	volatile CHDLC_MAILBOX_STRUCT* mb;
-	CHDLC_MAILBOX_STRUCT* mb1;
-	unsigned long timeout;
-
-	/* Verify configuration ID */
-	if (conf->config_id != WANCONFIG_MPPP) {
-		printk(KERN_INFO "%s: invalid configuration ID %u!\n",
-				  card->devname, conf->config_id);
-		return -EINVAL;
-	}
-
-	/* Find out which Port to use */
-	if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
-		if (card->next){
-
-			if (conf->comm_port != card->next->u.c.comm_port){
-				card->u.c.comm_port = conf->comm_port;
-			}else{
-				printk(KERN_ERR "%s: ERROR - %s port used!\n",
-        		        	card->wandev.name, PORT(conf->comm_port));
-				return -EINVAL;
-			}
-		}else{
-			card->u.c.comm_port = conf->comm_port;
-		}
-	}else{
-		printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n",
-                			card->wandev.name);
-		return -EINVAL;
-	}
-	
-
-	/* Initialize protocol-specific fields */
-	if(card->hw.type != SDLA_S514){
-
-		if (card->u.c.comm_port == WANOPT_PRI){	
-			card->mbox  = (void *) card->hw.dpmbase;
-		}else{
-			card->mbox  = (void *) card->hw.dpmbase + 
-				SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
-		}	
-	}else{ 
-		/* for a S514 adapter, set a pointer to the actual mailbox in the */
-		/* allocated virtual memory area */
-		if (card->u.c.comm_port == WANOPT_PRI){
-			card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
-		}else{
-			card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
-		}	
-	}
-
-	mb = mb1 = card->mbox;
-
-	if (!card->configured){
-
-		/* The board will place an 'I' in the return code to indicate that it is
-	   	ready to accept commands.  We expect this to be completed in less
-           	than 1 second. */
-
-		timeout = jiffies + 1 * HZ;
-		while (mb->return_code != 'I')	/* Wait 1s for board to initialize */
-			if (time_after(jiffies, timeout)) break;
-
-		if (mb->return_code != 'I') {
-			printk(KERN_INFO
-				"%s: Initialization not completed by adapter\n",
-				card->devname);
-			printk(KERN_INFO "Please contact Sangoma representative.\n");
-			return -EIO;
-		}
-	}
-
-	/* Read firmware version.  Note that when adapter initializes, it
-	 * clears the mailbox, so it may appear that the first command was
-	 * executed successfully when in fact it was merely erased. To work
-	 * around this, we execute the first command twice.
-	 */
-
-	if (chdlc_read_version(card, u.str))
-		return -EIO;
-
-	printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n" 
-			 "%s: for Multi-Port PPP protocol.\n",
-			card->devname,u.str,card->devname); 
-
-	card->isr			= &wsppp_isr;
-	card->poll			= NULL;
-	card->exec			= NULL;
-	card->wandev.update		= &update;
- 	card->wandev.new_if		= &new_if;
-	card->wandev.del_if		= &del_if;
-	card->wandev.udp_port   	= conf->udp_port;
-
-	card->wandev.new_if_cnt = 0;
-
-	/* reset the number of times the 'update()' proc has been called */
-	card->u.c.update_call_count = 0;
-	
-	card->wandev.ttl = conf->ttl;
-	card->wandev.interface = conf->interface; 
-
-	if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
-	    card->hw.type != SDLA_S514){
-		printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
-			card->devname, PORT(card->u.c.comm_port));
-		return -EIO;
-	}
-
-
-	card->wandev.clocking = conf->clocking;
-
-	port_num = card->u.c.comm_port;
-
-	/* Setup Port Bps */
-
-	if(card->wandev.clocking) {
-		if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-			/* For Primary Port 0 */
-               		max_permitted_baud =
-				(card->hw.type == SDLA_S514) ?
-				PRI_MAX_BAUD_RATE_S514 : 
-				PRI_MAX_BAUD_RATE_S508;
-		}
-		else if(port_num == WANOPT_SEC) {
-			/* For Secondary Port 1 */
-                        max_permitted_baud =
-                               (card->hw.type == SDLA_S514) ?
-                                SEC_MAX_BAUD_RATE_S514 :
-                                SEC_MAX_BAUD_RATE_S508;
-                        }
-  
-			if(conf->bps > max_permitted_baud) {
-				conf->bps = max_permitted_baud;
-				printk(KERN_INFO "%s: Baud too high!\n",
-					card->wandev.name);
- 				printk(KERN_INFO "%s: Baud rate set to %lu bps\n", 
-					card->wandev.name, max_permitted_baud);
-			}
-                             
-			card->wandev.bps = conf->bps;
-	}else{
-        	card->wandev.bps = 0;
-  	}
-
-	/* Setup the Port MTU */
-	if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
-		/* For Primary Port 0 */
-		card->wandev.mtu =
-			(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
-			min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
-			CHDLC_DFLT_DATA_LEN;
-	} else if(port_num == WANOPT_SEC) { 
-		/* For Secondary Port 1 */
-		card->wandev.mtu =
-			(conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
-			min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
-			CHDLC_DFLT_DATA_LEN;
-	}
-
-	/* Add on a PPP Header */
-	card->wandev.mtu += PPP_HEADER_LEN;
-
-	/* Set up the interrupt status area */
-	/* Read the CHDLC Configuration and obtain: 
-	 *	Ptr to shared memory infor struct
-         * Use this pointer to calculate the value of card->u.c.flags !
- 	 */
-	mb1->buffer_length = 0;
-	mb1->command = READ_CHDLC_CONFIGURATION;
-	err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
-	if(err != COMMAND_OK) {
-		clear_bit(1, (void*)&card->wandev.critical);
-
-                if(card->hw.type != SDLA_S514)
-                	enable_irq(card->hw.irq);
-
-		chdlc_error(card, err, mb1);
-		return -EIO;
-	}
-
-	if(card->hw.type == SDLA_S514){
-               	card->u.c.flags = (void *)(card->hw.dpmbase +
-               		(((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct));
-        }else{
-                card->u.c.flags = (void *)(card->hw.dpmbase +
-                        (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
-			ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
-	}
-	
-	flags = card->u.c.flags;
-	
-	/* This is for the ports link state */
-	card->wandev.state = WAN_DUALPORT;
-	card->u.c.state = WAN_DISCONNECTED;
-
-
-	if (!card->wandev.piggyback){
-		err = intr_test(card);
-
-		if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { 
-			printk(KERN_ERR "%s: Interrupt test failed (%i)\n",
-					card->devname, Intr_test_counter);
-			printk(KERN_ERR "%s: Please choose another interrupt\n",
-					card->devname);
-			return  -EIO;
-		}
-			
-		printk(KERN_INFO "%s: Interrupt test passed (%i)\n", 
-				card->devname, Intr_test_counter);
-	}
-
-
-	if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
-		printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
-				card->devname);
-		return -EIO;	
-        }
-	
-	/* Mask the Timer interrupt */
-	flags->interrupt_info_struct.interrupt_permission &= 
-		~APP_INT_ON_TIMER;
-
-	printk(KERN_INFO "\n");
-
-	return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3 
- * different locations:
- * 	1) The 'if_stats' recorded for the device.
- * 	2) Communication error statistics on the adapter.
- *      3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we 
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
-	sdla_t* card = wandev->private;
- 	struct net_device* dev;
-        volatile chdlc_private_area_t* chdlc_priv_area;
-        SHARED_MEMORY_INFO_STRUCT *flags;
-	unsigned long timeout;
-
-	/* sanity checks */
-	if((wandev == NULL) || (wandev->private == NULL))
-		return -EFAULT;
-	
-	if(wandev->state == WAN_UNCONFIGURED)
-		return -ENODEV;
-
-	/* more sanity checks */
-        if(!card->u.c.flags)
-                return -ENODEV;
-
-	if((dev=card->wandev.dev) == NULL)
-		return -ENODEV;
-
-	if((chdlc_priv_area=dev->priv) == NULL)
-		return -ENODEV;
-
-      	flags = card->u.c.flags;
-
-       	if(chdlc_priv_area->update_comms_stats){
-		return -EAGAIN;
-	}
-			
-	/* we will need 2 timer interrupts to complete the */
-	/* reading of the statistics */
-	chdlc_priv_area->update_comms_stats = 2;
-       	flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
-	chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-  
-	/* wait a maximum of 1 second for the statistics to be updated */ 
-        timeout = jiffies + 1 * HZ;
-        for(;;) {
-		if(chdlc_priv_area->update_comms_stats == 0)
-			break;
-                if (time_after(jiffies, timeout)){
-    			chdlc_priv_area->update_comms_stats = 0;
- 			chdlc_priv_area->timer_int_enabled &=
-				~TMR_INT_ENABLED_UPDATE; 
- 			return -EAGAIN;
-		}
-        }
-
-	return 0;
-}
-
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return:	0	o.k.
- *		< 0	failure (channel will not be created)
- */
-static int new_if(struct wan_device* wandev, struct net_device* pdev,
-		  wanif_conf_t* conf)
-{
-
-	struct ppp_device *pppdev = (struct ppp_device *)pdev;
-	struct net_device *dev = NULL;
-	struct sppp *sp;
-	sdla_t* card = wandev->private;
-	chdlc_private_area_t* chdlc_priv_area;
-	
-	if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) {
-		printk(KERN_INFO "%s: invalid interface name!\n",
-			card->devname);
-		return -EINVAL;
-	}
-		
-	/* allocate and initialize private data */
-	chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-	
-	if(chdlc_priv_area == NULL) 
-		return -ENOMEM;
-
-	memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
-	chdlc_priv_area->card = card; 
-
-	/* initialize data */
-	strcpy(card->u.c.if_name, conf->name);
-
-	if(card->wandev.new_if_cnt > 0) {
-                kfree(chdlc_priv_area);
-		return -EEXIST;
-	}
-
-	card->wandev.new_if_cnt++;
-
-	chdlc_priv_area->TracingEnabled = 0;
-
-	//We don't need this any more
-	chdlc_priv_area->route_status = NO_ROUTE;
-	chdlc_priv_area->route_removed = 0;
-
-	printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",
-		wandev->name);
-	
-	/* Setup wanpipe as a router (WANPIPE) or as an API */
-	if( strcmp(conf->usedby, "WANPIPE") == 0) {
-		printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",
-			wandev->name);
-		card->u.c.usedby = WANPIPE;
-	} else {
-		printk(KERN_INFO 
-			"%s: API Mode is not supported for SyncPPP!\n",
-			wandev->name);
-		kfree(chdlc_priv_area);
-		return -EINVAL;
-	}
-
-	/* Get Multicast Information */
-	chdlc_priv_area->mc = conf->mc;
-
-
-	chdlc_priv_area->if_ptr = pppdev;
-
-	/* prepare network device data space for registration */
-
-	strcpy(dev->name,card->u.c.if_name);
-
-	/* Attach PPP protocol layer to pppdev
-	 * The sppp_attach() will initilize the dev structure
-         * and setup ppp layer protocols.
-         * All we have to do is to bind in:
-         *        if_open(), if_close(), if_send() and get_stats() functions.
-         */
-	sppp_attach(pppdev);
-	dev = pppdev->dev;
-	sp = &pppdev->sppp;
-	
-	/* Enable PPP Debugging */
-	// FIXME Fix this up somehow
-	//sp->pp_flags |= PP_DEBUG; 	
-	sp->pp_flags &= ~PP_CISCO;
-
-	dev->init = &if_init;
-	dev->priv = chdlc_priv_area;
-	
-	return 0;
-}
-
-
-
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
-	chdlc_private_area_t *chdlc_priv_area = dev->priv;
-	sdla_t *card = chdlc_priv_area->card;
-	unsigned long smp_lock;
-	
-	/* Detach the PPP layer */
-	printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",
-			wandev->name,dev->name);
-
-	lock_adapter_irq(&wandev->lock,&smp_lock);
-
-	sppp_detach(dev);
-	chdlc_priv_area->if_ptr=NULL;
-	
-	chdlc_set_intr_mode(card, 0);
-	if (card->u.c.comm_enabled)
-		chdlc_comm_disable(card);
-	unlock_adapter_irq(&wandev->lock,&smp_lock);
-	
-	port_set_state(card, WAN_DISCONNECTED);
-
-	return 0;
-}
-
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration.  Returning anything but zero will fail interface
- * registration.
- */
-static int if_init(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-	struct wan_device* wandev = &card->wandev;
-	
-	/* NOTE: Most of the dev initialization was
-         *       done in sppp_attach(), called by new_if() 
-         *       function. All we have to do here is
-         *       to link four major routines below. 
-         */
-
-	/* Initialize device driver entry points */
-	dev->open		= &if_open;
-	dev->stop		= &if_close;
-	dev->hard_start_xmit	= &if_send;
-	dev->get_stats		= &if_stats;
-	dev->tx_timeout		= &if_tx_timeout;
-	dev->watchdog_timeo	= TX_TIMEOUT;
-
-
-	/* Initialize hardware parameters */
-	dev->irq	= wandev->irq;
-	dev->dma	= wandev->dma;
-	dev->base_addr	= wandev->ioport;
-	dev->mem_start	= wandev->maddr;
-	dev->mem_end	= wandev->maddr + wandev->msize - 1;
-
-	/* Set transmit buffer queue length 
-         * If we over fill this queue the packets will
-         * be droped by the kernel.
-         * sppp_attach() sets this to 10, but
-         * 100 will give us more room at low speeds.
-	 */
-        dev->tx_queue_len = 100;
-   
-	return 0;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
-    	chdlc_private_area_t* chan = dev->priv;
-	sdla_t *card = chan->card;
-	
-	/* If our device stays busy for at least 5 seconds then we will
-	 * kick start the device by making dev->tbusy = 0.  We expect
-	 * that our device never stays busy more than 5 seconds. So this                 
-	 * is only used as a last resort.
-	 */
-
-	++card->wandev.stats.collisions;
-
-	printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
-	netif_wake_queue (dev);
-}
-
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-	struct timeval tv;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
-	/* Only one open per interface is allowed */
-	if (netif_running(dev))
-		return -EBUSY;
-
-	/* Start PPP Layer */
-	if (sppp_open(dev)){
-		return -EIO;
-	}
-
-	do_gettimeofday(&tv);
-	chdlc_priv_area->router_start_time = tv.tv_sec;
- 
-	netif_start_queue(dev);
-	
-	wanpipe_open(card);
-
-	chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
-	flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
-	return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
-	chdlc_private_area_t* chdlc_priv_area = dev->priv;
-	sdla_t* card = chdlc_priv_area->card;
-
-	/* Stop the PPP Layer */
-	sppp_close(dev);
-	netif_stop_queue(dev);
-
-	wanpipe_close(card);
-	
-	return 0;
-}
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- *   transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * o free socket buffer
- *
- * Return:	0	complete (socket buffer must be freed)
- *		non-0	packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- *    bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- *    protocol stack and can be used for flow control with protocol layer.
- */
-static int if_send(struct sk_buff* skb, struct net_device* dev)
-{
-	chdlc_private_area_t *chdlc_priv_area = dev->priv;
-	sdla_t *card = chdlc_priv_area->card;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
-	int udp_type = 0;
-	unsigned long smp_flags;
-	int err=0;
-
-	netif_stop_queue(dev);
-
-	
-	if (skb == NULL){
-		/* If we get here, some higher layer thinks we've missed an
-		 * tx-done interrupt.
-		 */
-		printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
-			card->devname, dev->name);
-
-		netif_wake_queue(dev);
-		return 0;
-	}
-
-   	if (ntohs(skb->protocol) != htons(PVC_PROT)){
-		/* check the udp packet type */
-		
-		udp_type = udp_pkt_type(skb, card);
-		if (udp_type == UDP_CPIPE_TYPE){
-                        if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
-                                chdlc_priv_area)){
-				chdlc_int->interrupt_permission |=
-					APP_INT_ON_TIMER;
-			}
-			netif_start_queue(dev);
-			return 0;
-		}
-        }
-
-	/* Lock the 508 Card: SMP is supported */
-      	if(card->hw.type != SDLA_S514){
-		s508_lock(card,&smp_flags);
-	} 
-
-    	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-	
-		printk(KERN_INFO "%s: Critical in if_send: %lx\n",
-					card->wandev.name,card->wandev.critical);
-                ++card->wandev.stats.tx_dropped;
-		netif_start_queue(dev);
-		goto if_send_crit_exit;
-	}
-
-	if (card->wandev.state != WAN_CONNECTED){
-		++card->wandev.stats.tx_dropped;
-		netif_start_queue(dev);
-		goto if_send_crit_exit;
-	}
-	
-	if (chdlc_send(card, skb->data, skb->len)){
-		netif_stop_queue(dev);
-
-	}else{
-		++card->wandev.stats.tx_packets;
-       		card->wandev.stats.tx_bytes += skb->len;
-		dev->trans_start = jiffies;
-		netif_start_queue(dev);
-	}	
-
-if_send_crit_exit:
-	if (!(err=netif_queue_stopped(dev))){
-                dev_kfree_skb_any(skb);
-	}else{
-		chdlc_priv_area->tick_counter = jiffies;
-		chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
-	}
-
-	clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
-	if(card->hw.type != SDLA_S514){
-		s508_unlock(card,&smp_flags);
-	}
-
-	return err;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
-	unsigned short len, udp_length, temp, ip_length;
-	unsigned long ip_temp;
-	int even_bound = 0;
-  	chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-	 
-	/* Set length of packet */
-	len = sizeof(ip_pkt_t)+ 
-	      sizeof(udp_pkt_t)+
-	      sizeof(wp_mgmt_t)+
-	      sizeof(cblock_t)+
-	      sizeof(trace_info_t)+ 
-	      mbox_len;
-
-	/* fill in UDP reply */
-	c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-   
-	/* fill in UDP length */
-	udp_length = sizeof(udp_pkt_t)+ 
-		     sizeof(wp_mgmt_t)+
-		     sizeof(cblock_t)+
-	             sizeof(trace_info_t)+
-		     mbox_len; 
-
- 	/* put it on an even boundary */
-	if ( udp_length & 0x0001 ) {
-		udp_length += 1;
-		len += 1;
-		even_bound = 1;
-	}  
-
-	temp = (udp_length<<8)|(udp_length>>8);
-	c_udp_pkt->udp_pkt.udp_length = temp;
-		 
-	/* swap UDP ports */
-	temp = c_udp_pkt->udp_pkt.udp_src_port;
-	c_udp_pkt->udp_pkt.udp_src_port = 
-			c_udp_pkt->udp_pkt.udp_dst_port; 
-	c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
-	/* add UDP pseudo header */
-	temp = 0x1100;
-	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;	
-	temp = (udp_length<<8)|(udp_length>>8);
-	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-		 
-	/* calculate UDP checksum */
-	c_udp_pkt->udp_pkt.udp_checksum = 0;
-	c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
-	/* fill in IP length */
-	ip_length = len;
-	temp = (ip_length<<8)|(ip_length>>8);
-	c_udp_pkt->ip_pkt.total_length = temp;
-  
-	/* swap IP addresses */
-	ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
-	c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
-	c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
-	/* fill in IP checksum */
-	c_udp_pkt->ip_pkt.hdr_checksum = 0;
-	c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
-	return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
-	unsigned short temp; 
-	unsigned long sum=0;
-	int i;
-
-	for( i = 0; i <len; i+=2 ) {
-		memcpy(&temp,&data[i],2);
-		sum += (unsigned long)temp;
-	}
-
-	while (sum >> 16 ) {
-		sum = (sum & 0xffffUL) + (sum >> 16);
-	}
-
-	temp = (unsigned short)sum;
-	temp = ~temp;
-
-	if( temp == 0 ) 
-		temp = 0xffff;
-
-	return temp;	
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
-	sdla_t *my_card;
-	chdlc_private_area_t* chdlc_priv_area;
-
-	/* Shutdown bug fix. In del_if() we kill
-         * dev->priv pointer. This function, gets
-         * called after del_if(), thus check
-         * if pointer has been deleted */
-	if ((chdlc_priv_area=dev->priv) == NULL)
-		return NULL;
-
-	my_card = chdlc_priv_area->card;
-	return &my_card->wandev.stats; 
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- *	Put code version as ASCII string in str. 
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int len;
-	char err;
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_CODE_VERSION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	if(err != COMMAND_OK) {
-		chdlc_error(card,err,mb);
-	}
-	else if (str) {  /* is not null */
-		len = mb->buffer_length;
-		memcpy(str, mb->data, len);
-		str[len] = '\0';
-	}
-	return (err);
-}
-
-/*-----------------------------------------------------------------------------
- *  Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
-	int err;
-	CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
-	int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-	
-	mailbox->buffer_length = data_length;  
-	memcpy(mailbox->data, data, data_length);
-	mailbox->command = SET_CHDLC_CONFIGURATION;
-	err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-	
-	if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-                           
-	return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	CHDLC_INT_TRIGGERS_STRUCT* int_data =
-		 (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
-	int err;
-
-	int_data->CHDLC_interrupt_triggers 	= mode;
-	int_data->IRQ				= card->hw.irq;
-	int_data->interrupt_timer               = 1;
-   
-	mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
-	mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK)
-		chdlc_error (card, err, mb);
-	return err;
-}
-
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
-	int err;
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-	mb->buffer_length = 0;
-	mb->command = ENABLE_CHDLC_COMMUNICATIONS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK)
-		chdlc_error(card, err, mb);
-	else
-		card->u.c.comm_enabled=1;
-
-	return err;
-}
-
-/*============================================================================
- * Disable communications and Drop the Modem lines (DCD and RTS).
- */
-static int chdlc_comm_disable (sdla_t* card)
-{
-	int err;
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-	mb->buffer_length = 0;
-	mb->command = DISABLE_CHDLC_COMMUNICATIONS;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if (err != COMMAND_OK)
-		chdlc_error(card,err,mb);
-
-	return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
-        int err;
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-        mb->buffer_length = 0;
-        mb->command = READ_COMMS_ERROR_STATS;
-        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-        if (err != COMMAND_OK)
-                chdlc_error(card,err,mb);
-        return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
-        int err;
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
-        mb->buffer_length = 0;
-        mb->command = READ_CHDLC_OPERATIONAL_STATS;
-        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-        if (err != COMMAND_OK)
-                chdlc_error(card,err,mb);
-        return err;
-}
-
-
-/*============================================================================
- * Update communications error and general packet statistics.
- */
-static int update_comms_stats(sdla_t* card,
-	chdlc_private_area_t* chdlc_priv_area)
-{
-        CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-  	COMMS_ERROR_STATS_STRUCT* err_stats;
-        CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;
-
-	/* on the first timer interrupt, read the comms error statistics */
-	if(chdlc_priv_area->update_comms_stats == 2) {
-		if(chdlc_read_comm_err_stats(card))
-			return 1;
-		err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;
-		card->wandev.stats.rx_over_errors = 
-				err_stats->Rx_overrun_err_count;
-		card->wandev.stats.rx_crc_errors = 
-				err_stats->CRC_err_count;
-		card->wandev.stats.rx_frame_errors = 
-				err_stats->Rx_abort_count;
-		card->wandev.stats.rx_fifo_errors = 
-				err_stats->Rx_dis_pri_bfrs_full_count; 
-		card->wandev.stats.rx_missed_errors =
-				card->wandev.stats.rx_fifo_errors;
-		card->wandev.stats.tx_aborted_errors =
-				err_stats->sec_Tx_abort_count;
-	}
-
-        /* on the second timer interrupt, read the operational statistics */
-	else {
-        	if(chdlc_read_op_stats(card))
-                	return 1;
-		op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;
-		card->wandev.stats.rx_length_errors =
-			(op_stats->Rx_Data_discard_short_count +
-			op_stats->Rx_Data_discard_long_count);
-	}
-
-	return 0;
-}
-
-/*============================================================================
- * Send packet.
- *	Return:	0 - o.k.
- *		1 - no transmit buffers available
- */
-static int chdlc_send (sdla_t* card, void* data, unsigned len)
-{
-	CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;
-
-	if (txbuf->opp_flag)
-		return 1;
-	
-	sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);
-
-	txbuf->frame_length = len;
-	txbuf->opp_flag = 1;		/* start transmission */
-	
-	/* Update transmit buffer control fields */
-	card->u.c.txbuf = ++txbuf;
-
-	if ((void*)txbuf > card->u.c.txbuf_last)
-		card->u.c.txbuf = card->u.c.txbuf_base;
-
-	return 0;
-}
-
-/****** Firmware Error Handler **********************************************/
-
-/*============================================================================
- * Firmware error handler.
- *	This routine is called whenever firmware command returns non-zero
- *	return code.
- *
- * Return zero if previous command has to be cancelled.
- */
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
-{
-	unsigned cmd = mb->command;
-
-	switch (err) {
-
-	case CMD_TIMEOUT:
-		printk(KERN_ERR "%s: command 0x%02X timed out!\n",
-			card->devname, cmd);
-		break;
-
-	case S514_BOTH_PORTS_SAME_CLK_MODE:
-		if(cmd == SET_CHDLC_CONFIGURATION) {
-			printk(KERN_INFO
-			 "%s: Configure both ports for the same clock source\n",
-				card->devname);
-			break;
-		}
-
-	default:
-		printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
-			card->devname, cmd, err);
-	}
-
-	return 0;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * Cisco HDLC interrupt service routine.
- */
-STATIC void wsppp_isr (sdla_t* card)
-{
-	struct net_device* dev;
-	SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-	int i;
-	sdla_t *my_card;
-
-
-	/* Check for which port the interrupt has been generated
-	 * Since Secondary Port is piggybacking on the Primary
-         * the check must be done here. 
-	 */
-
-	flags = card->u.c.flags;
-	if (!flags->interrupt_info_struct.interrupt_type){
-		/* Check for a second port (piggybacking) */
-		if((my_card = card->next)){
-			flags = my_card->u.c.flags;
-			if (flags->interrupt_info_struct.interrupt_type){
-				card = my_card;
-				card->isr(card);
-				return;
-			}
-		}
-	}
-
-	dev = card->wandev.dev;
-	card->in_isr = 1;
-	flags = card->u.c.flags;
-		
-	/* If we get an interrupt with no network device, stop the interrupts
-	 * and issue an error */
-	if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type != 
-	    	COMMAND_COMPLETE_APP_INT_PEND){
-		goto isr_done;
-	}
-
-	
-	/* if critical due to peripheral operations
-	 * ie. update() or getstats() then reset the interrupt and
-	 * wait for the board to retrigger.
-	 */
-	if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {
-		flags->interrupt_info_struct.
-					interrupt_type = 0;
-		goto isr_done;
-	}
-
-
-	/* On a 508 Card, if critical due to if_send 
-         * Major Error !!!
-	 */
-	if(card->hw.type != SDLA_S514) {
-		if(test_bit(0, (void*)&card->wandev.critical)) {
-			printk(KERN_INFO "%s: Critical while in ISR: %lx\n",
-				card->devname, card->wandev.critical);
-			goto isr_done;
-		}
-	}
-
-	switch(flags->interrupt_info_struct.interrupt_type) {
-
-		case RX_APP_INT_PEND:	/* 0x01: receive interrupt */
-			rx_intr(card);
-			break;
-
-		case TX_APP_INT_PEND:	/* 0x02: transmit interrupt */
-			flags->interrupt_info_struct.interrupt_permission &=
-				 ~APP_INT_ON_TX_FRAME;
-
-			netif_wake_queue(dev);
-			break;
-
-		case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */
-			++ Intr_test_counter;
-			break;
-
-		case CHDLC_EXCEP_COND_APP_INT_PEND:	/* 0x20 */
-			process_chdlc_exception(card);
-			break;
-
-		case GLOBAL_EXCEP_COND_APP_INT_PEND:
-			process_global_exception(card);
-			break;
-
-		case TIMER_APP_INT_PEND:
-			timer_intr(card);
-			break;
-
-		default:
-			printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", 
-				card->devname,
-				flags->interrupt_info_struct.interrupt_type);
-			printk(KERN_INFO "Code name: ");
-			for(i = 0; i < 4; i ++)
-				printk(KERN_INFO "%c",
-					flags->global_info_struct.codename[i]); 
-			printk(KERN_INFO "\nCode version: ");
-			for(i = 0; i < 4; i ++)
-				printk(KERN_INFO "%c", 
-					flags->global_info_struct.codeversion[i]); 
-			printk(KERN_INFO "\n");	
-			break;
-	}
-
-isr_done:
-	card->in_isr = 0;
-	flags->interrupt_info_struct.interrupt_type = 0;
-}
-
-/*============================================================================
- * Receive interrupt handler.
- */
-static void rx_intr (sdla_t* card)
-{
-	struct net_device *dev;
-	chdlc_private_area_t *chdlc_priv_area;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;
-	struct sk_buff *skb;
-	unsigned len;
-	unsigned addr = rxbuf->ptr_data_bfr;
-	void *buf;
-	int i,udp_type;
-	
-	if (rxbuf->opp_flag != 0x01) {
-		printk(KERN_INFO 
-			"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", 
-			card->devname, (unsigned)rxbuf, rxbuf->opp_flag);
-                printk(KERN_INFO "Code name: ");
-                for(i = 0; i < 4; i ++)
-                        printk(KERN_INFO "%c",
-                                flags->global_info_struct.codename[i]);
-                printk(KERN_INFO "\nCode version: ");
-                for(i = 0; i < 4; i ++)
-                        printk(KERN_INFO "%c",
-                                flags->global_info_struct.codeversion[i]);
-                printk(KERN_INFO "\n");
-
-
-		/* Bug Fix: Mar 6 2000
-                 * If we get a corrupted mailbox, it measn that driver 
-                 * is out of sync with the firmware. There is no recovery.
-                 * If we don't turn off all interrupts for this card
-                 * the machine will crash. 
-                 */
-		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);
-		printk(KERN_INFO "Please contact Sangoma Technologies !\n");
-		chdlc_set_intr_mode(card,0);	
-		return;
-	}
-
-	dev = card->wandev.dev;
-
-	if (!dev){ 
-		goto rx_exit;
-	}
-	
-	if (!netif_running(dev)){
-		goto rx_exit;
-	}
-
-	chdlc_priv_area = dev->priv;
-
-	if (rxbuf->error_flag){	
-		goto rx_exit;
-	}
-	/* Take off two CRC bytes */
-
-	if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){
-		goto rx_exit;
-	}	
-
-	len = rxbuf->frame_length - CRC_LENGTH;
-
-	/* Allocate socket buffer */
-	skb = dev_alloc_skb(len);
-
-	if (skb == NULL) {
-		if (net_ratelimit()){
-			printk(KERN_INFO "%s: no socket buffers available!\n",
-						card->devname);
-		}
-		++card->wandev.stats.rx_dropped;
-		goto rx_exit;
-	}
-
-	/* Copy data to the socket buffer */
-	if((addr + len) > card->u.c.rx_top + 1) {
-		unsigned tmp = card->u.c.rx_top - addr + 1;
-		buf = skb_put(skb, tmp);
-		sdla_peek(&card->hw, addr, buf, tmp);
-		addr = card->u.c.rx_base;
-		len -= tmp;
-	}
-		
-	buf = skb_put(skb, len);
-	sdla_peek(&card->hw, addr, buf, len);
-
-	skb->protocol = htons(ETH_P_WAN_PPP);
-
-	card->wandev.stats.rx_packets ++;
-	card->wandev.stats.rx_bytes += skb->len;
-	udp_type = udp_pkt_type( skb, card );
-
-	if(udp_type == UDP_CPIPE_TYPE) {
-		if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,
-   				      card, skb, dev, chdlc_priv_area)) {
-     		        flags->interrupt_info_struct.
-						interrupt_permission |= 
-							APP_INT_ON_TIMER; 
-		}
-	}else{
-               	/* Pass it up the protocol stack */
-                skb->dev = dev;
-                skb->mac.raw  = skb->data;
-                netif_rx(skb);
-                dev->last_rx = jiffies;
-	}
-
-rx_exit:
-	/* Release buffer element and calculate a pointer to the next one */
-	rxbuf->opp_flag = 0x00;
-	card->u.c.rxmb = ++ rxbuf;
-	if((void*)rxbuf > card->u.c.rxbuf_last){
-		card->u.c.rxmb = card->u.c.rxbuf_base;
-	}
-}
-
-/*============================================================================
- * Timer interrupt handler.
- * The timer interrupt is used for two purposes:
- *    1) Processing udp calls from 'cpipemon'.
- *    2) Reading board-level statistics for updating the proc file system.
- */
-void timer_intr(sdla_t *card)
-{
-        struct net_device* dev;
-        chdlc_private_area_t* chdlc_priv_area = NULL;
-        SHARED_MEMORY_INFO_STRUCT* flags = NULL;
-
-        dev = card->wandev.dev; 
-        chdlc_priv_area = dev->priv;
-
-	if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {
-		if (!config_chdlc(card)){
-			chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;
-		}
-	}
-	
-	/* process a udp call if pending */
-       	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {
-               	process_udp_mgmt_pkt(card, dev,
-                       chdlc_priv_area);
-		chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;
-        }
-	
-
-	/* read the communications statistics if required */
-	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {
-		update_comms_stats(card, chdlc_priv_area);
-                if(!(-- chdlc_priv_area->update_comms_stats)) {
-			chdlc_priv_area->timer_int_enabled &= 
-				~TMR_INT_ENABLED_UPDATE;
-		}
-        }
-
-	/* only disable the timer interrupt if there are no udp or statistic */
-	/* updates pending */
-        if(!chdlc_priv_area->timer_int_enabled) {
-                flags = card->u.c.flags;
-                flags->interrupt_info_struct.interrupt_permission &=
-                        ~APP_INT_ON_TIMER;
-        }
-}
-
-/*------------------------------------------------------------------------------
-  Miscellaneous Functions
-	- set_chdlc_config() used to set configuration options on the board
-------------------------------------------------------------------------------*/
-
-static int set_chdlc_config(sdla_t* card)
-{
-
-	CHDLC_CONFIGURATION_STRUCT cfg;
-
-	memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));
-
-	if(card->wandev.clocking)
-		cfg.baud_rate = card->wandev.bps;
-
-	cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
-		INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
-
-	cfg.modem_config_options	= 0;
-	//API OPTIONS
-	cfg.CHDLC_API_options		= DISCARD_RX_ERROR_FRAMES;
-	cfg.modem_status_timer		= 100;
-	cfg.CHDLC_protocol_options	= HDLC_STREAMING_MODE;
-	cfg.percent_data_buffer_for_Tx  = 50;
-	cfg.CHDLC_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |
-		CHDLC_RX_DATA_BYTE_COUNT_STAT);
-	cfg.max_CHDLC_data_field_length	= card->wandev.mtu;
-
-	cfg.transmit_keepalive_timer	= 0;
-	cfg.receive_keepalive_timer	= 0;
-	cfg.keepalive_error_tolerance	= 0;
-	cfg.SLARP_request_timer		= 0;
-
-	cfg.IP_address		= 0;
-	cfg.IP_netmask		= 0;
-	
-	return chdlc_configure(card, &cfg);
-}
-
-/*============================================================================
- * Process global exception condition
- */
-static int process_global_exception(sdla_t *card)
-{
-	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
-	int err;
-
-	mbox->buffer_length = 0;
-	mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
-	err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
-
-	if(err != CMD_TIMEOUT ){
-	
-		switch(mbox->return_code) {
-         
-	      	case EXCEP_MODEM_STATUS_CHANGE:
-
-			printk(KERN_INFO "%s: Modem status change\n",
-				card->devname);
-
-			switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
-				case (DCD_HIGH):
-					printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);
-					break;
-				case (CTS_HIGH):
-                                        printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);
-                                        break;
-                                case ((DCD_HIGH | CTS_HIGH)):
-                                        printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);
-                                        break;
-				default:
-                                        printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);
-                                        break;
-			}
-
-			if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){
-				//printk(KERN_INFO "Sending TERM Request Manually !\n");
-				send_ppp_term_request(card->wandev.dev);
-			}	
-			break;
-
-                case EXCEP_TRC_DISABLED:
-                        printk(KERN_INFO "%s: Line trace disabled\n",
-				card->devname);
-                        break;
-
-		case EXCEP_IRQ_TIMEOUT:
-			printk(KERN_INFO "%s: IRQ timeout occurred\n",
-				card->devname); 
-			break;
-
-                default:
-                        printk(KERN_INFO "%s: Global exception %x\n",
-				card->devname, mbox->return_code);
-                        break;
-                }
-	}
-	return 0;
-}
-
-
-/*============================================================================
- * Process chdlc exception condition
- */
-static int process_chdlc_exception(sdla_t *card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int err;
-
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_EXCEPTION_CONDITION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-	if(err != CMD_TIMEOUT) {
-	
-		switch (err) {
-
-		case EXCEP_LINK_ACTIVE:
-			port_set_state(card, WAN_CONNECTED);
-			break;
-
-		case EXCEP_LINK_INACTIVE_MODEM:
-			port_set_state(card, WAN_DISCONNECTED);
-			break;
-
-		case EXCEP_LOOPBACK_CONDITION:
-			printk(KERN_INFO "%s: Loopback Condition Detected.\n",
-						card->devname);
-			break;
-
-		case NO_CHDLC_EXCEP_COND_TO_REPORT:
-			printk(KERN_INFO "%s: No exceptions reported.\n",
-						card->devname);
-			break;
-		default:
-			printk(KERN_INFO "%s: Exception Condition %x!\n",
-					card->devname,err);
-			break;
-		}
-
-	}
-	return 0;
-}
-
-
-/*=============================================================================
- * Store a UDP management packet for later processing.
- */
-
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
-			      struct sk_buff *skb, struct net_device* dev,
-			      chdlc_private_area_t* chdlc_priv_area )
-{
-	int udp_pkt_stored = 0;
-
-	if(!chdlc_priv_area->udp_pkt_lgth &&
-	  (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
-        	chdlc_priv_area->udp_pkt_lgth = skb->len;
-		chdlc_priv_area->udp_pkt_src = udp_pkt_src;
-       		memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
-		chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
-		udp_pkt_stored = 1;
-	}
-
-	if(udp_pkt_src == UDP_PKT_FRM_STACK)
-		dev_kfree_skb_any(skb);
-	else
-                dev_kfree_skb_any(skb);
-	
-	return(udp_pkt_stored);
-}
-
-
-/*=============================================================================
- * Process UDP management packet.
- */
-
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
-				chdlc_private_area_t* chdlc_priv_area ) 
-{
-	unsigned char *buf;
-	unsigned int frames, len;
-	struct sk_buff *new_skb;
-	unsigned short buffer_length, real_len;
-	unsigned long data_ptr;
-	unsigned data_length;
-	int udp_mgmt_req_valid = 1;
-	CHDLC_MAILBOX_STRUCT *mb = card->mbox;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-	chdlc_udp_pkt_t *chdlc_udp_pkt;
-	struct timeval tv;
-	int err;
-	char ut_char;
-
-	chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
-
-	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-
-		switch(chdlc_udp_pkt->cblock.command) {
-			case READ_GLOBAL_STATISTICS:
-			case READ_MODEM_STATUS:  
-			case READ_CHDLC_LINK_STATUS:
-			case CPIPE_ROUTER_UP_TIME:
-			case READ_COMMS_ERROR_STATS:
-			case READ_CHDLC_OPERATIONAL_STATS:
-
-			/* These two commands are executed for
-			 * each request */
-			case READ_CHDLC_CONFIGURATION:
-			case READ_CHDLC_CODE_VERSION:
-				udp_mgmt_req_valid = 1;
-				break;
-			default:
-				udp_mgmt_req_valid = 0;
-				break;
-		} 
-	}
-	
-  	if(!udp_mgmt_req_valid) {
-
-		/* set length to 0 */
-		chdlc_udp_pkt->cblock.buffer_length = 0;
-
-    		/* set return code */
-		chdlc_udp_pkt->cblock.return_code = 0xCD;
-
-		if (net_ratelimit()){	
-			printk(KERN_INFO 
-			"%s: Warning, Illegal UDP command attempted from network: %x\n",
-			card->devname,chdlc_udp_pkt->cblock.command);
-		}
-
-   	} else {
-	   	unsigned long trace_status_cfg_addr = 0;
-		TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
-		TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
-
-		switch(chdlc_udp_pkt->cblock.command) {
-
-		case CPIPE_ENABLE_TRACING:
-		     if (!chdlc_priv_area->TracingEnabled) {
-
-			/* OPERATE_DATALINE_MONITOR */
-
-			mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
-			mb->command = SET_TRACE_CONFIGURATION;
-
-    			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-				trace_config = TRACE_ACTIVE;
-			/* Trace delay mode is not used because it slows
-			   down transfer and results in a standoff situation
-			   when there is a lot of data */
-
-			/* Configure the Trace based on user inputs */
-			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= 
-					chdlc_udp_pkt->data[0];
-
-			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-			   trace_deactivation_timer = 4000;
-
-
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-			if (err != COMMAND_OK) {
-				chdlc_error(card,err,mb);
-				card->TracingEnabled = 0;
-				chdlc_udp_pkt->cblock.return_code = err;
-				mb->buffer_length = 0;
-				break;
-	    		} 
-
-			/* Get the base address of the trace element list */
-			mb->buffer_length = 0;
-			mb->command = READ_TRACE_CONFIGURATION;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-			if (err != COMMAND_OK) {
-				chdlc_error(card,err,mb);
-				chdlc_priv_area->TracingEnabled = 0;
-				chdlc_udp_pkt->cblock.return_code = err;
-				mb->buffer_length = 0;
-				break;
-	    		} 	
-
-	   		trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
-				mb->data) -> ptr_trace_stat_el_cfg_struct;
-
-			sdla_peek(&card->hw, trace_status_cfg_addr,
-				 &trace_cfg_struct, sizeof(trace_cfg_struct));
-		    
-			chdlc_priv_area->start_trace_addr = trace_cfg_struct.
-				base_addr_trace_status_elements;
-
-			chdlc_priv_area->number_trace_elements = 
-					trace_cfg_struct.number_trace_status_elements;
-
-			chdlc_priv_area->end_trace_addr = (unsigned long)
-					((TRACE_STATUS_ELEMENT_STRUCT *)
-					 chdlc_priv_area->start_trace_addr + 
-					 (chdlc_priv_area->number_trace_elements - 1));
-
-			chdlc_priv_area->base_addr_trace_buffer = 
-					trace_cfg_struct.base_addr_trace_buffer;
-
-			chdlc_priv_area->end_addr_trace_buffer = 
-					trace_cfg_struct.end_addr_trace_buffer;
-
-		    	chdlc_priv_area->curr_trace_addr = 
-					trace_cfg_struct.next_trace_element_to_use;
-
-	    		chdlc_priv_area->available_buffer_space = 2000 - 
-								  sizeof(ip_pkt_t) -
-								  sizeof(udp_pkt_t) -
-							      	  sizeof(wp_mgmt_t) -
-								  sizeof(cblock_t) -
-							          sizeof(trace_info_t);	
-	       	     }
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-		     mb->buffer_length = 0;
-	       	     chdlc_priv_area->TracingEnabled = 1;
-	       	     break;
-	   
-
-		case CPIPE_DISABLE_TRACING:
-		     if (chdlc_priv_area->TracingEnabled) {
-
-			/* OPERATE_DATALINE_MONITOR */
-			mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
-			mb->command = SET_TRACE_CONFIGURATION;
-    			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
-				trace_config = TRACE_INACTIVE;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-		     }		
-
-		     chdlc_priv_area->TracingEnabled = 0;
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-		     mb->buffer_length = 0;
-		     break;
-	   
-
-		case CPIPE_GET_TRACE_INFO:
-
-		     if (!chdlc_priv_area->TracingEnabled) {
-			chdlc_udp_pkt->cblock.return_code = 1;
-			mb->buffer_length = 0;
-			break;
-		     }
-
-  		     chdlc_udp_pkt->trace_info.ismoredata = 0x00;
-		     buffer_length = 0;	/* offset of packet already occupied */
-
-		     for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
-
-			trace_pkt_t *trace_pkt = (trace_pkt_t *)
-				&chdlc_udp_pkt->data[buffer_length];
-
-			sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
-			   	  (unsigned char *)&trace_element_struct,
-			   	  sizeof(TRACE_STATUS_ELEMENT_STRUCT));
-
-     			if (trace_element_struct.opp_flag == 0x00) {
-			 	break;
-			}
-
-			/* get pointer to real data */
-			data_ptr = trace_element_struct.ptr_data_bfr;
-
-			/* See if there is actual data on the trace buffer */
-			if (data_ptr){
-				data_length = trace_element_struct.trace_length;
-			}else{
-				data_length = 0;
-				chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-			}
-	
-   			if( (chdlc_priv_area->available_buffer_space - buffer_length)
-				< ( sizeof(trace_pkt_t) + data_length) ) {
-
-                            /* indicate there are more frames on board & exit */
-				chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-                               	break;
-                         }
-
-			trace_pkt->status = trace_element_struct.trace_type;
-
-			trace_pkt->time_stamp =
-				trace_element_struct.trace_time_stamp;
-
-			trace_pkt->real_length =
-				trace_element_struct.trace_length;
-
-			/* see if we can fit the frame into the user buffer */
-			real_len = trace_pkt->real_length;
-
-			if (data_ptr == 0) {
-			     	trace_pkt->data_avail = 0x00;
-			} else {
-				unsigned tmp = 0;
-
-				/* get the data from circular buffer
-				    must check for end of buffer */
-			        trace_pkt->data_avail = 0x01;
-
-				if ((data_ptr + real_len) >
-					     chdlc_priv_area->end_addr_trace_buffer + 1){
-
-				    	tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
-				    	sdla_peek(&card->hw, data_ptr,
-					       	  trace_pkt->data,tmp);
-				    	data_ptr = chdlc_priv_area->base_addr_trace_buffer;
-				}
-	
-		        	sdla_peek(&card->hw, data_ptr,
-					  &trace_pkt->data[tmp], real_len - tmp);
-			}	
-
-			/* zero the opp flag to show we got the frame */
-			ut_char = 0x00;
-			sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
-
-       			/* now move onto the next frame */
-       			chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
-
-       			/* check if we went over the last address */
-			if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
-				chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
-       			}
-
-            		if(trace_pkt->data_avail == 0x01) {
-				buffer_length += real_len - 1;
-			}
-	 
-	       	    	/* for the header */
-	            	buffer_length += sizeof(trace_pkt_t);
-
-		     }  /* For Loop */
-
-		     if (frames == chdlc_priv_area->number_trace_elements){
-			chdlc_udp_pkt->trace_info.ismoredata = 0x01;
-	             }
- 		     chdlc_udp_pkt->trace_info.num_frames = frames;
-		 
-    		     mb->buffer_length = buffer_length;
-		     chdlc_udp_pkt->cblock.buffer_length = buffer_length; 
-		 
-		     chdlc_udp_pkt->cblock.return_code = COMMAND_OK; 
-		     
-		     break;
-
-
-		case CPIPE_FT1_READ_STATUS:
-			((unsigned char *)chdlc_udp_pkt->data )[0] =
-				flags->FT1_info_struct.parallel_port_A_input;
-
-			((unsigned char *)chdlc_udp_pkt->data )[1] =
-				flags->FT1_info_struct.parallel_port_B_input;
-				 
-			chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-			mb->buffer_length = 2;
-			break;
-		
-		case CPIPE_ROUTER_UP_TIME:
-			do_gettimeofday( &tv );
-			chdlc_priv_area->router_up_time = tv.tv_sec - 
-					chdlc_priv_area->router_start_time;
-			*(unsigned long *)&chdlc_udp_pkt->data = 
-					chdlc_priv_area->router_up_time;	
-			mb->buffer_length = sizeof(unsigned long);
-			break;
-
-   		case FT1_MONITOR_STATUS_CTRL:
-			/* Enable FT1 MONITOR STATUS */
-	        	if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||  
-				(chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-			
-			     	if( rCount++ != 0 ) {
-					chdlc_udp_pkt->cblock.
-					return_code = COMMAND_OK;
-					mb->buffer_length = 1;
-		  			break;
-		    	     	}
-	      		}
-
-	      		/* Disable FT1 MONITOR STATUS */
-	      		if( chdlc_udp_pkt->data[0] == 0) {
-
-	      	   	     	if( --rCount != 0) {
-		  			chdlc_udp_pkt->cblock.
-					return_code = COMMAND_OK;
-					mb->buffer_length = 1;
-		  			break;
-	   	    	     	} 
-	      		} 	
-	
-		default:
-			/* it's a board command */
-			mb->command = chdlc_udp_pkt->cblock.command;
-			mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
-			if (mb->buffer_length) {
-				memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
-							data, mb->buffer_length);
-	      		} 
-			/* run the command on the board */
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-			if (err != COMMAND_OK) {
-				break;
-			}
-
-			/* copy the result back to our buffer */
-	         	memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); 
-			
-			if (mb->buffer_length) {
-	         		memcpy(&chdlc_udp_pkt->data, &mb->data, 
-								mb->buffer_length); 
-	      		}
-
-		} /* end of switch */
-     	} /* end of else */
-
-     	/* Fill UDP TTL */
-	chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; 
-
-     	len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-	
-     	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {
-		if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
-			++ card->wandev.stats.tx_packets;
-			card->wandev.stats.tx_bytes += len;
-		}
-	} else {	
-	
-		/* Pass it up the stack
-    		   Allocate socket buffer */
-		if ((new_skb = dev_alloc_skb(len)) != NULL) {
-			/* copy data into new_skb */
-
- 	    		buf = skb_put(new_skb, len);
-  	    		memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
-
-            		/* Decapsulate pkt and pass it up the protocol stack */
-	    		new_skb->protocol = htons(ETH_P_IP);
-            		new_skb->dev = dev;
-	    		new_skb->mac.raw  = new_skb->data;
-	
-			netif_rx(new_skb);
-			dev->last_rx = jiffies;
-		} else {
-	    	
-			printk(KERN_INFO "%s: no socket buffers available!\n",
-					card->devname);
-  		}
-    	}
- 
-	chdlc_priv_area->udp_pkt_lgth = 0;
- 	
-	return 0;
-}
-
-/*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
-
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
-	CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
-	char err;
-	
-	mb->buffer_length = 0;
-	mb->command = READ_CHDLC_CONFIGURATION;
-	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
-	if(err != COMMAND_OK) {
-		chdlc_error(card,err,mb);
-		return;
-	}
-
-	if(card->hw.type == SDLA_S514) {
-		tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-                (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-                            ptr_CHDLC_Tx_stat_el_cfg_struct));
-        	rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-                (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-                            ptr_CHDLC_Rx_stat_el_cfg_struct));
-
-       		/* Setup Head and Tails for buffers */
-        	card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
-                tx_config->base_addr_Tx_status_elements);
-        	card->u.c.txbuf_last = 
-		(CHDLC_DATA_TX_STATUS_EL_STRUCT *)  
-                card->u.c.txbuf_base +
-		(tx_config->number_Tx_status_elements - 1);
-
-        	card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
-                rx_config->base_addr_Rx_status_elements);
-        	card->u.c.rxbuf_last =
-		(CHDLC_DATA_RX_STATUS_EL_STRUCT *)
-                card->u.c.rxbuf_base +
-		(rx_config->number_Rx_status_elements - 1);
-
- 		/* Set up next pointer to be used */
-        	card->u.c.txbuf = (void *)(card->hw.dpmbase +
-                tx_config->next_Tx_status_element_to_use);
-        	card->u.c.rxmb = (void *)(card->hw.dpmbase +
-                rx_config->next_Rx_status_element_to_use);
-	}
-        else {
-                tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-			(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-			ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
-                rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
-			(((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
-			ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
-
-                /* Setup Head and Tails for buffers */
-                card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
-		(tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
-                card->u.c.txbuf_last =
-		(CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
-		+ (tx_config->number_Tx_status_elements - 1);
-                card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
-		(rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
-                card->u.c.rxbuf_last = 
-		(CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
-		+ (rx_config->number_Rx_status_elements - 1);
-
-                 /* Set up next pointer to be used */
-                card->u.c.txbuf = (void *)(card->hw.dpmbase +
-		(tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
-                card->u.c.rxmb = (void *)(card->hw.dpmbase +
-		(rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
-        }
-
-        /* Setup Actual Buffer Start and end addresses */
-        card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
-        card->u.c.rx_top  = rx_config->end_addr_Rx_buffer;
-
-}
-
-/*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
-static int intr_test( sdla_t* card)
-{
-	CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-	int err,i;
-
-	Intr_test_counter = 0;
-
-	/* The critical flag is unset because during initialization (if_open) 
-	 * we want the interrupts to be enabled so that when the wpc_isr is
-	 * called it does not exit due to critical flag set.
-	 */ 
-
-	err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
-
-	if (err == CMD_OK) { 
-		for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {	
-			mb->buffer_length  = 0;
-			mb->command = READ_CHDLC_CODE_VERSION;
-			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-		}
-	}
-	else {
-		return err;
-	}
-
-	err = chdlc_set_intr_mode(card, 0);
-
-	if (err != CMD_OK)
-		return err;
-
-	return 0;
-}
-
-/*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
-static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
-{
-	 chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
-
-	if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
-	   (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
-	   (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
-	   (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
-		return UDP_CPIPE_TYPE;
-	}
-	else return UDP_INVALID_TYPE;
-}
-
-/*============================================================================
- * Set PORT state.
- */
-static void port_set_state (sdla_t *card, int state)
-{
-	struct net_device *dev = card->wandev.dev;
-	chdlc_private_area_t *chdlc_priv_area = dev->priv;
-
-        if (card->u.c.state != state)
-        {
-                switch (state)
-                {
-                case WAN_CONNECTED:
-                        printk (KERN_INFO "%s: HDLC link connected!\n",
-                                card->devname);
-                      break;
-
-                case WAN_CONNECTING:
-                        printk (KERN_INFO "%s: HDLC link connecting...\n",
-                                card->devname);
-                        break;
-
-                case WAN_DISCONNECTED:
-                        printk (KERN_INFO "%s: HDLC link disconnected!\n",
-                                card->devname);
-                        break;
-                }
-
-                card->wandev.state = card->u.c.state = state;
-		chdlc_priv_area->common.state = state;
-        }
-}
-
-void s508_lock (sdla_t *card, unsigned long *smp_flags)
-{
-	spin_lock_irqsave(&card->wandev.lock, *smp_flags);
-        if (card->next){
-		/* It is ok to use spin_lock here, since we
-		 * already turned off interrupts */
-        	spin_lock(&card->next->wandev.lock);
-	}
-}
-
-void s508_unlock (sdla_t *card, unsigned long *smp_flags)
-{
-	if (card->next){
-		spin_unlock(&card->next->wandev.lock);
-	}
-	spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
-}
-
-
-
-/*===========================================================================
- * config_chdlc
- *
- *	Configure the chdlc protocol and enable communications.		
- *
- *   	The if_open() function binds this function to the poll routine.
- *      Therefore, this function will run every time the chdlc interface
- *      is brought up. We cannot run this function from the if_open 
- *      because if_open does not have access to the remote IP address.
- *      
- *	If the communications are not enabled, proceed to configure
- *      the card and enable communications.
- *
- *      If the communications are enabled, it means that the interface
- *      was shutdown by ether the user or driver. In this case, we 
- *      have to check that the IP addresses have not changed.  If
- *      the IP addresses have changed, we have to reconfigure the firmware
- *      and update the changed IP addresses.  Otherwise, just exit.
- *
- */
-
-static int config_chdlc (sdla_t *card)
-{
-	struct net_device *dev = card->wandev.dev;
-	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
-	if (card->u.c.comm_enabled){
-		chdlc_comm_disable(card);
-		port_set_state(card, WAN_DISCONNECTED);
-	}
-
-	if (set_chdlc_config(card)) {
-		printk(KERN_INFO "%s: CHDLC Configuration Failed!\n",
-				card->devname);
-		return 0;
-	}
-	init_chdlc_tx_rx_buff(card, dev);
-
-	/* Set interrupt mode and mask */
-        if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
-                		APP_INT_ON_GLOBAL_EXCEP_COND |
-                		APP_INT_ON_TX_FRAME |
-                		APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
-		printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
-				card->devname);
-		return 0;	
-        }
-	
-
-	/* Mask the Transmit and Timer interrupt */
-	flags->interrupt_info_struct.interrupt_permission &= 
-		~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
-
-	if (chdlc_comm_enable(card) != 0) {
-		printk(KERN_INFO "%s: Failed to enable chdlc communications!\n",
-				card->devname);
-		flags->interrupt_info_struct.interrupt_permission = 0;
-		card->u.c.comm_enabled=0;
-		chdlc_set_intr_mode(card,0);
-		return 0;
-	}
-
-	/* Initialize Rx/Tx buffer control fields */
-	port_set_state(card, WAN_CONNECTING);
-	return 0; 
-}
-
-
-static void send_ppp_term_request(struct net_device *dev)
-{
-	struct sk_buff *new_skb;
-	unsigned char *buf;
-
-	if ((new_skb = dev_alloc_skb(8)) != NULL) {
-		/* copy data into new_skb */
-
-		buf = skb_put(new_skb, 8);
-		sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07);
-
-		/* Decapsulate pkt and pass it up the protocol stack */
-		new_skb->protocol = htons(ETH_P_WAN_PPP);
-		new_skb->dev = dev;
-		new_skb->mac.raw  = new_skb->data;
-
-		netif_rx(new_skb);
-		dev->last_rx = jiffies;
-	}
-}
-
-
-MODULE_LICENSE("GPL");
-
-/****** End ****************************************************************/
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index bad09eb..e0874cb 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -6,7 +6,7 @@
 	depends on NETDEVICES
 
 config NET_RADIO
-	bool "Wireless LAN drivers (non-hamradio)"
+	bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
 	select WIRELESS_EXT
 	---help---
 	  Support for wireless LANs and everything having to do with radio,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 108d9fe..00764dd 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -3139,6 +3139,7 @@
 		}
 		if ( status & EV_LINK ) {
 			union iwreq_data	wrqu;
+			int scan_forceloss = 0;
 			/* The link status has changed, if you want to put a
 			   monitor hook in, do it here.  (Remember that
 			   interrupts are still disabled!)
@@ -3157,7 +3158,8 @@
 			  code) */
 #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
 			   code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
 #define RC_RESERVED 0 /* Reserved return code */
 #define RC_NOREASON 1 /* Unspecified reason */
 #define RC_AUTHINV 2 /* Previous authentication invalid */
@@ -3174,44 +3176,30 @@
 			  leaving BSS */
 #define RC_NOAUTH 9 /* Station requesting (Re)Association is not
 		       Authenticated with the responding station */
-			if (newStatus != ASSOCIATED) {
-				if (auto_wep && !apriv->expires) {
-					apriv->expires = RUN_AT(3*HZ);
-					wake_up_interruptible(&apriv->thr_wait);
-				}
-			} else {
-				struct task_struct *task = apriv->task;
+			if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+				scan_forceloss = 1;
+			if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
 				if (auto_wep)
 					apriv->expires = 0;
-				if (task)
-					wake_up_process (task);
+				if (apriv->task)
+					wake_up_process (apriv->task);
 				set_bit(FLAG_UPDATE_UNI, &apriv->flags);
 				set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-			}
-			/* Question : is ASSOCIATED the only status
-			 * that is valid ? We want to catch handover
-			 * and reassociations as valid status
-			 * Jean II */
-			if(newStatus == ASSOCIATED) {
-#if 0
-				/* FIXME: Grabbing scan results here
-				 * seems to be too early???  Just wait for
-				 * timeout instead. */
-				if (apriv->scan_timeout > 0) {
-					set_bit(JOB_SCAN_RESULTS, &apriv->flags);
-					wake_up_interruptible(&apriv->thr_wait);
-				}
-#endif
+
 				if (down_trylock(&apriv->sem) != 0) {
 					set_bit(JOB_EVENT, &apriv->flags);
 					wake_up_interruptible(&apriv->thr_wait);
 				} else
 					airo_send_event(dev);
-			} else {
-				memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
-				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			} else if (!scan_forceloss) {
+				if (auto_wep && !apriv->expires) {
+					apriv->expires = RUN_AT(3*HZ);
+					wake_up_interruptible(&apriv->thr_wait);
+				}
 
 				/* Send event to user space */
+				memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+				wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 				wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
 			}
 		}
@@ -7136,10 +7124,10 @@
 		goto out;
 
 	/* Initiate a scan command */
+	ai->scan_timeout = RUN_AT(3*HZ);
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.cmd=CMD_LISTBSS;
 	issuecommand(ai, &cmd, &rsp);
-	ai->scan_timeout = RUN_AT(3*HZ);
 	wake = 1;
 
 out:
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index a496460..af0cbb6 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -80,8 +80,8 @@
    event handler. 
 */
 
-static void airo_config(dev_link_t *link);
-static void airo_release(dev_link_t *link);
+static int airo_config(struct pcmcia_device *link);
+static void airo_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -101,10 +101,10 @@
 /*
    A linked list of "instances" of the  aironet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -114,7 +114,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -141,24 +141,16 @@
   
   ======================================================================*/
 
-static int airo_attach(struct pcmcia_device *p_dev)
+static int airo_probe(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
 	local_info_t *local;
 
 	DEBUG(0, "airo_attach()\n");
 
-	/* Initialize the dev_link_t structure */
-	link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-	if (!link) {
-		printk(KERN_ERR "airo_cs: no memory for new device\n");
-		return -ENOMEM;
-	}
-	
 	/* Interrupt setup */
-	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-	link->irq.Handler = NULL;
+	p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+	p_dev->irq.Handler = NULL;
 	
 	/*
 	  General socket configuration defaults can go here.  In this
@@ -167,26 +159,18 @@
 	  and attributes of IO windows) are fixed by the nature of the
 	  device, and can be hard-wired here.
 	*/
-	link->conf.Attributes = 0;
-	link->conf.Vcc = 50;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	p_dev->conf.Attributes = 0;
+	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 	
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
 		printk(KERN_ERR "airo_cs: no memory for new device\n");
-		kfree (link);
 		return -ENOMEM;
 	}
-	link->priv = local;
+	p_dev->priv = local;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	airo_config(link);
-
-	return 0;
+	return airo_config(p_dev);
 } /* airo_attach */
 
 /*======================================================================
@@ -198,14 +182,11 @@
   
   ======================================================================*/
 
-static void airo_detach(struct pcmcia_device *p_dev)
+static void airo_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "airo_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		airo_release(link);
+	airo_release(link);
 
 	if ( ((local_info_t*)link->priv)->eth_dev ) {
 		stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
@@ -213,7 +194,6 @@
 	((local_info_t*)link->priv)->eth_dev = NULL;
 
 	kfree(link->priv);
-	kfree(link);
 } /* airo_detach */
 
 /*======================================================================
@@ -227,9 +207,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void airo_config(dev_link_t *link)
+static int airo_config(struct pcmcia_device *link)
 {
-	client_handle_t handle;
 	tuple_t tuple;
 	cisparse_t parse;
 	local_info_t *dev;
@@ -237,8 +216,7 @@
 	u_char buf[64];
 	win_req_t req;
 	memreq_t map;
-	
-	handle = link->handle;
+
 	dev = link->priv;
 
 	DEBUG(0, "airo_config(0x%p)\n", link);
@@ -252,15 +230,12 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
-	
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	
+
 	/*
 	  In this loop, we scan the CIS for configuration table entries,
 	  each of which describes a valid card configuration, including
@@ -274,12 +249,12 @@
 	  will only use the CIS to fill in implementation-defined details.
 	*/
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t dflt = { 0 };
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 		
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -294,16 +269,11 @@
 		
 		/* Use power settings for Vcc and Vpp if present */
 		/*  Note that the CIS values need to be rescaled */
-		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
-		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-		
 		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
 		
 		/* Do we need to allocate an interrupt? */
@@ -329,12 +299,12 @@
 		}
 		
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(link->handle, &link->io) != 0)
+		if (pcmcia_request_io(link, &link->io) != 0)
 			goto next_entry;
 		
 		/*
 		  Now set up a common memory window, if needed.  There is room
-		  in the dev_link_t structure for one memory window handle,
+		  in the struct pcmcia_device structure for one memory window handle,
 		  but if the base addresses need to be saved, or if multiple
 		  windows are needed, the info should go in the private data
 		  structure for this device.
@@ -350,7 +320,7 @@
 			req.Base = mem->win[0].host_addr;
 			req.Size = mem->win[0].len;
 			req.AccessSpeed = 0;
-			if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+			if (pcmcia_request_window(&link, &req, &link->win) != 0)
 				goto next_entry;
 			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
 			if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -360,7 +330,7 @@
 		break;
 		
 	next_entry:
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 	
     /*
@@ -369,33 +339,32 @@
       irq structure is initialized.
     */
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 	
 	/*
 	  This actually configures the PCMCIA socket -- setting up
 	  the I/O windows and the interrupt mapping, and putting the
 	  card and host interface into "Memory and IO" mode.
 	*/
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 	((local_info_t*)link->priv)->eth_dev = 
 		init_airo_card( link->irq.AssignedIRQ,
-				link->io.BasePort1, 1, &handle_to_dev(handle) );
+				link->io.BasePort1, 1, &handle_to_dev(link) );
 	if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
 	
 	/*
 	  At this point, the dev_node_t structure(s) need to be
-	  initialized and arranged in a linked list at link->dev.
+	  initialized and arranged in a linked list at link->dev_node.
 	*/
 	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
 	dev->node.major = dev->node.minor = 0;
-	link->dev = &dev->node;
+	link->dev_node = &dev->node;
 	
 	/* Finally, report what we've done */
-	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-	       dev->node.dev_name, link->conf.ConfigIndex,
-	       link->conf.Vcc/10, link->conf.Vcc%10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+	printk(KERN_INFO "%s: index 0x%02x: ",
+	       dev->node.dev_name, link->conf.ConfigIndex);
+	if (link->conf.Vpp)
+		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq.AssignedIRQ);
 	if (link->io.NumPorts1)
@@ -408,14 +377,12 @@
 		printk(", mem 0x%06lx-0x%06lx", req.Base,
 		       req.Base+req.Size-1);
 	printk("\n");
-	
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
-	
+	return 0;
+
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	airo_release(link);
-	
+	return -ENODEV;
 } /* airo_config */
 
 /*======================================================================
@@ -426,51 +393,26 @@
   
   ======================================================================*/
 
-static void airo_release(dev_link_t *link)
+static void airo_release(struct pcmcia_device *link)
 {
 	DEBUG(0, "airo_release(0x%p)\n", link);
-	
-	/* Unlink the device chain */
-	link->dev = NULL;
-	
-	/*
-	  In a normal driver, additional code may be needed to release
-	  other kernel data structures associated with this device. 
-	*/
-	
-	/* Don't bother checking to see if these succeed or not */
-	if (link->win)
-		pcmcia_release_window(link->win);
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int airo_suspend(struct pcmcia_device *p_dev)
+static int airo_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *local = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		netif_device_detach(local->eth_dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	netif_device_detach(local->eth_dev);
 
 	return 0;
 }
 
-static int airo_resume(struct pcmcia_device *p_dev)
+static int airo_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	local_info_t *local = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
+	if (link->open) {
 		reset_airo_card(local->eth_dev);
 		netif_device_attach(local->eth_dev);
 	}
@@ -492,7 +434,7 @@
 	.drv		= {
 		.name	= "airo_cs",
 	},
-	.probe		= airo_attach,
+	.probe		= airo_probe,
 	.remove		= airo_detach,
 	.id_table       = airo_ids,
 	.suspend	= airo_suspend,
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 87afa68..8606c88 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3463,6 +3463,7 @@
 	u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
 	u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
 	int fast_scan;
+	union iwreq_data wrqu;
 
 	if (status == CMD_STATUS_IDLE ||
 	    status == CMD_STATUS_IN_PROGRESS)
@@ -3487,6 +3488,7 @@
 			atmel_scan(priv, 1);
 		} else {
 			int bss_index = retrieve_bss(priv);
+			int notify_scan_complete = 1;
 			if (bss_index != -1) {
 				atmel_join_bss(priv, bss_index);
 			} else if (priv->operating_mode == IW_MODE_ADHOC &&
@@ -3495,8 +3497,14 @@
 			} else {
 				priv->fast_scan = !fast_scan;
 				atmel_scan(priv, 1);
+				notify_scan_complete = 0;
 			}
 			priv->site_survey_state = SITE_SURVEY_COMPLETED;
+			if (notify_scan_complete) {
+				wrqu.data.length = 0;
+				wrqu.data.flags = 0;
+				wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+			}
 		}
 		break;
 
@@ -3509,6 +3517,9 @@
 		priv->site_survey_state = SITE_SURVEY_COMPLETED;
 		if (priv->station_is_associated) {
 			atmel_enter_state(priv, STATION_STATE_READY);
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
 		} else {
 			atmel_scan(priv, 1);
 		}
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index d6f4a5a..26bf112 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -91,8 +91,8 @@
    event handler. 
 */
 
-static void atmel_config(dev_link_t *link);
-static void atmel_release(dev_link_t *link);
+static int atmel_config(struct pcmcia_device *link);
+static void atmel_release(struct pcmcia_device *link);
 
 /*
    The attach() and detach() entry points are used to create and destroy
@@ -112,10 +112,10 @@
 /*
    A linked list of "instances" of the  atmelnet device.  Each actual
    PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
+   by one struct pcmcia_device structure (defined in ds.h).
 
    You may not want to use a linked list for this -- for example, the
-   memory card driver uses an array of dev_link_t pointers, where minor
+   memory card driver uses an array of struct pcmcia_device pointers, where minor
    device numbers are used to derive the corresponding array index.
 */
 
@@ -125,7 +125,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally shouldn't be allocated dynamically.
 
@@ -152,24 +152,16 @@
   
   ======================================================================*/
 
-static int atmel_attach(struct pcmcia_device *p_dev)
+static int atmel_probe(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
 	local_info_t *local;
 
 	DEBUG(0, "atmel_attach()\n");
 
-	/* Initialize the dev_link_t structure */
-	link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-	if (!link) {
-		printk(KERN_ERR "atmel_cs: no memory for new device\n");
-		return -ENOMEM;
-	}
-
 	/* Interrupt setup */
-	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-	link->irq.Handler = NULL;
+	p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+	p_dev->irq.Handler = NULL;
 
 	/*
 	  General socket configuration defaults can go here.  In this
@@ -178,26 +170,18 @@
 	  and attributes of IO windows) are fixed by the nature of the
 	  device, and can be hard-wired here.
 	*/
-	link->conf.Attributes = 0;
-	link->conf.Vcc = 50;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	p_dev->conf.Attributes = 0;
+	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
 		printk(KERN_ERR "atmel_cs: no memory for new device\n");
-		kfree (link);
 		return -ENOMEM;
 	}
-	link->priv = local;
+	p_dev->priv = local;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	atmel_config(link);
-
-	return 0;
+	return atmel_config(p_dev);
 } /* atmel_attach */
 
 /*======================================================================
@@ -209,17 +193,13 @@
   
   ======================================================================*/
 
-static void atmel_detach(struct pcmcia_device *p_dev)
+static void atmel_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "atmel_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		atmel_release(link);
+	atmel_release(link);
 
 	kfree(link->priv);
-	kfree(link);
 }
 
 /*======================================================================
@@ -236,19 +216,17 @@
 /* Call-back function to interrogate PCMCIA-specific information
    about the current existance of the card */
 static int card_present(void *arg)
-{ 
-	dev_link_t *link = (dev_link_t *)arg;
-	if (link->state & DEV_SUSPEND)
-		return 0;
-	else if (link->state & DEV_PRESENT)
+{
+	struct pcmcia_device *link = (struct pcmcia_device *)arg;
+
+	if (pcmcia_dev_present(link))
 		return 1;
-	
+
 	return 0;
 }
 
-static void atmel_config(dev_link_t *link)
+static int atmel_config(struct pcmcia_device *link)
 {
-	client_handle_t handle;
 	tuple_t tuple;
 	cisparse_t parse;
 	local_info_t *dev;
@@ -256,9 +234,8 @@
 	u_char buf[64];
 	struct pcmcia_device_id *did;
 
-	handle = link->handle;
 	dev = link->priv;
-	did = handle_to_dev(handle).driver_data;
+	did = handle_to_dev(link).driver_data;
 
 	DEBUG(0, "atmel_config(0x%p)\n", link);
 	
@@ -272,15 +249,12 @@
 	  registers.
 	*/
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
-	
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-	
+
 	/*
 	  In this loop, we scan the CIS for configuration table entries,
 	  each of which describes a valid card configuration, including
@@ -294,12 +268,12 @@
 	  will only use the CIS to fill in implementation-defined details.
 	*/
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t dflt = { 0 };
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 		
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
@@ -314,16 +288,11 @@
 		
 		/* Use power settings for Vcc and Vpp if present */
 		/*  Note that the CIS values need to be rescaled */
-		if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
-		else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
-		
 		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
 		
 		/* Do we need to allocate an interrupt? */
@@ -349,14 +318,14 @@
 		}
 		
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(link->handle, &link->io) != 0)
+		if (pcmcia_request_io(link, &link->io) != 0)
 			goto next_entry;
 
 		/* If we got this far, we're cool! */
 		break;
 		
 	next_entry:
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 	
 	/*
@@ -365,14 +334,14 @@
 	  irq structure is initialized.
 	*/
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 	
 	/*
 	  This actually configures the PCMCIA socket -- setting up
 	  the I/O windows and the interrupt mapping, and putting the
 	  card and host interface into "Memory and IO" mode.
 	*/
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 	
 	if (link->irq.AssignedIRQ == 0) {
 		printk(KERN_ALERT 
@@ -384,7 +353,7 @@
 		init_atmel_card(link->irq.AssignedIRQ,
 				link->io.BasePort1,
 				did ? did->driver_info : ATMEL_FW_TYPE_NONE,
-				&handle_to_dev(handle),
+				&handle_to_dev(link),
 				card_present, 
 				link);
 	if (!((local_info_t*)link->priv)->eth_dev) 
@@ -393,18 +362,18 @@
 	
 	/*
 	  At this point, the dev_node_t structure(s) need to be
-	  initialized and arranged in a linked list at link->dev.
+	  initialized and arranged in a linked list at link->dev_node.
 	*/
 	strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
 	dev->node.major = dev->node.minor = 0;
-	link->dev = &dev->node;
-			
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
-	
+	link->dev_node = &dev->node;
+
+	return 0;
+
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	atmel_release(link);
+	return -ENODEV;
 }
 
 /*======================================================================
@@ -415,53 +384,34 @@
   
   ======================================================================*/
 
-static void atmel_release(dev_link_t *link)
+static void atmel_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
-		
+
 	DEBUG(0, "atmel_release(0x%p)\n", link);
-	
-	/* Unlink the device chain */
-	link->dev = NULL;
-	
-	if (dev) 
+
+	if (dev)
 		stop_atmel_card(dev);
-	((local_info_t*)link->priv)->eth_dev = NULL; 
-	
-	/* Don't bother checking to see if these succeed or not */
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	((local_info_t*)link->priv)->eth_dev = NULL;
+
+	pcmcia_disable_device(link);
 }
 
-static int atmel_suspend(struct pcmcia_device *dev)
+static int atmel_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	local_info_t *local = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		netif_device_detach(local->eth_dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	netif_device_detach(local->eth_dev);
 
 	return 0;
 }
 
-static int atmel_resume(struct pcmcia_device *dev)
+static int atmel_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	local_info_t *local = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		atmel_open(local->eth_dev);
-		netif_device_attach(local->eth_dev);
-	}
+	atmel_open(local->eth_dev);
+	netif_device_attach(local->eth_dev);
 
 	return 0;
 }
@@ -515,7 +465,7 @@
 	.drv		= {
 		.name	= "atmel_cs",
         },
-	.probe          = atmel_attach,
+	.probe          = atmel_probe,
 	.remove		= atmel_detach,
 	.id_table	= atmel_ids,
 	.suspend	= atmel_suspend,
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
index 4184656..25ea474 100644
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -17,8 +17,11 @@
 
 config BCM43XX_DMA
 	bool
+	depends on BCM43XX
+
 config BCM43XX_PIO
 	bool
+	depends on BCM43XX
 
 choice
 	prompt "BCM43xx data transfer mode"
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index dcadd29..2e83083 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -15,7 +15,6 @@
 
 #include "bcm43xx_debugfs.h"
 #include "bcm43xx_leds.h"
-#include "bcm43xx_sysfs.h"
 
 
 #define PFX				KBUILD_MODNAME ": "
@@ -638,8 +637,6 @@
 };
 
 struct bcm43xx_private {
-	struct bcm43xx_sysfs sysfs;
-
 	struct ieee80211_device *ieee;
 	struct ieee80211softmac_device *softmac;
 
@@ -772,6 +769,20 @@
 	return ieee80211softmac_priv(dev);
 }
 
+struct device;
+
+static inline
+struct bcm43xx_private * dev_to_bcm(struct device *dev)
+{
+	struct net_device *net_dev;
+	struct bcm43xx_private *bcm;
+
+	net_dev = dev_get_drvdata(dev);
+	bcm = bcm43xx_priv(net_dev);
+
+	return bcm;
+}
+
 
 /* Helper function, which returns a boolean.
  * TRUE, if PIO is used; FALSE, if DMA is used.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index d2c3401..35a4fcb 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -452,12 +452,12 @@
 	size_t i;
 	char c;
 
-	printk(KERN_INFO PFX "Data dump (%s, %u bytes):",
+	printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
 	       description, size);
 	for (i = 0; i < size; i++) {
 		c = data[i];
 		if (i % 8 == 0)
-			printk("\n" KERN_INFO PFX "0x%08x:  0x%02x, ", i, c & 0xff);
+			printk("\n" KERN_INFO PFX "0x%08zx:  0x%02x, ", i, c & 0xff);
 		else
 			printk("0x%02x, ", c & 0xff);
 	}
@@ -472,12 +472,12 @@
 	int j;
 	const unsigned char *d;
 
-	printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***",
+	printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
 	       description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
 	for (i = 0; i < bytes; i++) {
 		d = data + i;
 		if (i % 8 == 0)
-			printk("\n" KERN_INFO PFX "0x%08x:  ", i);
+			printk("\n" KERN_INFO PFX "0x%08zx:  ", i);
 		if (msb_to_lsb) {
 			for (j = 7; j >= 0; j--) {
 				if (*d & (1 << j))
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index c3681b8..bbecba0 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -196,8 +196,9 @@
 	}
 	if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RINGMEMORY >1G "
-				    "(0x%08x, len: %lu)\n",
-		       ring->dmabase, BCM43xx_DMA_RINGMEMSIZE);
+				    "(0x%llx, len: %lu)\n",
+				(unsigned long long)ring->dmabase,
+				BCM43xx_DMA_RINGMEMSIZE);
 		dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
 				  ring->vbase, ring->dmabase);
 		return -ENOMEM;
@@ -307,8 +308,8 @@
 		unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
 		dev_kfree_skb_any(skb);
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RX SKB >1G "
-				    "(0x%08x, len: %u)\n",
-		       dmaaddr, ring->rx_buffersize);
+				    "(0x%llx, len: %u)\n",
+			(unsigned long long)dmaaddr, ring->rx_buffersize);
 		return -ENOMEM;
 	}
 	meta->skb = skb;
@@ -729,8 +730,8 @@
 	if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
 		return_slot(ring, slot);
 		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA TX SKB >1G "
-				    "(0x%08x, len: %u)\n",
-		       meta->dmaaddr, skb->len);
+				    "(0x%llx, len: %u)\n",
+			(unsigned long long)meta->dmaaddr, skb->len);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index 2d520e4..b7d7763 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -213,6 +213,14 @@
 void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
 {
 }
+static inline
+void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
+{
+}
+static inline
+void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
+{
+}
 
 #endif /* CONFIG_BCM43XX_DMA */
 #endif /* BCM43xx_DMA_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c37371f..9a06e61 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -52,6 +52,7 @@
 #include "bcm43xx_wx.h"
 #include "bcm43xx_ethtool.h"
 #include "bcm43xx_xmit.h"
+#include "bcm43xx_sysfs.h"
 
 
 MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
@@ -3522,6 +3523,7 @@
 		err = bcm43xx_pio_tx(bcm, txb);
 	else
 		err = bcm43xx_dma_tx(bcm, txb);
+	bcm->net_dev->trans_start = jiffies;
 
 	return err;
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index 0a66f43..3313716 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -2151,6 +2151,7 @@
 				phy->tssi2dbm = NULL;
 				printk(KERN_ERR PFX "Could not generate "
 						    "tssi2dBm table\n");
+				kfree(dyn_tssi2dbm);
 				return -ENODEV;
 			}
 		phy->tssi2dbm = dyn_tssi2dbm;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index c59ddd4..0aa1bd2 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -27,6 +27,7 @@
 #include "bcm43xx_pio.h"
 #include "bcm43xx_main.h"
 #include "bcm43xx_xmit.h"
+#include "bcm43xx_power.h"
 
 #include <linux/delay.h>
 
@@ -44,10 +45,10 @@
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  octet);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI);
+				  BCM43xx_PIO_TXCTL_WRITELO);
 	} else {
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI);
+				  BCM43xx_PIO_TXCTL_WRITELO);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  octet);
 	}
@@ -103,7 +104,7 @@
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
 				  skb->data[skb->len - 1]);
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-				  BCM43xx_PIO_TXCTL_WRITEHI |
+				  BCM43xx_PIO_TXCTL_WRITELO |
 				  BCM43xx_PIO_TXCTL_COMPLETE);
 	} else {
 		bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
@@ -112,9 +113,10 @@
 }
 
 static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
-			   int packetindex)
+			   struct bcm43xx_pio_txpacket *packet)
 {
 	u16 cookie = 0x0000;
+	int packetindex;
 
 	/* We use the upper 4 bits for the PIO
 	 * controller ID and the lower 12 bits
@@ -135,6 +137,7 @@
 	default:
 		assert(0);
 	}
+	packetindex = pio_txpacket_getindex(packet);
 	assert(((u16)packetindex & 0xF000) == 0x0000);
 	cookie |= (u16)packetindex;
 
@@ -184,7 +187,7 @@
 	bcm43xx_generate_txhdr(queue->bcm,
 			       &txhdr, skb->data, skb->len,
 			       (packet->xmitted_frags == 0),
-			       generate_cookie(queue, pio_txpacket_getindex(packet)));
+			       generate_cookie(queue, packet));
 
 	tx_start(queue);
 	octets = skb->len + sizeof(txhdr);
@@ -241,7 +244,7 @@
 		queue->tx_devq_packets++;
 		queue->tx_devq_used += octets;
 
-		assert(packet->xmitted_frags <= packet->txb->nr_frags);
+		assert(packet->xmitted_frags < packet->txb->nr_frags);
 		packet->xmitted_frags++;
 		packet->xmitted_octets += octets;
 	}
@@ -257,8 +260,14 @@
 	unsigned long flags;
 	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
 	int err;
+	u16 txctl;
 
 	bcm43xx_lock_mmio(bcm, flags);
+
+	txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
+	if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
+		goto out_unlock;
+
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
 		assert(packet->xmitted_frags < packet->txb->nr_frags);
 		if (packet->xmitted_frags == 0) {
@@ -288,6 +297,7 @@
 	next_packet:
 		continue;
 	}
+out_unlock:
 	bcm43xx_unlock_mmio(bcm, flags);
 }
 
@@ -330,12 +340,19 @@
 		     (unsigned long)queue);
 
 	value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-	value |= BCM43xx_SBF_XFER_REG_BYTESWAP;
+	value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
 
 	qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
+	if (qsize == 0) {
+		printk(KERN_ERR PFX "ERROR: This card does not support PIO "
+				    "operation mode. Please use DMA mode "
+				    "(module parameter pio=0).\n");
+		goto err_freequeue;
+	}
 	if (qsize <= BCM43xx_PIO_TXQADJUST) {
-		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize);
+		printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
+		       qsize);
 		goto err_freequeue;
 	}
 	qsize -= BCM43xx_PIO_TXQADJUST;
@@ -444,15 +461,10 @@
 {
 	struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
 	struct bcm43xx_pio_txpacket *packet;
-	u16 tmp;
 
 	assert(!queue->tx_suspended);
 	assert(!list_empty(&queue->txfree));
 
-	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
-	if (tmp & BCM43xx_PIO_TXCTL_SUSPEND)
-		return -EBUSY;
-
 	packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
 	packet->txb = txb;
 	packet->xmitted_frags = 0;
@@ -462,7 +474,7 @@
 	assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
 
 	/* Suspend TX, if we are out of packets in the "free" queue. */
-	if (unlikely(list_empty(&queue->txfree))) {
+	if (list_empty(&queue->txfree)) {
 		netif_stop_queue(queue->bcm->net_dev);
 		queue->tx_suspended = 1;
 	}
@@ -480,15 +492,15 @@
 
 	queue = parse_cookie(bcm, status->cookie, &packet);
 	assert(queue);
-//TODO
-if (!queue)
-return;
+
 	free_txpacket(packet, 1);
-	if (unlikely(queue->tx_suspended)) {
+	if (queue->tx_suspended) {
 		queue->tx_suspended = 0;
 		netif_wake_queue(queue->bcm->net_dev);
 	}
-	/* If there are packets on the txqueue, poke the tasklet. */
+	/* If there are packets on the txqueue, poke the tasklet
+	 * to transmit them.
+	 */
 	if (!list_empty(&queue->txqueue))
 		tasklet_schedule(&queue->txtask);
 }
@@ -519,12 +531,9 @@
 	int i, preamble_readwords;
 	struct sk_buff *skb;
 
-return;
 	tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
-	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) {
-		dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk.
+	if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
 		return;
-	}
 	bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
 			  BCM43xx_PIO_RXCTL_DATAAVAILABLE);
 
@@ -538,8 +547,7 @@
 	return;
 data_ready:
 
-//FIXME: endianess in this function.
-	len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
+	len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
 	if (unlikely(len > 0x700)) {
 		pio_rx_error(queue, 0, "len > 0x700");
 		return;
@@ -555,7 +563,7 @@
 		preamble_readwords = 18 / sizeof(u16);
 	for (i = 0; i < preamble_readwords; i++) {
 		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-		preamble[i + 1] = cpu_to_be16(tmp);//FIXME?
+		preamble[i + 1] = cpu_to_le16(tmp);
 	}
 	rxhdr = (struct bcm43xx_rxhdr *)preamble;
 	rxflags2 = le16_to_cpu(rxhdr->flags2);
@@ -591,16 +599,40 @@
 	}
 	skb_put(skb, len);
 	for (i = 0; i < len - 1; i += 2) {
-		tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA));
-		*((u16 *)(skb->data + i)) = tmp;
+		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
+		*((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
 	}
 	if (len % 2) {
 		tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
 		skb->data[len - 1] = (tmp & 0x00FF);
+/* The specs say the following is required, but
+ * it is wrong and corrupts the PLCP. If we don't do
+ * this, the PLCP seems to be correct. So ifdef it out for now.
+ */
+#if 0
 		if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
-			skb->data[0x20] = (tmp & 0xFF00) >> 8;
+			skb->data[2] = (tmp & 0xFF00) >> 8;
 		else
-			skb->data[0x1E] = (tmp & 0xFF00) >> 8;
+			skb->data[0] = (tmp & 0xFF00) >> 8;
+#endif
 	}
+	skb_trim(skb, len - IEEE80211_FCS_LEN);
 	bcm43xx_rx(queue->bcm, skb, rxhdr);
 }
+
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+			  | BCM43xx_PIO_TXCTL_SUSPEND);
+}
+
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+	bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
+			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
+			  & ~BCM43xx_PIO_TXCTL_SUSPEND);
+	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
+	tasklet_schedule(&queue->txtask);
+}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
index 970627b..dfc7820 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -14,8 +14,8 @@
 #define BCM43xx_PIO_RXCTL		0x08
 #define BCM43xx_PIO_RXDATA		0x0A
 
-#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 0)
-#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 1)
+#define BCM43xx_PIO_TXCTL_WRITELO	(1 << 0)
+#define BCM43xx_PIO_TXCTL_WRITEHI	(1 << 1)
 #define BCM43xx_PIO_TXCTL_COMPLETE	(1 << 2)
 #define BCM43xx_PIO_TXCTL_INIT		(1 << 3)
 #define BCM43xx_PIO_TXCTL_SUSPEND	(1 << 7)
@@ -95,6 +95,7 @@
 		       u16 offset, u16 value)
 {
 	bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
+	mmiowb();
 }
 
 
@@ -107,6 +108,9 @@
 				   struct bcm43xx_xmitstatus *status);
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
 
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+
 #else /* CONFIG_BCM43XX_PIO */
 
 static inline
@@ -133,6 +137,14 @@
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
 {
 }
+static inline
+void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
+{
+}
+static inline
+void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
+{
+}
 
 #endif /* CONFIG_BCM43XX_PIO */
 #endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
index 3c92b62..6569da3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c
@@ -35,77 +35,101 @@
 #include "bcm43xx_main.h"
 
 
+/* Get the Slow Clock Source */
+static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
+{
+	u32 tmp;
+	int err;
+
+	assert(bcm->current_core == &bcm->core_chipcommon);
+	if (bcm->current_core->rev < 6) {
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
+		    bcm->bustype == BCM43xx_BUSTYPE_SB)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
+			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
+			assert(!err);
+			if (tmp & 0x10)
+				return BCM43xx_PCTL_CLKSRC_PCI;
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		}
+	}
+	if (bcm->current_core->rev < 10) {
+		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+		tmp &= 0x7;
+		if (tmp == 0)
+			return BCM43xx_PCTL_CLKSRC_LOPWROS;
+		if (tmp == 1)
+			return BCM43xx_PCTL_CLKSRC_XTALOS;
+		if (tmp == 2)
+			return BCM43xx_PCTL_CLKSRC_PCI;
+	}
+
+	return BCM43xx_PCTL_CLKSRC_XTALOS;
+}
+
 /* Get max/min slowclock frequency
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
 static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
 				       int get_max)
 {
-	int limit = 0;
+	int limit;
+	int clocksrc;
 	int divisor;
-	int selection;
-	int err;
 	u32 tmp;
-	struct bcm43xx_coreinfo *old_core;
 
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
-		goto out;
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err)
-		goto out;
+	assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
+	assert(bcm->current_core == &bcm->core_chipcommon);
 
+	clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
 	if (bcm->current_core->rev < 6) {
-		if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) ||
-			(bcm->bustype == BCM43xx_BUSTYPE_SB)) {
-			selection = 1;
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_PCI:
+			divisor = 64;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
 			divisor = 32;
-		} else {
-			err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
-			if (err) {
-				printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n");
-				goto out_switchback;
-			}
-			if (tmp & 0x10) {
-				/* PCI */
-				selection = 2;
-				divisor = 64;
-			} else {
-				/* XTAL */
-				selection = 1;
-				divisor = 32;
-			}
+			break;
+		default:
+			assert(0);
+			divisor = 1;
 		}
 	} else if (bcm->current_core->rev < 10) {
-		selection = (tmp & 0x07);
-		if (selection) {
-			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-			divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		} else
+		switch (clocksrc) {
+		case BCM43xx_PCTL_CLKSRC_LOPWROS:
 			divisor = 1;
+			break;
+		case BCM43xx_PCTL_CLKSRC_XTALOS:
+		case BCM43xx_PCTL_CLKSRC_PCI:
+			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+			divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+			divisor *= 4;
+			break;
+		default:
+			assert(0);
+			divisor = 1;
+		}
 	} else {
 		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
-		divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16));
-		selection = 1;
+		divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
+		divisor *= 4;
 	}
-	
-	switch (selection) {
-	case 0:
-		/* LPO */
+
+	switch (clocksrc) {
+	case BCM43xx_PCTL_CLKSRC_LOPWROS:
 		if (get_max)
 			limit = 43000;
 		else
 			limit = 25000;
 		break;
-	case 1:
-		/* XTAL */
+	case BCM43xx_PCTL_CLKSRC_XTALOS:
 		if (get_max)
 			limit = 20200000;
 		else
 			limit = 19800000;
 		break;
-	case 2:
-		/* PCI */
+	case BCM43xx_PCTL_CLKSRC_PCI:
 		if (get_max)
 			limit = 34000000;
 		else
@@ -113,17 +137,14 @@
 		break;
 	default:
 		assert(0);
+		limit = 0;
 	}
 	limit /= divisor;
 
-out_switchback:
-	err = bcm43xx_switch_core(bcm, old_core);
-	assert(err == 0);
-
-out:
 	return limit;
 }
 
+
 /* init power control
  * as described in http://bcm-specs.sipsolutions.net/PowerControl
  */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
index 5f63640..c966ab3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h
@@ -33,6 +33,15 @@
 
 #include <linux/types.h>
 
+/* Clock sources */
+enum {
+	/* PCI clock */
+	BCM43xx_PCTL_CLKSRC_PCI,
+	/* Crystal slow clock oscillator */
+	BCM43xx_PCTL_CLKSRC_XTALOS,
+	/* Low power oscillator */
+	BCM43xx_PCTL_CLKSRC_LOPWROS,
+};
 
 struct bcm43xx_private;
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index c44d890..b438f48 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -71,14 +71,46 @@
 	return -EINVAL;
 }
 
+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
+{
+	int i, pos = 0;
+
+	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
+		pos += snprintf(buf + pos, buf_len - pos - 1,
+				"%04X", swab16(sprom[i]) & 0xFFFF);
+	}
+	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
+
+	return pos + 1;
+}
+
+static int hex2sprom(u16 *sprom, const char *dump, size_t len)
+{
+	char tmp[5] = { 0 };
+	int cnt = 0;
+	unsigned long parsed;
+
+	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
+		return -EINVAL;
+
+	while (cnt < BCM43xx_SPROM_SIZE) {
+		memcpy(tmp, dump, 4);
+		dump += 4;
+		parsed = simple_strtoul(tmp, NULL, 16);
+		sprom[cnt++] = swab16((u16)parsed);
+	}
+
+	return 0;
+}
+
 static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -91,55 +123,53 @@
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_read(bcm, sprom);
-	if (!err) {
-		for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-			buf[i * 2] = sprom[i] & 0x00FF;
-			buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8;
-		}
-	}
+	if (!err)
+		err = sprom2hex(sprom, buf, PAGE_SIZE);
 	bcm43xx_unlock_mmio(bcm, flags);
 	kfree(sprom);
 
-	return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16);
+	return err;
 }
 
 static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
 					struct device_attribute *attr,
 					const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	u16 *sprom;
 	unsigned long flags;
-	int i, err;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	if (count != BCM43xx_SPROM_SIZE * sizeof(u16))
-		return -EINVAL;
 	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-		sprom[i] = buf[i * 2] & 0xFF;
-		sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8;
-	}
+	err = hex2sprom(sprom, buf, count);
+	if (err)
+		goto out_kfree;
 	bcm43xx_lock_mmio(bcm, flags);
 	assert(bcm->initialized);
 	err = bcm43xx_sprom_write(bcm, sprom);
 	bcm43xx_unlock_mmio(bcm, flags);
+out_kfree:
 	kfree(sprom);
 
 	return err ? err : count;
 
 }
 
+static DEVICE_ATTR(sprom, 0600,
+		   bcm43xx_attr_sprom_show,
+		   bcm43xx_attr_sprom_store);
+
 static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
 					    struct device_attribute *attr,
 					    char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count = 0;
@@ -175,7 +205,7 @@
 					     struct device_attribute *attr,
 					     const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int mode;
@@ -215,11 +245,15 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(interference, 0644,
+		   bcm43xx_attr_interfmode_show,
+		   bcm43xx_attr_interfmode_store);
+
 static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	ssize_t count;
@@ -245,7 +279,7 @@
 					   struct device_attribute *attr,
 					   const char *buf, size_t count)
 {
-	struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble);
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
 	int err;
 	int value;
@@ -267,56 +301,41 @@
 	return err ? err : count;
 }
 
+static DEVICE_ATTR(shortpreamble, 0644,
+		   bcm43xx_attr_preamble_show,
+		   bcm43xx_attr_preamble_store);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 	int err;
 
 	assert(bcm->initialized);
 
-	sysfs->attr_sprom.attr.name = "sprom";
-	sysfs->attr_sprom.attr.owner = THIS_MODULE;
-	sysfs->attr_sprom.attr.mode = 0600;
-	sysfs->attr_sprom.show = bcm43xx_attr_sprom_show;
-	sysfs->attr_sprom.store = bcm43xx_attr_sprom_store;
-	err = device_create_file(dev, &sysfs->attr_sprom);
+	err = device_create_file(dev, &dev_attr_sprom);
 	if (err)
 		goto out;
-
-	sysfs->attr_interfmode.attr.name = "interference";
-	sysfs->attr_interfmode.attr.owner = THIS_MODULE;
-	sysfs->attr_interfmode.attr.mode = 0600;
-	sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show;
-	sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store;
-	err = device_create_file(dev, &sysfs->attr_interfmode);
+	err = device_create_file(dev, &dev_attr_interference);
 	if (err)
 		goto err_remove_sprom;
-
-	sysfs->attr_preamble.attr.name = "shortpreamble";
-	sysfs->attr_preamble.attr.owner = THIS_MODULE;
-	sysfs->attr_preamble.attr.mode = 0600;
-	sysfs->attr_preamble.show = bcm43xx_attr_preamble_show;
-	sysfs->attr_preamble.store = bcm43xx_attr_preamble_store;
-	err = device_create_file(dev, &sysfs->attr_preamble);
+	err = device_create_file(dev, &dev_attr_shortpreamble);
 	if (err)
 		goto err_remove_interfmode;
 
 out:
 	return err;
 err_remove_interfmode:
-	device_remove_file(dev, &sysfs->attr_interfmode);
+	device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_sprom);
 	goto out;
 }
 
 void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
-	struct bcm43xx_sysfs *sysfs = &bcm->sysfs;
 
-	device_remove_file(dev, &sysfs->attr_preamble);
-	device_remove_file(dev, &sysfs->attr_interfmode);
-	device_remove_file(dev, &sysfs->attr_sprom);
+	device_remove_file(dev, &dev_attr_shortpreamble);
+	device_remove_file(dev, &dev_attr_interference);
+	device_remove_file(dev, &dev_attr_sprom);
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
index 57f1451..cc701df 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
@@ -1,22 +1,6 @@
 #ifndef BCM43xx_SYSFS_H_
 #define BCM43xx_SYSFS_H_
 
-#include <linux/device.h>
-
-
-struct bcm43xx_sysfs {
-	struct device_attribute attr_sprom;
-	struct device_attribute attr_interfmode;
-	struct device_attribute attr_preamble;
-};
-
-#define devattr_to_bcm(attr, attr_name)	({				\
-	struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p;		\
-	__s = container_of((attr), struct bcm43xx_sysfs, attr_name);	\
-	__p = container_of(__s, struct bcm43xx_private, sysfs);		\
-	__p;								\
-					})
-
 struct bcm43xx_private;
 
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 3daee82..3edbb48 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -962,22 +962,22 @@
 	{
 		.cmd		= PRIV_WX_SET_SHORTPREAMBLE,
 		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		.name		= "set_shortpreambl",
+		.name		= "set_shortpreamb",
 	},
 	{
 		.cmd		= PRIV_WX_GET_SHORTPREAMBLE,
 		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-		.name		= "get_shortpreambl",
+		.name		= "get_shortpreamb",
 	},
 	{
 		.cmd		= PRIV_WX_SET_SWENCRYPTION,
 		.set_args	= IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		.name		= "set_swencryption",
+		.name		= "set_swencrypt",
 	},
 	{
 		.cmd		= PRIV_WX_GET_SWENCRYPTION,
 		.get_args	= IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-		.name		= "get_swencryption",
+		.name		= "get_swencrypt",
 	},
 	{
 		.cmd		= PRIV_WX_SPROM_WRITE,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index d335b25..55bed92 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -42,7 +42,7 @@
 /* struct local_info::hw_priv */
 struct hostap_cs_priv {
 	dev_node_t node;
-	dev_link_t *link;
+	struct pcmcia_device *link;
 	int sandisk_connectplus;
 };
 
@@ -204,15 +204,13 @@
 
 static void prism2_detach(struct pcmcia_device *p_dev);
 static void prism2_release(u_long arg);
-static int prism2_config(dev_link_t *link);
+static int prism2_config(struct pcmcia_device *link);
 
 
 static int prism2_pccard_card_present(local_info_t *local)
 {
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
-	if (hw_priv != NULL && hw_priv->link != NULL &&
-	    ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) ==
-	     (DEV_PRESENT | DEV_CONFIG)))
+	if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link))
 		return 1;
 	return 0;
 }
@@ -237,7 +235,7 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = 0x10; /* 0x3f0 IO base 1 */
 	reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
@@ -249,7 +247,7 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = 0x12; /* 0x3f2 IO base 2 */
 	reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
@@ -301,9 +299,9 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
-	    pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
-	    pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+	if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+	    pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+	    pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
 	    parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
 		/* No SanDisk manfid found */
 		ret = -ENODEV;
@@ -311,9 +309,9 @@
 	}
 
 	tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
-	if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) ||
-	    pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) ||
-	    pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) ||
+	if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
+	    pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
+	    pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
 		parse->longlink_mfc.nfn < 2) {
 		/* No multi-function links found */
 		ret = -ENODEV;
@@ -328,7 +326,7 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_COR;
 	reg.Value = COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -345,7 +343,7 @@
 	 * will be enabled during the first cor_sreset call.
 	 */
 	reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
@@ -380,7 +378,7 @@
 	reg.Action = CS_READ;
 	reg.Offset = CISREG_COR;
 	reg.Value = 0;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
@@ -392,7 +390,7 @@
 
 	reg.Action = CS_WRITE;
 	reg.Value |= COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
@@ -405,7 +403,7 @@
 	reg.Value &= ~COR_SOFT_RESET;
 	if (hw_priv->sandisk_connectplus)
 		reg.Value |= COR_IREQ_ENA;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
@@ -439,7 +437,7 @@
 	reg.Action = CS_READ;
 	reg.Offset = CISREG_COR;
 	reg.Value = 0;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
@@ -452,7 +450,7 @@
 
 	reg.Action = CS_WRITE;
 	reg.Value |= COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
@@ -466,7 +464,7 @@
 	reg.Action = CS_WRITE;
 	reg.Value = hcr;
 	reg.Offset = CISREG_CCSR;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
@@ -478,7 +476,7 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_COR;
 	reg.Value = old_cor & ~COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link->handle,
+	res = pcmcia_access_configuration_register(hw_priv->link,
 						   &reg);
 	if (res != CS_SUCCESS) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
@@ -501,40 +499,27 @@
 
 /* allocate local data and register with CardServices
  * initialize dev_link structure, but do not configure the card yet */
-static int prism2_attach(struct pcmcia_device *p_dev)
+static int hostap_cs_probe(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
-
-	link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
-	if (link == NULL)
-		return -ENOMEM;
-
-	memset(link, 0, sizeof(dev_link_t));
+	int ret;
 
 	PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
-	link->conf.Vcc = 33;
-	link->conf.IntType = INT_MEMORY_AND_IO;
+	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	if (prism2_config(link))
+	ret = prism2_config(p_dev);
+	if (ret) {
 		PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+	}
 
-	return 0;
+	return ret;
 }
 
 
-static void prism2_detach(struct pcmcia_device *p_dev)
+static void prism2_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	PDEBUG(DEBUG_FLOW, "prism2_detach\n");
 
-	if (link->state & DEV_CONFIG) {
-		prism2_release((u_long)link);
-	}
+	prism2_release((u_long)link);
 
 	/* release net devices */
 	if (link->priv) {
@@ -547,7 +532,6 @@
 		prism2_free_local_data(dev);
 		kfree(hw_priv);
 	}
-	kfree(link);
 }
 
 
@@ -558,7 +542,7 @@
 do { int ret = (retf); \
 if (ret != 0) { \
 	PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
-	cs_error(link->handle, fn, ret); \
+	cs_error(link, fn, ret); \
 	goto next_entry; \
 } \
 } while (0)
@@ -566,7 +550,7 @@
 
 /* run after a CARD_INSERTION event is received to configure the PCMCIA
  * socket and make the device available to the system */
-static int prism2_config(dev_link_t *link)
+static int prism2_config(struct pcmcia_device *link)
 {
 	struct net_device *dev;
 	struct hostap_interface *iface;
@@ -595,27 +579,24 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
 	link->conf.ConfigBase = parse->config.base;
 	link->conf.Present = parse->config.rmask[0];
 
 	CS_CHECK(GetConfigurationInfo,
-		 pcmcia_get_configuration_info(link->handle, &conf));
-	PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info,
-	       ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc);
-	link->conf.Vcc = conf.Vcc;
+		 pcmcia_get_configuration_info(link, &conf));
 
 	/* Look for an appropriate configuration table entry in the CIS */
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	for (;;) {
 		cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
 		CFG_CHECK2(GetTupleData,
-			   pcmcia_get_tuple_data(link->handle, &tuple));
+			   pcmcia_get_tuple_data(link, &tuple));
 		CFG_CHECK2(ParseTuple,
-			   pcmcia_parse_tuple(link->handle, &tuple, parse));
+			   pcmcia_parse_tuple(link, &tuple, parse));
 
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 			dflt = *cfg;
@@ -650,10 +631,10 @@
 		}
 
 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 		/* Do we need to allocate an interrupt? */
@@ -695,19 +676,19 @@
 
 		/* This reserves IO space but doesn't actually enable it */
 		CFG_CHECK2(RequestIO,
-			   pcmcia_request_io(link->handle, &link->io));
+			   pcmcia_request_io(link, &link->io));
 
 		/* This configuration table entry is OK */
 		break;
 
 	next_entry:
 		CS_CHECK(GetNextTuple,
-			 pcmcia_get_next_tuple(link->handle, &tuple));
+			 pcmcia_get_next_tuple(link, &tuple));
 	}
 
 	/* Need to allocate net_device before requesting IRQ handler */
 	dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
-				     &handle_to_dev(link->handle));
+				     &handle_to_dev(link));
 	if (dev == NULL)
 		goto failed;
 	link->priv = dev;
@@ -717,7 +698,7 @@
 	local->hw_priv = hw_priv;
 	hw_priv->link = link;
 	strcpy(hw_priv->node.dev_name, dev->name);
-	link->dev = &hw_priv->node;
+	link->dev_node = &hw_priv->node;
 
 	/*
 	 * Allocate an interrupt line.  Note that this does not assign a
@@ -730,7 +711,7 @@
 		link->irq.Handler = prism2_interrupt;
 		link->irq.Instance = dev;
 		CS_CHECK(RequestIRQ,
-			 pcmcia_request_irq(link->handle, &link->irq));
+			 pcmcia_request_irq(link, &link->irq));
 	}
 
 	/*
@@ -739,18 +720,17 @@
 	 * card and host interface into "Memory and IO" mode.
 	 */
 	CS_CHECK(RequestConfiguration,
-		 pcmcia_request_configuration(link->handle, &link->conf));
+		 pcmcia_request_configuration(link, &link->conf));
 
 	dev->irq = link->irq.AssignedIRQ;
 	dev->base_addr = link->io.BasePort1;
 
 	/* Finally, report what we've done */
-	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-	       dev_info, link->conf.ConfigIndex,
-	       link->conf.Vcc / 10, link->conf.Vcc % 10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-		       link->conf.Vpp1 % 10);
+	printk(KERN_INFO "%s: index 0x%02x: ",
+	       dev_info, link->conf.ConfigIndex);
+	if (link->conf.Vpp)
+		printk(", Vpp %d.%d", link->conf.Vpp / 10,
+		       link->conf.Vpp % 10);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq.AssignedIRQ);
 	if (link->io.NumPorts1)
@@ -761,9 +741,6 @@
 		       link->io.BasePort2+link->io.NumPorts2-1);
 	printk("\n");
 
-	link->state |= DEV_CONFIG;
-	link->state &= ~DEV_CONFIG_PENDING;
-
 	local->shutdown = 0;
 
 	sandisk_enable_wireless(dev);
@@ -778,7 +755,7 @@
 	return ret;
 
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
  failed:
 	kfree(parse);
@@ -790,7 +767,7 @@
 
 static void prism2_release(u_long arg)
 {
-	dev_link_t *link = (dev_link_t *)arg;
+	struct pcmcia_device *link = (struct pcmcia_device *)arg;
 
 	PDEBUG(DEBUG_FLOW, "prism2_release\n");
 
@@ -799,71 +776,54 @@
 		struct hostap_interface *iface;
 
 		iface = netdev_priv(dev);
-		if (link->state & DEV_CONFIG)
-			prism2_hw_shutdown(dev, 0);
+		prism2_hw_shutdown(dev, 0);
 		iface->local->shutdown = 1;
 	}
 
-	if (link->win)
-		pcmcia_release_window(link->win);
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
-
+	pcmcia_disable_device(link);
 	PDEBUG(DEBUG_FLOW, "release - done\n");
 }
 
-static int hostap_cs_suspend(struct pcmcia_device *p_dev)
+static int hostap_cs_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = (struct net_device *) link->priv;
 	int dev_open = 0;
+	struct hostap_interface *iface = NULL;
+
+	if (dev)
+		iface = netdev_priv(dev);
 
 	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
-
-	link->state |= DEV_SUSPEND;
-
-	if (link->state & DEV_CONFIG) {
-		struct hostap_interface *iface = netdev_priv(dev);
-		if (iface && iface->local)
-			dev_open = iface->local->num_dev_open > 0;
-		if (dev_open) {
-			netif_stop_queue(dev);
-			netif_device_detach(dev);
-		}
-		prism2_suspend(dev);
-		pcmcia_release_configuration(link->handle);
+	if (iface && iface->local)
+		dev_open = iface->local->num_dev_open > 0;
+	if (dev_open) {
+		netif_stop_queue(dev);
+		netif_device_detach(dev);
 	}
+	prism2_suspend(dev);
 
 	return 0;
 }
 
-static int hostap_cs_resume(struct pcmcia_device *p_dev)
+static int hostap_cs_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = (struct net_device *) link->priv;
 	int dev_open = 0;
+	struct hostap_interface *iface = NULL;
+
+	if (dev)
+		iface = netdev_priv(dev);
 
 	PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		struct hostap_interface *iface = netdev_priv(dev);
-		if (iface && iface->local)
-			dev_open = iface->local->num_dev_open > 0;
+	if (iface && iface->local)
+		dev_open = iface->local->num_dev_open > 0;
 
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-		prism2_hw_shutdown(dev, 1);
-		prism2_hw_config(dev, dev_open ? 0 : 1);
-		if (dev_open) {
-			netif_device_attach(dev);
-			netif_start_queue(dev);
-		}
+	prism2_hw_shutdown(dev, 1);
+	prism2_hw_config(dev, dev_open ? 0 : 1);
+	if (dev_open) {
+		netif_device_attach(dev);
+		netif_start_queue(dev);
 	}
 
 	return 0;
@@ -930,7 +890,7 @@
 	.drv		= {
 		.name	= "hostap_cs",
 	},
-	.probe		= prism2_attach,
+	.probe		= hostap_cs_probe,
 	.remove		= prism2_detach,
 	.owner		= THIS_MODULE,
 	.id_table	= hostap_cs_ids,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 8b37e82..8399de5 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1860,7 +1860,7 @@
 	memset(&iwe, 0, sizeof(iwe));
 	iwe.cmd = SIOCGIWFREQ;
 	if (scan) {
-		chan = scan->chid;
+		chan = le16_to_cpu(scan->chid);
 	} else if (bss) {
 		chan = bss->chan;
 	} else {
@@ -1868,7 +1868,7 @@
 	}
 
 	if (chan > 0) {
-		iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000;
+		iwe.u.freq.m = freq_list[chan - 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/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 9dce522..bca89cf 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5573,8 +5573,7 @@
 	case IEEE80211_52GHZ_BAND:
 		network->mode = IEEE_A;
 		i = ieee80211_channel_to_index(priv->ieee, priv->channel);
-		if (i == -1)
-			BUG();
+		BUG_ON(i == -1);
 		if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
 			IPW_WARNING("Overriding invalid channel\n");
 			priv->channel = geo->a[0].channel;
@@ -5587,8 +5586,7 @@
 		else
 			network->mode = IEEE_B;
 		i = ieee80211_channel_to_index(priv->ieee, priv->channel);
-		if (i == -1)
-			BUG();
+		BUG_ON(i == -1);
 		if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
 			IPW_WARNING("Overriding invalid channel\n");
 			priv->channel = geo->bg[0].channel;
@@ -6715,8 +6713,7 @@
 
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:
-		if (!(network->capability & WLAN_CAPABILITY_IBSS))
-			BUG();
+		BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS));
 
 		qos_data = &ibss_data;
 		break;
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 75ce6dd..9343d97 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -190,8 +190,8 @@
 /*====================================================================*/
 
 /* PCMCIA (Card Services) related functions */
-static void netwave_release(dev_link_t *link);     /* Card removal */
-static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 
+static void netwave_release(struct pcmcia_device *link);     /* Card removal */
+static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
 													   insertion */
 static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
 
@@ -221,10 +221,10 @@
 static void set_multicast_list(struct net_device *dev);
 
 /*
-   A dev_link_t structure has fields for most things that are needed
+   A struct pcmcia_device structure has fields for most things that are needed
    to keep track of a socket, but there will usually be some device
    specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
+   'priv' pointer in a struct pcmcia_device structure can be used to point to
    a device-specific private data structure, like this.
 
    A driver needs to provide a dev_node_t structure for each device
@@ -232,7 +232,7 @@
    example, ethernet cards, modems).  In other cases, there may be
    many actual or logical devices (SCSI adapters, memory cards with
    multiple partitions).  The dev_node_t structures need to be kept
-   in a linked list starting at the 'dev' field of a dev_link_t
+   in a linked list starting at the 'dev' field of a struct pcmcia_device
    structure.  We allocate them in the card's private data structure,
    because they generally can't be allocated dynamically.
 */
@@ -268,7 +268,7 @@
 };	
    
 typedef struct netwave_private {
-    dev_link_t link;
+	struct pcmcia_device	*p_dev;
     spinlock_t	spinlock;	/* Serialize access to the hardware (SMP) */
     dev_node_t node;
     u_char     __iomem *ramBase;
@@ -376,20 +376,19 @@
  *     configure the card at this point -- we wait until we receive a
  *     card insertion event.
  */
-static int netwave_attach(struct pcmcia_device *p_dev)
+static int netwave_probe(struct pcmcia_device *link)
 {
-    dev_link_t *link;
     struct net_device *dev;
     netwave_private *priv;
 
     DEBUG(0, "netwave_attach()\n");
 
-    /* Initialize the dev_link_t structure */
+    /* Initialize the struct pcmcia_device structure */
     dev = alloc_etherdev(sizeof(netwave_private));
     if (!dev)
 	return -ENOMEM;
     priv = netdev_priv(dev);
-    link = &priv->link;
+    priv->p_dev = link;
     link->priv = dev;
 
     /* The io structure describes IO port mapping */
@@ -406,7 +405,6 @@
     
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
@@ -430,13 +428,7 @@
     dev->stop = &netwave_close;
     link->irq.Instance = dev;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    netwave_pcmcia_config( link);
-
-    return 0;
+    return netwave_pcmcia_config( link);
 } /* netwave_attach */
 
 /*
@@ -447,17 +439,15 @@
  *    structures are freed.  Otherwise, the structures will be freed
  *    when the device is released.
  */
-static void netwave_detach(struct pcmcia_device *p_dev)
+static void netwave_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
 	DEBUG(0, "netwave_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		netwave_release(link);
+	netwave_release(link);
 
-	if (link->dev)
+	if (link->dev_node)
 		unregister_netdev(dev);
 
 	free_netdev(dev);
@@ -743,8 +733,7 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void netwave_pcmcia_config(dev_link_t *link) {
-    client_handle_t handle = link->handle;
+static int netwave_pcmcia_config(struct pcmcia_device *link) {
     struct net_device *dev = link->priv;
     netwave_private *priv = netdev_priv(dev);
     tuple_t tuple;
@@ -766,15 +755,12 @@
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /*
      *  Try allocating IO ports.  This tries a few fixed addresses.
      *  If you want, you can also read the card's config table to
@@ -782,11 +768,11 @@
      */
     for (i = j = 0x0; j < 0x400; j += 0x20) {
 	link->io.BasePort1 = j ^ 0x300;
-	i = pcmcia_request_io(link->handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
 	if (i == CS_SUCCESS) break;
     }
     if (i != CS_SUCCESS) {
-	cs_error(link->handle, RequestIO, i);
+	cs_error(link, RequestIO, i);
 	goto failed;
     }
 
@@ -794,16 +780,16 @@
      *  Now allocate an interrupt line.  Note that this does not
      *  actually assign a handler to the interrupt.
      */
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
     /*
      *  This actually configures the PCMCIA socket -- setting up
      *  the I/O windows and the interrupt mapping.
      */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
     /*
-     *  Allocate a 32K memory window.  Note that the dev_link_t
+     *  Allocate a 32K memory window.  Note that the struct pcmcia_device
      *  structure provides space for one window handle -- if your
      *  device needs several windows, you'll need to keep track of
      *  the handles in your private data structure, dev->priv.
@@ -813,7 +799,7 @@
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
     req.Base = 0; req.Size = 0x8000;
     req.AccessSpeed = mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
     mem.CardOffset = 0x20000; mem.Page = 0; 
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
 
@@ -823,7 +809,7 @@
 
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
 
     if (register_netdev(dev) != 0) {
 	printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
@@ -831,8 +817,7 @@
     }
 
     strcpy(priv->node.dev_name, dev->name);
-    link->dev = &priv->node;
-    link->state &= ~DEV_CONFIG_PENDING;
+    link->dev_node = &priv->node;
 
     /* Reset card before reading physical address */
     netwave_doreset(dev->base_addr, ramBase);
@@ -852,12 +837,13 @@
     printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", 
 	   get_uint16(ramBase + NETWAVE_EREG_ARW),
 	   get_uint16(ramBase + NETWAVE_EREG_ARW+2));
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     netwave_release(link);
+    return -ENODEV;
 } /* netwave_pcmcia_config */
 
 /*
@@ -867,52 +853,35 @@
  *    device, and release the PCMCIA configuration.  If the device is
  *    still open, this will be postponed until it is closed.
  */
-static void netwave_release(dev_link_t *link)
+static void netwave_release(struct pcmcia_device *link)
 {
-    struct net_device *dev = link->priv;
-    netwave_private *priv = netdev_priv(dev);
+	struct net_device *dev = link->priv;
+	netwave_private *priv = netdev_priv(dev);
 
-    DEBUG(0, "netwave_release(0x%p)\n", link);
+	DEBUG(0, "netwave_release(0x%p)\n", link);
 
-    /* Don't bother checking to see if these succeed or not */
-    if (link->win) {
-	iounmap(priv->ramBase);
-	pcmcia_release_window(link->win);
-    }
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
+	if (link->win)
+		iounmap(priv->ramBase);
 }
 
-static int netwave_suspend(struct pcmcia_device *p_dev)
+static int netwave_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int netwave_resume(struct pcmcia_device *p_dev)
+static int netwave_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			netwave_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		netwave_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -1119,7 +1088,7 @@
     u_char __iomem *ramBase;
     struct net_device *dev = (struct net_device *)dev_id;
     struct netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
     int i;
     
     if (!netif_device_present(dev))
@@ -1138,7 +1107,7 @@
 	
         status = inb(iobase + NETWAVE_REG_ASR);
 		
-	if (!DEV_OK(link)) {
+	if (!pcmcia_dev_present(link)) {
 	    DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x "
 		  "from removed or suspended card!\n", status);
 	    break;
@@ -1373,11 +1342,11 @@
 
 static int netwave_open(struct net_device *dev) {
     netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
 
     DEBUG(1, "netwave_open: starting.\n");
     
-    if (!DEV_OK(link))
+    if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
     link->open++;
@@ -1390,7 +1359,7 @@
 
 static int netwave_close(struct net_device *dev) {
     netwave_private *priv = netdev_priv(dev);
-    dev_link_t *link = &priv->link;
+    struct pcmcia_device *link = priv->p_dev;
 
     DEBUG(1, "netwave_close: finishing.\n");
 
@@ -1411,7 +1380,7 @@
 	.drv		= {
 		.name	= "netwave_cs",
 	},
-	.probe		= netwave_attach,
+	.probe		= netwave_probe,
 	.remove		= netwave_detach,
 	.id_table       = netwave_ids,
 	.suspend	= netwave_suspend,
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 8dfdfbd..06523e2 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -390,7 +390,7 @@
 		}
 	} else {
 		struct {
-			__le16 qual, signal, noise;
+			__le16 qual, signal, noise, unused;
 		} __attribute__ ((packed)) cq;
 
 		err = HERMES_READ_RECORD(hw, USER_BAP,
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index ec6f2a4..434f7d7 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -49,7 +49,7 @@
 /* PCMCIA specific device information (goes in the card field of
  * struct orinoco_private */
 struct orinoco_pccard {
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 
 	/* Used to handle hard reset */
@@ -63,8 +63,8 @@
 /* Function prototypes						    */
 /********************************************************************/
 
-static void orinoco_cs_config(dev_link_t *link);
-static void orinoco_cs_release(dev_link_t *link);
+static int orinoco_cs_config(struct pcmcia_device *link);
+static void orinoco_cs_release(struct pcmcia_device *link);
 static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
@@ -75,13 +75,13 @@
 orinoco_cs_hard_reset(struct orinoco_private *priv)
 {
 	struct orinoco_pccard *card = priv->card;
-	dev_link_t *link = &card->link;
+	struct pcmcia_device *link = card->p_dev;
 	int err;
 
 	/* We need atomic ops here, because we're not holding the lock */
 	set_bit(0, &card->hard_reset_in_progress);
 
-	err = pcmcia_reset_card(link->handle, NULL);
+	err = pcmcia_reset_card(link, NULL);
 	if (err)
 		return err;
 
@@ -104,12 +104,11 @@
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
 static int
-orinoco_cs_attach(struct pcmcia_device *p_dev)
+orinoco_cs_probe(struct pcmcia_device *link)
 {
 	struct net_device *dev;
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
-	dev_link_t *link;
 
 	dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
 	if (! dev)
@@ -118,7 +117,7 @@
 	card = priv->card;
 
 	/* Link both structures together */
-	link = &card->link;
+	card->p_dev = link;
 	link->priv = dev;
 
 	/* Interrupt setup */
@@ -135,16 +134,7 @@
 	link->conf.Attributes = 0;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	/* Register with Card Services */
-	link->next = NULL;
-
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	orinoco_cs_config(link);
-
-	return 0;
+	return orinoco_cs_config(link);
 }				/* orinoco_cs_attach */
 
 /*
@@ -153,16 +143,14 @@
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void orinoco_cs_detach(struct pcmcia_device *p_dev)
+static void orinoco_cs_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		orinoco_cs_release(link);
+	orinoco_cs_release(link);
 
-	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
-	if (link->dev) {
+	DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+	if (link->dev_node) {
 		DEBUG(0, PFX "About to unregister net device %p\n",
 		      dev);
 		unregister_netdev(dev);
@@ -180,11 +168,10 @@
 		last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
 	} while (0)
 
-static void
-orinoco_cs_config(dev_link_t *link)
+static int
+orinoco_cs_config(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
-	client_handle_t handle = link->handle;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	hermes_t *hw = &priv->hw;
@@ -196,7 +183,7 @@
 	cisparse_t parse;
 	void __iomem *mem;
 
-	CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+	CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
 
 	/*
 	 * This reads the card's CONFIG tuple to find its
@@ -207,19 +194,15 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	/* Look up the current Vcc */
 	CS_CHECK(GetConfigurationInfo,
-		 pcmcia_get_configuration_info(handle, &conf));
-	link->conf.Vcc = conf.Vcc;
+		 pcmcia_get_configuration_info(link, &conf));
 
 	/*
 	 * In this loop, we scan the CIS for configuration table
@@ -236,13 +219,13 @@
 	 * implementation-defined details.
 	 */
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 		cistpl_cftable_entry_t dflt = { .index = 0 };
 
-		if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
-		    || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+		if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+		    || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
 			goto next_entry;
 
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -274,10 +257,10 @@
 		}
 
 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		
 		/* Do we need to allocate an interrupt? */
@@ -307,7 +290,7 @@
 			}
 
 			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(link->handle, &link->io) != 0)
+			if (pcmcia_request_io(link, &link->io) != 0)
 				goto next_entry;
 		}
 
@@ -317,9 +300,8 @@
 		break;
 		
 	next_entry:
-		if (link->io.NumPorts1)
-			pcmcia_release_io(link->handle, &link->io);
-		last_ret = pcmcia_get_next_tuple(handle, &tuple);
+		pcmcia_disable_device(link);
+		last_ret = pcmcia_get_next_tuple(link, &tuple);
 		if (last_ret  == CS_NO_MORE_ITEMS) {
 			printk(KERN_ERR PFX "GetNextTuple(): No matching "
 			       "CIS configuration.  Maybe you need the "
@@ -333,7 +315,7 @@
 	 * a handler to the interrupt, unless the 'Handler' member of
 	 * the irq structure is initialized.
 	 */
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
 	/* We initialize the hermes structure before completing PCMCIA
 	 * configuration just in case the interrupt handler gets
@@ -350,7 +332,7 @@
 	 * card and host interface into "Memory and IO" mode.
 	 */
 	CS_CHECK(RequestConfiguration,
-		 pcmcia_request_configuration(link->handle, &link->conf));
+		 pcmcia_request_configuration(link, &link->conf));
 
 	/* Ok, we have the configuration, prepare to register the netdev */
 	dev->base_addr = link->io.BasePort1;
@@ -358,7 +340,7 @@
 	SET_MODULE_OWNER(dev);
 	card->node.major = card->node.minor = 0;
 
-	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+	SET_NETDEV_DEV(dev, &handle_to_dev(link));
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
 		printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -366,20 +348,18 @@
 	}
 
 	/* At this point, the dev_node_t structure(s) needs to be
-	 * initialized and arranged in a linked list at link->dev. */
+	 * initialized and arranged in a linked list at link->dev_node. */
 	strcpy(card->node.dev_name, dev->name);
-	link->dev = &card->node; /* link->dev being non-NULL is also
+	link->dev_node = &card->node; /* link->dev_node being non-NULL is also
                                     used to indicate that the
                                     net_device has been registered */
-	link->state &= ~DEV_CONFIG_PENDING;
 
 	/* Finally, report what we've done */
-	printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
-	       dev->name, link->conf.ConfigIndex,
-	       link->conf.Vcc / 10, link->conf.Vcc % 10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-		       link->conf.Vpp1 % 10);
+	printk(KERN_DEBUG "%s: index 0x%02x: ",
+	       dev->name, link->conf.ConfigIndex);
+	if (link->conf.Vpp)
+		printk(", Vpp %d.%d", link->conf.Vpp / 10,
+		       link->conf.Vpp % 10);
 	printk(", irq %d", link->irq.AssignedIRQ);
 	if (link->io.NumPorts1)
 		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -389,13 +369,14 @@
 		       link->io.BasePort2 + link->io.NumPorts2 - 1);
 	printk("\n");
 
-	return;
+	return 0;
 
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
  failed:
 	orinoco_cs_release(link);
+	return -ENODEV;
 }				/* orinoco_cs_config */
 
 /*
@@ -404,7 +385,7 @@
  * still open, this will be postponed until it is closed.
  */
 static void
-orinoco_cs_release(dev_link_t *link)
+orinoco_cs_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -416,88 +397,68 @@
 	priv->hw_unavailable++;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Don't bother checking to see if these succeed or not */
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 	if (priv->hw.iobase)
 		ioport_unmap(priv->hw.iobase);
 }				/* orinoco_cs_release */
 
-static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
+static int orinoco_cs_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
 	unsigned long flags;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		/* This is probably racy, but I can't think of
-		   a better way, short of rewriting the PCMCIA
-		   layer to not suck :-( */
-		if (! test_bit(0, &card->hard_reset_in_progress)) {
-			spin_lock_irqsave(&priv->lock, flags);
+	/* This is probably racy, but I can't think of
+	   a better way, short of rewriting the PCMCIA
+	   layer to not suck :-( */
+	if (! test_bit(0, &card->hard_reset_in_progress)) {
+		spin_lock_irqsave(&priv->lock, flags);
 
-			err = __orinoco_down(dev);
-			if (err)
-				printk(KERN_WARNING "%s: Error %d downing interface\n",
-				       dev->name, err);
+		err = __orinoco_down(dev);
+		if (err)
+			printk(KERN_WARNING "%s: Error %d downing interface\n",
+			       dev->name, err);
 
-			netif_device_detach(dev);
-			priv->hw_unavailable++;
+		netif_device_detach(dev);
+		priv->hw_unavailable++;
 
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-
-		pcmcia_release_configuration(link->handle);
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
 	return 0;
 }
 
-static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+static int orinoco_cs_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
 	unsigned long flags;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		/* FIXME: should we double check that this is
-		 * the same card as we had before */
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-		if (! test_bit(0, &card->hard_reset_in_progress)) {
-			err = orinoco_reinit_firmware(dev);
-			if (err) {
-				printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
-				       dev->name, err);
-				return -EIO;
-			}
-
-			spin_lock_irqsave(&priv->lock, flags);
-
-			netif_device_attach(dev);
-			priv->hw_unavailable--;
-
-			if (priv->open && ! priv->hw_unavailable) {
-				err = __orinoco_up(dev);
-				if (err)
-					printk(KERN_ERR "%s: Error %d restarting card\n",
-					       dev->name, err);
-			}
-
-			spin_unlock_irqrestore(&priv->lock, flags);
+	if (! test_bit(0, &card->hard_reset_in_progress)) {
+		err = orinoco_reinit_firmware(dev);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+			       dev->name, err);
+			return -EIO;
 		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		netif_device_attach(dev);
+		priv->hw_unavailable--;
+
+		if (priv->open && ! priv->hw_unavailable) {
+			err = __orinoco_up(dev);
+			if (err)
+				printk(KERN_ERR "%s: Error %d restarting card\n",
+				       dev->name, err);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
 	return 0;
@@ -604,7 +565,7 @@
 	.drv		= {
 		.name	= DRIVER_NAME,
 	},
-	.probe		= orinoco_cs_attach,
+	.probe		= orinoco_cs_probe,
 	.remove		= orinoco_cs_detach,
 	.id_table       = orinoco_cs_ids,
 	.suspend	= orinoco_cs_suspend,
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7880d8c..879eb42 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -90,8 +90,8 @@
 #define DEBUG(n, args...)
 #endif
 /** Prototypes based on PCMCIA skeleton driver *******************************/
-static void ray_config(dev_link_t *link);
-static void ray_release(dev_link_t *link);
+static int ray_config(struct pcmcia_device *link);
+static void ray_release(struct pcmcia_device *link);
 static void ray_detach(struct pcmcia_device *p_dev);
 
 /***** Prototypes indicated by device structure ******************************/
@@ -190,20 +190,17 @@
 static char *phy_addr = NULL;
 
 
-/* A linked list of "instances" of the ray device.  Each actual
-   PCMCIA card corresponds to one device instance, and is described
-   by one dev_link_t structure (defined in ds.h).
-*/
-static dev_link_t *dev_list = NULL;
-
-/* A dev_link_t structure has fields for most things that are needed
+/* A struct pcmcia_device structure has fields for most things that are needed
    to keep track of a socket, but there will usually be some device
    specific information that also needs to be kept track of.  The
-   'priv' pointer in a dev_link_t structure can be used to point to
+   'priv' pointer in a struct pcmcia_device structure can be used to point to
    a device-specific private data structure, like this.
 */
 static unsigned int ray_mem_speed = 500;
 
+/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */
+static struct pcmcia_device *this_device = NULL;
+
 MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
 MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
 MODULE_LICENSE("GPL");
@@ -306,56 +303,46 @@
     configure the card at this point -- we wait until we receive a
     card insertion event.
 =============================================================================*/
-static int ray_attach(struct pcmcia_device *p_dev)
+static int ray_probe(struct pcmcia_device *p_dev)
 {
-    dev_link_t *link;
     ray_dev_t *local;
     struct net_device *dev;
-    
+
     DEBUG(1, "ray_attach()\n");
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-
-    if (!link)
-	    return -ENOMEM;
-
     /* Allocate space for private device-specific data */
     dev = alloc_etherdev(sizeof(ray_dev_t));
-
     if (!dev)
 	    goto fail_alloc_dev;
 
     local = dev->priv;
-
-    memset(link, 0, sizeof(struct dev_link_t));
+    local->finder = p_dev;
 
     /* The io structure describes IO port mapping. None used here */
-    link->io.NumPorts1 = 0;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.IOAddrLines = 5;
+    p_dev->io.NumPorts1 = 0;
+    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    p_dev->io.IOAddrLines = 5;
 
     /* Interrupt setup. For PCMCIA, driver takes what's given */
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->irq.Handler = &ray_interrupt;
+    p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+    p_dev->irq.Handler = &ray_interrupt;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->conf.IntType = INT_MEMORY_AND_IO;
+    p_dev->conf.ConfigIndex = 1;
+    p_dev->conf.Present = PRESENT_OPTION;
 
-    link->priv = dev;
-    link->irq.Instance = dev;
+    p_dev->priv = dev;
+    p_dev->irq.Instance = dev;
     
-    local->finder = link;
+    local->finder = p_dev;
     local->card_status = CARD_INSERTED;
     local->authentication_state = UNAUTHENTICATED;
     local->num_multi = 0;
-    DEBUG(2,"ray_attach link = %p,  dev = %p,  local = %p, intr = %p\n",
-          link,dev,local,&ray_interrupt);
+    DEBUG(2,"ray_attach p_dev = %p,  dev = %p,  local = %p, intr = %p\n",
+          p_dev,dev,local,&ray_interrupt);
 
     /* Raylink entries in the device structure */
     dev->hard_start_xmit = &ray_dev_start_xmit;
@@ -379,16 +366,10 @@
 
     init_timer(&local->timer);
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    ray_config(link);
-
-    return 0;
+    this_device = p_dev;
+    return ray_config(p_dev);
 
 fail_alloc_dev:
-    kfree(link);
     return -ENOMEM;
 } /* ray_attach */
 /*=============================================================================
@@ -397,37 +378,25 @@
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-static void ray_detach(struct pcmcia_device *p_dev)
+static void ray_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    dev_link_t **linkp;
     struct net_device *dev;
     ray_dev_t *local;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-        if (*linkp == link) break;
-    if (*linkp == NULL)
-        return;
 
+    this_device = NULL;
     dev = link->priv;
 
-    if (link->state & DEV_CONFIG) {
-	    ray_release(link);
+    ray_release(link);
 
-	    local = (ray_dev_t *)dev->priv;
-            del_timer(&local->timer);
-    }
+    local = (ray_dev_t *)dev->priv;
+    del_timer(&local->timer);
 
-    /* Unlink device structure, free pieces */
-    *linkp = link->next;
     if (link->priv) {
-	if (link->dev) unregister_netdev(dev);
+	if (link->dev_node) unregister_netdev(dev);
         free_netdev(dev);
     }
-    kfree(link);
     DEBUG(2,"ray_cs ray_detach ending\n");
 } /* ray_detach */
 /*=============================================================================
@@ -438,9 +407,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 #define MAX_TUPLE_SIZE 128
-static void ray_config(dev_link_t *link)
+static int ray_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     tuple_t tuple;
     cisparse_t parse;
     int last_fn = 0, last_ret = 0;
@@ -455,48 +423,45 @@
 
     /* This reads the card's CONFIG tuple to find its configuration regs */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = buf;
     tuple.TupleDataMax = MAX_TUPLE_SIZE;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
 
     /* Determine card type and firmware version */
     buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
     tuple.DesiredTuple = CISTPL_VERS_1;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     tuple.TupleData = buf;
     tuple.TupleDataMax = MAX_TUPLE_SIZE;
     tuple.TupleOffset = 2;
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 
     for (i=0; i<tuple.TupleDataLen - 4; i++) 
         if (buf[i] == 0) buf[i] = ' ';
     printk(KERN_INFO "ray_cs Detected: %s\n",buf);
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     /* Now allocate an interrupt line.  Note that this does not
        actually assign a handler to the interrupt.
     */
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     dev->irq = link->irq.AssignedIRQ;
     
     /* This actually configures the PCMCIA socket -- setting up
        the I/O windows and the interrupt mapping.
     */
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 /*** Set up 32k window for shared memory (transmit and control) ************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
     req.Base = 0;
     req.Size = 0x8000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
     local->sram = ioremap(req.Base,req.Size);
@@ -506,7 +471,7 @@
     req.Base = 0;
     req.Size = 0x4000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle));
     mem.CardOffset = 0x8000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
     local->rmem = ioremap(req.Base,req.Size);
@@ -516,7 +481,7 @@
     req.Base = 0;
     req.Size = 0x1000;
     req.AccessSpeed = ray_mem_speed;
-    CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
+    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
     local->amem = ioremap(req.Base,req.Size);
@@ -526,32 +491,32 @@
     DEBUG(3,"ray_config amem=%p\n",local->amem);
     if (ray_init(dev) < 0) {
         ray_release(link);
-        return;
+        return -ENODEV;
     }
 
-    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+    SET_NETDEV_DEV(dev, &handle_to_dev(link));
     i = register_netdev(dev);
     if (i != 0) {
         printk("ray_config register_netdev() failed\n");
         ray_release(link);
-        return;
+        return i;
     }
 
     strcpy(local->node.dev_name, dev->name);
-    link->dev = &local->node;
+    link->dev_node = &local->node;
 
-    link->state &= ~DEV_CONFIG_PENDING;
     printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
        dev->name, dev->irq);
     for (i = 0; i < 6; i++)
     printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
 
-    return;
+    return 0;
 
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 
     ray_release(link);
+    return -ENODEV;
 } /* ray_config */
 
 static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
@@ -578,9 +543,9 @@
     UCHAR *p;
     struct ccs __iomem *pccs;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     DEBUG(1, "ray_init(0x%p)\n", dev);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(0,"ray_init - device not present\n");
         return -1;
     }
@@ -640,10 +605,10 @@
     int ccsindex;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     struct ccs __iomem *pccs;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
     DEBUG(1,"dl_startup_params entered\n");
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs dl_startup_params - device not present\n");
         return -1;
     }
@@ -747,9 +712,9 @@
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
     UCHAR status;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
         return;
     }
@@ -787,8 +752,8 @@
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs __iomem *pccs;
     int ccsindex;
-    dev_link_t *link = local->finder;
-    if (!(link->state & DEV_PRESENT)) {
+    struct pcmcia_device *link = local->finder;
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs start_net - device not present\n");
         return;
     }
@@ -814,9 +779,9 @@
 
     struct ccs __iomem *pccs;
     int ccsindex;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs join_net - device not present\n");
         return;
     }
@@ -840,7 +805,7 @@
     device, and release the PCMCIA configuration.  If the device is
     still open, this will be postponed until it is closed.
 =============================================================================*/
-static void ray_release(dev_link_t *link)
+static void ray_release(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv; 
     ray_dev_t *local = dev->priv;
@@ -849,56 +814,38 @@
     DEBUG(1, "ray_release(0x%p)\n", link);
 
     del_timer(&local->timer);
-    link->state &= ~DEV_CONFIG;
 
     iounmap(local->sram);
     iounmap(local->rmem);
     iounmap(local->amem);
     /* Do bother checking to see if these succeed or not */
-    i = pcmcia_release_window(link->win);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
     i = pcmcia_release_window(local->amem_handle);
     if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
     i = pcmcia_release_window(local->rmem_handle);
     if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
-    i = pcmcia_release_configuration(link->handle);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
-    i = pcmcia_release_irq(link->handle, &link->irq);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
+    pcmcia_disable_device(link);
 
     DEBUG(2,"ray_release ending\n");
 }
 
-static int ray_suspend(struct pcmcia_device *p_dev)
+static int ray_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-
-		pcmcia_release_configuration(link->handle);
-        }
-
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int ray_resume(struct pcmcia_device *p_dev)
+static int ray_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-        if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			ray_reset(dev);
-			netif_device_attach(dev);
-		}
-        }
+	if (link->open) {
+		ray_reset(dev);
+		netif_device_attach(dev);
+	}
 
 	return 0;
 }
@@ -910,10 +857,10 @@
     int i;
 #endif	/* RAY_IMMEDIATE_INIT */
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
     DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_init - device not present\n");
         return -1;
     }
@@ -944,10 +891,10 @@
 static int ray_dev_config(struct net_device *dev, struct ifmap *map)
 {
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     /* Dummy routine to satisfy device structure */
     DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_config - device not present\n");
         return -1;
     }
@@ -958,10 +905,10 @@
 static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     ray_dev_t *local = dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     short length = skb->len;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_dev_start_xmit - device not present\n");
         return -1;
     }
@@ -1570,7 +1517,7 @@
 static iw_stats * ray_get_wireless_stats(struct net_device *	dev)
 {
   ray_dev_t *	local = (ray_dev_t *) dev->priv;
-  dev_link_t *link = local->finder;
+  struct pcmcia_device *link = local->finder;
   struct status __iomem *p = local->sram + STATUS_BASE;
 
   if(local == (ray_dev_t *) NULL)
@@ -1588,7 +1535,7 @@
     }
 #endif /* WIRELESS_SPY */
 
-  if((link->state & DEV_PRESENT)) {
+  if(pcmcia_dev_present(link)) {
     local->wstats.qual.noise = readb(&p->rxnoise);
     local->wstats.qual.updated |= 4;
   }
@@ -1657,18 +1604,14 @@
 /*===========================================================================*/
 static int ray_open(struct net_device *dev)
 {
-    dev_link_t *link;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
+    struct pcmcia_device *link;
+    link = local->finder;
     
     DEBUG(1, "ray_open('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-        if (link->priv == dev) break;
-    if (!DEV_OK(link)) {
-        return -ENODEV;
-    }
-
-    if (link->open == 0) local->num_multi = 0;
+    if (link->open == 0)
+	    local->num_multi = 0;
     link->open++;
 
     /* If the card is not started, time to start it ! - Jean II */
@@ -1695,15 +1638,12 @@
 /*===========================================================================*/
 static int ray_dev_close(struct net_device *dev)
 {
-    dev_link_t *link;
+    ray_dev_t *local = (ray_dev_t *)dev->priv;
+    struct pcmcia_device *link;
+    link = local->finder;
 
     DEBUG(1, "ray_dev_close('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-        if (link->priv == dev) break;
-    if (link == NULL)
-        return -ENODEV;
-
     link->open--;
     netif_stop_queue(dev);
 
@@ -1725,9 +1665,9 @@
 static int interrupt_ecf(ray_dev_t *local, int ccs)
 {
     int i = 50;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
         return -1;
     }
@@ -1752,9 +1692,9 @@
 {
     int i;
     struct ccs __iomem *pccs = ccs_base(local);
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
         return ECARDGONE;
     }
@@ -1783,9 +1723,9 @@
 {
     int i;
     struct ccs __iomem *pccs = ccs_base(local);
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs get_free_ccs - device not present\n");
         return ECARDGONE;
     }
@@ -1858,9 +1798,9 @@
 static struct net_device_stats *ray_get_stats(struct net_device *dev)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     struct status __iomem *p = local->sram + STATUS_BASE;
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs net_device_stats - device not present\n");
         return &local->stats;
     }
@@ -1888,12 +1828,12 @@
 static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     int ccsindex;
     int i;
     struct ccs __iomem *pccs;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_update_parm - device not present\n");
         return;
     }
@@ -1925,10 +1865,10 @@
     struct ccs __iomem *pccs;
     int i = 0;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     void __iomem *p = local->sram + HOST_TO_ECF_BASE;
 
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_update_multi_list - device not present\n");
         return;
     }
@@ -2005,7 +1945,7 @@
 static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
     struct net_device *dev = (struct net_device *)dev_id;
-    dev_link_t *link;
+    struct pcmcia_device *link;
     ray_dev_t *local;
     struct ccs __iomem *pccs;
     struct rcs __iomem *prcs;
@@ -2020,8 +1960,8 @@
     DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
 
     local = (ray_dev_t *)dev->priv;
-    link = (dev_link_t *)local->finder;
-    if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
+    link = (struct pcmcia_device *)local->finder;
+    if (!pcmcia_dev_present(link)) {
         DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
         return IRQ_NONE;
     }
@@ -2540,9 +2480,9 @@
 /*===========================================================================*/
 static void authenticate(ray_dev_t *local)
 {
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     DEBUG(0,"ray_cs Starting authentication.\n");
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs authenticate - device not present\n");
         return;
     }
@@ -2606,10 +2546,10 @@
 static void associate(ray_dev_t *local)
 {
     struct ccs __iomem *pccs;
-    dev_link_t *link = local->finder;
+    struct pcmcia_device *link = local->finder;
     struct net_device *dev = link->priv;
     int ccsindex;
-    if (!(link->state & DEV_PRESENT)) {
+    if (!(pcmcia_dev_present(link))) {
         DEBUG(2,"ray_cs associate - device not present\n");
         return;
     }
@@ -2689,14 +2629,14 @@
  * eg ifconfig 
  */
     int i;
-    dev_link_t *link;
+    struct pcmcia_device *link;
     struct net_device *dev;
     ray_dev_t *local;
     UCHAR *p;
     struct freq_hop_element *pfh;
     UCHAR c[33];
 
-    link = dev_list;
+    link = this_device;
     if (!link)
     	return 0;
     dev = (struct net_device *)link->priv;
@@ -2898,7 +2838,7 @@
 	.drv		= {
 		.name	= "ray_cs",
 	},
-	.probe		= ray_attach,
+	.probe		= ray_probe,
 	.remove		= ray_detach,
 	.id_table       = ray_ids,
 	.suspend	= ray_suspend,
@@ -2940,7 +2880,6 @@
 #endif
 
     pcmcia_unregister_driver(&ray_driver);
-    BUG_ON(dev_list != NULL);
 } /* exit_ray_cs */
 
 module_init(init_ray_cs);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 42660fe..bd73ebf 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -31,7 +31,7 @@
     void __iomem *sram;            /* pointer to beginning of shared RAM     */
     void __iomem *amem;            /* pointer to attribute mem window        */
     void __iomem *rmem;            /* pointer to receive buffer window       */
-    dev_link_t *finder;            /* pointer back to dev_link_t for card    */
+    struct pcmcia_device *finder;            /* pointer back to struct pcmcia_device for card    */
     struct timer_list timer;
     long tx_ccs_lock;
     long ccs_lock;
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 5fa6fbe..f7b77ce 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -63,7 +63,7 @@
 /* PCMCIA specific device information (goes in the card field of
  * struct orinoco_private */
 struct orinoco_pccard {
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 };
 
@@ -71,8 +71,8 @@
 /* Function prototypes						    */
 /********************************************************************/
 
-static void spectrum_cs_config(dev_link_t *link);
-static void spectrum_cs_release(dev_link_t *link);
+static int spectrum_cs_config(struct pcmcia_device *link);
+static void spectrum_cs_release(struct pcmcia_device *link);
 
 /********************************************************************/
 /* Firmware downloader						    */
@@ -238,14 +238,14 @@
  * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
  */
 static int
-spectrum_reset(dev_link_t *link, int idle)
+spectrum_reset(struct pcmcia_device *link, int idle)
 {
 	int last_ret, last_fn;
 	conf_reg_t reg;
 	u_int save_cor;
 
 	/* Doing it if hardware is gone is guaranteed crash */
-	if (!(link->state & DEV_CONFIG))
+	if (pcmcia_dev_present(link))
 		return -ENODEV;
 
 	/* Save original COR value */
@@ -253,7 +253,7 @@
 	reg.Action = CS_READ;
 	reg.Offset = CISREG_COR;
 	CS_CHECK(AccessConfigurationRegister,
-		 pcmcia_access_configuration_register(link->handle, &reg));
+		 pcmcia_access_configuration_register(link, &reg));
 	save_cor = reg.Value;
 
 	/* Soft-Reset card */
@@ -261,14 +261,14 @@
 	reg.Offset = CISREG_COR;
 	reg.Value = (save_cor | COR_SOFT_RESET);
 	CS_CHECK(AccessConfigurationRegister,
-		 pcmcia_access_configuration_register(link->handle, &reg));
+		 pcmcia_access_configuration_register(link, &reg));
 	udelay(1000);
 
 	/* Read CCSR */
 	reg.Action = CS_READ;
 	reg.Offset = CISREG_CCSR;
 	CS_CHECK(AccessConfigurationRegister,
-		 pcmcia_access_configuration_register(link->handle, &reg));
+		 pcmcia_access_configuration_register(link, &reg));
 
 	/*
 	 * Start or stop the firmware.  Memory width bit should be
@@ -278,7 +278,7 @@
 	reg.Offset = CISREG_CCSR;
 	reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
 	CS_CHECK(AccessConfigurationRegister,
-		 pcmcia_access_configuration_register(link->handle, &reg));
+		 pcmcia_access_configuration_register(link, &reg));
 	udelay(1000);
 
 	/* Restore original COR configuration index */
@@ -286,12 +286,12 @@
 	reg.Offset = CISREG_COR;
 	reg.Value = (save_cor & ~COR_SOFT_RESET);
 	CS_CHECK(AccessConfigurationRegister,
-		 pcmcia_access_configuration_register(link->handle, &reg));
+		 pcmcia_access_configuration_register(link, &reg));
 	udelay(1000);
 	return 0;
 
       cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	return -ENODEV;
 }
 
@@ -441,7 +441,7 @@
  * care of the PDA - read it and then write it on top of the firmware.
  */
 static int
-spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
 		  const unsigned char *image)
 {
 	int ret;
@@ -505,14 +505,13 @@
  * reset on the card, to make sure it's in a sane state.
  */
 static int
-spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
 {
 	int ret;
-	client_handle_t handle = link->handle;
 	const struct firmware *fw_entry;
 
 	if (request_firmware(&fw_entry, primary_fw_name,
-			     &handle_to_dev(handle)) == 0) {
+			     &handle_to_dev(link)) == 0) {
 		primsym = fw_entry->data;
 	} else {
 		printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -521,7 +520,7 @@
 	}
 
 	if (request_firmware(&fw_entry, secondary_fw_name,
-			     &handle_to_dev(handle)) == 0) {
+			     &handle_to_dev(link)) == 0) {
 		secsym = fw_entry->data;
 	} else {
 		printk(KERN_ERR PFX "Cannot find firmware: %s\n",
@@ -554,12 +553,12 @@
 spectrum_cs_hard_reset(struct orinoco_private *priv)
 {
 	struct orinoco_pccard *card = priv->card;
-	dev_link_t *link = &card->link;
+	struct pcmcia_device *link = card->p_dev;
 	int err;
 
 	if (!hermes_present(&priv->hw)) {
 		/* The firmware needs to be reloaded */
-		if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+		if (spectrum_dl_firmware(&priv->hw, link) != 0) {
 			printk(KERN_ERR PFX "Firmware download failed\n");
 			err = -ENODEV;
 		}
@@ -584,12 +583,11 @@
  * configure the card at this point -- we wait until we receive a card
  * insertion event.  */
 static int
-spectrum_cs_attach(struct pcmcia_device *p_dev)
+spectrum_cs_probe(struct pcmcia_device *link)
 {
 	struct net_device *dev;
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
-	dev_link_t *link;
 
 	dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
 	if (! dev)
@@ -598,7 +596,7 @@
 	card = priv->card;
 
 	/* Link both structures together */
-	link = &card->link;
+	card->p_dev = link;
 	link->priv = dev;
 
 	/* Interrupt setup */
@@ -615,13 +613,7 @@
 	link->conf.Attributes = 0;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	spectrum_cs_config(link);
-
-	return 0;
+	return spectrum_cs_config(link);
 }				/* spectrum_cs_attach */
 
 /*
@@ -630,16 +622,14 @@
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void spectrum_cs_detach(struct pcmcia_device *p_dev)
+static void spectrum_cs_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	if (link->state & DEV_CONFIG)
-		spectrum_cs_release(link);
+	spectrum_cs_release(link);
 
-	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
-	if (link->dev) {
+	DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
+	if (link->dev_node) {
 		DEBUG(0, PFX "About to unregister net device %p\n",
 		      dev);
 		unregister_netdev(dev);
@@ -653,11 +643,10 @@
  * device available to the system.
  */
 
-static void
-spectrum_cs_config(dev_link_t *link)
+static int
+spectrum_cs_config(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
-	client_handle_t handle = link->handle;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	hermes_t *hw = &priv->hw;
@@ -669,7 +658,7 @@
 	cisparse_t parse;
 	void __iomem *mem;
 
-	CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+	CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
 
 	/*
 	 * This reads the card's CONFIG tuple to find its
@@ -680,19 +669,15 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	/* Look up the current Vcc */
 	CS_CHECK(GetConfigurationInfo,
-		 pcmcia_get_configuration_info(handle, &conf));
-	link->conf.Vcc = conf.Vcc;
+		 pcmcia_get_configuration_info(link, &conf));
 
 	/*
 	 * In this loop, we scan the CIS for configuration table
@@ -709,13 +694,13 @@
 	 * implementation-defined details.
 	 */
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 		cistpl_cftable_entry_t dflt = { .index = 0 };
 
-		if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
-		    || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+		if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
+		    || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
 			goto next_entry;
 
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -747,10 +732,10 @@
 		}
 
 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		
 		/* Do we need to allocate an interrupt? */
@@ -780,7 +765,7 @@
 			}
 
 			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(link->handle, &link->io) != 0)
+			if (pcmcia_request_io(link, &link->io) != 0)
 				goto next_entry;
 		}
 
@@ -790,9 +775,8 @@
 		break;
 		
 	next_entry:
-		if (link->io.NumPorts1)
-			pcmcia_release_io(link->handle, &link->io);
-		last_ret = pcmcia_get_next_tuple(handle, &tuple);
+		pcmcia_disable_device(link);
+		last_ret = pcmcia_get_next_tuple(link, &tuple);
 		if (last_ret  == CS_NO_MORE_ITEMS) {
 			printk(KERN_ERR PFX "GetNextTuple(): No matching "
 			       "CIS configuration.  Maybe you need the "
@@ -806,7 +790,7 @@
 	 * a handler to the interrupt, unless the 'Handler' member of
 	 * the irq structure is initialized.
 	 */
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
 	/* We initialize the hermes structure before completing PCMCIA
 	 * configuration just in case the interrupt handler gets
@@ -823,7 +807,7 @@
 	 * card and host interface into "Memory and IO" mode.
 	 */
 	CS_CHECK(RequestConfiguration,
-		 pcmcia_request_configuration(link->handle, &link->conf));
+		 pcmcia_request_configuration(link, &link->conf));
 
 	/* Ok, we have the configuration, prepare to register the netdev */
 	dev->base_addr = link->io.BasePort1;
@@ -836,7 +820,7 @@
 		goto failed;
 	}
 
-	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+	SET_NETDEV_DEV(dev, &handle_to_dev(link));
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
 		printk(KERN_ERR PFX "register_netdev() failed\n");
@@ -844,20 +828,18 @@
 	}
 
 	/* At this point, the dev_node_t structure(s) needs to be
-	 * initialized and arranged in a linked list at link->dev. */
+	 * initialized and arranged in a linked list at link->dev_node. */
 	strcpy(card->node.dev_name, dev->name);
-	link->dev = &card->node; /* link->dev being non-NULL is also
+	link->dev_node = &card->node; /* link->dev_node being non-NULL is also
                                     used to indicate that the
                                     net_device has been registered */
-	link->state &= ~DEV_CONFIG_PENDING;
 
 	/* Finally, report what we've done */
-	printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
-	       dev->name, link->conf.ConfigIndex,
-	       link->conf.Vcc / 10, link->conf.Vcc % 10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
-		       link->conf.Vpp1 % 10);
+	printk(KERN_DEBUG "%s: index 0x%02x: ",
+	       dev->name, link->conf.ConfigIndex);
+	if (link->conf.Vpp)
+		printk(", Vpp %d.%d", link->conf.Vpp / 10,
+		       link->conf.Vpp % 10);
 	printk(", irq %d", link->irq.AssignedIRQ);
 	if (link->io.NumPorts1)
 		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
@@ -867,13 +849,14 @@
 		       link->io.BasePort2 + link->io.NumPorts2 - 1);
 	printk("\n");
 
-	return;
+	return 0;
 
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 
  failed:
 	spectrum_cs_release(link);
+	return -ENODEV;
 }				/* spectrum_cs_config */
 
 /*
@@ -882,7 +865,7 @@
  * still open, this will be postponed until it is closed.
  */
 static void
-spectrum_cs_release(dev_link_t *link)
+spectrum_cs_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -894,64 +877,46 @@
 	priv->hw_unavailable++;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Don't bother checking to see if these succeed or not */
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 	if (priv->hw.iobase)
 		ioport_unmap(priv->hw.iobase);
 }				/* spectrum_cs_release */
 
 
 static int
-spectrum_cs_suspend(struct pcmcia_device *p_dev)
+spectrum_cs_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err = 0;
 
-	link->state |= DEV_SUSPEND;
 	/* Mark the device as stopped, to block IO until later */
-	if (link->state & DEV_CONFIG) {
-		spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 
-		err = __orinoco_down(dev);
-		if (err)
-			printk(KERN_WARNING "%s: Error %d downing interface\n",
-			       dev->name, err);
+	err = __orinoco_down(dev);
+	if (err)
+		printk(KERN_WARNING "%s: Error %d downing interface\n",
+		       dev->name, err);
 
-		netif_device_detach(dev);
-		priv->hw_unavailable++;
+	netif_device_detach(dev);
+	priv->hw_unavailable++;
 
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		pcmcia_release_configuration(link->handle);
-	}
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return 0;
 }
 
 static int
-spectrum_cs_resume(struct pcmcia_device *p_dev)
+spectrum_cs_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		/* FIXME: should we double check that this is
-		 * the same card as we had before */
-		pcmcia_request_configuration(link->handle, &link->conf);
-		netif_device_attach(dev);
-		priv->hw_unavailable--;
-		schedule_work(&priv->reset_work);
-	}
+	netif_device_attach(dev);
+	priv->hw_unavailable--;
+	schedule_work(&priv->reset_work);
+
 	return 0;
 }
 
@@ -979,7 +944,7 @@
 	.drv		= {
 		.name	= DRIVER_NAME,
 	},
-	.probe		= spectrum_cs_attach,
+	.probe		= spectrum_cs_probe,
 	.remove		= spectrum_cs_detach,
 	.suspend	= spectrum_cs_suspend,
 	.resume		= spectrum_cs_resume,
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 98122f3..f7724eb 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1005,7 +1005,7 @@
 wv_82593_reconfig(struct net_device *	dev)
 {
   net_local *		lp = netdev_priv(dev);
-  dev_link_t *		link = lp->link;
+  struct pcmcia_device *		link = lp->link;
   unsigned long		flags;
 
   /* Arm the flag, will be cleard in wv_82593_config() */
@@ -3744,16 +3744,16 @@
 {
   int		i;
   conf_reg_t	reg = { 0, CS_READ, CISREG_COR, 0 };
-  dev_link_t *	link = ((net_local *)netdev_priv(dev))->link;
+  struct pcmcia_device *	link = ((net_local *)netdev_priv(dev))->link;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name);
 #endif
 
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
       
@@ -3764,19 +3764,19 @@
 
   reg.Action = CS_WRITE;
   reg.Value = reg.Value | COR_SW_RESET;
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
       
   reg.Action = CS_WRITE;
   reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
-  i = pcmcia_access_configuration_register(link->handle, &reg);
+  i = pcmcia_access_configuration_register(link, &reg);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, AccessConfigurationRegister, i);
+      cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
     }
 
@@ -3940,9 +3940,8 @@
  * (called by wavelan_event())
  */
 static inline int
-wv_pcmcia_config(dev_link_t *	link)
+wv_pcmcia_config(struct pcmcia_device *	link)
 {
-  client_handle_t	handle = link->handle;
   tuple_t		tuple;
   cisparse_t		parse;
   struct net_device *	dev = (struct net_device *) link->priv;
@@ -3965,16 +3964,16 @@
     {
       tuple.Attributes = 0;
       tuple.DesiredTuple = CISTPL_CONFIG;
-      i = pcmcia_get_first_tuple(handle, &tuple);
+      i = pcmcia_get_first_tuple(link, &tuple);
       if(i != CS_SUCCESS)
 	break;
       tuple.TupleData = (cisdata_t *)buf;
       tuple.TupleDataMax = 64;
       tuple.TupleOffset = 0;
-      i = pcmcia_get_tuple_data(handle, &tuple);
+      i = pcmcia_get_tuple_data(link, &tuple);
       if(i != CS_SUCCESS)
 	break;
-      i = pcmcia_parse_tuple(handle, &tuple, &parse);
+      i = pcmcia_parse_tuple(link, &tuple, &parse);
       if(i != CS_SUCCESS)
 	break;
       link->conf.ConfigBase = parse.config.base;
@@ -3983,19 +3982,16 @@
   while(0);
   if(i != CS_SUCCESS)
     {
-      cs_error(link->handle, ParseTuple, i);
-      link->state &= ~DEV_CONFIG_PENDING;
+      cs_error(link, ParseTuple, i);
       return FALSE;
     }
-    
-  /* Configure card */
-  link->state |= DEV_CONFIG;
+
   do
     {
-      i = pcmcia_request_io(link->handle, &link->io);
+      i = pcmcia_request_io(link, &link->io);
       if(i != CS_SUCCESS)
 	{
-	  cs_error(link->handle, RequestIO, i);
+	  cs_error(link, RequestIO, i);
 	  break;
 	}
 
@@ -4003,10 +3999,10 @@
        * Now allocate an interrupt line.  Note that this does not
        * actually assign a handler to the interrupt.
        */
-      i = pcmcia_request_irq(link->handle, &link->irq);
+      i = pcmcia_request_irq(link, &link->irq);
       if(i != CS_SUCCESS)
 	{
-	  cs_error(link->handle, RequestIRQ, i);
+	  cs_error(link, RequestIRQ, i);
 	  break;
 	}
 
@@ -4015,15 +4011,15 @@
        * the I/O windows and the interrupt mapping.
        */
       link->conf.ConfigIndex = 1;
-      i = pcmcia_request_configuration(link->handle, &link->conf);
+      i = pcmcia_request_configuration(link, &link->conf);
       if(i != CS_SUCCESS)
 	{
-	  cs_error(link->handle, RequestConfiguration, i);
+	  cs_error(link, RequestConfiguration, i);
 	  break;
 	}
 
       /*
-       * Allocate a small memory window.  Note that the dev_link_t
+       * Allocate a small memory window.  Note that the struct pcmcia_device
        * structure provides space for one window handle -- if your
        * device needs several windows, you'll need to keep track of
        * the handles in your private data structure, link->priv.
@@ -4031,10 +4027,10 @@
       req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
       req.Base = req.Size = 0;
       req.AccessSpeed = mem_speed;
-      i = pcmcia_request_window(&link->handle, &req, &link->win);
+      i = pcmcia_request_window(&link, &req, &link->win);
       if(i != CS_SUCCESS)
 	{
-	  cs_error(link->handle, RequestWindow, i);
+	  cs_error(link, RequestWindow, i);
 	  break;
 	}
 
@@ -4046,7 +4042,7 @@
       i = pcmcia_map_mem_page(link->win, &mem);
       if(i != CS_SUCCESS)
 	{
-	  cs_error(link->handle, MapMemPage, i);
+	  cs_error(link, MapMemPage, i);
 	  break;
 	}
 
@@ -4060,7 +4056,7 @@
 	     lp->mem, dev->irq, (u_int) dev->base_addr);
 #endif
 
-      SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+      SET_NETDEV_DEV(dev, &handle_to_dev(link));
       i = register_netdev(dev);
       if(i != 0)
 	{
@@ -4072,7 +4068,6 @@
     }
   while(0);		/* Humm... Disguised goto !!! */
 
-  link->state &= ~DEV_CONFIG_PENDING;
   /* If any step failed, release any partially configured state */
   if(i != 0)
     {
@@ -4081,7 +4076,7 @@
     }
 
   strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name);
-  link->dev = &((net_local *) netdev_priv(dev))->node;
+  link->dev_node = &((net_local *) netdev_priv(dev))->node;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "<-wv_pcmcia_config()\n");
@@ -4096,26 +4091,20 @@
  * still open, this will be postponed until it is closed.
  */
 static void
-wv_pcmcia_release(dev_link_t *link)
+wv_pcmcia_release(struct pcmcia_device *link)
 {
-  struct net_device *	dev = (struct net_device *) link->priv;
-  net_local *		lp = netdev_priv(dev);
+	struct net_device *	dev = (struct net_device *) link->priv;
+	net_local *		lp = netdev_priv(dev);
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
+	printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link);
 #endif
 
-  /* Don't bother checking to see if these succeed or not */
-  iounmap(lp->mem);
-  pcmcia_release_window(link->win);
-  pcmcia_release_configuration(link->handle);
-  pcmcia_release_io(link->handle, &link->io);
-  pcmcia_release_irq(link->handle, &link->irq);
-
-  link->state &= ~DEV_CONFIG;
+	iounmap(lp->mem);
+	pcmcia_disable_device(link);
 
 #ifdef DEBUG_CONFIG_TRACE
-  printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
+	printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name);
 #endif
 }
 
@@ -4479,7 +4468,7 @@
 wavelan_open(struct net_device *	dev)
 {
   net_local *	lp = netdev_priv(dev);
-  dev_link_t *	link = lp->link;
+  struct pcmcia_device *	link = lp->link;
   kio_addr_t	base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4533,7 +4522,7 @@
 static int
 wavelan_close(struct net_device *	dev)
 {
-  dev_link_t *	link = ((net_local *)netdev_priv(dev))->link;
+  struct pcmcia_device *	link = ((net_local *)netdev_priv(dev))->link;
   kio_addr_t	base = dev->base_addr;
 
 #ifdef DEBUG_CALLBACK_TRACE
@@ -4587,45 +4576,36 @@
  * card insertion event.
  */
 static int
-wavelan_attach(struct pcmcia_device *p_dev)
+wavelan_probe(struct pcmcia_device *p_dev)
 {
-  dev_link_t *	link;		/* Info for cardmgr */
   struct net_device *	dev;		/* Interface generic data */
   net_local *	lp;		/* Interface specific data */
+  int ret;
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_attach()\n");
 #endif
 
-  /* Initialize the dev_link_t structure */
-  link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-  if (!link) return -ENOMEM;
-
   /* The io structure describes IO port mapping */
-  link->io.NumPorts1 = 8;
-  link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-  link->io.IOAddrLines = 3;
+  p_dev->io.NumPorts1 = 8;
+  p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+  p_dev->io.IOAddrLines = 3;
 
   /* Interrupt setup */
-  link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-  link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-  link->irq.Handler = wavelan_interrupt;
+  p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+  p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
+  p_dev->irq.Handler = wavelan_interrupt;
 
   /* General socket configuration */
-  link->conf.Attributes = CONF_ENABLE_IRQ;
-  link->conf.Vcc = 50;
-  link->conf.IntType = INT_MEMORY_AND_IO;
-
-  /* Chain drivers */
-  link->next = NULL;
+  p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+  p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
   /* Allocate the generic data structure */
   dev = alloc_etherdev(sizeof(net_local));
-  if (!dev) {
-      kfree(link);
+  if (!dev)
       return -ENOMEM;
-  }
-  link->priv = link->irq.Instance = dev;
+
+  p_dev->priv = p_dev->irq.Instance = dev;
 
   lp = netdev_priv(dev);
 
@@ -4642,7 +4622,6 @@
   spin_lock_init(&lp->spinlock);
 
   /* back links */
-  lp->link = link;
   lp->dev = dev;
 
   /* wavelan NET3 callbacks */
@@ -4668,15 +4647,18 @@
   /* Other specific data */
   dev->mtu = WAVELAN_MTU;
 
-  link->handle = p_dev;
-  p_dev->instance = link;
+  ret = wv_pcmcia_config(p_dev);
+  if (ret)
+	  return ret;
 
-  link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-  if(wv_pcmcia_config(link) &&
-     wv_hw_config(dev))
-	  wv_init_info(dev);
-  else
+  ret = wv_hw_config(dev);
+  if (ret) {
 	  dev->irq = 0;
+	  pcmcia_disable_device(p_dev);
+	  return ret;
+  }
+
+  wv_init_info(dev);
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_attach()\n");
@@ -4693,25 +4675,14 @@
  * is released.
  */
 static void
-wavelan_detach(struct pcmcia_device *p_dev)
+wavelan_detach(struct pcmcia_device *link)
 {
-   dev_link_t *link = dev_to_instance(p_dev);
-
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
 #endif
 
-  /*
-   * If the device is currently configured and active, we won't
-   * actually delete it yet.  Instead, it is marked so that when the
-   * release() function is called, that will trigger a proper
-   * detach().
-   */
-  if(link->state & DEV_CONFIG)
-    {
-      /* Some others haven't done their job : give them another chance */
-      wv_pcmcia_release(link);
-    }
+  /* Some others haven't done their job : give them another chance */
+  wv_pcmcia_release(link);
 
   /* Free pieces */
   if(link->priv)
@@ -4720,23 +4691,21 @@
 
       /* Remove ourselves from the kernel list of ethernet devices */
       /* Warning : can't be called from interrupt, timer or wavelan_close() */
-      if (link->dev)
+      if (link->dev_node)
 	unregister_netdev(dev);
-      link->dev = NULL;
+      link->dev_node = NULL;
       ((net_local *)netdev_priv(dev))->link = NULL;
       ((net_local *)netdev_priv(dev))->dev = NULL;
       free_netdev(dev);
     }
-  kfree(link);
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_detach()\n");
 #endif
 }
 
-static int wavelan_suspend(struct pcmcia_device *p_dev)
+static int wavelan_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *	dev = (struct net_device *) link->priv;
 
 	/* NB: wavelan_close will be called, but too late, so we are
@@ -4748,36 +4717,22 @@
 	/* Stop receiving new messages and wait end of transmission */
 	wv_ru_stop(dev);
 
+	if (link->open)
+		netif_device_detach(dev);
+
 	/* Power down the module */
 	hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT));
 
-	/* The card is now suspended */
-	link->state |= DEV_SUSPEND;
-
-    	if(link->state & DEV_CONFIG)
-	{
-		if(link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
-
 	return 0;
 }
 
-static int wavelan_resume(struct pcmcia_device *p_dev)
+static int wavelan_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *	dev = (struct net_device *) link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if(link->state & DEV_CONFIG)
-	{
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if(link->open)	/* If RESET -> True, If RESUME -> False ? */
-		{
-			wv_hw_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		wv_hw_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -4798,7 +4753,7 @@
 	.drv		= {
 		.name	= "wavelan_cs",
 	},
-	.probe		= wavelan_attach,
+	.probe		= wavelan_probe,
 	.remove		= wavelan_detach,
 	.id_table       = wavelan_ids,
 	.suspend	= wavelan_suspend,
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 451f627..c65fe7a 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -602,7 +602,7 @@
   dev_node_t 	node;		/* ???? What is this stuff ???? */
   struct net_device *	dev;		/* Reverse link... */
   spinlock_t	spinlock;	/* Serialize access to the hardware (SMP) */
-  dev_link_t *	link;		/* pcmcia structure */
+  struct pcmcia_device *	link;		/* pcmcia structure */
   en_stats	stats;		/* Ethernet interface statistics */
   int		nresets;	/* Number of hw resets */
   u_char	configured;	/* If it is configured */
@@ -733,9 +733,9 @@
 static inline void
 	wv_hw_reset(struct net_device *);	/* Same, + start receiver unit */
 static inline int
-	wv_pcmcia_config(dev_link_t *);	/* Configure the pcmcia interface */
+	wv_pcmcia_config(struct pcmcia_device *);	/* Configure the pcmcia interface */
 static void
-	wv_pcmcia_release(dev_link_t *);/* Remove a device */
+	wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
 static irqreturn_t
 	wavelan_interrupt(int,	/* Interrupt handler */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 4303c50..65ceb08 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -611,5 +611,6 @@
 	struct iw_spy_data		spy_data;
 	struct iw_public_data		wireless_data;
 	struct dev_node_t		node;
+	struct pcmcia_device		*p_dev;
 };
 #endif
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 48e10b0..e52a650 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -103,8 +103,8 @@
  * release a socket, in response to card insertion and ejection events.  They
  * are invoked from the wl24 event handler.
  */
-static void wl3501_config(dev_link_t *link);
-static void wl3501_release(dev_link_t *link);
+static int wl3501_config(struct pcmcia_device *link);
+static void wl3501_release(struct pcmcia_device *link);
 
 /*
  * The dev_info variable is the "key" that is used to match up this
@@ -226,17 +226,6 @@
 	iw_set_mgmt_info_element(from->id, to, from->data, from->len);
 }
 
-/*
- * A linked list of "instances" of the wl24 device.  Each actual PCMCIA card
- * corresponds to one device instance, and is described by one dev_link_t
- * structure (defined in ds.h).
- *
- * You may not want to use a linked list for this -- for example, the memory
- * card driver uses an array of dev_link_t pointers, where minor device numbers
- * are used to derive the corresponding array index.
- */
-static dev_link_t *wl3501_dev_list;
-
 static inline void wl3501_switch_page(struct wl3501_card *this, u8 page)
 {
 	wl3501_outb(page, this->base_addr + WL3501_NIC_BSS);
@@ -1281,15 +1270,10 @@
 	struct wl3501_card *this = dev->priv;
 	int rc = -ENODEV;
 	unsigned long flags;
-	dev_link_t *link;
+	struct pcmcia_device *link;
+	link = this->p_dev;
 
 	spin_lock_irqsave(&this->lock, flags);
-	/* Check if the device is in wl3501_dev_list */
-	for (link = wl3501_dev_list; link; link = link->next)
-		if (link->priv == dev)
-			break;
-	if (!link)
-		goto out;
 	link->open--;
 
 	/* Stop wl3501_hard_start_xmit() from now on */
@@ -1301,7 +1285,6 @@
 
 	rc = 0;
 	printk(KERN_INFO "%s: WL3501 closed\n", dev->name);
-out:
 	spin_unlock_irqrestore(&this->lock, flags);
 	return rc;
 }
@@ -1400,14 +1383,11 @@
 	int rc = -ENODEV;
 	struct wl3501_card *this = dev->priv;
 	unsigned long flags;
-	dev_link_t *link;
+	struct pcmcia_device *link;
+	link = this->p_dev;
 
 	spin_lock_irqsave(&this->lock, flags);
-	/* Check if the device is in wl3501_dev_list */
-	for (link = wl3501_dev_list; link; link = link->next)
-		if (link->priv == dev)
-			break;
-	if (!DEV_OK(link))
+	if (!pcmcia_dev_present(link))
 		goto out;
 	netif_device_attach(dev);
 	link->open++;
@@ -1497,38 +1477,23 @@
  * Services. If it has been released, all local data structures are freed.
  * Otherwise, the structures will be freed when the device is released.
  */
-static void wl3501_detach(struct pcmcia_device *p_dev)
+static void wl3501_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-	dev_link_t **linkp;
 	struct net_device *dev = link->priv;
 
-	/* Locate device structure */
-	for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
-		if (*linkp == link)
-			break;
-	if (!*linkp)
-		goto out;
-
 	/* If the device is currently configured and active, we won't actually
 	 * delete it yet.  Instead, it is marked so that when the release()
 	 * function is called, that will trigger a proper detach(). */
 
-	if (link->state & DEV_CONFIG) {
-		while (link->open > 0)
-			wl3501_close(dev);
+	while (link->open > 0)
+		wl3501_close(dev);
 
-		netif_device_detach(dev);
-		wl3501_release(link);
-	}
-
-	/* Unlink device structure, free pieces */
-	*linkp = link->next;
+	netif_device_detach(dev);
+	wl3501_release(link);
 
 	if (link->priv)
 		free_netdev(link->priv);
-	kfree(link);
-out:
+
 	return;
 }
 
@@ -1953,33 +1918,26 @@
  * The dev_link structure is initialized, but we don't actually configure the
  * card at this point -- we wait until we receive a card insertion event.
  */
-static int wl3501_attach(struct pcmcia_device *p_dev)
+static int wl3501_probe(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
 	struct net_device *dev;
 	struct wl3501_card *this;
 
-	/* Initialize the dev_link_t structure */
-	link = kzalloc(sizeof(*link), GFP_KERNEL);
-	if (!link)
-		return -ENOMEM;
-
 	/* The io structure describes IO port mapping */
-	link->io.NumPorts1	= 16;
-	link->io.Attributes1	= IO_DATA_PATH_WIDTH_8;
-	link->io.IOAddrLines	= 5;
+	p_dev->io.NumPorts1	= 16;
+	p_dev->io.Attributes1	= IO_DATA_PATH_WIDTH_8;
+	p_dev->io.IOAddrLines	= 5;
 
 	/* Interrupt setup */
-	link->irq.Attributes	= IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-	link->irq.IRQInfo1	= IRQ_LEVEL_ID;
-	link->irq.Handler = wl3501_interrupt;
+	p_dev->irq.Attributes	= IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+	p_dev->irq.IRQInfo1	= IRQ_LEVEL_ID;
+	p_dev->irq.Handler = wl3501_interrupt;
 
 	/* General socket configuration */
-	link->conf.Attributes	= CONF_ENABLE_IRQ;
-	link->conf.Vcc		= 50;
-	link->conf.IntType	= INT_MEMORY_AND_IO;
-	link->conf.ConfigIndex	= 1;
-	link->conf.Present	= PRESENT_OPTION;
+	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
+	p_dev->conf.IntType	= INT_MEMORY_AND_IO;
+	p_dev->conf.ConfigIndex	= 1;
+	p_dev->conf.Present	= PRESENT_OPTION;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
 	if (!dev)
@@ -1992,22 +1950,15 @@
 	dev->get_stats		= wl3501_get_stats;
 	this = dev->priv;
 	this->wireless_data.spy_data = &this->spy_data;
+	this->p_dev = p_dev;
 	dev->wireless_data	= &this->wireless_data;
 	dev->wireless_handlers	= (struct iw_handler_def *)&wl3501_handler_def;
 	SET_ETHTOOL_OPS(dev, &ops);
 	netif_stop_queue(dev);
-	link->priv = link->irq.Instance = dev;
+	p_dev->priv = p_dev->irq.Instance = dev;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	wl3501_config(link);
-
-	return 0;
+	return wl3501_config(p_dev);
 out_link:
-	kfree(link);
-	link = NULL;
 	return -ENOMEM;
 }
 
@@ -2022,11 +1973,10 @@
  * received, to configure the PCMCIA socket, and to make the ethernet device
  * available to the system.
  */
-static void wl3501_config(dev_link_t *link)
+static int wl3501_config(struct pcmcia_device *link)
 {
 	tuple_t tuple;
 	cisparse_t parse;
-	client_handle_t handle = link->handle;
 	struct net_device *dev = link->priv;
 	int i = 0, j, last_fn, last_ret;
 	unsigned char bf[64];
@@ -2035,18 +1985,15 @@
 	/* This reads the card's CONFIG tuple to find its config registers. */
 	tuple.Attributes	= 0;
 	tuple.DesiredTuple	= CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	tuple.TupleData		= bf;
 	tuple.TupleDataMax	= sizeof(bf);
 	tuple.TupleOffset	= 0;
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase	= parse.config.base;
 	link->conf.Present	= parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	/* Try allocating IO ports.  This tries a few fixed addresses.  If you
 	 * want, you can also read the card's config table to pick addresses --
 	 * see the serial driver for an example. */
@@ -2056,28 +2003,28 @@
 		 * 0x200-0x2ff, and so on, because this seems safer */
 		link->io.BasePort1 = j;
 		link->io.BasePort2 = link->io.BasePort1 + 0x10;
-		i = pcmcia_request_io(link->handle, &link->io);
+		i = pcmcia_request_io(link, &link->io);
 		if (i == CS_SUCCESS)
 			break;
 	}
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		goto failed;
 	}
 
 	/* Now allocate an interrupt line. Note that this does not actually
 	 * assign a handler to the interrupt. */
 
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 
 	/* This actually configures the PCMCIA socket -- setting up the I/O
 	 * windows and the interrupt mapping.  */
 
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	dev->irq = link->irq.AssignedIRQ;
 	dev->base_addr = link->io.BasePort1;
-	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+	SET_NETDEV_DEV(dev, &handle_to_dev(link));
 	if (register_netdev(dev)) {
 		printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
 		goto failed;
@@ -2088,10 +2035,9 @@
 	this = dev->priv;
 	/*
 	 * At this point, the dev_node_t structure(s) should be initialized and
-	 * arranged in a linked list at link->dev.
+	 * arranged in a linked list at link->dev_node.
 	 */
-	link->dev = &this->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &this->node;
 
 	this->base_addr = dev->base_addr;
 
@@ -2127,13 +2073,13 @@
 	spin_lock_init(&this->lock);
 	init_waitqueue_head(&this->wait);
 	netif_start_queue(dev);
-	goto out;
+	return 0;
+
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 failed:
 	wl3501_release(link);
-out:
-	return;
+	return -ENODEV;
 }
 
 /**
@@ -2144,52 +2090,36 @@
  * and release the PCMCIA configuration.  If the device is still open, this
  * will be postponed until it is closed.
  */
-static void wl3501_release(dev_link_t *link)
+static void wl3501_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
 
 	/* Unlink the device chain */
-	if (link->dev) {
+	if (link->dev_node)
 		unregister_netdev(dev);
-		link->dev = NULL;
-	}
 
-	/* Don't bother checking to see if these succeed or not */
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int wl3501_suspend(struct pcmcia_device *p_dev)
+static int wl3501_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
-	link->state |= DEV_SUSPEND;
-
 	wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
-	if (link->state & DEV_CONFIG) {
-		if (link->open)
-			netif_device_detach(dev);
-		pcmcia_release_configuration(link->handle);
-	}
+	if (link->open)
+		netif_device_detach(dev);
 
 	return 0;
 }
 
-static int wl3501_resume(struct pcmcia_device *p_dev)
+static int wl3501_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct net_device *dev = link->priv;
 
 	wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if (link->open) {
-			wl3501_reset(dev);
-			netif_device_attach(dev);
-		}
+	if (link->open) {
+		wl3501_reset(dev);
+		netif_device_attach(dev);
 	}
 
 	return 0;
@@ -2207,7 +2137,7 @@
 	.drv		= {
 		.name	= "wl3501_cs",
 	},
-	.probe		= wl3501_attach,
+	.probe		= wl3501_probe,
 	.remove		= wl3501_detach,
 	.id_table	= wl3501_ids,
 	.suspend	= wl3501_suspend,
@@ -2221,9 +2151,7 @@
 
 static void __exit wl3501_exit_module(void)
 {
-	dprintk(0, ": unloading");
 	pcmcia_unregister_driver(&wl3501_driver);
-	BUG_ON(wl3501_dev_list != NULL);
 }
 
 module_init(wl3501_init_module);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 75d56bf..fd0f43b 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1441,8 +1441,7 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct yellowfin_private *np;
 
-	if (!dev)
-		BUG();
+	BUG_ON(!dev);
 	np = netdev_priv(dev);
 
         pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 4e53be9..bbeabe3 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -535,7 +535,7 @@
 {
 	char *out = buf;
 	struct pdcspath_entry *pathentry;
-	
+
 	if (!entry || !buf)
 		return -EINVAL;
 
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 42b32ff..278f325 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -178,6 +178,11 @@
 #define ROPE6_CTL	0x230
 #define ROPE7_CTL	0x238
 
+#define IOC_ROPE0_CFG	0x500	/* pluto only */
+#define   IOC_ROPE_AO	  0x10	/* Allow "Relaxed Ordering" */
+
+
+
 #define HF_ENABLE	0x40
 
 
@@ -1759,19 +1764,33 @@
 
 	sba_dev->num_ioc = num_ioc;
 	for (i = 0; i < num_ioc; i++) {
-		/*
-		** Make sure the box crashes if we get any errors on a rope.
-		*/
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
-		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+		unsigned long ioc_hpa = sba_dev->ioc[i].ioc_hpa;
+		unsigned int j;
 
-		/* flush out the writes */
+		for (j=0; j < sizeof(u64) * ROPES_PER_IOC; j+=sizeof(u64)) {
+
+			/*
+			 * Clear ROPE(N)_CONFIG AO bit.
+			 * Disables "NT Ordering" (~= !"Relaxed Ordering")
+			 * Overrides bit 1 in DMA Hint Sets.
+			 * Improves netperf UDP_STREAM by ~10% for bcm5701.
+			 */
+			if (IS_PLUTO(sba_dev->iodc)) {
+				unsigned long rope_cfg, cfg_val;
+
+				rope_cfg = ioc_hpa + IOC_ROPE0_CFG + j;
+				cfg_val = READ_REG(rope_cfg);
+				cfg_val &= ~IOC_ROPE_AO;
+				WRITE_REG(cfg_val, rope_cfg);
+			}
+
+			/*
+			** Make sure the box crashes on rope errors.
+			*/
+			WRITE_REG(HF_ENABLE, ioc_hpa + ROPE0_CTL + j);
+		}
+
+		/* flush out the last writes */
 		READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
 		DBG_INIT("	ioc[%d] ROPE_CFG 0x%Lx  ROPE_DBG 0x%Lx\n",
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 719b863..828eb45 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -155,7 +155,7 @@
 	struct pci_dev *pdev = sio->lio_pdev;
 	u16 word;
 
-        if (sio->suckyio_irq_enabled)                                       
+	if (sio->suckyio_irq_enabled)
 		return;
 
 	BUG_ON(!pdev);
@@ -194,7 +194,7 @@
 	request_region (sio->acpi_base, 0x1f, "acpi");
 
 	/* Enable the legacy I/O function */
-        pci_read_config_word (pdev, PCI_COMMAND, &word);
+	pci_read_config_word (pdev, PCI_COMMAND, &word);
 	word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
 	pci_write_config_word (pdev, PCI_COMMAND, word);
 
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 158d925..b953d59 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -81,15 +81,15 @@
 #define FORCE_EPP_MODE	0x08
 
 typedef struct parport_info_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     int			ndev;
     dev_node_t		node;
     struct parport	*port;
 } parport_info_t;
 
 static void parport_detach(struct pcmcia_device *p_dev);
-static void parport_config(dev_link_t *link);
-static void parport_cs_release(dev_link_t *);
+static int parport_config(struct pcmcia_device *link);
+static void parport_cs_release(struct pcmcia_device *);
 
 /*======================================================================
 
@@ -99,10 +99,9 @@
 
 ======================================================================*/
 
-static int parport_attach(struct pcmcia_device *p_dev)
+static int parport_probe(struct pcmcia_device *link)
 {
     parport_info_t *info;
-    dev_link_t *link;
 
     DEBUG(0, "parport_attach()\n");
 
@@ -110,23 +109,17 @@
     info = kmalloc(sizeof(*info), GFP_KERNEL);
     if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
+    link->priv = info;
+    info->p_dev = link;
 
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    parport_config(link);
-
-    return 0;
+    return parport_config(link);
 } /* parport_attach */
 
 /*======================================================================
@@ -138,14 +131,11 @@
 
 ======================================================================*/
 
-static void parport_detach(struct pcmcia_device *p_dev)
+static void parport_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-
     DEBUG(0, "parport_detach(0x%p)\n", link);
 
-    if (link->state & DEV_CONFIG)
-	parport_cs_release(link);
+    parport_cs_release(link);
 
     kfree(link->priv);
 } /* parport_detach */
@@ -161,14 +151,12 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-void parport_config(dev_link_t *link)
+static int parport_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     parport_info_t *info = link->priv;
     tuple_t tuple;
     u_short buf[128];
     cisparse_t parse;
-    config_info_t conf;
     cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
     cistpl_cftable_entry_t dflt = { 0 };
     struct parport *p;
@@ -180,24 +168,18 @@
     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present = parse.config.rmask[0];
-    
-    /* Configure card */
-    link->state |= DEV_CONFIG;
 
-    /* Not sure if this is right... look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-    
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 	    goto next_entry;
 
 	if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
@@ -212,7 +194,7 @@
 		link->io.BasePort2 = io->win[1].base;
 		link->io.NumPorts2 = io->win[1].len;
 	    }
-	    if (pcmcia_request_io(link->handle, &link->io) != 0)
+	    if (pcmcia_request_io(link, &link->io) != 0)
 		goto next_entry;
 	    /* If we've got this far, we're done */
 	    break;
@@ -220,15 +202,12 @@
 	
     next_entry:
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
     
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
-    release_region(link->io.BasePort1, link->io.NumPorts1);
-    if (link->io.NumPorts2)
-	release_region(link->io.BasePort2, link->io.NumPorts2);
     p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
 			      link->irq.AssignedIRQ, PARPORT_DMA_NONE,
 			      NULL);
@@ -247,17 +226,15 @@
     info->node.minor = p->number;
     info->port = p;
     strcpy(info->node.dev_name, p->name);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
 
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
 failed:
     parport_cs_release(link);
-    link->state &= ~DEV_CONFIG_PENDING;
-
+    return -ENODEV;
 } /* parport_config */
 
 /*======================================================================
@@ -268,53 +245,21 @@
     
 ======================================================================*/
 
-void parport_cs_release(dev_link_t *link)
+void parport_cs_release(struct pcmcia_device *link)
 {
-    parport_info_t *info = link->priv;
-    
-    DEBUG(0, "parport_release(0x%p)\n", link);
+	parport_info_t *info = link->priv;
 
-    if (info->ndev) {
-	struct parport *p = info->port;
-	parport_pc_unregister_port(p);
-	request_region(link->io.BasePort1, link->io.NumPorts1,
-		       info->node.dev_name);
-	if (link->io.NumPorts2)
-	    request_region(link->io.BasePort2, link->io.NumPorts2,
-			   info->node.dev_name);
-    }
-    info->ndev = 0;
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-    
-    link->state &= ~DEV_CONFIG;
+	DEBUG(0, "parport_release(0x%p)\n", link);
 
+	if (info->ndev) {
+		struct parport *p = info->port;
+		parport_pc_unregister_port(p);
+	}
+	info->ndev = 0;
+
+	pcmcia_disable_device(link);
 } /* parport_cs_release */
 
-static int parport_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int parport_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
 
 static struct pcmcia_device_id parport_ids[] = {
 	PCMCIA_DEVICE_FUNC_ID(3),
@@ -328,11 +273,9 @@
 	.drv		= {
 		.name	= "parport_cs",
 	},
-	.probe		= parport_attach,
+	.probe		= parport_probe,
 	.remove		= parport_detach,
 	.id_table	= parport_ids,
-	.suspend	= parport_suspend,
-	.resume		= parport_resume,
 };
 
 static int __init init_parport_cs(void)
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index d589002..48bbf32 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -97,7 +97,7 @@
 	int io;
 	int irq;
 	int dma;
-} superios[NR_SUPERIOS] __devinitdata = { {0,},};
+} superios[NR_SUPERIOS] = { {0,},};
 
 static int user_specified;
 #if defined(CONFIG_PARPORT_PC_SUPERIO) || \
@@ -1557,7 +1557,7 @@
 	return PARPORT_DMA_NONE;
 }
 
-static int __devinit get_superio_irq (struct parport *p)
+static int get_superio_irq (struct parport *p)
 {
 	int i=0;
         while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -1579,7 +1579,7 @@
  *                         this shall always be the case!)
  *
  */
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
 {
 	unsigned char r, w;
 
@@ -1660,7 +1660,7 @@
  * two bits of ECR aren't writable, so we check by writing ECR and
  * reading it back to see if it's what we expect.
  */
-static int __devinit parport_ECR_present(struct parport *pb)
+static int parport_ECR_present(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 	unsigned char r = 0xc;
@@ -1712,7 +1712,7 @@
  * be misdetected here is rather academic. 
  */
 
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
 {
 	int ok = 0;
   
@@ -1868,7 +1868,7 @@
 }
 #endif
 
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
 {
 	const struct parport_pc_private *priv = pb->private_data;
 	int result;
@@ -1886,7 +1886,7 @@
 
 /* EPP mode detection  */
 
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
 {
 	const struct parport_pc_private *priv = pb->private_data;
 
@@ -1931,7 +1931,7 @@
 	return 1;
 }
 
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 	int result;
@@ -2073,7 +2073,7 @@
  * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
-static int __devinit parport_irq_probe(struct parport *pb)
+static int parport_irq_probe(struct parport *pb)
 {
 	struct parport_pc_private *priv = pb->private_data;
 
@@ -2779,7 +2779,7 @@
 	/* If set, this is called after probing for ports.  If 'failed'
 	 * is non-zero we couldn't use any of the ports. */
 	void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+} cards[] = {
 	/* siig_1p_10x */		{ 1, { { 2, 3 }, } },
 	/* siig_2p_10x */		{ 2, { { 2, 3 }, { 4, 5 }, } },
 	/* siig_1p_20x */		{ 1, { { 0, 1 }, } },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d121644..98b83a8 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -100,8 +100,6 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
-	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 6e79f56..6380045 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -360,9 +360,6 @@
 	while ((dn = of_find_node_by_type(dn, "pci")))
 		rpaphp_add_slot(dn);
 
-	if (!num_slots)
-		return -ENODEV;
-
 	return 0;
 }
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a77e79c..9855c4c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -504,6 +504,201 @@
 		nr_reserved_vectors++;
 }
 
+#ifdef CONFIG_PM
+int pci_save_msi_state(struct pci_dev *dev)
+{
+	int pos, i = 0;
+	u16 control;
+	struct pci_cap_saved_state *save_state;
+	u32 *cap;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (pos <= 0 || dev->no_msi)
+		return 0;
+
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+	if (!(control & PCI_MSI_FLAGS_ENABLE))
+		return 0;
+
+	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
+		GFP_KERNEL);
+	if (!save_state) {
+		printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
+		return -ENOMEM;
+	}
+	cap = &save_state->data[0];
+
+	pci_read_config_dword(dev, pos, &cap[i++]);
+	control = cap[0] >> 16;
+	pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
+	if (control & PCI_MSI_FLAGS_64BIT) {
+		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
+		pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
+	} else
+		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
+	if (control & PCI_MSI_FLAGS_MASKBIT)
+		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
+	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+	save_state->cap_nr = PCI_CAP_ID_MSI;
+	pci_add_saved_cap(dev, save_state);
+	return 0;
+}
+
+void pci_restore_msi_state(struct pci_dev *dev)
+{
+	int i = 0, pos;
+	u16 control;
+	struct pci_cap_saved_state *save_state;
+	u32 *cap;
+
+	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!save_state || pos <= 0)
+		return;
+	cap = &save_state->data[0];
+
+	control = cap[i++] >> 16;
+	pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
+	if (control & PCI_MSI_FLAGS_64BIT) {
+		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
+		pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
+	} else
+		pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
+	if (control & PCI_MSI_FLAGS_MASKBIT)
+		pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
+	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+	pci_remove_saved_cap(save_state);
+	kfree(save_state);
+}
+
+int pci_save_msix_state(struct pci_dev *dev)
+{
+	int pos;
+	u16 control;
+	struct pci_cap_saved_state *save_state;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos <= 0 || dev->no_msi)
+		return 0;
+
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+	if (!(control & PCI_MSIX_FLAGS_ENABLE))
+		return 0;
+	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
+		GFP_KERNEL);
+	if (!save_state) {
+		printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
+		return -ENOMEM;
+	}
+	*((u16 *)&save_state->data[0]) = control;
+
+	disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+	save_state->cap_nr = PCI_CAP_ID_MSIX;
+	pci_add_saved_cap(dev, save_state);
+	return 0;
+}
+
+void pci_restore_msix_state(struct pci_dev *dev)
+{
+	u16 save;
+	int pos;
+	int vector, head, tail = 0;
+	void __iomem *base;
+	int j;
+	struct msg_address address;
+	struct msg_data data;
+	struct msi_desc *entry;
+	int temp;
+	struct pci_cap_saved_state *save_state;
+
+	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
+	if (!save_state)
+		return;
+	save = *((u16 *)&save_state->data[0]);
+	pci_remove_saved_cap(save_state);
+	kfree(save_state);
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos <= 0)
+		return;
+
+	/* route the table */
+	temp = dev->irq;
+	if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX))
+		return;
+	vector = head = dev->irq;
+	while (head != tail) {
+		entry = msi_desc[vector];
+		base = entry->mask_base;
+		j = entry->msi_attrib.entry_nr;
+
+		msi_address_init(&address);
+		msi_data_init(&data, vector);
+
+		address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
+		address.lo_address.value |= entry->msi_attrib.current_cpu <<
+					MSI_TARGET_CPU_SHIFT;
+
+		writel(address.lo_address.value,
+			base + j * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+		writel(address.hi_address,
+			base + j * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+		writel(*(u32*)&data,
+			base + j * PCI_MSIX_ENTRY_SIZE +
+			PCI_MSIX_ENTRY_DATA_OFFSET);
+
+		tail = msi_desc[vector]->link.tail;
+		vector = tail;
+	}
+	dev->irq = temp;
+
+	pci_write_config_word(dev, msi_control_reg(pos), save);
+	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+}
+#endif
+
+static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
+{
+	struct msg_address address;
+	struct msg_data data;
+	int pos, vector = dev->irq;
+	u16 control;
+
+   	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+	/* Configure MSI capability structure */
+	msi_address_init(&address);
+	msi_data_init(&data, vector);
+	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
+				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
+	pci_write_config_dword(dev, msi_lower_address_reg(pos),
+			address.lo_address.value);
+	if (is_64bit_address(control)) {
+		pci_write_config_dword(dev,
+			msi_upper_address_reg(pos), address.hi_address);
+		pci_write_config_word(dev,
+			msi_data_reg(pos, 1), *((u32*)&data));
+	} else
+		pci_write_config_word(dev,
+			msi_data_reg(pos, 0), *((u32*)&data));
+	if (entry->msi_attrib.maskbit) {
+		unsigned int maskbits, temp;
+		/* All MSIs are unmasked by default, Mask them all */
+		pci_read_config_dword(dev,
+			msi_mask_bits_reg(pos, is_64bit_address(control)),
+			&maskbits);
+		temp = (1 << multi_msi_capable(control));
+		temp = ((temp - 1) & ~temp);
+		maskbits |= temp;
+		pci_write_config_dword(dev,
+			msi_mask_bits_reg(pos, is_64bit_address(control)),
+			maskbits);
+	}
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -516,8 +711,6 @@
 static int msi_capability_init(struct pci_dev *dev)
 {
 	struct msi_desc *entry;
-	struct msg_address address;
-	struct msg_data data;
 	int pos, vector;
 	u16 control;
 
@@ -549,33 +742,8 @@
 	/* Replace with MSI handler */
 	irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
 	/* Configure MSI capability structure */
-	msi_address_init(&address);
-	msi_data_init(&data, vector);
-	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
-				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
-	pci_write_config_dword(dev, msi_lower_address_reg(pos),
-			address.lo_address.value);
-	if (is_64bit_address(control)) {
-		pci_write_config_dword(dev,
-			msi_upper_address_reg(pos), address.hi_address);
-		pci_write_config_word(dev,
-			msi_data_reg(pos, 1), *((u32*)&data));
-	} else
-		pci_write_config_word(dev,
-			msi_data_reg(pos, 0), *((u32*)&data));
-	if (entry->msi_attrib.maskbit) {
-		unsigned int maskbits, temp;
-		/* All MSIs are unmasked by default, Mask them all */
-		pci_read_config_dword(dev,
-			msi_mask_bits_reg(pos, is_64bit_address(control)),
-			&maskbits);
-		temp = (1 << multi_msi_capable(control));
-		temp = ((temp - 1) & ~temp);
-		maskbits |= temp;
-		pci_write_config_dword(dev,
-			msi_mask_bits_reg(pos, is_64bit_address(control)),
-			maskbits);
-	}
+	msi_register_init(dev, entry);
+
 	attach_msi_entry(entry, vector);
 	/* Set MSI enabled bits	 */
 	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
@@ -625,8 +793,10 @@
 		if (!entry)
 			break;
 		vector = get_msi_vector(dev);
-		if (vector < 0)
+		if (vector < 0) {
+			kmem_cache_free(msi_cachep, entry);
 			break;
+		}
 
  		j = entries[i].entry;
  		entries[i].vector = vector;
@@ -731,6 +901,7 @@
 			vector_irq[dev->irq] = -1;
 			nr_released_vectors--;
 			spin_unlock_irqrestore(&msi_lock, flags);
+			msi_register_init(dev, msi_desc[dev->irq]);
 			enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
 			return 0;
 		}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f22f69a..1456759 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -271,10 +271,12 @@
 	struct pci_driver * drv = pci_dev->driver;
 	int i = 0;
 
-	if (drv && drv->suspend)
+	if (drv && drv->suspend) {
 		i = drv->suspend(pci_dev, state);
-	else
+		suspend_report_result(drv->suspend, i);
+	} else {
 		pci_save_state(pci_dev);
+	}
 	return i;
 }
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bea1ad1..2329f94 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -307,9 +307,11 @@
 	 * Can enter D0 from any state, but if we can only go deeper 
 	 * to sleep if we're already in a low power state
 	 */
-	if (state != PCI_D0 && dev->current_state > state)
+	if (state != PCI_D0 && dev->current_state > state) {
+		printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n",
+			__FUNCTION__, pci_name(dev), state, dev->current_state);
 		return -EINVAL;
-	else if (dev->current_state == state) 
+	} else if (dev->current_state == state)
 		return 0;        /* we're already there */
 
 	/* find PCI PM capability in list */
@@ -444,6 +446,10 @@
 	/* XXX: 100% dword access ok here? */
 	for (i = 0; i < 16; i++)
 		pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+	if ((i = pci_save_msi_state(dev)) != 0)
+		return i;
+	if ((i = pci_save_msix_state(dev)) != 0)
+		return i;
 	return 0;
 }
 
@@ -458,6 +464,8 @@
 
 	for (i = 0; i < 16; i++)
 		pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
+	pci_restore_msi_state(dev);
+	pci_restore_msix_state(dev);
 	return 0;
 }
 
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8f3fb47..30630cb 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -55,6 +55,17 @@
 static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { }
 static inline void pci_no_msi(void) { }
 #endif
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
+int pci_save_msi_state(struct pci_dev *dev);
+int pci_save_msix_state(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
+void pci_restore_msix_state(struct pci_dev *dev);
+#else
+static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; }
+static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; }
+static inline void pci_restore_msi_state(struct pci_dev *dev) {}
+static inline void pci_restore_msix_state(struct pci_dev *dev) {}
+#endif
 
 extern int pcie_mch_quirk;
 extern struct device_attribute pci_dev_attrs[];
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 4970f47..19e2b17 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -592,7 +592,7 @@
                 pci_write_config_byte( dev, AMD8131_MISC, tmp);
         }
 } 
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,         quirk_amd_8131_ioapic ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
 
 static void __init quirk_svw_msi(struct pci_dev *dev)
 {
@@ -642,13 +642,15 @@
 	new_irq = dev->irq & 0xf;
 	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
 	if (new_irq != irq) {
-		printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
+		printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
 			pci_name(dev), irq, new_irq);
 		udelay(15);	/* unknown if delay really needed */
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
 
 /*
  * VIA VT82C598 has its device ID settable and many BIOSes
@@ -865,6 +867,35 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );
 
 /*
+ * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
+ * when a PCI-Soundcard is added. The BIOS only gives Options
+ * "Disabled" and "AUTO". This Quirk Sets the corresponding
+ * Register-Value to enable the Soundcard.
+ */
+static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+{
+	unsigned char val;
+
+	printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
+	pci_read_config_byte(dev, 0x50, &val);
+	if (val == 0x88 || val == 0xc8) {
+		pci_write_config_byte(dev, 0x50, val & (~0x40));
+
+		/* Verify the Change for Status output */
+		pci_read_config_byte(dev, 0x50, &val);
+		if (val & 0x40)
+			printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+		else
+			printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
+	} else {
+		printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
+					"no Change!\n");
+	}
+
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+
+/*
  * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
  * is not activated. The myth is that Asus said that they do not want the
  * users to be irritated by just another PCI Device in the Win98 device
@@ -921,6 +952,7 @@
 		if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) {
 			switch (dev->subsystem_device) {
 			case 0x1882: /* M6V notebook */
+			case 0x1977: /* A6VA notebook */
 				asus_hides_smbus = 1;
 			}
 		}
@@ -999,6 +1031,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc );
 
 static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
 {
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 1f4ad0e..61cb4b2 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -250,7 +250,7 @@
 
 config PCMCIA_VRC4171
 	tristate "NEC VRC4171 Card Controllers support"
-	depends on VRC4171 && PCMCIA
+	depends on CPU_VR41XX && ISA && PCMCIA
 
 config PCMCIA_VRC4173
 	tristate "NEC VRC4173 CARDU support"
@@ -263,6 +263,13 @@
 	  Say Y here to support the CompactFlash controller on OMAP.
 	  Note that this doesn't support "True IDE" mode.
 
+config AT91_CF
+	tristate "AT91 CompactFlash Controller"
+	depends on PCMCIA && ARCH_AT91RM9200
+	help
+	  Say Y here to support the CompactFlash controller on AT91 chips.
+	  Or choose M to compile the driver as a module named "at91_cf".
+
 config PCCARD_NONSTATIC
 	tristate
 
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index bcecf51..4276965 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,7 +10,7 @@
 pcmcia_core-$(CONFIG_CARDBUS)			+= cardbus.o
 obj-$(CONFIG_PCCARD)				+= pcmcia_core.o
 
-pcmcia-y					+= ds.o pcmcia_compat.o pcmcia_resource.o
+pcmcia-y					+= ds.o pcmcia_resource.o
 pcmcia-$(CONFIG_PCMCIA_IOCTL)			+= pcmcia_ioctl.o
 obj-$(CONFIG_PCMCIA)				+= pcmcia.o
 
@@ -36,6 +36,7 @@
 obj-$(CONFIG_PCMCIA_VRC4171)			+= vrc4171_card.o
 obj-$(CONFIG_PCMCIA_VRC4173)			+= vrc4173_cardu.o
 obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
+obj-$(CONFIG_AT91_CF)				+= at91_cf.o
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
new file mode 100644
index 0000000..a4d5094
--- /dev/null
+++ b/drivers/pcmcia/at91_cf.c
@@ -0,0 +1,376 @@
+/*
+ * at91_cf.c -- AT91 CompactFlash controller driver
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+/*
+ * A0..A10 work in each range; A23 indicates I/O space;  A25 is CFRNW;
+ * some other bit in {A24,A22..A11} is nREG to flag memory access
+ * (vs attributes).  So more than 2KB/region would just be waste.
+ */
+#define	CF_ATTR_PHYS	(AT91_CF_BASE)
+#define	CF_IO_PHYS	(AT91_CF_BASE  + (1 << 23))
+#define	CF_MEM_PHYS	(AT91_CF_BASE  + 0x017ff800)
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "at91_cf";
+
+struct at91_cf_socket {
+	struct pcmcia_socket	socket;
+
+	unsigned		present:1;
+
+	struct platform_device	*pdev;
+	struct at91_cf_data	*board;
+};
+
+#define	SZ_2K			(2 * SZ_1K)
+
+static inline int at91_cf_present(struct at91_cf_socket *cf)
+{
+	return !at91_get_gpio_value(cf->board->det_pin);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int at91_cf_ss_init(struct pcmcia_socket *s)
+{
+	return 0;
+}
+
+static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+	struct at91_cf_socket	*cf = (struct at91_cf_socket *) _cf;
+
+	if (irq == cf->board->det_pin) {
+		unsigned present = at91_cf_present(cf);
+
+		/* kick pccard as needed */
+		if (present != cf->present) {
+			cf->present = present;
+			pr_debug("%s: card %s\n", driver_name,
+					present ? "present" : "gone");
+			pcmcia_parse_events(&cf->socket, SS_DETECT);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+	struct at91_cf_socket	*cf;
+
+	if (!sp)
+		return -EINVAL;
+
+	cf = container_of(s, struct at91_cf_socket, socket);
+
+	/* NOTE: CF is always 3VCARD */
+	if (at91_cf_present(cf)) {
+		int rdy	= cf->board->irq_pin;	/* RDY/nIRQ */
+		int vcc	= cf->board->vcc_pin;
+
+		*sp = SS_DETECT | SS_3VCARD;
+		if (!rdy || at91_get_gpio_value(rdy))
+			*sp |= SS_READY;
+		if (!vcc || at91_get_gpio_value(vcc))
+			*sp |= SS_POWERON;
+	} else
+		*sp = 0;
+
+	return 0;
+}
+
+static int
+at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+	struct at91_cf_socket	*cf;
+
+	cf = container_of(sock, struct at91_cf_socket, socket);
+
+	/* switch Vcc if needed and possible */
+	if (cf->board->vcc_pin) {
+		switch (s->Vcc) {
+			case 0:
+				at91_set_gpio_value(cf->board->vcc_pin, 0);
+				break;
+			case 33:
+				at91_set_gpio_value(cf->board->vcc_pin, 1);
+				break;
+			default:
+				return -EINVAL;
+		}
+	}
+
+	/* toggle reset if needed */
+	at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET);
+
+	pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+		driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+	return 0;
+}
+
+static int at91_cf_ss_suspend(struct pcmcia_socket *s)
+{
+	return at91_cf_set_socket(s, &dead_socket);
+}
+
+/* we already mapped the I/O region */
+static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+	struct at91_cf_socket	*cf;
+	u32			csr;
+
+	cf = container_of(s, struct at91_cf_socket, socket);
+	io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ);
+
+	/*
+	 * Use 16 bit accesses unless/until we need 8-bit i/o space.
+	 * Always set CSR4 ... PCMCIA won't always unmap things.
+	 */
+	csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW;
+
+	/*
+	 * NOTE: this CF controller ignores IOIS16, so we can't really do
+	 * MAP_AUTOSZ.  The 16bit mode allows single byte access on either
+	 * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many
+	 * purposes (and handles ide-cs).
+	 *
+	 * The 8bit mode is needed for odd byte access on D0-D7.  It seems
+	 * some cards only like that way to get at the odd byte, despite
+	 * CF 3.0 spec table 35 also giving the D8-D15 option.
+	 */
+	if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
+		csr |= AT91_SMC_DBW_8;
+		pr_debug("%s: 8bit i/o bus\n", driver_name);
+	} else {
+		csr |= AT91_SMC_DBW_16;
+		pr_debug("%s: 16bit i/o bus\n", driver_name);
+	}
+	at91_sys_write(AT91_SMC_CSR(4), csr);
+
+	io->start = cf->socket.io_offset;
+	io->stop = io->start + SZ_2K - 1;
+
+	return 0;
+}
+
+/* pcmcia layer maps/unmaps mem regions */
+static int
+at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+	struct at91_cf_socket	*cf;
+
+	if (map->card_start)
+		return -EINVAL;
+
+	cf = container_of(s, struct at91_cf_socket, socket);
+
+	map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+	if (map->flags & MAP_ATTRIB)
+		map->static_start = CF_ATTR_PHYS;
+	else
+		map->static_start = CF_MEM_PHYS;
+
+	return 0;
+}
+
+static struct pccard_operations at91_cf_ops = {
+	.init			= at91_cf_ss_init,
+	.suspend		= at91_cf_ss_suspend,
+	.get_status		= at91_cf_get_status,
+	.set_socket		= at91_cf_set_socket,
+	.set_io_map		= at91_cf_set_io_map,
+	.set_mem_map		= at91_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_probe(struct device *dev)
+{
+	struct at91_cf_socket	*cf;
+	struct at91_cf_data	*board = dev->platform_data;
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct resource		*io;
+	unsigned int		csa;
+	int			status;
+
+	if (!board || !board->det_pin || !board->rst_pin)
+		return -ENODEV;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io)
+		return -ENODEV;
+
+	cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+	if (!cf)
+		return -ENOMEM;
+
+	cf->board = board;
+	cf->pdev = pdev;
+	dev_set_drvdata(dev, cf);
+
+	/* CF takes over CS4, CS5, CS6 */
+	csa = at91_sys_read(AT91_EBI_CSA);
+	at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
+
+	/* force poweron defaults for these pins ... */
+	(void) at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
+	(void) at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
+	(void) at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
+	(void) at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
+
+	/* nWAIT is _not_ a default setting */
+	(void) at91_set_A_periph(AT91_PIN_PC6, 1);	/*  nWAIT */
+
+	/*
+	 * Static memory controller timing adjustments.
+	 * REVISIT:  these timings are in terms of MCK cycles, so
+	 * when MCK changes (cpufreq etc) so must these values...
+	 */
+	at91_sys_write(AT91_SMC_CSR(4),
+				  AT91_SMC_ACSS_STD
+				| AT91_SMC_DBW_16
+				| AT91_SMC_BAT
+				| AT91_SMC_WSEN
+				| AT91_SMC_NWS_(32)	/* wait states */
+				| AT91_SMC_RWSETUP_(6)	/* setup time */
+				| AT91_SMC_RWHOLD_(4)	/* hold time */
+	);
+
+	/* must be a GPIO; ergo must trigger on both edges */
+	status = request_irq(board->det_pin, at91_cf_irq,
+			SA_SAMPLE_RANDOM, driver_name, cf);
+	if (status < 0)
+		goto fail0;
+
+	/*
+	 * The card driver will request this irq later as needed.
+	 * but it causes lots of "irqNN: nobody cared" messages
+	 * unless we report that we handle everything (sigh).
+	 * (Note:  DK board doesn't wire the IRQ pin...)
+	 */
+	if (board->irq_pin) {
+		status = request_irq(board->irq_pin, at91_cf_irq,
+				SA_SHIRQ, driver_name, cf);
+		if (status < 0)
+			goto fail0a;
+		cf->socket.pci_irq = board->irq_pin;
+	} else
+		cf->socket.pci_irq = NR_IRQS + 1;
+
+	/* pcmcia layer only remaps "real" memory not iospace */
+	cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
+	if (!cf->socket.io_offset)
+		goto fail1;
+
+	/* reserve CS4, CS5, and CS6 regions; but use just CS4 */
+	if (!request_mem_region(io->start, io->end + 1 - io->start,
+				driver_name))
+		goto fail1;
+
+	pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+		board->det_pin, board->irq_pin);
+
+	cf->socket.owner = THIS_MODULE;
+	cf->socket.dev.dev = dev;
+	cf->socket.ops = &at91_cf_ops;
+	cf->socket.resource_ops = &pccard_static_ops;
+	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+				| SS_CAP_MEM_ALIGN;
+	cf->socket.map_size = SZ_2K;
+	cf->socket.io[0].res = io;
+
+	status = pcmcia_register_socket(&cf->socket);
+	if (status < 0)
+		goto fail2;
+
+	return 0;
+
+fail2:
+	iounmap((void __iomem *) cf->socket.io_offset);
+	release_mem_region(io->start, io->end + 1 - io->start);
+fail1:
+	if (board->irq_pin)
+		free_irq(board->irq_pin, cf);
+fail0a:
+	free_irq(board->det_pin, cf);
+fail0:
+	at91_sys_write(AT91_EBI_CSA, csa);
+	kfree(cf);
+	return status;
+}
+
+static int __exit at91_cf_remove(struct device *dev)
+{
+	struct at91_cf_socket	*cf = dev_get_drvdata(dev);
+	struct resource		*io = cf->socket.io[0].res;
+	unsigned int		csa;
+
+	pcmcia_unregister_socket(&cf->socket);
+	free_irq(cf->board->irq_pin, cf);
+	free_irq(cf->board->det_pin, cf);
+	iounmap((void __iomem *) cf->socket.io_offset);
+	release_mem_region(io->start, io->end + 1 - io->start);
+
+	csa = at91_sys_read(AT91_EBI_CSA);
+	at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
+
+	kfree(cf);
+	return 0;
+}
+
+static struct device_driver at91_cf_driver = {
+	.name		= (char *) driver_name,
+	.bus		= &platform_bus_type,
+	.probe		= at91_cf_probe,
+	.remove		= __exit_p(at91_cf_remove),
+	.suspend	= pcmcia_socket_dev_suspend,
+	.resume		= pcmcia_socket_dev_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init at91_cf_init(void)
+{
+	return driver_register(&at91_cf_driver);
+}
+module_init(at91_cf_init);
+
+static void __exit at91_cf_exit(void)
+{
+	driver_unregister(&at91_cf_driver);
+}
+module_exit(at91_cf_exit);
+
+MODULE_DESCRIPTION("AT91 Compact Flash Driver");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 120fa8d..912c03e 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -12,7 +12,6 @@
  * (C) 1999		David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 613f2f1..3162998 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -16,7 +16,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/errno.h>
@@ -111,9 +110,9 @@
 	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
 		if (socket->dev.dev != dev)
 			continue;
-		down(&socket->skt_sem);
+		mutex_lock(&socket->skt_mutex);
 		socket_suspend(socket);
-		up(&socket->skt_sem);
+		mutex_unlock(&socket->skt_mutex);
 	}
 	up_read(&pcmcia_socket_list_rwsem);
 
@@ -129,9 +128,9 @@
 	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
 		if (socket->dev.dev != dev)
 			continue;
-		down(&socket->skt_sem);
+		mutex_lock(&socket->skt_mutex);
 		socket_resume(socket);
-		up(&socket->skt_sem);
+		mutex_unlock(&socket->skt_mutex);
 	}
 	up_read(&pcmcia_socket_list_rwsem);
 
@@ -237,7 +236,7 @@
 	init_completion(&socket->socket_released);
 	init_completion(&socket->thread_done);
 	init_waitqueue_head(&socket->thread_wait);
-	init_MUTEX(&socket->skt_sem);
+	mutex_init(&socket->skt_mutex);
 	spin_lock_init(&socket->thread_lock);
 
 	ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
@@ -406,8 +405,6 @@
 	cb_free(s);
 #endif
 	s->functions = 0;
-	kfree(s->config);
-	s->config = NULL;
 
 	s->ops->get_status(s, &status);
 	if (status & SS_POWERON) {
@@ -664,7 +661,7 @@
 		spin_unlock_irqrestore(&skt->thread_lock, flags);
 
 		if (events) {
-			down(&skt->skt_sem);
+			mutex_lock(&skt->skt_mutex);
 			if (events & SS_DETECT)
 				socket_detect_change(skt);
 			if (events & SS_BATDEAD)
@@ -673,7 +670,7 @@
 				send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
 			if (events & SS_READY)
 				send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
-			up(&skt->skt_sem);
+			mutex_unlock(&skt->skt_mutex);
 			continue;
 		}
 
@@ -717,8 +714,8 @@
 {
         int ret = 0;
 
-	/* s->skt_sem also protects s->callback */
-	down(&s->skt_sem);
+	/* s->skt_mutex also protects s->callback */
+	mutex_lock(&s->skt_mutex);
 
 	if (c) {
 		/* registration */
@@ -734,7 +731,7 @@
 	} else
 		s->callback = NULL;
  err:
-	up(&s->skt_sem);
+	mutex_unlock(&s->skt_mutex);
 
 	return ret;
 }
@@ -752,7 +749,7 @@
 
 	cs_dbg(skt, 1, "resetting socket\n");
 
-	down(&skt->skt_sem);
+	mutex_lock(&skt->skt_mutex);
 	do {
 		if (!(skt->state & SOCKET_PRESENT)) {
 			ret = CS_NO_CARD;
@@ -781,7 +778,7 @@
 
 		ret = CS_SUCCESS;
 	} while (0);
-	up(&skt->skt_sem);
+	mutex_unlock(&skt->skt_mutex);
 
 	return ret;
 } /* reset_card */
@@ -797,7 +794,7 @@
 
 	cs_dbg(skt, 1, "suspending socket\n");
 
-	down(&skt->skt_sem);
+	mutex_lock(&skt->skt_mutex);
 	do {
 		if (!(skt->state & SOCKET_PRESENT)) {
 			ret = CS_NO_CARD;
@@ -814,7 +811,7 @@
 		}
 		ret = socket_suspend(skt);
 	} while (0);
-	up(&skt->skt_sem);
+	mutex_unlock(&skt->skt_mutex);
 
 	return ret;
 } /* suspend_card */
@@ -827,7 +824,7 @@
     
 	cs_dbg(skt, 1, "waking up socket\n");
 
-	down(&skt->skt_sem);
+	mutex_lock(&skt->skt_mutex);
 	do {
 		if (!(skt->state & SOCKET_PRESENT)) {
 			ret = CS_NO_CARD;
@@ -841,7 +838,7 @@
 		if (!ret && skt->callback)
 			skt->callback->resume(skt);
 	} while (0);
-	up(&skt->skt_sem);
+	mutex_unlock(&skt->skt_mutex);
 
 	return ret;
 } /* resume_card */
@@ -855,7 +852,7 @@
     
 	cs_dbg(skt, 1, "user eject request\n");
 
-	down(&skt->skt_sem);
+	mutex_lock(&skt->skt_mutex);
 	do {
 		if (!(skt->state & SOCKET_PRESENT)) {
 			ret = -ENODEV;
@@ -871,7 +868,7 @@
 		socket_remove(skt);
 		ret = 0;
 	} while (0);
-	up(&skt->skt_sem);
+	mutex_unlock(&skt->skt_mutex);
 
 	return ret;
 } /* eject_card */
@@ -884,7 +881,7 @@
 
 	cs_dbg(skt, 1, "user insert request\n");
 
-	down(&skt->skt_sem);
+	mutex_lock(&skt->skt_mutex);
 	do {
 		if (skt->state & SOCKET_PRESENT) {
 			ret = -EBUSY;
@@ -896,7 +893,7 @@
 		}
 		ret = 0;
 	} while (0);
-	up(&skt->skt_sem);
+	mutex_unlock(&skt->skt_mutex);
 
 	return ret;
 } /* insert_card */
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7b37eba..d6164cd 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -15,7 +15,7 @@
 #ifndef _LINUX_CS_INTERNAL_H
 #define _LINUX_CS_INTERNAL_H
 
-#include <linux/config.h>
+#include <linux/kref.h>
 
 /* Flags in client state */
 #define CLIENT_CONFIG_LOCKED	0x0001
@@ -23,7 +23,7 @@
 #define CLIENT_IO_REQ		0x0004
 #define CLIENT_UNBOUND		0x0008
 #define CLIENT_STALE		0x0010
-#define CLIENT_WIN_REQ(i)	(0x20<<(i))
+#define CLIENT_WIN_REQ(i)	(0x1<<(i))
 #define CLIENT_CARDBUS		0x8000
 
 #define REGION_MAGIC	0xE3C9
@@ -31,7 +31,7 @@
     u_short		region_magic;
     u_short		state;
     dev_info_t		dev_info;
-    client_handle_t	mtd;
+    struct pcmcia_device	*mtd;
     u_int		MediaID;
     region_info_t	info;
 } region_t;
@@ -40,12 +40,12 @@
 
 /* Each card function gets one of these guys */
 typedef struct config_t {
+	struct kref	ref;
     u_int		state;
     u_int		Attributes;
     u_int		IntType;
     u_int		ConfigBase;
     u_char		Status, Pin, Copy, Option, ExtStatus;
-    u_int		Present;
     u_int		CardValues;
     io_req_t		io;
     struct {
@@ -95,12 +95,6 @@
 	}
 }
 
-#define CHECK_SOCKET(s) \
-    (((s) >= sockets) || (socket_table[s]->ops == NULL))
-
-#define SOCKET(h) (h->socket)
-#define CONFIG(h) (&SOCKET(h)->config[(h)->func])
-
 /* In cardbus.c */
 int cb_alloc(struct pcmcia_socket *s);
 void cb_free(struct pcmcia_socket *s);
@@ -133,10 +127,9 @@
 extern struct rw_semaphore pcmcia_socket_list_rwsem;
 extern struct list_head pcmcia_socket_list;
 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config);
+int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
 int pccard_reset_card(struct pcmcia_socket *skt);
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status);
-int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg);
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status);
 
 
 struct pcmcia_callback{
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bb96ce1..48d3b3d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -10,10 +10,9 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * (C) 1999		David A. Hinds
- * (C) 2003 - 2005	Dominik Brodowski
+ * (C) 2003 - 2006	Dominik Brodowski
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -23,6 +22,7 @@
 #include <linux/workqueue.h>
 #include <linux/crc32.h>
 #include <linux/firmware.h>
+#include <linux/kref.h>
 
 #define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
@@ -236,11 +236,11 @@
 /**
  * pcmcia_load_firmware - load CIS from userspace if device-provided is broken
  * @dev - the pcmcia device which needs a CIS override
- * @filename - requested filename in /lib/firmware/cis/
+ * @filename - requested filename in /lib/firmware/
  *
  * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
  * the one provided by the card is broken. The firmware files reside in
- * /lib/firmware/cis/ in userspace.
+ * /lib/firmware/ in userspace.
  */
 static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 {
@@ -298,9 +298,6 @@
  *
  * Registers a PCMCIA driver with the PCMCIA bus core.
  */
-static int pcmcia_device_probe(struct device *dev);
-static int pcmcia_device_remove(struct device * dev);
-
 int pcmcia_register_driver(struct pcmcia_driver *driver)
 {
 	if (!driver)
@@ -343,12 +340,19 @@
 		put_device(&p_dev->dev);
 }
 
+static void pcmcia_release_function(struct kref *ref)
+{
+	struct config_t *c = container_of(ref, struct config_t, ref);
+	kfree(c);
+}
+
 static void pcmcia_release_dev(struct device *dev)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 	ds_dbg(1, "releasing dev %p\n", p_dev);
 	pcmcia_put_socket(p_dev->socket);
 	kfree(p_dev->devname);
+	kref_put(&p_dev->function_config->ref, pcmcia_release_function);
 	kfree(p_dev);
 }
 
@@ -377,29 +381,12 @@
 	p_drv = to_pcmcia_drv(dev->driver);
 	s = p_dev->socket;
 
-	if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
+	if ((!p_drv->probe) || (!p_dev->function_config) ||
+	    (!try_module_get(p_drv->owner))) {
 		ret = -EINVAL;
 		goto put_dev;
 	}
 
-	p_dev->state &= ~CLIENT_UNBOUND;
-
-	/* set up the device configuration, if it hasn't been done before */
-	if (!s->functions) {
-		cistpl_longlink_mfc_t mfc;
-		if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
-				      &mfc) == CS_SUCCESS)
-			s->functions = mfc.nfn;
-		else
-			s->functions = 1;
-		s->config = kzalloc(sizeof(config_t) * s->functions,
-				    GFP_KERNEL);
-		if (!s->config) {
-			ret = -ENOMEM;
-			goto put_module;
-		}
-	}
-
 	ret = p_drv->probe(p_dev);
 	if (ret)
 		goto put_module;
@@ -410,7 +397,7 @@
 	 * call which will then check whether there are two
 	 * pseudo devices, and if not, add the second one.
 	 */
-	did = (struct pcmcia_device_id *) p_dev->dev.driver_data;
+	did = p_dev->dev.driver_data;
 	if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
 	    (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
 		pcmcia_add_pseudo_device(p_dev->socket);
@@ -425,69 +412,84 @@
 }
 
 
-static int pcmcia_device_remove(struct device * dev)
-{
-	struct pcmcia_device *p_dev;
-	struct pcmcia_driver *p_drv;
-	int i;
-
-	/* detach the "instance" */
-	p_dev = to_pcmcia_dev(dev);
-	p_drv = to_pcmcia_drv(dev->driver);
-	if (!p_drv)
-		return 0;
-
-	if (p_drv->remove)
-	       	p_drv->remove(p_dev);
-
-	/* check for proper unloading */
-	if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
-		printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
-		       p_drv->drv.name);
-
-	for (i = 0; i < MAX_WIN; i++)
-		if (p_dev->state & CLIENT_WIN_REQ(i))
-			printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
-			       p_drv->drv.name);
-
-	/* references from pcmcia_probe_device */
-	p_dev->state = CLIENT_UNBOUND;
-	pcmcia_put_dev(p_dev);
-	module_put(p_drv->owner);
-
-	return 0;
-}
-
-
 /*
  * Removes a PCMCIA card from the device tree and socket list.
  */
-static void pcmcia_card_remove(struct pcmcia_socket *s)
+static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
 {
 	struct pcmcia_device	*p_dev;
+	struct pcmcia_device	*tmp;
 	unsigned long		flags;
 
 	ds_dbg(2, "unbind_request(%d)\n", s->sock);
 
-	s->device_count = 0;
 
-	for (;;) {
-		/* unregister all pcmcia_devices registered with this socket*/
+	if (!leftover)
+		s->device_count = 0;
+	else
+		s->device_count = 1;
+
+	/* unregister all pcmcia_devices registered with this socket, except leftover */
+	list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
+		if (p_dev == leftover)
+			continue;
+
 		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-		if (list_empty(&s->devices_list)) {
-			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- 			return;
-		}
-		p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
 		list_del(&p_dev->socket_device_list);
-		p_dev->state |= CLIENT_STALE;
+		p_dev->_removed=1;
 		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
 		device_unregister(&p_dev->dev);
 	}
 
 	return;
-} /* unbind_request */
+}
+
+static int pcmcia_device_remove(struct device * dev)
+{
+	struct pcmcia_device *p_dev;
+	struct pcmcia_driver *p_drv;
+	struct pcmcia_device_id *did;
+	int i;
+
+	p_dev = to_pcmcia_dev(dev);
+	p_drv = to_pcmcia_drv(dev->driver);
+
+	/* If we're removing the primary module driving a
+	 * pseudo multi-function card, we need to unbind
+	 * all devices
+	 */
+	did = p_dev->dev.driver_data;
+	if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+	    (p_dev->socket->device_count != 0) &&
+	    (p_dev->device_no == 0))
+		pcmcia_card_remove(p_dev->socket, p_dev);
+
+	/* detach the "instance" */
+	if (!p_drv)
+		return 0;
+
+	if (p_drv->remove)
+	       	p_drv->remove(p_dev);
+
+	p_dev->dev_node = NULL;
+
+	/* check for proper unloading */
+	if (p_dev->_irq || p_dev->_io || p_dev->_locked)
+		printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
+		       p_drv->drv.name);
+
+	for (i = 0; i < MAX_WIN; i++)
+		if (p_dev->_win & CLIENT_WIN_REQ(i))
+			printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
+			       p_drv->drv.name);
+
+	/* references from pcmcia_probe_device */
+	pcmcia_put_dev(p_dev);
+	module_put(p_drv->owner);
+
+	return 0;
+}
 
 
 /*
@@ -546,7 +548,7 @@
 			tmp = vers1->str + vers1->ofs[i];
 
 			length = strlen(tmp) + 1;
-			if ((length < 3) || (length > 255))
+			if ((length < 2) || (length > 255))
 				continue;
 
 			p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
@@ -571,11 +573,11 @@
  * won't work, this doesn't matter much at the moment: the driver core doesn't
  * support it either.
  */
-static DECLARE_MUTEX(device_add_lock);
+static DEFINE_MUTEX(device_add_lock);
 
 struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
 {
-	struct pcmcia_device *p_dev;
+	struct pcmcia_device *p_dev, *tmp_dev;
 	unsigned long flags;
 	int bus_id_len;
 
@@ -583,7 +585,7 @@
 	if (!s)
 		return NULL;
 
-	down(&device_add_lock);
+	mutex_lock(&device_add_lock);
 
 	/* max of 2 devices per card */
 	if (s->device_count == 2)
@@ -596,6 +598,8 @@
 	p_dev->socket = s;
 	p_dev->device_no = (s->device_count++);
 	p_dev->func   = function;
+	if (s->functions <= function)
+		s->functions = function + 1;
 
 	p_dev->dev.bus = &pcmcia_bus_type;
 	p_dev->dev.parent = s->dev.dev;
@@ -608,36 +612,55 @@
 	sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
 
 	/* compat */
-	p_dev->state = CLIENT_UNBOUND;
+	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+
+	/*
+	 * p_dev->function_config must be the same for all card functions.
+	 * Note that this is serialized by the device_add_lock, so that
+	 * only one such struct will be created.
+	 */
+        list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
+                if (p_dev->func == tmp_dev->func) {
+			p_dev->function_config = tmp_dev->function_config;
+			kref_get(&p_dev->function_config->ref);
+		}
 
 	/* Add to the list in pcmcia_bus_socket */
-	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-	list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+	list_add(&p_dev->socket_device_list, &s->devices_list);
+
 	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
+	if (!p_dev->function_config) {
+		p_dev->function_config = kzalloc(sizeof(struct config_t),
+						 GFP_KERNEL);
+		if (!p_dev->function_config)
+			goto err_unreg;
+		kref_init(&p_dev->function_config->ref);
+	}
+
 	printk(KERN_NOTICE "pcmcia: registering new device %s\n",
 	       p_dev->devname);
 
 	pcmcia_device_query(p_dev);
 
-	if (device_register(&p_dev->dev)) {
-		spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-		list_del(&p_dev->socket_device_list);
-		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+	if (device_register(&p_dev->dev))
+		goto err_unreg;
 
-		goto err_free;
-       }
-
-	up(&device_add_lock);
+	mutex_unlock(&device_add_lock);
 
 	return p_dev;
 
+ err_unreg:
+	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+	list_del(&p_dev->socket_device_list);
+	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
  err_free:
 	kfree(p_dev->devname);
 	kfree(p_dev);
 	s->device_count--;
  err_put:
-	up(&device_add_lock);
+	mutex_unlock(&device_add_lock);
 	pcmcia_put_socket(s);
 
 	return NULL;
@@ -696,7 +719,7 @@
 	int no_devices=0;
 	unsigned long flags;
 
-	/* must be called with skt_sem held */
+	/* must be called with skt_mutex held */
 	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
 	if (list_empty(&skt->devices_list))
 		no_devices=1;
@@ -819,9 +842,11 @@
 	struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
 	struct pcmcia_device_id *did = p_drv->id_table;
 
+#ifdef CONFIG_PCMCIA_IOCTL
 	/* matching by cardmgr */
 	if (p_dev->cardmgr == p_drv)
 		return 1;
+#endif
 
 	while (did && did->match_flags) {
 		if (pcmcia_devmatch(p_dev, did))
@@ -927,7 +952,7 @@
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 
-	if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+	if (p_dev->suspended)
 		return sprintf(buf, "off\n");
 	else
 		return sprintf(buf, "on\n");
@@ -942,11 +967,9 @@
         if (!count)
                 return -EINVAL;
 
-	if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
-	    (!strncmp(buf, "off", 3)))
+	if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
 		ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
-	else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
-		 (!strncmp(buf, "on", 2)))
+	else if (p_dev->suspended && !strncmp(buf, "on", 2))
 		dpm_runtime_resume(dev);
 
 	return ret ? ret : count;
@@ -982,9 +1005,9 @@
 	if (!count)
 		return -EINVAL;
 
-	down(&p_dev->socket->skt_sem);
+	mutex_lock(&p_dev->socket->skt_mutex);
 	p_dev->allow_func_id_match = 1;
-	up(&p_dev->socket->skt_sem);
+	mutex_unlock(&p_dev->socket->skt_mutex);
 
 	bus_rescan_devices(&pcmcia_bus_type);
 
@@ -1012,14 +1035,27 @@
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 	struct pcmcia_driver *p_drv = NULL;
+	int ret = 0;
 
 	if (dev->driver)
 		p_drv = to_pcmcia_drv(dev->driver);
 
-	if (p_drv && p_drv->suspend)
-		return p_drv->suspend(p_dev);
+	if (!p_drv)
+		goto out;
 
-	return 0;
+	if (p_drv->suspend) {
+		ret = p_drv->suspend(p_dev);
+		if (ret)
+			goto out;
+	}
+
+	if (p_dev->device_no == p_dev->func)
+		pcmcia_release_configuration(p_dev);
+
+ out:
+	if (!ret)
+		p_dev->suspended = 1;
+	return ret;
 }
 
 
@@ -1027,14 +1063,27 @@
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
         struct pcmcia_driver *p_drv = NULL;
+	int ret = 0;
 
 	if (dev->driver)
 		p_drv = to_pcmcia_drv(dev->driver);
 
-	if (p_drv && p_drv->resume)
-		return p_drv->resume(p_dev);
+	if (!p_drv)
+		goto out;
 
-	return 0;
+	if (p_dev->device_no == p_dev->func) {
+		ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+		if (ret)
+			goto out;
+	}
+
+	if (p_drv->resume)
+		ret = p_drv->resume(p_dev);
+
+ out:
+	if (!ret)
+		p_dev->suspended = 0;
+	return ret;
 }
 
 
@@ -1100,7 +1149,7 @@
 	switch (event) {
 	case CS_EVENT_CARD_REMOVAL:
 		s->pcmcia_state.present = 0;
-		pcmcia_card_remove(skt);
+		pcmcia_card_remove(skt, NULL);
 		handle_event(skt, event);
 		break;
 
@@ -1128,6 +1177,32 @@
 } /* ds_event */
 
 
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev)
+{
+	struct pcmcia_device *p_dev;
+	struct pcmcia_device *ret = NULL;
+
+	p_dev = pcmcia_get_dev(_p_dev);
+	if (!p_dev)
+		return NULL;
+
+	if (!p_dev->socket->pcmcia_state.present)
+		goto out;
+
+	if (p_dev->_removed)
+		goto out;
+
+	if (p_dev->suspended)
+		goto out;
+
+	ret = p_dev;
+ out:
+	pcmcia_put_dev(p_dev);
+	return ret;
+}
+EXPORT_SYMBOL(pcmcia_dev_present);
+
+
 static struct pcmcia_callback pcmcia_bus_callback = {
 	.owner = THIS_MODULE,
 	.event = ds_event,
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h
index d359bd2..3a2b25e 100644
--- a/drivers/pcmcia/ds_internal.h
+++ b/drivers/pcmcia/ds_internal.h
@@ -8,6 +8,8 @@
 
 struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
 
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
 #ifdef CONFIG_PCMCIA_IOCTL
 extern void __init pcmcia_setup_ioctl(void);
 extern void __exit pcmcia_cleanup_ioctl(void);
@@ -15,7 +17,7 @@
 extern int handle_request(struct pcmcia_socket *s, event_t event);
 #else
 static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __init pcmcia_cleanup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
 static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
 static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
 #endif
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 7979c85..d5f03a3 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 35a92d1..a2f05f4 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/string.h>
@@ -510,7 +509,8 @@
 static u_int __init test_irq(u_short sock, int irq)
 {
     debug(2, "  testing ISA irq %d\n", irq);
-    if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
+    if (request_irq(irq, i365_count_irq, SA_PROBEIRQ, "scan",
+			i365_count_irq) != 0)
 	return 1;
     irq_hits = 0; irq_sock = sock;
     msleep(10);
@@ -562,7 +562,7 @@
     } else {
 	/* Fallback: just find interrupts that aren't in use */
 	for (i = 0; i < 16; i++)
-	    if ((mask0 & (1 << i)) && (_check_irq(i, 0) == 0))
+	    if ((mask0 & (1 << i)) && (_check_irq(i, SA_PROBEIRQ) == 0))
 		mask1 |= (1 << i);
 	printk("default");
 	/* If scan failed, default to polled status */
@@ -726,7 +726,7 @@
 	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
 	for (cs_irq = 15; cs_irq > 0; cs_irq--)
 	    if ((cs_mask & (1 << cs_irq)) &&
-		(_check_irq(cs_irq, 0) == 0))
+		(_check_irq(cs_irq, SA_PROBEIRQ) == 0))
 		break;
 	if (cs_irq) {
 	    grab_irq = 1;
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c
deleted file mode 100644
index ebb161c..0000000
--- a/drivers/pcmcia/pcmcia_compat.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * PCMCIA 16-bit compatibility functions
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * Copyright (C) 2004 Dominik Brodowski
- *
- * 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/module.h>
-#include <linux/init.h>
-
-#define IN_CARD_SERVICES
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/ss.h>
-
-#include "cs_internal.h"
-
-int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-	return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_first_tuple);
-
-int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-	return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_next_tuple);
-
-int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple)
-{
-	return pccard_get_tuple_data(p_dev->socket, tuple);
-}
-EXPORT_SYMBOL(pcmcia_get_tuple_data);
-
-int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse)
-{
-	return pccard_parse_tuple(tuple, parse);
-}
-EXPORT_SYMBOL(pcmcia_parse_tuple);
-
-int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info)
-{
-	return pccard_validate_cis(p_dev->socket, p_dev->func, info);
-}
-EXPORT_SYMBOL(pcmcia_validate_cis);
-
-
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req)
-{
-	return pccard_reset_card(p_dev->socket);
-}
-EXPORT_SYMBOL(pcmcia_reset_card);
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 80969f7..c53db7c 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -18,7 +18,6 @@
  */
 
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -70,10 +69,26 @@
 #define ds_dbg(lvl, fmt, arg...) do { } while (0)
 #endif
 
+static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
+						unsigned int function)
+{
+	struct pcmcia_device *p_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+	list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+		if (p_dev->func == function) {
+			spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+			return pcmcia_get_dev(p_dev);
+		}
+	}
+	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+	return NULL;
+}
 
 /* backwards-compatible accessing of driver --- by name! */
 
-static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
+static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
 {
 	struct device_driver *drv;
 	struct pcmcia_driver *p_drv;
@@ -214,7 +229,7 @@
 					 * by userspace before, we need to
 					 * return the "instance". */
 					spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-					bind_info->instance = p_dev->instance;
+					bind_info->instance = p_dev;
 					ret = -EBUSY;
 					goto err_put_module;
 				} else {
@@ -253,9 +268,9 @@
 	/*
 	 * Prevent this racing with a card insertion.
 	 */
-	down(&s->skt_sem);
+	mutex_lock(&s->skt_mutex);
 	bus_rescan_devices(&pcmcia_bus_type);
-	up(&s->skt_sem);
+	mutex_unlock(&s->skt_mutex);
 
 	/* check whether the driver indeed matched. I don't care if this
 	 * is racy or not, because it can only happen on cardmgr access
@@ -289,6 +304,7 @@
 {
 	dev_node_t *node;
 	struct pcmcia_device *p_dev;
+	struct pcmcia_driver *p_drv;
 	unsigned long flags;
 	int ret = 0;
 
@@ -343,16 +359,16 @@
  found:
 	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
-	if ((!p_dev->instance) ||
-	    (p_dev->instance->state & DEV_CONFIG_PENDING)) {
+	p_drv = to_pcmcia_drv(p_dev->dev.driver);
+	if (p_drv && !p_dev->_locked) {
 		ret = -EAGAIN;
 		goto err_put;
 	}
 
 	if (first)
-		node = p_dev->instance->dev;
+		node = p_dev->dev_node;
 	else
-		for (node = p_dev->instance->dev; node; node = node->next)
+		for (node = p_dev->dev_node; node; node = node->next)
 			if (node == bind_info->next)
 				break;
 	if (!node) {
@@ -583,14 +599,16 @@
 	if (buf->config.Function &&
 	   (buf->config.Function >= s->functions))
 	    ret = CS_BAD_ARGS;
-	else
-	    ret = pccard_get_configuration_info(s,
-			buf->config.Function, &buf->config);
+	else {
+	    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
+	    ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+	    pcmcia_put_dev(p_dev);
+	}
 	break;
     case DS_GET_FIRST_TUPLE:
-	down(&s->skt_sem);
+	mutex_lock(&s->skt_mutex);
 	pcmcia_validate_mem(s);
-	up(&s->skt_sem);
+	mutex_unlock(&s->skt_mutex);
 	ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
 	break;
     case DS_GET_NEXT_TUPLE:
@@ -609,16 +627,19 @@
 	ret = pccard_reset_card(s);
 	break;
     case DS_GET_STATUS:
-	if (buf->status.Function &&
-	   (buf->status.Function >= s->functions))
-	    ret = CS_BAD_ARGS;
-	else
-	ret = pccard_get_status(s, buf->status.Function, &buf->status);
-	break;
+	    if (buf->status.Function &&
+		(buf->status.Function >= s->functions))
+		    ret = CS_BAD_ARGS;
+	    else {
+		    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
+		    ret = pccard_get_status(s, p_dev, &buf->status);
+		    pcmcia_put_dev(p_dev);
+	    }
+	    break;
     case DS_VALIDATE_CIS:
-	down(&s->skt_sem);
+	mutex_lock(&s->skt_mutex);
 	pcmcia_validate_mem(s);
-	up(&s->skt_sem);
+	mutex_unlock(&s->skt_mutex);
 	ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
 	break;
     case DS_SUSPEND_CARD:
@@ -638,12 +659,16 @@
 	    err = -EPERM;
 	    goto free_out;
 	}
-	if (buf->conf_reg.Function &&
-	   (buf->conf_reg.Function >= s->functions))
-	    ret = CS_BAD_ARGS;
-	else
-	    ret = pccard_access_configuration_register(s,
-			buf->conf_reg.Function, &buf->conf_reg);
+
+	ret = CS_BAD_ARGS;
+
+	if (!(buf->conf_reg.Function &&
+	     (buf->conf_reg.Function >= s->functions))) {
+		struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
+		if (p_dev)
+			ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
+		pcmcia_put_dev(p_dev);
+	}
 	break;
     case DS_GET_FIRST_REGION:
     case DS_GET_NEXT_REGION:
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 89022ad..3131bb0 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
@@ -89,7 +88,6 @@
 	}
 	if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
 		*base = s->io_offset | (*base & 0x0fff);
-		s->io[0].Attributes = attr;
 		return 0;
 	}
 	/* Check for an already-allocated window that must conflict with
@@ -97,38 +95,36 @@
 	 * potential conflicts, just the most obvious ones.
 	 */
 	for (i = 0; i < MAX_IO_WIN; i++)
-		if ((s->io[i].NumPorts != 0) &&
-		    ((s->io[i].BasePort & (align-1)) == *base))
+		if ((s->io[i].res) &&
+		    ((s->io[i].res->start & (align-1)) == *base))
 			return 1;
 	for (i = 0; i < MAX_IO_WIN; i++) {
-		if (s->io[i].NumPorts == 0) {
+		if (!s->io[i].res) {
 			s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
 			if (s->io[i].res) {
-				s->io[i].Attributes = attr;
-				s->io[i].BasePort = *base = s->io[i].res->start;
-				s->io[i].NumPorts = s->io[i].InUse = num;
+				*base = s->io[i].res->start;
+				s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
+				s->io[i].InUse = num;
 				break;
 			} else
 				return 1;
-		} else if (s->io[i].Attributes != attr)
+		} else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
 			continue;
 		/* Try to extend top of window */
-		try = s->io[i].BasePort + s->io[i].NumPorts;
+		try = s->io[i].res->end + 1;
 		if ((*base == 0) || (*base == try))
 			if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
 						    s->io[i].res->end + num, s) == 0) {
 				*base = try;
-				s->io[i].NumPorts += num;
 				s->io[i].InUse += num;
 				break;
 			}
 		/* Try to extend bottom of window */
-		try = s->io[i].BasePort - num;
+		try = s->io[i].res->start - num;
 		if ((*base == 0) || (*base == try))
 			if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
 						    s->io[i].res->end, s) == 0) {
-				s->io[i].BasePort = *base = try;
-				s->io[i].NumPorts += num;
+				*base = try;
 				s->io[i].InUse += num;
 				break;
 			}
@@ -143,12 +139,13 @@
 	int i;
 
 	for (i = 0; i < MAX_IO_WIN; i++) {
-		if ((s->io[i].BasePort <= base) &&
-		    (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
+		if (!s->io[i].res)
+			continue;
+		if ((s->io[i].res->start <= base) &&
+		    (s->io[i].res->end >= base+num-1)) {
 			s->io[i].InUse -= num;
 			/* Free the window if no one else is using it */
 			if (s->io[i].InUse == 0) {
-				s->io[i].NumPorts = 0;
 				release_resource(s->io[i].res);
 				kfree(s->io[i].res);
 				s->io[i].res = NULL;
@@ -165,21 +162,19 @@
  * this and the tuple reading services.
  */
 
-int pccard_access_configuration_register(struct pcmcia_socket *s,
-					 unsigned int function,
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
 					 conf_reg_t *reg)
 {
+	struct pcmcia_socket *s;
 	config_t *c;
 	int addr;
 	u_char val;
 
-	if (!s || !s->config)
+	if (!p_dev || !p_dev->function_config)
 		return CS_NO_CARD;
 
-	c = &s->config[function];
-
-	if (c == NULL)
-		return CS_NO_CARD;
+	s = p_dev->socket;
+	c = p_dev->function_config;
 
 	if (!(c->state & CONFIG_LOCKED))
 		return CS_CONFIGURATION_LOCKED;
@@ -200,20 +195,12 @@
 		break;
 	}
 	return CS_SUCCESS;
-} /* pccard_access_configuration_register */
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
-					 conf_reg_t *reg)
-{
-	return pccard_access_configuration_register(p_dev->socket,
-						    p_dev->func, reg);
-}
+} /* pcmcia_access_configuration_register */
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 
 
-
 int pccard_get_configuration_info(struct pcmcia_socket *s,
-				  unsigned int function,
+				  struct pcmcia_device *p_dev,
 				  config_info_t *config)
 {
 	config_t *c;
@@ -221,7 +208,6 @@
 	if (!(s->state & SOCKET_PRESENT))
 		return CS_NO_CARD;
 
-	config->Function = function;
 
 #ifdef CONFIG_CARDBUS
 	if (s->state & SOCKET_CARDBUS) {
@@ -235,14 +221,22 @@
 			config->AssignedIRQ = s->irq.AssignedIRQ;
 			if (config->AssignedIRQ)
 				config->Attributes |= CONF_ENABLE_IRQ;
-			config->BasePort1 = s->io[0].BasePort;
-			config->NumPorts1 = s->io[0].NumPorts;
+			if (s->io[0].res) {
+				config->BasePort1 = s->io[0].res->start;
+				config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
+			}
 		}
 		return CS_SUCCESS;
 	}
 #endif
 
-	c = (s->config != NULL) ? &s->config[function] : NULL;
+	if (p_dev) {
+		c = p_dev->function_config;
+		config->Function = p_dev->func;
+	} else {
+		c = NULL;
+		config->Function = 0;
+	}
 
 	if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
 		config->Attributes = 0;
@@ -271,7 +265,7 @@
 int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
 				  config_info_t *config)
 {
-	return pccard_get_configuration_info(p_dev->socket, p_dev->func,
+	return pccard_get_configuration_info(p_dev->socket, p_dev,
 					     config);
 }
 EXPORT_SYMBOL(pcmcia_get_configuration_info);
@@ -317,7 +311,7 @@
  * SocketState yet: I haven't seen any point for it.
  */
 
-int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
+int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
 		      cs_status_t *status)
 {
 	config_t *c;
@@ -334,11 +328,12 @@
 	if (!(s->state & SOCKET_PRESENT))
 		return CS_NO_CARD;
 
-	c = (s->config != NULL) ? &s->config[function] : NULL;
+	c = (p_dev) ? p_dev->function_config : NULL;
+
 	if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
 	    (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
 		u_char reg;
-		if (c->Present & PRESENT_PIN_REPLACE) {
+		if (c->CardValues & PRESENT_PIN_REPLACE) {
 			pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
 			status->CardState |=
 				(reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -352,7 +347,7 @@
 			/* No PRR?  Then assume we're always ready */
 			status->CardState |= CS_EVENT_READY_CHANGE;
 		}
-		if (c->Present & PRESENT_EXT_STATUS) {
+		if (c->CardValues & PRESENT_EXT_STATUS) {
 			pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
 			status->CardState |=
 				(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
@@ -370,11 +365,9 @@
 	return CS_SUCCESS;
 } /* pccard_get_status */
 
-int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
+int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
 {
-	struct pcmcia_socket *s;
-	s = SOCKET(handle);
-	return pccard_get_status(s, handle->func, status);
+	return pccard_get_status(p_dev->socket, p_dev, status);
 }
 EXPORT_SYMBOL(pcmcia_get_status);
 
@@ -422,7 +415,8 @@
 	config_t *c;
 
 	s = p_dev->socket;
-	c = CONFIG(p_dev);
+	c = p_dev->function_config;
+
 	if (!(s->state & SOCKET_PRESENT))
 		return CS_NO_CARD;
 	if (!(c->state & CONFIG_LOCKED))
@@ -454,6 +448,28 @@
 		   (mod->Attributes & CONF_VPP2_CHANGE_VALID))
 		return CS_BAD_VPP;
 
+	if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
+		pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+		pccard_io_map io_on;
+		int i;
+
+		io_on.speed = io_speed;
+		for (i = 0; i < MAX_IO_WIN; i++) {
+			if (!s->io[i].res)
+				continue;
+			io_off.map = i;
+			io_on.map = i;
+
+			io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+			io_on.start = s->io[i].res->start;
+			io_on.stop = s->io[i].res->end;
+
+			s->ops->set_io_map(s, &io_off);
+			mdelay(40);
+			s->ops->set_io_map(s, &io_on);
+		}
+	}
+
 	return CS_SUCCESS;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
@@ -463,23 +479,23 @@
 {
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
 	struct pcmcia_socket *s = p_dev->socket;
+	config_t *c = p_dev->function_config;
 	int i;
 
-	if (!(p_dev->state & CLIENT_CONFIG_LOCKED))
-		return CS_BAD_HANDLE;
-	p_dev->state &= ~CLIENT_CONFIG_LOCKED;
-
-	if (!(p_dev->state & CLIENT_STALE)) {
-		config_t *c = CONFIG(p_dev);
+	if (p_dev->_locked) {
+		p_dev->_locked = 0;
 		if (--(s->lock_count) == 0) {
 			s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
 			s->socket.Vpp = 0;
 			s->socket.io_irq = 0;
 			s->ops->set_socket(s, &s->socket);
 		}
+	}
+	if (c->state & CONFIG_LOCKED) {
+		c->state &= ~CONFIG_LOCKED;
 		if (c->state & CONFIG_IO_REQ)
 			for (i = 0; i < MAX_IO_WIN; i++) {
-				if (s->io[i].NumPorts == 0)
+				if (!s->io[i].res)
 					continue;
 				s->io[i].Config--;
 				if (s->io[i].Config != 0)
@@ -487,12 +503,10 @@
 				io.map = i;
 				s->ops->set_io_map(s, &io);
 			}
-		c->state &= ~CONFIG_LOCKED;
 	}
 
 	return CS_SUCCESS;
 } /* pcmcia_release_configuration */
-EXPORT_SYMBOL(pcmcia_release_configuration);
 
 
 /** pcmcia_release_io
@@ -503,25 +517,23 @@
  * don't bother checking the port ranges against the current socket
  * values.
  */
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
+static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
 {
 	struct pcmcia_socket *s = p_dev->socket;
+	config_t *c = p_dev->function_config;
 
-	if (!(p_dev->state & CLIENT_IO_REQ))
+	if (!p_dev->_io )
 		return CS_BAD_HANDLE;
-	p_dev->state &= ~CLIENT_IO_REQ;
 
-	if (!(p_dev->state & CLIENT_STALE)) {
-		config_t *c = CONFIG(p_dev);
-		if (c->state & CONFIG_LOCKED)
-			return CS_CONFIGURATION_LOCKED;
-		if ((c->io.BasePort1 != req->BasePort1) ||
-		    (c->io.NumPorts1 != req->NumPorts1) ||
-		    (c->io.BasePort2 != req->BasePort2) ||
-		    (c->io.NumPorts2 != req->NumPorts2))
-			return CS_BAD_ARGS;
-		c->state &= ~CONFIG_IO_REQ;
-	}
+	p_dev->_io = 0;
+
+	if ((c->io.BasePort1 != req->BasePort1) ||
+	    (c->io.NumPorts1 != req->NumPorts1) ||
+	    (c->io.BasePort2 != req->BasePort2) ||
+	    (c->io.NumPorts2 != req->NumPorts2))
+		return CS_BAD_ARGS;
+
+	c->state &= ~CONFIG_IO_REQ;
 
 	release_io_space(s, req->BasePort1, req->NumPorts1);
 	if (req->NumPorts2)
@@ -529,28 +541,26 @@
 
 	return CS_SUCCESS;
 } /* pcmcia_release_io */
-EXPORT_SYMBOL(pcmcia_release_io);
 
 
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
+static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 {
 	struct pcmcia_socket *s = p_dev->socket;
-	if (!(p_dev->state & CLIENT_IRQ_REQ))
-		return CS_BAD_HANDLE;
-	p_dev->state &= ~CLIENT_IRQ_REQ;
+	config_t *c= p_dev->function_config;
 
-	if (!(p_dev->state & CLIENT_STALE)) {
-		config_t *c = CONFIG(p_dev);
-		if (c->state & CONFIG_LOCKED)
-			return CS_CONFIGURATION_LOCKED;
-		if (c->irq.Attributes != req->Attributes)
-			return CS_BAD_ATTRIBUTE;
-		if (s->irq.AssignedIRQ != req->AssignedIRQ)
-			return CS_BAD_IRQ;
-		if (--s->irq.Config == 0) {
-			c->state &= ~CONFIG_IRQ_REQ;
-			s->irq.AssignedIRQ = 0;
-		}
+	if (!p_dev->_irq)
+		return CS_BAD_HANDLE;
+	p_dev->_irq = 0;
+
+	if (c->state & CONFIG_LOCKED)
+		return CS_CONFIGURATION_LOCKED;
+	if (c->irq.Attributes != req->Attributes)
+		return CS_BAD_ATTRIBUTE;
+	if (s->irq.AssignedIRQ != req->AssignedIRQ)
+		return CS_BAD_IRQ;
+	if (--s->irq.Config == 0) {
+		c->state &= ~CONFIG_IRQ_REQ;
+		s->irq.AssignedIRQ = 0;
 	}
 
 	if (req->Attributes & IRQ_HANDLE_PRESENT) {
@@ -563,7 +573,6 @@
 
 	return CS_SUCCESS;
 } /* pcmcia_release_irq */
-EXPORT_SYMBOL(pcmcia_release_irq);
 
 
 int pcmcia_release_window(window_handle_t win)
@@ -573,7 +582,7 @@
 	if ((win == NULL) || (win->magic != WINDOW_MAGIC))
 		return CS_BAD_HANDLE;
 	s = win->sock;
-	if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
+	if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
 		return CS_BAD_HANDLE;
 
 	/* Shut down memory window */
@@ -587,7 +596,7 @@
 		kfree(win->ctl.res);
 		win->ctl.res = NULL;
 	}
-	win->handle->state &= ~CLIENT_WIN_REQ(win->index);
+	win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
 
 	win->magic = 0;
 
@@ -610,16 +619,12 @@
 
 	if (req->IntType & INT_CARDBUS)
 		return CS_UNSUPPORTED_MODE;
-	c = CONFIG(p_dev);
+	c = p_dev->function_config;
 	if (c->state & CONFIG_LOCKED)
 		return CS_CONFIGURATION_LOCKED;
 
 	/* Do power control.  We don't allow changes in Vcc. */
-	if (s->socket.Vcc != req->Vcc)
-		return CS_BAD_VCC;
-	if (req->Vpp1 != req->Vpp2)
-		return CS_BAD_VPP;
-	s->socket.Vpp = req->Vpp1;
+	s->socket.Vpp = req->Vpp;
 	if (s->ops->set_socket(s, &s->socket))
 		return CS_BAD_VPP;
 
@@ -643,7 +648,7 @@
 
 	/* Set up CIS configuration registers */
 	base = c->ConfigBase = req->ConfigBase;
-	c->Present = c->CardValues = req->Present;
+	c->CardValues = req->Present;
 	if (req->Present & PRESENT_COPY) {
 		c->Copy = req->Copy;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
@@ -690,10 +695,10 @@
 	if (c->state & CONFIG_IO_REQ) {
 		iomap.speed = io_speed;
 		for (i = 0; i < MAX_IO_WIN; i++)
-			if (s->io[i].NumPorts != 0) {
+			if (s->io[i].res) {
 				iomap.map = i;
 				iomap.flags = MAP_ACTIVE;
-				switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
+				switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
 				case IO_DATA_PATH_WIDTH_16:
 					iomap.flags |= MAP_16BIT; break;
 				case IO_DATA_PATH_WIDTH_AUTO:
@@ -701,15 +706,15 @@
 				default:
 					break;
 				}
-				iomap.start = s->io[i].BasePort;
-				iomap.stop = iomap.start + s->io[i].NumPorts - 1;
+				iomap.start = s->io[i].res->start;
+				iomap.stop = s->io[i].res->end;
 				s->ops->set_io_map(s, &iomap);
 				s->io[i].Config++;
 			}
 	}
 
 	c->state |= CONFIG_LOCKED;
-	p_dev->state |= CLIENT_CONFIG_LOCKED;
+	p_dev->_locked = 1;
 	return CS_SUCCESS;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -730,7 +735,7 @@
 
 	if (!req)
 		return CS_UNSUPPORTED_MODE;
-	c = CONFIG(p_dev);
+	c = p_dev->function_config;
 	if (c->state & CONFIG_LOCKED)
 		return CS_CONFIGURATION_LOCKED;
 	if (c->state & CONFIG_IO_REQ)
@@ -755,7 +760,7 @@
 
 	c->io = *req;
 	c->state |= CONFIG_IO_REQ;
-	p_dev->state |= CLIENT_IO_REQ;
+	p_dev->_io = 1;
 	return CS_SUCCESS;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
@@ -786,7 +791,7 @@
 
 	if (!(s->state & SOCKET_PRESENT))
 		return CS_NO_CARD;
-	c = CONFIG(p_dev);
+	c = p_dev->function_config;
 	if (c->state & CONFIG_LOCKED)
 		return CS_CONFIGURATION_LOCKED;
 	if (c->state & CONFIG_IRQ_REQ)
@@ -851,7 +856,7 @@
 	s->irq.Config++;
 
 	c->state |= CONFIG_IRQ_REQ;
-	p_dev->state |= CLIENT_IRQ_REQ;
+	p_dev->_irq = 1;
 
 #ifdef CONFIG_PCMCIA_PROBE
 	pcmcia_used_irq[irq]++;
@@ -911,7 +916,7 @@
 		if (!win->ctl.res)
 			return CS_IN_USE;
 	}
-	(*p_dev)->state |= CLIENT_WIN_REQ(w);
+	(*p_dev)->_win |= CLIENT_WIN_REQ(w);
 
 	/* Configure the socket controller */
 	win->ctl.map = w+1;
@@ -941,3 +946,12 @@
 	return CS_SUCCESS;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
+
+void pcmcia_disable_device(struct pcmcia_device *p_dev) {
+	pcmcia_release_configuration(p_dev);
+	pcmcia_release_io(p_dev, &p_dev->io);
+	pcmcia_release_irq(p_dev, &p_dev->irq);
+	if (&p_dev->win)
+		pcmcia_release_window(p_dev->win);
+}
+EXPORT_SYMBOL(pcmcia_disable_device);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index f2789af..16d1ea7 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index fd36473..b7b9e14 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -26,14 +26,6 @@
 #include "soc_common.h"
 
 #define	NO_KEEP_VS 0x0001
-
-/* PCMCIA to Scoop linkage
-
-   There is no easy way to link multiple scoop devices into one
-   single entity for the pxa2xx_pcmcia device so this structure
-   is used which is setup by the platform code
-*/
-struct scoop_pcmcia_config *platform_scoop_config;
 #define SCOOP_DEV platform_scoop_config->devs
 
 static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 5146093..81dfc2c 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -12,7 +12,6 @@
  * (C) 1999		David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 
@@ -22,6 +21,8 @@
 #include "cs_internal.h"
 
 
+#ifdef CONFIG_PCMCIA_IOCTL
+
 #ifdef CONFIG_PCMCIA_PROBE
 
 static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
@@ -98,6 +99,8 @@
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
 
+#endif
+
 int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
 	if (s->resource_ops->validate_mem)
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 5301ac6..0f8b157 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -12,7 +12,6 @@
  * (C) 1999		David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -61,7 +60,7 @@
 	unsigned int			rsrc_mem_probe;
 };
 
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
 #define MEM_PROBE_LOW	(1 << 0)
 #define MEM_PROBE_HIGH	(1 << 1)
 
@@ -484,7 +483,7 @@
 
 
 /*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex held!
  */
 static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 {
@@ -495,7 +494,7 @@
 	if (!probe_mem)
 		return 0;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 
 	if (s->features & SS_CAP_PAGE_REGS)
 		probe_mask = MEM_PROBE_HIGH;
@@ -507,7 +506,7 @@
 			s_data->rsrc_mem_probe |= probe_mask;
 	}
 
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -585,7 +584,7 @@
 	struct socket_data *s_data = s->resource_data;
 	int ret = -ENOMEM;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
 		unsigned long start = m->base;
 		unsigned long end = m->base + m->num - 1;
@@ -596,7 +595,7 @@
 		ret = adjust_resource(res, r_start, r_end - r_start + 1);
 		break;
 	}
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -630,7 +629,7 @@
 	data.offset = base & data.mask;
 	data.map = &s_data->io_db;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
 	if (s->cb_dev) {
 		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -639,7 +638,7 @@
 #endif
 		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
 					1, pcmcia_align, &data);
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 
 	if (ret != 0) {
 		kfree(res);
@@ -672,7 +671,7 @@
 			min = 0x100000UL + base;
 		}
 
-		down(&rsrc_sem);
+		mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
 		if (s->cb_dev) {
 			ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -682,7 +681,7 @@
 #endif
 			ret = allocate_resource(&iomem_resource, res, num, min,
 						max, 1, pcmcia_align, &data);
-		up(&rsrc_sem);
+		mutex_unlock(&rsrc_mutex);
 		if (ret == 0 || low)
 			break;
 		low = 1;
@@ -705,7 +704,7 @@
 	if (end < start)
 		return -EINVAL;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	switch (action) {
 	case ADD_MANAGED_RESOURCE:
 		ret = add_interval(&data->mem_db, start, size);
@@ -723,7 +722,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -741,7 +740,7 @@
 	if (end > IO_SPACE_LIMIT)
 		return -EINVAL;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	switch (action) {
 	case ADD_MANAGED_RESOURCE:
 		if (add_interval(&data->io_db, start, size) != 0) {
@@ -760,7 +759,7 @@
 		ret = -EINVAL;
 		break;
 	}
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -867,7 +866,7 @@
 	struct socket_data *data = s->resource_data;
 	struct resource_map *p, *q;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	for (p = data->mem_db.next; p != &data->mem_db; p = q) {
 		q = p->next;
 		kfree(p);
@@ -876,7 +875,7 @@
 		q = p->next;
 		kfree(p);
 	}
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 }
 
 
@@ -901,7 +900,7 @@
 	struct resource_map *p;
 	ssize_t ret = 0;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	data = s->resource_data;
 
 	for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -913,7 +912,7 @@
 				 ((unsigned long) p->base + p->num - 1));
 	}
 
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 	return (ret);
 }
 
@@ -953,7 +952,7 @@
 	struct resource_map *p;
 	ssize_t ret = 0;
 
-	down(&rsrc_sem);
+	mutex_lock(&rsrc_mutex);
 	data = s->resource_data;
 
 	for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -965,7 +964,7 @@
 				 ((unsigned long) p->base + p->num - 1));
 	}
 
-	up(&rsrc_sem);
+	mutex_unlock(&rsrc_mutex);
 	return (ret);
 }
 
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index 2b3c289..eb89928 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -5,7 +5,6 @@
  * Based off the Assabet.
  *
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 5ab1cde..c5d7476 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -12,7 +12,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/errno.h>
@@ -25,6 +24,7 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
@@ -183,7 +183,7 @@
 		s->resource_setup_done = 1;
 	spin_unlock_irqrestore(&s->lock, flags);
 
-	down(&s->skt_sem);
+	mutex_lock(&s->skt_mutex);
 	if ((s->callback) &&
 	    (s->state & SOCKET_PRESENT) &&
 	    !(s->state & SOCKET_CARDBUS)) {
@@ -192,7 +192,7 @@
 			module_put(s->callback->owner);
 		}
 	}
-	up(&s->skt_sem);
+	mutex_unlock(&s->skt_mutex);
 
 	return count;
 }
@@ -322,7 +322,7 @@
 	kfree(cis);
 
 	if (!ret) {
-		down(&s->skt_sem);
+		mutex_lock(&s->skt_mutex);
 		if ((s->callback) && (s->state & SOCKET_PRESENT) &&
 		    !(s->state & SOCKET_CARDBUS)) {
 			if (try_module_get(s->callback->owner)) {
@@ -330,7 +330,7 @@
 				module_put(s->callback->owner);
 			}
 		}
-		up(&s->skt_sem);
+		mutex_unlock(&s->skt_mutex);
 	}
 
 
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index d5b4ff7..7a3d1b8 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -30,7 +30,6 @@
 #ifndef _LINUX_TI113X_H
 #define _LINUX_TI113X_H
 
-#include <linux/config.h>
 
 /* Register definitions for TI 113X PCI-to-CardBus bridges */
 
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c4256aa..6fff109 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -479,7 +479,7 @@
 int pnp_start_dev(struct pnp_dev *dev)
 {
 	if (!pnp_can_write(dev)) {
-		pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+		pnp_info("Device %s does not support activation.", dev->dev.bus_id);
 		return -EINVAL;
 	}
 
@@ -503,7 +503,7 @@
 int pnp_stop_dev(struct pnp_dev *dev)
 {
 	if (!pnp_can_disable(dev)) {
-		pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+		pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
 		return -EINVAL;
 	}
 	if (dev->protocol->disable(dev)<0) {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 929dd80..65d090d 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -147,6 +147,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc-sa1100.
 
+config RTC_DRV_VR41XX
+	tristate "NEC VR41XX"
+	depends on RTC_CLASS && CPU_VR41XX
+	help
+	  If you say Y here you will get access to the real time clock
+	  built into your NEC VR41XX CPU.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rtc-vr41xx.
+
 config RTC_DRV_TEST
 	tristate "Test driver/device"
 	depends on RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 8d4c7fe..a9ca0f1 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,3 +19,4 @@
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_SA1100)	+= rtc-sa1100.o
+obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 8533936..413c7d5 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -96,6 +96,8 @@
 	idr_remove(&rtc_idr, id);
 
 exit:
+	dev_err(dev, "rtc core: unable to register %s, err = %d\n",
+			name, err);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(rtc_device_register);
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 358695a..9be81fd 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -1,6 +1,8 @@
 /*
  * An rtc/i2c driver for the Dallas DS1672
- * Copyright 2005 Alessandro Zummo
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
  *
  * 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
@@ -11,7 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/rtc.h>
 
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
 
 /* Addresses to scan: none. This chip cannot be detected. */
 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
@@ -25,6 +27,7 @@
 #define DS1672_REG_CONTROL	4
 #define DS1672_REG_TRICKLE	5
 
+#define DS1672_REG_CONTROL_EOSC	0x80
 
 /* Prototypes */
 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
@@ -53,8 +56,7 @@
 
 	dev_dbg(&client->dev,
 		"%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
-		__FUNCTION__,
-		buf[0], buf[1], buf[2], buf[3]);
+		__FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
 
 	time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
 
@@ -62,8 +64,7 @@
 
 	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
-		__FUNCTION__,
-		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		__FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
 	return 0;
@@ -72,16 +73,17 @@
 static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
 {
 	int xfer;
-	unsigned char buf[5];
+	unsigned char buf[6];
 
 	buf[0] = DS1672_REG_CNT_BASE;
 	buf[1] = secs & 0x000000FF;
 	buf[2] = (secs & 0x0000FF00) >> 8;
 	buf[3] = (secs & 0x00FF0000) >> 16;
 	buf[4] = (secs & 0xFF000000) >> 24;
+	buf[5] = 0;	/* set control reg to enable counting */
 
-	xfer = i2c_master_send(client, buf, 5);
-	if (xfer != 5) {
+	xfer = i2c_master_send(client, buf, 6);
+	if (xfer != 6) {
 		dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
 		return -EIO;
 	}
@@ -120,6 +122,40 @@
 	return ds1672_set_mmss(to_i2c_client(dev), secs);
 }
 
+static int ds1672_get_control(struct i2c_client *client, u8 *status)
+{
+	unsigned char addr = DS1672_REG_CONTROL;
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 1, &addr },		/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, status },	/* read control */
+	};
+
+	/* read control register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 control;
+	int err;
+
+	err = ds1672_get_control(client, &control);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
+					? "disabled" : "enabled");
+}
+static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
+
 static struct rtc_class_ops ds1672_rtc_ops = {
 	.read_time	= ds1672_rtc_read_time,
 	.set_time	= ds1672_rtc_set_time,
@@ -128,7 +164,6 @@
 
 static int ds1672_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, ds1672_probe);
 }
 
@@ -137,8 +172,6 @@
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
  	if (rtc)
 		rtc_device_unregister(rtc);
 
@@ -162,6 +195,7 @@
 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
 {
 	int err = 0;
+	u8 control;
 	struct i2c_client *client;
 	struct rtc_device *rtc;
 
@@ -195,13 +229,23 @@
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
 	i2c_set_clientdata(client, rtc);
 
+	/* read control register */
+	err = ds1672_get_control(client, &control);
+	if (err)
+		goto exit_detach;
+
+	if (control & DS1672_REG_CONTROL_EOSC)
+		dev_warn(&client->dev, "Oscillator not enabled. "
+					"Set time to enable.\n");
+
+	/* Register sysfs hooks */
+	device_create_file(&client->dev, &dev_attr_control);
+
 	return 0;
 
 exit_detach:
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 0dd80ea..e1a1169 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -67,7 +67,6 @@
 
 	ep93xx_get_swcomp(dev, &preload, &delete);
 
-	seq_printf(seq, "24hr\t\t: yes\n");
 	seq_printf(seq, "preload\t\t: %d\n", preload);
 	seq_printf(seq, "delete\t\t: %d\n", delete);
 
@@ -110,7 +109,6 @@
 				&dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc)) {
-		dev_err(&dev->dev, "unable to register\n");
 		return PTR_ERR(rtc);
 	}
 
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index db445c8..f6e7ee0 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -23,7 +23,7 @@
 #define M48T86_REG_SECALRM	0x01
 #define M48T86_REG_MIN		0x02
 #define M48T86_REG_MINALRM	0x03
-#define M48T86_REG_HOUR	0x04
+#define M48T86_REG_HOUR		0x04
 #define M48T86_REG_HOURALRM	0x05
 #define M48T86_REG_DOW		0x06 /* 1 = sunday */
 #define M48T86_REG_DOM		0x07
@@ -127,9 +127,6 @@
 
 	reg = ops->readb(M48T86_REG_B);
 
-	seq_printf(seq, "24hr\t\t: %s\n",
-		 (reg & M48T86_REG_B_H24) ? "yes" : "no");
-
 	seq_printf(seq, "mode\t\t: %s\n",
 		 (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
 
@@ -154,10 +151,8 @@
 	struct rtc_device *rtc = rtc_device_register("m48t86",
 				&dev->dev, &m48t86_rtc_ops, THIS_MODULE);
 
-	if (IS_ERR(rtc)) {
-		dev_err(&dev->dev, "unable to register\n");
+	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
-	}
 
 	platform_set_drvdata(dev, rtc);
 
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index d857d45..ba9a583 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -227,14 +227,7 @@
 	return pcf8563_set_datetime(to_i2c_client(dev), tm);
 }
 
-static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq)
-{
-	seq_printf(seq, "24hr\t\t: yes\n");
-	return 0;
-}
-
 static struct rtc_class_ops pcf8563_rtc_ops = {
-	.proc		= pcf8563_rtc_proc,
 	.read_time	= pcf8563_rtc_read_time,
 	.set_time	= pcf8563_rtc_set_time,
 };
@@ -297,8 +290,6 @@
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
@@ -321,8 +312,6 @@
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
 	if (rtc)
 		rtc_device_unregister(rtc);
 
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index 90b8a97..cef5f5a 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -71,6 +71,8 @@
 				alrm.pending ? "yes" : "no");
 	}
 
+	seq_printf(seq, "24hr\t\t: yes\n");
+
 	if (ops->proc)
 		ops->proc(class_dev->dev, seq);
 
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 396c868..7553d79 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -151,9 +151,8 @@
 {
 	int err, osc, trim;
 
-	seq_printf(seq, "24hr\t\t: yes\n");
-
-	if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) {
+	err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim);
+	if (err == 0) {
 		seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
 		seq_printf(seq, "trim\t: %d\n", trim);
 	}
@@ -170,30 +169,31 @@
 static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int trim;
+	int err, trim;
 
-	if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0)
-		return sprintf(buf, "0x%2x\n", trim);
+	err = rs5c372_get_trim(to_i2c_client(dev), NULL, &trim);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "0x%2x\n", trim);
 }
 static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
 
 static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int osc;
+	int err, osc;
 
-	if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0)
-		return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+	err = rs5c372_get_trim(to_i2c_client(dev), &osc, NULL);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
 }
 static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
 
 static int rs5c372_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, rs5c372_probe);
 }
 
@@ -233,8 +233,6 @@
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
@@ -260,8 +258,6 @@
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
 	if (rtc)
 		rtc_device_unregister(rtc);
 
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 83b2bb4..a23ec54 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -160,19 +160,19 @@
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT,
 				"rtc 1Hz", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
 		goto fail_ui;
 	}
 	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT,
 				"rtc Alrm", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
 	ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT,
 				"rtc timer", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
 		goto fail_pi;
 	}
 	return 0;
@@ -332,7 +332,7 @@
 	 */
 	if (RTTR == 0) {
 		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
+		dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
 		/* The current RTC value probably doesn't make sense either */
 		RCNR = 0;
 	}
@@ -340,15 +340,11 @@
 	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
 				THIS_MODULE);
 
-	if (IS_ERR(rtc)) {
-		dev_err(&pdev->dev, "Unable to register the RTC device\n");
+	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
-	}
 
 	platform_set_drvdata(pdev, rtc);
 
-	dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n");
-
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 43d1074..e1f7e8e 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -49,7 +49,6 @@
 {
 	struct platform_device *plat_dev = to_platform_device(dev);
 
-	seq_printf(seq, "24hr\t\t: yes\n");
 	seq_printf(seq, "test\t\t: yes\n");
 	seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
 
@@ -120,8 +119,6 @@
 						&test_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&plat_dev->dev,
-			"unable to register the class device\n");
 		return err;
 	}
 	device_create_file(&plat_dev->dev, &dev_attr_irq);
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
new file mode 100644
index 0000000..4d49fd5
--- /dev/null
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -0,0 +1,471 @@
+/*
+ *  Driver for NEC VR4100 series Real Time Clock unit.
+ *
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/div64.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
+MODULE_LICENSE("GPL");
+
+#define RTC1_TYPE1_START	0x0b0000c0UL
+#define RTC1_TYPE1_END		0x0b0000dfUL
+#define RTC2_TYPE1_START	0x0b0001c0UL
+#define RTC2_TYPE1_END		0x0b0001dfUL
+
+#define RTC1_TYPE2_START	0x0f000100UL
+#define RTC1_TYPE2_END		0x0f00011fUL
+#define RTC2_TYPE2_START	0x0f000120UL
+#define RTC2_TYPE2_END		0x0f00013fUL
+
+#define RTC1_SIZE		0x20
+#define RTC2_SIZE		0x20
+
+/* RTC 1 registers */
+#define ETIMELREG		0x00
+#define ETIMEMREG		0x02
+#define ETIMEHREG		0x04
+/* RFU */
+#define ECMPLREG		0x08
+#define ECMPMREG		0x0a
+#define ECMPHREG		0x0c
+/* RFU */
+#define RTCL1LREG		0x10
+#define RTCL1HREG		0x12
+#define RTCL1CNTLREG		0x14
+#define RTCL1CNTHREG		0x16
+#define RTCL2LREG		0x18
+#define RTCL2HREG		0x1a
+#define RTCL2CNTLREG		0x1c
+#define RTCL2CNTHREG		0x1e
+
+/* RTC 2 registers */
+#define TCLKLREG		0x00
+#define TCLKHREG		0x02
+#define TCLKCNTLREG		0x04
+#define TCLKCNTHREG		0x06
+/* RFU */
+#define RTCINTREG		0x1e
+ #define TCLOCK_INT		0x08
+ #define RTCLONG2_INT		0x04
+ #define RTCLONG1_INT		0x02
+ #define ELAPSEDTIME_INT	0x01
+
+#define RTC_FREQUENCY		32768
+#define MAX_PERIODIC_RATE	6553
+#define MAX_USER_PERIODIC_RATE	64
+
+static void __iomem *rtc1_base;
+static void __iomem *rtc2_base;
+
+#define rtc1_read(offset)		readw(rtc1_base + (offset))
+#define rtc1_write(offset, value)	writew((value), rtc1_base + (offset))
+
+#define rtc2_read(offset)		readw(rtc2_base + (offset))
+#define rtc2_write(offset, value)	writew((value), rtc2_base + (offset))
+
+static unsigned long epoch = 1970;	/* Jan 1 1970 00:00:00 */
+
+static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+static char rtc_name[] = "RTC";
+static unsigned long periodic_frequency;
+static unsigned long periodic_count;
+
+struct resource rtc_resource[2] = {
+	{	.name	= rtc_name,
+		.flags	= IORESOURCE_MEM,	},
+	{	.name	= rtc_name,
+		.flags	= IORESOURCE_MEM,	},
+};
+
+static inline unsigned long read_elapsed_second(void)
+{
+
+	unsigned long first_low, first_mid, first_high;
+
+	unsigned long second_low, second_mid, second_high;
+
+	do {
+		first_low = rtc1_read(ETIMELREG);
+		first_mid = rtc1_read(ETIMEMREG);
+		first_high = rtc1_read(ETIMEHREG);
+		second_low = rtc1_read(ETIMELREG);
+		second_mid = rtc1_read(ETIMEMREG);
+		second_high = rtc1_read(ETIMEHREG);
+	} while (first_low != second_low || first_mid != second_mid ||
+	         first_high != second_high);
+
+	return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
+}
+
+static inline void write_elapsed_second(unsigned long sec)
+{
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
+	rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
+	rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
+
+	spin_unlock_irq(&rtc_lock);
+}
+
+static void vr41xx_rtc_release(struct device *dev)
+{
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, 0);
+	rtc1_write(ECMPMREG, 0);
+	rtc1_write(ECMPHREG, 0);
+	rtc1_write(RTCL1LREG, 0);
+	rtc1_write(RTCL1HREG, 0);
+
+	spin_unlock_irq(&rtc_lock);
+
+	disable_irq(ELAPSEDTIME_IRQ);
+	disable_irq(RTCLONG1_IRQ);
+}
+
+static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
+{
+	unsigned long epoch_sec, elapsed_sec;
+
+	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+	elapsed_sec = read_elapsed_second();
+
+	rtc_time_to_tm(epoch_sec + elapsed_sec, time);
+
+	return 0;
+}
+
+static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
+{
+	unsigned long epoch_sec, current_sec;
+
+	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+	current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+	                     time->tm_hour, time->tm_min, time->tm_sec);
+
+	write_elapsed_second(current_sec - epoch_sec);
+
+	return 0;
+}
+
+static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	unsigned long low, mid, high;
+	struct rtc_time *time = &wkalrm->time;
+
+	spin_lock_irq(&rtc_lock);
+
+	low = rtc1_read(ECMPLREG);
+	mid = rtc1_read(ECMPMREG);
+	high = rtc1_read(ECMPHREG);
+
+	spin_unlock_irq(&rtc_lock);
+
+	rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
+
+	return 0;
+}
+
+static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	unsigned long alarm_sec;
+	struct rtc_time *time = &wkalrm->time;
+
+	alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+	                   time->tm_hour, time->tm_min, time->tm_sec);
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
+	rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
+	rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
+
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	unsigned long count;
+
+	switch (cmd) {
+	case RTC_AIE_ON:
+		enable_irq(ELAPSEDTIME_IRQ);
+		break;
+	case RTC_AIE_OFF:
+		disable_irq(ELAPSEDTIME_IRQ);
+		break;
+	case RTC_PIE_ON:
+		enable_irq(RTCLONG1_IRQ);
+		break;
+	case RTC_PIE_OFF:
+		disable_irq(RTCLONG1_IRQ);
+		break;
+	case RTC_IRQP_READ:
+		return put_user(periodic_frequency, (unsigned long __user *)arg);
+		break;
+	case RTC_IRQP_SET:
+		if (arg > MAX_PERIODIC_RATE)
+			return -EINVAL;
+
+		if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
+			return -EACCES;
+
+		periodic_frequency = arg;
+
+		count = RTC_FREQUENCY;
+		do_div(count, arg);
+
+		periodic_count = count;
+
+		spin_lock_irq(&rtc_lock);
+
+		rtc1_write(RTCL1LREG, count);
+		rtc1_write(RTCL1HREG, count >> 16);
+
+		spin_unlock_irq(&rtc_lock);
+		break;
+	case RTC_EPOCH_READ:
+		return put_user(epoch, (unsigned long __user *)arg);
+	case RTC_EPOCH_SET:
+		/* Doesn't support before 1900 */
+		if (arg < 1900)
+			return -EINVAL;
+
+		if (capable(CAP_SYS_TIME) == 0)
+			return -EACCES;
+
+		epoch = arg;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
+
+	rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+	unsigned long count = periodic_count;
+
+	rtc2_write(RTCINTREG, RTCLONG1_INT);
+
+	rtc1_write(RTCL1LREG, count);
+	rtc1_write(RTCL1HREG, count >> 16);
+
+	rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
+
+	return IRQ_HANDLED;
+}
+
+static struct rtc_class_ops vr41xx_rtc_ops = {
+	.release	= vr41xx_rtc_release,
+	.ioctl		= vr41xx_rtc_ioctl,
+	.read_time	= vr41xx_rtc_read_time,
+	.set_time	= vr41xx_rtc_set_time,
+	.read_alarm	= vr41xx_rtc_read_alarm,
+	.set_alarm	= vr41xx_rtc_set_alarm,
+};
+
+static int __devinit rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	unsigned int irq;
+	int retval;
+
+	if (pdev->num_resources != 2)
+		return -EBUSY;
+
+	rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
+	if (rtc1_base == NULL)
+		return -EBUSY;
+
+	rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
+	if (rtc2_base == NULL) {
+		iounmap(rtc1_base);
+		rtc1_base = NULL;
+		return -EBUSY;
+	}
+
+	rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		iounmap(rtc1_base);
+		iounmap(rtc2_base);
+		rtc1_base = NULL;
+		rtc2_base = NULL;
+		return PTR_ERR(rtc);
+	}
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, 0);
+	rtc1_write(ECMPMREG, 0);
+	rtc1_write(ECMPHREG, 0);
+	rtc1_write(RTCL1LREG, 0);
+	rtc1_write(RTCL1HREG, 0);
+
+	spin_unlock_irq(&rtc_lock);
+
+	irq = ELAPSEDTIME_IRQ;
+	retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
+	                     "elapsed_time", pdev);
+	if (retval == 0) {
+		irq = RTCLONG1_IRQ;
+		retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
+		                     "rtclong1", pdev);
+	}
+
+	if (retval < 0) {
+		printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
+		rtc_device_unregister(rtc);
+		if (irq == RTCLONG1_IRQ)
+			free_irq(ELAPSEDTIME_IRQ, NULL);
+		iounmap(rtc1_base);
+		iounmap(rtc2_base);
+		rtc1_base = NULL;
+		rtc2_base = NULL;
+		return retval;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	disable_irq(ELAPSEDTIME_IRQ);
+	disable_irq(RTCLONG1_IRQ);
+
+	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
+
+	return 0;
+}
+
+static int __devexit rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+
+	rtc = platform_get_drvdata(pdev);
+	if (rtc != NULL)
+		rtc_device_unregister(rtc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_irq(ELAPSEDTIME_IRQ, NULL);
+	free_irq(RTCLONG1_IRQ, NULL);
+	if (rtc1_base != NULL)
+		iounmap(rtc1_base);
+	if (rtc2_base != NULL)
+		iounmap(rtc2_base);
+
+	return 0;
+}
+
+static struct platform_device *rtc_platform_device;
+
+static struct platform_driver rtc_platform_driver = {
+	.probe		= rtc_probe,
+	.remove		= __devexit_p(rtc_remove),
+	.driver		= {
+		.name	= rtc_name,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init vr41xx_rtc_init(void)
+{
+	int retval;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		rtc_resource[0].start = RTC1_TYPE1_START;
+		rtc_resource[0].end = RTC1_TYPE1_END;
+		rtc_resource[1].start = RTC2_TYPE1_START;
+		rtc_resource[1].end = RTC2_TYPE1_END;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		rtc_resource[0].start = RTC1_TYPE2_START;
+		rtc_resource[0].end = RTC1_TYPE2_END;
+		rtc_resource[1].start = RTC2_TYPE2_START;
+		rtc_resource[1].end = RTC2_TYPE2_END;
+		break;
+	default:
+		return -ENODEV;
+		break;
+	}
+
+	rtc_platform_device = platform_device_alloc("RTC", -1);
+	if (rtc_platform_device == NULL)
+		return -ENOMEM;
+
+	retval = platform_device_add_resources(rtc_platform_device,
+				rtc_resource, ARRAY_SIZE(rtc_resource));
+
+	if (retval == 0)
+		retval = platform_device_add(rtc_platform_device);
+
+	if (retval < 0) {
+		platform_device_put(rtc_platform_device);
+		return retval;
+	}
+
+	retval = platform_driver_register(&rtc_platform_driver);
+	if (retval < 0)
+		platform_device_unregister(rtc_platform_device);
+
+	return retval;
+}
+
+static void __exit vr41xx_rtc_exit(void)
+{
+	platform_driver_unregister(&rtc_platform_driver);
+	platform_device_unregister(rtc_platform_device);
+}
+
+module_init(vr41xx_rtc_init);
+module_exit(vr41xx_rtc_exit);
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 621d17a..788b6d1 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -19,7 +19,7 @@
 #include <linux/rtc.h>
 #include <linux/delay.h>
 
-#define DRV_VERSION "1.0.6"
+#define DRV_VERSION "1.0.7"
 
 /* Addresses to scan: none. This chip is located at
  * 0x6f and uses a two bytes register addressing.
@@ -451,8 +451,6 @@
 {
 	int err, dtrim, atrim;
 
-	seq_printf(seq, "24hr\t\t: yes\n");
-
 	if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
 		seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
 
@@ -473,30 +471,31 @@
 static ssize_t x1205_sysfs_show_atrim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int atrim;
+	int err, atrim;
 
-	if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0)
-		return sprintf(buf, "%d.%02d pF\n",
-			atrim / 1000, atrim % 1000);
-	return 0;
+	err = x1205_get_atrim(to_i2c_client(dev), &atrim);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
 }
 static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
 
 static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int dtrim;
+	int err, dtrim;
 
-	if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0)
-		return sprintf(buf, "%d ppm\n", dtrim);
+	err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "%d ppm\n", dtrim);
 }
 static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
 
 static int x1205_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, x1205_probe);
 }
 
@@ -545,8 +544,6 @@
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
@@ -585,8 +582,6 @@
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
  	if (rtc)
 		rtc_device_unregister(rtc);
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 0a9f12c..cfb1fff 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -315,6 +315,11 @@
 		rc = dasd_state_basic_to_ready(device);
 
 	if (!rc &&
+	    device->state == DASD_STATE_UNFMT &&
+	    device->target > DASD_STATE_UNFMT)
+		rc = -EPERM;
+
+	if (!rc &&
 	    device->state == DASD_STATE_READY &&
 	    device->target >= DASD_STATE_ONLINE)
 		rc = dasd_state_ready_to_online(device);
@@ -1257,25 +1262,28 @@
 	if (list_empty(&device->ccw_queue))
 		return;
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
-        /* check FAILFAST */
+	if (cqr->status != DASD_CQR_QUEUED)
+		return;
+	/* Non-temporary stop condition will trigger fail fast */
 	if (device->stopped & ~DASD_STOPPED_PENDING &&
 	    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
 	    (!dasd_eer_enabled(device))) {
 		cqr->status = DASD_CQR_FAILED;
 		dasd_schedule_bh(device);
+		return;
 	}
-	if ((cqr->status == DASD_CQR_QUEUED) &&
-	    (!device->stopped)) {
-		/* try to start the first I/O that can be started */
-		rc = device->discipline->start_IO(cqr);
-		if (rc == 0)
-			dasd_set_timer(device, cqr->expires);
-		else if (rc == -EACCES) {
-			dasd_schedule_bh(device);
-		} else
-			/* Hmpf, try again in 1/2 sec */
-			dasd_set_timer(device, 50);
-	}
+	/* Don't try to start requests if device is stopped */
+	if (device->stopped)
+		return;
+
+	rc = device->discipline->start_IO(cqr);
+	if (rc == 0)
+		dasd_set_timer(device, cqr->expires);
+	else if (rc == -EACCES) {
+		dasd_schedule_bh(device);
+	} else
+		/* Hmpf, try again in 1/2 sec */
+		dasd_set_timer(device, 50);
 }
 
 /*
@@ -1968,7 +1976,7 @@
 dasd_generic_set_offline (struct ccw_device *cdev)
 {
 	struct dasd_device *device;
-	int max_count;
+	int max_count, open_count;
 
 	device = dasd_device_from_cdev(cdev);
 	if (IS_ERR(device))
@@ -1985,10 +1993,16 @@
 	 * in the other openers.
 	 */
 	max_count = device->bdev ? 0 : -1;
-	if (atomic_read(&device->open_count) > max_count) {
-		printk (KERN_WARNING "Can't offline dasd device with open"
-			" count = %i.\n",
-			atomic_read(&device->open_count));
+	open_count = (int) atomic_read(&device->open_count);
+	if (open_count > max_count) {
+		if (open_count > 0)
+			printk (KERN_WARNING "Can't offline dasd device with "
+				"open count = %i.\n",
+				open_count);
+		else
+			printk (KERN_WARNING "%s",
+				"Can't offline dasd device due to internal "
+				"use\n");
 		clear_bit(DASD_FLAG_OFFLINE, &device->flags);
 		dasd_put_device(device);
 		return -EBUSY;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index c1c6f13..216bc4f 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -45,6 +45,7 @@
         unsigned int devindex;
         unsigned short features;
 	struct dasd_device *device;
+	struct dasd_uid uid;
 };
 
 /*
@@ -716,6 +717,68 @@
 
 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
 
+static ssize_t
+dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct dasd_devmap *devmap;
+	int alias;
+
+	devmap = dasd_find_busid(dev->bus_id);
+	spin_lock(&dasd_devmap_lock);
+	if (!IS_ERR(devmap))
+		alias = devmap->uid.alias;
+	else
+		alias = 0;
+	spin_unlock(&dasd_devmap_lock);
+
+	return sprintf(buf, alias ? "1\n" : "0\n");
+}
+
+static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
+
+static ssize_t
+dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct dasd_devmap *devmap;
+	char *vendor;
+
+	devmap = dasd_find_busid(dev->bus_id);
+	spin_lock(&dasd_devmap_lock);
+	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+		vendor = devmap->uid.vendor;
+	else
+		vendor = "";
+	spin_unlock(&dasd_devmap_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+}
+
+static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
+
+#define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
+		     /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
+
+static ssize_t
+dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct dasd_devmap *devmap;
+	char uid[UID_STRLEN];
+
+	devmap = dasd_find_busid(dev->bus_id);
+	spin_lock(&dasd_devmap_lock);
+	if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
+		snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
+			 devmap->uid.vendor, devmap->uid.serial,
+			 devmap->uid.ssid, devmap->uid.unit_addr);
+	else
+		uid[0] = 0;
+	spin_unlock(&dasd_devmap_lock);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", uid);
+}
+
+static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
+
 /*
  * extended error-reporting
  */
@@ -759,6 +822,9 @@
 static struct attribute * dasd_attrs[] = {
 	&dev_attr_readonly.attr,
 	&dev_attr_discipline.attr,
+	&dev_attr_alias.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_uid.attr,
 	&dev_attr_use_diag.attr,
 	&dev_attr_eer_enabled.attr,
 	NULL,
@@ -768,6 +834,42 @@
 	.attrs = dasd_attrs,
 };
 
+
+/*
+ * Return copy of the device unique identifier.
+ */
+int
+dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+	struct dasd_devmap *devmap;
+
+	devmap = dasd_find_busid(cdev->dev.bus_id);
+	if (IS_ERR(devmap))
+		return PTR_ERR(devmap);
+	spin_lock(&dasd_devmap_lock);
+	*uid = devmap->uid;
+	spin_unlock(&dasd_devmap_lock);
+	return 0;
+}
+
+/*
+ * Register the given device unique identifier into devmap struct.
+ */
+int
+dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
+{
+	struct dasd_devmap *devmap;
+
+	devmap = dasd_find_busid(cdev->dev.bus_id);
+	if (IS_ERR(devmap))
+		return PTR_ERR(devmap);
+	spin_lock(&dasd_devmap_lock);
+	devmap->uid = *uid;
+	spin_unlock(&dasd_devmap_lock);
+	return 0;
+}
+EXPORT_SYMBOL(dasd_set_uid);
+
 /*
  * Return value of the specified feature.
  */
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ee09ef3..7d5a6ce 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -446,6 +446,39 @@
 	return LABEL_SIZE;
 }
 
+/*
+ * Generate device unique id that specifies the physical device.
+ */
+static int
+dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
+{
+	struct dasd_eckd_private *private;
+	struct dasd_eckd_confdata *confdata;
+
+	private = (struct dasd_eckd_private *) device->private;
+	if (!private)
+		return -ENODEV;
+	confdata = &private->conf_data;
+	if (!confdata)
+		return -ENODEV;
+
+	memset(uid, 0, sizeof(struct dasd_uid));
+	strncpy(uid->vendor, confdata->ned1.HDA_manufacturer,
+		sizeof(uid->vendor) - 1);
+	EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
+	strncpy(uid->serial, confdata->ned1.HDA_location,
+		sizeof(uid->serial) - 1);
+	EBCASC(uid->serial, sizeof(uid->serial) - 1);
+	uid->ssid = confdata->neq.subsystemID;
+	if (confdata->ned2.sneq.flags == 0x40) {
+		uid->alias = 1;
+		uid->unit_addr = confdata->ned2.sneq.base_unit_addr;
+	} else
+		uid->unit_addr = confdata->ned1.unit_addr;
+
+	return 0;
+}
+
 static int
 dasd_eckd_read_conf(struct dasd_device *device)
 {
@@ -507,11 +540,15 @@
 	return 0;
 }
 
-
+/*
+ * Check device characteristics.
+ * If the device is accessible using ECKD discipline, the device is enabled.
+ */
 static int
 dasd_eckd_check_characteristics(struct dasd_device *device)
 {
 	struct dasd_eckd_private *private;
+	struct dasd_uid uid;
 	void *rdc_data;
 	int rc;
 
@@ -536,6 +573,7 @@
 
 	/* Read Device Characteristics */
 	rdc_data = (void *) &(private->rdc_data);
+	memset(rdc_data, 0, sizeof(rdc_data));
 	rc = read_dev_chars(device->cdev, &rdc_data, 64);
 	if (rc) {
 		DEV_MESSAGE(KERN_WARNING, device,
@@ -556,8 +594,17 @@
 
 	/* Read Configuration Data */
 	rc = dasd_eckd_read_conf (device);
-	return rc;
+	if (rc)
+		return rc;
 
+	/* Generate device unique id and register in devmap */
+	rc = dasd_eckd_generate_uid(device, &uid);
+	if (rc)
+		return rc;
+
+	rc = dasd_set_uid(device->cdev, &uid);
+
+	return rc;
 }
 
 static struct dasd_ccw_req *
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index ad8524b..d5734e9 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -228,26 +228,36 @@
 		unsigned char HDA_manufacturer[3];
 		unsigned char HDA_location[2];
 		unsigned char HDA_seqno[12];
-		__u16 ID;
+		__u8 ID;
+		__u8 unit_addr;
 	} __attribute__ ((packed)) ned1;
-	struct {
+	union {
 		struct {
-			unsigned char identifier:2;
-			unsigned char token_id:1;
-			unsigned char sno_valid:1;
-			unsigned char subst_sno:1;
-			unsigned char recNED:1;
-			unsigned char emuNED:1;
-			unsigned char reserved:1;
-		} __attribute__ ((packed)) flags;
-		__u8 descriptor;
-		__u8 reserved[2];
-		unsigned char dev_type[6];
-		unsigned char dev_model[3];
-		unsigned char DASD_manufacturer[3];
-		unsigned char DASD_location[2];
-		unsigned char DASD_seqno[12];
-		__u16 ID;
+			struct {
+				unsigned char identifier:2;
+				unsigned char token_id:1;
+				unsigned char sno_valid:1;
+				unsigned char subst_sno:1;
+				unsigned char recNED:1;
+				unsigned char emuNED:1;
+				unsigned char reserved:1;
+			} __attribute__ ((packed)) flags;
+			__u8 descriptor;
+			__u8 reserved[2];
+			unsigned char dev_type[6];
+			unsigned char dev_model[3];
+			unsigned char DASD_manufacturer[3];
+			unsigned char DASD_location[2];
+			unsigned char DASD_seqno[12];
+			__u16 ID;
+		} __attribute__ ((packed)) ned;
+		struct {
+			unsigned char flags;            /* byte  0    */
+			unsigned char res2[7];          /* byte  1- 7 */
+			unsigned char sua_flags;	/* byte  8    */
+			__u8 base_unit_addr;            /* byte  9    */
+			unsigned char res3[22];	        /* byte 10-31 */
+		} __attribute__ ((packed)) sneq;
 	} __attribute__ ((packed)) ned2;
 	struct {
 		struct {
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 8fd71ab..b842377 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -32,9 +32,8 @@
 	int size;
 
 	/* Sanity checks */
-	if ( magic == NULL || datasize > PAGE_SIZE ||
-	     (cplength*sizeof(struct ccw1)) > PAGE_SIZE)
-		BUG();
+	BUG_ON( magic == NULL || datasize > PAGE_SIZE ||
+	     (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
 
 	size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
 	if (cplength > 0)
@@ -125,8 +124,7 @@
 	struct dasd_device *device;
 	int success;
 
-	if (cqr->refers == NULL || cqr->function == NULL)
-		BUG();
+	BUG_ON(cqr->refers == NULL || cqr->function == NULL);
 
 	device = cqr->device;
 	success = cqr->status == DASD_CQR_DONE;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 4293ba8..d4b13e3 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -268,6 +268,16 @@
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
 
+/*
+ * Unique identifier for dasd device.
+ */
+struct dasd_uid {
+	__u8 alias;
+	char vendor[4];
+	char serial[15];
+	__u16 ssid;
+	__u8 unit_addr;
+};
 
 /*
  * Notification numbers for extended error reporting notifications:
@@ -516,6 +526,8 @@
 struct dasd_device *dasd_create_device(struct ccw_device *);
 void dasd_delete_device(struct dasd_device *);
 
+int dasd_get_uid(struct ccw_device *, struct dasd_uid *);
+int dasd_set_uid(struct ccw_device *, struct dasd_uid *);
 int dasd_get_feature(struct ccw_device *, int);
 int dasd_set_feature(struct ccw_device *, int, int);
 
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 1aa3c26..ad23aed 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -294,23 +294,40 @@
 #endif				/* CONFIG_DASD_PROFILE */
 }
 
+/*
+ * Create dasd proc-fs entries.
+ * In case creation failed, cleanup and return -ENOENT.
+ */
 int
 dasd_proc_init(void)
 {
 	dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+	if (!dasd_proc_root_entry)
+		goto out_nodasd;
 	dasd_proc_root_entry->owner = THIS_MODULE;
 	dasd_devices_entry = create_proc_entry("devices",
 					       S_IFREG | S_IRUGO | S_IWUSR,
 					       dasd_proc_root_entry);
+	if (!dasd_devices_entry)
+		goto out_nodevices;
 	dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
 	dasd_devices_entry->owner = THIS_MODULE;
 	dasd_statistics_entry = create_proc_entry("statistics",
 						  S_IFREG | S_IRUGO | S_IWUSR,
 						  dasd_proc_root_entry);
+	if (!dasd_statistics_entry)
+		goto out_nostatistics;
 	dasd_statistics_entry->read_proc = dasd_statistics_read;
 	dasd_statistics_entry->write_proc = dasd_statistics_write;
 	dasd_statistics_entry->owner = THIS_MODULE;
 	return 0;
+
+ out_nostatistics:
+	remove_proc_entry("devices", dasd_proc_root_entry);
+ out_nodevices:
+	remove_proc_entry("dasd", &proc_root);
+ out_nodasd:
+	return -ENOENT;
 }
 
 void
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 6badd84..d4d2ff0 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -54,7 +54,7 @@
 	if (!kbd)
 		goto out;
 	kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL);
-	if (!key_maps)
+	if (!kbd->key_maps)
 		goto out_kbd;
 	for (i = 0; i < ARRAY_SIZE(key_maps); i++) {
 		if (key_maps[i]) {
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index ac10dfb..91e93c7 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -24,7 +24,7 @@
 
 /*
  * The room for the SCCB (only for writing) is not equal to a pages size
- * (as it is specified as the maximum size in the the SCLP ducumentation)
+ * (as it is specified as the maximum size in the the SCLP documentation)
  * because of the additional data structure described above.
  */
 #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index c3915f6..d71ef1a 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -230,14 +230,16 @@
  * These functions are used to schedule follow-up actions from within an
  * interrupt context (like unsolicited interrupts).
  */
+struct work_handler_data {
+	struct tape_device *device;
+	enum tape_op        op;
+	struct work_struct  work;
+};
+
 static void
 tape_3590_work_handler(void *data)
 {
-	struct {
-		struct tape_device *device;
-		enum tape_op op;
-		struct work_struct work;
-	} *p = data;
+	struct work_handler_data *p = data;
 
 	switch (p->op) {
 	case TO_MSEN:
@@ -257,11 +259,7 @@
 static int
 tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
 {
-	struct {
-		struct tape_device *device;
-		enum tape_op op;
-		struct work_struct work;
-	} *p;
+	struct work_handler_data *p;
 
 	if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
 		return -ENOMEM;
@@ -316,7 +314,7 @@
 
 	rq_for_each_bio(bio, req) {
 		bio_for_each_segment(bv, bio, i) {
-			dst = kmap(bv->bv_page) + bv->bv_offset;
+			dst = page_address(bv->bv_page) + bv->bv_offset;
 			for (off = 0; off < bv->bv_len;
 			     off += TAPEBLOCK_HSEC_SIZE) {
 				ccw->flags = CCW_FLAG_CC;
@@ -1168,6 +1166,7 @@
 static void
 tape_3590_cleanup_device(struct tape_device *device)
 {
+	flush_scheduled_work();
 	tape_std_unassign(device);
 
 	kfree(device->discdata);
@@ -1234,6 +1233,7 @@
 
 static struct ccw_device_id tape_3590_ids[] = {
 	{CCW_DEVICE_DEVTYPE(0x3590, 0, 0x3590, 0), .driver_info = tape_3590},
+	{CCW_DEVICE_DEVTYPE(0x3592, 0, 0x3592, 0), .driver_info = tape_3592},
 	{ /* end of list */ }
 };
 
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 5ced272..b70d926 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -198,9 +198,7 @@
 
 	device = (struct tape_device *) queue->queuedata;
 	DBF_LH(6, "tapeblock_request_fn(device=%p)\n", device);
-	if (device == NULL)
-		BUG();
-
+	BUG_ON(device == NULL);
 	tapeblock_trigger_requeue(device);
 }
 
@@ -307,8 +305,7 @@
 	int			rc;
 
 	device = (struct tape_device *) disk->private_data;
-	if (!device)
-		BUG();
+	BUG_ON(!device);
 
 	if (!device->blk_data.medium_changed)
 		return 0;
@@ -435,16 +432,14 @@
 ) {
 	int rc;
 	int minor;
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct tape_device *device = disk->private_data;
+	struct gendisk *disk;
+	struct tape_device *device;
 
 	rc     = 0;
 	disk   = inode->i_bdev->bd_disk;
-	if (!disk)
-		BUG();
+	BUG_ON(!disk);
 	device = disk->private_data;
-	if (!device)
-		BUG();
+	BUG_ON(!device);
 	minor  = iminor(inode);
 
 	DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 389ee2c..e6e4086 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -210,18 +210,14 @@
 		return;
 	}
 	DBF_EVENT(4, "ts. dev:	%x\n", device->first_minor);
-	if (device->tape_state < TO_SIZE && device->tape_state >= 0)
-		str = tape_state_verbose[device->tape_state];
-	else
-		str = "UNKNOWN TS";
-	DBF_EVENT(4, "old ts:	%s\n", str);
-	if (device->tape_state < TO_SIZE && device->tape_state >=0 )
+	DBF_EVENT(4, "old ts:\t\n");
+	if (device->tape_state < TS_SIZE && device->tape_state >=0 )
 		str = tape_state_verbose[device->tape_state];
 	else
 		str = "UNKNOWN TS";
 	DBF_EVENT(4, "%s\n", str);
 	DBF_EVENT(4, "new ts:\t\n");
-	if (newstate < TO_SIZE && newstate >= 0)
+	if (newstate < TS_SIZE && newstate >= 0)
 		str = tape_state_verbose[newstate];
 	else
 		str = "UNKNOWN TS";
diff --git a/drivers/s390/char/tape_std.h b/drivers/s390/char/tape_std.h
index 2d31179..1fc9523 100644
--- a/drivers/s390/char/tape_std.h
+++ b/drivers/s390/char/tape_std.h
@@ -153,6 +153,7 @@
         tape_3480,
         tape_3490,
         tape_3590,
+        tape_3592,
 };
 
 #endif // _TAPE_STD_H
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index cb8e2e6..0960bef 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -414,11 +414,11 @@
 	entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
 				   &proc_root);
 	if (!entry)
-		return 0;
+		return -ENOENT;
 
 	entry->proc_fops = &cio_ignore_proc_fops;
 
-	return 1;
+	return 0;
 }
 
 __initcall (cio_ignore_proc_init);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 6412b2c..72187e5 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -242,28 +242,10 @@
 	if (sch->vpm == mask)
 		goto out_unreg;
 
-	if ((sch->schib.scsw.actl & (SCSW_ACTL_CLEAR_PEND |
-				     SCSW_ACTL_HALT_PEND |
-				     SCSW_ACTL_START_PEND |
-				     SCSW_ACTL_RESUME_PEND)) &&
-	    (sch->schib.pmcw.lpum == mask)) {
-		int cc = cio_cancel(sch);
-		
-		if (cc == -ENODEV)
-			goto out_unreg;
-
-		if (cc == -EINVAL) {
-			cc = cio_clear(sch);
-			if (cc == -ENODEV)
-				goto out_unreg;
-			/* Call handler. */
-			if (sch->driver && sch->driver->termination)
-				sch->driver->termination(&sch->dev);
-			goto out_unlock;
-		}
-	} else if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
-		   (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
-		   (sch->schib.pmcw.lpum == mask)) {
+	if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
+	    (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
+	    (sch->schib.pmcw.lpum == mask) &&
+	    (sch->vpm == 0)) {
 		int cc;
 
 		cc = cio_clear(sch);
@@ -653,13 +635,13 @@
 		if (sch->schib.pmcw.chpid[i] == chp->id) {
 			if (stsch(sch->schid, &sch->schib) != 0) {
 				/* Endgame. */
-				spin_unlock(&sch->lock);
+				spin_unlock_irq(&sch->lock);
 				return -ENXIO;
 			}
 			break;
 		}
 	if (i==8) {
-		spin_unlock(&sch->lock);
+		spin_unlock_irq(&sch->lock);
 		return 0;
 	}
 	sch->lpm = ((sch->schib.pmcw.pim &
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index cbb86fa..5b20d8c 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -67,7 +67,7 @@
 		goto out_unregister;
 	debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
 	debug_set_level (cio_debug_msg_id, 2);
-	cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
+	cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 16);
 	if (!cio_debug_trace_id)
 		goto out_unregister;
 	debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h
index 6af8b27..f88844a 100644
--- a/drivers/s390/cio/cio_debug.h
+++ b/drivers/s390/cio/cio_debug.h
@@ -3,6 +3,11 @@
 
 #include <asm/debug.h>
 
+/* for use of debug feature */
+extern debug_info_t *cio_debug_msg_id;
+extern debug_info_t *cio_debug_trace_id;
+extern debug_info_t *cio_debug_crw_id;
+
 #define CIO_TRACE_EVENT(imp, txt) do { \
 		debug_text_event(cio_debug_trace_id, imp, txt); \
 	} while (0)
@@ -15,18 +20,19 @@
 		debug_sprintf_event(cio_debug_crw_id, imp , ##args); \
 	} while (0)
 
-#define CIO_HEX_EVENT(imp, args...) do { \
-                debug_event(cio_debug_trace_id, imp, ##args); \
-        } while (0)
+static inline void
+CIO_HEX_EVENT(int level, void *data, int length)
+{
+	while (length > 0) {
+		debug_event(cio_debug_trace_id, level, data, length);
+		length -= cio_debug_trace_id->buf_size;
+		data += cio_debug_trace_id->buf_size;
+	}
+}
 
 #define CIO_DEBUG(printk_level,event_level,msg...) ({ \
 	if (cio_show_msg) printk(printk_level msg); \
 	CIO_MSG_EVENT (event_level, msg); \
 })
 
-/* for use of debug feature */
-extern debug_info_t *cio_debug_msg_id;
-extern debug_info_t *cio_debug_trace_id;
-extern debug_info_t *cio_debug_crw_id;
-
 #endif
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 814f925..96f5192 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -38,6 +38,7 @@
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
 #include <linux/timer.h>
+#include <linux/mempool.h>
 
 #include <asm/ccwdev.h>
 #include <asm/io.h>
@@ -80,6 +81,8 @@
 static __u32 * volatile indicators;
 static __u32 volatile spare_indicator;
 static atomic_t spare_indicator_usecount;
+#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
+static mempool_t *qdio_mempool_scssc;
 
 static debug_info_t *qdio_dbf_setup;
 static debug_info_t *qdio_dbf_sbal;
@@ -1637,7 +1640,7 @@
 
 	}
 	kfree(irq_ptr->qdr);
-	kfree(irq_ptr);
+	free_page((unsigned long) irq_ptr);
 }
 
 static void
@@ -2304,7 +2307,7 @@
 
 	QDIO_DBF_TEXT0(0,setup,"getssqd");
 	qdioac = 0;
-	ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
 	if (!ssqd_area) {
 	        QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
 				"SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
@@ -2364,7 +2367,7 @@
 out:
 	qdio_check_subchannel_qebsm(irq_ptr, qdioac,
 				    ssqd_area->sch_token);
-	free_page ((unsigned long) ssqd_area);
+	mempool_free(ssqd_area, qdio_mempool_scssc);
 	irq_ptr->qdioac = qdioac;
 }
 
@@ -2458,7 +2461,7 @@
 			virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
 	}
 
-	scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
 	if (!scssc_area) {
 		QDIO_PRINT_WARN("No memory for setting indicators on " \
 				"subchannel 0.%x.%x.\n",
@@ -2514,7 +2517,7 @@
 	QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
 	result = 0;
 out:
-	free_page ((unsigned long) scssc_area);
+	mempool_free(scssc_area, qdio_mempool_scssc);
 	return result;
 
 }
@@ -2543,7 +2546,7 @@
 	if (!irq_ptr->is_thinint_irq)
 		return -ENODEV;
 
-	scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
 	if (!scsscf_area) {
 		QDIO_PRINT_WARN("No memory for setting delay target on " \
 				"subchannel 0.%x.%x.\n",
@@ -2581,7 +2584,7 @@
 	QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
 	result = 0; /* not critical */
 out:
-	free_page ((unsigned long) scsscf_area);
+	mempool_free(scsscf_area, qdio_mempool_scssc);
 	return result;
 }
 
@@ -2980,7 +2983,7 @@
 	qdio_allocate_do_dbf(init_data);
 
 	/* create irq */
-	irq_ptr = kzalloc(sizeof(struct qdio_irq), GFP_KERNEL | GFP_DMA);
+	irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 
 	QDIO_DBF_TEXT0(0,setup,"irq_ptr:");
 	QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
@@ -2995,7 +2998,7 @@
 	/* QDR must be in DMA area since CCW data address is only 32 bit */
 	irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
   	if (!(irq_ptr->qdr)) {
-   		kfree(irq_ptr);
+   		free_page((unsigned long) irq_ptr);
     		QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
 		return -ENOMEM;
        	}
@@ -3780,6 +3783,16 @@
 	return -ENOMEM;
 }
 
+static void *qdio_mempool_alloc(gfp_t gfp_mask, void *size)
+{
+	return (void *) get_zeroed_page(gfp_mask|GFP_DMA);
+}
+
+static void qdio_mempool_free(void *element, void *size)
+{
+	free_page((unsigned long) element);
+}
+
 static int __init
 init_QDIO(void)
 {
@@ -3809,6 +3822,10 @@
 
 	qdio_add_procfs_entry();
 
+	qdio_mempool_scssc = mempool_create(QDIO_MEMPOOL_SCSSC_ELEMENTS,
+					    qdio_mempool_alloc,
+					    qdio_mempool_free, NULL);
+
 	if (tiqdio_check_chsc_availability())
 		QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
 
@@ -3824,6 +3841,7 @@
 	qdio_remove_procfs_entry();
 	qdio_release_qdio_memory();
 	qdio_unregister_dbf_views();
+	mempool_destroy(qdio_mempool_scssc);
 
   	printk("qdio: %s: module removed\n",version);
 }
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index edcf05d..5d6b7a5 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -675,9 +675,8 @@
 	int index, rc;
 
 	LCS_DBF_TEXT(5, trace, "rdybuff");
-	if (buffer->state != BUF_STATE_LOCKED &&
-	    buffer->state != BUF_STATE_PROCESSED)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+		buffer->state != BUF_STATE_PROCESSED);
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_READY;
 	index = buffer - channel->iob;
@@ -701,8 +700,7 @@
 	int index, prev, next;
 
 	LCS_DBF_TEXT(5, trace, "prcsbuff");
-	if (buffer->state != BUF_STATE_READY)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_READY);
 	buffer->state = BUF_STATE_PROCESSED;
 	index = buffer - channel->iob;
 	prev = (index - 1) & (LCS_NUM_BUFFS - 1);
@@ -734,9 +732,8 @@
 	unsigned long flags;
 
 	LCS_DBF_TEXT(5, trace, "relbuff");
-	if (buffer->state != BUF_STATE_LOCKED &&
-	    buffer->state != BUF_STATE_PROCESSED)
-		BUG();
+	BUG_ON(buffer->state != BUF_STATE_LOCKED &&
+		buffer->state != BUF_STATE_PROCESSED);
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	buffer->state = BUF_STATE_EMPTY;
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 3bf4666..5ae1480 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -362,12 +362,19 @@
 	return kill_task;
 }
 
+#define MAX_IPD_COUNT	29
+#define MAX_IPD_TIME	(5 * 60 * 100 * 1000) /* 5 minutes */
+
 /*
  * machine check handler.
  */
 void
 s390_do_machine_check(struct pt_regs *regs)
 {
+	static DEFINE_SPINLOCK(ipd_lock);
+	static unsigned long long last_ipd;
+	static int ipd_count;
+	unsigned long long tmp;
 	struct mci *mci;
 	struct mcck_struct *mcck;
 	int umode;
@@ -404,11 +411,27 @@
 				s390_handle_damage("processing backup machine "
 						   "check with damage.");
 			}
-			if (!umode)
-				s390_handle_damage("processing backup machine "
-						   "check in kernel mode.");
-			mcck->kill_task = 1;
-			mcck->mcck_code = *(unsigned long long *) mci;
+
+			/*
+			 * Nullifying exigent condition, therefore we might
+			 * retry this instruction.
+			 */
+
+			spin_lock(&ipd_lock);
+
+			tmp = get_clock();
+
+			if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
+				ipd_count++;
+			else
+				ipd_count = 1;
+
+			last_ipd = tmp;
+
+			if (ipd_count == MAX_IPD_COUNT)
+				s390_handle_damage("too many ipd retries.");
+
+			spin_unlock(&ipd_lock);
 		}
 		else {
 			/* Processing damage -> stopping machine */
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 0d2b447..caeb6d2 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -65,6 +65,7 @@
    2.26.02.005 - Fix use_sg == 0 mapping on systems with 4GB or higher.
    2.26.02.006 - Fix 9550SX pchip reset timeout.
                  Add big endian support.
+   2.26.02.007 - Disable local interrupts during kmap/unmap_atomic().
 */
 
 #include <linux/module.h>
@@ -88,7 +89,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.006"
+#define TW_DRIVER_VERSION "2.26.02.007"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -1942,9 +1943,13 @@
 		}
 		if (tw_dev->srb[request_id]->use_sg == 1) {
 			struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
-			char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+			char *buf;
+			unsigned long flags = 0;
+			local_irq_save(flags);
+			buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 			memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);
 			kunmap_atomic(buf - sg->offset, KM_IRQ0);
+			local_irq_restore(flags);
 		}
 	}
 } /* End twa_scsiop_execute_scsi_complete() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 25f678d..e8e41e6 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1508,10 +1508,12 @@
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 	void *buf;
 	unsigned int transfer_len;
+	unsigned long flags = 0;
 
 	if (cmd->use_sg) {
 		struct scatterlist *sg =
 			(struct scatterlist *)cmd->request_buffer;
+		local_irq_save(flags);
 		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
 		transfer_len = min(sg->length, len);
 	} else {
@@ -1526,6 +1528,7 @@
 
 		sg = (struct scatterlist *)cmd->request_buffer;
 		kunmap_atomic(buf - sg->offset, KM_IRQ0);
+		local_irq_restore(flags);
 	}
 }
 
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4035920..3e73026 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1079,7 +1079,7 @@
 	  memory using PCI DAC cycles.
 
 config SCSI_SYM53C8XX_DEFAULT_TAGS
-	int "default tagged command queue depth"
+	int "Default tagged command queue depth"
 	depends on SCSI_SYM53C8XX_2
 	default "16"
 	help
@@ -1090,7 +1090,7 @@
 	  exceed CONFIG_SCSI_SYM53C8XX_MAX_TAGS.
 
 config SCSI_SYM53C8XX_MAX_TAGS
-	int "maximum number of queued commands"
+	int "Maximum number of queued commands"
 	depends on SCSI_SYM53C8XX_2
 	default "64"
 	help
@@ -1099,13 +1099,14 @@
 	  possible. The driver supports up to 256 queued commands per device.
 	  This value is used as a compiled-in hard limit.
 
-config SCSI_SYM53C8XX_IOMAPPED
-	bool "use port IO"
+config SCSI_SYM53C8XX_MMIO
+	bool "Use memory mapped IO"
 	depends on SCSI_SYM53C8XX_2
+	default y
 	help
-	  If you say Y here, the driver will use port IO to access
-	  the card.  This is significantly slower then using memory
-	  mapped IO.  Most people should answer N.
+	  Memory mapped IO is faster than Port IO.  Most people should
+	  answer Y here, but some machines may have problems.  If you have
+	  to answer N here, please report the problem to the maintainer.
 
 config SCSI_IPR
 	tristate "IBM Power Linux RAID adapter support"
@@ -1309,15 +1310,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called qlogicfas.
 
-config SCSI_QLOGIC_FC
-	tristate "Qlogic ISP FC SCSI support"
-	depends on PCI && SCSI
-	help
-	  This is a driver for the QLogic ISP2100 SCSI-FCP host adapter.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called qlogicfc.
-
 config SCSI_QLOGIC_FC_FIRMWARE
 	bool "Include loadable firmware in driver"
 	depends on SCSI_QLOGIC_FC
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index e513c31..81803a1 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -78,7 +78,6 @@
 obj-$(CONFIG_SCSI_SYM53C416)	+= sym53c416.o
 obj-$(CONFIG_SCSI_QLOGIC_FAS)	+= qlogicfas408.o	qlogicfas.o
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogicfas408.o
-obj-$(CONFIG_SCSI_QLOGIC_FC)	+= qlogicfc.o 
 obj-$(CONFIG_SCSI_QLOGIC_1280)	+= qla1280.o 
 obj-$(CONFIG_SCSI_QLA_FC)	+= qla2xxx/
 obj-$(CONFIG_SCSI_LPFC)		+= lpfc/
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 8df4a0e..642a3b4 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -149,20 +149,20 @@
 
 static int commit = -1;
 
-module_param(nondasd, int, 0);
+module_param(nondasd, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-module_param(dacmode, int, 0);
+module_param(dacmode, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
-module_param(commit, int, 0);
+module_param(commit, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
 
 int numacb = -1;
 module_param(numacb, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid values are 512 and down. Default is to use suggestion from Firmware.");
 
 int acbsize = -1;
 module_param(acbsize, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
 /**
  *	aac_get_config_status	-	check the adapter configuration
  *	@common: adapter to query
@@ -387,6 +387,7 @@
 	struct scsi_cmnd * scsicmd;
 
 	scsicmd = (struct scsi_cmnd *) context;
+	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
 	dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
 	if (fibptr == NULL)
@@ -453,8 +454,10 @@
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS) 
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
 		return 0;
+	}
 		
 	printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
 	aac_fib_complete(cmd_fibcontext);
@@ -907,9 +910,10 @@
 	u32 cid;
 
 	scsicmd = (struct scsi_cmnd *) context;
+	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-	cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+	cid = scmd_id(scsicmd);
 
 	if (nblank(dprintk(x))) {
 		u64 lba;
@@ -1151,8 +1155,10 @@
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS) 
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
 		return 0;
+	}
 		
 	printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
 	/*
@@ -1318,8 +1324,8 @@
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS)
-	{
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
 		return 0;
 	}
 
@@ -1341,6 +1347,7 @@
 	struct scsi_cmnd *cmd;
 
 	cmd = context;
+	cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
 	dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
 				smp_processor_id(), jiffies));
@@ -1354,7 +1361,7 @@
 	else {
 		struct scsi_device *sdev = cmd->device;
 		struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
-		u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
+		u32 cid = sdev_id(sdev);
 		printk(KERN_WARNING 
 		     "synchronize_callback: synchronize failed, status = %d\n",
 		     le32_to_cpu(synchronizereply->status));
@@ -1386,12 +1393,12 @@
 	unsigned long flags;
 
 	/*
-	 * Wait for all commands to complete to this specific
-	 * target (block).
+	 * Wait for all outstanding queued commands to complete to this
+	 * specific target (block).
 	 */
 	spin_lock_irqsave(&sdev->list_lock, flags);
 	list_for_each_entry(cmd, &sdev->cmd_list, list)
-		if (cmd != scsicmd && cmd->serial_number != 0) {
+		if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
 			++active;
 			break;
 		}
@@ -1434,8 +1441,10 @@
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS)
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
 		return 0;
+	}
 
 	printk(KERN_WARNING 
 		"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@@ -1458,7 +1467,6 @@
 	struct Scsi_Host *host = scsicmd->device->host;
 	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
 	struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
-	int ret;
 	
 	/*
 	 *	If the bus, id or lun is out of range, return fail
@@ -1466,13 +1474,14 @@
 	 *	itself.
 	 */
 	if (scmd_id(scsicmd) != host->this_id) {
-		if ((scsicmd->device->channel == CONTAINER_CHANNEL)) {
-			if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ 
+		if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) {
+			if((scmd_id(scsicmd) >= dev->maximum_num_containers) ||
+					(scsicmd->device->lun != 0)) {
 				scsicmd->result = DID_NO_CONNECT << 16;
 				scsicmd->scsi_done(scsicmd);
 				return 0;
 			}
-			cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);
+			cid = scmd_id(scsicmd);
 
 			/*
 			 *	If the target container doesn't exist, it may have
@@ -1548,7 +1557,7 @@
 	{
 		struct inquiry_data inq_data;
 
-		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));
+		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd)));
 		memset(&inq_data, 0, sizeof (struct inquiry_data));
 
 		inq_data.inqd_ver = 2;	/* claim compliance to SCSI-2 */
@@ -1598,13 +1607,14 @@
 		cp[11] = 0;
 		cp[12] = 0;
 		aac_internal_transfer(scsicmd, cp, 0,
-		  min((unsigned int)scsicmd->cmnd[13], sizeof(cp)));
+		  min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));
 		if (sizeof(cp) < scsicmd->cmnd[13]) {
 			unsigned int len, offset = sizeof(cp);
 
 			memset(cp, 0, offset);
 			do {
-				len = min(scsicmd->cmnd[13]-offset, sizeof(cp));
+				len = min_t(size_t, scsicmd->cmnd[13] - offset,
+						sizeof(cp));
 				aac_internal_transfer(scsicmd, cp, offset, len);
 			} while ((offset += len) < scsicmd->cmnd[13]);
 		}
@@ -1728,24 +1738,19 @@
 			 *	containers to /dev/sd device names
 			 */
 			 
-			spin_unlock_irq(host->host_lock);
 			if (scsicmd->request->rq_disk)
 				strlcpy(fsa_dev_ptr[cid].devname,
 				scsicmd->request->rq_disk->disk_name,
 			  	min(sizeof(fsa_dev_ptr[cid].devname),
 				sizeof(scsicmd->request->rq_disk->disk_name) + 1));
-			ret = aac_read(scsicmd, cid);
-			spin_lock_irq(host->host_lock);
-			return ret;
+
+			return aac_read(scsicmd, cid);
 
 		case WRITE_6:
 		case WRITE_10:
 		case WRITE_12:
 		case WRITE_16:
-			spin_unlock_irq(host->host_lock);
-			ret = aac_write(scsicmd, cid);
-			spin_lock_irq(host->host_lock);
-			return ret;
+			return aac_write(scsicmd, cid);
 
 		case SYNCHRONIZE_CACHE:
 			/* Issue FIB to tell Firmware to flush it's cache */
@@ -1778,7 +1783,7 @@
 	if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
 		return -EFAULT;
 	if (qd.cnum == -1)
-		qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);
+		qd.cnum = qd.id;
 	else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) 
 	{
 		if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
@@ -1890,6 +1895,7 @@
 	struct scsi_cmnd *scsicmd;
 
 	scsicmd = (struct scsi_cmnd *) context;
+	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
 	if (fibptr == NULL)
@@ -2068,14 +2074,13 @@
 	u32 timeout;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
-	if (scsicmd->device->id >= dev->maximum_num_physicals || 
+	if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
 			scsicmd->device->lun > 7) {
 		scsicmd->result = DID_NO_CONNECT << 16;
 		scsicmd->scsi_done(scsicmd);
 		return 0;
 	}
 
-	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	switch(scsicmd->sc_data_direction){
 	case DMA_TO_DEVICE:
 		flag = SRB_DataOut;
@@ -2103,8 +2108,8 @@
 
 	srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
 	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
-	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));
-	srbcmd->id   = cpu_to_le32(scsicmd->device->id);
+	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(scsicmd)));
+	srbcmd->id   = cpu_to_le32(scmd_id(scsicmd));
 	srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);
 	srbcmd->flags    = cpu_to_le32(flag);
 	timeout = scsicmd->timeout_per_command/HZ;
@@ -2161,7 +2166,8 @@
 	/*
 	 *	Check that the command queued to the controller
 	 */
-	if (status == -EINPROGRESS){
+	if (status == -EINPROGRESS) {
+		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
 		return 0;
 	}
 
@@ -2192,8 +2198,6 @@
 			scsicmd->sc_data_direction);
 		psg->count = cpu_to_le32(sg_count);
 
-		byte_count = 0;
-
 		for (i = 0; i < sg_count; i++) {
 			psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
 			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
@@ -2249,18 +2253,17 @@
 
 		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
 			scsicmd->sc_data_direction);
-		psg->count = cpu_to_le32(sg_count);
-
-		byte_count = 0;
 
 		for (i = 0; i < sg_count; i++) {
+			int count = sg_dma_len(sg);
 			addr = sg_dma_address(sg);
 			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
 			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
-			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
-			byte_count += sg_dma_len(sg);
+			psg->sg[i].count = cpu_to_le32(count);
+			byte_count += count;
 			sg++;
 		}
+		psg->count = cpu_to_le32(sg_count);
 		/* hba wants the size to be exact */
 		if(byte_count > scsicmd->request_bufflen){
 			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
@@ -2275,16 +2278,15 @@
 		}
 	}
 	else if(scsicmd->request_bufflen) {
-		u64 addr; 
-		addr = pci_map_single(dev->pdev,
+		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
 				scsicmd->request_buffer,
 				scsicmd->request_bufflen,
 				scsicmd->sc_data_direction);
+		addr = scsicmd->SCp.dma_handle;
 		psg->count = cpu_to_le32(1);
 		psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
 		psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 9ce7002..f773b0d 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -10,6 +10,10 @@
  *              D E F I N E S
  *----------------------------------------------------------------------------*/
 
+#ifndef AAC_DRIVER_BUILD
+# define AAC_DRIVER_BUILD 2409
+# define AAC_DRIVER_BRANCH "-mh1"
+#endif
 #define MAXIMUM_NUM_CONTAINERS	32
 
 #define AAC_NUM_MGT_FIB         8
@@ -25,7 +29,6 @@
  * These macros convert from physical channels to virtual channels
  */
 #define CONTAINER_CHANNEL		(0)
-#define ID_LUN_TO_CONTAINER(id, lun)	(id)
 #define CONTAINER_TO_CHANNEL(cont)	(CONTAINER_CHANNEL)
 #define CONTAINER_TO_ID(cont)		(cont)
 #define CONTAINER_TO_LUN(cont)		(0)
@@ -789,6 +792,7 @@
 	u64		size;
 	u32		type;
 	u32		config_waiting_on;
+	unsigned long	config_waiting_stamp;
 	u16		queue_depth;
 	u8		config_needed;
 	u8		valid;
@@ -1771,6 +1775,11 @@
 }
 
 struct scsi_cmnd;
+/* SCp.phase values */
+#define AAC_OWNER_MIDLEVEL	0x101
+#define AAC_OWNER_LOWLEVEL	0x102
+#define AAC_OWNER_ERROR_HANDLER	0x103
+#define AAC_OWNER_FIRMWARE	0x106
 
 const char *aac_driverinfo(struct Scsi_Host *);
 struct fib *aac_fib_alloc(struct aac_dev *dev);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 47fefca..9f75144 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -38,6 +38,8 @@
 #include <linux/completion.h>
 #include <linux/dma-mapping.h>
 #include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
@@ -293,6 +295,16 @@
 		status = 0;
 	} else {
 		spin_unlock_irqrestore(&dev->fib_lock, flags);
+		/* If someone killed the AIF aacraid thread, restart it */
+		status = !dev->aif_thread;
+		if (status && dev->queues && dev->fsa_dev) {
+			/* Be paranoid, be very paranoid! */
+			kthread_stop(dev->thread);
+			ssleep(1);
+			dev->aif_thread = 0;
+			dev->thread = kthread_run(aac_command_thread, dev, dev->name);
+			ssleep(1);
+		}
 		if (f.wait) {
 			if(down_interruptible(&fibctx->wait_sem) < 0) {
 				status = -EINTR;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index c7f80ec..9f9f4aa 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -767,9 +767,9 @@
 		if (cp[length] != 0)
 			cp[length] = 0;
 		if (level == LOG_AAC_HIGH_ERROR)
-			printk(KERN_WARNING "aacraid:%s", cp);
+			printk(KERN_WARNING "%s:%s", dev->name, cp);
 		else
-			printk(KERN_INFO "aacraid:%s", cp);
+			printk(KERN_INFO "%s:%s", dev->name, cp);
 	}
 	memset(cp, 0,  256);
 }
@@ -784,6 +784,7 @@
  *	dispatches it to the appropriate routine for handling.
  */
 
+#define AIF_SNIFF_TIMEOUT	(30*HZ)
 static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 {
 	struct hw_fib * hw_fib = fibptr->hw_fib;
@@ -837,6 +838,7 @@
 				if (device) {
 					dev->fsa_dev[container].config_needed = CHANGE;
 					dev->fsa_dev[container].config_waiting_on = AifEnConfigChange;
+					dev->fsa_dev[container].config_waiting_stamp = jiffies;
 					scsi_device_put(device);
 				}
 			}
@@ -849,13 +851,15 @@
 		if (container != (u32)-1) {
 			if (container >= dev->maximum_num_containers)
 				break;
-			if (dev->fsa_dev[container].config_waiting_on ==
-			    le32_to_cpu(*(u32 *)aifcmd->data))
+			if ((dev->fsa_dev[container].config_waiting_on ==
+			    le32_to_cpu(*(u32 *)aifcmd->data)) &&
+			 time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
 				dev->fsa_dev[container].config_waiting_on = 0;
 		} else for (container = 0;
 		    container < dev->maximum_num_containers; ++container) {
-			if (dev->fsa_dev[container].config_waiting_on ==
-			    le32_to_cpu(*(u32 *)aifcmd->data))
+			if ((dev->fsa_dev[container].config_waiting_on ==
+			    le32_to_cpu(*(u32 *)aifcmd->data)) &&
+			 time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
 				dev->fsa_dev[container].config_waiting_on = 0;
 		}
 		break;
@@ -872,6 +876,7 @@
 			dev->fsa_dev[container].config_needed = ADD;
 			dev->fsa_dev[container].config_waiting_on =
 				AifEnConfigChange;
+			dev->fsa_dev[container].config_waiting_stamp = jiffies;
 			break;
 
 		/*
@@ -884,6 +889,7 @@
 			dev->fsa_dev[container].config_needed = DELETE;
 			dev->fsa_dev[container].config_waiting_on =
 				AifEnConfigChange;
+			dev->fsa_dev[container].config_waiting_stamp = jiffies;
 			break;
 
 		/*
@@ -894,11 +900,13 @@
 			container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
 			if (container >= dev->maximum_num_containers)
 				break;
-			if (dev->fsa_dev[container].config_waiting_on)
+			if (dev->fsa_dev[container].config_waiting_on &&
+			 time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
 				break;
 			dev->fsa_dev[container].config_needed = CHANGE;
 			dev->fsa_dev[container].config_waiting_on =
 				AifEnConfigChange;
+			dev->fsa_dev[container].config_waiting_stamp = jiffies;
 			break;
 
 		case AifEnConfigChange:
@@ -913,13 +921,15 @@
 		if (container != (u32)-1) {
 			if (container >= dev->maximum_num_containers)
 				break;
-			if (dev->fsa_dev[container].config_waiting_on ==
-			    le32_to_cpu(*(u32 *)aifcmd->data))
+			if ((dev->fsa_dev[container].config_waiting_on ==
+			    le32_to_cpu(*(u32 *)aifcmd->data)) &&
+			 time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
 				dev->fsa_dev[container].config_waiting_on = 0;
 		} else for (container = 0;
 		    container < dev->maximum_num_containers; ++container) {
-			if (dev->fsa_dev[container].config_waiting_on ==
-			    le32_to_cpu(*(u32 *)aifcmd->data))
+			if ((dev->fsa_dev[container].config_waiting_on ==
+			    le32_to_cpu(*(u32 *)aifcmd->data)) &&
+			 time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT))
 				dev->fsa_dev[container].config_waiting_on = 0;
 		}
 		break;
@@ -946,6 +956,8 @@
 				dev->fsa_dev[container].config_waiting_on =
 					AifEnContainerChange;
 				dev->fsa_dev[container].config_needed = ADD;
+				dev->fsa_dev[container].config_waiting_stamp =
+					jiffies;
 			}
 		}
 		if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
@@ -961,6 +973,8 @@
 				dev->fsa_dev[container].config_waiting_on =
 					AifEnContainerChange;
 				dev->fsa_dev[container].config_needed = DELETE;
+				dev->fsa_dev[container].config_waiting_stamp =
+					jiffies;
 			}
 		}
 		break;
@@ -969,8 +983,9 @@
 	device_config_needed = NOTHING;
 	for (container = 0; container < dev->maximum_num_containers;
 	    ++container) {
-		if ((dev->fsa_dev[container].config_waiting_on == 0)
-		 && (dev->fsa_dev[container].config_needed != NOTHING)) {
+		if ((dev->fsa_dev[container].config_waiting_on == 0) &&
+			(dev->fsa_dev[container].config_needed != NOTHING) &&
+			time_before(jiffies, dev->fsa_dev[container].config_waiting_stamp + AIF_SNIFF_TIMEOUT)) {
 			device_config_needed =
 				dev->fsa_dev[container].config_needed;
 			dev->fsa_dev[container].config_needed = NOTHING;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 7203307..6ef89c9 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -27,12 +27,6 @@
  * Abstract: Linux Driver entry module for Adaptec RAID Array Controller
  */
 
-#define AAC_DRIVER_VERSION		"1.1-4"
-#ifndef AAC_DRIVER_BRANCH
-#define AAC_DRIVER_BRANCH		""
-#endif
-#define AAC_DRIVER_BUILD_DATE		__DATE__ " " __TIME__
-#define AAC_DRIVERNAME			"aacraid"
 
 #include <linux/compat.h>
 #include <linux/blkdev.h>
@@ -62,6 +56,13 @@
 
 #include "aacraid.h"
 
+#define AAC_DRIVER_VERSION		"1.1-5"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH		""
+#endif
+#define AAC_DRIVER_BUILD_DATE		__DATE__ " " __TIME__
+#define AAC_DRIVERNAME			"aacraid"
+
 #ifdef AAC_DRIVER_BUILD
 #define _str(x) #x
 #define str(x) _str(x)
@@ -73,7 +74,7 @@
 MODULE_AUTHOR("Red Hat Inc and Adaptec");
 MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
 		   "Adaptec Advanced Raid Products, "
-		   "and HP NetRAID-4M SCSI driver");
+		   "HP NetRAID-4M, IBM ServeRAID & ICP SCSI driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
@@ -243,6 +244,7 @@
 static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	cmd->scsi_done = done;
+	cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
 	return (aac_scsi_cmd(cmd) ? FAILED : 0);
 } 
 
@@ -471,7 +473,8 @@
 		__shost_for_each_device(dev, host) {
 			spin_lock_irqsave(&dev->list_lock, flags);
 			list_for_each_entry(command, &dev->cmd_list, list) {
-				if (command->serial_number) {
+				if ((command != cmd) &&
+				    (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
 					active++;
 					break;
 				}
@@ -569,12 +572,12 @@
 		
 		f = compat_alloc_user_space(sizeof(*f));
 		ret = 0;
-		if (clear_user(f, sizeof(*f) != sizeof(*f)))
+		if (clear_user(f, sizeof(*f)) != sizeof(*f))
 			ret = -EFAULT;
 		if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
 			ret = -EFAULT;
 		if (!ret)
-			ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+			ret = aac_do_ioctl(dev, cmd, f);
 		break;
 	}
 
@@ -687,6 +690,18 @@
 	return len;
 }
 
+static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+	  class_to_shost(class_dev)->max_channel);
+}
+
+static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+	  class_to_shost(class_dev)->max_id);
+}
+
 
 static struct class_device_attribute aac_model = {
 	.attr = {
@@ -730,6 +745,20 @@
 	},
 	.show = aac_show_serial_number,
 };
+static struct class_device_attribute aac_max_channel = {
+	.attr = {
+		.name = "max_channel",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_max_channel,
+};
+static struct class_device_attribute aac_max_id = {
+	.attr = {
+		.name = "max_id",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_max_id,
+};
 
 static struct class_device_attribute *aac_attrs[] = {
 	&aac_model,
@@ -738,6 +767,8 @@
 	&aac_monitor_version,
 	&aac_bios_version,
 	&aac_serial_number,
+	&aac_max_channel,
+	&aac_max_id,
 	NULL
 };
 
@@ -775,6 +806,7 @@
 	.cmd_per_lun    		= AAC_NUM_IO_FIB, 
 #endif	
 	.use_clustering			= ENABLE_CLUSTERING,
+	.emulated                       = 1,
 };
 
 
@@ -798,10 +830,11 @@
 	error = pci_enable_device(pdev);
 	if (error)
 		goto out;
+	error = -ENODEV;
 
 	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || 
 			pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
-		goto out;
+		goto out_disable_pdev;
 	/*
 	 * If the quirk31 bit is set, the adapter needs adapter
 	 * to driver communication memory to be allocated below 2gig
@@ -809,7 +842,7 @@
 	if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) 
 		if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) ||
 				pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK))
-			goto out;
+			goto out_disable_pdev;
 	
 	pci_set_master(pdev);
 
@@ -904,9 +937,9 @@
 	 * physical channels are address by their actual physical number+1
 	 */
 	if (aac->nondasd_support == 1)
-		shost->max_channel = aac->maximum_num_channels + 1;
+		shost->max_channel = aac->maximum_num_channels;
 	else
-		shost->max_channel = 1;
+		shost->max_channel = 0;
 
 	aac_get_config_status(aac);
 	aac_get_containers(aac);
@@ -1020,7 +1053,8 @@
 
 static void __exit aac_exit(void)
 {
-	unregister_chrdev(aac_cfg_major, "aac");
+	if (aac_cfg_major > -1)
+		unregister_chrdev(aac_cfg_major, "aac");
 	pci_unregister_driver(&aac_pci_driver);
 }
 
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index e9b775d..7a23e02 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -183,7 +183,7 @@
 		/*
 		 *	Yield the processor in case we are slow 
 		 */
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 	if (ok != 1) {
 		/*
@@ -343,7 +343,7 @@
 		  NULL, NULL, NULL, NULL, NULL);
 		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
 		  post, paddr);
-                if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+                if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
                         ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
                         ret <<= 4;
                         ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 6998bc8..729b9eb 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -183,7 +183,7 @@
 		/*
 		 *	Yield the processor in case we are slow 
 		 */
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 	if (ok != 1) {
 		/*
@@ -342,7 +342,7 @@
 		  NULL, NULL, NULL, NULL, NULL);
 		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
 		  post, paddr);
-		if ((buffer[0] == '0') && (buffer[1] == 'x')) {
+		if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
 			ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
 			ret <<= 4;
 			ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 466f05c..a534549 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -189,7 +189,7 @@
 			ok = 1;
 			break;
 		}
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 
 	if (ok != 1)
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 1bd82c4..b4f8fb1 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -207,7 +207,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= AHCI_MAX_SG,
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 6c2c395..5517da5 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -86,7 +86,7 @@
         default "0"
         help
 	Bit mask of debug options that is only valid if the
-	CONFIG_AIC7XXX_DEBUG_ENBLE option is enabled.  The bits in this mask
+	CONFIG_AIC7XXX_DEBUG_ENABLE option is enabled.  The bits in this mask
 	are defined in the drivers/scsi/aic7xxx/aic7xxx.h - search for the
 	variable ahc_debug in that file to find them.
 
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 1d11f7e..bb5166d 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -372,7 +372,7 @@
 	AHD_CURRENT_SENSING   = 0x40000,
 	AHD_SCB_CONFIG_USED   = 0x80000,/* No SEEPROM but SCB had info. */
 	AHD_HP_BOARD	      = 0x100000,
-	AHD_RESET_POLL_ACTIVE = 0x200000,
+	AHD_BUS_RESET_ACTIVE  = 0x200000,
 	AHD_UPDATE_PEND_CMDS  = 0x400000,
 	AHD_RUNNING_QOUTFIFO  = 0x800000,
 	AHD_HAD_FIRST_SEL     = 0x1000000
@@ -589,7 +589,7 @@
 	SCB_PACKETIZED		= 0x00800,
 	SCB_EXPECT_PPR_BUSFREE	= 0x01000,
 	SCB_PKT_SENSE		= 0x02000,
-	SCB_CMDPHASE_ABORT	= 0x04000,
+	SCB_EXTERNAL_RESET	= 0x04000,/* Device was reset externally */
 	SCB_ON_COL_LIST		= 0x08000,
 	SCB_SILENT		= 0x10000 /*
 					   * Be quiet about transmission type
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 326a622..08771f6 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -207,7 +207,6 @@
 static u_int		ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
 				     u_int prev, u_int next, u_int tid);
 static void		ahd_reset_current_bus(struct ahd_softc *ahd);
-static ahd_callback_t	ahd_reset_poll;
 static ahd_callback_t	ahd_stat_timer;
 #ifdef AHD_DUMP_SEQ
 static void		ahd_dumpseq(struct ahd_softc *ahd);
@@ -1054,12 +1053,10 @@
 			 * If a target takes us into the command phase
 			 * assume that it has been externally reset and
 			 * has thus lost our previous packetized negotiation
-			 * agreement.  Since we have not sent an identify
-			 * message and may not have fully qualified the
-			 * connection, we change our command to TUR, assert
-			 * ATN and ABORT the task when we go to message in
-			 * phase.  The OSM will see the REQUEUE_REQUEST
-			 * status and retry the command.
+			 * agreement.
+			 * Revert to async/narrow transfers until we
+			 * can renegotiate with the device and notify
+			 * the OSM about the reset.
 			 */
 			scbid = ahd_get_scbptr(ahd);
 			scb = ahd_lookup_scb(ahd, scbid);
@@ -1086,31 +1083,15 @@
 			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
 					 /*offset*/0, /*ppr_options*/0,
 					 AHD_TRANS_ACTIVE, /*paused*/TRUE);
-			ahd_outb(ahd, SCB_CDB_STORE, 0);
-			ahd_outb(ahd, SCB_CDB_STORE+1, 0);
-			ahd_outb(ahd, SCB_CDB_STORE+2, 0);
-			ahd_outb(ahd, SCB_CDB_STORE+3, 0);
-			ahd_outb(ahd, SCB_CDB_STORE+4, 0);
-			ahd_outb(ahd, SCB_CDB_STORE+5, 0);
-			ahd_outb(ahd, SCB_CDB_LEN, 6);
-			scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
-			scb->hscb->control |= MK_MESSAGE;
-			ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
-			ahd_outb(ahd, MSG_OUT, HOST_MSG);
-			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
-			/*
-			 * The lun is 0, regardless of the SCB's lun
-			 * as we have not sent an identify message.
-			 */
-			ahd_outb(ahd, SAVED_LUN, 0);
-			ahd_outb(ahd, SEQ_FLAGS, 0);
-			ahd_assert_atn(ahd);
-			scb->flags &= ~SCB_PACKETIZED;
-			scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
+			scb->flags |= SCB_EXTERNAL_RESET;
 			ahd_freeze_devq(ahd, scb);
 			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
 			ahd_freeze_scb(scb);
 
+			/* Notify XPT */
+			ahd_send_async(ahd, devinfo.channel, devinfo.target,
+				       CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
+
 			/*
 			 * Allow the sequencer to continue with
 			 * non-pack processing.
@@ -1534,6 +1515,18 @@
 	lqistat1 = ahd_inb(ahd, LQISTAT1);
 	lqostat0 = ahd_inb(ahd, LQOSTAT0);
 	busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
+
+	/*
+	 * Ignore external resets after a bus reset.
+	 */
+	if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE))
+		return;
+
+	/*
+	 * Clear bus reset flag
+	 */
+	ahd->flags &= ~AHD_BUS_RESET_ACTIVE;
+
 	if ((status0 & (SELDI|SELDO)) != 0) {
 		u_int simode0;
 
@@ -2207,22 +2200,6 @@
 			if (sent_msg == MSG_ABORT_TAG)
 				tag = SCB_GET_TAG(scb);
 
-			if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
-				/*
-				 * This abort is in response to an
-				 * unexpected switch to command phase
-				 * for a packetized connection.  Since
-				 * the identify message was never sent,
-				 * "saved lun" is 0.  We really want to
-				 * abort only the SCB that encountered
-				 * this error, which could have a different
-				 * lun.  The SCB will be retried so the OS
-				 * will see the UA after renegotiating to
-				 * packetized.
-				 */
-				tag = SCB_GET_TAG(scb);
-				saved_lun = scb->hscb->lun;
-			}
 			found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
 					       tag, ROLE_INITIATOR,
 					       CAM_REQ_ABORTED);
@@ -7847,6 +7824,17 @@
 	int	found;
 	u_int	fifo;
 	u_int	next_fifo;
+	uint8_t scsiseq;
+
+	/*
+	 * Check if the last bus reset is cleared
+	 */
+	if (ahd->flags & AHD_BUS_RESET_ACTIVE) {
+		printf("%s: bus reset still active\n",
+		       ahd_name(ahd));
+		return 0;
+	}
+	ahd->flags |= AHD_BUS_RESET_ACTIVE;
 
 	ahd->pending_device = NULL;
 
@@ -7860,6 +7848,12 @@
 	/* Make sure the sequencer is in a safe location. */
 	ahd_clear_critical_section(ahd);
 
+	/*
+	 * Run our command complete fifos to ensure that we perform
+	 * completion processing on any commands that 'completed'
+	 * before the reset occurred.
+	 */
+	ahd_run_qoutfifo(ahd);
 #ifdef AHD_TARGET_MODE
 	if ((ahd->flags & AHD_TARGETROLE) != 0) {
 		ahd_run_tqinfifo(ahd, /*paused*/TRUE);
@@ -7924,30 +7918,14 @@
 	ahd_clear_fifo(ahd, 1);
 
 	/*
-	 * Revert to async/narrow transfers until we renegotiate.
+	 * Reenable selections
 	 */
+	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
+	scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE);
+	ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
+
 	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
-	for (target = 0; target <= max_scsiid; target++) {
-
-		if (ahd->enabled_targets[target] == NULL)
-			continue;
-		for (initiator = 0; initiator <= max_scsiid; initiator++) {
-			struct ahd_devinfo devinfo;
-
-			ahd_compile_devinfo(&devinfo, target, initiator,
-					    CAM_LUN_WILDCARD,
-					    'A', ROLE_UNKNOWN);
-			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
-				      AHD_TRANS_CUR, /*paused*/TRUE);
-			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
-					 /*offset*/0, /*ppr_options*/0,
-					 AHD_TRANS_CUR, /*paused*/TRUE);
-		}
-	}
-
 #ifdef AHD_TARGET_MODE
-	max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
-
 	/*
 	 * Send an immediate notify ccb to all target more peripheral
 	 * drivers affected by this action.
@@ -7975,53 +7953,33 @@
 	/* Notify the XPT that a bus reset occurred */
 	ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
 		       CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
-	ahd_restart(ahd);
+
 	/*
-	 * Freeze the SIMQ until our poller can determine that
-	 * the bus reset has really gone away.  We set the initial
-	 * timer to 0 to have the check performed as soon as possible
-	 * from the timer context.
+	 * Revert to async/narrow transfers until we renegotiate.
 	 */
-	if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
-		ahd->flags |= AHD_RESET_POLL_ACTIVE;
-		ahd_freeze_simq(ahd);
-		ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
+	for (target = 0; target <= max_scsiid; target++) {
+
+		if (ahd->enabled_targets[target] == NULL)
+			continue;
+		for (initiator = 0; initiator <= max_scsiid; initiator++) {
+			struct ahd_devinfo devinfo;
+
+			ahd_compile_devinfo(&devinfo, target, initiator,
+					    CAM_LUN_WILDCARD,
+					    'A', ROLE_UNKNOWN);
+			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+				      AHD_TRANS_CUR, /*paused*/TRUE);
+			ahd_set_syncrate(ahd, &devinfo, /*period*/0,
+					 /*offset*/0, /*ppr_options*/0,
+					 AHD_TRANS_CUR, /*paused*/TRUE);
+		}
 	}
+
+	ahd_restart(ahd);
+
 	return (found);
 }
 
-
-#define AHD_RESET_POLL_US 1000
-static void
-ahd_reset_poll(void *arg)
-{
-	struct	ahd_softc *ahd = arg;
-	u_int	scsiseq1;
-	u_long	s;
-	
-	ahd_lock(ahd, &s);
-	ahd_pause(ahd);
-	ahd_update_modes(ahd);
-	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-	ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
-	if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
-		ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US,
-				ahd_reset_poll, ahd);
-		ahd_unpause(ahd);
-		ahd_unlock(ahd, &s);
-		return;
-	}
-
-	/* Reset is now low.  Complete chip reinitialization. */
-	ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
-	scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
-	ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
-	ahd_unpause(ahd);
-	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
-	ahd_unlock(ahd, &s);
-	ahd_release_simq(ahd);
-}
-
 /**************************** Statistics Processing ***************************/
 static void
 ahd_stat_timer(void *arg)
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index bcced0a..66e4a47 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -782,6 +782,7 @@
 {
 	struct ahd_softc *ahd;
 	int    found;
+	unsigned long flags;
 
 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
 #ifdef AHD_DEBUG
@@ -789,8 +790,11 @@
 		printf("%s: Bus reset called for cmd %p\n",
 		       ahd_name(ahd), cmd);
 #endif
+	ahd_lock(ahd, &flags);
+
 	found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
 				  /*initiate reset*/TRUE);
+	ahd_unlock(ahd, &flags);
 
 	if (bootverbose)
 		printf("%s: SCSI bus reset delivered. "
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 24e71b5..6dc8814 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -209,7 +209,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ef57f25..dfcb96f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -294,18 +294,6 @@
 	if (sht->unchecked_isa_dma && privsize)
 		gfp_mask |= __GFP_DMA;
 
-        /* Check to see if this host has any error handling facilities */
-        if (!sht->eh_strategy_handler && !sht->eh_abort_handler &&
-	    !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler &&
-            !sht->eh_host_reset_handler) {
-		printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n"
-				"ERROR: This is not a safe way to run your "
-				        "SCSI host\n"
-				"ERROR: The error handling must be added to "
-				"this driver\n", sht->proc_name);
-		dump_stack();
-        }
-
 	shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
 	if (!shost)
 		return NULL;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index eaefedd..0a8ad37 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -168,7 +168,7 @@
 			++in_use;
 		if (pool->events[i].ext_list) {
 			dma_free_coherent(hostdata->dev,
-				  SG_ALL * sizeof(struct memory_descriptor),
+				  SG_ALL * sizeof(struct srp_direct_buf),
 				  pool->events[i].ext_list,
 				  pool->events[i].ext_list_token);
 		}
@@ -284,40 +284,37 @@
 			      struct srp_cmd *srp_cmd, 
 			      int numbuf)
 {
+	u8 fmt;
+
 	if (numbuf == 0)
 		return;
 	
-	if (numbuf == 1) {
+	if (numbuf == 1)
+		fmt = SRP_DATA_DESC_DIRECT;
+	else {
+		fmt = SRP_DATA_DESC_INDIRECT;
+		numbuf = min(numbuf, MAX_INDIRECT_BUFS);
+
 		if (cmd->sc_data_direction == DMA_TO_DEVICE)
-			srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
-		else 
-			srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
-	} else {
-		if (cmd->sc_data_direction == DMA_TO_DEVICE) {
-			srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
-			srp_cmd->data_out_count =
-				numbuf < MAX_INDIRECT_BUFS ?
-					numbuf: MAX_INDIRECT_BUFS;
-		} else {
-			srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
-			srp_cmd->data_in_count =
-				numbuf < MAX_INDIRECT_BUFS ?
-					numbuf: MAX_INDIRECT_BUFS;
-		}
+			srp_cmd->data_out_desc_cnt = numbuf;
+		else
+			srp_cmd->data_in_desc_cnt = numbuf;
 	}
+
+	if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		srp_cmd->buf_fmt = fmt << 4;
+	else
+		srp_cmd->buf_fmt = fmt;
 }
 
-static void unmap_sg_list(int num_entries, 
+static void unmap_sg_list(int num_entries,
 		struct device *dev,
-		struct memory_descriptor *md)
-{ 
+		struct srp_direct_buf *md)
+{
 	int i;
 
-	for (i = 0; i < num_entries; ++i) {
-		dma_unmap_single(dev,
-			md[i].virtual_address,
-			md[i].length, DMA_BIDIRECTIONAL);
-	}
+	for (i = 0; i < num_entries; ++i)
+		dma_unmap_single(dev, md[i].va, md[i].len, DMA_BIDIRECTIONAL);
 }
 
 /**
@@ -330,23 +327,26 @@
 			   struct srp_event_struct *evt_struct,
 			   struct device *dev)
 {
-	if ((cmd->data_out_format == SRP_NO_BUFFER) &&
-	    (cmd->data_in_format == SRP_NO_BUFFER))
+	u8 out_fmt, in_fmt;
+
+	out_fmt = cmd->buf_fmt >> 4;
+	in_fmt = cmd->buf_fmt & ((1U << 4) - 1);
+
+	if (out_fmt == SRP_NO_DATA_DESC && in_fmt == SRP_NO_DATA_DESC)
 		return;
-	else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
-		 (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
-		struct memory_descriptor *data =
-			(struct memory_descriptor *)cmd->additional_data;
-		dma_unmap_single(dev, data->virtual_address, data->length,
-				 DMA_BIDIRECTIONAL);
+	else if (out_fmt == SRP_DATA_DESC_DIRECT ||
+		 in_fmt == SRP_DATA_DESC_DIRECT) {
+		struct srp_direct_buf *data =
+			(struct srp_direct_buf *) cmd->add_data;
+		dma_unmap_single(dev, data->va, data->len, DMA_BIDIRECTIONAL);
 	} else {
-		struct indirect_descriptor *indirect =
-			(struct indirect_descriptor *)cmd->additional_data;
-		int num_mapped = indirect->head.length / 
-			sizeof(indirect->list[0]);
+		struct srp_indirect_buf *indirect =
+			(struct srp_indirect_buf *) cmd->add_data;
+		int num_mapped = indirect->table_desc.len /
+			sizeof(struct srp_direct_buf);
 
 		if (num_mapped <= MAX_INDIRECT_BUFS) {
-			unmap_sg_list(num_mapped, dev, &indirect->list[0]);
+			unmap_sg_list(num_mapped, dev, &indirect->desc_list[0]);
 			return;
 		}
 
@@ -356,17 +356,17 @@
 
 static int map_sg_list(int num_entries, 
 		       struct scatterlist *sg,
-		       struct memory_descriptor *md)
+		       struct srp_direct_buf *md)
 {
 	int i;
 	u64 total_length = 0;
 
 	for (i = 0; i < num_entries; ++i) {
-		struct memory_descriptor *descr = md + i;
+		struct srp_direct_buf *descr = md + i;
 		struct scatterlist *sg_entry = &sg[i];
-		descr->virtual_address = sg_dma_address(sg_entry);
-		descr->length = sg_dma_len(sg_entry);
-		descr->memory_handle = 0;
+		descr->va = sg_dma_address(sg_entry);
+		descr->len = sg_dma_len(sg_entry);
+		descr->key = 0;
 		total_length += sg_dma_len(sg_entry);
  	}
 	return total_length;
@@ -389,10 +389,10 @@
 	int sg_mapped;
 	u64 total_length = 0;
 	struct scatterlist *sg = cmd->request_buffer;
-	struct memory_descriptor *data =
-	    (struct memory_descriptor *)srp_cmd->additional_data;
-	struct indirect_descriptor *indirect =
-	    (struct indirect_descriptor *)data;
+	struct srp_direct_buf *data =
+		(struct srp_direct_buf *) srp_cmd->add_data;
+	struct srp_indirect_buf *indirect =
+		(struct srp_indirect_buf *) data;
 
 	sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
 
@@ -403,9 +403,9 @@
 
 	/* special case; we can use a single direct descriptor */
 	if (sg_mapped == 1) {
-		data->virtual_address = sg_dma_address(&sg[0]);
-		data->length = sg_dma_len(&sg[0]);
-		data->memory_handle = 0;
+		data->va = sg_dma_address(&sg[0]);
+		data->len = sg_dma_len(&sg[0]);
+		data->key = 0;
 		return 1;
 	}
 
@@ -416,25 +416,26 @@
 		return 0;
 	}
 
-	indirect->head.virtual_address = 0;
-	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
-	indirect->head.memory_handle = 0;
+	indirect->table_desc.va = 0;
+	indirect->table_desc.len = sg_mapped * sizeof(struct srp_direct_buf);
+	indirect->table_desc.key = 0;
 
 	if (sg_mapped <= MAX_INDIRECT_BUFS) {
-		total_length = map_sg_list(sg_mapped, sg, &indirect->list[0]);
-		indirect->total_length = total_length;
+		total_length = map_sg_list(sg_mapped, sg,
+					   &indirect->desc_list[0]);
+		indirect->len = total_length;
 		return 1;
 	}
 
 	/* get indirect table */
 	if (!evt_struct->ext_list) {
-		evt_struct->ext_list =(struct memory_descriptor*)
+		evt_struct->ext_list = (struct srp_direct_buf *)
 			dma_alloc_coherent(dev, 
-				SG_ALL * sizeof(struct memory_descriptor),
-				&evt_struct->ext_list_token, 0);
+					   SG_ALL * sizeof(struct srp_direct_buf),
+					   &evt_struct->ext_list_token, 0);
 		if (!evt_struct->ext_list) {
-		    printk(KERN_ERR
-		   	"ibmvscsi: Can't allocate memory for indirect table\n");
+			printk(KERN_ERR
+			       "ibmvscsi: Can't allocate memory for indirect table\n");
 			return 0;
 			
 		}
@@ -442,11 +443,11 @@
 
 	total_length = map_sg_list(sg_mapped, sg, evt_struct->ext_list);	
 
-	indirect->total_length = total_length;
-	indirect->head.virtual_address = evt_struct->ext_list_token;
-	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
-	memcpy(indirect->list, evt_struct->ext_list,
-		MAX_INDIRECT_BUFS * sizeof(struct memory_descriptor));
+	indirect->len = total_length;
+	indirect->table_desc.va = evt_struct->ext_list_token;
+	indirect->table_desc.len = sg_mapped * sizeof(indirect->desc_list[0]);
+	memcpy(indirect->desc_list, evt_struct->ext_list,
+	       MAX_INDIRECT_BUFS * sizeof(struct srp_direct_buf));
 	
  	return 1;
 }
@@ -463,20 +464,20 @@
 static int map_single_data(struct scsi_cmnd *cmd,
 			   struct srp_cmd *srp_cmd, struct device *dev)
 {
-	struct memory_descriptor *data =
-	    (struct memory_descriptor *)srp_cmd->additional_data;
+	struct srp_direct_buf *data =
+		(struct srp_direct_buf *) srp_cmd->add_data;
 
-	data->virtual_address =
+	data->va =
 		dma_map_single(dev, cmd->request_buffer,
 			       cmd->request_bufflen,
 			       DMA_BIDIRECTIONAL);
-	if (dma_mapping_error(data->virtual_address)) {
+	if (dma_mapping_error(data->va)) {
 		printk(KERN_ERR
 		       "ibmvscsi: Unable to map request_buffer for command!\n");
 		return 0;
 	}
-	data->length = cmd->request_bufflen;
-	data->memory_handle = 0;
+	data->len = cmd->request_bufflen;
+	data->key = 0;
 
 	set_srp_direction(cmd, srp_cmd, 1);
 
@@ -548,7 +549,7 @@
 
 	/* Copy the IU into the transfer area */
 	*evt_struct->xfer_iu = evt_struct->iu;
-	evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+	evt_struct->xfer_iu->srp.rsp.tag = (u64)evt_struct;
 
 	/* Add this to the sent list.  We need to do this 
 	 * before we actually send 
@@ -586,27 +587,27 @@
 	struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
 	struct scsi_cmnd *cmnd = evt_struct->cmnd;
 
-	if (unlikely(rsp->type != SRP_RSP_TYPE)) {
+	if (unlikely(rsp->opcode != SRP_RSP)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING 
 			       "ibmvscsi: bad SRP RSP type %d\n",
-			       rsp->type);
+			       rsp->opcode);
 	}
 	
 	if (cmnd) {
 		cmnd->result = rsp->status;
 		if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
 			memcpy(cmnd->sense_buffer,
-			       rsp->sense_and_response_data,
-			       rsp->sense_data_list_length);
+			       rsp->data,
+			       rsp->sense_data_len);
 		unmap_cmd_data(&evt_struct->iu.srp.cmd, 
 			       evt_struct, 
 			       evt_struct->hostdata->dev);
 
-		if (rsp->doover)
-			cmnd->resid = rsp->data_out_residual_count;
-		else if (rsp->diover)
-			cmnd->resid = rsp->data_in_residual_count;
+		if (rsp->flags & SRP_RSP_FLAG_DOOVER)
+			cmnd->resid = rsp->data_out_res_cnt;
+		else if (rsp->flags & SRP_RSP_FLAG_DIOVER)
+			cmnd->resid = rsp->data_in_res_cnt;
 	}
 
 	if (evt_struct->cmnd_done)
@@ -633,10 +634,11 @@
 {
 	struct srp_cmd *srp_cmd;
 	struct srp_event_struct *evt_struct;
-	struct indirect_descriptor *indirect;
+	struct srp_indirect_buf *indirect;
 	struct ibmvscsi_host_data *hostdata =
 		(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
 	u16 lun = lun_from_dev(cmnd->device);
+	u8 out_fmt, in_fmt;
 
 	evt_struct = get_event_struct(&hostdata->pool);
 	if (!evt_struct)
@@ -644,8 +646,8 @@
 
 	/* Set up the actual SRP IU */
 	srp_cmd = &evt_struct->iu.srp.cmd;
-	memset(srp_cmd, 0x00, sizeof(*srp_cmd));
-	srp_cmd->type = SRP_CMD_TYPE;
+	memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
+	srp_cmd->opcode = SRP_CMD;
 	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
 	srp_cmd->lun = ((u64) lun) << 48;
 
@@ -664,13 +666,15 @@
 	evt_struct->cmnd_done = done;
 
 	/* Fix up dma address of the buffer itself */
-	indirect = (struct indirect_descriptor *)srp_cmd->additional_data;
-	if (((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
-	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) &&
-	    (indirect->head.virtual_address == 0)) {
-		indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
-		    offsetof(struct srp_cmd, additional_data) +
-		    offsetof(struct indirect_descriptor, list);
+	indirect = (struct srp_indirect_buf *) srp_cmd->add_data;
+	out_fmt = srp_cmd->buf_fmt >> 4;
+	in_fmt = srp_cmd->buf_fmt & ((1U << 4) - 1);
+	if ((in_fmt == SRP_DATA_DESC_INDIRECT ||
+	     out_fmt == SRP_DATA_DESC_INDIRECT) &&
+	    indirect->table_desc.va == 0) {
+		indirect->table_desc.va = evt_struct->crq.IU_data_ptr +
+			offsetof(struct srp_cmd, add_data) +
+			offsetof(struct srp_indirect_buf, desc_list);
 	}
 
 	return ibmvscsi_send_srp_event(evt_struct, hostdata);
@@ -780,10 +784,10 @@
 static void login_rsp(struct srp_event_struct *evt_struct)
 {
 	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
-	switch (evt_struct->xfer_iu->srp.generic.type) {
-	case SRP_LOGIN_RSP_TYPE:	/* it worked! */
+	switch (evt_struct->xfer_iu->srp.login_rsp.opcode) {
+	case SRP_LOGIN_RSP:	/* it worked! */
 		break;
-	case SRP_LOGIN_REJ_TYPE:	/* refused! */
+	case SRP_LOGIN_REJ:	/* refused! */
 		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REJ reason %u\n",
 		       evt_struct->xfer_iu->srp.login_rej.reason);
 		/* Login failed.  */
@@ -792,7 +796,7 @@
 	default:
 		printk(KERN_ERR
 		       "ibmvscsi: Invalid login response typecode 0x%02x!\n",
-		       evt_struct->xfer_iu->srp.generic.type);
+		       evt_struct->xfer_iu->srp.login_rsp.opcode);
 		/* Login failed.  */
 		atomic_set(&hostdata->request_limit, -1);
 		return;
@@ -800,17 +804,17 @@
 
 	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
 
-	if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+	if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
 	    (max_requests - 2))
-		evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+		evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
 		    max_requests - 2;
 
 	/* Now we know what the real request-limit is */
 	atomic_set(&hostdata->request_limit,
-		   evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+		   evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
 
 	hostdata->host->can_queue =
-	    evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+	    evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
 
 	if (hostdata->host->can_queue < 1) {
 		printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
@@ -849,18 +853,19 @@
 
 	login = &evt_struct->iu.srp.login_req;
 	memset(login, 0x00, sizeof(struct srp_login_req));
-	login->type = SRP_LOGIN_REQ_TYPE;
-	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
-	login->required_buffer_formats = 0x0006;
+	login->opcode = SRP_LOGIN_REQ;
+	login->req_it_iu_len = sizeof(union srp_iu);
+	login->req_buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
 	
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	/* Start out with a request limit of 1, since this is negotiated in
 	 * the login request we are just sending
 	 */
 	atomic_set(&hostdata->request_limit, 1);
 
-	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+	printk("ibmvscsic: sent SRP login\n");
 	return rc;
 };
 
@@ -928,13 +933,13 @@
 	
 	/* Set up an abort SRP command */
 	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
-	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->opcode = SRP_TSK_MGMT;
 	tsk_mgmt->lun = ((u64) lun) << 48;
-	tsk_mgmt->task_mgmt_flags = 0x01;	/* ABORT TASK */
-	tsk_mgmt->managed_task_tag = (u64) found_evt;
+	tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
+	tsk_mgmt->task_tag = (u64) found_evt;
 
 	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
-	       tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+	       tsk_mgmt->lun, tsk_mgmt->task_tag);
 
 	evt->sync_srp = &srp_rsp;
 	init_completion(&evt->comp);
@@ -948,25 +953,25 @@
 	wait_for_completion(&evt->comp);
 
 	/* make sure we got a good response */
-	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+	if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING 
 			       "ibmvscsi: abort bad SRP RSP type %d\n",
-			       srp_rsp.srp.generic.type);
+			       srp_rsp.srp.rsp.opcode);
 		return FAILED;
 	}
 
-	if (srp_rsp.srp.rsp.rspvalid)
-		rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+	if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+		rsp_rc = *((int *)srp_rsp.srp.rsp.data);
 	else
 		rsp_rc = srp_rsp.srp.rsp.status;
 
 	if (rsp_rc) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING 
-		       "ibmvscsi: abort code %d for task tag 0x%lx\n",
+			       "ibmvscsi: abort code %d for task tag 0x%lx\n",
 			       rsp_rc,
-			       tsk_mgmt->managed_task_tag);
+			       tsk_mgmt->task_tag);
 		return FAILED;
 	}
 
@@ -987,13 +992,13 @@
 		spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 		printk(KERN_INFO
 		       "ibmvscsi: aborted task tag 0x%lx completed\n",
-		       tsk_mgmt->managed_task_tag);
+		       tsk_mgmt->task_tag);
 		return SUCCESS;
 	}
 
 	printk(KERN_INFO
 	       "ibmvscsi: successfully aborted task tag 0x%lx\n",
-	       tsk_mgmt->managed_task_tag);
+	       tsk_mgmt->task_tag);
 
 	cmd->result = (DID_ABORT << 16);
 	list_del(&found_evt->list);
@@ -1040,9 +1045,9 @@
 
 	/* Set up a lun reset SRP command */
 	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
-	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->opcode = SRP_TSK_MGMT;
 	tsk_mgmt->lun = ((u64) lun) << 48;
-	tsk_mgmt->task_mgmt_flags = 0x08;	/* LUN RESET */
+	tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
 
 	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
 	       tsk_mgmt->lun);
@@ -1059,16 +1064,16 @@
 	wait_for_completion(&evt->comp);
 
 	/* make sure we got a good response */
-	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
+	if (unlikely(srp_rsp.srp.rsp.opcode != SRP_RSP)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING 
 			       "ibmvscsi: reset bad SRP RSP type %d\n",
-			       srp_rsp.srp.generic.type);
+			       srp_rsp.srp.rsp.opcode);
 		return FAILED;
 	}
 
-	if (srp_rsp.srp.rsp.rspvalid)
-		rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
+	if (srp_rsp.srp.rsp.flags & SRP_RSP_FLAG_RSPVALID)
+		rsp_rc = *((int *)srp_rsp.srp.rsp.data);
 	else
 		rsp_rc = srp_rsp.srp.rsp.status;
 
@@ -1076,8 +1081,7 @@
 		if (printk_ratelimit())
 			printk(KERN_WARNING 
 			       "ibmvscsi: reset code %d for task tag 0x%lx\n",
-		       rsp_rc,
-			       tsk_mgmt->managed_task_tag);
+			       rsp_rc, tsk_mgmt->task_tag);
 		return FAILED;
 	}
 
@@ -1179,6 +1183,7 @@
 			/* We need to re-setup the interpartition connection */
 			printk(KERN_INFO
 			       "ibmvscsi: Re-enabling adapter!\n");
+			atomic_set(&hostdata->request_limit, -1);
 			purge_requests(hostdata, DID_REQUEUE);
 			if (ibmvscsi_reenable_crq_queue(&hostdata->queue,
 							hostdata) == 0)
@@ -1226,7 +1231,7 @@
 	}
 
 	if (crq->format == VIOSRP_SRP_FORMAT)
-		atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+		atomic_add(evt_struct->xfer_iu->srp.rsp.req_lim_delta,
 			   &hostdata->request_limit);
 
 	if (evt_struct->done)
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 4550d71..5c6d935 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -68,7 +68,7 @@
 	void (*cmnd_done) (struct scsi_cmnd *);
 	struct completion comp;
 	union viosrp_iu *sync_srp;
-	struct memory_descriptor *ext_list;
+	struct srp_direct_buf *ext_list;
 	dma_addr_t ext_list_token;
 };
 
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index f47dd87..1a9992b 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -34,7 +34,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include "ibmvscsi.h"
-#include "srp.h"
 
 static char partition_name[97] = "UNKNOWN";
 static unsigned int partition_number = -1;
@@ -80,7 +79,7 @@
 	tasklet_kill(&hostdata->srp_task);
 	do {
 		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 	dma_unmap_single(hostdata->dev,
 			 queue->msg_token,
 			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
@@ -230,7 +229,7 @@
 	rc = plpar_hcall_norets(H_REG_CRQ,
 				vdev->unit_address,
 				queue->msg_token, PAGE_SIZE);
-	if (rc == H_Resource) 
+	if (rc == H_RESOURCE)
 		/* maybe kexecing and resource is busy. try a reset */
 		rc = ibmvscsi_reset_crq_queue(queue,
 					      hostdata);
@@ -269,7 +268,7 @@
       req_irq_failed:
 	do {
 		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
       reg_crq_failed:
 	dma_unmap_single(hostdata->dev,
 			 queue->msg_token,
@@ -295,7 +294,7 @@
 	/* Re-enable the CRQ */
 	do {
 		rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address);
-	} while ((rc == H_InProgress) || (rc == H_Busy) || (H_isLongBusy(rc)));
+	} while ((rc == H_IN_PROGRESS) || (rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 
 	if (rc)
 		printk(KERN_ERR "ibmvscsi: Error %d enabling adapter\n", rc);
@@ -317,7 +316,7 @@
 	/* Close the CRQ */
 	do {
 		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
-	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+	} while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
 
 	/* Clean out the queue */
 	memset(queue->msgs, 0x00, PAGE_SIZE);
diff --git a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
deleted file mode 100644
index 7d8e4c4..0000000
--- a/drivers/scsi/ibmvscsi/srp.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*****************************************************************************/
-/* srp.h -- SCSI RDMA Protocol definitions                                   */
-/*                                                                           */
-/* Written By: Colin Devilbis, IBM Corporation                               */
-/*                                                                           */
-/* Copyright (C) 2003 IBM Corporation                                        */
-/*                                                                           */
-/* This program is free software; you can redistribute it and/or modify      */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* This program is distributed in the hope that it will be useful,           */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-/*                                                                           */
-/*                                                                           */
-/* This file contains structures and definitions for the SCSI RDMA Protocol  */
-/* (SRP) as defined in the T10 standard available at www.t10.org.  This      */
-/* file was based on the 16a version of the standard                         */
-/*                                                                           */
-/*****************************************************************************/
-#ifndef SRP_H
-#define SRP_H
-
-#define SRP_VERSION "16.a"
-
-#define PACKED __attribute__((packed))
-
-enum srp_types {
-	SRP_LOGIN_REQ_TYPE = 0x00,
-	SRP_LOGIN_RSP_TYPE = 0xC0,
-	SRP_LOGIN_REJ_TYPE = 0xC2,
-	SRP_I_LOGOUT_TYPE = 0x03,
-	SRP_T_LOGOUT_TYPE = 0x80,
-	SRP_TSK_MGMT_TYPE = 0x01,
-	SRP_CMD_TYPE = 0x02,
-	SRP_RSP_TYPE = 0xC1,
-	SRP_CRED_REQ_TYPE = 0x81,
-	SRP_CRED_RSP_TYPE = 0x41,
-	SRP_AER_REQ_TYPE = 0x82,
-	SRP_AER_RSP_TYPE = 0x42
-};
-
-enum srp_descriptor_formats {
-	SRP_NO_BUFFER = 0x00,
-	SRP_DIRECT_BUFFER = 0x01,
-	SRP_INDIRECT_BUFFER = 0x02
-};
-
-struct memory_descriptor {
-	u64 virtual_address;
-	u32 memory_handle;
-	u32 length;
-};
-
-struct indirect_descriptor {
-	struct memory_descriptor head;
-	u32 total_length;
-	struct memory_descriptor list[1] PACKED;
-};
-
-struct srp_generic {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-};
-
-struct srp_login_req {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-	u32 max_requested_initiator_to_target_iulen;
-	u32 reserved2;
-	u16 required_buffer_formats;
-	u8 reserved3:6;
-	u8 multi_channel_action:2;
-	u8 reserved4;
-	u32 reserved5;
-	u8 initiator_port_identifier[16];
-	u8 target_port_identifier[16];
-};
-
-struct srp_login_rsp {
-	u8 type;
-	u8 reserved1[3];
-	u32 request_limit_delta;
-	u64 tag;
-	u32 max_initiator_to_target_iulen;
-	u32 max_target_to_initiator_iulen;
-	u16 supported_buffer_formats;
-	u8 reserved2:6;
-	u8 multi_channel_result:2;
-	u8 reserved3;
-	u8 reserved4[24];
-};
-
-struct srp_login_rej {
-	u8 type;
-	u8 reserved1[3];
-	u32 reason;
-	u64 tag;
-	u64 reserved2;
-	u16 supported_buffer_formats;
-	u8 reserved3[6];
-};
-
-struct srp_i_logout {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-};
-
-struct srp_t_logout {
-	u8 type;
-	u8 reserved1[3];
-	u32 reason;
-	u64 tag;
-};
-
-struct srp_tsk_mgmt {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-	u32 reserved2;
-	u64 lun PACKED;
-	u8 reserved3;
-	u8 reserved4;
-	u8 task_mgmt_flags;
-	u8 reserved5;
-	u64 managed_task_tag;
-	u64 reserved6;
-};
-
-struct srp_cmd {
-	u8 type;
-	u32 reserved1 PACKED;
-	u8 data_out_format:4;
-	u8 data_in_format:4;
-	u8 data_out_count;
-	u8 data_in_count;
-	u64 tag;
-	u32 reserved2;
-	u64 lun PACKED;
-	u8 reserved3;
-	u8 reserved4:5;
-	u8 task_attribute:3;
-	u8 reserved5;
-	u8 additional_cdb_len;
-	u8 cdb[16];
-	u8 additional_data[0x100 - 0x30];
-};
-
-struct srp_rsp {
-	u8 type;
-	u8 reserved1[3];
-	u32 request_limit_delta;
-	u64 tag;
-	u16 reserved2;
-	u8 reserved3:2;
-	u8 diunder:1;
-	u8 diover:1;
-	u8 dounder:1;
-	u8 doover:1;
-	u8 snsvalid:1;
-	u8 rspvalid:1;
-	u8 status;
-	u32 data_in_residual_count;
-	u32 data_out_residual_count;
-	u32 sense_data_list_length;
-	u32 response_data_list_length;
-	u8 sense_and_response_data[18];
-};
-
-struct srp_cred_req {
-	u8 type;
-	u8 reserved1[3];
-	u32 request_limit_delta;
-	u64 tag;
-};
-
-struct srp_cred_rsp {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-};
-
-struct srp_aer_req {
-	u8 type;
-	u8 reserved1[3];
-	u32 request_limit_delta;
-	u64 tag;
-	u32 reserved2;
-	u64 lun;
-	u32 sense_data_list_length;
-	u32 reserved3;
-	u8 sense_data[20];
-};
-
-struct srp_aer_rsp {
-	u8 type;
-	u8 reserved1[7];
-	u64 tag;
-};
-
-union srp_iu {
-	struct srp_generic generic;
-	struct srp_login_req login_req;
-	struct srp_login_rsp login_rsp;
-	struct srp_login_rej login_rej;
-	struct srp_i_logout i_logout;
-	struct srp_t_logout t_logout;
-	struct srp_tsk_mgmt tsk_mgmt;
-	struct srp_cmd cmd;
-	struct srp_rsp rsp;
-	struct srp_cred_req cred_req;
-	struct srp_cred_rsp cred_rsp;
-	struct srp_aer_req aer_req;
-	struct srp_aer_rsp aer_rsp;
-};
-
-#endif
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
index 6a6bba8..90f1a61 100644
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ b/drivers/scsi/ibmvscsi/viosrp.h
@@ -33,7 +33,22 @@
 /*****************************************************************************/
 #ifndef VIOSRP_H
 #define VIOSRP_H
-#include "srp.h"
+#include <scsi/srp.h>
+
+#define SRP_VERSION "16.a"
+#define SRP_MAX_IU_LEN	256
+
+union srp_iu {
+	struct srp_login_req login_req;
+	struct srp_login_rsp login_rsp;
+	struct srp_login_rej login_rej;
+	struct srp_i_logout i_logout;
+	struct srp_t_logout t_logout;
+	struct srp_tsk_mgmt tsk_mgmt;
+	struct srp_cmd cmd;
+	struct srp_rsp rsp;
+	u8 reserved[SRP_MAX_IU_LEN];
+};
 
 enum viosrp_crq_formats {
 	VIOSRP_SRP_FORMAT = 0x01,
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5890e5f..8b80e59 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -164,29 +164,6 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IPR_DRIVER_VERSION);
 
-static const char *ipr_gpdd_dev_end_states[] = {
-	"Command complete",
-	"Terminated by host",
-	"Terminated by device reset",
-	"Terminated by bus reset",
-	"Unknown",
-	"Command not started"
-};
-
-static const char *ipr_gpdd_dev_bus_phases[] = {
-	"Bus free",
-	"Arbitration",
-	"Selection",
-	"Message out",
-	"Command",
-	"Message in",
-	"Data out",
-	"Data in",
-	"Status",
-	"Reselection",
-	"Unknown"
-};
-
 /*  A constant array of IOASCs/URCs/Error Messages */
 static const
 struct ipr_error_table_t ipr_error_table[] = {
@@ -869,8 +846,8 @@
 
 	if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) {
 		if (res->sdev) {
-			res->sdev->hostdata = NULL;
 			res->del_from_ml = 1;
+			res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
 			if (ioa_cfg->allow_ml_add_del)
 				schedule_work(&ioa_cfg->work_q);
 		} else
@@ -1356,8 +1333,8 @@
 		return;
 
 	if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) {
-		ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
-			    "%s\n", ipr_error_table[error_index].error);
+		ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
+			   "%s\n", ipr_error_table[error_index].error);
 	} else {
 		dev_err(&ioa_cfg->pdev->dev, "%s\n",
 			ipr_error_table[error_index].error);
@@ -2107,7 +2084,6 @@
 				did_work = 1;
 				sdev = res->sdev;
 				if (!scsi_device_get(sdev)) {
-					res->sdev = NULL;
 					list_move_tail(&res->queue, &ioa_cfg->free_res_q);
 					spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 					scsi_remove_device(sdev);
@@ -2124,6 +2100,7 @@
 			bus = res->cfgte.res_addr.bus;
 			target = res->cfgte.res_addr.target;
 			lun = res->cfgte.res_addr.lun;
+			res->add_to_ml = 0;
 			spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 			scsi_add_device(ioa_cfg->host, bus, target, lun);
 			spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -3214,7 +3191,7 @@
 			sdev->timeout = IPR_VSET_RW_TIMEOUT;
 			blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
 		}
-		if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+		if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
 			sdev->allow_restart = 1;
 		scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
 	}
@@ -3304,6 +3281,44 @@
 }
 
 /**
+ * ipr_device_reset - Reset the device
+ * @ioa_cfg:	ioa config struct
+ * @res:		resource entry struct
+ *
+ * This function issues a device reset to the affected device.
+ * If the device is a SCSI device, a LUN reset will be sent
+ * to the device first. If that does not work, a target reset
+ * will be sent.
+ *
+ * Return value:
+ *	0 on success / non-zero on failure
+ **/
+static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
+			    struct ipr_resource_entry *res)
+{
+	struct ipr_cmnd *ipr_cmd;
+	struct ipr_ioarcb *ioarcb;
+	struct ipr_cmd_pkt *cmd_pkt;
+	u32 ioasc;
+
+	ENTER;
+	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
+	ioarcb = &ipr_cmd->ioarcb;
+	cmd_pkt = &ioarcb->cmd_pkt;
+
+	ioarcb->res_handle = res->cfgte.res_handle;
+	cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
+	cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
+
+	ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
+	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
+	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
+
+	LEAVE;
+	return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0);
+}
+
+/**
  * ipr_eh_dev_reset - Reset the device
  * @scsi_cmd:	scsi command struct
  *
@@ -3319,8 +3334,7 @@
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_resource_entry *res;
-	struct ipr_cmd_pkt *cmd_pkt;
-	u32 ioasc;
+	int rc;
 
 	ENTER;
 	ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
@@ -3347,25 +3361,12 @@
 	}
 
 	res->resetting_device = 1;
-
-	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
-
-	ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
-	cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
-	cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
-	cmd_pkt->cdb[0] = IPR_RESET_DEVICE;
-
-	ipr_sdev_err(scsi_cmd->device, "Resetting device\n");
-	ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT);
-
-	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
-
+	scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n");
+	rc = ipr_device_reset(ioa_cfg, res);
 	res->resetting_device = 0;
 
-	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
-
 	LEAVE;
-	return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
+	return (rc ? FAILED : SUCCESS);
 }
 
 static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
@@ -3440,7 +3441,7 @@
 		return;
 	}
 
-	ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n");
+	sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n");
 	reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ipr_cmd->sibling = reset_cmd;
 	reset_cmd->sibling = ipr_cmd;
@@ -3504,7 +3505,8 @@
 	cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
 	ipr_cmd->u.sdev = scsi_cmd->device;
 
-	ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
+	scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n",
+		    scsi_cmd->cmnd[0]);
 	ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
 	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
@@ -3815,8 +3817,8 @@
 
 	if (IPR_IOASC_SENSE_KEY(ioasc) > 0) {
 		scsi_cmd->result |= (DID_ERROR << 16);
-		ipr_sdev_err(scsi_cmd->device,
-			     "Request Sense failed with IOASC: 0x%08X\n", ioasc);
+		scmd_printk(KERN_ERR, scsi_cmd,
+			    "Request Sense failed with IOASC: 0x%08X\n", ioasc);
 	} else {
 		memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer,
 		       SCSI_SENSE_BUFFERSIZE);
@@ -3938,6 +3940,7 @@
  * ipr_dump_ioasa - Dump contents of IOASA
  * @ioa_cfg:	ioa config struct
  * @ipr_cmd:	ipr command struct
+ * @res:		resource entry struct
  *
  * This function is invoked by the interrupt handler when ops
  * fail. It will log the IOASA if appropriate. Only called
@@ -3947,7 +3950,7 @@
  * 	none
  **/
 static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
-			   struct ipr_cmnd *ipr_cmd)
+			   struct ipr_cmnd *ipr_cmd, struct ipr_resource_entry *res)
 {
 	int i;
 	u16 data_len;
@@ -3975,16 +3978,7 @@
 			return;
 	}
 
-	ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n",
-		     ipr_error_table[error_index].error);
-
-	if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) &&
-	    (ioasa->u.gpdd.bus_phase <=  ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) {
-		ipr_sdev_err(ipr_cmd->scsi_cmd->device,
-			     "Device End state: %s Phase: %s\n",
-			     ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state],
-			     ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]);
-	}
+	ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error);
 
 	if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len))
 		data_len = sizeof(struct ipr_ioasa);
@@ -4141,7 +4135,7 @@
 	}
 
 	if (ipr_is_gscsi(res))
-		ipr_dump_ioasa(ioa_cfg, ipr_cmd);
+		ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
 	else
 		ipr_gen_sense(ipr_cmd);
 
@@ -4540,7 +4534,7 @@
 	ipr_cmd->job_step = ipr_ioa_reset_done;
 
 	list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) {
-		if (!IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+		if (!ipr_is_scsi_disk(res))
 			continue;
 
 		ipr_cmd->u.res = res;
@@ -4980,7 +4974,7 @@
 	list_for_each_entry_safe(res, temp, &old_res, queue) {
 		if (res->sdev) {
 			res->del_from_ml = 1;
-			res->sdev->hostdata = NULL;
+			res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
 			list_move_tail(&res->queue, &ioa_cfg->used_res_q);
 		} else {
 			list_move_tail(&res->queue, &ioa_cfg->free_res_q);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index fd360bf..1ad24df 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.1.2"
-#define IPR_DRIVER_DATE "(February 8, 2006)"
+#define IPR_DRIVER_VERSION "2.1.3"
+#define IPR_DRIVER_DATE "(March 29, 2006)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -133,6 +133,7 @@
 #define IPR_MAX_SCSI_RATE(width) ((320 * 10) / ((width) / 8))
 
 #define IPR_IOA_RES_HANDLE				0xffffffff
+#define IPR_INVALID_RES_HANDLE			0
 #define IPR_IOA_RES_ADDR				0x00ffffff
 
 /*
@@ -1191,30 +1192,17 @@
  */
 #define ipr_err(...) printk(KERN_ERR IPR_NAME ": "__VA_ARGS__)
 #define ipr_info(...) printk(KERN_INFO IPR_NAME ": "__VA_ARGS__)
-#define ipr_crit(...) printk(KERN_CRIT IPR_NAME ": "__VA_ARGS__)
-#define ipr_warn(...) printk(KERN_WARNING IPR_NAME": "__VA_ARGS__)
 #define ipr_dbg(...) IPR_DBG_CMD(printk(KERN_INFO IPR_NAME ": "__VA_ARGS__))
 
-#define ipr_sdev_printk(level, sdev, fmt, args...) \
-	sdev_printk(level, sdev, fmt, ## args)
+#define ipr_ra_printk(level, ioa_cfg, ra, fmt, ...) \
+	printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, (ioa_cfg)->host->host_no, \
+		(ra).bus, (ra).target, (ra).lun, ##__VA_ARGS__)
 
-#define ipr_sdev_err(sdev, fmt, ...) \
-	ipr_sdev_printk(KERN_ERR, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_info(sdev, fmt, ...) \
-	ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__)
-
-#define ipr_sdev_dbg(sdev, fmt, ...) \
-	IPR_DBG_CMD(ipr_sdev_printk(KERN_INFO, sdev, fmt, ##__VA_ARGS__))
-
-#define ipr_res_printk(level, ioa_cfg, res, fmt, ...) \
-	printk(level IPR_NAME ": %d:%d:%d:%d: " fmt, ioa_cfg->host->host_no, \
-		res.bus, res.target, res.lun, ##__VA_ARGS__)
+#define ipr_ra_err(ioa_cfg, ra, fmt, ...) \
+	ipr_ra_printk(KERN_ERR, ioa_cfg, ra, fmt, ##__VA_ARGS__)
 
 #define ipr_res_err(ioa_cfg, res, fmt, ...) \
-	ipr_res_printk(KERN_ERR, ioa_cfg, res, fmt, ##__VA_ARGS__)
-#define ipr_res_dbg(ioa_cfg, res, fmt, ...) \
-	IPR_DBG_CMD(ipr_res_printk(KERN_INFO, ioa_cfg, res, fmt, ##__VA_ARGS__))
+	ipr_ra_err(ioa_cfg, (res)->cfgte.res_addr, fmt, ##__VA_ARGS__)
 
 #define ipr_phys_res_err(ioa_cfg, res, fmt, ...)			\
 {									\
@@ -1304,6 +1292,22 @@
 }
 
 /**
+ * ipr_is_scsi_disk - Determine if a resource is a SCSI disk
+ * @res:	resource entry struct
+ *
+ * Return value:
+ * 	1 if SCSI disk / 0 if not SCSI disk
+ **/
+static inline int ipr_is_scsi_disk(struct ipr_resource_entry *res)
+{
+	if (ipr_is_af_dasd_device(res) ||
+	    (ipr_is_gscsi(res) && IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)))
+		return 1;
+	else
+		return 0;
+}
+
+/**
  * ipr_is_naca_model - Determine if a resource is using NACA queueing model
  * @res:	resource entry struct
  *
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index e63c1ff..bd14720 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4938,7 +4938,6 @@
 EXPORT_SYMBOL_GPL(ata_port_queue_task);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
-EXPORT_SYMBOL_GPL(ata_scsi_error);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 53f5b0d..a0289ec 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -53,6 +53,7 @@
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+static void ata_scsi_error(struct Scsi_Host *host);
 enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 
 #define RW_RECOVERY_MPAGE 0x1
@@ -99,6 +100,7 @@
  * It just needs the eh_timed_out hook.
  */
 struct scsi_transport_template ata_scsi_transport_template = {
+	.eh_strategy_handler	= ata_scsi_error,
 	.eh_timed_out		= ata_scsi_timed_out,
 };
 
@@ -772,12 +774,9 @@
  *
  *	LOCKING:
  *	Inherited from SCSI layer (none, can sleep)
- *
- *	RETURNS:
- *	Zero.
  */
 
-int ata_scsi_error(struct Scsi_Host *host)
+static void ata_scsi_error(struct Scsi_Host *host)
 {
 	struct ata_port *ap;
 	unsigned long flags;
@@ -805,7 +804,6 @@
 	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
 	DPRINTK("EXIT\n");
-	return 0;
 }
 
 static void ata_eh_scsidone(struct scsi_cmnd *scmd)
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 1c755b1..bac8cba 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -60,7 +60,6 @@
 extern struct scsi_transport_template ata_scsi_transport_template;
 
 extern void ata_scsi_scan_host(struct ata_port *ap);
-extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
 
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 5609847..ee449b2 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -89,29 +89,29 @@
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t		node;
     struct Scsi_Host	*host;
 } scsi_info_t;
 
-static void aha152x_release_cs(dev_link_t *link);
+static void aha152x_release_cs(struct pcmcia_device *link);
 static void aha152x_detach(struct pcmcia_device *p_dev);
-static void aha152x_config_cs(dev_link_t *link);
+static int aha152x_config_cs(struct pcmcia_device *link);
 
-static dev_link_t *dev_list;
+static struct pcmcia_device *dev_list;
 
-static int aha152x_attach(struct pcmcia_device *p_dev)
+static int aha152x_probe(struct pcmcia_device *link)
 {
     scsi_info_t *info;
-    dev_link_t *link;
-    
+
     DEBUG(0, "aha152x_attach()\n");
 
     /* Create new SCSI device */
     info = kmalloc(sizeof(*info), GFP_KERNEL);
     if (!info) return -ENOMEM;
     memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
+    info->p_dev = link;
+    link->priv = info;
 
     link->io.NumPorts1 = 0x20;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -119,41 +119,22 @@
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
-
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    aha152x_config_cs(link);
-
-    return 0;
+    return aha152x_config_cs(link);
 } /* aha152x_attach */
 
 /*====================================================================*/
 
-static void aha152x_detach(struct pcmcia_device *p_dev)
+static void aha152x_detach(struct pcmcia_device *link)
 {
-    dev_link_t *link = dev_to_instance(p_dev);
-    dev_link_t **linkp;
-
     DEBUG(0, "aha152x_detach(0x%p)\n", link);
-    
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-	if (*linkp == link) break;
-    if (*linkp == NULL)
-	return;
 
-    if (link->state & DEV_CONFIG)
-	aha152x_release_cs(link);
+    aha152x_release_cs(link);
 
     /* Unlink device structure, free bits */
-    *linkp = link->next;
     kfree(link->priv);
-    
 } /* aha152x_detach */
 
 /*====================================================================*/
@@ -161,9 +142,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void aha152x_config_cs(dev_link_t *link)
+static int aha152x_config_cs(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     scsi_info_t *info = link->priv;
     struct aha152x_setup s;
     tuple_t tuple;
@@ -178,19 +158,16 @@
     tuple.TupleData = tuple_data;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 	    goto next_entry;
 	/* For New Media T&J, look for a SCSI window */
 	if (parse.cftable_entry.io.win[0].len >= 0x20)
@@ -201,15 +178,15 @@
 	if ((parse.cftable_entry.io.nwin > 0) &&
 	    (link->io.BasePort1 < 0xffff)) {
 	    link->conf.ConfigIndex = parse.cftable_entry.index;
-	    i = pcmcia_request_io(handle, &link->io);
+	    i = pcmcia_request_io(link, &link->io);
 	    if (i == CS_SUCCESS) break;
 	}
     next_entry:
-	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
     
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     
     /* Set configuration options for the aha152x driver */
     memset(&s, 0, sizeof(s));
@@ -231,53 +208,30 @@
     }
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
     info->host = host;
 
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     aha152x_release_cs(link);
-    return;
+    return -ENODEV;
 }
 
-static void aha152x_release_cs(dev_link_t *link)
+static void aha152x_release_cs(struct pcmcia_device *link)
 {
 	scsi_info_t *info = link->priv;
 
 	aha152x_release(info->host);
-	link->dev = NULL;
-    
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-    
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 }
 
-static int aha152x_suspend(struct pcmcia_device *dev)
+static int aha152x_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int aha152x_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
 	scsi_info_t *info = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		aha152x_host_reset_host(info->host);
-	}
+	aha152x_host_reset_host(info->host);
 
 	return 0;
 }
@@ -297,10 +251,9 @@
 	.drv		= {
 		.name	= "aha152x_cs",
 	},
-	.probe		= aha152x_attach,
+	.probe		= aha152x_probe,
 	.remove		= aha152x_detach,
 	.id_table       = aha152x_ids,
-	.suspend	= aha152x_suspend,
 	.resume		= aha152x_resume,
 };
 
@@ -317,4 +270,3 @@
 
 module_init(init_aha152x_cs);
 module_exit(exit_aha152x_cs);
- 
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 788c58d..85f7ffa 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -73,57 +73,48 @@
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-    dev_link_t		link;
+	struct pcmcia_device	*p_dev;
     dev_node_t		node;
     struct Scsi_Host	*host;
 } scsi_info_t;
 
 
-static void fdomain_release(dev_link_t *link);
+static void fdomain_release(struct pcmcia_device *link);
 static void fdomain_detach(struct pcmcia_device *p_dev);
-static void fdomain_config(dev_link_t *link);
+static int fdomain_config(struct pcmcia_device *link);
 
-static int fdomain_attach(struct pcmcia_device *p_dev)
+static int fdomain_probe(struct pcmcia_device *link)
 {
-    scsi_info_t *info;
-    dev_link_t *link;
+	scsi_info_t *info;
 
-    DEBUG(0, "fdomain_attach()\n");
+	DEBUG(0, "fdomain_attach()\n");
 
-    /* Create new SCSI device */
-    info = kmalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return -ENOMEM;
-    memset(info, 0, sizeof(*info));
-    link = &info->link; link->priv = info;
-    link->io.NumPorts1 = 0x10;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 10;
-    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Vcc = 50;
-    link->conf.IntType = INT_MEMORY_AND_IO;
-    link->conf.Present = PRESENT_OPTION;
+	/* Create new SCSI device */
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
 
-    link->handle = p_dev;
-    p_dev->instance = link;
+	info->p_dev = link;
+	link->priv = info;
+	link->io.NumPorts1 = 0x10;
+	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+	link->io.IOAddrLines = 10;
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+	link->conf.Present = PRESENT_OPTION;
 
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    fdomain_config(link);
-
-    return 0;
+	return fdomain_config(link);
 } /* fdomain_attach */
 
 /*====================================================================*/
 
-static void fdomain_detach(struct pcmcia_device *p_dev)
+static void fdomain_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "fdomain_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		fdomain_release(link);
+	fdomain_release(link);
 
 	kfree(link->priv);
 } /* fdomain_detach */
@@ -133,9 +124,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void fdomain_config(dev_link_t *link)
+static int fdomain_config(struct pcmcia_device *link)
 {
-    client_handle_t handle = link->handle;
     scsi_info_t *info = link->priv;
     tuple_t tuple;
     cisparse_t parse;
@@ -150,103 +140,75 @@
     tuple.TupleData = tuple_data;
     tuple.TupleDataMax = 64;
     tuple.TupleOffset = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
     link->conf.ConfigBase = parse.config.base;
 
-    /* Configure card */
-    link->state |= DEV_CONFIG;
-    
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (1) {
-	if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 	    goto next_entry;
 	link->conf.ConfigIndex = parse.cftable_entry.index;
 	link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-	i = pcmcia_request_io(handle, &link->io);
+	i = pcmcia_request_io(link, &link->io);
 	if (i == CS_SUCCESS) break;
     next_entry:
-	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+	CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
     }
 
-    CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
-    
+    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
     /* A bad hack... */
     release_region(link->io.BasePort1, link->io.NumPorts1);
 
     /* Set configuration options for the fdomain driver */
     sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
     fdomain_setup(str);
-    
+
     host = __fdomain_16x0_detect(&fdomain_driver_template);
     if (!host) {
         printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
 	goto cs_failed;
     }
- 
-    scsi_add_host(host, NULL); /* XXX handle failure */
+
+    if (scsi_add_host(host, NULL))
+	    goto cs_failed;
     scsi_scan_host(host);
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
-    link->dev = &info->node;
+    link->dev_node = &info->node;
     info->host = host;
-    
-    link->state &= ~DEV_CONFIG_PENDING;
-    return;
-    
+
+    return 0;
+
 cs_failed:
-    cs_error(link->handle, last_fn, last_ret);
+    cs_error(link, last_fn, last_ret);
     fdomain_release(link);
-    return;
-    
+    return -ENODEV;
 } /* fdomain_config */
 
 /*====================================================================*/
 
-static void fdomain_release(dev_link_t *link)
+static void fdomain_release(struct pcmcia_device *link)
 {
-    scsi_info_t *info = link->priv;
+	scsi_info_t *info = link->priv;
 
-    DEBUG(0, "fdomain_release(0x%p)\n", link);
+	DEBUG(0, "fdomain_release(0x%p)\n", link);
 
-    scsi_remove_host(info->host);
-    link->dev = NULL;
-    
-    pcmcia_release_configuration(link->handle);
-    pcmcia_release_io(link->handle, &link->io);
-    pcmcia_release_irq(link->handle, &link->irq);
-
-    scsi_unregister(info->host);
-
-    link->state &= ~DEV_CONFIG;
+	scsi_remove_host(info->host);
+	pcmcia_disable_device(link);
+	scsi_unregister(info->host);
 }
 
 /*====================================================================*/
 
-static int fdomain_suspend(struct pcmcia_device *dev)
+static int fdomain_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int fdomain_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-		fdomain_16x0_bus_reset(NULL);
-	}
+	fdomain_16x0_bus_reset(NULL);
 
 	return 0;
 }
@@ -264,10 +226,9 @@
 	.drv		= {
 		.name	= "fdomain_cs",
 	},
-	.probe		= fdomain_attach,
+	.probe		= fdomain_probe,
 	.remove		= fdomain_detach,
 	.id_table       = fdomain_ids,
-	.suspend	= fdomain_suspend,
 	.resume		= fdomain_resume,
 };
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 9e3ab3f..231f9c3 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1593,11 +1593,11 @@
     configure the card at this point -- we wait until we receive a
     card insertion event.
 ======================================================================*/
-static int nsp_cs_attach(struct pcmcia_device *p_dev)
+static int nsp_cs_probe(struct pcmcia_device *link)
 {
 	scsi_info_t  *info;
-	dev_link_t   *link;
 	nsp_hw_data  *data = &nsp_data_base;
+	int ret;
 
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
@@ -1605,7 +1605,7 @@
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (info == NULL) { return -ENOMEM; }
 	memset(info, 0, sizeof(*info));
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 	data->ScsiInfo = info;
 
@@ -1627,18 +1627,13 @@
 
 	/* General socket configuration */
 	link->conf.Attributes	 = CONF_ENABLE_IRQ;
-	link->conf.Vcc		 = 50;
 	link->conf.IntType	 = INT_MEMORY_AND_IO;
 	link->conf.Present	 = PRESENT_OPTION;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	nsp_cs_config(link);
+	ret = nsp_cs_config(link);
 
 	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
-	return 0;
+	return ret;
 } /* nsp_cs_attach */
 
 
@@ -1648,16 +1643,12 @@
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 ======================================================================*/
-static void nsp_cs_detach(struct pcmcia_device *p_dev)
+static void nsp_cs_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
 
-	if (link->state & DEV_CONFIG) {
-		((scsi_info_t *)link->priv)->stop = 1;
-		nsp_cs_release(link);
-	}
+	((scsi_info_t *)link->priv)->stop = 1;
+	nsp_cs_release(link);
 
 	kfree(link->priv);
 	link->priv = NULL;
@@ -1672,9 +1663,9 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 /*====================================================================*/
-static void nsp_cs_config(dev_link_t *link)
+static int nsp_cs_config(struct pcmcia_device *link)
 {
-	client_handle_t	  handle = link->handle;
+	int		  ret;
 	scsi_info_t	 *info	 = link->priv;
 	tuple_t		  tuple;
 	cisparse_t	  parse;
@@ -1698,26 +1689,22 @@
 	tuple.TupleData	      = tuple_data;
 	tuple.TupleDataMax    = sizeof(tuple_data);
 	tuple.TupleOffset     = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData,	pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple,	pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData,	pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple,	pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present    = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state	      |= DEV_CONFIG;
-
 	/* Look up the current Vcc */
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-	link->conf.Vcc = conf.Vcc;
+	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
@@ -1743,10 +1730,10 @@
 		}
 
 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		} else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		}
 
@@ -1773,7 +1760,7 @@
 				link->io.NumPorts2 = io->win[1].len;
 			}
 			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(link->handle, &link->io) != 0)
+			if (pcmcia_request_io(link, &link->io) != 0)
 				goto next_entry;
 		}
 
@@ -1788,7 +1775,7 @@
 				req.Size = 0x1000;
 			}
 			req.AccessSpeed = 0;
-			if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+			if (pcmcia_request_window(&link, &req, &link->win) != 0)
 				goto next_entry;
 			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
 			if (pcmcia_map_mem_page(link->win, &map) != 0)
@@ -1802,17 +1789,14 @@
 
 	next_entry:
 		nsp_dbg(NSP_DEBUG_INIT, "next");
-
-		if (link->io.NumPorts1) {
-			pcmcia_release_io(link->handle, &link->io);
-		}
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		pcmcia_disable_device(link);
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 
 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-		CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
 	}
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	if (free_ports) {
 		if (link->io.BasePort1) {
@@ -1854,16 +1838,19 @@
 
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
-	scsi_add_host (host, NULL);
+	ret = scsi_add_host (host, NULL);
+	if (ret)
+		goto cs_failed;
+
 	scsi_scan_host(host);
 
 	snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
-	link->dev  = &info->node;
+	link->dev_node  = &info->node;
 	info->host = host;
 
 #else
 	nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
-	tail = &link->dev;
+	tail = &link->dev_node;
 	info->ndev = 0;
 
 	nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
@@ -1908,11 +1895,10 @@
 #endif
 
 	/* Finally, report what we've done */
-	printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",
-	       link->conf.ConfigIndex,
-	       link->conf.Vcc/10, link->conf.Vcc%10);
-	if (link->conf.Vpp1) {
-		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+	printk(KERN_INFO "nsp_cs: index 0x%02x: ",
+	       link->conf.ConfigIndex);
+	if (link->conf.Vpp) {
+		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
 	}
 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
 		printk(", irq %d", link->irq.AssignedIRQ);
@@ -1929,15 +1915,14 @@
 		       req.Base+req.Size-1);
 	printk("\n");
 
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	return 0;
 
  cs_failed:
 	nsp_dbg(NSP_DEBUG_INIT, "config fail");
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	nsp_cs_release(link);
 
-	return;
+	return -ENODEV;
 } /* nsp_cs_config */
 #undef CS_CHECK
 
@@ -1947,7 +1932,7 @@
     device, and release the PCMCIA configuration.  If the device is
     still open, this will be postponed until it is closed.
 ======================================================================*/
-static void nsp_cs_release(dev_link_t *link)
+static void nsp_cs_release(struct pcmcia_device *link)
 {
 	scsi_info_t *info = link->priv;
 	nsp_hw_data *data = NULL;
@@ -1968,22 +1953,15 @@
 #else
 	scsi_unregister_host(&nsp_driver_template);
 #endif
-	link->dev = NULL;
+	link->dev_node = NULL;
 
 	if (link->win) {
 		if (data != NULL) {
 			iounmap((void *)(data->MmioAddress));
 		}
-		pcmcia_release_window(link->win);
 	}
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1) {
-		pcmcia_release_io(link->handle, &link->io);
-	}
-	if (link->irq.AssignedIRQ) {
-		pcmcia_release_irq(link->handle, &link->irq);
-	}
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
 	if (info->host != NULL) {
 		scsi_host_put(info->host);
@@ -1991,14 +1969,11 @@
 #endif
 } /* nsp_cs_release */
 
-static int nsp_cs_suspend(struct pcmcia_device *dev)
+static int nsp_cs_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	scsi_info_t *info = link->priv;
 	nsp_hw_data *data;
 
-	link->state |= DEV_SUSPEND;
-
 	nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
 
 	if (info->host != NULL) {
@@ -2011,25 +1986,16 @@
 
 	info->stop = 1;
 
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
 	return 0;
 }
 
-static int nsp_cs_resume(struct pcmcia_device *dev)
+static int nsp_cs_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	scsi_info_t *info = link->priv;
 	nsp_hw_data *data;
 
 	nsp_dbg(NSP_DEBUG_INIT, "event: resume");
 
-	link->state &= ~DEV_SUSPEND;
-
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
 	info->stop = 0;
 
 	if (info->host != NULL) {
@@ -2065,7 +2031,7 @@
 	.drv		= {
 		.name	= "nsp_cs",
 	},
-	.probe		= nsp_cs_attach,
+	.probe		= nsp_cs_probe,
 	.remove		= nsp_cs_detach,
 	.id_table	= nsp_cs_ids,
 	.suspend	= nsp_cs_suspend,
@@ -2098,19 +2064,7 @@
 static void __exit nsp_cs_exit(void)
 {
 	nsp_msg(KERN_INFO, "unloading...");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
 	pcmcia_unregister_driver(&nsp_driver);
-#else
-	unregister_pcmcia_driver(&dev_info);
-	/* XXX: this really needs to move into generic code.. */
-	while (dev_list != NULL) {
-		if (dev_list->state & DEV_CONFIG) {
-			nsp_cs_release(dev_list);
-		}
-		nsp_cs_detach(dev_list);
-	}
-#endif
 }
 
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index b66b140..8908b8e 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -225,7 +225,7 @@
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-	dev_link_t             link;
+	struct pcmcia_device	*p_dev;
 	struct Scsi_Host      *host;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
 	dev_node_t             node;
@@ -297,8 +297,8 @@
 
 /* Card service functions */
 static void        nsp_cs_detach (struct pcmcia_device *p_dev);
-static void        nsp_cs_release(dev_link_t *link);
-static void        nsp_cs_config (dev_link_t *link);
+static void        nsp_cs_release(struct pcmcia_device *link);
+static int        nsp_cs_config (struct pcmcia_device *link);
 
 /* Linux SCSI subsystem specific functions */
 static struct Scsi_Host *nsp_detect     (struct scsi_host_template *sht);
@@ -450,7 +450,7 @@
 	return host;
 }
 
-static void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(struct pcmcia_device *handle, int func, int ret)
 {
 	error_info_t err = { func, ret };
 	pcmcia_report_error(handle, &err);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index dce7e68..86c2ac6 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -91,18 +91,18 @@
 /*====================================================================*/
 
 typedef struct scsi_info_t {
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 	struct Scsi_Host *host;
 	unsigned short manf_id;
 } scsi_info_t;
 
-static void qlogic_release(dev_link_t *link);
+static void qlogic_release(struct pcmcia_device *link);
 static void qlogic_detach(struct pcmcia_device *p_dev);
-static void qlogic_config(dev_link_t * link);
+static int qlogic_config(struct pcmcia_device * link);
 
 static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
-				dev_link_t *link, int qbase, int qlirq)
+				struct pcmcia_device *link, int qbase, int qlirq)
 {
 	int qltyp;		/* type of chip */
 	int qinitid;
@@ -156,10 +156,9 @@
 err:
 	return NULL;
 }
-static int qlogic_attach(struct pcmcia_device *p_dev)
+static int qlogic_probe(struct pcmcia_device *link)
 {
 	scsi_info_t *info;
-	dev_link_t *link;
 
 	DEBUG(0, "qlogic_attach()\n");
 
@@ -168,7 +167,7 @@
 	if (!info)
 		return -ENOMEM;
 	memset(info, 0, sizeof(*info));
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 	link->io.NumPorts1 = 16;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -176,30 +175,19 @@
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	qlogic_config(link);
-
-	return 0;
+	return qlogic_config(link);
 }				/* qlogic_attach */
 
 /*====================================================================*/
 
-static void qlogic_detach(struct pcmcia_device *p_dev)
+static void qlogic_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "qlogic_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		qlogic_release(link);
-
+	qlogic_release(link);
 	kfree(link->priv);
 
 }				/* qlogic_detach */
@@ -209,9 +197,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void qlogic_config(dev_link_t * link)
+static int qlogic_config(struct pcmcia_device * link)
 {
-	client_handle_t handle = link->handle;
 	scsi_info_t *info = link->priv;
 	tuple_t tuple;
 	cisparse_t parse;
@@ -225,38 +212,35 @@
 	tuple.TupleDataMax = 64;
 	tuple.TupleOffset = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 
 	tuple.DesiredTuple = CISTPL_MANFID;
-	if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+	if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
 		info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 		link->conf.ConfigIndex = parse.cftable_entry.index;
 		link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
 		link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
 		if (link->io.BasePort1 != 0) {
-			i = pcmcia_request_io(handle, &link->io);
+			i = pcmcia_request_io(link, &link->io);
 			if (i == CS_SUCCESS)
 				break;
 		}
 	      next_entry:
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
 		/* set ATAcmd */
@@ -275,82 +259,54 @@
 	
 	if (!host) {
 		printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
-		goto out;
+		goto cs_failed;
 	}
 
 	sprintf(info->node.dev_name, "scsi%d", host->host_no);
-	link->dev = &info->node;
+	link->dev_node = &info->node;
 	info->host = host;
 
-out:
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
-	link->dev = NULL;
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
-	return;
+	cs_error(link, last_fn, last_ret);
+	pcmcia_disable_device(link);
+	return -ENODEV;
 
 }				/* qlogic_config */
 
 /*====================================================================*/
 
-static void qlogic_release(dev_link_t *link)
+static void qlogic_release(struct pcmcia_device *link)
 {
 	scsi_info_t *info = link->priv;
 
 	DEBUG(0, "qlogic_release(0x%p)\n", link);
 
 	scsi_remove_host(info->host);
-	link->dev = NULL;
 
 	free_irq(link->irq.AssignedIRQ, info->host);
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
+	pcmcia_disable_device(link);
 
 	scsi_host_put(info->host);
-
-	link->state &= ~DEV_CONFIG;
 }
 
 /*====================================================================*/
 
-static int qlogic_suspend(struct pcmcia_device *dev)
+static int qlogic_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
+	scsi_info_t *info = link->priv;
 
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int qlogic_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		scsi_info_t *info = link->priv;
-
-		pcmcia_request_configuration(link->handle, &link->conf);
-		if ((info->manf_id == MANFID_MACNICA) ||
-		    (info->manf_id == MANFID_PIONEER) ||
-		    (info->manf_id == 0x0098)) {
-			outb(0x80, link->io.BasePort1 + 0xd);
-			outb(0x24, link->io.BasePort1 + 0x9);
-			outb(0x04, link->io.BasePort1 + 0xd);
-		}
-		/* Ugggglllyyyy!!! */
-		qlogicfas408_bus_reset(NULL);
+	pcmcia_request_configuration(link, &link->conf);
+	if ((info->manf_id == MANFID_MACNICA) ||
+	    (info->manf_id == MANFID_PIONEER) ||
+	    (info->manf_id == 0x0098)) {
+		outb(0x80, link->io.BasePort1 + 0xd);
+		outb(0x24, link->io.BasePort1 + 0x9);
+		outb(0x04, link->io.BasePort1 + 0xd);
 	}
+	/* Ugggglllyyyy!!! */
+	qlogicfas408_bus_reset(NULL);
 
 	return 0;
 }
@@ -382,10 +338,9 @@
 	.drv		= {
 	.name		= "qlogic_cs",
 	},
-	.probe		= qlogic_attach,
+	.probe		= qlogic_probe,
 	.remove		= qlogic_detach,
 	.id_table       = qlogic_ids,
-	.suspend	= qlogic_suspend,
 	.resume		= qlogic_resume,
 };
 
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 3a4dd6f..9f59827 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -202,7 +202,7 @@
 /* ================================================================== */
 
 struct scsi_info_t {
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 	struct Scsi_Host *host;
 	unsigned short manf_id;
@@ -527,7 +527,7 @@
 }
 
 static void
-SYM53C500_release(dev_link_t *link)
+SYM53C500_release(struct pcmcia_device *link)
 {
 	struct scsi_info_t *info = link->priv;
 	struct Scsi_Host *shost = info->host;
@@ -550,13 +550,7 @@
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 
-	link->dev = NULL;
-
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 
 	scsi_host_put(shost);
 } /* SYM53C500_release */
@@ -713,10 +707,9 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void
-SYM53C500_config(dev_link_t *link)
+static int
+SYM53C500_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	struct scsi_info_t *info = link->priv;
 	tuple_t tuple;
 	cisparse_t parse;
@@ -733,40 +726,37 @@
 	tuple.TupleDataMax = 64;
 	tuple.TupleOffset = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 
 	tuple.DesiredTuple = CISTPL_MANFID;
-	if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) &&
-	    (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
+	if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
+	    (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
 		info->manf_id = le16_to_cpu(tuple.TupleData[0]);
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-		    pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+		    pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 		link->conf.ConfigIndex = parse.cftable_entry.index;
 		link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
 		link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
 
 		if (link->io.BasePort1 != 0) {
-			i = pcmcia_request_io(handle, &link->io);
+			i = pcmcia_request_io(link, &link->io);
 			if (i == CS_SUCCESS)
 				break;
 		}
 next_entry:
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	/*
 	*  That's the trouble with copying liberally from another driver.
@@ -835,7 +825,7 @@
 	data->fast_pio = USE_FAST_PIO;
 
 	sprintf(info->node.dev_name, "scsi%d", host->host_no);
-	link->dev = &info->node;
+	link->dev_node = &info->node;
 	info->host = host;
 
 	if (scsi_add_host(host, NULL))
@@ -843,7 +833,7 @@
 
 	scsi_scan_host(host);
 
-	goto out;	/* SUCCESS */
+	return 0;
 
 err_free_irq:
 	free_irq(irq_level, host);
@@ -852,74 +842,50 @@
 err_release:
 	release_region(port_base, 0x10);
 	printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");
-
-out:
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	return -ENODEV;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	SYM53C500_release(link);
-	return;
+	return -ENODEV;
 } /* SYM53C500_config */
 
-static int sym53c500_suspend(struct pcmcia_device *dev)
+static int sym53c500_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int sym53c500_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
 	struct scsi_info_t *info = link->priv;
 
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG) {
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-		/* See earlier comment about manufacturer IDs. */
-		if ((info->manf_id == MANFID_MACNICA) ||
-		    (info->manf_id == MANFID_PIONEER) ||
-		    (info->manf_id == 0x0098)) {
-			outb(0x80, link->io.BasePort1 + 0xd);
-			outb(0x24, link->io.BasePort1 + 0x9);
-			outb(0x04, link->io.BasePort1 + 0xd);
-		}
-		/*
-		 *  If things don't work after a "resume",
-		 *  this is a good place to start looking.
-		 */
-		SYM53C500_int_host_reset(link->io.BasePort1);
+	/* See earlier comment about manufacturer IDs. */
+	if ((info->manf_id == MANFID_MACNICA) ||
+	    (info->manf_id == MANFID_PIONEER) ||
+	    (info->manf_id == 0x0098)) {
+		outb(0x80, link->io.BasePort1 + 0xd);
+		outb(0x24, link->io.BasePort1 + 0x9);
+		outb(0x04, link->io.BasePort1 + 0xd);
 	}
+	/*
+	 *  If things don't work after a "resume",
+	 *  this is a good place to start looking.
+	 */
+	SYM53C500_int_host_reset(link->io.BasePort1);
 
 	return 0;
 }
 
 static void
-SYM53C500_detach(struct pcmcia_device *p_dev)
+SYM53C500_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
 
-	if (link->state & DEV_CONFIG)
-		SYM53C500_release(link);
+	SYM53C500_release(link);
 
 	kfree(link->priv);
 	link->priv = NULL;
 } /* SYM53C500_detach */
 
 static int
-SYM53C500_attach(struct pcmcia_device *p_dev)
+SYM53C500_probe(struct pcmcia_device *link)
 {
 	struct scsi_info_t *info;
-	dev_link_t *link;
 
 	DEBUG(0, "SYM53C500_attach()\n");
 
@@ -928,7 +894,7 @@
 	if (!info)
 		return -ENOMEM;
 	memset(info, 0, sizeof(*info));
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 	link->io.NumPorts1 = 16;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -936,17 +902,10 @@
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	SYM53C500_config(link);
-
-	return 0;
+	return SYM53C500_config(link);
 } /* SYM53C500_attach */
 
 MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -966,10 +925,9 @@
 	.drv		= {
 		.name	= "sym53c500_cs",
 	},
-	.probe		= SYM53C500_attach,
+	.probe		= SYM53C500_probe,
 	.remove		= SYM53C500_detach,
 	.id_table       = sym53c500_ids,
-	.suspend	= sym53c500_suspend,
 	.resume		= sym53c500_resume,
 };
 
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 3c85c4b..5cda16c 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -143,7 +143,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
deleted file mode 100644
index 52b224a..0000000
--- a/drivers/scsi/qlogicfc.c
+++ /dev/null
@@ -1,2228 +0,0 @@
-/*
- * QLogic ISP2x00 SCSI-FCP
- * Written by Erik H. Moe, ehm@cris.com
- * Copyright 1995, Erik H. Moe
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
-
-/* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
- *
- * Big endian support and dynamic DMA mapping added
- * by Jakub Jelinek <jakub@redhat.com>.
- *
- * Conversion to final pci64 DMA interfaces
- * by David S. Miller <davem@redhat.com>.
- */
-
-/*
- * $Date: 1995/09/22 02:23:15 $
- * $Revision: 0.5 $
- *
- * $Log: isp1020.c,v $
- * Revision 0.5  1995/09/22  02:23:15  root
- * do auto request sense
- *
- * Revision 0.4  1995/08/07  04:44:33  root
- * supply firmware with driver.
- * numerous bug fixes/general cleanup of code.
- *
- * Revision 0.3  1995/07/16  16:15:39  root
- * added reset/abort code.
- *
- * Revision 0.2  1995/06/29  03:14:19  root
- * fixed biosparam.
- * added queue protocol.
- *
- * Revision 0.1  1995/06/25  01:55:45  root
- * Initial release.
- *
- */
-
-#include <linux/blkdev.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/unistd.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-
-#define pci64_dma_hi32(a) ((u32) (0xffffffff & (((u64)(a))>>32)))
-#define pci64_dma_lo32(a) ((u32) (0xffffffff & (((u64)(a)))))
-#define pci64_dma_build(hi,lo) \
-	((dma_addr_t)(((u64)(lo))|(((u64)(hi))<<32)))
-
-/*
- * With the qlogic interface, every queue slot can hold a SCSI
- * command with up to 2 scatter/gather entries.  If we need more
- * than 2 entries, continuation entries can be used that hold
- * another 5 entries each.  Unlike for other drivers, this means
- * that the maximum number of scatter/gather entries we can
- * support at any given time is a function of the number of queue
- * slots available.  That is, host->can_queue and host->sg_tablesize
- * are dynamic and _not_ independent.  This all works fine because
- * requests are queued serially and the scatter/gather limit is
- * determined for each queue request anew.
- */
-
-#define DATASEGS_PER_COMMAND 2
-#define DATASEGS_PER_CONT 5
-
-#define QLOGICFC_REQ_QUEUE_LEN 255     /* must be power of two - 1 */
-#define QLOGICFC_MAX_SG(ql)	(DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
-#define QLOGICFC_CMD_PER_LUN    8
-
-/* Configuration section **************************************************** */
-
-/* Set the following macro to 1 to reload the ISP2x00's firmware.  This is
-   version 1.17.30 of the isp2100's firmware and version 2.00.40 of the 
-   isp2200's firmware. 
-*/
-
-#define USE_NVRAM_DEFAULTS      1
-
-#define ISP2x00_PORTDB          1
-
-/* Set the following to 1 to include fabric support, fabric support is 
- * currently not as well tested as the other aspects of the driver */
-
-#define ISP2x00_FABRIC          1
-
-/*  Macros used for debugging */
-#define DEBUG_ISP2x00		0
-#define DEBUG_ISP2x00_INT	0
-#define DEBUG_ISP2x00_INTR	0
-#define DEBUG_ISP2x00_SETUP	0
-#define DEBUG_ISP2x00_FABRIC    0
-#define TRACE_ISP 		0 
-
-
-#define DEFAULT_LOOP_COUNT	1000000000
-
-#define ISP_TIMEOUT (2*HZ)
-/* End Configuration section ************************************************ */
-
-#include <linux/module.h>
-
-#if TRACE_ISP
-
-#define TRACE_BUF_LEN	(32*1024)
-
-struct {
-	u_long next;
-	struct {
-		u_long time;
-		u_int index;
-		u_int addr;
-		u_char *name;
-	} buf[TRACE_BUF_LEN];
-} trace;
-
-#define TRACE(w, i, a)						\
-{								\
-	unsigned long flags;					\
-								\
-	save_flags(flags);					\
-	cli();							\
-	trace.buf[trace.next].name  = (w);			\
-	trace.buf[trace.next].time  = jiffies;			\
-	trace.buf[trace.next].index = (i);			\
-	trace.buf[trace.next].addr  = (long) (a);		\
-	trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1);	\
-	restore_flags(flags);					\
-}
-
-#else
-#define TRACE(w, i, a)
-#endif
-
-#if DEBUG_ISP2x00_FABRIC
-#define DEBUG_FABRIC(x)	x
-#else
-#define DEBUG_FABRIC(x)
-#endif				/* DEBUG_ISP2x00_FABRIC */
-
-
-#if DEBUG_ISP2x00
-#define ENTER(x)	printk("isp2x00 : entering %s()\n", x);
-#define LEAVE(x)	printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG(x)	x
-#else
-#define ENTER(x)
-#define LEAVE(x)
-#define DEBUG(x)
-#endif				/* DEBUG_ISP2x00 */
-
-#if DEBUG_ISP2x00_INTR
-#define ENTER_INTR(x)	printk("isp2x00 : entering %s()\n", x);
-#define LEAVE_INTR(x)	printk("isp2x00 : leaving %s()\n", x);
-#define DEBUG_INTR(x)	x
-#else
-#define ENTER_INTR(x)
-#define LEAVE_INTR(x)
-#define DEBUG_INTR(x)
-#endif				/* DEBUG ISP2x00_INTR */
-
-
-#define ISP2100_REV_ID1	       1
-#define ISP2100_REV_ID3        3
-#define ISP2200_REV_ID5        5
-
-/* host configuration and control registers */
-#define HOST_HCCR	0xc0	/* host command and control */
-
-/* pci bus interface registers */
-#define FLASH_BIOS_ADDR	0x00
-#define FLASH_BIOS_DATA	0x02
-#define ISP_CTRL_STATUS	0x06	/* configuration register #1 */
-#define PCI_INTER_CTL	0x08	/* pci interrupt control */
-#define PCI_INTER_STS	0x0a	/* pci interrupt status */
-#define PCI_SEMAPHORE	0x0c	/* pci semaphore */
-#define PCI_NVRAM	0x0e	/* pci nvram interface */
-
-/* mailbox registers */
-#define MBOX0		0x10	/* mailbox 0 */
-#define MBOX1		0x12	/* mailbox 1 */
-#define MBOX2		0x14	/* mailbox 2 */
-#define MBOX3		0x16	/* mailbox 3 */
-#define MBOX4		0x18	/* mailbox 4 */
-#define MBOX5		0x1a	/* mailbox 5 */
-#define MBOX6		0x1c	/* mailbox 6 */
-#define MBOX7		0x1e	/* mailbox 7 */
-
-/* mailbox command complete status codes */
-#define MBOX_COMMAND_COMPLETE		0x4000
-#define INVALID_COMMAND			0x4001
-#define HOST_INTERFACE_ERROR		0x4002
-#define TEST_FAILED			0x4003
-#define COMMAND_ERROR			0x4005
-#define COMMAND_PARAM_ERROR		0x4006
-#define PORT_ID_USED                    0x4007
-#define LOOP_ID_USED                    0x4008
-#define ALL_IDS_USED                    0x4009
-
-/* async event status codes */
-#define RESET_DETECTED  		0x8001
-#define SYSTEM_ERROR			0x8002
-#define REQUEST_TRANSFER_ERROR		0x8003
-#define RESPONSE_TRANSFER_ERROR		0x8004
-#define REQUEST_QUEUE_WAKEUP		0x8005
-#define LIP_OCCURRED                     0x8010
-#define LOOP_UP                         0x8011
-#define LOOP_DOWN                       0x8012
-#define LIP_RECEIVED                    0x8013
-#define PORT_DB_CHANGED                 0x8014
-#define CHANGE_NOTIFICATION             0x8015
-#define SCSI_COMMAND_COMPLETE           0x8020
-#define POINT_TO_POINT_UP               0x8030
-#define CONNECTION_MODE                 0x8036
-
-struct Entry_header {
-	u_char entry_type;
-	u_char entry_cnt;
-	u_char sys_def_1;
-	u_char flags;
-};
-
-/* entry header type commands */
-#define ENTRY_COMMAND		0x19
-#define ENTRY_CONTINUATION	0x0a
-
-#define ENTRY_STATUS		0x03
-#define ENTRY_MARKER		0x04
-
-
-/* entry header flag definitions */
-#define EFLAG_BUSY		2
-#define EFLAG_BAD_HEADER	4
-#define EFLAG_BAD_PAYLOAD	8
-
-struct dataseg {
-	u_int d_base;
-	u_int d_base_hi;
-	u_int d_count;
-};
-
-struct Command_Entry {
-	struct Entry_header hdr;
-	u_int handle;
-	u_char target_lun;
-	u_char target_id;
-	u_short expanded_lun;
-	u_short control_flags;
-	u_short rsvd2;
-	u_short time_out;
-	u_short segment_cnt;
-	u_char cdb[16];
-	u_int total_byte_cnt;
-	struct dataseg dataseg[DATASEGS_PER_COMMAND];
-};
-
-/* command entry control flag definitions */
-#define CFLAG_NODISC		0x01
-#define CFLAG_HEAD_TAG		0x02
-#define CFLAG_ORDERED_TAG	0x04
-#define CFLAG_SIMPLE_TAG	0x08
-#define CFLAG_TAR_RTN		0x10
-#define CFLAG_READ		0x20
-#define CFLAG_WRITE		0x40
-
-struct Continuation_Entry {
-	struct Entry_header hdr;
-	struct dataseg dataseg[DATASEGS_PER_CONT];
-};
-
-struct Marker_Entry {
-	struct Entry_header hdr;
-	u_int reserved;
-	u_char target_lun;
-	u_char target_id;
-	u_char modifier;
-	u_char expanded_lun;
-	u_char rsvds[52];
-};
-
-/* marker entry modifier definitions */
-#define SYNC_DEVICE	0
-#define SYNC_TARGET	1
-#define SYNC_ALL	2
-
-struct Status_Entry {
-	struct Entry_header hdr;
-	u_int handle;
-	u_short scsi_status;
-	u_short completion_status;
-	u_short state_flags;
-	u_short status_flags;
-	u_short res_info_len;
-	u_short req_sense_len;
-	u_int residual;
-	u_char res_info[8];
-	u_char req_sense_data[32];
-};
-
-/* status entry completion status definitions */
-#define CS_COMPLETE			0x0000
-#define CS_DMA_ERROR			0x0002
-#define CS_RESET_OCCURRED		0x0004
-#define CS_ABORTED			0x0005
-#define CS_TIMEOUT			0x0006
-#define CS_DATA_OVERRUN			0x0007
-#define CS_DATA_UNDERRUN		0x0015
-#define CS_QUEUE_FULL			0x001c
-#define CS_PORT_UNAVAILABLE             0x0028
-#define CS_PORT_LOGGED_OUT              0x0029
-#define CS_PORT_CONFIG_CHANGED		0x002a
-
-/* status entry state flag definitions */
-#define SF_SENT_CDB			0x0400
-#define SF_TRANSFERRED_DATA		0x0800
-#define SF_GOT_STATUS			0x1000
-
-/* status entry status flag definitions */
-#define STF_BUS_RESET			0x0008
-#define STF_DEVICE_RESET		0x0010
-#define STF_ABORTED			0x0020
-#define STF_TIMEOUT			0x0040
-
-/* interrupt control commands */
-#define ISP_EN_INT			0x8000
-#define ISP_EN_RISC			0x0008
-
-/* host control commands */
-#define HCCR_NOP			0x0000
-#define HCCR_RESET			0x1000
-#define HCCR_PAUSE			0x2000
-#define HCCR_RELEASE			0x3000
-#define HCCR_SINGLE_STEP		0x4000
-#define HCCR_SET_HOST_INTR		0x5000
-#define HCCR_CLEAR_HOST_INTR		0x6000
-#define HCCR_CLEAR_RISC_INTR		0x7000
-#define HCCR_BP_ENABLE			0x8000
-#define HCCR_BIOS_DISABLE		0x9000
-#define HCCR_TEST_MODE			0xf000
-
-#define RISC_BUSY			0x0004
-
-/* mailbox commands */
-#define MBOX_NO_OP			0x0000
-#define MBOX_LOAD_RAM			0x0001
-#define MBOX_EXEC_FIRMWARE		0x0002
-#define MBOX_DUMP_RAM			0x0003
-#define MBOX_WRITE_RAM_WORD		0x0004
-#define MBOX_READ_RAM_WORD		0x0005
-#define MBOX_MAILBOX_REG_TEST		0x0006
-#define MBOX_VERIFY_CHECKSUM		0x0007
-#define MBOX_ABOUT_FIRMWARE		0x0008
-#define MBOX_LOAD_RISC_RAM              0x0009
-#define MBOX_DUMP_RISC_RAM              0x000a
-#define MBOX_CHECK_FIRMWARE		0x000e
-#define MBOX_INIT_REQ_QUEUE		0x0010
-#define MBOX_INIT_RES_QUEUE		0x0011
-#define MBOX_EXECUTE_IOCB		0x0012
-#define MBOX_WAKE_UP			0x0013
-#define MBOX_STOP_FIRMWARE		0x0014
-#define MBOX_ABORT_IOCB			0x0015
-#define MBOX_ABORT_DEVICE		0x0016
-#define MBOX_ABORT_TARGET		0x0017
-#define MBOX_BUS_RESET			0x0018
-#define MBOX_STOP_QUEUE			0x0019
-#define MBOX_START_QUEUE		0x001a
-#define MBOX_SINGLE_STEP_QUEUE		0x001b
-#define MBOX_ABORT_QUEUE		0x001c
-#define MBOX_GET_DEV_QUEUE_STATUS	0x001d
-#define MBOX_GET_FIRMWARE_STATUS	0x001f
-#define MBOX_GET_INIT_SCSI_ID		0x0020
-#define MBOX_GET_RETRY_COUNT		0x0022
-#define MBOX_GET_TARGET_PARAMS		0x0028
-#define MBOX_GET_DEV_QUEUE_PARAMS	0x0029
-#define MBOX_SET_RETRY_COUNT		0x0032
-#define MBOX_SET_TARGET_PARAMS		0x0038
-#define MBOX_SET_DEV_QUEUE_PARAMS	0x0039
-#define MBOX_EXECUTE_IOCB64             0x0054
-#define MBOX_INIT_FIRMWARE              0x0060
-#define MBOX_GET_INIT_CB                0x0061
-#define MBOX_INIT_LIP			0x0062
-#define MBOX_GET_POS_MAP                0x0063
-#define MBOX_GET_PORT_DB                0x0064
-#define MBOX_CLEAR_ACA                  0x0065
-#define MBOX_TARGET_RESET               0x0066
-#define MBOX_CLEAR_TASK_SET             0x0067
-#define MBOX_ABORT_TASK_SET             0x0068
-#define MBOX_GET_FIRMWARE_STATE         0x0069
-#define MBOX_GET_PORT_NAME              0x006a
-#define MBOX_SEND_SNS                   0x006e
-#define MBOX_PORT_LOGIN                 0x006f
-#define MBOX_SEND_CHANGE_REQUEST        0x0070
-#define MBOX_PORT_LOGOUT                0x0071
-
-/*
- *	Firmware if needed (note this is a hack, it belongs in a separate
- *	module.
- */
- 
-#ifdef CONFIG_SCSI_QLOGIC_FC_FIRMWARE
-#include "qlogicfc_asm.c"
-#else
-static unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-/* Each element in mbox_param is an 8 bit bitmap where each bit indicates
-   if that mbox should be copied as input.  For example 0x2 would mean
-   only copy mbox1. */
-
-static const u_char mbox_param[] =
-{
-	0x01,			/* MBOX_NO_OP */
-	0x1f,			/* MBOX_LOAD_RAM */
-	0x03,			/* MBOX_EXEC_FIRMWARE */
-	0x1f,			/* MBOX_DUMP_RAM */
-	0x07,			/* MBOX_WRITE_RAM_WORD */
-	0x03,			/* MBOX_READ_RAM_WORD */
-	0xff,			/* MBOX_MAILBOX_REG_TEST */
-	0x03,			/* MBOX_VERIFY_CHECKSUM */
-	0x01,			/* MBOX_ABOUT_FIRMWARE */
-	0xff,			/* MBOX_LOAD_RISC_RAM */
-	0xff,			/* MBOX_DUMP_RISC_RAM */
-	0x00,			/* 0x000b */
-	0x00,			/* 0x000c */
-	0x00,			/* 0x000d */
-	0x01,			/* MBOX_CHECK_FIRMWARE */
-	0x00,			/* 0x000f */
-	0x1f,			/* MBOX_INIT_REQ_QUEUE */
-	0x2f,			/* MBOX_INIT_RES_QUEUE */
-	0x0f,			/* MBOX_EXECUTE_IOCB */
-	0x03,			/* MBOX_WAKE_UP */
-	0x01,			/* MBOX_STOP_FIRMWARE */
-	0x0f,			/* MBOX_ABORT_IOCB */
-	0x03,			/* MBOX_ABORT_DEVICE */
-	0x07,			/* MBOX_ABORT_TARGET */
-	0x03,			/* MBOX_BUS_RESET */
-	0x03,			/* MBOX_STOP_QUEUE */
-	0x03,			/* MBOX_START_QUEUE */
-	0x03,			/* MBOX_SINGLE_STEP_QUEUE */
-	0x03,			/* MBOX_ABORT_QUEUE */
-	0x03,			/* MBOX_GET_DEV_QUEUE_STATUS */
-	0x00,			/* 0x001e */
-	0x01,			/* MBOX_GET_FIRMWARE_STATUS */
-	0x01,			/* MBOX_GET_INIT_SCSI_ID */
-	0x00,			/* 0x0021 */
-	0x01,			/* MBOX_GET_RETRY_COUNT */
-	0x00,			/* 0x0023 */
-	0x00,			/* 0x0024 */
-	0x00,			/* 0x0025 */
-	0x00,			/* 0x0026 */
-	0x00,			/* 0x0027 */
-	0x03,			/* MBOX_GET_TARGET_PARAMS */
-	0x03,			/* MBOX_GET_DEV_QUEUE_PARAMS */
-	0x00,			/* 0x002a */
-	0x00,			/* 0x002b */
-	0x00,			/* 0x002c */
-	0x00,			/* 0x002d */
-	0x00,			/* 0x002e */
-	0x00,			/* 0x002f */
-	0x00,			/* 0x0030 */
-	0x00,			/* 0x0031 */
-	0x07,			/* MBOX_SET_RETRY_COUNT */
-	0x00,			/* 0x0033 */
-	0x00,			/* 0x0034 */
-	0x00,			/* 0x0035 */
-	0x00,			/* 0x0036 */
-	0x00,			/* 0x0037 */
-	0x0f,			/* MBOX_SET_TARGET_PARAMS */
-	0x0f,			/* MBOX_SET_DEV_QUEUE_PARAMS */
-	0x00,			/* 0x003a */
-	0x00,			/* 0x003b */
-	0x00,			/* 0x003c */
-	0x00,			/* 0x003d */
-	0x00,			/* 0x003e */
-	0x00,			/* 0x003f */
-	0x00,			/* 0x0040 */
-	0x00,			/* 0x0041 */
-	0x00,			/* 0x0042 */
-	0x00,			/* 0x0043 */
-	0x00,			/* 0x0044 */
-	0x00,			/* 0x0045 */
-	0x00,			/* 0x0046 */
-	0x00,			/* 0x0047 */
-	0x00,			/* 0x0048 */
-	0x00,			/* 0x0049 */
-	0x00,			/* 0x004a */
-	0x00,			/* 0x004b */
-	0x00,			/* 0x004c */
-	0x00,			/* 0x004d */
-	0x00,			/* 0x004e */
-	0x00,			/* 0x004f */
-	0x00,			/* 0x0050 */
-	0x00,			/* 0x0051 */
-	0x00,			/* 0x0052 */
-	0x00,			/* 0x0053 */
-	0xcf,			/* MBOX_EXECUTE_IOCB64 */
-	0x00,			/* 0x0055 */
-	0x00,			/* 0x0056 */
-	0x00,			/* 0x0057 */
-	0x00,			/* 0x0058 */
-	0x00,			/* 0x0059 */
-	0x00,			/* 0x005a */
-	0x00,			/* 0x005b */
-	0x00,			/* 0x005c */
-	0x00,			/* 0x005d */
-	0x00,			/* 0x005e */
-	0x00,			/* 0x005f */
-	0xff,			/* MBOX_INIT_FIRMWARE */
-	0xcd,			/* MBOX_GET_INIT_CB */
-	0x01,			/* MBOX_INIT_LIP */
-	0xcd,			/* MBOX_GET_POS_MAP */
-	0xcf,			/* MBOX_GET_PORT_DB */
-	0x03,			/* MBOX_CLEAR_ACA */
-	0x03,			/* MBOX_TARGET_RESET */
-	0x03,			/* MBOX_CLEAR_TASK_SET */
-	0x03,			/* MBOX_ABORT_TASK_SET */
-	0x01,			/* MBOX_GET_FIRMWARE_STATE */
-	0x03,			/* MBOX_GET_PORT_NAME */
-	0x00,			/* 0x006b */
-	0x00,			/* 0x006c */
-	0x00,			/* 0x006d */
-	0xcf,			/* MBOX_SEND_SNS */
-	0x0f,			/* MBOX_PORT_LOGIN */
-	0x03,			/* MBOX_SEND_CHANGE_REQUEST */
-	0x03,			/* MBOX_PORT_LOGOUT */
-};
-
-#define MAX_MBOX_COMMAND	(sizeof(mbox_param)/sizeof(u_short))
-
-
-struct id_name_map {
-	u64 wwn;
-	u_char loop_id;
-};
-
-struct sns_cb {
-	u_short len;
-	u_short res1;
-	u_int response_low;
-	u_int response_high;
-	u_short sub_len;
-	u_short res2;
-	u_char data[44];
-};
-
-/* address of instance of this struct is passed to adapter to initialize things
- */
-struct init_cb {
-	u_char version;
-	u_char reseverd1[1];
-	u_short firm_opts;
-	u_short max_frame_len;
-	u_short max_iocb;
-	u_short exec_throttle;
-	u_char retry_cnt;
-	u_char retry_delay;
-	u_short node_name[4];
-	u_short hard_addr;
-	u_char reserved2[10];
-	u_short req_queue_out;
-	u_short res_queue_in;
-	u_short req_queue_len;
-	u_short res_queue_len;
-	u_int req_queue_addr_lo;
-	u_int req_queue_addr_high;
-	u_int res_queue_addr_lo;
-	u_int res_queue_addr_high;
-        /* the rest of this structure only applies to the isp2200 */
-        u_short lun_enables;
-        u_char cmd_resource_cnt;
-        u_char notify_resource_cnt;
-        u_short timeout;
-        u_short reserved3;
-        u_short add_firm_opts;
-        u_char res_accum_timer;
-        u_char irq_delay_timer;
-        u_short special_options;
-        u_short reserved4[13];
-};
-
-/*
- * The result queue can be quite a bit smaller since continuation entries
- * do not show up there:
- */
-#define RES_QUEUE_LEN		((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)
-#define QUEUE_ENTRY_LEN		64
-
-#if ISP2x00_FABRIC
-#define QLOGICFC_MAX_ID    0xff
-#else
-#define QLOGICFC_MAX_ID    0x7d
-#endif
-
-#define QLOGICFC_MAX_LUN	128
-#define QLOGICFC_MAX_LOOP_ID	0x7d
-
-/* the following connection options only apply to the 2200.  i have only
- * had success with LOOP_ONLY and P2P_ONLY.
- */
-
-#define LOOP_ONLY              0
-#define P2P_ONLY               1
-#define LOOP_PREFERED          2
-#define P2P_PREFERED           3
-
-#define CONNECTION_PREFERENCE  LOOP_ONLY
-
-/* adapter_state values */
-#define AS_FIRMWARE_DEAD      -1
-#define AS_LOOP_DOWN           0
-#define AS_LOOP_GOOD           1
-#define AS_REDO_FABRIC_PORTDB  2
-#define AS_REDO_LOOP_PORTDB    4
-
-#define RES_SIZE	((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-#define REQ_SIZE	((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
-
-struct isp2x00_hostdata {
-	u_char revision;
-	struct pci_dev *pci_dev;
-	/* result and request queues (shared with isp2x00): */
-	u_int req_in_ptr;	/* index of next request slot */
-	u_int res_out_ptr;	/* index of next result slot */
-
-	/* this is here so the queues are nicely aligned */
-	long send_marker;	/* do we need to send a marker? */
-
-	char * res;
-	char * req;
-	struct init_cb control_block;
-	int adapter_state;
-	unsigned long int tag_ages[QLOGICFC_MAX_ID + 1];
-	Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];
-	unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];
-	struct id_name_map port_db[QLOGICFC_MAX_ID + 1];
-	u_char mbox_done;
-	u64 wwn;
-	u_int port_id;
-	u_char queued;
-	u_char host_id;
-        struct timer_list explore_timer;
-	struct id_name_map tempmap[QLOGICFC_MAX_ID + 1];
-};
-
-
-/* queue length's _must_ be power of two: */
-#define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))
-#define REQ_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, 		     \
-						    QLOGICFC_REQ_QUEUE_LEN)
-#define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
-
-static void isp2x00_enable_irqs(struct Scsi_Host *);
-static void isp2x00_disable_irqs(struct Scsi_Host *);
-static int isp2x00_init(struct Scsi_Host *);
-static int isp2x00_reset_hardware(struct Scsi_Host *);
-static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);
-static int isp2x00_return_status(Scsi_Cmnd *, struct Status_Entry *);
-static void isp2x00_intr_handler(int, void *, struct pt_regs *);
-static irqreturn_t do_isp2x00_intr_handler(int, void *, struct pt_regs *);
-static int isp2x00_make_portdb(struct Scsi_Host *);
-
-#if ISP2x00_FABRIC
-static int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
-#endif
-
-#if USE_NVRAM_DEFAULTS
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
-static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short);
-#endif
-
-#if DEBUG_ISP2x00
-static void isp2x00_print_scsi_cmd(Scsi_Cmnd *);
-#endif
-
-#if DEBUG_ISP2x00_INTR
-static void isp2x00_print_status_entry(struct Status_Entry *);
-#endif
-
-static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
-{
-	outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
-}
-
-
-static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
-{
-	outw(0x0, host->io_port + PCI_INTER_CTL);
-}
-
-
-static int isp2x00_detect(struct scsi_host_template * tmpt)
-{
-	int hosts = 0;
-	unsigned long wait_time;
-	struct Scsi_Host *host = NULL;
-	struct isp2x00_hostdata *hostdata;
-	struct pci_dev *pdev;
-	unsigned short device_ids[2];
-	dma_addr_t busaddr;
-	int i;
-
-
-	ENTER("isp2x00_detect");
-
-       	device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;
-	device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;
-
-	tmpt->proc_name = "isp2x00";
-
-	for (i=0; i<2; i++){
-		pdev = NULL;
-	        while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) {
-			if (pci_enable_device(pdev))
-				continue;
-
-			/* Try to configure DMA attributes. */
-			if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
-			    pci_set_dma_mask(pdev, DMA_32BIT_MASK))
-					continue;
-
-		        host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
-			if (!host) {
-			        printk("qlogicfc%d : could not register host.\n", hosts);
-				continue;
-			}
-			host->max_id = QLOGICFC_MAX_ID + 1;
-			host->max_lun = QLOGICFC_MAX_LUN;
-			hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-			memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
-			hostdata->pci_dev = pdev;
-			hostdata->res = pci_alloc_consistent(pdev, RES_SIZE + REQ_SIZE, &busaddr);
-
-			if (!hostdata->res){
-			        printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hosts);
-			        scsi_unregister(host);
-				continue;
-			}
-			hostdata->req = hostdata->res + (RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN;
-			hostdata->queued = 0;
-			/* set up the control block */
-			hostdata->control_block.version = 0x1;
-			hostdata->control_block.firm_opts = cpu_to_le16(0x800e);
-			hostdata->control_block.max_frame_len = cpu_to_le16(2048);
-			hostdata->control_block.max_iocb = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN);
-			hostdata->control_block.exec_throttle = cpu_to_le16(QLOGICFC_CMD_PER_LUN);
-			hostdata->control_block.retry_delay = 5;
-			hostdata->control_block.retry_cnt = 1;
-			hostdata->control_block.node_name[0] = cpu_to_le16(0x0020);
-			hostdata->control_block.node_name[1] = cpu_to_le16(0xE000);
-			hostdata->control_block.node_name[2] = cpu_to_le16(0x008B);
-			hostdata->control_block.node_name[3] = cpu_to_le16(0x0000);
-			hostdata->control_block.hard_addr = cpu_to_le16(0x0003);
-			hostdata->control_block.req_queue_len = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN + 1);
-			hostdata->control_block.res_queue_len = cpu_to_le16(RES_QUEUE_LEN + 1);
-			hostdata->control_block.res_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr));
-			hostdata->control_block.res_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr));
-			hostdata->control_block.req_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr + RES_SIZE));
-			hostdata->control_block.req_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr + RES_SIZE));
-
-
-			hostdata->control_block.add_firm_opts |= cpu_to_le16(CONNECTION_PREFERENCE<<4);
-			hostdata->adapter_state = AS_LOOP_DOWN;
-			hostdata->explore_timer.data = 1;
-			hostdata->host_id = hosts;
-
-			if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
-				pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-			        scsi_unregister(host);
-				continue;
-			}
-			host->this_id = 0;
-
-			if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
-			        printk("qlogicfc%d : interrupt %d already in use\n",
-				       hostdata->host_id, host->irq);
-				pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-				scsi_unregister(host);
-				continue;
-			}
-			if (!request_region(host->io_port, 0xff, "qlogicfc")) {
-			        printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
-				       "in use\n",
-				       hostdata->host_id, host->io_port, host->io_port + 0xff);
-				free_irq(host->irq, host);
-				pci_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-				scsi_unregister(host);
-				continue;
-			}
-
-			outw(0x0, host->io_port + PCI_SEMAPHORE);
-			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
-			isp2x00_enable_irqs(host);
-			/* wait for the loop to come up */
-			for (wait_time = jiffies + 10 * HZ; time_before(jiffies, wait_time) && hostdata->adapter_state == AS_LOOP_DOWN;) {
-			        barrier();
-				cpu_relax();
-			}
-			if (hostdata->adapter_state == AS_LOOP_DOWN) {
-			        printk("qlogicfc%d : link is not up\n", hostdata->host_id);
-			}
-			hosts++;
-			hostdata->explore_timer.data = 0;
-		}
-	}
-
-
-	/* this busy loop should not be needed but the isp2x00 seems to need 
-	   some time before recognizing it is attached to a fabric */
-
-#if ISP2x00_FABRIC
-	if (hosts) {
-		for (wait_time = jiffies + 5 * HZ; time_before(jiffies, wait_time);) {
-			barrier();
-			cpu_relax();
-		}
-	}
-#endif
-
-	LEAVE("isp2x00_detect");
-
-	return hosts;
-}
-
-
-static int isp2x00_make_portdb(struct Scsi_Host *host)
-{
-
-	short param[8];
-	int i, j;
-	struct isp2x00_hostdata *hostdata;
-
-	isp2x00_disable_irqs(host);
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-	memset(hostdata->tempmap, 0, sizeof(hostdata->tempmap));
-
-#if ISP2x00_FABRIC
-	for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
-		param[0] = MBOX_PORT_LOGOUT;
-		param[1] = i << 8;
-		param[2] = 0;
-		param[3] = 0;
-
-		isp2x00_mbox_command(host, param);
-
-		if (param[0] != MBOX_COMMAND_COMPLETE) {
-
-			DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x  %x\n", hostdata->host_id, i, param[0]));
-		}
-	}
-#endif
-
-
-	param[0] = MBOX_GET_INIT_SCSI_ID;
-
-	isp2x00_mbox_command(host, param);
-
-	if (param[0] == MBOX_COMMAND_COMPLETE) {
-		hostdata->port_id = ((u_int) param[3]) << 16;
-		hostdata->port_id |= param[2];
-		hostdata->tempmap[0].loop_id = param[1];
-		hostdata->tempmap[0].wwn = hostdata->wwn;
-	}
-	else {
-	        printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
-	}
-
-        for (i = 0; i <=QLOGICFC_MAX_ID; i++)
-                hostdata->tempmap[i].loop_id = hostdata->tempmap[0].loop_id;
-   
-        for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
-                param[0] = MBOX_GET_PORT_NAME;
-		param[1] = (i << 8) & 0xff00;
-
-		isp2x00_mbox_command(host, param);
-
-		if (param[0] == MBOX_COMMAND_COMPLETE) {
-			hostdata->tempmap[j].loop_id = i;
-			hostdata->tempmap[j].wwn = ((u64) (param[2] & 0xff)) << 56;
-			hostdata->tempmap[j].wwn |= ((u64) ((param[2] >> 8) & 0xff)) << 48;
-			hostdata->tempmap[j].wwn |= ((u64) (param[3] & 0xff)) << 40;
-			hostdata->tempmap[j].wwn |= ((u64) ((param[3] >> 8) & 0xff)) << 32;
-			hostdata->tempmap[j].wwn |= ((u64) (param[6] & 0xff)) << 24;
-			hostdata->tempmap[j].wwn |= ((u64) ((param[6] >> 8) & 0xff)) << 16;
-			hostdata->tempmap[j].wwn |= ((u64) (param[7] & 0xff)) << 8;
-			hostdata->tempmap[j].wwn |= ((u64) ((param[7] >> 8) & 0xff));
-
-			j++;
-
-		}
-	}
-
-
-#if ISP2x00_FABRIC
-	isp2x00_init_fabric(host, hostdata->tempmap, j);
-#endif
-
-	for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
-		if (hostdata->tempmap[i].wwn != hostdata->port_db[i].wwn) {
-			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
-				if (hostdata->tempmap[j].wwn == hostdata->port_db[i].wwn) {
-					hostdata->port_db[i].loop_id = hostdata->tempmap[j].loop_id;
-					break;
-				}
-			}
-			if (j == QLOGICFC_MAX_ID + 1)
-				hostdata->port_db[i].loop_id = hostdata->tempmap[0].loop_id;
-
-			for (j = 0; j <= QLOGICFC_MAX_ID; j++) {
-				if (hostdata->port_db[j].wwn == hostdata->tempmap[i].wwn || !hostdata->port_db[j].wwn) {
-					break;
-				}
-			}
-			if (j == QLOGICFC_MAX_ID + 1)
-				printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
-			if (!hostdata->port_db[j].wwn) {
-				hostdata->port_db[j].loop_id = hostdata->tempmap[i].loop_id;
-				hostdata->port_db[j].wwn = hostdata->tempmap[i].wwn;
-			}
-		} else
-			hostdata->port_db[i].loop_id = hostdata->tempmap[i].loop_id;
-
-	}
-
-	isp2x00_enable_irqs(host);
-
-	return 0;
-}
-
-
-#if ISP2x00_FABRIC
-
-#define FABRIC_PORT          0x7e
-#define FABRIC_CONTROLLER    0x7f
-#define FABRIC_SNS           0x80
-
-int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id)
-{
-
-	u_short param[8];
-	u64 wwn;
-	int done = 0;
-	u_short loop_id = 0x81;
-	u_short scsi_id = cur_scsi_id;
-	u_int port_id;
-	struct sns_cb *req;
-	u_char *sns_response;
-	dma_addr_t busaddr;
-	struct isp2x00_hostdata *hostdata;
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-	
-	DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id));
-	param[0] = MBOX_GET_PORT_NAME;
-	param[1] = (u16)FABRIC_PORT << 8;
-
-	isp2x00_mbox_command(host, param);
-
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0]));
-		return 0;
-	}
-	printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
-
-	req = (struct sns_cb *)pci_alloc_consistent(hostdata->pci_dev, sizeof(*req) + 608, &busaddr);
-	
-	if (!req){
-		printk("qlogicfc%d : Could not allocate DMA resources for fabric initialization\n", hostdata->host_id);
-		return 0;
-	}
-	sns_response = (u_char *)(req + 1);
-
-	if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){
-	        memset(req, 0, sizeof(*req));
-	
-		req->len = cpu_to_le16(8);
-		req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
-		req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
-		req->sub_len = cpu_to_le16(22);
-		req->data[0] = 0x17;
-		req->data[1] = 0x02;
-		req->data[8] = (u_char) (hostdata->port_id & 0xff);
-		req->data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
-		req->data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
-		req->data[13] = 0x01;
-		param[0] = MBOX_SEND_SNS;
-		param[1] = 30;
-		param[2] = pci64_dma_lo32(busaddr) >> 16;
-		param[3] = pci64_dma_lo32(busaddr);
-		param[6] = pci64_dma_hi32(busaddr) >> 16;
-		param[7] = pci64_dma_hi32(busaddr);
-
-		isp2x00_mbox_command(host, param);
-	
-		if (param[0] != MBOX_COMMAND_COMPLETE)
-		        printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);
-	}
-
-	port_id = hostdata->port_id;
-	while (!done) {
-		memset(req, 0, sizeof(*req));
-
-		req->len = cpu_to_le16(304);
-		req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
-		req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
-		req->sub_len = cpu_to_le16(6);
-		req->data[0] = 0x00;
-		req->data[1] = 0x01;
-		req->data[8] = (u_char) (port_id & 0xff);
-		req->data[9] = (u_char) (port_id >> 8 & 0xff);
-		req->data[10] = (u_char) (port_id >> 16 & 0xff);
-
-		param[0] = MBOX_SEND_SNS;
-		param[1] = 14;
-		param[2] = pci64_dma_lo32(busaddr) >> 16;
-		param[3] = pci64_dma_lo32(busaddr);
-		param[6] = pci64_dma_hi32(busaddr) >> 16;
-		param[7] = pci64_dma_hi32(busaddr);
-
-		isp2x00_mbox_command(host, param);
-
-		if (param[0] == MBOX_COMMAND_COMPLETE) {
-			DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
-			DEBUG_FABRIC(printk("  port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19]));
-			port_id = ((u_int) sns_response[17]) << 16;
-			port_id |= ((u_int) sns_response[18]) << 8;
-			port_id |= ((u_int) sns_response[19]);
-			wwn = ((u64) sns_response[20]) << 56;
-			wwn |= ((u64) sns_response[21]) << 48;
-			wwn |= ((u64) sns_response[22]) << 40;
-			wwn |= ((u64) sns_response[23]) << 32;
-			wwn |= ((u64) sns_response[24]) << 24;
-			wwn |= ((u64) sns_response[25]) << 16;
-			wwn |= ((u64) sns_response[26]) << 8;
-			wwn |= ((u64) sns_response[27]);
-			if (hostdata->port_id >> 8 != port_id >> 8) {
-				DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id));
-				param[0] = MBOX_PORT_LOGIN;
-				param[1] = loop_id << 8;
-				param[2] = (u_short) (port_id >> 16);
-				param[3] = (u_short) (port_id);
-
-				isp2x00_mbox_command(host, param);
-
-				if (param[0] == MBOX_COMMAND_COMPLETE) {
-					port_db[scsi_id].wwn = wwn;
-					port_db[scsi_id].loop_id = loop_id;
-					loop_id++;
-					scsi_id++;
-				} else {
-					printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]);
-					DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id));
-					param[0] = MBOX_PORT_LOGOUT;
-					param[1] = loop_id << 8;
-					param[2] = 0;
-					param[3] = 0;
-
-					isp2x00_mbox_command(host, param);
-					
-				}
-
-			}
-			if (hostdata->port_id == port_id)
-				done = 1;
-		} else {
-			printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]);
-			pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
-			return 0;
-		}
-	}
-
-	pci_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
-	return 1;
-}
-
-#endif				/* ISP2x00_FABRIC */
-
-
-static int isp2x00_release(struct Scsi_Host *host)
-{
-	struct isp2x00_hostdata *hostdata;
-	dma_addr_t busaddr;
-
-	ENTER("isp2x00_release");
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-	outw(0x0, host->io_port + PCI_INTER_CTL);
-	free_irq(host->irq, host);
-
-	release_region(host->io_port, 0xff);
-
-	busaddr = pci64_dma_build(le32_to_cpu(hostdata->control_block.res_queue_addr_high),
-				  le32_to_cpu(hostdata->control_block.res_queue_addr_lo));
-	pci_free_consistent(hostdata->pci_dev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
-
-	LEAVE("isp2x00_release");
-
-	return 0;
-}
-
-
-static const char *isp2x00_info(struct Scsi_Host *host)
-{
-	static char buf[80];
-	struct isp2x00_hostdata *hostdata;
-	ENTER("isp2x00_info");
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-	sprintf(buf,
-		"QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
-		hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
-		host->io_port);
-
-
-	LEAVE("isp2x00_info");
-
-	return buf;
-}
-
-
-/*
- * The middle SCSI layer ensures that queuecommand never gets invoked
- * concurrently with itself or the interrupt handler (though the
- * interrupt handler may call this routine as part of
- * request-completion handling).
- */
-static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
-{
-	int i, sg_count, n, num_free;
-	u_int in_ptr, out_ptr;
-	struct dataseg *ds;
-	struct scatterlist *sg;
-	struct Command_Entry *cmd;
-	struct Continuation_Entry *cont;
-	struct Scsi_Host *host;
-	struct isp2x00_hostdata *hostdata;
-
-	ENTER("isp2x00_queuecommand");
-
-	host = Cmnd->device->host;
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-	Cmnd->scsi_done = done;
-
-	DEBUG(isp2x00_print_scsi_cmd(Cmnd));
-
-	if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
-		isp2x00_make_portdb(host);
-		hostdata->adapter_state = AS_LOOP_GOOD;
-		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
-		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
-			printk("wwn: %08x%08x  scsi_id: %x  loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
-			if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
-			        printk("%x", hostdata->port_db[i].loop_id);
-			else
-			        printk("Not Available");
-			printk("\n");
-		}
-	}
-	if (hostdata->adapter_state == AS_FIRMWARE_DEAD) {
-		printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id);
-		host->max_id = 0;
-		return 0;
-	}
-
-	out_ptr = inw(host->io_port + MBOX4);
-	in_ptr = hostdata->req_in_ptr;
-
-	DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id,
-		     REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
-
-	cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
-	in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
-	if (in_ptr == out_ptr) {
-		DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
-		return 1;
-	}
-	if (hostdata->send_marker) {
-		struct Marker_Entry *marker;
-
-		TRACE("queue marker", in_ptr, 0);
-
-		DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id));
-		marker = (struct Marker_Entry *) cmd;
-		memset(marker, 0, sizeof(struct Marker_Entry));
-
-		marker->hdr.entry_type = ENTRY_MARKER;
-		marker->hdr.entry_cnt = 1;
-		marker->modifier = SYNC_ALL;
-
-		hostdata->send_marker = 0;
-
-		if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) {
-			outw(in_ptr, host->io_port + MBOX4);
-			hostdata->req_in_ptr = in_ptr;
-			DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
-			return 1;
-		}
-		cmd = (struct Command_Entry *) &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
-		in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
-	}
-	TRACE("queue command", in_ptr, Cmnd);
-
-	memset(cmd, 0, sizeof(struct Command_Entry));
-
-	/* find a free handle mapping slot */
-	for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1)));
-
-	if (!hostdata->handle_ptrs[i]) {
-		cmd->handle = cpu_to_le32(i);
-		hostdata->handle_ptrs[i] = Cmnd;
-		hostdata->handle_serials[i] = Cmnd->serial_number;
-	} else {
-		printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id);
-		printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr);
-		for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){
-			if (!hostdata->handle_ptrs[i]){
-				printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]);
-			}
-		}
-		return 1;
-	}
-
-	cmd->hdr.entry_type = ENTRY_COMMAND;
-	cmd->hdr.entry_cnt = 1;
-	cmd->target_lun = Cmnd->device->lun;
-	cmd->expanded_lun = cpu_to_le16(Cmnd->device->lun);
-#if ISP2x00_PORTDB
-	cmd->target_id = hostdata->port_db[Cmnd->device->id].loop_id;
-#else
-	cmd->target_id = Cmnd->target;
-#endif
-	cmd->total_byte_cnt = cpu_to_le32(Cmnd->request_bufflen);
-	cmd->time_out = 0;
-	memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
-
-	if (Cmnd->use_sg) {
-		sg = (struct scatterlist *) Cmnd->request_buffer;
-		sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
-		cmd->segment_cnt = cpu_to_le16(sg_count);
-		ds = cmd->dataseg;
-		/* fill in first two sg entries: */
-		n = sg_count;
-		if (n > DATASEGS_PER_COMMAND)
-			n = DATASEGS_PER_COMMAND;
-
-		for (i = 0; i < n; i++) {
-			ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
-			ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
-			ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
-			++sg;
-		}
-		sg_count -= DATASEGS_PER_COMMAND;
-
-		while (sg_count > 0) {
-			++cmd->hdr.entry_cnt;
-			cont = (struct Continuation_Entry *)
-			    &hostdata->req[in_ptr*QUEUE_ENTRY_LEN];
-			memset(cont, 0, sizeof(struct Continuation_Entry));
-			in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
-			if (in_ptr == out_ptr) {
-				DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id));
-				return 1;
-			}
-			TRACE("queue continuation", in_ptr, 0);
-			cont->hdr.entry_type = ENTRY_CONTINUATION;
-			ds = cont->dataseg;
-			n = sg_count;
-			if (n > DATASEGS_PER_CONT)
-				n = DATASEGS_PER_CONT;
-			for (i = 0; i < n; ++i) {
-				ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma_address(sg)));
-				ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma_address(sg)));
-				ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
-				++sg;
-			}
-			sg_count -= n;
-		}
-	} else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE) {
-		struct page *page = virt_to_page(Cmnd->request_buffer);
-		unsigned long offset = offset_in_page(Cmnd->request_buffer);
-		dma_addr_t busaddr = pci_map_page(hostdata->pci_dev,
-						  page, offset,
-						  Cmnd->request_bufflen,
-						  Cmnd->sc_data_direction);
-		Cmnd->SCp.dma_handle = busaddr;
-
-		cmd->dataseg[0].d_base = cpu_to_le32(pci64_dma_lo32(busaddr));
-		cmd->dataseg[0].d_base_hi = cpu_to_le32(pci64_dma_hi32(busaddr));
-		cmd->dataseg[0].d_count = cpu_to_le32(Cmnd->request_bufflen);
-		cmd->segment_cnt = cpu_to_le16(1);
-	} else {
-		cmd->dataseg[0].d_base = 0;
-		cmd->dataseg[0].d_base_hi = 0;
-		cmd->segment_cnt = cpu_to_le16(1); /* Shouldn't this be 0? */
-	}
-
-	if (Cmnd->sc_data_direction == DMA_TO_DEVICE)
-		cmd->control_flags = cpu_to_le16(CFLAG_WRITE);
-	else 
-		cmd->control_flags = cpu_to_le16(CFLAG_READ);
-
-	if (Cmnd->device->tagged_supported) {
-		if (time_after(jiffies, hostdata->tag_ages[Cmnd->device->id] + (2 * ISP_TIMEOUT))) {
-			cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
-			hostdata->tag_ages[Cmnd->device->id] = jiffies;
-		} else
-			switch (Cmnd->tag) {
-			case HEAD_OF_QUEUE_TAG:
-				cmd->control_flags |= cpu_to_le16(CFLAG_HEAD_TAG);
-				break;
-			case ORDERED_QUEUE_TAG:
-				cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
-				break;
-			default:
-				cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
-				break;
-		}
-	}
-	/*
-	 * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped
-	 * commands attempted" unless we setup at least a simple queue (midlayer 
-	 * will embelish this once it can do an INQUIRY command to the device)
-	 */
-	else
-		cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
-	outw(in_ptr, host->io_port + MBOX4);
-	hostdata->req_in_ptr = in_ptr;
-
-	hostdata->queued++;
-
-	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
-	num_free = (num_free > 2) ? num_free - 2 : 0;
-       host->can_queue = host->host_busy + num_free;
-	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
-		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
-	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
-	LEAVE("isp2x00_queuecommand");
-
-	return 0;
-}
-
-
-/* we have received an event, such as a lip or an RSCN, which may mean that
- * our port database is incorrect so the port database must be recreated.
- */
-static void redo_port_db(unsigned long arg)
-{
-
-        struct Scsi_Host * host = (struct Scsi_Host *) arg;
-	struct isp2x00_hostdata * hostdata;
-	unsigned long flags;
-	int i;
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-	hostdata->explore_timer.data = 0;
-	del_timer(&hostdata->explore_timer);
-
-	spin_lock_irqsave(host->host_lock, flags);
-
-	if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
-		isp2x00_make_portdb(host);
-		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
-		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
-			printk("wwn: %08x%08x  scsi_id: %x  loop_id: ", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i);
-			if (hostdata->port_db[i].loop_id != hostdata->port_db[0].loop_id || i == 0)
-			        printk("%x", hostdata->port_db[i].loop_id);
-			else
-			        printk("Not Available");
-			printk("\n");
-		}
-		
-	        for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++){ 
-		        if (hostdata->handle_ptrs[i] && (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id > QLOGICFC_MAX_LOOP_ID || hostdata->adapter_state & AS_REDO_LOOP_PORTDB)){
-                                if (hostdata->port_db[hostdata->handle_ptrs[i]->device->id].loop_id != hostdata->port_db[0].loop_id){
-					Scsi_Cmnd *Cmnd = hostdata->handle_ptrs[i];
-
-					 if (Cmnd->use_sg)
-						 pci_unmap_sg(hostdata->pci_dev,
-							      (struct scatterlist *)Cmnd->buffer,
-							      Cmnd->use_sg,
-							      Cmnd->sc_data_direction);
-					 else if (Cmnd->request_bufflen &&
-						  Cmnd->sc_data_direction != PCI_DMA_NONE) {
-						 pci_unmap_page(hostdata->pci_dev,
-								Cmnd->SCp.dma_handle,
-								Cmnd->request_bufflen,
-								Cmnd->sc_data_direction);
-					 }
-
-					 hostdata->handle_ptrs[i]->result = DID_SOFT_ERROR << 16;
-
-					 if (hostdata->handle_ptrs[i]->scsi_done){
-					   (*hostdata->handle_ptrs[i]->scsi_done) (hostdata->handle_ptrs[i]);
-					 }
-					 else printk("qlogicfc%d : done is null?\n", hostdata->host_id);
-					 hostdata->handle_ptrs[i] = NULL;
-					 hostdata->handle_serials[i] = 0;
-				}
-			}
-		}
-		
-		hostdata->adapter_state = AS_LOOP_GOOD;
-	}
-
-	spin_unlock_irqrestore(host->host_lock, flags);
-
-}
-
-#define ASYNC_EVENT_INTERRUPT	0x01
-
-irqreturn_t do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct Scsi_Host *host = dev_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(host->host_lock, flags);
-	isp2x00_intr_handler(irq, dev_id, regs);
-	spin_unlock_irqrestore(host->host_lock, flags);
-
-	return IRQ_HANDLED;
-}
-
-void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-	Scsi_Cmnd *Cmnd;
-	struct Status_Entry *sts;
-	struct Scsi_Host *host = dev_id;
-	struct isp2x00_hostdata *hostdata;
-	u_int in_ptr, out_ptr, handle, num_free;
-	u_short status;
-
-	ENTER_INTR("isp2x00_intr_handler");
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-	DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq));
-
-	if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
-		/* spurious interrupts can happen legally */
-		DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id));
-		return;
-	}
-	in_ptr = inw(host->io_port + MBOX5);
-	out_ptr = hostdata->res_out_ptr;
-
-	if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
-		status = inw(host->io_port + MBOX0);
-
-		DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n",
-				  hostdata->host_id, status));
-
-		switch (status) {
-		case LOOP_UP:
-		case POINT_TO_POINT_UP:
-		        printk("qlogicfc%d : Link is Up\n", hostdata->host_id);
-			hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;
-			break;
-		case LOOP_DOWN:
-		        printk("qlogicfc%d : Link is Down\n", hostdata->host_id);
-			hostdata->adapter_state = AS_LOOP_DOWN;
-			break;
-		case CONNECTION_MODE:
-		        printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
-			break;
-		case CHANGE_NOTIFICATION:
-		        printk("qlogicfc%d : RSCN Received\n", hostdata->host_id);
-			if (hostdata->adapter_state == AS_LOOP_GOOD)
-				hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
-			break;		        
-		case LIP_OCCURRED:
-		case LIP_RECEIVED:
-		        printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
-			if (hostdata->adapter_state == AS_LOOP_GOOD)
-				hostdata->adapter_state = AS_REDO_LOOP_PORTDB;
-			break;
-		case SYSTEM_ERROR:
-			printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);
-			hostdata->adapter_state = AS_FIRMWARE_DEAD;
-			break;
-		case SCSI_COMMAND_COMPLETE:
-			handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);
-			Cmnd = hostdata->handle_ptrs[handle];
-			hostdata->handle_ptrs[handle] = NULL;
-			hostdata->handle_serials[handle] = 0;
-			hostdata->queued--;
-			if (Cmnd != NULL) {
-				if (Cmnd->use_sg)
-					pci_unmap_sg(hostdata->pci_dev,
-						     (struct scatterlist *)Cmnd->buffer,
-						     Cmnd->use_sg,
-						     Cmnd->sc_data_direction);
-				else if (Cmnd->request_bufflen &&
-					 Cmnd->sc_data_direction != PCI_DMA_NONE)
-					pci_unmap_page(hostdata->pci_dev,
-						       Cmnd->SCp.dma_handle,
-						       Cmnd->request_bufflen,
-						       Cmnd->sc_data_direction);
-				Cmnd->result = 0x0;
-				(*Cmnd->scsi_done) (Cmnd);
-			} else
-				printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id);
-			break;
-		case MBOX_COMMAND_COMPLETE:
-		case INVALID_COMMAND:
-		case HOST_INTERFACE_ERROR:
-		case TEST_FAILED:
-		case COMMAND_ERROR:
-		case COMMAND_PARAM_ERROR:
-		case PORT_ID_USED:
-		case LOOP_ID_USED:
-		case ALL_IDS_USED:
-			hostdata->mbox_done = 1;
-			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
-			return;
-		default:
-			printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);
-		}
-		if ((hostdata->adapter_state & AS_REDO_LOOP_PORTDB || hostdata->adapter_state & AS_REDO_FABRIC_PORTDB) && hostdata->explore_timer.data == 0){
-                        hostdata->explore_timer.function = redo_port_db;
-			hostdata->explore_timer.data = (unsigned long)host;
-			hostdata->explore_timer.expires = jiffies + (HZ/4);
-			init_timer(&hostdata->explore_timer);
-			add_timer(&hostdata->explore_timer);
-		}
-		outw(0x0, host->io_port + PCI_SEMAPHORE);
-	} else {
-		DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));
-		DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
-
-		while (out_ptr != in_ptr) {
-			unsigned le_hand;
-			sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];
-			out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
-                 
-			TRACE("done", out_ptr, Cmnd);
-			DEBUG_INTR(isp2x00_print_status_entry(sts));
-			le_hand = le32_to_cpu(sts->handle);
-			if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) {
-				Cmnd->result = isp2x00_return_status(Cmnd, sts);
-				hostdata->queued--;
-
-				if (Cmnd->use_sg)
-					pci_unmap_sg(hostdata->pci_dev,
-						     (struct scatterlist *)Cmnd->buffer, Cmnd->use_sg,
-						     Cmnd->sc_data_direction);
-				else if (Cmnd->request_bufflen && Cmnd->sc_data_direction != PCI_DMA_NONE)
-					pci_unmap_page(hostdata->pci_dev,
-						       Cmnd->SCp.dma_handle,
-						       Cmnd->request_bufflen,
-						       Cmnd->sc_data_direction);
-
-				/* 
-				 * if any of the following are true we do not
-				 * call scsi_done.  if the status is CS_ABORTED
-				 * we don't have to call done because the upper
-				 * level should already know its aborted.
-				 */
-				if (hostdata->handle_serials[le_hand] != Cmnd->serial_number 
-				    || le16_to_cpu(sts->completion_status) == CS_ABORTED){
-					hostdata->handle_serials[le_hand] = 0;
-					hostdata->handle_ptrs[le_hand] = NULL;
-					outw(out_ptr, host->io_port + MBOX5);
-					continue;
-				}
-				/*
-				 * if we get back an error indicating the port
-				 * is not there or if the link is down and 
-				 * this is a device that used to be there 
-				 * allow the command to timeout.
-				 * the device may well be back in a couple of
-				 * seconds.
-				 */
-				if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == cpu_to_le16(CS_PORT_UNAVAILABLE) || sts->completion_status == cpu_to_le16(CS_PORT_LOGGED_OUT) || sts->completion_status == cpu_to_le16(CS_PORT_CONFIG_CHANGED)) && hostdata->port_db[Cmnd->device->id].wwn){
-					outw(out_ptr, host->io_port + MBOX5);
-					continue;
-				}
-			} else {
-				outw(out_ptr, host->io_port + MBOX5);
-				continue;
-			}
-
-			hostdata->handle_ptrs[le_hand] = NULL;
-
-			if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)
-			    || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))
-				hostdata->send_marker = 1;
-
-			if (le16_to_cpu(sts->scsi_status) & 0x0200)
-				memcpy(Cmnd->sense_buffer, sts->req_sense_data,
-				       sizeof(Cmnd->sense_buffer));
-
-			outw(out_ptr, host->io_port + MBOX5);
-
-			if (Cmnd->scsi_done != NULL) {
-				(*Cmnd->scsi_done) (Cmnd);
-			} else
-				printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id);
-		}
-		hostdata->res_out_ptr = out_ptr;
-	}
-
-
-	out_ptr = inw(host->io_port + MBOX4);
-	in_ptr = hostdata->req_in_ptr;
-
-	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
-	num_free = (num_free > 2) ? num_free - 2 : 0;
-       host->can_queue = host->host_busy + num_free;
-	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
-		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
-	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
-	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
-	LEAVE_INTR("isp2x00_intr_handler");
-}
-
-
-static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
-{
-	int host_status = DID_ERROR;
-#if DEBUG_ISP2x00_INTR
-	static char *reason[] =
-	{
-		"DID_OK",
-		"DID_NO_CONNECT",
-		"DID_BUS_BUSY",
-		"DID_TIME_OUT",
-		"DID_BAD_TARGET",
-		"DID_ABORT",
-		"DID_PARITY",
-		"DID_ERROR",
-		"DID_RESET",
-		"DID_BAD_INTR"
-	};
-#endif				/* DEBUG_ISP2x00_INTR */
-
-	ENTER("isp2x00_return_status");
-
-	DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
-		     le16_to_cpu(sts->completion_status)));
-
-	switch (le16_to_cpu(sts->completion_status)) {
-	case CS_COMPLETE:
-		host_status = DID_OK;
-		break;
-	case CS_DMA_ERROR:
-		host_status = DID_ERROR;
-		break;
-	case CS_RESET_OCCURRED:
-		host_status = DID_RESET;
-		break;
-	case CS_ABORTED:
-		host_status = DID_ABORT;
-		break;
-	case CS_TIMEOUT:
-		host_status = DID_TIME_OUT;
-		break;
-	case CS_DATA_OVERRUN:
-		host_status = DID_ERROR;
-		break;
-	case CS_DATA_UNDERRUN:
-	        if (Cmnd->underflow <= (Cmnd->request_bufflen - le32_to_cpu(sts->residual)))
-		        host_status = DID_OK;
-		else
-		        host_status = DID_ERROR;
-		break;
-	case CS_PORT_UNAVAILABLE:
-	case CS_PORT_LOGGED_OUT:
-	case CS_PORT_CONFIG_CHANGED:
-		host_status = DID_BAD_TARGET;
-		break;
-	case CS_QUEUE_FULL:
-		host_status = DID_ERROR;
-		break;
-	default:
-		printk("qlogicfc : unknown completion status 0x%04x\n",
-		       le16_to_cpu(sts->completion_status));
-		host_status = DID_ERROR;
-		break;
-	}
-
-	DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
-			  reason[host_status], le16_to_cpu(sts->scsi_status)));
-
-	LEAVE("isp2x00_return_status");
-
-	return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);
-}
-
-
-static int isp2x00_abort(Scsi_Cmnd * Cmnd)
-{
-	u_short param[8];
-	int i;
-	struct Scsi_Host *host;
-	struct isp2x00_hostdata *hostdata;
-	int return_status = SUCCESS;
-
-	ENTER("isp2x00_abort");
-
-	host = Cmnd->device->host;
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-	for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)
-		if (hostdata->handle_ptrs[i] == Cmnd)
-			break;
-
-	if (i == QLOGICFC_REQ_QUEUE_LEN){
-		return SUCCESS;
-	}
-
-	isp2x00_disable_irqs(host);
-
-	param[0] = MBOX_ABORT_IOCB;
-#if ISP2x00_PORTDB
-	param[1] = (((u_short) hostdata->port_db[Cmnd->device->id].loop_id) << 8) | Cmnd->device->lun;
-#else
-	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-#endif
-	param[2] = i & 0xffff;
-	param[3] = i >> 16;
-
-	isp2x00_mbox_command(host, param);
-
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]);
-		if (param[0] == 0x4005)
-			Cmnd->result = DID_ERROR << 16;
-		if (param[0] == 0x4006)
-			Cmnd->result = DID_BAD_TARGET << 16;
-		return_status = FAILED;
-	}
-
-	if (return_status != SUCCESS){
-		param[0] = MBOX_GET_FIRMWARE_STATE;
-		isp2x00_mbox_command(host, param);
-		printk("qlogicfc%d : abort failed\n", hostdata->host_id);
-		printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]);
-	}
-
-	isp2x00_enable_irqs(host);
-
-	LEAVE("isp2x00_abort");
-
-	return return_status;
-}
-
-
-static int isp2x00_biosparam(struct scsi_device *sdev, struct block_device *n,
-		sector_t capacity, int ip[])
-{
-	int size = capacity;
-
-	ENTER("isp2x00_biosparam");
-
-	ip[0] = 64;
-	ip[1] = 32;
-	ip[2] = size >> 11;
-	if (ip[2] > 1024) {
-		ip[0] = 255;
-		ip[1] = 63;
-		ip[2] = size / (ip[0] * ip[1]);
-	}
-	LEAVE("isp2x00_biosparam");
-
-	return 0;
-}
-
-static int isp2x00_reset_hardware(struct Scsi_Host *host)
-{
-	u_short param[8];
-	struct isp2x00_hostdata *hostdata;
-	int loop_count;
-	dma_addr_t busaddr;
-
-	ENTER("isp2x00_reset_hardware");
-
-	hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-	/*
-	 *	This cannot be right - PCI writes are posted
-	 *	(apparently this is hardware design flaw not software ?)
-	 */
-	 
-	outw(0x01, host->io_port + ISP_CTRL_STATUS);
-	udelay(100);
-	outw(HCCR_RESET, host->io_port + HOST_HCCR);
-	udelay(100);
-	outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
-	outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
-
-	loop_count = DEFAULT_LOOP_COUNT;
-	while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) {
-		barrier();
-		cpu_relax();
-	}
-	if (!loop_count)
-		printk("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id);
-
-
-
-#if DEBUG_ISP2x00
-	printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX0));
-	printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX1));
-	printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX2));
-	printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX3));
-	printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX4));
-	printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX5));
-	printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX6));
-	printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX7));
-#endif				/* DEBUG_ISP2x00 */
-
-	DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id));
-
-#if defined(CONFIG_SCSI_QLOGIC_FC_FIRMWARE)
-	{
-		int i;
-		unsigned short * risc_code = NULL;
-		unsigned short risc_code_len = 0;
-		if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){
-		        risc_code = risc_code2100;
-			risc_code_len = risc_code_length2100;
-		}
-		else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){
-		        risc_code = risc_code2200;
-			risc_code_len = risc_code_length2200;
-		}
-
-		for (i = 0; i < risc_code_len; i++) {
-			param[0] = MBOX_WRITE_RAM_WORD;
-			param[1] = risc_code_addr01 + i;
-			param[2] = risc_code[i];
-
-			isp2x00_mbox_command(host, param);
-
-			if (param[0] != MBOX_COMMAND_COMPLETE) {
-				printk("qlogicfc%d : firmware load failure\n", hostdata->host_id);
-				return 1;
-			}
-		}
-	}
-#endif				/* RELOAD_FIRMWARE */
-
-	param[0] = MBOX_VERIFY_CHECKSUM;
-	param[1] = risc_code_addr01;
-
-	isp2x00_mbox_command(host, param);
-
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id);
-		return 1;
-	}
-	DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id));
-
-	param[0] = MBOX_EXEC_FIRMWARE;
-	param[1] = risc_code_addr01;
-
-	isp2x00_mbox_command(host, param);
-
-	param[0] = MBOX_ABOUT_FIRMWARE;
-
-	isp2x00_mbox_command(host, param);
-
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc%d : about firmware failure\n", hostdata->host_id);
-		return 1;
-	}
-	DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id,  param[1]));
-	DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id,  param[2]));
-
-#ifdef USE_NVRAM_DEFAULTS
-
-	if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) {
-		printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id);
-	}
-#endif
-
-	hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8;
-	hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8;
-
-	/* FIXME: If the DMA transfer goes one way only, this should use
-	 *        PCI_DMA_TODEVICE and below as well.
-	 */
-	busaddr = pci_map_page(hostdata->pci_dev,
-			       virt_to_page(&hostdata->control_block),
-			       offset_in_page(&hostdata->control_block),
-			       sizeof(hostdata->control_block),
-			       PCI_DMA_BIDIRECTIONAL);
-
-	param[0] = MBOX_INIT_FIRMWARE;
-	param[2] = (u_short) (pci64_dma_lo32(busaddr) >> 16);
-	param[3] = (u_short) (pci64_dma_lo32(busaddr) & 0xffff);
-	param[4] = 0;
-	param[5] = 0;
-	param[6] = (u_short) (pci64_dma_hi32(busaddr) >> 16);
-	param[7] = (u_short) (pci64_dma_hi32(busaddr) & 0xffff);
-	isp2x00_mbox_command(host, param);
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id,  param[0]);
-		pci_unmap_page(hostdata->pci_dev, busaddr,
-			       sizeof(hostdata->control_block),
-			       PCI_DMA_BIDIRECTIONAL);
-		return 1;
-	}
-	param[0] = MBOX_GET_FIRMWARE_STATE;
-	isp2x00_mbox_command(host, param);
-	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id,  param[0]);
-		pci_unmap_page(hostdata->pci_dev, busaddr,
-			       sizeof(hostdata->control_block),
-			       PCI_DMA_BIDIRECTIONAL);
-		return 1;
-	}
-
-	pci_unmap_page(hostdata->pci_dev, busaddr,
-		       sizeof(hostdata->control_block),
-		       PCI_DMA_BIDIRECTIONAL);
-	LEAVE("isp2x00_reset_hardware");
-
-	return 0;
-}
-
-#ifdef USE_NVRAM_DEFAULTS
-
-static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
-{
-
-	u_short value;
-	if (isp2x00_read_nvram_word(host, 0) != 0x5349)
-		return 1;
-
-	value = isp2x00_read_nvram_word(host, 8);
-	control_block->node_name[0] = cpu_to_le16(isp2x00_read_nvram_word(host, 9));
-	control_block->node_name[1] = cpu_to_le16(isp2x00_read_nvram_word(host, 10));
-	control_block->node_name[2] = cpu_to_le16(isp2x00_read_nvram_word(host, 11));
-	control_block->node_name[3] = cpu_to_le16(isp2x00_read_nvram_word(host, 12));
-	control_block->hard_addr = cpu_to_le16(isp2x00_read_nvram_word(host, 13));
-
-	return 0;
-
-}
-
-#endif
-
-static int isp2x00_init(struct Scsi_Host *sh)
-{
-	u_long io_base;
-	struct isp2x00_hostdata *hostdata;
-	u_char revision;
-	u_int irq;
-	u_short command;
-	struct pci_dev *pdev;
-
-
-	ENTER("isp2x00_init");
-
-	hostdata = (struct isp2x00_hostdata *) sh->hostdata;
-	pdev = hostdata->pci_dev;
-
-	if (pci_read_config_word(pdev, PCI_COMMAND, &command)
-	  || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) {
-		printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id);
-		return 1;
-	}
-	io_base = pci_resource_start(pdev, 0);
-	irq = pdev->irq;
-
-
-	if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
-		printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id, 
-		       pdev->vendor);
-		return 1;
-	}
-	if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) {
-		printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id, 
-		       pdev->device);
-		return 1;
-	}
-	if (!(command & PCI_COMMAND_IO) ||
-	    !(pdev->resource[0].flags & IORESOURCE_IO)) {
-		printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id);
-		return 1;
-	}
-
-	pci_set_master(pdev);
-	if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5)
-		printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id,  revision);
-
-
-	hostdata->revision = revision;
-
-	sh->irq = irq;
-	sh->io_port = io_base;
-
-	LEAVE("isp2x00_init");
-
-	return 0;
-}
-
-#if USE_NVRAM_DEFAULTS
-
-#define NVRAM_DELAY() udelay(10)	/* 10 microsecond delay */
-
-
-u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte)
-{
-	int i;
-	u_short value, output, input;
-
-	outw(0x2, host->io_port + PCI_NVRAM);
-	NVRAM_DELAY();
-	outw(0x3, host->io_port + PCI_NVRAM);
-	NVRAM_DELAY();
-
-	byte &= 0xff;
-	byte |= 0x0600;
-	for (i = 10; i >= 0; i--) {
-		output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
-		outw(output | 0x2, host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-		outw(output | 0x3, host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-		outw(output | 0x2, host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-	}
-
-	for (i = 0xf, value = 0; i >= 0; i--) {
-		value <<= 1;
-		outw(0x3, host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-		input = inw(host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-		outw(0x2, host->io_port + PCI_NVRAM);
-		NVRAM_DELAY();
-		if (input & 0x8)
-			value |= 1;
-	}
-
-	outw(0x0, host->io_port + PCI_NVRAM);
-	NVRAM_DELAY();
-
-	return value;
-}
-
-
-#endif				/* USE_NVRAM_DEFAULTS */
-
-
-
-/*
- * currently, this is only called during initialization or abort/reset,
- * at which times interrupts are disabled, so polling is OK, I guess...
- */
-static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[])
-{
-	int loop_count;
-	struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
-	if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD)
-		return 1;
-
-	loop_count = DEFAULT_LOOP_COUNT;
-	while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) {
-		barrier();
-		cpu_relax();
-	}
-	if (!loop_count) {
-		printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id);
-		param[0] = 0x4006;
-		hostdata->adapter_state = AS_FIRMWARE_DEAD;
-		return 1;
-	}
-	hostdata->mbox_done = 0;
-
-	if (mbox_param[param[0]] == 0)
-		printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id);
-
-	if (mbox_param[param[0]] & 0x80)
-		outw(param[7], host->io_port + MBOX7);
-	if (mbox_param[param[0]] & 0x40)
-		outw(param[6], host->io_port + MBOX6);
-	if (mbox_param[param[0]] & 0x20)
-		outw(param[5], host->io_port + MBOX5);
-	if (mbox_param[param[0]] & 0x10)
-		outw(param[4], host->io_port + MBOX4);
-	if (mbox_param[param[0]] & 0x08)
-		outw(param[3], host->io_port + MBOX3);
-	if (mbox_param[param[0]] & 0x04)
-		outw(param[2], host->io_port + MBOX2);
-	if (mbox_param[param[0]] & 0x02)
-		outw(param[1], host->io_port + MBOX1);
-	if (mbox_param[param[0]] & 0x01)
-		outw(param[0], host->io_port + MBOX0);
-
-
-	outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
-
-	while (1) {
-		loop_count = DEFAULT_LOOP_COUNT;
-		while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) { 
-			barrier();
-			cpu_relax();
-		}
-
-		if (!loop_count) {
-			hostdata->adapter_state = AS_FIRMWARE_DEAD;
-			printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id);
-			break;
-		}
-		isp2x00_intr_handler(host->irq, host, NULL);
-
-		if (hostdata->mbox_done == 1)
-			break;
-
-	}
-
-	loop_count = DEFAULT_LOOP_COUNT;
-	while (--loop_count && inw(host->io_port + MBOX0) == 0x04) {
-		barrier();
-		cpu_relax();
-	}
-	if (!loop_count)
-		printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id);
-
-	param[7] = inw(host->io_port + MBOX7);
-	param[6] = inw(host->io_port + MBOX6);
-	param[5] = inw(host->io_port + MBOX5);
-	param[4] = inw(host->io_port + MBOX4);
-	param[3] = inw(host->io_port + MBOX3);
-	param[2] = inw(host->io_port + MBOX2);
-	param[1] = inw(host->io_port + MBOX1);
-	param[0] = inw(host->io_port + MBOX0);
-
-
-	outw(0x0, host->io_port + PCI_SEMAPHORE);
-
-	if (inw(host->io_port + HOST_HCCR) & 0x0080) {
-		hostdata->adapter_state = AS_FIRMWARE_DEAD;
-		printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id);
-	}
-	return 0;
-}
-
-#if DEBUG_ISP2x00_INTR
-
-void isp2x00_print_status_entry(struct Status_Entry *status)
-{
-	printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", 
-	status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
-	printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
-	       le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status));
-	printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n", 
-	       le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags));
-	printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
-	       le16_to_cpu(status->res_info_len), le16_to_cpu(status->req_sense_len));
-	printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", le32_to_cpu(status->residual), status->res_info[3]);
-
-}
-
-#endif                         /* DEBUG_ISP2x00_INTR */
-
-
-#if DEBUG_ISP2x00
-
-void isp2x00_print_scsi_cmd(Scsi_Cmnd * cmd)
-{
-	int i;
-
-	printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", 
-	       cmd->target, cmd->lun, cmd->cmd_len);
-	printk("qlogicfc : command = ");
-	for (i = 0; i < cmd->cmd_len; i++)
-		printk("0x%02x ", cmd->cmnd[i]);
-	printk("\n");
-}
-
-#endif				/* DEBUG_ISP2x00 */
-
-MODULE_LICENSE("GPL");
-
-static struct scsi_host_template driver_template = {
-        .detect                 = isp2x00_detect,
-        .release                = isp2x00_release,
-        .info                   = isp2x00_info,
-        .queuecommand           = isp2x00_queuecommand,
-        .eh_abort_handler       = isp2x00_abort,
-        .bios_param             = isp2x00_biosparam,
-        .can_queue              = QLOGICFC_REQ_QUEUE_LEN,
-        .this_id                = -1,
-        .sg_tablesize           = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN),
-	.cmd_per_lun		= QLOGICFC_CMD_PER_LUN,
-        .use_clustering         = ENABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c
deleted file mode 100644
index b1d4510..0000000
--- a/drivers/scsi/qlogicfc_asm.c
+++ /dev/null
@@ -1,9751 +0,0 @@
-/************************************************************************
- *									*
- * 	 --- ISP2100 Fabric Initiator/Target Firmware ---               *
- *                   with expanded LUN addressing                       *
- *                   and FcTape (FCP-2) support                         *
- *									*
- *									*
- ************************************************************************
-  Copyright (C) 2000 and 2001 Qlogic Corporation 
-  (www.qlogic.com)
-
-  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.
-************************************************************************/
-
-/*
- *	Firmware Version 1.19.16 (10:36 Nov 02, 2000)
- */
-
-static unsigned short risc_code_addr01 = 0x1000 ;
-
-static unsigned short risc_code_length2100 = 0x9260;
-static unsigned short risc_code2100[] = {
-	0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010,
-	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
-	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1,
-	0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff,
-	0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04,
-	0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c,
-	0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020,
-	0x2039, 0x8fff, 0x20a1, 0xaa00, 0x2708, 0x810d, 0x810d, 0x810d,
-	0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8,
-	0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102,
-	0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1,
-	0xa260, 0x2009, 0x0000, 0x20a9, 0x07a0, 0x41a4, 0x3400, 0x20c9,
-	0xa7ff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x255d,
-	0x2051, 0xa300, 0x2a70, 0x775e, 0xa786, 0x8fff, 0x0040, 0x1092,
-	0x705b, 0xca00, 0x7057, 0xc9f1, 0x7063, 0x0200, 0x7067, 0x0200,
-	0x0078, 0x109a, 0x7057, 0xba01, 0x7063, 0x0100, 0x7067, 0x0100,
-	0x705b, 0xba00, 0x1078, 0x12df, 0x1078, 0x13c0, 0x1078, 0x1569,
-	0x1078, 0x1ca4, 0x1078, 0x4229, 0x1078, 0x74cf, 0x1078, 0x134b,
-	0x1078, 0x2a3f, 0x1078, 0x4da2, 0x1078, 0x48b2, 0x1078, 0x57df,
-	0x1078, 0x21f7, 0x1078, 0x5abf, 0x1078, 0x5369, 0x1078, 0x210d,
-	0x1078, 0x21d4, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf,
-	0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068,
-	0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
-	0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000,
-	0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x35bc, 0x1078, 0x2a67,
-	0x1078, 0x4df2, 0x1078, 0x4a75, 0x2009, 0x0100, 0x2104, 0xa082,
-	0x0002, 0x0048, 0x10f3, 0x1078, 0x57fb, 0x0078, 0x10d6, 0x1079,
-	0x10f7, 0x0078, 0x10dc, 0x1078, 0x6fa9, 0x0078, 0x10eb, 0x1101,
-	0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078,
-	0x1328, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086,
-	0x0001, 0x00c0, 0x1198, 0x1078, 0x3a43, 0x2079, 0x0100, 0x7844,
-	0xa005, 0x00c0, 0x1198, 0x2011, 0x4129, 0x1078, 0x58d4, 0x1078,
-	0x1ab1, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011,
-	0x8010, 0x73c0, 0x1078, 0x3579, 0x2001, 0xffff, 0x1078, 0x5975,
-	0x7238, 0xc284, 0x723a, 0x2001, 0xa30c, 0x2014, 0xc2ac, 0x2202,
-	0x1078, 0x6db5, 0x2011, 0x0004, 0x1078, 0x8a59, 0x1078, 0x47ce,
-	0x1078, 0x4211, 0x0040, 0x1144, 0x7083, 0x0001, 0x70bb, 0x0000,
-	0x1078, 0x3bf5, 0x0078, 0x1198, 0x1078, 0x4897, 0x0040, 0x114d,
-	0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x8ddf, 0x70c8,
-	0xd09c, 0x00c0, 0x1159, 0x7094, 0xa005, 0x0040, 0x1159, 0x1078,
-	0x41f5, 0x70d3, 0x0000, 0x70cf, 0x0000, 0x72c8, 0x2079, 0xa351,
-	0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ca, 0xa296, 0x0004,
-	0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8a59, 0x708f, 0x0000,
-	0x7093, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x260d, 0x2011,
-	0x0005, 0x1078, 0x6ef2, 0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100,
-	0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x708f, 0x0000,
-	0x7093, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x6ef2,
-	0x1078, 0x6109, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f,
-	0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e,
-	0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078,
-	0x71e0, 0x027f, 0x1078, 0xa190, 0x037f, 0x027f, 0x017f, 0x1078,
-	0x2921, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706b, 0x0000, 0x706c,
-	0xa084, 0x00ff, 0x706e, 0x7097, 0x0000, 0x007c, 0x127e, 0x2091,
-	0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7090, 0xa086,
-	0xffff, 0x0040, 0x11d1, 0x1078, 0x260d, 0x1078, 0x6109, 0x0078,
-	0x1244, 0x70c8, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd,
-	0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
-	0x0040, 0x11fd, 0x70cc, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078,
-	0x278a, 0x1078, 0x6109, 0x70c8, 0xd094, 0x00c0, 0x1244, 0x2011,
-	0x0001, 0x2019, 0x0000, 0x1078, 0x27c2, 0x1078, 0x6109, 0x0078,
-	0x1244, 0x70d0, 0xa005, 0x00c0, 0x1244, 0x708c, 0xa005, 0x00c0,
-	0x1244, 0x1078, 0x4897, 0x00c0, 0x1244, 0x2001, 0xa352, 0x2004,
-	0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x121a, 0x6000, 0xd0ec,
-	0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f,
-	0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003,
-	0x0003, 0x7093, 0xffff, 0x2001, 0x0000, 0x1078, 0x2480, 0x1078,
-	0x35f7, 0x2001, 0xa5ac, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c,
-	0x2011, 0x0000, 0x1078, 0x6ef2, 0x2011, 0x0000, 0x1078, 0x6efc,
-	0x1078, 0x6109, 0x1078, 0x61d3, 0x127f, 0x007c, 0x017e, 0x0f7e,
-	0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078,
-	0x41de, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040,
-	0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008,
-	0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5975, 0x7900, 0xa18a,
-	0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009,
-	0x00f8, 0x1078, 0x41de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
-	0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0,
-	0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x2480, 0x0078,
-	0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0,
-	0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f,
-	0x0000, 0x2009, 0x00f8, 0x1078, 0x41de, 0x20a9, 0x000e, 0x0005,
-	0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010,
-	0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4,
-	0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009,
-	0xa331, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4,
-	0x200b, 0x0000, 0x1078, 0x251e, 0x2001, 0x0001, 0x1078, 0x2480,
-	0x0078, 0x12d3, 0x2001, 0xa331, 0x2003, 0x0000, 0x7828, 0xc09d,
-	0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f,
-	0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70,
-	0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048, 0x12eb, 0x704f,
-	0xffff, 0x0078, 0x12ed, 0x704f, 0x0000, 0x7053, 0xffff, 0x706b,
-	0x0000, 0x706f, 0x0000, 0x1078, 0x8ddf, 0x2061, 0xa58c, 0x6003,
-	0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
-	0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
-	0xa594, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
-	0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
-	0x0000, 0x2061, 0xa5a3, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b,
-	0x4943, 0x600f, 0x2020, 0x2001, 0xa325, 0x2003, 0x0000, 0x007c,
-	0x2091, 0x8000, 0x0068, 0x132a, 0x007e, 0x017e, 0x2079, 0x0000,
-	0x7818, 0xd084, 0x00c0, 0x1330, 0x017f, 0x792e, 0x007f, 0x782a,
-	0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001,
-	0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa300, 0x7803, 0x0005,
-	0x0078, 0x1348, 0x007c, 0x2071, 0xa300, 0x7158, 0x712e, 0x2021,
-	0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048, 0x1361, 0x705c,
-	0xa302, 0x00c8, 0x1361, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078,
-	0x1353, 0x200b, 0x0000, 0x74a6, 0x74aa, 0x007c, 0x0e7e, 0x127e,
-	0x2091, 0x8000, 0x2071, 0xa300, 0x70a8, 0xa0ea, 0x0010, 0x00c8,
-	0x1374, 0xa06e, 0x0078, 0x137e, 0x8001, 0x70aa, 0x702c, 0x2068,
-	0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f,
-	0x007c, 0x0e7e, 0x2071, 0xa300, 0x127e, 0x2091, 0x8000, 0x70a8,
-	0x8001, 0x00c8, 0x138e, 0xa06e, 0x0078, 0x1397, 0x70aa, 0x702c,
-	0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f,
-	0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa300,
-	0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa, 0x127f,
-	0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13b6, 0x6804, 0x6807, 0x0000,
-	0x007e, 0x1078, 0x139a, 0x0d7f, 0x0078, 0x13aa, 0x007c, 0x0e7e,
-	0x2071, 0xa300, 0x70a8, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c,
-	0x0e7e, 0x2071, 0xa5d0, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f,
-	0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f,
-	0x007c, 0x0e7e, 0x2270, 0x700b, 0x0000, 0x2071, 0xa5d0, 0x7018,
-	0xa088, 0xa5d9, 0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004,
-	0xa005, 0x00c0, 0x13e9, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa,
-	0x0f7f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa5d0, 0x7004, 0xa005,
-	0x00c0, 0x13f8, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13fa, 0x0f7f,
-	0x0e7f, 0x007c, 0x7000, 0x0079, 0x13fd, 0x1401, 0x146b, 0x1488,
-	0x1488, 0x7018, 0x711c, 0xa106, 0x00c0, 0x1409, 0x7007, 0x0000,
-	0x007c, 0x0d7e, 0xa180, 0xa5d9, 0x2004, 0x700a, 0x2068, 0x8108,
-	0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828,
-	0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c,
-	0x7016, 0x6804, 0x0d7f, 0xd084, 0x0040, 0x142b, 0x7007, 0x0001,
-	0x1078, 0x1430, 0x007c, 0x7007, 0x0002, 0x1078, 0x1446, 0x007c,
-	0x017e, 0x027e, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8,
-	0x143b, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803,
-	0x0020, 0x7803, 0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e,
-	0x137e, 0x147e, 0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803,
-	0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x145a,
-	0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
-	0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f,
-	0x027f, 0x017f, 0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa3f9,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
-	0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
-	0x7002, 0x700b, 0xa3f4, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
-	0x137e, 0x147e, 0x157e, 0x2001, 0xa428, 0x209c, 0x20a1, 0x0014,
-	0x7803, 0x0026, 0x2001, 0xa429, 0x20ac, 0x53a6, 0x2099, 0xa42a,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e,
-	0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
-	0x7002, 0x700b, 0xa425, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c,
-	0x017e, 0x0e7e, 0x2071, 0xa5d0, 0x0f7e, 0x2079, 0x0010, 0x7904,
-	0x7803, 0x0002, 0xd1fc, 0x0040, 0x14c2, 0xa18c, 0x0700, 0x7004,
-	0x1079, 0x14c6, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13fa, 0x14ce,
-	0x14fb, 0x1523, 0x1556, 0x14cc, 0x0078, 0x14cc, 0xa18c, 0x0700,
-	0x00c0, 0x14f4, 0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099,
-	0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016,
-	0x157f, 0x147f, 0x137f, 0x700c, 0xa005, 0x0040, 0x1510, 0x1078,
-	0x1430, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007,
-	0x0000, 0x1078, 0x13fa, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003,
-	0x0200, 0x0078, 0x14ef, 0xa18c, 0x0700, 0x00c0, 0x1506, 0x700c,
-	0xa005, 0x0040, 0x1510, 0x1078, 0x1446, 0x007c, 0x7008, 0xa080,
-	0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x1078, 0x13fa, 0x007c,
-	0x0d7e, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
-	0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000,
-	0x1078, 0x13fa, 0x007c, 0xa18c, 0x0700, 0x00c0, 0x1550, 0x137e,
-	0x147e, 0x157e, 0x2001, 0xa3f7, 0x2004, 0xa080, 0x000d, 0x20a0,
-	0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001,
-	0xa3f9, 0x2004, 0xd0bc, 0x0040, 0x1546, 0x2001, 0xa402, 0x2004,
-	0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f,
-	0x137f, 0x7007, 0x0000, 0x1078, 0x4e9b, 0x1078, 0x13fa, 0x007c,
-	0x2011, 0x8003, 0x1078, 0x3579, 0x0078, 0x1554, 0xa18c, 0x0700,
-	0x00c0, 0x1563, 0x2001, 0xa427, 0x2003, 0x0100, 0x7007, 0x0000,
-	0x1078, 0x13fa, 0x007c, 0x2011, 0x8004, 0x1078, 0x3579, 0x0078,
-	0x1567, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa5e1,
-	0x7803, 0x0004, 0x7003, 0x0000, 0x700f, 0xa5e7, 0x7013, 0xa5e7,
-	0x780f, 0x0076, 0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184,
-	0x0007, 0x0079, 0x1583, 0x158b, 0x15d1, 0x158b, 0x158b, 0x158b,
-	0x15b6, 0x159a, 0x158f, 0xa085, 0x0001, 0x0078, 0x15eb, 0x684c,
-	0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858,
-	0x0078, 0x15d9, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x158b,
-	0x684c, 0xd0bc, 0x0040, 0x158b, 0x6860, 0x682e, 0x685c, 0x682a,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x2015, 0x2004, 0x6832, 0x6858, 0x0078, 0x15e1, 0xa18c, 0x00ff,
-	0xa186, 0x0015, 0x00c0, 0x158b, 0x684c, 0xd0ac, 0x0040, 0x158b,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x2015, 0x2004, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078,
-	0x15e1, 0x684c, 0xd0ac, 0x0040, 0x158b, 0xa006, 0x682e, 0x682a,
-	0x6858, 0xa18c, 0x000f, 0xa188, 0x2015, 0x210c, 0x6932, 0x2d08,
-	0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
-	0x6912, 0x6980, 0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000,
-	0x2001, 0x020a, 0x2004, 0x82ff, 0x0040, 0x160e, 0xa280, 0x0004,
-	0x0d7e, 0x206c, 0x684c, 0xd0dc, 0x00c0, 0x160a, 0x1078, 0x157e,
-	0x0040, 0x160a, 0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016,
-	0x0078, 0x160e, 0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e,
-	0x037e, 0x027e, 0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000,
-	0xa005, 0x00c0, 0x1622, 0x7206, 0x2001, 0x1643, 0x007e, 0x2260,
-	0x0078, 0x17be, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
-	0x8108, 0xa182, 0xa602, 0x0048, 0x162f, 0x2009, 0xa5e7, 0x710e,
-	0x7010, 0xa102, 0xa082, 0x0009, 0x0040, 0x163a, 0xa080, 0x001b,
-	0x00c0, 0x163d, 0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0,
-	0x1643, 0x1078, 0x179f, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e,
-	0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f,
-	0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005,
-	0x0040, 0x16cf, 0x6808, 0xa005, 0x0040, 0x173c, 0x7000, 0xa005,
-	0x00c0, 0x1664, 0x0078, 0x16c4, 0x700c, 0x7110, 0xa106, 0x00c0,
-	0x1745, 0x7004, 0xa406, 0x00c0, 0x16c4, 0x2001, 0x0005, 0x2004,
-	0xd08c, 0x0040, 0x1681, 0x047e, 0x1078, 0x18e2, 0x047f, 0x2460,
-	0x6010, 0xa080, 0x0002, 0x2004, 0xa005, 0x0040, 0x173c, 0x0078,
-	0x165e, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x166d, 0x7804,
-	0xa084, 0x6000, 0x0040, 0x1692, 0xa086, 0x6000, 0x0040, 0x1692,
-	0x0078, 0x166d, 0x7100, 0xa186, 0x0002, 0x00c0, 0x16b2, 0x0e7e,
-	0x2b68, 0x6818, 0x2060, 0x1078, 0x1fea, 0x2804, 0xac70, 0x6034,
-	0xd09c, 0x00c0, 0x16a7, 0x7108, 0x720c, 0x0078, 0x16a9, 0x7110,
-	0x7214, 0x6810, 0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f,
-	0x0078, 0x16b6, 0xa186, 0x0001, 0x00c0, 0x16be, 0x7820, 0x6910,
-	0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0,
-	0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0078, 0x1745, 0x6808,
-	0xa005, 0x0040, 0x173c, 0x7000, 0xa005, 0x00c0, 0x16d9, 0x0078,
-	0x173c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x16e2, 0x7004, 0xa406,
-	0x00c0, 0x173c, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x16f6,
-	0x047e, 0x1078, 0x18e2, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002,
-	0x2004, 0xa005, 0x0040, 0x173c, 0x0078, 0x16d3, 0x2001, 0x0207,
-	0x2004, 0xd09c, 0x00c0, 0x16e2, 0x2001, 0x0005, 0x2004, 0xd08c,
-	0x00c0, 0x16e8, 0x7804, 0xa084, 0x6000, 0x0040, 0x170d, 0xa086,
-	0x6000, 0x0040, 0x170d, 0x0078, 0x16e2, 0x7007, 0x0000, 0xa016,
-	0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x172e, 0xa08e, 0x0002,
-	0x00c0, 0x173c, 0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x1fea,
-	0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x172a, 0x7308, 0x720c,
-	0x0078, 0x172c, 0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318,
-	0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816,
-	0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0,
-	0x1745, 0x2009, 0x0048, 0x1078, 0x756c, 0x0c7f, 0x0d7f, 0x127f,
-	0x007c, 0x0f7e, 0x0e7e, 0x027e, 0x037e, 0x047e, 0x1078, 0x1af7,
-	0x027e, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0000, 0x0040, 0x1790,
-	0x7004, 0xac06, 0x00c0, 0x1781, 0x2079, 0x0030, 0x7000, 0xa086,
-	0x0003, 0x0040, 0x1781, 0x7804, 0xd0fc, 0x00c0, 0x177d, 0x2001,
-	0x0207, 0x2004, 0xd09c, 0x00c0, 0x1763, 0x7803, 0x0004, 0x7804,
-	0xd0ac, 0x00c0, 0x176f, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003,
-	0x0003, 0x7007, 0x0000, 0x0078, 0x1781, 0x1078, 0x18e2, 0x0078,
-	0x1753, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa5e7, 0x2104, 0xac06,
-	0x00c0, 0x178b, 0x200a, 0xa188, 0x0003, 0x00f0, 0x1786, 0x157f,
-	0x027f, 0x2001, 0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138,
-	0x2202, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f, 0x007c, 0x700c,
-	0x7110, 0xa106, 0x00c0, 0x17a7, 0x7003, 0x0000, 0x007c, 0x2104,
-	0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182,
-	0xa602, 0x0048, 0x17b5, 0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106,
-	0x00c0, 0x17be, 0x2001, 0x0138, 0x2003, 0x0008, 0x8cff, 0x00c0,
-	0x17c5, 0x1078, 0x1b22, 0x0078, 0x1823, 0x6010, 0x2068, 0x2d58,
-	0x6828, 0xa406, 0x00c0, 0x17d0, 0x682c, 0xa306, 0x0040, 0x17fe,
-	0x601c, 0xa086, 0x0008, 0x0040, 0x17fe, 0x6024, 0xd0f4, 0x00c0,
-	0x17fa, 0xd0d4, 0x0040, 0x17f6, 0x6038, 0xa402, 0x6034, 0xa303,
-	0x0040, 0x17e4, 0x00c8, 0x17f6, 0x643a, 0x6336, 0x6c2a, 0x6b2e,
-	0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80,
-	0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x17fa, 0x1078, 0x8d8e,
-	0x0040, 0x17c1, 0x1078, 0x2035, 0x00c0, 0x17c1, 0x0c7e, 0x7004,
-	0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4, 0x0040,
-	0x180f, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17c1, 0x6824,
-	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
-	0x2009, 0x0011, 0x1078, 0x1824, 0x0040, 0x1822, 0x2009, 0x0001,
-	0x1078, 0x1824, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18bb, 0xa03e,
-	0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1846, 0xd0f4, 0x00c0, 0x1856,
-	0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1836, 0x189d, 0x185d,
-	0x185d, 0x189d, 0x189d, 0x1895, 0x189d, 0x185d, 0x189d, 0x1863,
-	0x1863, 0x189d, 0x189d, 0x189d, 0x188c, 0x1863, 0xc0fc, 0x6852,
-	0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040, 0x18a0,
-	0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18a0, 0xc0f4, 0x6852,
-	0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18a7, 0x6b08, 0x6a0c, 0x6d00,
-	0x6c04, 0x0078, 0x18a0, 0x7b0c, 0xd3bc, 0x0040, 0x1884, 0x7004,
-	0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1884,
-	0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff,
-	0x00c0, 0x187f, 0x6810, 0xa302, 0x0048, 0x187f, 0x6b10, 0x2011,
-	0x0000, 0x2468, 0x0078, 0x1886, 0x6b10, 0x6a14, 0x6d00, 0x6c04,
-	0x6f08, 0x6e0c, 0x0078, 0x18a0, 0x0d7f, 0x0d7e, 0x6834, 0xa084,
-	0x00ff, 0xa086, 0x001e, 0x00c0, 0x189d, 0x0d7f, 0x1078, 0x1fd1,
-	0x00c0, 0x1824, 0xa00e, 0x0078, 0x18bb, 0x0d7f, 0x1078, 0x1328,
-	0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000,
-	0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201,
-	0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14, 0xa203,
-	0x6816, 0x1078, 0x1fd1, 0x007c, 0x1078, 0x1328, 0x1078, 0x1c52,
-	0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000, 0x1078,
-	0x1ac6, 0x1078, 0x8a44, 0x0040, 0x18db, 0x6808, 0x8001, 0x680a,
-	0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
-	0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758, 0x0078, 0x1aad,
-	0x1078, 0x1328, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e, 0x2b68,
-	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
-	0x18be, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x18e0, 0x7000,
-	0x0079, 0x18fa, 0x1902, 0x1904, 0x1a06, 0x1a84, 0x1a9b, 0x1902,
-	0x1902, 0x1902, 0x1078, 0x1328, 0x8001, 0x7002, 0xa184, 0x0880,
-	0x00c0, 0x1919, 0x8aff, 0x0040, 0x199b, 0x2009, 0x0001, 0x1078,
-	0x1824, 0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078,
-	0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0, 0x1979,
-	0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1930, 0x7c20, 0x7d24,
-	0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1932,
-	0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500,
-	0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060, 0x6024,
-	0xd0f4, 0x00c0, 0x1945, 0x633a, 0x6236, 0x0c7f, 0x2400, 0x6910,
-	0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f, 0x027f,
-	0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x1fea, 0x2a00, 0x6826,
-	0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852, 0x6808,
-	0x8001, 0x680a, 0x00c0, 0x196e, 0x684c, 0xd0e4, 0x0040, 0x196e,
-	0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x7000, 0xa086,
-	0x0004, 0x0040, 0x1aad, 0x7003, 0x0000, 0x1078, 0x179f, 0x0078,
-	0x1aad, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x1980, 0x1078, 0xa20c,
-	0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4893,
-	0x0040, 0x198d, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff,
-	0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x0078, 0x1aad, 0x7004, 0x0c7e, 0x2060, 0x6024, 0x0c7f,
-	0xd0f4, 0x0040, 0x19a8, 0x6808, 0x8001, 0x680a, 0x0078, 0x1aad,
-	0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19c0, 0x7003,
-	0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19bc, 0x7004, 0x2060,
-	0x2009, 0x0048, 0x1078, 0x756c, 0x1078, 0x179f, 0x0078, 0x1aad,
-	0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816,
-	0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
-	0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
-	0x810b, 0x1078, 0x1b4d, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
-	0x0001, 0x7804, 0xd0fc, 0x0040, 0x19e1, 0x7803, 0x0002, 0x7803,
-	0x0004, 0x780f, 0x0076, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009,
-	0x0048, 0x1078, 0x756c, 0x1078, 0x1b81, 0x0040, 0x19bc, 0x7908,
-	0xd1ec, 0x00c0, 0x19ff, 0x2009, 0x0009, 0x0078, 0x1a01, 0x2009,
-	0x0019, 0x7902, 0x7003, 0x0003, 0x0078, 0x1aad, 0x8001, 0x7002,
-	0xd194, 0x0040, 0x1a18, 0x7804, 0xd0fc, 0x00c0, 0x18ea, 0x8aff,
-	0x0040, 0x1aad, 0x2009, 0x0001, 0x1078, 0x1824, 0x0078, 0x1aad,
-	0xa184, 0x0880, 0x00c0, 0x1a25, 0x8aff, 0x0040, 0x1aad, 0x2009,
-	0x0001, 0x1078, 0x1824, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003,
-	0x0000, 0xd1bc, 0x00c0, 0x1a65, 0x027e, 0x037e, 0x7808, 0xd0ec,
-	0x00c0, 0x1a38, 0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a3a,
-	0x1078, 0x1b9f, 0x6b28, 0x6a2c, 0x1078, 0x1fea, 0x0d7e, 0x0f7e,
-	0x2d78, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a55, 0x6808,
-	0x2008, 0xa31a, 0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c,
-	0x7814, 0xa101, 0x7816, 0x0078, 0x1a61, 0x6810, 0x2008, 0xa31a,
-	0x6814, 0xa213, 0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101,
-	0x7816, 0x0f7f, 0x0d7f, 0x0078, 0x1934, 0x057e, 0x7d0c, 0x1078,
-	0xa20c, 0x057f, 0x1078, 0x1ac6, 0x0f7e, 0x7004, 0x2078, 0x1078,
-	0x4893, 0x0040, 0x1a76, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b,
-	0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912,
-	0x6980, 0x6916, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000,
-	0x7004, 0xa00d, 0x0040, 0x1a97, 0x6808, 0x8001, 0x680a, 0x00c0,
-	0x1a97, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x756c, 0x1078,
-	0x179f, 0x0078, 0x1aad, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
-	0x2060, 0x6010, 0xa005, 0x0040, 0x1a97, 0x2068, 0x6808, 0x8000,
-	0x680a, 0x6c28, 0x6b2c, 0x1078, 0x17be, 0x017f, 0x007f, 0x127f,
-	0x007c, 0x127e, 0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0,
-	0x1ac4, 0x700c, 0x7110, 0xa106, 0x0040, 0x1ac4, 0x20e1, 0x9028,
-	0x700f, 0xa5e7, 0x7013, 0xa5e7, 0x127f, 0x007c, 0x0c7e, 0x1078,
-	0x1af7, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1aed,
-	0x2104, 0xa005, 0x0040, 0x1ada, 0x2060, 0x6010, 0x2060, 0x6008,
-	0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xa602, 0x0048, 0x1ae2,
-	0x2009, 0xa5e7, 0x7112, 0x700c, 0xa106, 0x00c0, 0x1acb, 0x2001,
-	0x0138, 0x2003, 0x0008, 0x0078, 0x1acb, 0x2001, 0x015d, 0x200c,
-	0x810a, 0x2102, 0x2001, 0x0138, 0x2202, 0x0c7f, 0x007c, 0x2001,
-	0x0138, 0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141,
-	0x201c, 0xd3dc, 0x00c0, 0x1b14, 0x2001, 0x0109, 0x201c, 0xa39c,
-	0x0048, 0x00c0, 0x1b14, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0,
-	0x1b14, 0x8421, 0x00c0, 0x1afe, 0x007c, 0x2011, 0x0201, 0x2009,
-	0x003c, 0x2204, 0xa005, 0x00c0, 0x1b21, 0x8109, 0x00c0, 0x1b19,
-	0x007c, 0x007c, 0x1078, 0x1b15, 0x0040, 0x1b4a, 0x7908, 0xd1ec,
-	0x00c0, 0x1b3a, 0x1078, 0x1b81, 0x0040, 0x1b3a, 0x7803, 0x0009,
-	0x7904, 0xd1fc, 0x0040, 0x1b30, 0x7803, 0x0006, 0x1078, 0x1b15,
-	0x0040, 0x1b4a, 0x780c, 0xd0a4, 0x00c0, 0x1b4a, 0x7007, 0x0000,
-	0x1078, 0x1b81, 0x0040, 0x1b4c, 0x7803, 0x0019, 0x7003, 0x0003,
-	0x0078, 0x1b4c, 0x1078, 0x1ac6, 0x007c, 0x0e7e, 0x2071, 0x0200,
-	0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1af7, 0x2019, 0x5000,
-	0x8319, 0x0040, 0x1b6b, 0x2001, 0xa602, 0x2004, 0xa086, 0x0000,
-	0x0040, 0x1b6b, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b58, 0x1078,
-	0x1e5d, 0x0078, 0x1b56, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028,
-	0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100,
-	0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x0e7f,
-	0x007c, 0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x1b8c,
-	0xa085, 0x0001, 0x0078, 0x1b9e, 0x2001, 0x020a, 0x81ff, 0x0040,
-	0x1b97, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1,
-	0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007c, 0x7c20,
-	0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c24,
-	0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c24, 0x0d7e,
-	0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c22, 0x6824, 0xd0d4,
-	0x00c0, 0x1c22, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0040, 0x1bec,
-	0x8108, 0x2104, 0x6b2c, 0xa306, 0x00c0, 0x1c22, 0x8108, 0x2104,
-	0x6a28, 0xa206, 0x00c0, 0x1c22, 0x6850, 0xc0fc, 0xc0f5, 0x6852,
-	0x686c, 0x7822, 0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836,
-	0x6818, 0x2060, 0x6034, 0xd09c, 0x0040, 0x1be7, 0x6830, 0x2004,
-	0xac68, 0x6808, 0x783a, 0x680c, 0x783e, 0x0078, 0x1c20, 0xa006,
-	0x783a, 0x783e, 0x0078, 0x1c20, 0x8108, 0x2104, 0xa005, 0x00c0,
-	0x1c22, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c22, 0x6850, 0xc0f5,
-	0x6852, 0x6830, 0x2004, 0x6918, 0xa160, 0xa180, 0x000d, 0x2004,
-	0xd09c, 0x00c0, 0x1c12, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826,
-	0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e,
-	0x0078, 0x1c20, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872,
-	0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e,
-	0x7803, 0x0011, 0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e,
-	0x027e, 0x2071, 0xa5e1, 0x2079, 0x0030, 0x2011, 0x0050, 0x7000,
-	0xa086, 0x0000, 0x0040, 0x1c4d, 0x8211, 0x0040, 0x1c4b, 0x2001,
-	0x0005, 0x2004, 0xd08c, 0x0040, 0x1c34, 0x7904, 0xa18c, 0x0780,
-	0x017e, 0x1078, 0x18e2, 0x017f, 0x81ff, 0x00c0, 0x1c4b, 0x2011,
-	0x0050, 0x0078, 0x1c2f, 0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f,
-	0x0f7f, 0x007c, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
-	0x0040, 0x1ca3, 0x8109, 0x00c0, 0x1c56, 0x2009, 0x0100, 0x210c,
-	0xa18a, 0x0003, 0x1048, 0x1328, 0x1078, 0x1f75, 0x0e7e, 0x0f7e,
-	0x2071, 0xa5d0, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0040,
-	0x1c9b, 0x7800, 0x007e, 0x7820, 0x007e, 0x7830, 0x007e, 0x7834,
-	0x007e, 0x7838, 0x007e, 0x783c, 0x007e, 0x7803, 0x0004, 0x7823,
-	0x0000, 0x0005, 0x0005, 0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0,
-	0x1328, 0x2079, 0x0010, 0x007f, 0x783e, 0x007f, 0x783a, 0x007f,
-	0x7836, 0x007f, 0x7832, 0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f,
-	0x0e7f, 0x0078, 0x1ca1, 0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0,
-	0x1328, 0x1078, 0x61d3, 0x007c, 0x0e7e, 0x2071, 0xa602, 0x7003,
-	0x0000, 0x0e7f, 0x007c, 0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c,
-	0xd1dc, 0x00c0, 0x1d26, 0x6934, 0xa184, 0x0007, 0x0079, 0x1cb8,
-	0x1cc0, 0x1d11, 0x1cc0, 0x1cc0, 0x1cc0, 0x1cf6, 0x1cd3, 0x1cc2,
-	0x1078, 0x1328, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
-	0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
-	0x6958, 0x0078, 0x1d19, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
-	0x00c0, 0x1cc0, 0x684c, 0xd0b4, 0x0040, 0x1e34, 0x6860, 0x682e,
-	0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x2015, 0x2004, 0x6832, 0x6958, 0x0078, 0x1d22, 0xa18c, 0x00ff,
-	0xa186, 0x0015, 0x00c0, 0x1d26, 0x684c, 0xd0b4, 0x0040, 0x1e34,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x2015, 0x2004, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0078,
-	0x1d22, 0x684c, 0xd0b4, 0x0040, 0x18bc, 0x6958, 0xa006, 0x682e,
-	0x682a, 0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2015,
-	0x2004, 0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c,
-	0x0f7e, 0x2079, 0x0020, 0x7804, 0xd0fc, 0x10c0, 0x1e5d, 0x0e7e,
-	0x0d7e, 0x2071, 0xa602, 0x7000, 0xa005, 0x00c0, 0x1dab, 0x0c7e,
-	0x7206, 0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004,
-	0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1,
-	0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6,
-	0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
-	0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0x2001, 0x04fd, 0x2004,
-	0xa086, 0x0007, 0x0040, 0x1d6d, 0xa184, 0x0007, 0x0040, 0x1d6d,
-	0x017e, 0x2009, 0x0008, 0xa102, 0x017f, 0xa108, 0x791a, 0x7116,
-	0x701e, 0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e,
-	0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x00c0, 0x1d84, 0x6928,
-	0x6810, 0xa106, 0x0040, 0x1d91, 0x037e, 0x047e, 0x6b14, 0x6c10,
-	0x1078, 0x2035, 0x047f, 0x037f, 0x0040, 0x1d91, 0x0c7f, 0x0078,
-	0x1dab, 0x8aff, 0x00c0, 0x1d99, 0x0c7f, 0xa085, 0x0001, 0x0078,
-	0x1dab, 0x127e, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009, 0x0001,
-	0x1078, 0x1daf, 0x0040, 0x1da8, 0x2009, 0x0001, 0x1078, 0x1daf,
-	0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e,
-	0x067e, 0x057e, 0x047e, 0x037e, 0x027e, 0x8aff, 0x0040, 0x1e2d,
-	0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0048, 0x1e2c,
-	0xa705, 0x0040, 0x1e2c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
-	0x1ddf, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1dcf, 0x1e0e,
-	0x1def, 0x1def, 0x1e0e, 0x1e0e, 0x1e06, 0x1e0e, 0x1def, 0x1e0e,
-	0x1df5, 0x1df5, 0x1e0e, 0x1e0e, 0x1e0e, 0x1dfd, 0x1df5, 0xc0fc,
-	0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e12,
-	0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x6b08,
-	0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1e11, 0x6b10, 0x6a14, 0x6d00,
-	0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1e11, 0x0d7f, 0x0d7e, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1e0e, 0x0d7f, 0x1078,
-	0x1fd1, 0x00c0, 0x1db5, 0xa00e, 0x0078, 0x1e2d, 0x0d7f, 0x1078,
-	0x1328, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e,
-	0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c,
-	0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012,
-	0x1078, 0x1fd1, 0x0078, 0x1e2d, 0xa006, 0x027f, 0x037f, 0x047f,
-	0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x1328, 0x027e, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44,
-	0x0040, 0x1e4d, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8758,
-	0x20e1, 0x9040, 0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc,
-	0x1078, 0x61d3, 0x027f, 0x0078, 0x1f29, 0x127e, 0x2091, 0x2200,
-	0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020,
-	0x2071, 0xa602, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
-	0xa184, 0x0700, 0x00c0, 0x1e36, 0x7000, 0x0079, 0x1e77, 0x1f29,
-	0x1e7b, 0x1ef6, 0x1f27, 0x8001, 0x7002, 0xd19c, 0x00c0, 0x1e8f,
-	0x8aff, 0x0040, 0x1eae, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0040,
-	0x1f29, 0x2009, 0x0001, 0x1078, 0x1daf, 0x0078, 0x1f29, 0x7803,
-	0x0004, 0xd194, 0x0040, 0x1e9f, 0x6850, 0xc0fc, 0x6852, 0x8aff,
-	0x00c0, 0x1ea4, 0x684c, 0xc0f5, 0x684e, 0x0078, 0x1ea4, 0x1078,
-	0x1fea, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a,
-	0x2800, 0x6832, 0x7003, 0x0000, 0x0078, 0x1f29, 0x711c, 0x81ff,
-	0x0040, 0x1ec4, 0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001,
-	0x7000, 0x8000, 0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081,
-	0x0000, 0x7012, 0x0078, 0x1f29, 0x0f7e, 0x027e, 0x781c, 0x007e,
-	0x7818, 0x007e, 0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085,
-	0x0012, 0x7816, 0x037e, 0x2019, 0x1000, 0x8319, 0x1040, 0x1328,
-	0x7820, 0xd0bc, 0x00c0, 0x1ed5, 0x037f, 0x79c8, 0x007f, 0xa102,
-	0x017f, 0x007e, 0x017e, 0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f,
-	0x78ca, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
-	0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1f29, 0x8001, 0x7002,
-	0xd194, 0x0040, 0x1f0b, 0x7804, 0xd0fc, 0x00c0, 0x1e6d, 0xd19c,
-	0x00c0, 0x1f25, 0x8aff, 0x0040, 0x1f29, 0x2009, 0x0001, 0x1078,
-	0x1daf, 0x0078, 0x1f29, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
-	0x1fea, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f1e,
-	0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1f22, 0x6810, 0xa31a,
-	0x6814, 0xa213, 0x0d7f, 0x0078, 0x1e9f, 0x0078, 0x1e9f, 0x1078,
-	0x1328, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
-	0x007c, 0x0f7e, 0x0e7e, 0x2071, 0xa602, 0x7000, 0xa086, 0x0000,
-	0x0040, 0x1f72, 0x2079, 0x0020, 0x017e, 0x2009, 0x0207, 0x210c,
-	0xd194, 0x0040, 0x1f4f, 0x2009, 0x020c, 0x210c, 0xa184, 0x0003,
-	0x0040, 0x1f4f, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102, 0x2009,
-	0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x00c0, 0x1f5a,
-	0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0040, 0x1f3d, 0x1078, 0x1e5d,
-	0x7000, 0xa086, 0x0000, 0x00c0, 0x1f3d, 0x017f, 0x7803, 0x0004,
-	0x7804, 0xd0ac, 0x00c0, 0x1f68, 0x20e1, 0x9040, 0x7803, 0x0002,
-	0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e,
-	0x0e7e, 0x0f7e, 0x2071, 0xa602, 0x2079, 0x0020, 0x7000, 0xa086,
-	0x0000, 0x0040, 0x1fae, 0x7004, 0x2060, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x1f98, 0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c,
-	0xa206, 0x00c0, 0x1f98, 0x6808, 0x7a18, 0xa206, 0x0040, 0x1fb4,
-	0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x1078, 0x8758, 0x20e1, 0x9040,
-	0x1078, 0x719a, 0x2011, 0x0000, 0x1078, 0x6efc, 0x0f7f, 0x0e7f,
-	0x0d7f, 0x0c7f, 0x027f, 0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0,
-	0x1f98, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x1078, 0x1cab, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x2069, 0xa5ab, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078,
-	0x1fae, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1fe5, 0x6004, 0xa005,
-	0x0040, 0x1fe7, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080,
-	0x2015, 0x2044, 0x88ff, 0x1040, 0x1328, 0x8a51, 0x007c, 0x2051,
-	0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x2004,
-	0x2c00, 0xad06, 0x0040, 0x1ff9, 0x6000, 0xa005, 0x00c0, 0x1ff9,
-	0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x2025,
-	0x2044, 0x88ff, 0x1040, 0x1328, 0x007c, 0x0000, 0x0011, 0x0015,
-	0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015,
-	0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x200a, 0x2006,
-	0x0000, 0x0000, 0x2014, 0x0000, 0x200a, 0x0000, 0x2011, 0x200e,
-	0x0000, 0x0000, 0x0000, 0x2014, 0x2011, 0x0000, 0x200c, 0x200c,
-	0x0000, 0x0000, 0x2014, 0x0000, 0x200c, 0x0000, 0x2012, 0x2012,
-	0x0000, 0x0000, 0x0000, 0x2014, 0x2012, 0x0a7e, 0x097e, 0x087e,
-	0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0040, 0x20d8, 0x2d60, 0x6034,
-	0xa0cc, 0x000f, 0xa9c0, 0x2015, 0xa986, 0x0007, 0x0040, 0x2050,
-	0xa986, 0x000e, 0x0040, 0x2050, 0xa986, 0x000f, 0x00c0, 0x2054,
-	0x605c, 0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x2062,
-	0x0050, 0x205c, 0x0078, 0x20d8, 0x6004, 0xa065, 0x0040, 0x20d8,
-	0x0078, 0x203f, 0x2804, 0xa005, 0x0040, 0x2080, 0xac68, 0xd99c,
-	0x00c0, 0x2070, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x2074,
-	0x6810, 0xa422, 0x6814, 0xa31b, 0x0048, 0x209f, 0x2300, 0xa405,
-	0x0040, 0x2086, 0x8a51, 0x0040, 0x20d8, 0x8840, 0x0078, 0x2062,
-	0x6004, 0xa065, 0x0040, 0x20d8, 0x0078, 0x203f, 0x8a51, 0x0040,
-	0x20d8, 0x8840, 0x2804, 0xa005, 0x00c0, 0x2099, 0x6004, 0xa065,
-	0x0040, 0x20d8, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2015, 0x2804,
-	0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x20cc, 0x8422,
-	0x8420, 0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72,
-	0x0d7f, 0xd99c, 0x00c0, 0x20ba, 0x6908, 0x2400, 0xa122, 0x690c,
-	0x2300, 0xa11b, 0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319,
-	0x0078, 0x20c6, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
-	0x1048, 0x1328, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
-	0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
-	0x2a00, 0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x20dd,
-	0x087f, 0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005,
-	0x2004, 0xa084, 0x0007, 0x0079, 0x20e5, 0x20ed, 0x20ee, 0x20f1,
-	0x20f4, 0x20f9, 0x20fc, 0x2101, 0x2106, 0x007c, 0x1078, 0x1e5d,
-	0x007c, 0x1078, 0x18e2, 0x007c, 0x1078, 0x18e2, 0x1078, 0x1e5d,
-	0x007c, 0x1078, 0x14b0, 0x007c, 0x1078, 0x1e5d, 0x1078, 0x14b0,
-	0x007c, 0x1078, 0x18e2, 0x1078, 0x14b0, 0x007c, 0x1078, 0x18e2,
-	0x1078, 0x1e5d, 0x1078, 0x14b0, 0x007c, 0x127e, 0x2091, 0x2300,
-	0x2079, 0x0200, 0x2071, 0xa880, 0x2069, 0xa300, 0x2009, 0x0004,
-	0x7912, 0x7817, 0x0004, 0x1078, 0x24b5, 0x781b, 0x0002, 0x20e1,
-	0x8700, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084,
-	0x0007, 0x0079, 0x212b, 0x214f, 0x2133, 0x2137, 0x213b, 0x2141,
-	0x2145, 0x2149, 0x214d, 0x1078, 0x5372, 0x0078, 0x214f, 0x1078,
-	0x53b3, 0x0078, 0x214f, 0x1078, 0x5372, 0x1078, 0x53b3, 0x0078,
-	0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x0078,
-	0x214f, 0x1078, 0x2151, 0x0078, 0x214f, 0x1078, 0x2151, 0x127f,
-	0x007c, 0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040,
-	0x215d, 0x20e1, 0x9040, 0x0078, 0x2186, 0xa184, 0x0030, 0x0040,
-	0x216e, 0x6a00, 0xa286, 0x0003, 0x00c0, 0x2168, 0x0078, 0x216a,
-	0x1078, 0x4171, 0x20e1, 0x9010, 0x0078, 0x2186, 0xa184, 0x00c0,
-	0x0040, 0x2180, 0x0e7e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa5e1,
-	0x1078, 0x1ac6, 0x057f, 0x047f, 0x037f, 0x0e7f, 0x0078, 0x2186,
-	0xa184, 0x0300, 0x0040, 0x2186, 0x20e1, 0x9020, 0x7932, 0x027f,
-	0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0xa300,
-	0x7128, 0x2001, 0xa58f, 0x2102, 0x2001, 0xa597, 0x2102, 0xa182,
-	0x0211, 0x00c8, 0x219f, 0x2009, 0x0008, 0x0078, 0x21c9, 0xa182,
-	0x0259, 0x00c8, 0x21a7, 0x2009, 0x0007, 0x0078, 0x21c9, 0xa182,
-	0x02c1, 0x00c8, 0x21af, 0x2009, 0x0006, 0x0078, 0x21c9, 0xa182,
-	0x0349, 0x00c8, 0x21b7, 0x2009, 0x0005, 0x0078, 0x21c9, 0xa182,
-	0x0421, 0x00c8, 0x21bf, 0x2009, 0x0004, 0x0078, 0x21c9, 0xa182,
-	0x0581, 0x00c8, 0x21c7, 0x2009, 0x0003, 0x0078, 0x21c9, 0x2009,
-	0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x1078, 0x24b5,
-	0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
-	0x0100, 0x2071, 0xa300, 0x6024, 0x6026, 0x6053, 0x0030, 0x6033,
-	0x00ef, 0x60e7, 0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b,
-	0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007,
-	0x0eaf, 0x600f, 0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001,
-	0xa32f, 0x2003, 0x0000, 0x2001, 0xa32e, 0x2003, 0x0001, 0x007c,
-	0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184,
-	0x002c, 0x00c0, 0x220f, 0xa184, 0x0007, 0x0079, 0x2215, 0xa195,
-	0x0004, 0xa284, 0x0007, 0x0079, 0x2215, 0x2241, 0x221d, 0x2221,
-	0x2225, 0x222b, 0x222f, 0x2235, 0x223b, 0x1078, 0x5ad2, 0x0078,
-	0x2241, 0x1078, 0x5bc1, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
-	0x5ad2, 0x0078, 0x2241, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078,
-	0x5ad2, 0x1078, 0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078,
-	0x2246, 0x0078, 0x2241, 0x1078, 0x5bc1, 0x1078, 0x5ad2, 0x1078,
-	0x2246, 0x027f, 0x017f, 0x007f, 0x127f, 0x007c, 0x6124, 0xd1ac,
-	0x0040, 0x2342, 0x017e, 0x047e, 0x0c7e, 0x644c, 0xa486, 0xf0f0,
-	0x00c0, 0x2259, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x74c2, 0xa48c, 0xff00, 0x7034, 0xd084, 0x0040, 0x2271,
-	0xa186, 0xf800, 0x00c0, 0x2271, 0x7038, 0xd084, 0x00c0, 0x2271,
-	0xc085, 0x703a, 0x037e, 0x2418, 0x2011, 0x8016, 0x1078, 0x3579,
-	0x037f, 0xa196, 0xff00, 0x0040, 0x22b3, 0x6030, 0xa084, 0x00ff,
-	0x810f, 0xa116, 0x0040, 0x22b3, 0x7130, 0xd184, 0x00c0, 0x22b3,
-	0x2011, 0xa352, 0x2214, 0xd2ec, 0x0040, 0x228e, 0xc18d, 0x7132,
-	0x2011, 0xa352, 0x2214, 0xd2ac, 0x00c0, 0x22b3, 0x6240, 0xa294,
-	0x0010, 0x0040, 0x229a, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00,
-	0x0040, 0x22b3, 0x7030, 0xd08c, 0x0040, 0x2305, 0x7034, 0xd08c,
-	0x00c0, 0x22aa, 0x2001, 0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305,
-	0xc1ad, 0x2102, 0x037e, 0x73c0, 0x2011, 0x8013, 0x1078, 0x3579,
-	0x037f, 0x0078, 0x2305, 0x7034, 0xd08c, 0x00c0, 0x22bf, 0x2001,
-	0xa30c, 0x200c, 0xd1ac, 0x00c0, 0x2305, 0xc1ad, 0x2102, 0x037e,
-	0x73c0, 0x2011, 0x8013, 0x1078, 0x3579, 0x037f, 0x7130, 0xc185,
-	0x7132, 0x2011, 0xa352, 0x220c, 0xd1a4, 0x0040, 0x22e9, 0x017e,
-	0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x5a6d, 0x2019, 0x000e,
-	0x1078, 0x9e3b, 0xa484, 0x00ff, 0xa080, 0x293f, 0x200c, 0xa18c,
-	0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x1078, 0x9ec0,
-	0x017f, 0xd1ac, 0x00c0, 0x22f6, 0x017e, 0x2009, 0x0000, 0x2019,
-	0x0004, 0x1078, 0x27e2, 0x017f, 0x0078, 0x2305, 0x157e, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x1078, 0x4501, 0x00c0, 0x2301, 0x1078,
-	0x4235, 0x8108, 0x00f0, 0x22fb, 0x157f, 0x0c7f, 0x047f, 0x0f7e,
-	0x2079, 0xa5be, 0x783c, 0xa086, 0x0000, 0x0040, 0x2317, 0x6027,
-	0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f,
-	0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011, 0x0002, 0x1078, 0x6efc,
-	0x1078, 0x6dda, 0x1078, 0x595a, 0x037e, 0x2019, 0x0000, 0x1078,
-	0x6e6c, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001, 0xa300, 0x2014,
-	0xa296, 0x0004, 0x00c0, 0x233a, 0xd19c, 0x00c0, 0x233a, 0x6228,
-	0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa321, 0x2003, 0x0000,
-	0x6027, 0x0020, 0xd194, 0x0040, 0x2426, 0x0f7e, 0x2079, 0xa5be,
-	0x783c, 0xa086, 0x0001, 0x00c0, 0x2366, 0x017e, 0x6027, 0x0004,
-	0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000,
-	0x2079, 0xa5ab, 0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x6109,
-	0x1078, 0x61d3, 0x017f, 0x0f7f, 0x0078, 0x2426, 0x0f7f, 0x017e,
-	0x3900, 0xa082, 0xa6cd, 0x00c8, 0x2371, 0x017e, 0x1078, 0x728a,
-	0x017f, 0x6220, 0xd2b4, 0x0040, 0x23dc, 0x1078, 0x595a, 0x1078,
-	0x6c41, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa5b4, 0x2304, 0xa07d,
-	0x0040, 0x23b2, 0x7804, 0xa086, 0x0032, 0x00c0, 0x23b2, 0x0d7e,
-	0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
-	0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x00c0,
-	0x2396, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e,
-	0x628a, 0x1078, 0x6010, 0x1078, 0x6109, 0x7810, 0x2070, 0x7037,
-	0x0103, 0x2f60, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0d7f, 0x0f7f,
-	0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084,
-	0x4000, 0x0040, 0x23bf, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f,
-	0x0c7e, 0x2061, 0xa5ab, 0x6028, 0xa09a, 0x00c8, 0x00c8, 0x23cf,
-	0x8000, 0x602a, 0x0c7f, 0x1078, 0x6c33, 0x0078, 0x2425, 0x2019,
-	0xa5b4, 0x2304, 0xa065, 0x0040, 0x23d9, 0x2009, 0x0027, 0x1078,
-	0x756c, 0x0c7f, 0x0078, 0x2425, 0xd2bc, 0x0040, 0x2425, 0x1078,
-	0x5967, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140,
-	0x6804, 0xa084, 0x4000, 0x0040, 0x23f1, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa5ab, 0x6044, 0xa09a, 0x00c8,
-	0x00c8, 0x2414, 0x8000, 0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040,
-	0x2425, 0x2009, 0x07d0, 0x1078, 0x595f, 0xa080, 0x0007, 0x2004,
-	0xa086, 0x0006, 0x00c0, 0x2410, 0x6017, 0x0012, 0x0078, 0x2425,
-	0x6017, 0x0016, 0x0078, 0x2425, 0x037e, 0x2019, 0x0001, 0x1078,
-	0x6e6c, 0x037f, 0x2019, 0xa5ba, 0x2304, 0xa065, 0x0040, 0x2424,
-	0x2009, 0x004f, 0x1078, 0x756c, 0x0c7f, 0x017f, 0xd19c, 0x0040,
-	0x247c, 0x7034, 0xd0ac, 0x00c0, 0x2457, 0x017e, 0x157e, 0x6027,
-	0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0, 0x2435, 0x602f,
-	0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0320, 0x00e0,
-	0x243f, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0, 0x244e, 0x157f,
-	0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x247c, 0x1078, 0x250d,
-	0x00f0, 0x243f, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x017e,
-	0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078, 0x6ef2, 0x2011,
-	0x0002, 0x1078, 0x6efc, 0x1078, 0x6dda, 0x1078, 0x595a, 0x037e,
-	0x2019, 0x0000, 0x1078, 0x6e6c, 0x037f, 0x60e3, 0x0000, 0x1078,
-	0xa22a, 0x1078, 0xa248, 0x2001, 0xa300, 0x2003, 0x0004, 0x6027,
-	0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c,
-	0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0xa300, 0x71b8, 0x70ba, 0xa116, 0x0040, 0x24ae, 0x81ff,
-	0x0040, 0x2498, 0x2011, 0x8011, 0x1078, 0x3579, 0x0078, 0x24ae,
-	0x2011, 0x8012, 0x1078, 0x3579, 0x2001, 0xa371, 0x2004, 0xd0fc,
-	0x00c0, 0x24ae, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028,
-	0x2009, 0x0000, 0x1078, 0x27e2, 0x0c7f, 0x037f, 0x127f, 0x0f7f,
-	0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e,
-	0x027e, 0x2061, 0x0100, 0xa190, 0x24d1, 0x2204, 0x60f2, 0x2011,
-	0x24de, 0x6000, 0xa082, 0x0003, 0x00c8, 0x24ca, 0x2001, 0x00ff,
-	0x0078, 0x24cb, 0x2204, 0x60ee, 0x027f, 0x007f, 0x0f7f, 0x0c7f,
-	0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0,
-	0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
-	0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094,
-	0xff00, 0x00c0, 0x24ee, 0x81ff, 0x0040, 0x24f2, 0x1078, 0x5623,
-	0x0078, 0x24f9, 0xa080, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
-	0xa006, 0x007c, 0xa080, 0x293f, 0x200c, 0xa18c, 0x00ff, 0x007c,
-	0x0c7e, 0x2061, 0xa300, 0x6030, 0x0040, 0x2509, 0xc09d, 0x0078,
-	0x250a, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e, 0x157e, 0x0f7e,
-	0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x00c0, 0x251a,
-	0x00f0, 0x2514, 0x0f7f, 0x157f, 0x007f, 0x007c, 0x0c7e, 0x007e,
-	0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e, 0x60e4, 0x007e,
-	0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e, 0x60ec, 0x007e,
-	0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e, 0x60e0, 0x007e,
-	0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2, 0x007f, 0x602a,
-	0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee, 0x007f, 0x60f2,
-	0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6, 0x007f, 0x604a,
-	0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x257d, 0x2581, 0x2585,
-	0x258b, 0x2591, 0x2597, 0x259d, 0x25a5, 0x25ad, 0x25b3, 0x25b9,
-	0x25c1, 0x25c9, 0x25d1, 0x25d9, 0x25e3, 0x25ed, 0x25ed, 0x25ed,
-	0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed,
-	0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x25ed, 0x107e, 0x007e, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
-	0x2200, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e,
-	0x007e, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
-	0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
-	0x2200, 0x1078, 0x20de, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078,
-	0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2123, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x2123, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x20de, 0x1078, 0x2123, 0x0078,
-	0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078, 0x20de, 0x1078,
-	0x2123, 0x0078, 0x2606, 0x107e, 0x007e, 0x1078, 0x2200, 0x1078,
-	0x20de, 0x1078, 0x2123, 0x0078, 0x2606, 0x0005, 0x0078, 0x25ed,
-	0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x25f6, 0x2606, 0x2583,
-	0x2587, 0x258d, 0x2593, 0x2599, 0x259f, 0x25a7, 0x25af, 0x25b5,
-	0x25bb, 0x25c3, 0x25cb, 0x25d3, 0x25db, 0x25e5, 0x0008, 0x25f0,
-	0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e, 0x027e, 0x047e,
-	0x2021, 0x0000, 0x1078, 0x4897, 0x00c0, 0x2705, 0x70c8, 0xd09c,
-	0x0040, 0x2624, 0xd084, 0x00c0, 0x2624, 0xd0bc, 0x00c0, 0x2705,
-	0x1078, 0x2709, 0x0078, 0x2705, 0xd094, 0x0040, 0x262b, 0x7093,
-	0xffff, 0x0078, 0x2705, 0x2001, 0x010c, 0x203c, 0x7280, 0xd284,
-	0x0040, 0x2694, 0xd28c, 0x00c0, 0x2694, 0x037e, 0x7390, 0xa38e,
-	0xffff, 0x0040, 0x263e, 0x83ff, 0x00c0, 0x2640, 0x2019, 0x0001,
-	0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xa38c, 0x0001, 0x0040, 0x264d,
-	0xa084, 0xff00, 0x8007, 0x0078, 0x264f, 0xa084, 0x00ff, 0xa70e,
-	0x0040, 0x2689, 0xa08e, 0x0000, 0x0040, 0x2689, 0xa08e, 0x00ff,
-	0x00c0, 0x2666, 0x7230, 0xd284, 0x00c0, 0x268f, 0x7280, 0xc28d,
-	0x7282, 0x7093, 0xffff, 0x037f, 0x0078, 0x2694, 0x2009, 0x0000,
-	0x1078, 0x24e3, 0x1078, 0x4499, 0x00c0, 0x268c, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x00c0, 0x2683, 0x7030, 0xd08c, 0x0040,
-	0x267d, 0x6000, 0xd0bc, 0x0040, 0x2683, 0x1078, 0x271f, 0x0040,
-	0x268c, 0x0078, 0x2689, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
-	0x268c, 0x8318, 0x0078, 0x2640, 0x7392, 0x0078, 0x2691, 0x7093,
-	0xffff, 0x037f, 0x0078, 0x2705, 0xa780, 0x293f, 0x203c, 0xa7bc,
-	0xff00, 0x873f, 0x2041, 0x007e, 0x7090, 0xa096, 0xffff, 0x00c0,
-	0x26a6, 0x2009, 0x0000, 0x28a8, 0x0078, 0x26b2, 0xa812, 0x0048,
-	0x26ae, 0x2008, 0xa802, 0x20a8, 0x0078, 0x26b2, 0x7093, 0xffff,
-	0x0078, 0x2705, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040, 0x26f9,
-	0xc484, 0x1078, 0x4501, 0x0040, 0x26c3, 0x1078, 0x4499, 0x00c0,
-	0x2702, 0x0078, 0x26c4, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x00c0, 0x26d3, 0x7030, 0xd08c, 0x0040, 0x26f1, 0x6000,
-	0xd0bc, 0x00c0, 0x26f1, 0x7280, 0xd28c, 0x0040, 0x26e9, 0x6004,
-	0xa084, 0x00ff, 0xa082, 0x0006, 0x0048, 0x26f9, 0xd484, 0x00c0,
-	0x26e5, 0x1078, 0x44bc, 0x0078, 0x26e7, 0x1078, 0x2921, 0x0078,
-	0x26f9, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040, 0x2702, 0x0078,
-	0x26f9, 0x1078, 0x28ec, 0x0040, 0x26f9, 0x1078, 0x271f, 0x0040,
-	0x2702, 0x017f, 0x8108, 0x157f, 0x00f0, 0x26b2, 0x7093, 0xffff,
-	0x0078, 0x2705, 0x017f, 0x157f, 0x7192, 0x047f, 0x027f, 0x0c7f,
-	0x007c, 0x0c7e, 0x017e, 0x7093, 0x0000, 0x2009, 0x007e, 0x1078,
-	0x4499, 0x00c0, 0x271c, 0x1078, 0x2857, 0x1078, 0x274c, 0x0040,
-	0x271c, 0x70c8, 0xc0bd, 0x70ca, 0x017f, 0x0c7f, 0x007c, 0x017e,
-	0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa356, 0x2004, 0xa084,
-	0x00ff, 0x6842, 0x1078, 0x74d7, 0x0040, 0x2747, 0x2d00, 0x601a,
-	0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0000,
-	0x1078, 0x443f, 0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e,
-	0x127f, 0x2009, 0x0004, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f,
-	0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
-	0x2c68, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078,
-	0x74d7, 0x0040, 0x2785, 0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802,
-	0x68a0, 0xa086, 0x007e, 0x0040, 0x276e, 0x6804, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x00c0, 0x276e, 0x1078, 0x2813, 0x601f, 0x0001,
-	0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
-	0x127e, 0x2091, 0x8000, 0x708c, 0x8000, 0x708e, 0x127f, 0x2009,
-	0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
-	0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009, 0x0080, 0x1078, 0x4499,
-	0x00c0, 0x2798, 0x1078, 0x279b, 0x0040, 0x2798, 0x70cf, 0xffff,
-	0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68,
-	0x1078, 0x74d7, 0x0040, 0x27bd, 0x2d00, 0x601a, 0x601f, 0x0001,
-	0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f,
-	0x127e, 0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x127f, 0x2009,
-	0x0002, 0x1078, 0x756c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f,
-	0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009,
-	0x007f, 0x1078, 0x4499, 0x00c0, 0x27de, 0x2c68, 0x1078, 0x74d7,
-	0x0040, 0x27de, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
-	0x2009, 0x0022, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0d7f,
-	0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078,
-	0x5d60, 0x1078, 0x5d02, 0x1078, 0x7ddf, 0x2130, 0x81ff, 0x0040,
-	0x27f7, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0078, 0x27fb, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0, 0x2804,
-	0x1078, 0x471b, 0x1078, 0x4235, 0x017f, 0x8108, 0x00f0, 0x27fb,
-	0x86ff, 0x00c0, 0x280d, 0x1078, 0x119b, 0x027f, 0x037f, 0x067f,
-	0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e,
-	0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53,
-	0x077e, 0x2039, 0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38,
-	0x077f, 0x017f, 0x2e60, 0x1078, 0x471b, 0x6210, 0x6314, 0x1078,
-	0x4235, 0x6212, 0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
-	0x007c, 0x0e7e, 0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc,
-	0x00c0, 0x284d, 0x2071, 0xa300, 0x708c, 0xa005, 0x0040, 0x284a,
-	0x8001, 0x708e, 0x007f, 0x0e7f, 0x007c, 0x2071, 0xa300, 0x70d0,
-	0xa005, 0x0040, 0x284a, 0x8001, 0x70d2, 0x0078, 0x284a, 0x6000,
-	0xc08c, 0x6002, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e,
-	0x017e, 0x157e, 0x2178, 0x81ff, 0x00c0, 0x286a, 0x20a9, 0x0001,
-	0x0078, 0x2885, 0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x2881,
-	0xd0a4, 0x0040, 0x2881, 0x047e, 0x6018, 0xa080, 0x0028, 0x2024,
-	0xa4a4, 0x00ff, 0x8427, 0xa006, 0x2009, 0x002d, 0x1078, 0x9ec0,
-	0x047f, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x027e, 0xa28e, 0x007e,
-	0x0040, 0x28c9, 0xa28e, 0x007f, 0x0040, 0x28c9, 0xa28e, 0x0080,
-	0x0040, 0x28c9, 0xa288, 0xa434, 0x210c, 0x81ff, 0x0040, 0x28c9,
-	0x8fff, 0x1040, 0x28d5, 0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078,
-	0x48a2, 0x0c7f, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
-	0x0000, 0x1078, 0x5c78, 0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294,
-	0x00ff, 0xa286, 0x0006, 0x00c0, 0x28b9, 0x6007, 0x0404, 0x0078,
-	0x28be, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f,
-	0x017e, 0x2c08, 0x1078, 0x9c38, 0x017f, 0x077f, 0x2160, 0x1078,
-	0x471b, 0x027f, 0x8210, 0x00f0, 0x2885, 0x157f, 0x017f, 0x027f,
-	0x037f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e,
-	0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x28e8, 0xd0a4, 0x0040,
-	0x28e8, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x1078, 0x9ec0,
-	0x017f, 0x027f, 0x047f, 0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e,
-	0x7280, 0x82ff, 0x0040, 0x291a, 0xa290, 0xa352, 0x2214, 0xd2ac,
-	0x00c0, 0x291a, 0x2100, 0x1078, 0x24fa, 0x81ff, 0x0040, 0x291c,
-	0x2019, 0x0001, 0x8314, 0xa2e0, 0xa9c0, 0x2c04, 0xd384, 0x0040,
-	0x290e, 0xa084, 0xff00, 0x8007, 0x0078, 0x2910, 0xa084, 0x00ff,
-	0xa116, 0x0040, 0x291c, 0xa096, 0x00ff, 0x0040, 0x291a, 0x8318,
-	0x0078, 0x2902, 0xa085, 0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f,
-	0x007c, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0xa180, 0xa434,
-	0x2004, 0xa065, 0x0040, 0x293b, 0x017e, 0x0c7e, 0x1078, 0x8ec0,
-	0x017f, 0x1040, 0x1328, 0x611a, 0x1078, 0x2813, 0x1078, 0x753d,
-	0x017f, 0x1078, 0x44bc, 0x127f, 0x0c7f, 0x017f, 0x007c, 0x7eef,
-	0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9,
-	0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd,
-	0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3,
-	0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2,
-	0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7,
-	0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098,
-	0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080,
-	0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072,
-	0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067,
-	0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055,
-	0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b,
-	0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a,
-	0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e,
-	0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025,
-	0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010,
-	0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800,
-	0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000,
-	0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000,
-	0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000,
-	0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000,
-	0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000,
-	0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000,
-	0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000,
-	0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000,
-	0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500,
-	0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071,
-	0xa381, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e,
-	0x7033, 0xa391, 0x7037, 0xa391, 0x7007, 0x0001, 0x2061, 0xa3d1,
-	0x6003, 0x0002, 0x007c, 0x0090, 0x2a66, 0x0068, 0x2a66, 0x2071,
-	0xa381, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2a66, 0x2a60, 0x7820,
-	0xa08e, 0x0069, 0x00c0, 0x2b56, 0x0079, 0x2aea, 0x007c, 0x2071,
-	0xa381, 0x7004, 0x0079, 0x2a6c, 0x2a70, 0x2a71, 0x2a7b, 0x2a8d,
-	0x007c, 0x0090, 0x2a7a, 0x0068, 0x2a7a, 0x2b78, 0x7818, 0xd084,
-	0x0040, 0x2a99, 0x007c, 0x2b78, 0x2061, 0xa3d1, 0x6008, 0xa08e,
-	0x0100, 0x0040, 0x2a88, 0xa086, 0x0200, 0x0040, 0x2b4e, 0x007c,
-	0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834,
-	0xa086, 0x0103, 0x0040, 0x2a95, 0x007c, 0x2a60, 0x2b78, 0x7018,
-	0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2aa2, 0x61b8,
-	0x0079, 0x2aaa, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2b4a, 0x61b8,
-	0x0079, 0x2aea, 0x2b2c, 0x2b5e, 0x2b66, 0x2b6a, 0x2b72, 0x2b78,
-	0x2b7c, 0x2b88, 0x2b8c, 0x2b96, 0x2b9a, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b9e, 0x2b4a, 0x2bae, 0x2bc5, 0x2bdc, 0x2c58, 0x2c5d, 0x2c8a,
-	0x2ce4, 0x2cf5, 0x2d13, 0x2d54, 0x2d5e, 0x2d6b, 0x2d7e, 0x2d9d,
-	0x2da6, 0x2de3, 0x2de9, 0x2b4a, 0x2e05, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2e0c, 0x2e16, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2e1e, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2e30, 0x2e47, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2e59, 0x2eb0, 0x2f0e, 0x2f1f, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x38f1, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2b96, 0x2b9a, 0x2f36, 0x2b4a, 0x2f43, 0x397d,
-	0x39da, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a,
-	0x2b4a, 0x2b4a, 0x2f90, 0x30c5, 0x30e1, 0x30ed, 0x3150, 0x31a9,
-	0x31b4, 0x31f3, 0x3202, 0x3211, 0x3214, 0x2f47, 0x3238, 0x3284,
-	0x3291, 0x33a2, 0x34cd, 0x34f7, 0x3604, 0x3614, 0x3621, 0x365b,
-	0x372a, 0x2b4a, 0x2b4a, 0x2b4a, 0x2b4a, 0x3792, 0x37ae, 0x3828,
-	0x38e2, 0x713c, 0x0078, 0x2b2c, 0x2021, 0x4000, 0x1078, 0x3553,
-	0x127e, 0x2091, 0x8000, 0x0068, 0x2b39, 0x7818, 0xd084, 0x0040,
-	0x2b3c, 0x127f, 0x0078, 0x2b30, 0x7c22, 0x7926, 0x7a2a, 0x7b2e,
-	0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000,
-	0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2b2e, 0x2021, 0x4002,
-	0x0078, 0x2b2e, 0x2021, 0x4003, 0x0078, 0x2b2e, 0x2021, 0x4005,
-	0x0078, 0x2b2e, 0x2021, 0x4006, 0x0078, 0x2b2e, 0xa02e, 0x2520,
-	0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3562, 0x7823, 0x0004,
-	0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
-	0x0078, 0x3566, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2b2c,
-	0x7924, 0x2114, 0x0078, 0x2b2c, 0x2099, 0x0009, 0x20a1, 0x0009,
-	0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078, 0x2b2c,
-	0x7824, 0x2060, 0x0078, 0x2ba0, 0x2009, 0x0001, 0x2011, 0x0013,
-	0x2019, 0x0010, 0x783b, 0x0017, 0x0078, 0x2b2c, 0x7d38, 0x7c3c,
-	0x0078, 0x2b60, 0x7d38, 0x7c3c, 0x0078, 0x2b6c, 0x2061, 0x1000,
-	0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0, 0x2ba2,
-	0x2010, 0xa005, 0x0040, 0x2b2c, 0x0078, 0x2b52, 0x2069, 0xa351,
-	0x7824, 0x7930, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a,
-	0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a,
-	0x685e, 0x1078, 0x4dbd, 0x0078, 0x2b2c, 0x2069, 0xa351, 0x7824,
-	0x7934, 0xa11a, 0x00c8, 0x2b5a, 0x8019, 0x0040, 0x2b5a, 0x684e,
-	0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e,
-	0x1078, 0x494d, 0x0078, 0x2b2c, 0xa02e, 0x2520, 0x81ff, 0x00c0,
-	0x2b56, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xa388,
-	0x41a1, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0020, 0x1078,
-	0x3562, 0x701b, 0x2bf4, 0x007c, 0x6834, 0x2008, 0xa084, 0x00ff,
-	0xa096, 0x0011, 0x0040, 0x2c00, 0xa096, 0x0019, 0x00c0, 0x2b56,
-	0x810f, 0xa18c, 0x00ff, 0x0040, 0x2b56, 0x710e, 0x700c, 0x8001,
-	0x0040, 0x2c31, 0x700e, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
-	0x0020, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530, 0xa290,
-	0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078,
-	0x3562, 0x701b, 0x2c24, 0x007c, 0x6834, 0xa084, 0x00ff, 0xa096,
-	0x0002, 0x0040, 0x2c2f, 0xa096, 0x000a, 0x00c0, 0x2b56, 0x0078,
-	0x2c06, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x436e,
-	0x00c0, 0x2c3f, 0x7007, 0x0003, 0x701b, 0x2c41, 0x007c, 0x1078,
-	0x4a60, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xa388,
-	0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f, 0x0078, 0x3566,
-	0x61a0, 0x7824, 0x60a2, 0x0078, 0x2b2c, 0x2091, 0x8000, 0x7823,
-	0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
-	0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
-	0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
-	0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
-	0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427,
-	0x0078, 0x0423, 0x81ff, 0x00c0, 0x2b56, 0x7924, 0x810f, 0xa18c,
-	0x00ff, 0x1078, 0x4501, 0x00c0, 0x2b5a, 0x7e38, 0xa684, 0x3fff,
-	0xa082, 0x4000, 0x0048, 0x2c9e, 0x0078, 0x2b5a, 0x7c28, 0x7d2c,
-	0x1078, 0x46d6, 0xd28c, 0x00c0, 0x2ca9, 0x1078, 0x466a, 0x0078,
-	0x2cab, 0x1078, 0x46a4, 0x00c0, 0x2cd5, 0x2061, 0xaa00, 0x127e,
-	0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2cc3, 0x6010,
-	0xa06d, 0x0040, 0x2cc3, 0x683c, 0xa406, 0x00c0, 0x2cc3, 0x6840,
-	0xa506, 0x0040, 0x2cce, 0x127f, 0xace0, 0x0010, 0x2001, 0xa315,
-	0x2004, 0xac02, 0x00c8, 0x2b56, 0x0078, 0x2caf, 0x1078, 0x8758,
-	0x127f, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0xa00e, 0x2001, 0x0005,
-	0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cc0, 0x1078,
-	0x4982, 0x127f, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078,
-	0x3530, 0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078,
-	0x46e4, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
-	0x1078, 0x3542, 0x0040, 0x2b5a, 0x1078, 0x475f, 0x0040, 0x2b56,
-	0x2019, 0x0005, 0x1078, 0x4705, 0x0040, 0x2b56, 0x7828, 0xa08a,
-	0x1000, 0x00c8, 0x2b5a, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078,
-	0x58e1, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x81ff, 0x0040,
-	0x2d1d, 0x2009, 0x0001, 0x0078, 0x2d4e, 0x2029, 0x00ff, 0x644c,
-	0x2400, 0xa506, 0x0040, 0x2d48, 0x2508, 0x1078, 0x4501, 0x00c0,
-	0x2d48, 0x1078, 0x475f, 0x00c0, 0x2d33, 0x2009, 0x0002, 0x62a8,
-	0x2518, 0x0078, 0x2d4e, 0x2019, 0x0004, 0x1078, 0x4705, 0x00c0,
-	0x2d3d, 0x2009, 0x0006, 0x0078, 0x2d4e, 0x7824, 0xa08a, 0x1000,
-	0x00c8, 0x2d51, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x58e1,
-	0x8529, 0x00c8, 0x2d20, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078,
-	0x2b56, 0x127f, 0x0078, 0x2b5a, 0x1078, 0x3530, 0x0040, 0x2b5a,
-	0x1078, 0x461b, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0,
-	0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a, 0x1078, 0x460a, 0x1078,
-	0x46d6, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
-	0x0040, 0x2b5a, 0x1078, 0x46a7, 0x0040, 0x2b56, 0x1078, 0x43c1,
-	0x1078, 0x4663, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530,
-	0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x62a0, 0x2019,
-	0x0005, 0x0c7e, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e,
-	0x2039, 0x0000, 0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38,
-	0x077f, 0x1078, 0x46d6, 0x0078, 0x2b2c, 0x1078, 0x3530, 0x0040,
-	0x2b5a, 0x1078, 0x46d6, 0x2208, 0x0078, 0x2b2c, 0x157e, 0x0d7e,
-	0x0e7e, 0x2069, 0xa413, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2db2,
-	0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9,
-	0x00ff, 0x2069, 0xa434, 0x2d04, 0xa075, 0x0040, 0x2dc7, 0x704c,
-	0x1078, 0x2dd1, 0xa210, 0x7080, 0x1078, 0x2dd1, 0xa318, 0x8d68,
-	0x00f0, 0x2dbb, 0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078,
-	0x2b2c, 0x0f7e, 0x017e, 0xa07d, 0x0040, 0x2de0, 0x2001, 0x0000,
-	0x8000, 0x2f0c, 0x81ff, 0x0040, 0x2de0, 0x2178, 0x0078, 0x2dd8,
-	0x017f, 0x0f7f, 0x007c, 0x2069, 0xa413, 0x6910, 0x62a4, 0x0078,
-	0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x614c, 0xa190, 0x293f, 0x2214,
-	0xa294, 0x00ff, 0x606c, 0xa084, 0xff00, 0xa215, 0x6368, 0x67c8,
-	0xd79c, 0x0040, 0x2dff, 0x2031, 0x0001, 0x0078, 0x2e01, 0x2031,
-	0x0000, 0x7e3a, 0x7f3e, 0x0078, 0x2b2c, 0x613c, 0x6240, 0x2019,
-	0xa5a0, 0x231c, 0x0078, 0x2b2c, 0x127e, 0x2091, 0x8000, 0x6134,
-	0xa006, 0x2010, 0x2018, 0x127f, 0x0078, 0x2b2c, 0x1078, 0x3542,
-	0x0040, 0x2b5a, 0x6244, 0x6338, 0x0078, 0x2b2c, 0x613c, 0x6240,
-	0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xa351, 0x831f, 0xa305,
-	0x6816, 0x782c, 0x2069, 0xa5a0, 0x2d1c, 0x206a, 0x0078, 0x2b2c,
-	0x017e, 0x127e, 0x2091, 0x8000, 0x7824, 0x6036, 0xd094, 0x0040,
-	0x2e43, 0x7828, 0xa085, 0x0001, 0x2009, 0xa5a9, 0x200a, 0x2001,
-	0xffff, 0x1078, 0x5975, 0x127f, 0x017f, 0x0078, 0x2b2c, 0x1078,
-	0x3542, 0x0040, 0x2b5a, 0x7828, 0xa00d, 0x0040, 0x2b5a, 0x782c,
-	0xa005, 0x0040, 0x2b5a, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078,
-	0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56,
-	0x0c7e, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196,
-	0x00ff, 0x00c0, 0x2e70, 0x6030, 0xa085, 0xff00, 0x0078, 0x2e7f,
-	0xa182, 0x007f, 0x00c8, 0x2ea9, 0xa188, 0x293f, 0x210c, 0xa18c,
-	0x00ff, 0x6030, 0xa116, 0x0040, 0x2ea9, 0x810f, 0xa105, 0x127e,
-	0x2091, 0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2ea5,
-	0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040,
-	0x2eac, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032,
-	0x1078, 0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078,
-	0x2b56, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2ea5,
-	0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0c7e,
-	0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff,
-	0x00c0, 0x2ec7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2ed6, 0xa182,
-	0x007f, 0x00c8, 0x2f00, 0xa188, 0x293f, 0x210c, 0xa18c, 0x00ff,
-	0x6030, 0xa116, 0x0040, 0x2f00, 0x810f, 0xa105, 0x127e, 0x2091,
-	0x8000, 0x007e, 0x1078, 0x74d7, 0x007f, 0x0040, 0x2efc, 0x601a,
-	0x600b, 0xbc05, 0x601f, 0x0001, 0x1078, 0x3518, 0x0040, 0x2f03,
-	0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x701b, 0x2f07, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078,
-	0x756c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2b56,
-	0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x753d, 0x0078, 0x2efc, 0x6830,
-	0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x2061, 0xa62d,
-	0x127e, 0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2f1c, 0x6104,
-	0x6208, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x81ff,
-	0x00c0, 0x2b56, 0x127e, 0x2091, 0x8000, 0x6244, 0x6060, 0xa202,
-	0x0048, 0x2f33, 0xa085, 0x0001, 0x1078, 0x2500, 0x1078, 0x3bf5,
-	0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b5a, 0x127e, 0x2091,
-	0x8000, 0x20a9, 0x0011, 0x2001, 0xa340, 0x20a0, 0xa006, 0x40a4,
-	0x127f, 0x0078, 0x2b2c, 0x7d38, 0x7c3c, 0x0078, 0x2bde, 0x7824,
-	0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2b56, 0x624c, 0xa084,
-	0xff00, 0x8007, 0xa206, 0x00c0, 0x2f5f, 0x2001, 0xa340, 0x2009,
-	0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566, 0x81ff,
-	0x00c0, 0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518,
-	0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x1078, 0x8b85, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x2f81,
-	0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0xad80, 0x000e,
-	0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x3566,
-	0x1078, 0x3518, 0x0040, 0x2b56, 0x1078, 0x421a, 0x2009, 0x001c,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x2fa1,
-	0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2b5a, 0x6804,
-	0xd0ac, 0x0040, 0x2fae, 0xd0a4, 0x0040, 0x2b5a, 0xd094, 0x0040,
-	0x2fb9, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106,
-	0x0c7f, 0xd08c, 0x0040, 0x2fc4, 0x0c7e, 0x2061, 0x0100, 0x6104,
-	0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a,
-	0x0002, 0x0048, 0x2fd9, 0xd084, 0x0040, 0x2fd9, 0x6a28, 0xa28a,
-	0x007f, 0x00c8, 0x2b5a, 0xa288, 0x293f, 0x210c, 0xa18c, 0x00ff,
-	0x6152, 0xd0dc, 0x0040, 0x2fe2, 0x6828, 0xa08a, 0x007f, 0x00c8,
-	0x2b5a, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2b5a, 0xa08a,
-	0x0841, 0x00c8, 0x2b5a, 0xa084, 0x0007, 0x00c0, 0x2b5a, 0x680c,
-	0xa005, 0x0040, 0x2b5a, 0x6810, 0xa005, 0x0040, 0x2b5a, 0x6848,
-	0x6940, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x684c,
-	0x6944, 0xa10a, 0x00c8, 0x2b5a, 0x8001, 0x0040, 0x2b5a, 0x6804,
-	0xd0fc, 0x0040, 0x3038, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009,
-	0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399,
-	0x0000, 0x1078, 0x3562, 0x701b, 0x301e, 0x007c, 0xade8, 0x000d,
-	0x20a9, 0x0014, 0x2d98, 0x2069, 0xa36d, 0x2da0, 0x53a3, 0x7010,
-	0xa0e8, 0x000d, 0x2001, 0xa371, 0x200c, 0xd1e4, 0x0040, 0x3038,
-	0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00, 0x6006, 0x0c7f,
-	0x20a9, 0x001c, 0x2d98, 0x2069, 0xa351, 0x2da0, 0x53a3, 0x6814,
-	0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078,
-	0x4dbd, 0x1078, 0x48dd, 0x1078, 0x494d, 0x6000, 0xa086, 0x0000,
-	0x00c0, 0x30c3, 0x6808, 0x602a, 0x1078, 0x218b, 0x6818, 0x691c,
-	0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
-	0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x3070, 0x6830, 0x6934,
-	0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x3072,
-	0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x59a8,
-	0x6904, 0xd1fc, 0x0040, 0x30a5, 0x0c7e, 0x2009, 0x0000, 0x20a9,
-	0x0001, 0x6b70, 0xd384, 0x0040, 0x30a2, 0x0078, 0x308c, 0x839d,
-	0x00c8, 0x30a2, 0x3508, 0x8109, 0x1078, 0x5364, 0x6878, 0x6016,
-	0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff,
-	0x6006, 0x8108, 0x00c0, 0x30a0, 0x6003, 0x0003, 0x0078, 0x30a2,
-	0x6003, 0x0001, 0x00f0, 0x3087, 0x0c7f, 0x0c7e, 0x2061, 0x0100,
-	0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078, 0x3784, 0x0040,
-	0x30b3, 0x1078, 0x2500, 0x60bc, 0xa005, 0x0040, 0x30bf, 0x6003,
-	0x0001, 0x2091, 0x301d, 0x1078, 0x4171, 0x0078, 0x30c3, 0x6003,
-	0x0004, 0x2091, 0x301d, 0x0078, 0x2b2c, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x2b56, 0x2069, 0xa351, 0x7830, 0x6842, 0x7834, 0x6846,
-	0x6804, 0xd0fc, 0x0040, 0x30d8, 0x2009, 0x0030, 0x0078, 0x30da,
-	0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
-	0x3566, 0xa006, 0x1078, 0x2500, 0x81ff, 0x00c0, 0x2b56, 0x1078,
-	0x421a, 0x1078, 0x4171, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56,
-	0x6180, 0x81ff, 0x0040, 0x3107, 0x703f, 0x0000, 0x2001, 0xa9c0,
-	0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x3566, 0x701b, 0x2b29, 0x127f, 0x007c, 0x703f,
-	0x0001, 0x0d7e, 0x2069, 0xa9c0, 0x20a9, 0x0040, 0x20a1, 0xa9c0,
-	0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x293f, 0x210c, 0xa18c,
-	0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040,
-	0x3139, 0x1078, 0x4501, 0x00c0, 0x3139, 0x6014, 0x821c, 0x0048,
-	0x3131, 0xa398, 0xa9c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078,
-	0x3138, 0xa398, 0xa9c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a,
-	0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x3140, 0x0078, 0x311d,
-	0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040,
-	0x20a1, 0xa9c0, 0x2099, 0xa9c0, 0x1078, 0x41be, 0x0078, 0x30f6,
-	0x1078, 0x3542, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f,
-	0x00c0, 0x315e, 0x2009, 0x0002, 0x0078, 0x2b56, 0x2001, 0xa352,
-	0x2004, 0xd0b4, 0x0040, 0x3185, 0x6000, 0xd08c, 0x00c0, 0x3185,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3185, 0x6837,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8bd9, 0x00c0, 0x317c,
-	0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3181,
-	0x007c, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x20a9, 0x002b, 0x2c98,
-	0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006,
-	0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x41be, 0x20a9, 0x0004,
-	0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x41be,
-	0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
-	0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040, 0x2b5a,
-	0x1078, 0x46ef, 0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x7828,
-	0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x1078, 0x3542, 0x0040, 0x2b5a,
-	0x1078, 0x475f, 0x0040, 0x2b56, 0x2019, 0x0004, 0x1078, 0x4705,
-	0x7924, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x0078, 0x2b2c, 0xa186,
-	0x00ff, 0x0040, 0x31d7, 0x1078, 0x31e7, 0x0078, 0x31e6, 0x2029,
-	0x007e, 0x2061, 0xa300, 0x644c, 0x2400, 0xa506, 0x0040, 0x31e3,
-	0x2508, 0x1078, 0x31e7, 0x8529, 0x00c8, 0x31dc, 0x007c, 0x1078,
-	0x4501, 0x00c0, 0x31f2, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108,
-	0x1078, 0x58e1, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530,
-	0x0040, 0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46fa,
-	0x0078, 0x2b2c, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
-	0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x46e4, 0x0078,
-	0x2b2c, 0x6100, 0x0078, 0x2b2c, 0x1078, 0x3542, 0x0040, 0x2b5a,
-	0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x0d7e,
-	0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x3228, 0xace8, 0x0006,
-	0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f,
-	0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200, 0x0078, 0x2b2c,
-	0xa006, 0x1078, 0x2500, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
-	0x0040, 0x3245, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x421a, 0x7828,
-	0xa08a, 0x1000, 0x00c8, 0x2b5a, 0x7924, 0xa18c, 0xff00, 0x810f,
-	0xa186, 0x00ff, 0x0040, 0x325b, 0xa182, 0x007f, 0x00c8, 0x2b5a,
-	0x2100, 0x1078, 0x24fa, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000,
-	0x2061, 0xa5be, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x0100,
-	0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090,
-	0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078, 0x596c,
-	0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078, 0x31cf, 0x127f,
-	0x0c7f, 0x027f, 0x0078, 0x2b2c, 0x7924, 0xa18c, 0xff00, 0x810f,
-	0x0c7e, 0x1078, 0x4499, 0x2c08, 0x0c7f, 0x00c0, 0x2b5a, 0x0078,
-	0x2b2c, 0x81ff, 0x0040, 0x3298, 0x2009, 0x0001, 0x0078, 0x2b56,
-	0x60c8, 0xd09c, 0x00c0, 0x32a0, 0x2009, 0x0005, 0x0078, 0x2b56,
-	0x1078, 0x3518, 0x00c0, 0x32a8, 0x2009, 0x0002, 0x0078, 0x2b56,
-	0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b,
-	0x32b2, 0x007c, 0x2009, 0x0080, 0x1078, 0x4501, 0x00c0, 0x32bf,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x32c3, 0x2021,
-	0x400a, 0x0078, 0x2b2e, 0x0d7e, 0xade8, 0x000d, 0x6900, 0x6a08,
-	0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0040,
-	0x3336, 0xa0be, 0x0112, 0x0040, 0x3336, 0xa0be, 0x0113, 0x0040,
-	0x3336, 0xa0be, 0x0114, 0x0040, 0x3336, 0xa0be, 0x0117, 0x0040,
-	0x3336, 0xa0be, 0x011a, 0x0040, 0x3336, 0xa0be, 0x0121, 0x0040,
-	0x332c, 0xa0be, 0x0131, 0x0040, 0x332c, 0xa0be, 0x0171, 0x0040,
-	0x3336, 0xa0be, 0x0173, 0x0040, 0x3336, 0xa0be, 0x01a1, 0x00c0,
-	0x32fe, 0x6830, 0x8007, 0x6832, 0x0078, 0x333c, 0xa0be, 0x0212,
-	0x0040, 0x3332, 0xa0be, 0x0213, 0x0040, 0x3332, 0xa0be, 0x0214,
-	0x0040, 0x3324, 0xa0be, 0x0217, 0x0040, 0x331e, 0xa0be, 0x021a,
-	0x00c0, 0x3317, 0x6838, 0x8007, 0x683a, 0x0078, 0x3336, 0xa0be,
-	0x0300, 0x0040, 0x3336, 0x0d7f, 0x0078, 0x2b5a, 0xad80, 0x0010,
-	0x20a9, 0x0007, 0x1078, 0x337e, 0xad80, 0x000e, 0x20a9, 0x0001,
-	0x1078, 0x337e, 0x0078, 0x3336, 0xad80, 0x000c, 0x1078, 0x338c,
-	0x0078, 0x333c, 0xad80, 0x000e, 0x1078, 0x338c, 0xad80, 0x000c,
-	0x20a9, 0x0001, 0x1078, 0x337e, 0x0c7e, 0x1078, 0x3518, 0x0040,
-	0x336f, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853, 0x0000,
-	0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000,
-	0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f,
-	0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
-	0x6804, 0x2068, 0x1078, 0x8ba1, 0x00c0, 0x336a, 0x2009, 0x0003,
-	0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3375, 0x007c, 0x0c7f,
-	0x0d7f, 0x2009, 0x0002, 0x0078, 0x2b56, 0x6820, 0xa086, 0x8001,
-	0x00c0, 0x2b2c, 0x2009, 0x0004, 0x0078, 0x2b56, 0x017e, 0x2008,
-	0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108,
-	0x00f0, 0x3380, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008,
-	0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a,
-	0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f,
-	0x017f, 0x007c, 0x81ff, 0x0040, 0x33a9, 0x2009, 0x0001, 0x0078,
-	0x2b56, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080,
-	0x0048, 0x2b5a, 0xa182, 0x00ff, 0x00c8, 0x2b5a, 0x7a2c, 0x7b28,
-	0x6068, 0xa306, 0x00c0, 0x33c4, 0x606c, 0xa24e, 0x0040, 0x2b5a,
-	0xa9cc, 0xff00, 0x0040, 0x2b5a, 0x0c7e, 0x1078, 0x346d, 0x2c68,
-	0x0c7f, 0x0040, 0x33fc, 0xa0c6, 0x4000, 0x00c0, 0x33e2, 0x0c7e,
-	0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x47cb, 0x00c0, 0x33d9,
-	0xc185, 0x6000, 0xd0bc, 0x0040, 0x33de, 0xc18d, 0x007f, 0x0c7f,
-	0x0078, 0x33f9, 0xa0c6, 0x4007, 0x00c0, 0x33e9, 0x2408, 0x0078,
-	0x33f9, 0xa0c6, 0x4008, 0x00c0, 0x33f1, 0x2708, 0x2610, 0x0078,
-	0x33f9, 0xa0c6, 0x4009, 0x00c0, 0x33f7, 0x0078, 0x33f9, 0x2001,
-	0x4006, 0x2020, 0x0078, 0x2b2e, 0x2d00, 0x7022, 0x017e, 0x0b7e,
-	0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x74d7, 0x0040, 0x3442, 0x2d00,
-	0x601a, 0x2001, 0xa356, 0x2004, 0xa084, 0x00ff, 0x6842, 0x2e58,
-	0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2b70, 0x00c0,
-	0x3423, 0x1078, 0x753d, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x2009,
-	0x0002, 0x0078, 0x2b56, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x2813, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x442b,
-	0x2001, 0x0002, 0x1078, 0x443f, 0x2009, 0x0002, 0x1078, 0x756c,
-	0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x00c0, 0x344c,
-	0x2009, 0x0003, 0x0078, 0x2b56, 0x7007, 0x0003, 0x701b, 0x3451,
-	0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060, 0x00c0, 0x345f,
-	0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078, 0x2b56, 0x2009,
-	0x0000, 0x1078, 0x47cb, 0x00c0, 0x3466, 0xc185, 0x6000, 0xd0bc,
-	0x0040, 0x346b, 0xc18d, 0x0078, 0x2b2c, 0x0e7e, 0x0d7e, 0x2029,
-	0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xa4b4, 0x2e04,
-	0xa005, 0x00c0, 0x3482, 0x2100, 0xa406, 0x00c0, 0x34b3, 0x2428,
-	0x0078, 0x34b3, 0x2068, 0x6f10, 0x2700, 0xa306, 0x00c0, 0x34a4,
-	0x6e14, 0x2600, 0xa206, 0x00c0, 0x34a4, 0x2400, 0xa106, 0x00c0,
-	0x34a0, 0x2d60, 0xd884, 0x0040, 0x34c8, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x00c0, 0x34c8, 0x2001, 0x4000, 0x0078, 0x34c9,
-	0x2001, 0x4007, 0x0078, 0x34c9, 0x2400, 0xa106, 0x00c0, 0x34b3,
-	0x6e14, 0x87ff, 0x00c0, 0x34af, 0x86ff, 0x0040, 0x347f, 0x2001,
-	0x4008, 0x0078, 0x34c9, 0x8420, 0x8e70, 0x00f0, 0x3477, 0x85ff,
-	0x00c0, 0x34c2, 0x2001, 0x4009, 0x0078, 0x34c9, 0x2001, 0x0001,
-	0x0078, 0x34c9, 0x1078, 0x4499, 0x00c0, 0x34be, 0x6312, 0x6216,
-	0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0, 0x2b56,
-	0x1078, 0x3518, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x7824, 0xa005, 0x0040, 0x2b5a, 0xa096, 0x00ff, 0x0040,
-	0x34e5, 0xa092, 0x0004, 0x00c8, 0x2b5a, 0x2010, 0x2d18, 0x1078,
-	0x27c2, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x34f0, 0x007c,
-	0x6830, 0xa086, 0x0100, 0x0040, 0x2b56, 0x0078, 0x2b2c, 0x7924,
-	0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2b5a, 0xa182,
-	0x00ff, 0x00c8, 0x2b5a, 0x127e, 0x2091, 0x8000, 0x1078, 0x8a89,
-	0x00c0, 0x3515, 0xa190, 0xa434, 0x2204, 0xa065, 0x0040, 0x3515,
-	0x1078, 0x4235, 0x127f, 0x0078, 0x2b2c, 0x127f, 0x0078, 0x2b56,
-	0x1078, 0x1381, 0x0040, 0x352f, 0xa006, 0x6802, 0x7010, 0xa005,
-	0x00c0, 0x3527, 0x2d00, 0x7012, 0x7016, 0x0078, 0x352d, 0x7014,
-	0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x007c,
-	0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501, 0x00c0, 0x353f,
-	0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048, 0x3540, 0xa066,
-	0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078, 0x4501,
-	0x00c0, 0x3550, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0048, 0x3551,
-	0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040, 0x355e,
-	0x2168, 0x6904, 0x1078, 0x139a, 0x0078, 0x3555, 0x7112, 0x7116,
-	0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x3568, 0x2031, 0x0000,
-	0x2061, 0xa3d1, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x2b2c,
-	0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001,
-	0xa38f, 0x2004, 0xa005, 0x00c0, 0x3594, 0x0068, 0x3594, 0x7818,
-	0xd084, 0x00c0, 0x3594, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001,
-	0x2091, 0x4080, 0x0078, 0x35b9, 0x017e, 0x0c7e, 0x0e7e, 0x2071,
-	0xa381, 0x7138, 0xa182, 0x0008, 0x0048, 0x35a2, 0x7030, 0x2060,
-	0x0078, 0x35b3, 0x7030, 0xa0e0, 0x0008, 0xac82, 0xa3d1, 0x0048,
-	0x35ab, 0x2061, 0xa391, 0x2c00, 0x7032, 0x81ff, 0x00c0, 0x35b1,
-	0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f, 0x0c7f,
-	0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0xa381, 0x7038,
-	0xa005, 0x0040, 0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x35f4,
-	0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x35f3, 0x0c7e,
-	0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a,
-	0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005,
-	0x00c0, 0x35e9, 0x7033, 0xa391, 0x7037, 0xa391, 0x0c7f, 0x0078,
-	0x35f3, 0xac80, 0x0008, 0xa0fa, 0xa3d1, 0x0048, 0x35f1, 0x2001,
-	0xa391, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c, 0x027e,
-	0x2001, 0xa352, 0x2004, 0xd0c4, 0x0040, 0x3602, 0x2011, 0x8014,
-	0x1078, 0x3579, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x2b56, 0x127e,
-	0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x1078,
-	0x4171, 0x127f, 0x0078, 0x2b2c, 0x7824, 0x2008, 0xa18c, 0xfffd,
-	0x00c0, 0x361f, 0x61d4, 0xa10d, 0x61d6, 0x0078, 0x2b2c, 0x0078,
-	0x2b5a, 0x81ff, 0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x00c0,
-	0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x2b56, 0x1078,
-	0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x00c0, 0x363e, 0x7828, 0xa005, 0x0040, 0x2b2c, 0x0c7e, 0x1078,
-	0x3518, 0x0c7f, 0x0040, 0x2b56, 0x6837, 0x0000, 0x6833, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x1078, 0x8c4d, 0x0040, 0x2b56, 0x7007,
-	0x0003, 0x701b, 0x3654, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
-	0x2b56, 0x0078, 0x2b2c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003,
-	0x00c0, 0x2b56, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
-	0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023,
-	0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078,
-	0x4501, 0x00c0, 0x36d8, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006,
-	0x0040, 0x3688, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x00c0, 0x36d8,
-	0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x3695, 0x1078, 0x47cb,
-	0x00c0, 0x3695, 0xd79c, 0x0040, 0x36d8, 0xd794, 0x00c0, 0x369b,
-	0xd784, 0x0040, 0x36a7, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
-	0x0004, 0x53a3, 0x1078, 0x338c, 0xd794, 0x0040, 0x36b0, 0xac80,
-	0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078, 0x338c,
-	0x21a2, 0xd794, 0x0040, 0x36d0, 0xac80, 0x0000, 0x2098, 0x94a0,
-	0x20a9, 0x0002, 0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80,
-	0x0004, 0x2098, 0x3400, 0x20a9, 0x0002, 0x53a3, 0x1078, 0x337e,
-	0xac80, 0x0026, 0x2098, 0x20a9, 0x0002, 0x53a3, 0x0078, 0x36d1,
-	0x94a0, 0xd794, 0x0040, 0x36d6, 0xa6b0, 0x000b, 0xa6b0, 0x0005,
-	0x8108, 0xd78c, 0x0040, 0x36e2, 0xa186, 0x0100, 0x0040, 0x36f3,
-	0x0078, 0x36e6, 0xa186, 0x007e, 0x0040, 0x36f3, 0xd794, 0x0040,
-	0x36ed, 0xa686, 0x0020, 0x0078, 0x36ef, 0xa686, 0x0028, 0x0040,
-	0x36fc, 0x0078, 0x3677, 0x86ff, 0x00c0, 0x36fa, 0x7120, 0x810b,
-	0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022,
-	0x772a, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e,
-	0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13d1, 0x7007,
-	0x0002, 0x701b, 0x3714, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3726,
-	0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0xa3d1,
-	0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3677, 0x7120, 0x810b,
-	0x0078, 0x2b2c, 0x2029, 0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38,
-	0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502,
-	0x0048, 0x2b5a, 0xa184, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
-	0xa502, 0x0048, 0x2b5a, 0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020,
-	0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa284, 0x00ff, 0xa0e2,
-	0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a, 0xa384, 0xff00,
-	0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048, 0x2b5a,
-	0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2b5a, 0xa502, 0x0048,
-	0x2b5a, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2b5a,
-	0xa502, 0x0048, 0x2b5a, 0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048,
-	0x2b5a, 0xa502, 0x0048, 0x2b5a, 0x2061, 0xa5a3, 0x6102, 0x6206,
-	0x630a, 0x640e, 0x0078, 0x2b2c, 0x007e, 0x2001, 0xa352, 0x2004,
-	0xd0cc, 0x007f, 0x007c, 0x007e, 0x2001, 0xa371, 0x2004, 0xd0bc,
-	0x007f, 0x007c, 0x6160, 0x7a24, 0x6300, 0x82ff, 0x00c0, 0x379b,
-	0x7926, 0x0078, 0x2b2c, 0x83ff, 0x00c0, 0x2b5a, 0x2001, 0xfff0,
-	0xa200, 0x00c8, 0x2b5a, 0x2019, 0xffff, 0x6064, 0xa302, 0xa200,
-	0x0048, 0x2b5a, 0x7926, 0x6262, 0x0078, 0x2b2c, 0x2001, 0xa300,
-	0x2004, 0xa086, 0x0003, 0x00c0, 0x2b56, 0x7c28, 0x7d24, 0x7e38,
-	0x7f2c, 0x1078, 0x3518, 0x0040, 0x2b56, 0x2009, 0x0000, 0x2019,
-	0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003, 0x7026,
-	0x20a0, 0xa1e0, 0xa434, 0x2c64, 0x8cff, 0x0040, 0x37e8, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x0040, 0x37dd, 0x6004, 0xa084,
-	0xff00, 0xa086, 0x0600, 0x00c0, 0x37e8, 0x6014, 0x20a2, 0x94a0,
-	0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002,
-	0x8108, 0xa182, 0x00ff, 0x0040, 0x37f3, 0xa386, 0x002a, 0x0040,
-	0x37fc, 0x0078, 0x37c9, 0x83ff, 0x00c0, 0x37fa, 0x7120, 0x810c,
-	0x0078, 0x2b2c, 0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022,
-	0x2061, 0xa3d1, 0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426,
-	0x652a, 0x662e, 0x6732, 0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002,
-	0x701b, 0x3813, 0x007c, 0x702c, 0xa005, 0x00c0, 0x3824, 0x711c,
-	0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xa3d1, 0x6424, 0x6528,
-	0x662c, 0x6730, 0x0078, 0x37c9, 0x7120, 0x810c, 0x0078, 0x2b2c,
-	0x81ff, 0x00c0, 0x2b56, 0x60c8, 0xd09c, 0x0040, 0x2b56, 0x1078,
-	0x3518, 0x0040, 0x2b56, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x1078, 0x3562, 0x701b, 0x383d, 0x007c, 0x0d7e, 0xade8, 0x000d,
-	0x6828, 0xa0be, 0x7000, 0x0040, 0x3850, 0xa0be, 0x7100, 0x0040,
-	0x3850, 0xa0be, 0x7200, 0x0040, 0x3850, 0x0d7f, 0x0078, 0x2b5a,
-	0x6820, 0x6924, 0x1078, 0x24e3, 0x00c0, 0x387b, 0x1078, 0x4499,
-	0x00c0, 0x387b, 0x7122, 0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078,
-	0x3518, 0x0040, 0x387b, 0x1078, 0x3518, 0x0040, 0x387b, 0x0c7f,
-	0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
-	0x6804, 0x2068, 0x1078, 0x8bbd, 0x0040, 0x2b56, 0x7007, 0x0003,
-	0x701b, 0x387e, 0x007c, 0x0d7f, 0x0078, 0x2b56, 0x7120, 0x1078,
-	0x2921, 0x6820, 0xa086, 0x8001, 0x0040, 0x2b56, 0x2d00, 0x701e,
-	0x6804, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0,
-	0x1078, 0x41be, 0x007f, 0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10,
-	0x6d14, 0x2061, 0xa3d1, 0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6,
-	0x7000, 0x00c0, 0x38a5, 0x0078, 0x38a9, 0xa7c6, 0x7100, 0x00c0,
-	0x38b1, 0xa6c2, 0x0004, 0x0048, 0x2b5a, 0x2009, 0x0004, 0x0078,
-	0x3566, 0xa7c6, 0x7200, 0x00c0, 0x2b5a, 0xa6c2, 0x0054, 0x0048,
-	0x2b5a, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e, 0x6532,
-	0x2c10, 0x1078, 0x13d1, 0x7007, 0x0002, 0x701b, 0x38c8, 0x007c,
-	0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002,
-	0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x41be, 0x007f,
-	0x2009, 0x002a, 0x2061, 0xa3d1, 0x6224, 0x6328, 0x642c, 0x6530,
-	0x0078, 0x3566, 0x81ff, 0x00c0, 0x2b56, 0x1078, 0x3530, 0x0040,
-	0x2b5a, 0x1078, 0x45a7, 0x0040, 0x2b56, 0x1078, 0x4710, 0x0078,
-	0x2b2c, 0x7824, 0xd084, 0x0040, 0x3150, 0x1078, 0x3542, 0x0040,
-	0x2b5a, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x00c0, 0x3903, 0x2009,
-	0x0002, 0x0078, 0x2b56, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x0040, 0x3910, 0xa08e, 0x0004, 0x0040, 0x3910, 0xa08e, 0x0005,
-	0x00c0, 0x3934, 0x2001, 0xa352, 0x2004, 0xd0b4, 0x0040, 0x3185,
-	0x6000, 0xd08c, 0x00c0, 0x3185, 0x6837, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x1078, 0x8bd9, 0x00c0, 0x3929, 0x2009, 0x0003, 0x0078,
-	0x2b56, 0x7007, 0x0003, 0x701b, 0x392e, 0x007c, 0x1078, 0x3542,
-	0x0040, 0x2b5a, 0x0078, 0x3185, 0x2009, 0xa32e, 0x210c, 0x81ff,
-	0x0040, 0x393e, 0x2009, 0x0001, 0x0078, 0x2b56, 0x2001, 0xa300,
-	0x2004, 0xa086, 0x0003, 0x0040, 0x3949, 0x2009, 0x0007, 0x0078,
-	0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x0040, 0x3953, 0x2009,
-	0x0008, 0x0078, 0x2b56, 0x609c, 0xd0a4, 0x00c0, 0x395a, 0xd0ac,
-	0x00c0, 0x3185, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x1078, 0x8c4d, 0x00c0, 0x3969, 0x2009, 0x0003, 0x0078,
-	0x2b56, 0x7007, 0x0003, 0x701b, 0x396e, 0x007c, 0x6830, 0xa086,
-	0x0100, 0x00c0, 0x3977, 0x2009, 0x0004, 0x0078, 0x2b56, 0x1078,
-	0x3542, 0x0040, 0x2b5a, 0x0078, 0x3912, 0x81ff, 0x2009, 0x0001,
-	0x00c0, 0x2b56, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0,
-	0x2b56, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x00c0,
-	0x2b56, 0x1078, 0x3542, 0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078,
-	0x3518, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2b56, 0x6837, 0x0000,
-	0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00,
-	0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x39bc, 0xc0ed, 0x6952,
-	0x792c, 0x6956, 0x0078, 0x39c5, 0xa28e, 0x0100, 0x00c0, 0x2b5a,
-	0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078, 0x8df6,
-	0x2009, 0x0003, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b, 0x39d1,
-	0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040, 0x2b56,
-	0x0078, 0x2b2c, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2b56, 0x6000,
-	0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2b56, 0x1078, 0x3542,
-	0x0040, 0x2b5a, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x2009,
-	0x0009, 0x00c0, 0x2b56, 0x0c7e, 0x1078, 0x3518, 0x0c7f, 0x2009,
-	0x0002, 0x0040, 0x2b56, 0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3562, 0x701b, 0x3a08, 0x007c,
-	0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0, 0x3a1b,
-	0x6804, 0xa005, 0x00c0, 0x3a1b, 0x6808, 0xa084, 0xff00, 0x00c0,
-	0x3a1b, 0x0078, 0x3a1e, 0x0d7f, 0x00c0, 0x2b5a, 0x0d7f, 0x6837,
-	0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e, 0x1078,
-	0x3542, 0x00c0, 0x3a2e, 0x0c7f, 0x0078, 0x2b5a, 0x1078, 0x8e52,
-	0x2009, 0x0003, 0x0c7f, 0x0040, 0x2b56, 0x7007, 0x0003, 0x701b,
-	0x3a3a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040,
-	0x2b56, 0x0078, 0x2b2c, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100,
-	0x2071, 0xa300, 0x6044, 0xd0a4, 0x00c0, 0x3a6c, 0xd084, 0x0040,
-	0x3a55, 0x1078, 0x3bcc, 0x0078, 0x3a68, 0xd08c, 0x0040, 0x3a5c,
-	0x1078, 0x3ae3, 0x0078, 0x3a68, 0xd094, 0x0040, 0x3a63, 0x1078,
-	0x3ab7, 0x0078, 0x3a68, 0xd09c, 0x0040, 0x3a68, 0x1078, 0x3a76,
-	0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0,
-	0x3a73, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3a68, 0x624c, 0xa286,
-	0xf0f0, 0x00c0, 0x3a87, 0x6048, 0xa086, 0xf0f0, 0x0040, 0x3a87,
-	0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3ab6, 0xa294,
-	0xff00, 0xa296, 0xf700, 0x0040, 0x3a9c, 0x7134, 0xd1a4, 0x00c0,
-	0x3a9c, 0x6240, 0xa294, 0x0010, 0x0040, 0x3a9c, 0x2009, 0x00f7,
-	0x1078, 0x41de, 0x0078, 0x3ab6, 0x6043, 0x0040, 0x6043, 0x0000,
-	0x7073, 0x0000, 0x708b, 0x0001, 0x70af, 0x0000, 0x70cb, 0x0000,
-	0x2009, 0xa9c0, 0x200b, 0x0000, 0x7083, 0x0000, 0x7077, 0x000f,
-	0x2009, 0x000f, 0x2011, 0x4122, 0x1078, 0x596c, 0x007c, 0x157e,
-	0x7074, 0xa005, 0x00c0, 0x3ae1, 0x2011, 0x4122, 0x1078, 0x58d4,
-	0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8,
-	0x6044, 0xd08c, 0x00c0, 0x3ada, 0x00f0, 0x3ac8, 0x6242, 0x7087,
-	0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
-	0x0078, 0x3ae1, 0x6242, 0x7087, 0x0000, 0x707b, 0x0000, 0x0078,
-	0x3ae1, 0x157f, 0x007c, 0x7078, 0xa08a, 0x0003, 0x00c8, 0x3aec,
-	0x1079, 0x3aef, 0x0078, 0x3aee, 0x1078, 0x1328, 0x007c, 0x3af2,
-	0x3b41, 0x3bcb, 0x0f7e, 0x707b, 0x0001, 0x20e1, 0xa000, 0x20e1,
-	0x8700, 0x1078, 0x218b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
-	0xa800, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
-	0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
-	0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
-	0x0000, 0x2079, 0xa80c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
-	0xa305, 0x20a1, 0xa80e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0xa812,
-	0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xa800, 0x20a1, 0x020b,
-	0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
-	0x4158, 0x0f7f, 0x707f, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
-	0x007c, 0x0d7e, 0x707c, 0x707f, 0x0000, 0xa025, 0x0040, 0x3bb5,
-	0x6020, 0xd0b4, 0x00c0, 0x3bb3, 0x7188, 0x81ff, 0x0040, 0x3ba2,
-	0xa486, 0x000c, 0x00c0, 0x3bad, 0xa480, 0x0018, 0x8004, 0x20a8,
-	0x2011, 0xa880, 0x2019, 0xa800, 0x220c, 0x2304, 0xa106, 0x00c0,
-	0x3b79, 0x8210, 0x8318, 0x00f0, 0x3b5c, 0x6043, 0x0004, 0x608b,
-	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707b, 0x0002, 0x7087,
-	0x0002, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c, 0x0078,
-	0x3bb3, 0x2069, 0xa880, 0x6930, 0xa18e, 0x1101, 0x00c0, 0x3bad,
-	0x6834, 0xa005, 0x00c0, 0x3bad, 0x6900, 0xa18c, 0x00ff, 0x00c0,
-	0x3b8d, 0x6804, 0xa005, 0x0040, 0x3ba2, 0x2011, 0xa88e, 0x2019,
-	0xa305, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048, 0x3ba0,
-	0x00c0, 0x3bad, 0x8210, 0x8318, 0x00f0, 0x3b93, 0x0078, 0x3bad,
-	0x708b, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
-	0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x0078, 0x3bb5, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
-	0x3bb3, 0x60c3, 0x000c, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
-	0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
-	0x6c38, 0x0078, 0x3bb3, 0x007c, 0x7084, 0xa08a, 0x001d, 0x00c8,
-	0x3bd5, 0x1079, 0x3bd8, 0x0078, 0x3bd7, 0x1078, 0x1328, 0x007c,
-	0x3c02, 0x3c11, 0x3c40, 0x3c59, 0x3c85, 0x3cb1, 0x3cdd, 0x3d13,
-	0x3d3f, 0x3d67, 0x3daa, 0x3dd4, 0x3df6, 0x3e0c, 0x3e32, 0x3e45,
-	0x3e4e, 0x3e7e, 0x3eaa, 0x3ed6, 0x3f02, 0x3f38, 0x3f7d, 0x3fac,
-	0x3fce, 0x4010, 0x4036, 0x404f, 0x4050, 0x0c7e, 0x2061, 0xa300,
-	0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006,
-	0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002,
-	0x7087, 0x0001, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
-	0x007c, 0x0f7e, 0x707c, 0xa086, 0x0014, 0x00c0, 0x3c3e, 0x6043,
-	0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3c3e, 0x2079, 0xa880, 0x7a30,
-	0xa296, 0x1102, 0x00c0, 0x3c3c, 0x7834, 0xa005, 0x00c0, 0x3c3c,
-	0x7a38, 0xd2fc, 0x0040, 0x3c32, 0x70ac, 0xa005, 0x00c0, 0x3c32,
-	0x70af, 0x0001, 0x2011, 0x4129, 0x1078, 0x58d4, 0x7087, 0x0010,
-	0x1078, 0x3e4e, 0x0078, 0x3c3e, 0x1078, 0x4171, 0x0f7f, 0x007c,
-	0x7087, 0x0003, 0x6043, 0x0004, 0x2011, 0x4129, 0x1078, 0x58d4,
-	0x1078, 0x41c6, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
-	0x20a3, 0x0000, 0x00f0, 0x3c50, 0x60c3, 0x0014, 0x1078, 0x4158,
-	0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3c83, 0x2011, 0x4129,
-	0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3c81, 0x2079, 0xa880,
-	0x7a30, 0xa296, 0x1102, 0x00c0, 0x3c81, 0x7834, 0xa005, 0x00c0,
-	0x3c81, 0x7a38, 0xd2fc, 0x0040, 0x3c7b, 0x70ac, 0xa005, 0x00c0,
-	0x3c7b, 0x70af, 0x0001, 0x7087, 0x0004, 0x1078, 0x3c85, 0x0078,
-	0x3c83, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0005, 0x1078,
-	0x41c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
-	0x1078, 0x4211, 0x00c0, 0x3ca3, 0x7070, 0xa005, 0x00c0, 0x3ca3,
-	0x714c, 0xa186, 0xffff, 0x0040, 0x3ca3, 0x1078, 0x40ea, 0x0040,
-	0x3ca3, 0x1078, 0x41f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158,
-	0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3cdb, 0x2011, 0x4129,
-	0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3cd9, 0x2079, 0xa880,
-	0x7a30, 0xa296, 0x1103, 0x00c0, 0x3cd9, 0x7834, 0xa005, 0x00c0,
-	0x3cd9, 0x7a38, 0xd2fc, 0x0040, 0x3cd3, 0x70ac, 0xa005, 0x00c0,
-	0x3cd3, 0x70af, 0x0001, 0x7087, 0x0006, 0x1078, 0x3cdd, 0x0078,
-	0x3cdb, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0007, 0x1078,
-	0x41c6, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e,
-	0x1078, 0x4211, 0x00c0, 0x3d05, 0x7070, 0xa005, 0x00c0, 0x3d05,
-	0x7150, 0xa186, 0xffff, 0x0040, 0x3d05, 0xa180, 0x293f, 0x200c,
-	0xa18c, 0xff00, 0x810f, 0x1078, 0x40ea, 0x0040, 0x3d05, 0x1078,
-	0x378b, 0x0040, 0x3d05, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2298,
-	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040, 0x3d3d,
-	0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0014, 0x00c0, 0x3d3b,
-	0x2079, 0xa880, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3d3b, 0x7834,
-	0xa005, 0x00c0, 0x3d3b, 0x7a38, 0xd2fc, 0x0040, 0x3d35, 0x70ac,
-	0xa005, 0x00c0, 0x3d35, 0x70af, 0x0001, 0x7087, 0x0008, 0x1078,
-	0x3d3f, 0x0078, 0x3d3d, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087,
-	0x0009, 0x1078, 0x41c6, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430,
-	0x1078, 0x4211, 0x00c0, 0x3d58, 0x7070, 0xa005, 0x00c0, 0x3d58,
-	0x1078, 0x4051, 0x00c0, 0x3d62, 0xa085, 0x0001, 0x1078, 0x2500,
-	0x20a9, 0x0008, 0x2099, 0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e,
-	0x707c, 0xa005, 0x0040, 0x3da8, 0x2011, 0x4129, 0x1078, 0x58d4,
-	0xa086, 0x0014, 0x00c0, 0x3da6, 0x2079, 0xa880, 0x7a30, 0xa296,
-	0x1105, 0x00c0, 0x3da6, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0,
-	0x3d91, 0x7a38, 0xd2fc, 0x0040, 0x3d8b, 0x70ac, 0xa005, 0x00c0,
-	0x3d8b, 0x70af, 0x0001, 0x7087, 0x000a, 0x1078, 0x3daa, 0x0078,
-	0x3da8, 0xa005, 0x00c0, 0x3da6, 0x7a38, 0xd2fc, 0x0040, 0x3d9e,
-	0x70ac, 0xa005, 0x00c0, 0x3d9e, 0x70af, 0x0001, 0x7083, 0x0000,
-	0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3da8, 0x1078, 0x4171,
-	0x0f7f, 0x007c, 0x7087, 0x000b, 0x2011, 0xa80e, 0x22a0, 0x20a9,
-	0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
-	0x41a4, 0x1078, 0x41c6, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x1078,
-	0x4211, 0x0040, 0x3dc7, 0x2013, 0x0000, 0x0078, 0x3dcb, 0x6030,
-	0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
-	0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
-	0x3df4, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
-	0x3df2, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3df2,
-	0x7834, 0xa005, 0x00c0, 0x3df2, 0x7087, 0x000c, 0x1078, 0x3df6,
-	0x0078, 0x3df4, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x000d,
-	0x1078, 0x41c6, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099, 0xa88e,
-	0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0084, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
-	0x3e30, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
-	0x3e2e, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x3e2e,
-	0x7834, 0xa005, 0x00c0, 0x3e2e, 0x7083, 0x0001, 0x1078, 0x41b8,
-	0x7087, 0x000e, 0x1078, 0x3e32, 0x0078, 0x3e30, 0x1078, 0x4171,
-	0x0f7f, 0x007c, 0x7087, 0x000f, 0x707f, 0x0000, 0x608b, 0xbc85,
-	0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0,
-	0x2011, 0x4129, 0x1078, 0x58c7, 0x007c, 0x707c, 0xa005, 0x0040,
-	0x3e4d, 0x2011, 0x4129, 0x1078, 0x58d4, 0x007c, 0x7087, 0x0011,
-	0x1078, 0x4211, 0x00c0, 0x3e67, 0x7168, 0x81ff, 0x0040, 0x3e67,
-	0x2009, 0x0000, 0x706c, 0xa084, 0x00ff, 0x1078, 0x24e3, 0xa186,
-	0x0080, 0x0040, 0x3e67, 0x2011, 0xa88e, 0x1078, 0x40ea, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x747c,
-	0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8,
-	0x53a6, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
-	0xa005, 0x0040, 0x3ea8, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
-	0x0014, 0x00c0, 0x3ea6, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1103,
-	0x00c0, 0x3ea6, 0x7834, 0xa005, 0x00c0, 0x3ea6, 0x7a38, 0xd2fc,
-	0x0040, 0x3ea0, 0x70ac, 0xa005, 0x00c0, 0x3ea0, 0x70af, 0x0001,
-	0x7087, 0x0012, 0x1078, 0x3eaa, 0x0078, 0x3ea8, 0x1078, 0x4171,
-	0x0f7f, 0x007c, 0x7087, 0x0013, 0x1078, 0x41d2, 0x20a3, 0x1103,
-	0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
-	0x3ec8, 0x7070, 0xa005, 0x00c0, 0x3ec8, 0x714c, 0xa186, 0xffff,
-	0x0040, 0x3ec8, 0x1078, 0x40ea, 0x0040, 0x3ec8, 0x1078, 0x41f5,
-	0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c,
-	0xa005, 0x0040, 0x3f00, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086,
-	0x0014, 0x00c0, 0x3efe, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1104,
-	0x00c0, 0x3efe, 0x7834, 0xa005, 0x00c0, 0x3efe, 0x7a38, 0xd2fc,
-	0x0040, 0x3ef8, 0x70ac, 0xa005, 0x00c0, 0x3ef8, 0x70af, 0x0001,
-	0x7087, 0x0014, 0x1078, 0x3f02, 0x0078, 0x3f00, 0x1078, 0x4171,
-	0x0f7f, 0x007c, 0x7087, 0x0015, 0x1078, 0x41d2, 0x20a3, 0x1104,
-	0x20a3, 0x0000, 0x3430, 0x2011, 0xa88e, 0x1078, 0x4211, 0x00c0,
-	0x3f2a, 0x7070, 0xa005, 0x00c0, 0x3f2a, 0x7150, 0xa186, 0xffff,
-	0x0040, 0x3f2a, 0xa180, 0x293f, 0x200c, 0xa18c, 0xff00, 0x810f,
-	0x1078, 0x40ea, 0x0040, 0x3f2a, 0x1078, 0x378b, 0x0040, 0x3f2a,
-	0x1078, 0x2500, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x4158, 0x007c,
-	0x0f7e, 0x707c, 0xa005, 0x0040, 0x3f7b, 0x2011, 0x4129, 0x1078,
-	0x58d4, 0xa086, 0x0014, 0x00c0, 0x3f79, 0x2079, 0xa880, 0x7a30,
-	0xa296, 0x1105, 0x00c0, 0x3f79, 0x7834, 0x2011, 0x0100, 0xa21e,
-	0x00c0, 0x3f5e, 0x7a38, 0xd2fc, 0x0040, 0x3f5c, 0x70ac, 0xa005,
-	0x00c0, 0x3f5c, 0x70af, 0x0001, 0x0078, 0x3f6d, 0xa005, 0x00c0,
-	0x3f79, 0x7a38, 0xd2fc, 0x0040, 0x3f6b, 0x70ac, 0xa005, 0x00c0,
-	0x3f6b, 0x70af, 0x0001, 0x7083, 0x0000, 0x7a38, 0xd2f4, 0x0040,
-	0x3f73, 0x70cb, 0x0008, 0x7087, 0x0016, 0x1078, 0x3f7d, 0x0078,
-	0x3f7b, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0xa880, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6,
-	0x3430, 0x2011, 0xa88e, 0x7087, 0x0017, 0x1078, 0x4211, 0x00c0,
-	0x3f9d, 0x7070, 0xa005, 0x00c0, 0x3f9d, 0x1078, 0x4051, 0x00c0,
-	0x3fa7, 0xa085, 0x0001, 0x1078, 0x2500, 0x20a9, 0x0008, 0x2099,
-	0xa88e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x1078, 0x4158, 0x007c, 0x0f7e, 0x707c, 0xa005, 0x0040,
-	0x3fcc, 0x2011, 0x4129, 0x1078, 0x58d4, 0xa086, 0x0084, 0x00c0,
-	0x3fca, 0x2079, 0xa880, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x3fca,
-	0x7834, 0xa005, 0x00c0, 0x3fca, 0x7087, 0x0018, 0x1078, 0x3fce,
-	0x0078, 0x3fcc, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x0019,
-	0x1078, 0x41d2, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430, 0x2099,
-	0xa88e, 0x2039, 0xa80e, 0x27a0, 0x20a9, 0x0040, 0x53a3, 0x1078,
-	0x4211, 0x00c0, 0x4002, 0x2728, 0x2514, 0x8207, 0xa084, 0x00ff,
-	0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a, 0x6030,
-	0x2310, 0x8214, 0xa2a0, 0xa80e, 0x2414, 0xa38c, 0x0001, 0x0040,
-	0x3ffd, 0xa294, 0xff00, 0x0078, 0x4000, 0xa294, 0x00ff, 0x8007,
-	0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c,
-	0x0f7e, 0x707c, 0xa005, 0x0040, 0x4034, 0x2011, 0x4129, 0x1078,
-	0x58d4, 0xa086, 0x0084, 0x00c0, 0x4032, 0x2079, 0xa880, 0x7a30,
-	0xa296, 0x1107, 0x00c0, 0x4032, 0x7834, 0xa005, 0x00c0, 0x4032,
-	0x7083, 0x0001, 0x1078, 0x41b8, 0x7087, 0x001a, 0x1078, 0x4036,
-	0x0078, 0x4034, 0x1078, 0x4171, 0x0f7f, 0x007c, 0x7087, 0x001b,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880, 0x20a1, 0x020b,
-	0x747c, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004,
-	0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x4158, 0x007c, 0x007c,
-	0x007c, 0x087e, 0x097e, 0x2029, 0xa352, 0x252c, 0x20a9, 0x0008,
-	0x2041, 0xa80e, 0x28a0, 0x2099, 0xa88e, 0x53a3, 0x20a9, 0x0008,
-	0x2011, 0x0007, 0xd5d4, 0x0040, 0x4067, 0x2011, 0x0000, 0x2800,
-	0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0, 0x4079, 0xd5d4, 0x0040,
-	0x4074, 0x8210, 0x0078, 0x4075, 0x8211, 0x00f0, 0x4067, 0x0078,
-	0x40e1, 0x82ff, 0x00c0, 0x408b, 0xd5d4, 0x0040, 0x4085, 0xa1a6,
-	0x3fff, 0x0040, 0x4071, 0x0078, 0x4089, 0xa1a6, 0x3fff, 0x0040,
-	0x40e1, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4,
-	0x0040, 0x4094, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x409b,
-	0x8423, 0x0078, 0x409c, 0x8424, 0x00c8, 0x40a9, 0xd5d4, 0x0040,
-	0x40a4, 0x8319, 0x0078, 0x40a5, 0x8318, 0x00f0, 0x4095, 0x0078,
-	0x40e1, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x40ad,
-	0x2328, 0x8529, 0xa2be, 0x0007, 0x0040, 0x40c1, 0x007e, 0x2039,
-	0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0,
-	0x40bd, 0x754e, 0xa5c8, 0x293f, 0x292c, 0xa5ac, 0x00ff, 0x6532,
-	0x60e7, 0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x2018, 0x2304,
-	0xa405, 0x201a, 0x7073, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0078,
-	0x40e7, 0xa006, 0x0078, 0x40e7, 0xa006, 0x1078, 0x1328, 0x097f,
-	0x087f, 0x007c, 0x2118, 0x2021, 0x0000, 0x2001, 0x0007, 0xa39a,
-	0x0010, 0x0048, 0x40f7, 0x8420, 0x8001, 0x0078, 0x40ef, 0x2118,
-	0x84ff, 0x0040, 0x4100, 0xa39a, 0x0010, 0x8421, 0x00c0, 0x40fb,
-	0x2021, 0x0001, 0x83ff, 0x0040, 0x4109, 0x8423, 0x8319, 0x00c0,
-	0x4105, 0xa238, 0x2704, 0xa42c, 0x00c0, 0x4121, 0xa405, 0x203a,
-	0x714e, 0xa1a0, 0x293f, 0x242c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
-	0x0000, 0x65ea, 0x706b, 0x0000, 0x756e, 0x7073, 0x0001, 0xa084,
-	0x0000, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x7077, 0x0000, 0x0e7f,
-	0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002, 0x1078, 0x5975, 0x2079,
-	0x0100, 0x2071, 0x0140, 0x1078, 0x6c41, 0x7004, 0xa084, 0x4000,
-	0x0040, 0x413e, 0x7003, 0x1000, 0x7003, 0x0000, 0x127e, 0x2091,
-	0x8000, 0x2071, 0xa321, 0x2073, 0x0000, 0x7840, 0x027e, 0x017e,
-	0x2009, 0x00f7, 0x1078, 0x41de, 0x017f, 0xa094, 0x0010, 0xa285,
-	0x0080, 0x7842, 0x7a42, 0x027f, 0x127f, 0x0f7f, 0x0e7f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x2011, 0xa5b5, 0x2013, 0x0000, 0x707f,
-	0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
-	0x1078, 0x6c38, 0x2009, 0x07d0, 0x2011, 0x4129, 0x1078, 0x596c,
-	0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2009,
-	0x00f7, 0x1078, 0x41de, 0x2061, 0xa5be, 0x601b, 0x0000, 0x601f,
-	0x0000, 0x2061, 0xa300, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4196, 0x1078,
-	0x58c7, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c, 0x0e7e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2001, 0x0001, 0x1078, 0x5975, 0x2071,
-	0x0100, 0x1078, 0x6c41, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
-	0x0040, 0x41ae, 0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001,
-	0x1078, 0x2480, 0x1078, 0x4171, 0x127f, 0x007f, 0x0e7f, 0x007c,
-	0x20a9, 0x0040, 0x20a1, 0xa9c0, 0x2099, 0xa88e, 0x3304, 0x8007,
-	0x20a2, 0x9398, 0x94a0, 0x00f0, 0x41be, 0x007c, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0xa800, 0x20a1, 0x020b, 0x20a9, 0x000c,
-	0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xa880,
-	0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e,
-	0x2061, 0x0100, 0x810f, 0x2001, 0xa32e, 0x2004, 0xa005, 0x00c0,
-	0x41ef, 0x6030, 0xa084, 0x00ff, 0xa105, 0x0078, 0x41f1, 0xa185,
-	0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001,
-	0xa352, 0x2004, 0xd0a4, 0x0040, 0x4208, 0xa006, 0x2020, 0x2009,
-	0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195, 0x2102,
-	0x2019, 0x002a, 0x2009, 0x0000, 0x1078, 0x27e2, 0x047f, 0x017f,
-	0x007c, 0x007e, 0x2001, 0xa30c, 0x2004, 0xd09c, 0x0040, 0x4218,
-	0x007f, 0x007c, 0x007e, 0x017e, 0x127e, 0x2091, 0x8000, 0x2001,
-	0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x127f, 0x017f, 0x007f,
-	0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009, 0xa434, 0xa006, 0x200a,
-	0x8108, 0x00f0, 0x422f, 0x157f, 0x007c, 0x0d7e, 0x037e, 0x157e,
-	0x137e, 0x147e, 0x2069, 0xa351, 0xa006, 0x6002, 0x6007, 0x0707,
-	0x600a, 0x600e, 0x6012, 0xa198, 0x293f, 0x231c, 0xa39c, 0x00ff,
-	0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9,
-	0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e,
-	0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a, 0x606e,
-	0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a, 0x608e,
-	0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x0d7e, 0x60a4,
-	0xa06d, 0x0040, 0x4275, 0x1078, 0x139a, 0x60a7, 0x0000, 0x60a8,
-	0xa06d, 0x0040, 0x427d, 0x1078, 0x139a, 0x60ab, 0x0000, 0x0d7f,
-	0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084,
-	0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082,
-	0x4000, 0x00c8, 0x4361, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
-	0x00c8, 0x4367, 0x2001, 0xa30c, 0x2004, 0xa084, 0x0003, 0x0040,
-	0x42c2, 0x2001, 0xa30c, 0x2004, 0xd084, 0x00c0, 0x4342, 0xa188,
-	0xa434, 0x2104, 0xa065, 0x0040, 0x4342, 0x6004, 0xa084, 0x00ff,
-	0xa08e, 0x0006, 0x00c0, 0x4342, 0x6000, 0xd0c4, 0x0040, 0x4342,
-	0x0078, 0x42cf, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4326,
-	0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x432c, 0x60a4,
-	0xa00d, 0x0040, 0x42d7, 0x1078, 0x4749, 0x0040, 0x4320, 0x60a8,
-	0xa00d, 0x0040, 0x42f1, 0x1078, 0x479a, 0x00c0, 0x42f1, 0x694c,
-	0xd1fc, 0x00c0, 0x42e7, 0x1078, 0x441c, 0x0078, 0x431b, 0x1078,
-	0x43d6, 0x694c, 0xd1ec, 0x00c0, 0x431b, 0x1078, 0x460a, 0x0078,
-	0x431b, 0x694c, 0xa184, 0xa000, 0x0040, 0x430b, 0xd1ec, 0x0040,
-	0x4304, 0xd1fc, 0x0040, 0x4300, 0x1078, 0x461b, 0x0078, 0x4307,
-	0x1078, 0x461b, 0x0078, 0x430b, 0xd1fc, 0x0040, 0x430b, 0x1078,
-	0x43d6, 0x0078, 0x431b, 0x6050, 0xa00d, 0x0040, 0x4316, 0x2d00,
-	0x200a, 0x6803, 0x0000, 0x6052, 0x0078, 0x431b, 0x2d00, 0x6052,
-	0x604e, 0x6803, 0x0000, 0x1078, 0x5c17, 0xa006, 0x127f, 0x007c,
-	0x2001, 0x0005, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001, 0x0028,
-	0x2009, 0x0000, 0x0078, 0x436b, 0xa082, 0x0006, 0x00c8, 0x4342,
-	0x60a0, 0xd0bc, 0x00c0, 0x433e, 0x6100, 0xd1fc, 0x0040, 0x42cf,
-	0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x436b, 0x2001, 0x0028,
-	0x0078, 0x435d, 0x2009, 0xa30c, 0x210c, 0xd18c, 0x0040, 0x434c,
-	0x2001, 0x0004, 0x0078, 0x435d, 0xd184, 0x0040, 0x4353, 0x2001,
-	0x0004, 0x0078, 0x435d, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0040,
-	0x435d, 0x2009, 0x1000, 0x0078, 0x436b, 0x2009, 0x0000, 0x0078,
-	0x436b, 0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x436b, 0x2001,
-	0x0029, 0x2009, 0x0000, 0xa005, 0x127f, 0x007c, 0x6944, 0x6e48,
-	0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x43bb, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x00ff, 0x00c8, 0x43a1, 0xa188, 0xa434, 0x2104,
-	0xa065, 0x0040, 0x43a1, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
-	0x00c0, 0x43a7, 0x684c, 0xd0ec, 0x0040, 0x4394, 0x1078, 0x461b,
-	0x1078, 0x43d6, 0x0078, 0x439c, 0x1078, 0x43d6, 0x684c, 0xd0fc,
-	0x0040, 0x439c, 0x1078, 0x460a, 0x1078, 0x4663, 0xa006, 0x0078,
-	0x43bf, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x43bf, 0xa082,
-	0x0006, 0x00c8, 0x43b5, 0x6100, 0xd1fc, 0x0040, 0x438a, 0x2001,
-	0x0029, 0x2009, 0x1000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009,
-	0x0000, 0x0078, 0x43bf, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040, 0x43cf,
-	0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c, 0x2d00,
-	0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x43cd, 0x127e, 0x2091,
-	0x8000, 0x604c, 0xa005, 0x0040, 0x43ec, 0x0e7e, 0x2071, 0xa5ab,
-	0x7004, 0xa086, 0x0002, 0x0040, 0x43f3, 0x0e7f, 0x604c, 0x6802,
-	0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803,
-	0x0000, 0x0078, 0x43ea, 0x701c, 0xac06, 0x00c0, 0x43e5, 0x604c,
-	0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x0e7f, 0x127f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040, 0x440e, 0x6800,
-	0xa005, 0x00c0, 0x440c, 0x6052, 0x604e, 0xad05, 0x127f, 0x007c,
-	0x604c, 0xa06d, 0x0040, 0x441b, 0x6800, 0xa005, 0x00c0, 0x4419,
-	0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000, 0x6084, 0xa00d,
-	0x0040, 0x4426, 0x2d00, 0x200a, 0x6086, 0x007c, 0x2d00, 0x6086,
-	0x6082, 0x0078, 0x4425, 0x127e, 0x0c7e, 0x027e, 0x2091, 0x8000,
-	0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x4439, 0xc285, 0x0078,
-	0x443a, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f, 0x007c, 0x127e,
-	0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086,
-	0x0006, 0x00c0, 0x445e, 0x609c, 0xd0ac, 0x0040, 0x445e, 0x2001,
-	0xa352, 0x2004, 0xd0a4, 0x0040, 0x445e, 0xa284, 0xff00, 0x8007,
-	0xa086, 0x0007, 0x00c0, 0x445e, 0x2011, 0x0600, 0x007f, 0xa294,
-	0xff00, 0xa215, 0x6206, 0x007e, 0xa086, 0x0006, 0x00c0, 0x446e,
-	0x6290, 0x82ff, 0x00c0, 0x446e, 0x1078, 0x1328, 0x007f, 0x0c7f,
-	0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260,
-	0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4490, 0x609c, 0xd0a4,
-	0x0040, 0x4490, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x4490,
-	0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0, 0x4490, 0x2011, 0x0006,
-	0x007f, 0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f,
-	0x007c, 0x027e, 0xa182, 0x00ff, 0x0048, 0x44a2, 0xa085, 0x0001,
-	0x0078, 0x44ba, 0xa190, 0xa434, 0x2204, 0xa065, 0x00c0, 0x44b9,
-	0x017e, 0x0d7e, 0x1078, 0x1366, 0x2d60, 0x0d7f, 0x017f, 0x0040,
-	0x449e, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab, 0x0000, 0x1078,
-	0x4235, 0xa006, 0x027f, 0x007c, 0x127e, 0x2091, 0x8000, 0x027e,
-	0xa182, 0x00ff, 0x0048, 0x44c8, 0xa085, 0x0001, 0x0078, 0x44fe,
-	0x0d7e, 0xa190, 0xa434, 0x2204, 0xa06d, 0x0040, 0x44fc, 0x2013,
-	0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4, 0xa06d, 0x0040, 0x44da,
-	0x1078, 0x139a, 0x60a8, 0xa06d, 0x0040, 0x44e0, 0x1078, 0x139a,
-	0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac, 0x2060, 0x8cff, 0x0040,
-	0x44f8, 0x600c, 0x007e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
-	0x44f3, 0x1078, 0x13aa, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x44e6,
-	0x0c7f, 0x0d7f, 0x1078, 0x139a, 0x0d7f, 0xa006, 0x027f, 0x127f,
-	0x007c, 0x017e, 0xa182, 0x00ff, 0x0048, 0x450a, 0xa085, 0x0001,
-	0x0078, 0x4511, 0xa188, 0xa434, 0x2104, 0xa065, 0x0040, 0x4506,
-	0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x600b,
-	0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x2069, 0xa88e,
-	0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0048, 0x4529,
-	0x603a, 0x6814, 0x6066, 0x2099, 0xa896, 0xac88, 0x000a, 0x21a0,
-	0x20a9, 0x0004, 0x53a3, 0x2099, 0xa89a, 0xac88, 0x0006, 0x21a0,
-	0x20a9, 0x0004, 0x53a3, 0x2069, 0xa8ae, 0x6808, 0x606a, 0x690c,
-	0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x00c8,
-	0x454d, 0x2009, 0x0008, 0x0078, 0x4577, 0xa182, 0x0259, 0x00c8,
-	0x4555, 0x2009, 0x0007, 0x0078, 0x4577, 0xa182, 0x02c1, 0x00c8,
-	0x455d, 0x2009, 0x0006, 0x0078, 0x4577, 0xa182, 0x0349, 0x00c8,
-	0x4565, 0x2009, 0x0005, 0x0078, 0x4577, 0xa182, 0x0421, 0x00c8,
-	0x456d, 0x2009, 0x0004, 0x0078, 0x4577, 0xa182, 0x0581, 0x00c8,
-	0x4575, 0x2009, 0x0003, 0x0078, 0x4577, 0x2009, 0x0002, 0x6192,
-	0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x017e, 0x027e, 0x0e7e,
-	0x2071, 0xa88d, 0x2e04, 0x6896, 0x2071, 0xa88e, 0x7004, 0x689a,
-	0x701c, 0x689e, 0x6a00, 0x2009, 0xa371, 0x210c, 0xd0bc, 0x0040,
-	0x4597, 0xd1ec, 0x0040, 0x4597, 0xc2ad, 0x0078, 0x4598, 0xc2ac,
-	0xd0c4, 0x0040, 0x45a1, 0xd1e4, 0x0040, 0x45a1, 0xc2bd, 0x0078,
-	0x45a2, 0xc2bc, 0x6a02, 0x0e7f, 0x027f, 0x017f, 0x007c, 0x0d7e,
-	0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x0040, 0x45cb, 0x6900,
-	0x81ff, 0x00c0, 0x45df, 0x6a04, 0xa282, 0x0010, 0x00c8, 0x45e4,
-	0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040,
-	0x45c6, 0x8108, 0x00f0, 0x45bc, 0x1078, 0x1328, 0x260a, 0x8210,
-	0x6a06, 0x0078, 0x45df, 0x1078, 0x1381, 0x0040, 0x45e4, 0x2d00,
-	0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
-	0xffff, 0x8108, 0x00f0, 0x45d7, 0x6807, 0x0001, 0x6e12, 0xa085,
-	0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x45e1, 0x127e,
-	0x2091, 0x8000, 0x0d7e, 0x60a4, 0xa00d, 0x0040, 0x4607, 0x2168,
-	0x6800, 0xa005, 0x00c0, 0x4603, 0x1078, 0x4749, 0x00c0, 0x4607,
-	0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0048, 0x4603, 0x8001,
-	0x6806, 0x0078, 0x4607, 0x1078, 0x139a, 0x60a7, 0x0000, 0x0d7f,
-	0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x47af, 0x0078,
-	0x4613, 0x1078, 0x43c1, 0x1078, 0x46a7, 0x00c0, 0x4611, 0x1078,
-	0x4663, 0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a8,
-	0xa06d, 0x0040, 0x463f, 0x6950, 0x81ff, 0x00c0, 0x4653, 0x6a54,
-	0xa282, 0x0010, 0x00c8, 0x4660, 0xad88, 0x0018, 0x20a9, 0x0010,
-	0x2104, 0xa086, 0xffff, 0x0040, 0x463a, 0x8108, 0x00f0, 0x4630,
-	0x1078, 0x1328, 0x260a, 0x8210, 0x6a56, 0x0078, 0x4653, 0x1078,
-	0x1381, 0x0040, 0x4660, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88,
-	0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x464b,
-	0x6857, 0x0001, 0x6e62, 0x0078, 0x4657, 0x1078, 0x441c, 0x1078,
-	0x466d, 0x00c0, 0x4655, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c,
-	0xa006, 0x0078, 0x465d, 0x127e, 0x2091, 0x8000, 0x1078, 0x5c17,
-	0x127f, 0x007c, 0xa01e, 0x0078, 0x466f, 0x2019, 0x0001, 0xa00e,
-	0x127e, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0,
-	0x468d, 0x8dff, 0x0040, 0x46a2, 0x83ff, 0x0040, 0x4685, 0x6848,
-	0xa606, 0x0040, 0x4692, 0x0078, 0x468d, 0x683c, 0xa406, 0x00c0,
-	0x468d, 0x6840, 0xa506, 0x0040, 0x4692, 0x2d08, 0x6800, 0x2068,
-	0x0078, 0x4679, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x469a, 0x624e,
-	0x0078, 0x469d, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x46a2,
-	0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x46a9, 0x2019,
-	0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x46d5, 0x83ff,
-	0x0040, 0x46b8, 0x6848, 0xa606, 0x0040, 0x46c5, 0x0078, 0x46c0,
-	0x683c, 0xa406, 0x00c0, 0x46c0, 0x6840, 0xa506, 0x0040, 0x46c5,
-	0x2d08, 0x6800, 0x2068, 0x0078, 0x46ac, 0x6a00, 0x6080, 0xad06,
-	0x00c0, 0x46cd, 0x6282, 0x0078, 0x46d0, 0xa180, 0x0000, 0x2202,
-	0x82ff, 0x00c0, 0x46d5, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078,
-	0x4742, 0x00c0, 0x46dd, 0x2011, 0x0001, 0x1078, 0x4793, 0x00c0,
-	0x46e3, 0xa295, 0x0002, 0x007c, 0x1078, 0x47cb, 0x0040, 0x46ec,
-	0x1078, 0x8b12, 0x0078, 0x46ee, 0xa085, 0x0001, 0x007c, 0x1078,
-	0x47cb, 0x0040, 0x46f7, 0x1078, 0x8aaa, 0x0078, 0x46f9, 0xa085,
-	0x0001, 0x007c, 0x1078, 0x47cb, 0x0040, 0x4702, 0x1078, 0x8af4,
-	0x0078, 0x4704, 0xa085, 0x0001, 0x007c, 0x1078, 0x47cb, 0x0040,
-	0x470d, 0x1078, 0x8ac6, 0x0078, 0x470f, 0xa085, 0x0001, 0x007c,
-	0x1078, 0x47cb, 0x0040, 0x4718, 0x1078, 0x8b30, 0x0078, 0x471a,
-	0xa085, 0x0001, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000,
-	0x6080, 0xa06d, 0x0040, 0x473a, 0x6800, 0x007e, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x007e, 0x6000, 0xd0fc,
-	0x0040, 0x4734, 0x1078, 0xa18c, 0x007f, 0x1078, 0x4982, 0x007f,
-	0x0078, 0x4721, 0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f,
-	0x127f, 0x007c, 0x60a4, 0xa00d, 0x00c0, 0x4749, 0xa085, 0x0001,
-	0x007c, 0x0e7e, 0x2170, 0x7000, 0xa005, 0x00c0, 0x475c, 0x20a9,
-	0x0010, 0xae88, 0x0004, 0x2104, 0xa606, 0x0040, 0x475c, 0x8108,
-	0x00f0, 0x4753, 0xa085, 0x0001, 0xa006, 0x0e7f, 0x007c, 0x0d7e,
-	0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x476d, 0x1078,
-	0x1381, 0x0040, 0x477f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807,
-	0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
-	0x00f0, 0x4775, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
-	0x0078, 0x477c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d,
-	0x0040, 0x4790, 0x60a7, 0x0000, 0x1078, 0x139a, 0xa085, 0x0001,
-	0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x479a, 0xa085,
-	0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x47ad,
-	0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x47ad,
-	0x8108, 0x00f0, 0x47a4, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x4793, 0x00c0, 0x47c9, 0x200b, 0xffff,
-	0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x47c4,
-	0x8001, 0x6856, 0x0078, 0x47c8, 0x1078, 0x139a, 0x60ab, 0x0000,
-	0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71ac,
-	0x81ff, 0x00c0, 0x47e9, 0x71c8, 0xd19c, 0x0040, 0x47e9, 0x2001,
-	0x007e, 0xa080, 0xa434, 0x2004, 0xa07d, 0x0040, 0x47e9, 0x7804,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x47e9, 0x7800, 0xc0ed,
-	0x7802, 0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x480f, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501,
-	0x00c0, 0x4809, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
-	0x0040, 0x4806, 0xa086, 0x0006, 0x00c0, 0x4809, 0x6000, 0xc0ed,
-	0x6002, 0x017f, 0x8108, 0x00f0, 0x47f5, 0x0c7f, 0x157f, 0x1078,
-	0x4897, 0x0040, 0x4818, 0x2001, 0xa59f, 0x200c, 0x0078, 0x4820,
-	0x2079, 0xa351, 0x7804, 0xd0a4, 0x0040, 0x4824, 0x2009, 0x07d0,
-	0x2011, 0x4826, 0x1078, 0x596c, 0x0f7f, 0x007c, 0x2011, 0x4826,
-	0x1078, 0x58d4, 0x1078, 0x4897, 0x0040, 0x484e, 0x2001, 0xa4b2,
-	0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa352,
-	0x2004, 0xd0a4, 0x0040, 0x4842, 0x2009, 0x07d0, 0x2011, 0x4826,
-	0x1078, 0x596c, 0x0e7e, 0x2071, 0xa300, 0x706b, 0x0000, 0x706f,
-	0x0000, 0x1078, 0x260d, 0x0e7f, 0x0078, 0x4886, 0x157e, 0x0c7e,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x4501, 0x00c0,
-	0x4880, 0x6000, 0xd0ec, 0x0040, 0x4880, 0x047e, 0x62a0, 0xa294,
-	0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6000,
-	0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700,
-	0x6006, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000,
-	0x1078, 0x5c78, 0x2009, 0x0000, 0x1078, 0x9c38, 0x077f, 0x047f,
-	0x017f, 0x8108, 0x00f0, 0x4854, 0x0c7f, 0x157f, 0x007c, 0x0c7e,
-	0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818,
-	0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e,
-	0x2001, 0xa4b2, 0x2004, 0xa07d, 0x0040, 0x48a0, 0x7800, 0xd0ec,
-	0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x6200, 0xa005,
-	0x0040, 0x48ad, 0xc2fd, 0x0078, 0x48ae, 0xc2fc, 0x6202, 0x027f,
-	0x127f, 0x007c, 0x2071, 0xa413, 0x7003, 0x0001, 0x7007, 0x0000,
-	0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000,
-	0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b, 0x0020,
-	0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa57c, 0x7003, 0xa413,
-	0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa55c, 0x7013, 0x0020,
-	0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e, 0x2071,
-	0xa534, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001, 0xa352,
-	0x2004, 0xd0fc, 0x00c0, 0x48f7, 0x2001, 0xa352, 0x2004, 0xa00e,
-	0xd09c, 0x0040, 0x48f4, 0x8108, 0x7102, 0x0078, 0x494a, 0x2001,
-	0xa371, 0x200c, 0xa184, 0x000f, 0x2009, 0xa372, 0x210c, 0x0079,
-	0x4901, 0x48ec, 0x4922, 0x492a, 0x4935, 0x493b, 0x48ec, 0x48ec,
-	0x48ec, 0x4911, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec, 0x48ec,
-	0x48ec, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099, 0xa375,
-	0x20a1, 0xa585, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f, 0x137f,
-	0x0078, 0x494a, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002,
-	0x0078, 0x4930, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003,
-	0x7002, 0x7097, 0x0001, 0x0078, 0x4947, 0x7007, 0x0122, 0x2001,
-	0x0002, 0x0078, 0x493f, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002,
-	0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a, 0xa184,
-	0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071, 0xa413,
-	0x684c, 0xa005, 0x00c0, 0x495b, 0x7028, 0xc085, 0x702a, 0xa085,
-	0x0001, 0x0078, 0x4980, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868,
-	0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844,
-	0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006,
-	0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
-	0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
-	0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0, 0x49d8,
-	0x6804, 0xa00d, 0x0040, 0x499e, 0x0d7e, 0x2071, 0xa300, 0xa016,
-	0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x00c0,
-	0x4991, 0x702e, 0x70a8, 0xa200, 0x70aa, 0x0d7f, 0x2071, 0xa413,
-	0x701c, 0xa005, 0x00c0, 0x49ea, 0x0068, 0x49e8, 0x2071, 0xa534,
-	0x7200, 0x82ff, 0x0040, 0x49e8, 0x6934, 0xa186, 0x0103, 0x00c0,
-	0x49fb, 0x6948, 0x6844, 0xa105, 0x00c0, 0x49db, 0x2009, 0x8020,
-	0x2200, 0x0079, 0x49bb, 0x49e8, 0x49c0, 0x4a18, 0x4a26, 0x49e8,
-	0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x49e8, 0x7122, 0x683c,
-	0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x2071,
-	0xa300, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70a8, 0x8000, 0x70aa,
-	0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0, 0x49e8,
-	0x6868, 0xa005, 0x00c0, 0x49e8, 0x2009, 0x8020, 0x0078, 0x49b8,
-	0x2071, 0xa413, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012,
-	0x7018, 0xa06d, 0x711a, 0x0040, 0x49f8, 0x6902, 0x0078, 0x49f9,
-	0x711e, 0x0078, 0x49d8, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040,
-	0x4a09, 0xa186, 0x001e, 0x0040, 0x4a09, 0xa18e, 0x001f, 0x00c0,
-	0x49e8, 0x684c, 0xd0cc, 0x0040, 0x49e8, 0x6850, 0xa084, 0x00ff,
-	0xa086, 0x0001, 0x00c0, 0x49e8, 0x2009, 0x8021, 0x0078, 0x49b8,
-	0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x49e8, 0x7186, 0xae90,
-	0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4a36, 0x7084, 0x8008,
-	0xa092, 0x000f, 0x00c8, 0x49e8, 0x7186, 0xae90, 0x0003, 0x8003,
-	0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
-	0x0048, 0x49cf, 0x718c, 0x7084, 0xa10a, 0x0048, 0x49cf, 0x2071,
-	0x0000, 0x7018, 0xd084, 0x00c0, 0x49cf, 0x2071, 0xa534, 0x7000,
-	0xa086, 0x0002, 0x00c0, 0x4a56, 0x1078, 0x4cd2, 0x2071, 0x0000,
-	0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf, 0x1078, 0x4cfd,
-	0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x49cf,
-	0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
-	0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084, 0x00ff,
-	0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa413, 0x7004,
-	0x0079, 0x4a7a, 0x4a84, 0x4a95, 0x4ca3, 0x4ca4, 0x4ccb, 0x4cd1,
-	0x4a85, 0x4c91, 0x4c32, 0x4cb4, 0x007c, 0x127e, 0x2091, 0x8000,
-	0x0068, 0x4a94, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080,
-	0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa5be, 0x6844,
-	0xa005, 0x0050, 0x4abd, 0x00c0, 0x4abd, 0x127e, 0x2091, 0x8000,
-	0x2069, 0x0000, 0x6934, 0x2001, 0xa41f, 0x2004, 0xa10a, 0x0040,
-	0x4ab8, 0x0068, 0x4abc, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
-	0x4abc, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080,
-	0x2069, 0xa5be, 0x6847, 0xffff, 0x127f, 0x2069, 0xa300, 0x6844,
-	0x6960, 0xa102, 0x2069, 0xa534, 0x688a, 0x6984, 0x701c, 0xa06d,
-	0x0040, 0x4acf, 0x81ff, 0x0040, 0x4b17, 0x0078, 0x4ae5, 0x81ff,
-	0x0040, 0x4be9, 0x2071, 0xa534, 0x7184, 0x7088, 0xa10a, 0x00c8,
-	0x4ae5, 0x7190, 0x2071, 0xa5be, 0x7040, 0xa005, 0x0040, 0x4ae5,
-	0x00d0, 0x4be9, 0x7142, 0x0078, 0x4be9, 0x2071, 0xa534, 0x718c,
-	0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4c06, 0x0068,
-	0x4b9b, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4b9b, 0x2001,
-	0xffff, 0x2071, 0xa5be, 0x7042, 0x2071, 0xa534, 0x7000, 0xa086,
-	0x0002, 0x00c0, 0x4b0d, 0x1078, 0x4cd2, 0x2071, 0x0000, 0x701b,
-	0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x1078, 0x4cfd, 0x2071,
-	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4b9b, 0x2071,
-	0xa534, 0x7000, 0xa005, 0x0040, 0x4bc8, 0x6934, 0xa186, 0x0103,
-	0x00c0, 0x4b9e, 0x684c, 0xd0bc, 0x00c0, 0x4bc8, 0x6948, 0x6844,
-	0xa105, 0x00c0, 0x4bbb, 0x2009, 0x8020, 0x2071, 0xa534, 0x7000,
-	0x0079, 0x4b32, 0x4bc8, 0x4b80, 0x4b58, 0x4b6a, 0x4b37, 0x137e,
-	0x147e, 0x157e, 0x2099, 0xa375, 0x20a1, 0xa585, 0x20a9, 0x0004,
-	0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa57c, 0xad80, 0x000f,
-	0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000, 0x2e10,
-	0x1078, 0x13d1, 0x2071, 0xa413, 0x7007, 0x0009, 0x0078, 0x4be9,
-	0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4be9, 0xae90, 0x0003,
-	0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b,
-	0x0078, 0x4be9, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8, 0x4be9,
-	0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840,
-	0x2012, 0x7186, 0x2071, 0xa413, 0x1078, 0x4d5b, 0x0078, 0x4be9,
-	0x127e, 0x2091, 0x8000, 0x0068, 0x4b9b, 0x2071, 0x0000, 0x7018,
-	0xd084, 0x00c0, 0x4b9b, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
-	0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa413, 0x1078,
-	0x4d5b, 0x0078, 0x4be9, 0x127f, 0x0078, 0x4be9, 0xa18c, 0x00ff,
-	0xa186, 0x0017, 0x0040, 0x4bac, 0xa186, 0x001e, 0x0040, 0x4bac,
-	0xa18e, 0x001f, 0x00c0, 0x4bc8, 0x684c, 0xd0cc, 0x0040, 0x4bc8,
-	0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4bc8, 0x2009,
-	0x8021, 0x0078, 0x4b2d, 0x6844, 0xa086, 0x0100, 0x00c0, 0x4bc8,
-	0x6868, 0xa005, 0x00c0, 0x4bc8, 0x2009, 0x8020, 0x0078, 0x4b2d,
-	0x2071, 0xa413, 0x1078, 0x4d6f, 0x0040, 0x4be9, 0x2071, 0xa413,
-	0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x00c0,
-	0x4be0, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4be0, 0x710e,
-	0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100, 0x0040,
-	0x4ca4, 0x127e, 0x2091, 0x8000, 0x2071, 0xa413, 0x7008, 0xa086,
-	0x0001, 0x00c0, 0x4c04, 0x0068, 0x4c04, 0x2009, 0x000d, 0x7030,
-	0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
-	0x00c0, 0x4c04, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071, 0xa413,
-	0x1078, 0x4d6f, 0x0040, 0x4c2f, 0x2071, 0xa534, 0x7084, 0x700a,
-	0x20a9, 0x0020, 0x2099, 0xa535, 0x20a1, 0xa55c, 0x53a3, 0x7087,
-	0x0000, 0x2071, 0xa413, 0x2069, 0xa57c, 0x706c, 0x6826, 0x7070,
-	0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078, 0x13d1,
-	0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa5be, 0x7042, 0x127f,
-	0x0078, 0x4be9, 0x2069, 0xa57c, 0x6808, 0xa08e, 0x0000, 0x0040,
-	0x4c90, 0xa08e, 0x0200, 0x0040, 0x4c8e, 0xa08e, 0x0100, 0x00c0,
-	0x4c90, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8b, 0x2069, 0x0000,
-	0x6818, 0xd084, 0x00c0, 0x4c8b, 0x702c, 0x7130, 0x8108, 0xa102,
-	0x0048, 0x4c59, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0078,
-	0x4c63, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4c63, 0x7070,
-	0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001,
-	0xa559, 0x2004, 0xa005, 0x00c0, 0x4c82, 0x6934, 0x2069, 0xa534,
-	0x689c, 0x699e, 0x2069, 0xa5be, 0xa102, 0x00c0, 0x4c7b, 0x6844,
-	0xa005, 0x00d0, 0x4c89, 0x2001, 0xa55a, 0x200c, 0x810d, 0x6946,
-	0x0078, 0x4c89, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091,
-	0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4c90, 0x7007, 0x0005,
-	0x007c, 0x701c, 0xa06d, 0x0040, 0x4ca2, 0x1078, 0x4d6f, 0x0040,
-	0x4ca2, 0x7007, 0x0003, 0x1078, 0x4d8f, 0x7050, 0xa086, 0x0100,
-	0x0040, 0x4ca4, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100, 0x00c0,
-	0x4cad, 0x7007, 0x0004, 0x0078, 0x4ccb, 0xa086, 0x0200, 0x00c0,
-	0x4cb3, 0x7007, 0x0005, 0x007c, 0x2001, 0xa57e, 0x2004, 0xa08e,
-	0x0100, 0x00c0, 0x4cc0, 0x7007, 0x0001, 0x1078, 0x4d5b, 0x007c,
-	0xa08e, 0x0000, 0x0040, 0x4cbf, 0xa08e, 0x0200, 0x00c0, 0x4cbf,
-	0x7007, 0x0005, 0x007c, 0x1078, 0x4d25, 0x7006, 0x1078, 0x4d5b,
-	0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa534, 0x7184, 0x81ff,
-	0x0040, 0x4cfa, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000,
-	0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x722a,
-	0x8000, 0x0070, 0x4cf7, 0x2014, 0x722e, 0x8000, 0x0070, 0x4cf7,
-	0x2014, 0x723a, 0x8000, 0x0070, 0x4cf7, 0x2014, 0x723e, 0xa180,
-	0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e, 0x2071,
-	0xa534, 0x7184, 0x81ff, 0x0040, 0x4d22, 0xa006, 0x7086, 0xae80,
-	0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014,
-	0x722a, 0x8000, 0x0070, 0x4d1b, 0x2014, 0x723a, 0x8000, 0x2014,
-	0x723e, 0x0078, 0x4d1f, 0x2001, 0x8020, 0x0078, 0x4d21, 0x2001,
-	0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0048, 0x4d32, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
-	0x0078, 0x4d3c, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d3c,
-	0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
-	0x00c0, 0x4d52, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d55, 0x2001,
-	0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b, 0x0000,
-	0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x700b,
-	0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d6e, 0x127e,
-	0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e, 0xa005,
-	0x00c0, 0x4d6b, 0x701a, 0x127f, 0x1078, 0x139a, 0x007c, 0x2019,
-	0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4d7e, 0x2304, 0x230c,
-	0xa10e, 0x0040, 0x4d7e, 0xa006, 0x0078, 0x4d8e, 0x732c, 0x8319,
-	0x7130, 0xa102, 0x00c0, 0x4d88, 0x2300, 0xa005, 0x0078, 0x4d8e,
-	0x0048, 0x4d8d, 0xa302, 0x0078, 0x4d8e, 0x8002, 0x007c, 0x2d00,
-	0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e, 0x2091,
-	0x8000, 0x2009, 0xa5d0, 0x2104, 0xc08d, 0x200a, 0x127f, 0x1078,
-	0x13eb, 0x007c, 0x2071, 0xa3e1, 0x7003, 0x0000, 0x7007, 0x0000,
-	0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001,
-	0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000,
-	0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa3e1,
-	0x6848, 0xa005, 0x00c0, 0x4dcb, 0x7028, 0xc085, 0x702a, 0xa085,
-	0x0001, 0x0078, 0x4df0, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858,
-	0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840,
-	0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c,
-	0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376,
-	0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006,
-	0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa3e1, 0x7004, 0x1079, 0x4e50,
-	0x700c, 0x0079, 0x4dfb, 0x4e00, 0x4df5, 0x4df5, 0x4df5, 0x4df5,
-	0x007c, 0x700c, 0x0079, 0x4e04, 0x4e09, 0x4e4e, 0x4e4e, 0x4e4f,
-	0x4e4f, 0x7830, 0x7930, 0xa106, 0x0040, 0x4e13, 0x7830, 0x7930,
-	0xa106, 0x00c0, 0x4e39, 0x7030, 0xa10a, 0x0040, 0x4e39, 0x00c8,
-	0x4e1b, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4e3a, 0x1078,
-	0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001,
-	0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000, 0x2009,
-	0xa5d0, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f, 0x1078,
-	0x13eb, 0x007c, 0x1078, 0x1366, 0x0040, 0x4e39, 0x2d00, 0x705a,
-	0x1078, 0x1366, 0x00c0, 0x4e46, 0x0078, 0x4e25, 0x2d00, 0x7086,
-	0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4e29, 0x007c, 0x007c,
-	0x4e61, 0x4e62, 0x4e99, 0x4e9a, 0x4e4e, 0x4ed0, 0x4ed5, 0x4f0c,
-	0x4f0d, 0x4f28, 0x4f29, 0x4f2a, 0x4f2b, 0x4f2c, 0x4f2d, 0x4fad,
-	0x4fd7, 0x007c, 0x700c, 0x0079, 0x4e65, 0x4e6a, 0x4e6d, 0x4e7d,
-	0x4e98, 0x4e98, 0x1078, 0x4e01, 0x007c, 0x127e, 0x8001, 0x700e,
-	0x7058, 0x007e, 0x1078, 0x5348, 0x0040, 0x4e7a, 0x2091, 0x8000,
-	0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4e86, 0x127e, 0x8001, 0x700e,
-	0x1078, 0x5348, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000,
-	0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x00c8,
-	0x4e95, 0x1079, 0x4eb0, 0x127f, 0x007c, 0x127f, 0x1078, 0x4f2e,
-	0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa3e1, 0x700c, 0x0079,
-	0x4ea1, 0x4ea6, 0x4ea6, 0x4ea6, 0x4ea8, 0x4eac, 0x0e7f, 0x007c,
-	0x700f, 0x0001, 0x0078, 0x4eae, 0x700f, 0x0002, 0x0e7f, 0x007c,
-	0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x5080, 0x4f2e, 0x4f2e, 0x4f2e,
-	0x4f2e, 0x4f2e, 0x4f4a, 0x50ca, 0x5117, 0x5170, 0x5186, 0x4f2e,
-	0x4f2e, 0x4f66, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f87, 0x5245, 0x5263,
-	0x4f2e, 0x4f66, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f7c, 0x5263,
-	0x7020, 0x2068, 0x1078, 0x139a, 0x007c, 0x700c, 0x0079, 0x4ed8,
-	0x4edd, 0x4ee0, 0x4ef0, 0x4f0b, 0x4f0b, 0x1078, 0x4e01, 0x007c,
-	0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5348, 0x0040,
-	0x4eed, 0x2091, 0x8000, 0x1078, 0x4e01, 0x0d7f, 0x0078, 0x4ef9,
-	0x127e, 0x8001, 0x700e, 0x1078, 0x5348, 0x7058, 0x2068, 0x7084,
-	0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
-	0xa08a, 0x001a, 0x00c8, 0x4f08, 0x1079, 0x4f0e, 0x127f, 0x007c,
-	0x127f, 0x1078, 0x4f2e, 0x007c, 0x007c, 0x007c, 0x4f2e, 0x4f4a,
-	0x506a, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
-	0x506a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f4a, 0x4f2e, 0x4f4a,
-	0x506a, 0x4f2e, 0x4f2e, 0x4f4a, 0x4f2e, 0x4f2e, 0x4f2e, 0x4f4a,
-	0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007, 0x0001,
-	0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4982, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
-	0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
-	0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed,
-	0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c,
-	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x4982, 0x127f, 0x007c, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x0040, 0x4f3c, 0x8001, 0x00c0, 0x4f73, 0x7007,
-	0x0001, 0x0078, 0x5049, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
-	0x701a, 0x704b, 0x5049, 0x007c, 0x684c, 0xa084, 0x00c0, 0xa086,
-	0x00c0, 0x00c0, 0x4f87, 0x7007, 0x0001, 0x0078, 0x5280, 0x2d00,
-	0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1,
-	0xa40c, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8, 0x4f58,
-	0x6884, 0xa08a, 0x0002, 0x00c8, 0x4f58, 0x82ff, 0x00c0, 0x4fa9,
-	0x6888, 0x698c, 0xa105, 0x0040, 0x4fa9, 0x2001, 0x5019, 0x0078,
-	0x4fac, 0xa280, 0x500f, 0x2004, 0x70c6, 0x7010, 0xa015, 0x0040,
-	0x4ff7, 0x1078, 0x1366, 0x00c0, 0x4fb8, 0x7007, 0x000f, 0x007c,
-	0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004, 0xad00,
-	0x7096, 0x6008, 0xa20a, 0x00c8, 0x4fc7, 0xa00e, 0x2200, 0x7112,
-	0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x4fd0, 0xa108,
-	0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13d1, 0x7090,
-	0xa08e, 0x0100, 0x0040, 0x4feb, 0xa086, 0x0200, 0x0040, 0x4fe3,
-	0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x139a, 0x7014,
-	0x2068, 0x0078, 0x4f58, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807,
-	0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x4fad, 0x7014,
-	0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x5006, 0x6888,
-	0x698c, 0xa105, 0x0040, 0x5006, 0x1078, 0x501d, 0x6834, 0xa084,
-	0x00ff, 0xa086, 0x001e, 0x0040, 0x5280, 0x0078, 0x5049, 0x5011,
-	0x5015, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005,
-	0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e, 0x0c7e,
-	0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021,
-	0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008, 0x7812,
-	0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0040,
-	0x503f, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x502c, 0x6004,
-	0xa065, 0x00c0, 0x5026, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f,
-	0x007c, 0x2009, 0xa32e, 0x210c, 0x81ff, 0x00c0, 0x5064, 0x6838,
-	0xa084, 0x00ff, 0x683a, 0x1078, 0x4290, 0x00c0, 0x5058, 0x007c,
-	0x1078, 0x4a60, 0x127e, 0x2091, 0x8000, 0x1078, 0x8cb8, 0x1078,
-	0x4982, 0x127f, 0x0078, 0x5057, 0x2001, 0x0028, 0x2009, 0x0000,
-	0x0078, 0x5058, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906, 0x711a,
-	0x7010, 0x8001, 0x7012, 0x0040, 0x5079, 0x7007, 0x0006, 0x0078,
-	0x507f, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a, 0x007c,
-	0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084,
-	0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x50a9, 0x2009,
-	0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x50a9, 0xa005,
-	0x00c0, 0x50bc, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x4501,
-	0x00c0, 0x50bc, 0x067e, 0x6e50, 0x1078, 0x45e7, 0x067f, 0x0078,
-	0x50bc, 0x047e, 0x2011, 0xa30c, 0x2224, 0xc484, 0xc48c, 0x2412,
-	0x047f, 0x0c7e, 0x1078, 0x4501, 0x00c0, 0x50b8, 0x1078, 0x4782,
-	0x8108, 0x00f0, 0x50b2, 0x0c7f, 0x684c, 0xd084, 0x00c0, 0x50c3,
-	0x1078, 0x139a, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4982,
-	0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001,
-	0xa352, 0x2004, 0xd0a4, 0x0040, 0x510e, 0x2061, 0xa62d, 0x6100,
-	0xd184, 0x0040, 0x50ee, 0x6858, 0xa084, 0x00ff, 0x00c0, 0x5111,
-	0x6000, 0xd084, 0x0040, 0x510e, 0x6004, 0xa005, 0x00c0, 0x5114,
-	0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x510b, 0x2011, 0x0001,
-	0x6860, 0xa005, 0x00c0, 0x50f6, 0x2001, 0x001e, 0x8000, 0x6016,
-	0x6858, 0xa084, 0x00ff, 0x0040, 0x510e, 0x6006, 0x6858, 0x8007,
-	0xa084, 0x00ff, 0x0040, 0x510e, 0x600a, 0x6858, 0x8000, 0x00c0,
-	0x510a, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5337, 0x127f, 0x0078,
-	0x532f, 0x127f, 0x0078, 0x5327, 0x127f, 0x0078, 0x532b, 0x127e,
-	0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa352, 0x2004, 0xd0a4,
-	0x0040, 0x516d, 0x2061, 0xa62d, 0x6000, 0xd084, 0x0040, 0x516d,
-	0x6204, 0x6308, 0xd08c, 0x00c0, 0x515f, 0x6c48, 0xa484, 0x0003,
-	0x0040, 0x5145, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x513e,
-	0x2100, 0xa210, 0x0048, 0x516a, 0x0078, 0x5145, 0x8001, 0x00c0,
-	0x516a, 0x2100, 0xa212, 0x0048, 0x516a, 0xa484, 0x000c, 0x0040,
-	0x515f, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
-	0x5157, 0x2100, 0xa318, 0x0048, 0x516a, 0x0078, 0x515f, 0xa082,
-	0x0004, 0x00c0, 0x516a, 0x2100, 0xa31a, 0x0048, 0x516a, 0x6860,
-	0xa005, 0x0040, 0x5165, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f,
-	0x0078, 0x5337, 0x127f, 0x0078, 0x5333, 0x127f, 0x0078, 0x532f,
-	0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xa62d, 0x6300,
-	0xd38c, 0x00c0, 0x5180, 0x6308, 0x8318, 0x0048, 0x5183, 0x630a,
-	0x127f, 0x0078, 0x5345, 0x127f, 0x0078, 0x5333, 0x127e, 0x0c7e,
-	0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040, 0x519a,
-	0x0c7e, 0x2061, 0xa62d, 0x6000, 0xa084, 0xfcff, 0x6002, 0x0c7f,
-	0x0078, 0x51c9, 0x6858, 0xa005, 0x0040, 0x51e0, 0x685c, 0xa065,
-	0x0040, 0x51dc, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x51ac,
-	0x1078, 0x8c01, 0x0078, 0x51ba, 0x6013, 0x0400, 0x6037, 0x0000,
-	0x694c, 0xd1a4, 0x0040, 0x51b6, 0x6950, 0x6136, 0x2009, 0x0041,
-	0x1078, 0x756c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x00c0,
-	0x51c9, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078, 0x5a6d,
-	0x027f, 0x684c, 0xd0c4, 0x0040, 0x51d8, 0x2061, 0xa62d, 0x6000,
-	0xd08c, 0x00c0, 0x51d8, 0x6008, 0x8000, 0x0048, 0x51dc, 0x600a,
-	0x0c7f, 0x127f, 0x0078, 0x5337, 0x0c7f, 0x127f, 0x0078, 0x532f,
-	0x6954, 0xa186, 0x0045, 0x0040, 0x5213, 0xa186, 0x002a, 0x00c0,
-	0x51f0, 0x2001, 0xa30c, 0x200c, 0xc194, 0x2102, 0x0078, 0x51c9,
-	0xa186, 0x0020, 0x0040, 0x5209, 0xa186, 0x0029, 0x0040, 0x51fc,
-	0xa186, 0x002d, 0x00c0, 0x51dc, 0x6944, 0xa18c, 0xff00, 0x810f,
-	0x1078, 0x4501, 0x00c0, 0x51c9, 0x6000, 0xc0e4, 0x6002, 0x0078,
-	0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x2001, 0xa5a1, 0x2004,
-	0x6016, 0x0078, 0x51c9, 0x685c, 0xa065, 0x0040, 0x51dc, 0x0e7e,
-	0x6860, 0xa075, 0x2001, 0xa32e, 0x2004, 0xa005, 0x0040, 0x522b,
-	0x1078, 0x8c01, 0x8eff, 0x0040, 0x5228, 0x2e60, 0x1078, 0x8c01,
-	0x0e7f, 0x0078, 0x51c9, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60,
-	0x6007, 0x003a, 0x6870, 0xa005, 0x0040, 0x523c, 0x6007, 0x003b,
-	0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x1078, 0x5bf8,
-	0x1078, 0x6109, 0x0e7f, 0x0078, 0x51c9, 0x2061, 0xa62d, 0x6000,
-	0xd084, 0x0040, 0x525f, 0xd08c, 0x00c0, 0x5345, 0x2091, 0x8000,
-	0x6204, 0x8210, 0x0048, 0x5259, 0x6206, 0x2091, 0x8001, 0x0078,
-	0x5345, 0x2091, 0x8001, 0x6853, 0x0016, 0x0078, 0x533e, 0x6853,
-	0x0007, 0x0078, 0x533e, 0x6834, 0x8007, 0xa084, 0x00ff, 0x00c0,
-	0x526d, 0x1078, 0x4f3c, 0x0078, 0x527f, 0x2030, 0x8001, 0x00c0,
-	0x5277, 0x7007, 0x0001, 0x1078, 0x5280, 0x0078, 0x527f, 0x7007,
-	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5280, 0x007c,
-	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2009, 0xa32e, 0x210c, 0x81ff,
-	0x00c0, 0x530b, 0x2009, 0xa30c, 0x210c, 0xd194, 0x00c0, 0x5315,
-	0x6848, 0x2070, 0xae82, 0xaa00, 0x0048, 0x52fb, 0x2001, 0xa315,
-	0x2004, 0xae02, 0x00c8, 0x52fb, 0x2061, 0xa62d, 0x6100, 0xa184,
-	0x0301, 0xa086, 0x0001, 0x00c0, 0x52de, 0x711c, 0xa186, 0x0006,
-	0x00c0, 0x52e6, 0x7018, 0xa005, 0x0040, 0x530b, 0x2004, 0xd0e4,
-	0x00c0, 0x530f, 0x7024, 0xd0dc, 0x00c0, 0x5319, 0x6853, 0x0000,
-	0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x00c0, 0x52ca, 0x7112,
-	0x684c, 0xd0f4, 0x00c0, 0x531d, 0x2e60, 0x1078, 0x59b6, 0x127f,
-	0x0e7f, 0x007c, 0x2068, 0x6800, 0xa005, 0x00c0, 0x52ca, 0x6902,
-	0x2168, 0x684c, 0xd0f4, 0x00c0, 0x531d, 0x127f, 0x0e7f, 0x007c,
-	0x127f, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x533e, 0xd184, 0x0040,
-	0x52d8, 0xd1c4, 0x00c0, 0x52ff, 0x0078, 0x5303, 0x6944, 0xa18c,
-	0xff00, 0x810f, 0x1078, 0x4501, 0x00c0, 0x530f, 0x6000, 0xd0e4,
-	0x00c0, 0x530f, 0x711c, 0xa186, 0x0007, 0x00c0, 0x52fb, 0x6853,
-	0x0002, 0x0078, 0x5311, 0x6853, 0x0008, 0x0078, 0x5311, 0x6853,
-	0x000e, 0x0078, 0x5311, 0x6853, 0x0017, 0x0078, 0x5311, 0x6853,
-	0x0035, 0x0078, 0x5311, 0x6853, 0x0028, 0x0078, 0x5311, 0x6853,
-	0x0029, 0x127f, 0x0e7f, 0x0078, 0x533e, 0x6853, 0x002a, 0x0078,
-	0x5311, 0x6853, 0x0045, 0x0078, 0x5311, 0x2e60, 0x2019, 0x0002,
-	0x6017, 0x0014, 0x1078, 0x9a6a, 0x127f, 0x0e7f, 0x007c, 0x2009,
-	0x003e, 0x0078, 0x5339, 0x2009, 0x0004, 0x0078, 0x5339, 0x2009,
-	0x0006, 0x0078, 0x5339, 0x2009, 0x0016, 0x0078, 0x5339, 0x2009,
-	0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x2091, 0x8000,
-	0x1078, 0x4982, 0x2091, 0x8001, 0x007c, 0x1078, 0x139a, 0x007c,
-	0x702c, 0x7130, 0x8108, 0xa102, 0x0048, 0x5355, 0xa00e, 0x7034,
-	0x7072, 0x7038, 0x7076, 0x0078, 0x5361, 0x7070, 0xa080, 0x0040,
-	0x7072, 0x00c8, 0x5361, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085,
-	0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e, 0x1078, 0x59ad, 0x0d7f,
-	0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012,
-	0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00,
-	0xa084, 0x7000, 0x0040, 0x5380, 0xa086, 0x1000, 0x00c0, 0x53ac,
-	0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217, 0xa084, 0xf000,
-	0xa086, 0x3000, 0x00c0, 0x5390, 0x1078, 0x5570, 0x0078, 0x53a7,
-	0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x5397, 0x3e60, 0xac84,
-	0x000f, 0x00c0, 0x53ac, 0xac82, 0xaa00, 0x0048, 0x53ac, 0x6854,
-	0xac02, 0x00c8, 0x53ac, 0x2009, 0x0047, 0x1078, 0x756c, 0x7a1c,
-	0xd284, 0x00c0, 0x5372, 0x007c, 0xa016, 0x1078, 0x15ec, 0x0078,
-	0x53a7, 0x0078, 0x53ac, 0x781c, 0xd08c, 0x0040, 0x53db, 0x157e,
-	0x137e, 0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076,
-	0x00c0, 0x53f1, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x53e0,
-	0x1078, 0x540c, 0x0040, 0x53f1, 0x20e1, 0x3000, 0x7828, 0x7828,
-	0x1078, 0x542a, 0x147f, 0x137f, 0x157f, 0x2009, 0xa5b3, 0x2104,
-	0xa005, 0x00c0, 0x53dc, 0x007c, 0x1078, 0x6109, 0x0078, 0x53db,
-	0xa484, 0x7000, 0x00c0, 0x53f1, 0x1078, 0x540c, 0x0040, 0x5403,
-	0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x53cc, 0x0078,
-	0x5403, 0x1078, 0xa1ee, 0xd5a4, 0x0040, 0x53ff, 0x1078, 0x1af7,
-	0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5407, 0x1078,
-	0x540c, 0x687f, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f,
-	0x137f, 0x157f, 0x0078, 0x53db, 0xa484, 0x01ff, 0x687e, 0xa005,
-	0x0040, 0x541e, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1,
-	0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c,
-	0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001,
-	0x0078, 0x541d, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
-	0xa196, 0x0000, 0x00c0, 0x5437, 0x0078, 0x567c, 0x007c, 0xa196,
-	0x2000, 0x00c0, 0x5448, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x5444,
-	0x1078, 0x3a43, 0x0078, 0x5436, 0x1078, 0x5450, 0x0078, 0x5436,
-	0xa196, 0x8000, 0x00c0, 0x5436, 0x1078, 0x570c, 0x0078, 0x5436,
-	0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040,
-	0x545d, 0xa196, 0x0023, 0x00c0, 0x5568, 0xa08e, 0x0023, 0x00c0,
-	0x5492, 0x1078, 0x57b2, 0x0040, 0x5568, 0x7124, 0x610a, 0x7030,
-	0xa08e, 0x0200, 0x00c0, 0x5476, 0x7034, 0xa005, 0x00c0, 0x5568,
-	0x2009, 0x0015, 0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0214,
-	0x0040, 0x547e, 0xa08e, 0x0210, 0x00c0, 0x5484, 0x2009, 0x0015,
-	0x1078, 0x756c, 0x0078, 0x5568, 0xa08e, 0x0100, 0x00c0, 0x5568,
-	0x7034, 0xa005, 0x00c0, 0x5568, 0x2009, 0x0016, 0x1078, 0x756c,
-	0x0078, 0x5568, 0xa08e, 0x0022, 0x00c0, 0x5568, 0x7030, 0xa08e,
-	0x0300, 0x00c0, 0x54a3, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
-	0x0017, 0x0078, 0x5534, 0xa08e, 0x0500, 0x00c0, 0x54af, 0x7034,
-	0xa005, 0x00c0, 0x5568, 0x2009, 0x0018, 0x0078, 0x5534, 0xa08e,
-	0x2010, 0x00c0, 0x54b7, 0x2009, 0x0019, 0x0078, 0x5534, 0xa08e,
-	0x2110, 0x00c0, 0x54bf, 0x2009, 0x001a, 0x0078, 0x5534, 0xa08e,
-	0x5200, 0x00c0, 0x54cb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
-	0x001b, 0x0078, 0x5534, 0xa08e, 0x5000, 0x00c0, 0x54d7, 0x7034,
-	0xa005, 0x00c0, 0x5568, 0x2009, 0x001c, 0x0078, 0x5534, 0xa08e,
-	0x1300, 0x00c0, 0x54df, 0x2009, 0x0034, 0x0078, 0x5534, 0xa08e,
-	0x1200, 0x00c0, 0x54eb, 0x7034, 0xa005, 0x00c0, 0x5568, 0x2009,
-	0x0024, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x00c0,
-	0x54f5, 0x2009, 0x002d, 0x0078, 0x5534, 0xa08c, 0xff00, 0xa18e,
-	0x5300, 0x00c0, 0x54ff, 0x2009, 0x002a, 0x0078, 0x5534, 0xa08e,
-	0x0f00, 0x00c0, 0x5507, 0x2009, 0x0020, 0x0078, 0x5534, 0xa08e,
-	0x5300, 0x00c0, 0x550d, 0x0078, 0x552a, 0xa08e, 0x6104, 0x00c0,
-	0x552a, 0x2011, 0xa88d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
-	0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x047e, 0x2124,
-	0x1078, 0x3579, 0x047f, 0x8108, 0x00f0, 0x551a, 0x2009, 0x0023,
-	0x0078, 0x5534, 0xa08e, 0x6000, 0x00c0, 0x5532, 0x2009, 0x003f,
-	0x0078, 0x5534, 0x2009, 0x001d, 0x017e, 0x2011, 0xa883, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x556a, 0x1078, 0x4499,
-	0x00c0, 0x556a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x555a, 0x017f,
-	0x017e, 0xa186, 0x0017, 0x00c0, 0x555a, 0x6868, 0xa606, 0x00c0,
-	0x555a, 0x686c, 0xa506, 0xa084, 0xff00, 0x00c0, 0x555a, 0x6000,
-	0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x74d7, 0x0040, 0x556d, 0x017f,
-	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x756c,
-	0x0c7f, 0x007c, 0x017f, 0x0078, 0x5568, 0x0c7f, 0x0078, 0x556a,
-	0x0c7e, 0x1078, 0x55d4, 0x00c0, 0x55d2, 0xa184, 0xff00, 0x8007,
-	0xa086, 0x0008, 0x00c0, 0x55d2, 0xa28e, 0x0033, 0x00c0, 0x55a3,
-	0x1078, 0x57b2, 0x0040, 0x55d2, 0x7124, 0x610a, 0x7030, 0xa08e,
-	0x0200, 0x00c0, 0x5595, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009,
-	0x0015, 0x1078, 0x756c, 0x0078, 0x55d2, 0xa08e, 0x0100, 0x00c0,
-	0x55d2, 0x7034, 0xa005, 0x00c0, 0x55d2, 0x2009, 0x0016, 0x1078,
-	0x756c, 0x0078, 0x55d2, 0xa28e, 0x0032, 0x00c0, 0x55d2, 0x7030,
-	0xa08e, 0x1400, 0x00c0, 0x55d2, 0x2009, 0x0038, 0x017e, 0x2011,
-	0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x55d1,
-	0x1078, 0x4499, 0x00c0, 0x55d1, 0x6612, 0x6516, 0x0c7e, 0x1078,
-	0x74d7, 0x0040, 0x55d0, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120,
-	0x610a, 0x017f, 0x1078, 0x756c, 0x1078, 0x6109, 0x0078, 0x55d2,
-	0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0d7e, 0x027e, 0x017e,
-	0x137e, 0x147e, 0x157e, 0x3c00, 0x007e, 0x2079, 0x0030, 0x2069,
-	0x0200, 0x1078, 0x1c25, 0x00c0, 0x5615, 0x1078, 0x1b15, 0x0040,
-	0x561f, 0x7908, 0xa18c, 0x1fff, 0xa182, 0x0011, 0x00c8, 0x561f,
-	0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
-	0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x7a0c, 0x7808, 0xa080,
-	0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140, 0x10c8, 0x1328, 0x80ac,
-	0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828,
-	0x6828, 0x7803, 0x0004, 0xa294, 0x0070, 0x007f, 0x20e0, 0x157f,
-	0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f, 0x0f7f, 0x007c, 0xa085,
-	0x0001, 0x0078, 0x5615, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130,
-	0xa696, 0x00ff, 0x00c0, 0x5644, 0xa596, 0xfffd, 0x00c0, 0x5634,
-	0x2009, 0x007f, 0x0078, 0x5677, 0xa596, 0xfffe, 0x00c0, 0x563c,
-	0x2009, 0x007e, 0x0078, 0x5677, 0xa596, 0xfffc, 0x00c0, 0x5644,
-	0x2009, 0x0080, 0x0078, 0x5677, 0x2011, 0x0000, 0x2021, 0x0081,
-	0x20a9, 0x007e, 0x2071, 0xa4b5, 0x2e1c, 0x83ff, 0x00c0, 0x5656,
-	0x82ff, 0x00c0, 0x566b, 0x2410, 0x0078, 0x566b, 0x2368, 0x6f10,
-	0x007e, 0x2100, 0xa706, 0x007f, 0x6b14, 0x00c0, 0x5665, 0xa346,
-	0x00c0, 0x5665, 0x2408, 0x0078, 0x5677, 0x87ff, 0x00c0, 0x566b,
-	0x83ff, 0x0040, 0x5650, 0x8420, 0x8e70, 0x00f0, 0x564c, 0x82ff,
-	0x00c0, 0x5676, 0xa085, 0x0001, 0x0078, 0x5678, 0x2208, 0xa006,
-	0x0d7f, 0x0e7f, 0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x5681,
-	0x007c, 0x5689, 0x5689, 0x5689, 0x57c8, 0x5689, 0x568a, 0x56a3,
-	0x56f3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x56a2, 0x7120, 0x2160,
-	0xac8c, 0x000f, 0x00c0, 0x56a2, 0xac8a, 0xaa00, 0x0048, 0x56a2,
-	0x6854, 0xac02, 0x00c8, 0x56a2, 0x7124, 0x610a, 0x2009, 0x0046,
-	0x1078, 0x756c, 0x007c, 0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x56f1,
-	0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0,
-	0x56f1, 0x1078, 0x4499, 0x00c0, 0x56f1, 0x6612, 0x6516, 0x6000,
-	0xd0ec, 0x00c0, 0x56f1, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286,
-	0x0006, 0x00c0, 0x56d6, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
-	0x56f1, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122,
-	0x2009, 0x0044, 0x1078, 0x756c, 0x0078, 0x56f1, 0x0c7e, 0x1078,
-	0x74d7, 0x017f, 0x0040, 0x56f1, 0x611a, 0x601f, 0x0004, 0x7120,
-	0x610a, 0xa286, 0x0004, 0x00c0, 0x56e9, 0x6007, 0x0005, 0x0078,
-	0x56eb, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078,
-	0x6109, 0x0c7f, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x570b, 0x7020,
-	0x2060, 0xac84, 0x000f, 0x00c0, 0x570b, 0xac82, 0xaa00, 0x0048,
-	0x570b, 0x6854, 0xac02, 0x00c8, 0x570b, 0x7124, 0x610a, 0x2009,
-	0x0045, 0x1078, 0x756c, 0x007c, 0x7110, 0xa18c, 0xff00, 0x810f,
-	0xa18e, 0x0000, 0x00c0, 0x571c, 0xa084, 0x000f, 0xa08a, 0x0006,
-	0x00c8, 0x571c, 0x1079, 0x571d, 0x007c, 0x5723, 0x5724, 0x5723,
-	0x5723, 0x5794, 0x57a3, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x572c,
-	0x702c, 0xd084, 0x0040, 0x5793, 0x700c, 0x7108, 0x1078, 0x24e3,
-	0x00c0, 0x5793, 0x1078, 0x4499, 0x00c0, 0x5793, 0x6612, 0x6516,
-	0x6204, 0x7110, 0xd1bc, 0x0040, 0x575e, 0xa28c, 0x00ff, 0xa186,
-	0x0004, 0x0040, 0x5747, 0xa186, 0x0006, 0x00c0, 0x5784, 0x0c7e,
-	0x1078, 0x57b2, 0x0c7f, 0x0040, 0x5793, 0x0c7e, 0x1078, 0x74d7,
-	0x017f, 0x0040, 0x5793, 0x611a, 0x601f, 0x0002, 0x7120, 0x610a,
-	0x2009, 0x0088, 0x1078, 0x756c, 0x0078, 0x5793, 0xa28c, 0x00ff,
-	0xa186, 0x0006, 0x0040, 0x5773, 0xa186, 0x0004, 0x0040, 0x5773,
-	0xa294, 0xff00, 0x8217, 0xa286, 0x0004, 0x0040, 0x5773, 0xa286,
-	0x0006, 0x00c0, 0x5784, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040,
-	0x5793, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088,
-	0x1078, 0x756c, 0x0078, 0x5793, 0x0c7e, 0x1078, 0x74d7, 0x017f,
-	0x0040, 0x5793, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009,
-	0x0001, 0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57a2,
-	0x1078, 0x57b2, 0x0040, 0x57a2, 0x7124, 0x610a, 0x2009, 0x0089,
-	0x1078, 0x756c, 0x007c, 0x7110, 0xd1bc, 0x0040, 0x57b1, 0x1078,
-	0x57b2, 0x0040, 0x57b1, 0x7124, 0x610a, 0x2009, 0x008a, 0x1078,
-	0x756c, 0x007c, 0x7020, 0x2060, 0xac84, 0x000f, 0x00c0, 0x57c5,
-	0xac82, 0xaa00, 0x0048, 0x57c5, 0x2001, 0xa315, 0x2004, 0xac02,
-	0x00c8, 0x57c5, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x57c4,
-	0x7110, 0xd1bc, 0x00c0, 0x57de, 0x7024, 0x2060, 0xac84, 0x000f,
-	0x00c0, 0x57de, 0xac82, 0xaa00, 0x0048, 0x57de, 0x6854, 0xac02,
-	0x00c8, 0x57de, 0x2009, 0x0051, 0x1078, 0x756c, 0x007c, 0x2071,
-	0xa5be, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
-	0x7017, 0xaa00, 0x7007, 0x0000, 0x7026, 0x702b, 0x6c4e, 0x7032,
-	0x7037, 0x6ca0, 0x703b, 0x0002, 0x703f, 0x0000, 0x7043, 0xffff,
-	0x7047, 0xffff, 0x007c, 0x2071, 0xa5be, 0x00e0, 0x58c1, 0x2091,
-	0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x5873, 0x700f, 0x0361,
-	0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109, 0x713a,
-	0x00c0, 0x5871, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104, 0xa082,
-	0x0003, 0x00c8, 0x5871, 0x703c, 0xa086, 0x0001, 0x00c0, 0x584e,
-	0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x582c,
-	0x6803, 0x1000, 0x0078, 0x5833, 0x6804, 0xa084, 0x1000, 0x0040,
-	0x5833, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000, 0x2069,
-	0xa5ab, 0x6804, 0xa082, 0x0006, 0x00c0, 0x5840, 0x6807, 0x0000,
-	0x6830, 0xa082, 0x0003, 0x00c0, 0x5847, 0x6833, 0x0000, 0x1078,
-	0x6109, 0x1078, 0x61d3, 0x0d7f, 0x0078, 0x5871, 0x0d7e, 0x2069,
-	0xa300, 0x6944, 0x6860, 0xa102, 0x00c8, 0x5870, 0x2069, 0xa5ab,
-	0x6804, 0xa086, 0x0000, 0x00c0, 0x5870, 0x6830, 0xa086, 0x0000,
-	0x00c0, 0x5870, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833, 0x0003,
-	0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803, 0x0600,
-	0x0d7f, 0x0078, 0x5876, 0x127e, 0x2091, 0x8000, 0x7024, 0xa00d,
-	0x0040, 0x588e, 0x7020, 0x8001, 0x7022, 0x00c0, 0x588e, 0x7023,
-	0x0009, 0x8109, 0x7126, 0xa186, 0x03e8, 0x00c0, 0x5889, 0x7028,
-	0x107a, 0x81ff, 0x00c0, 0x588e, 0x7028, 0x107a, 0x7030, 0xa00d,
-	0x0040, 0x589f, 0x702c, 0x8001, 0x702e, 0x00c0, 0x589f, 0x702f,
-	0x0009, 0x8109, 0x7132, 0x00c0, 0x589f, 0x7034, 0x107a, 0x7040,
-	0xa005, 0x0040, 0x58a7, 0x0050, 0x58a7, 0x8001, 0x7042, 0x7044,
-	0xa005, 0x0040, 0x58af, 0x0050, 0x58af, 0x8001, 0x7046, 0x7018,
-	0xa00d, 0x0040, 0x58c0, 0x7008, 0x8001, 0x700a, 0x00c0, 0x58c0,
-	0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x58c0, 0x701c, 0x107a,
-	0x127f, 0x7004, 0x0079, 0x58c4, 0x58eb, 0x58ec, 0x5908, 0x0e7e,
-	0x2071, 0xa5be, 0x7018, 0xa005, 0x00c0, 0x58d2, 0x711a, 0x721e,
-	0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071, 0xa5be,
-	0x701c, 0xa206, 0x00c0, 0x58de, 0x701a, 0x701e, 0x007f, 0x0e7f,
-	0x007c, 0x0e7e, 0x2071, 0xa5be, 0x6088, 0xa102, 0x0048, 0x58e9,
-	0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x4501, 0x00c0,
-	0x58fe, 0x6088, 0x8001, 0x0048, 0x58fe, 0x608a, 0x00c0, 0x58fe,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x8108, 0xa182,
-	0x00ff, 0x0048, 0x5906, 0xa00e, 0x7007, 0x0002, 0x7112, 0x007c,
-	0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005, 0x0040,
-	0x5917, 0x8001, 0x603e, 0x00c0, 0x5917, 0x1078, 0x8cd7, 0x6014,
-	0xa005, 0x0040, 0x5941, 0x8001, 0x6016, 0x00c0, 0x5941, 0x611c,
-	0xa186, 0x0003, 0x0040, 0x5928, 0xa186, 0x0006, 0x00c0, 0x593f,
-	0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x593f, 0xa082,
-	0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5938, 0x2001, 0x1999,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5941, 0x1078,
-	0x8810, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xca00, 0xa102,
-	0x0048, 0x594e, 0x7017, 0xaa00, 0x7007, 0x0000, 0x007c, 0x0e7e,
-	0x2071, 0xa5be, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b, 0x0002,
-	0x0e7f, 0x007c, 0x2001, 0xa5c7, 0x2003, 0x0000, 0x007c, 0x0e7e,
-	0x2071, 0xa5be, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c, 0x2011,
-	0xa5ca, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa5be, 0x711a,
-	0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e, 0x0f7e,
-	0x2079, 0xa300, 0x7a34, 0xd294, 0x0040, 0x59a4, 0x2071, 0xa5aa,
-	0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5991, 0xa0fe, 0x0001, 0x0040,
-	0x5995, 0xa0fe, 0x0002, 0x00c0, 0x59a0, 0xa292, 0x0085, 0x0078,
-	0x5997, 0xa292, 0x0005, 0x0078, 0x5997, 0xa292, 0x0002, 0x2272,
-	0x0040, 0x599c, 0x00c8, 0x59a4, 0x2011, 0x8037, 0x1078, 0x3579,
-	0x2011, 0xa5a9, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f, 0x007c,
-	0x0c7e, 0x2061, 0xa62d, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003,
-	0x8003, 0x8003, 0xa080, 0xa62d, 0x2060, 0x007c, 0x6854, 0xa08a,
-	0x199a, 0x0048, 0x59bd, 0x2001, 0x1999, 0xa005, 0x00c0, 0x59cc,
-	0x0c7e, 0x2061, 0xa62d, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x59d1,
-	0x2001, 0x001e, 0x0078, 0x59d1, 0xa08e, 0xffff, 0x00c0, 0x59d1,
-	0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
-	0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5a24, 0xd0b4, 0x00c0, 0x59e8,
-	0xd0bc, 0x00c0, 0x5a14, 0x2009, 0x0006, 0x1078, 0x5a43, 0x007c,
-	0xd0fc, 0x0040, 0x59f3, 0xa084, 0x0003, 0x0040, 0x59f3, 0xa086,
-	0x0003, 0x00c0, 0x5a3c, 0x6024, 0xd0d4, 0x0040, 0x59fd, 0xc0d4,
-	0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa373, 0x2104,
-	0xd084, 0x0040, 0x5a0f, 0x6118, 0xa188, 0x0027, 0x2104, 0xd08c,
-	0x00c0, 0x5a0f, 0x2009, 0x0042, 0x1078, 0x756c, 0x007c, 0x2009,
-	0x0043, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a1f, 0xa084,
-	0x0003, 0x0040, 0x5a1f, 0xa086, 0x0003, 0x00c0, 0x5a3c, 0x2009,
-	0x0042, 0x1078, 0x756c, 0x007c, 0xd0fc, 0x0040, 0x5a32, 0xa084,
-	0x0003, 0xa08e, 0x0002, 0x0040, 0x5a36, 0x2009, 0x0041, 0x1078,
-	0x756c, 0x007c, 0x1078, 0x5a41, 0x0078, 0x5a31, 0x2009, 0x0043,
-	0x1078, 0x756c, 0x0078, 0x5a31, 0x2009, 0x0004, 0x1078, 0x5a43,
-	0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040,
-	0x5a6b, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0,
-	0x5a65, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5a65,
-	0x0c7e, 0x2061, 0xa62d, 0x6200, 0xd28c, 0x00c0, 0x5a64, 0x6204,
-	0x8210, 0x0048, 0x5a64, 0x6206, 0x0c7f, 0x1078, 0x4982, 0x6010,
-	0xa06d, 0x10c0, 0x59b6, 0x0d7f, 0x007c, 0x157e, 0x0c7e, 0x2061,
-	0xa62d, 0x6000, 0x81ff, 0x0040, 0x5a78, 0xa205, 0x0078, 0x5a79,
-	0xa204, 0x6002, 0x0c7f, 0x157f, 0x007c, 0x6800, 0xd08c, 0x00c0,
-	0x5a89, 0x6808, 0xa005, 0x0040, 0x5a89, 0x8001, 0x680a, 0xa085,
-	0x0001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
-	0x00c8, 0x5a93, 0xa200, 0x00f0, 0x5a8e, 0x8086, 0x818e, 0x007c,
-	0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x5ab9, 0xa11a, 0x00c8,
-	0x5ab9, 0x8213, 0x818d, 0x0048, 0x5aac, 0xa11a, 0x00c8, 0x5aad,
-	0x00f0, 0x5aa1, 0x0078, 0x5ab1, 0xa11a, 0x2308, 0x8210, 0x00f0,
-	0x5aa1, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
-	0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x5ab5, 0x127e,
-	0x2091, 0x2200, 0x2079, 0xa5ab, 0x127f, 0x0d7e, 0x2069, 0xa5ab,
-	0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a,
-	0x0d7f, 0x007c, 0x0c7e, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007,
-	0x0079, 0x5ada, 0x5ae4, 0x5b09, 0x5b64, 0x5aea, 0x5b09, 0x5ae4,
-	0x5ae2, 0x5ae2, 0x1078, 0x1328, 0x1078, 0x595a, 0x1078, 0x6109,
-	0x0c7f, 0x007c, 0x62c0, 0x82ff, 0x00c0, 0x5af0, 0x0c7f, 0x007c,
-	0x2011, 0x4129, 0x1078, 0x58d4, 0x7828, 0xa092, 0x00c8, 0x00c8,
-	0x5aff, 0x8000, 0x782a, 0x1078, 0x4168, 0x0078, 0x5aee, 0x1078,
-	0x4129, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0078,
-	0x5aee, 0x1078, 0x595a, 0x3c00, 0x007e, 0x2011, 0x0209, 0x20e1,
-	0x4000, 0x2214, 0x007f, 0x20e0, 0x82ff, 0x0040, 0x5b27, 0x62c0,
-	0x82ff, 0x00c0, 0x5b27, 0x782b, 0x0000, 0x7824, 0xa065, 0x1040,
-	0x1328, 0x2009, 0x0013, 0x1078, 0x756c, 0x0c7f, 0x007c, 0x3900,
-	0xa082, 0xa6cd, 0x00c8, 0x5b2e, 0x1078, 0x728a, 0x0c7e, 0x7824,
-	0xa065, 0x1040, 0x1328, 0x7804, 0xa086, 0x0004, 0x0040, 0x5ba9,
-	0x7828, 0xa092, 0x2710, 0x00c8, 0x5b44, 0x8000, 0x782a, 0x0c7f,
-	0x1078, 0x6c33, 0x0078, 0x5b25, 0x6104, 0xa186, 0x0003, 0x00c0,
-	0x5b5b, 0x0e7e, 0x2071, 0xa300, 0x70d4, 0x0e7f, 0xd08c, 0x0040,
-	0x5b5b, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071, 0xa300, 0x1078,
-	0x4171, 0x0e7f, 0x0c7f, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
-	0x756c, 0x0c7f, 0x0078, 0x5b25, 0x2001, 0xa5c7, 0x2003, 0x0000,
-	0x62c0, 0x82ff, 0x00c0, 0x5b78, 0x782b, 0x0000, 0x7824, 0xa065,
-	0x1040, 0x1328, 0x2009, 0x0013, 0x1078, 0x75c3, 0x0c7f, 0x007c,
-	0x0c7e, 0x0d7e, 0x3900, 0xa082, 0xa6cd, 0x00c8, 0x5b81, 0x1078,
-	0x728a, 0x7824, 0xa005, 0x1040, 0x1328, 0x781c, 0xa06d, 0x1040,
-	0x1328, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x1078, 0x753d,
-	0x693c, 0x81ff, 0x1040, 0x1328, 0x8109, 0x693e, 0x6854, 0xa015,
-	0x0040, 0x5b9d, 0x7a1e, 0x0078, 0x5b9f, 0x7918, 0x791e, 0x7807,
-	0x0000, 0x7827, 0x0000, 0x0d7f, 0x0c7f, 0x1078, 0x6109, 0x0078,
-	0x5b76, 0x6104, 0xa186, 0x0002, 0x0040, 0x5bb4, 0xa186, 0x0004,
-	0x0040, 0x5bb4, 0x0078, 0x5b38, 0x7808, 0xac06, 0x0040, 0x5b38,
-	0x1078, 0x6010, 0x1078, 0x5c45, 0x0c7f, 0x1078, 0x6109, 0x0078,
-	0x5b25, 0x0c7e, 0x6027, 0x0002, 0x62c8, 0x82ff, 0x00c0, 0x5bdb,
-	0x62c4, 0x82ff, 0x00c0, 0x5bdb, 0x793c, 0xa1e5, 0x0000, 0x0040,
-	0x5bd5, 0x2009, 0x0049, 0x1078, 0x756c, 0x2011, 0xa5ca, 0x2013,
-	0x0000, 0x0c7f, 0x007c, 0x3908, 0xa192, 0xa6cd, 0x00c8, 0x5be2,
-	0x1078, 0x728a, 0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5bd5,
-	0x793c, 0xa188, 0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x5bf4,
-	0x6017, 0x0012, 0x0078, 0x5bd9, 0x6017, 0x0016, 0x0078, 0x5bd9,
-	0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000,
-	0x2c08, 0x2061, 0xa5ab, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
-	0x0040, 0x5c13, 0xa080, 0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f,
-	0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078, 0x5c0e, 0x0d7e,
-	0x2069, 0xa5ab, 0x6000, 0xd0d4, 0x0040, 0x5c2c, 0x6820, 0x8000,
-	0x6822, 0xa086, 0x0001, 0x00c0, 0x5c27, 0x2c00, 0x681e, 0x6804,
-	0xa084, 0x0007, 0x0079, 0x6111, 0xc0d5, 0x6002, 0x6818, 0xa005,
-	0x0040, 0x5c3e, 0x6056, 0x605b, 0x0000, 0x007e, 0x2c00, 0x681a,
-	0x0d7f, 0x685a, 0x2069, 0xa5ab, 0x0078, 0x5c1e, 0x6056, 0x605a,
-	0x2c00, 0x681a, 0x681e, 0x0078, 0x5c1e, 0x007e, 0x017e, 0x0c7e,
-	0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xa5ab,
-	0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040, 0x5c60, 0xa080,
-	0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c,
-	0x610e, 0x610a, 0x0078, 0x5c5b, 0x0c7e, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0xa5ab, 0x6034, 0xa005, 0x0040, 0x5c74, 0xa080, 0x0003,
-	0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136, 0x0078, 0x5c72,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x017e, 0x007e,
-	0x127e, 0x2071, 0xa5ab, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
-	0x8cff, 0x0040, 0x5ced, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x00c0, 0x5ce8, 0x87ff, 0x0040, 0x5c99, 0x6020, 0xa106, 0x00c0,
-	0x5ce8, 0x703c, 0xac06, 0x00c0, 0x5cab, 0x037e, 0x2019, 0x0001,
-	0x1078, 0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
-	0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x5cb1, 0x660c,
-	0x763a, 0x7034, 0xac36, 0x00c0, 0x5cbf, 0x2c00, 0xaf36, 0x0040,
-	0x5cbd, 0x2f00, 0x7036, 0x0078, 0x5cbf, 0x7037, 0x0000, 0x660c,
-	0x067e, 0x2c00, 0xaf06, 0x0040, 0x5cc8, 0x7e0e, 0x0078, 0x5cc9,
-	0x2678, 0x600f, 0x0000, 0x1078, 0x8a44, 0x0040, 0x5ce3, 0x6010,
-	0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5cf7, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078,
-	0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5c88,
-	0x2c78, 0x600c, 0x2060, 0x0078, 0x5c88, 0x127f, 0x007f, 0x017f,
-	0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c,
-	0xa086, 0x0006, 0x00c0, 0x5cd6, 0x1078, 0xa181, 0x1078, 0x9e70,
-	0x0078, 0x5ce3, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031,
-	0x0000, 0x127e, 0x2091, 0x8000, 0x2079, 0xa5ab, 0x7838, 0xa065,
-	0x0040, 0x5d41, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06,
-	0x00c0, 0x5d28, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x7833,
-	0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000, 0x037f,
-	0x1078, 0x8a44, 0x0040, 0x5d3c, 0x6010, 0x2068, 0x601c, 0xa086,
-	0x0003, 0x00c0, 0x5d4a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x007f, 0x0078,
-	0x5d0f, 0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f,
-	0x007f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5d33, 0x1078,
-	0x9e70, 0x0078, 0x5d3c, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000,
-	0x1078, 0x5d6d, 0x1078, 0x5e21, 0x087f, 0x027f, 0x017f, 0x007c,
-	0x0f7e, 0x127e, 0x2079, 0xa5ab, 0x2091, 0x8000, 0x1078, 0x5ebc,
-	0x1078, 0x5f32, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x067e, 0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0xa5ab, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5e01, 0x6018,
-	0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5dfc, 0x88ff, 0x0040,
-	0x5d8d, 0x6020, 0xa106, 0x00c0, 0x5dfc, 0x7024, 0xac06, 0x00c0,
-	0x5dbd, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x5db8, 0x1078,
-	0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188, 0x7027,
-	0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040,
-	0x5dad, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0040, 0x5db5, 0x6827, 0x0001, 0x037f, 0x0078, 0x5dbd,
-	0x6003, 0x0009, 0x630a, 0x0078, 0x5dfc, 0x7014, 0xac36, 0x00c0,
-	0x5dc3, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5dd1, 0x2c00,
-	0xaf36, 0x0040, 0x5dcf, 0x2f00, 0x7012, 0x0078, 0x5dd1, 0x7013,
-	0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5dda, 0x7e0e,
-	0x0078, 0x5ddb, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x5df5, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e0a,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078,
-	0xa181, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
-	0x7045, 0x0c7f, 0x0078, 0x5d7c, 0x2c78, 0x600c, 0x2060, 0x0078,
-	0x5d7c, 0x127f, 0x007f, 0x017f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5e15, 0x1078,
-	0xa181, 0x1078, 0x9e70, 0x0078, 0x5df5, 0x601c, 0xa086, 0x0002,
-	0x00c0, 0x5df5, 0x6004, 0xa086, 0x0085, 0x0040, 0x5de8, 0x0078,
-	0x5df5, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0xa434,
-	0x2004, 0xa065, 0x0040, 0x5eb8, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e,
-	0x2071, 0xa5ab, 0x6654, 0x7018, 0xac06, 0x00c0, 0x5e38, 0x761a,
-	0x701c, 0xac06, 0x00c0, 0x5e44, 0x86ff, 0x00c0, 0x5e43, 0x7018,
-	0x701e, 0x0078, 0x5e44, 0x761e, 0x6058, 0xa07d, 0x0040, 0x5e49,
-	0x7e56, 0xa6ed, 0x0000, 0x0040, 0x5e4f, 0x2f00, 0x685a, 0x6057,
-	0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078,
-	0x4410, 0x0040, 0x5eb4, 0x7624, 0x86ff, 0x0040, 0x5ea2, 0xa680,
-	0x0004, 0x2004, 0xad06, 0x00c0, 0x5ea2, 0x0d7e, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x5e99, 0x1078, 0x595a, 0x1078, 0x6c41,
-	0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5e82, 0x6803, 0x0100,
-	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5e8a,
-	0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040,
-	0x5e93, 0x8001, 0x603e, 0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078,
-	0x5ea2, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f,
-	0x0078, 0x5e57, 0x8dff, 0x0040, 0x5eb0, 0x6837, 0x0103, 0x6b4a,
-	0x6847, 0x0000, 0x1078, 0x8cb8, 0x1078, 0xa181, 0x1078, 0x4982,
-	0x1078, 0x7045, 0x0078, 0x5e57, 0x067f, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e, 0x0c7e, 0x0d7e,
-	0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x5f16, 0x600c, 0x007e,
-	0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x5efb, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x5ef5, 0x1078, 0x595a, 0x1078, 0x6c41,
-	0x68c3, 0x0000, 0x1078, 0x7188, 0x7827, 0x0000, 0x037e, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5eea, 0x6803, 0x0100,
-	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ef2,
-	0x6827, 0x0001, 0x037f, 0x0078, 0x5efb, 0x6003, 0x0009, 0x630a,
-	0x2c30, 0x0078, 0x5f13, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040,
-	0x5f0f, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5f1d, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078,
-	0x8c01, 0x1078, 0x7045, 0x007f, 0x0078, 0x5ec3, 0x7e16, 0x7e12,
-	0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x5f26, 0x1078, 0x9e70, 0x0078, 0x5f0f, 0x601c, 0xa086,
-	0x0002, 0x00c0, 0x5f0f, 0x6004, 0xa086, 0x0085, 0x0040, 0x5f06,
-	0x0078, 0x5f0f, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x7818, 0xa065,
-	0x0040, 0x5fa0, 0x6054, 0x007e, 0x6057, 0x0000, 0x605b, 0x0000,
-	0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x4410, 0x0040, 0x5f9d,
-	0x7e24, 0x86ff, 0x0040, 0x5f8f, 0xa680, 0x0004, 0x2004, 0xad06,
-	0x00c0, 0x5f8f, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040,
-	0x5f86, 0x1078, 0x595a, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078,
-	0x7188, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384,
-	0x1000, 0x0040, 0x5f6f, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
-	0x0100, 0x6824, 0xd084, 0x0040, 0x5f77, 0x6827, 0x0001, 0x037f,
-	0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x5f80, 0x8001, 0x603e,
-	0x2660, 0x1078, 0x8c01, 0x0c7f, 0x0078, 0x5f8f, 0x0d7f, 0x0c7e,
-	0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x5f44, 0x8dff,
-	0x0040, 0x5f99, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
-	0x4982, 0x1078, 0x7045, 0x0078, 0x5f44, 0x007f, 0x0078, 0x5f37,
-	0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x0e7e,
-	0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x5fc4, 0x604c, 0xa06d,
-	0x0040, 0x5fc4, 0x6848, 0xa606, 0x00c0, 0x5fc4, 0x2071, 0xa5ab,
-	0x7024, 0xa035, 0x0040, 0x5fc4, 0xa080, 0x0004, 0x2004, 0xad06,
-	0x00c0, 0x5fc4, 0x1078, 0x5fc8, 0x067f, 0x0d7f, 0x0e7f, 0x007c,
-	0x0f7e, 0x2079, 0x0100, 0x78c0, 0xa005, 0x00c0, 0x5fd7, 0x0c7e,
-	0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x600e, 0x1078,
-	0x6c41, 0x78c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e,
-	0x2079, 0x0140, 0x7b04, 0xa384, 0x1000, 0x0040, 0x5feb, 0x7803,
-	0x0100, 0x7803, 0x0000, 0x2079, 0x0100, 0x7824, 0xd084, 0x0040,
-	0x5ff3, 0x7827, 0x0001, 0x1078, 0x7188, 0x037f, 0x1078, 0x4410,
-	0x0c7e, 0x603c, 0xa005, 0x0040, 0x5fff, 0x8001, 0x603e, 0x2660,
-	0x1078, 0x753d, 0x0c7f, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x1078, 0x8cb8, 0x1078, 0x4982, 0x1078, 0x7045, 0x0f7f, 0x007c,
-	0x0e7e, 0x0c7e, 0x2071, 0xa5ab, 0x7004, 0xa084, 0x0007, 0x0079,
-	0x6019, 0x6023, 0x6026, 0x603f, 0x605b, 0x60a0, 0x6023, 0x6023,
-	0x6021, 0x1078, 0x1328, 0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065,
-	0x0040, 0x6034, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0040,
-	0x603b, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
-	0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x6034, 0x6018,
-	0x2060, 0x1078, 0x4410, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001,
-	0x7022, 0x0040, 0x6050, 0x6054, 0xa015, 0x0040, 0x6057, 0x721e,
-	0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218,
-	0x721e, 0x0078, 0x6050, 0x7024, 0xa065, 0x0040, 0x609d, 0x700c,
-	0xac06, 0x00c0, 0x6072, 0x1078, 0x7045, 0x600c, 0xa015, 0x0040,
-	0x606e, 0x720e, 0x600f, 0x0000, 0x0078, 0x609b, 0x720e, 0x720a,
-	0x0078, 0x609b, 0x7014, 0xac06, 0x00c0, 0x6085, 0x1078, 0x7045,
-	0x600c, 0xa015, 0x0040, 0x6081, 0x7216, 0x600f, 0x0000, 0x0078,
-	0x609b, 0x7216, 0x7212, 0x0078, 0x609b, 0x6018, 0x2060, 0x1078,
-	0x4410, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7045, 0x701c, 0xa065,
-	0x0040, 0x609b, 0x6054, 0xa015, 0x0040, 0x6099, 0x721e, 0x0078,
-	0x609b, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
-	0x7024, 0xa065, 0x0040, 0x60ad, 0x1078, 0x7045, 0x600c, 0xa015,
-	0x0040, 0x60b4, 0x720e, 0x600f, 0x0000, 0x1078, 0x7188, 0x7027,
-	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078, 0x60ad,
-	0x0d7e, 0x2069, 0xa5ab, 0x6830, 0xa084, 0x0003, 0x0079, 0x60c0,
-	0x60c6, 0x60c8, 0x60ee, 0x60c6, 0x1078, 0x1328, 0x0d7f, 0x007c,
-	0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x60e4, 0x683c, 0xa065,
-	0x0040, 0x60d9, 0x600c, 0xa015, 0x0040, 0x60e0, 0x6a3a, 0x600f,
-	0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f, 0x007c,
-	0x683a, 0x6836, 0x0078, 0x60d9, 0x6843, 0x0000, 0x6838, 0xa065,
-	0x0040, 0x60d9, 0x6003, 0x0003, 0x0078, 0x60d9, 0x0c7e, 0x6843,
-	0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x6106, 0x600c,
-	0xa015, 0x0040, 0x6102, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
-	0x0078, 0x6106, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f,
-	0x007c, 0x0d7e, 0x2069, 0xa5ab, 0x6804, 0xa084, 0x0007, 0x0079,
-	0x6111, 0x611b, 0x61c2, 0x61c2, 0x61c2, 0x61c2, 0x61c4, 0x61c2,
-	0x6119, 0x1078, 0x1328, 0x6820, 0xa005, 0x00c0, 0x6121, 0x0d7f,
-	0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x6130, 0x6807, 0x0004,
-	0x6826, 0x682b, 0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c,
-	0x6814, 0xa065, 0x0040, 0x613e, 0x6807, 0x0001, 0x6826, 0x682b,
-	0x0000, 0x1078, 0x620a, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e,
-	0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x61bd, 0x704c, 0xa00d, 0x0040,
-	0x614d, 0x7088, 0xa005, 0x0040, 0x6165, 0x7054, 0xa075, 0x0040,
-	0x6156, 0xa20e, 0x0040, 0x61bd, 0x0078, 0x615b, 0x6818, 0xa20e,
-	0x0040, 0x61bd, 0x2070, 0x704c, 0xa00d, 0x0040, 0x614d, 0x7088,
-	0xa005, 0x00c0, 0x614d, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302,
-	0x00c8, 0x614d, 0x1078, 0x750c, 0x0040, 0x61bd, 0x8318, 0x733e,
-	0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff,
-	0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004,
-	0xa08a, 0x199a, 0x0048, 0x6186, 0x2001, 0x1999, 0x8003, 0x801b,
-	0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc,
-	0x0040, 0x619f, 0x7100, 0xd1f4, 0x0040, 0x619b, 0x7114, 0xa18c,
-	0x00ff, 0x0078, 0x61a4, 0x2009, 0x0000, 0x0078, 0x61a4, 0xa1e0,
-	0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078,
-	0x679b, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26,
-	0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040,
-	0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f,
-	0x0078, 0x61bb, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040,
-	0x61d0, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x620a,
-	0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa5ab, 0x6830,
-	0xa086, 0x0000, 0x00c0, 0x61f1, 0x6838, 0xa07d, 0x0040, 0x61f1,
-	0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091,
-	0x2200, 0x027f, 0x1078, 0x1d28, 0x00c0, 0x61f4, 0x127f, 0x1078,
-	0x6ae5, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803,
-	0x0002, 0x780c, 0xa015, 0x0040, 0x6206, 0x6a3a, 0x780f, 0x0000,
-	0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x61f1, 0x683a, 0x6836,
-	0x0078, 0x6200, 0x601c, 0xa084, 0x000f, 0x1079, 0x6210, 0x007c,
-	0x6219, 0x621e, 0x663f, 0x6758, 0x621e, 0x663f, 0x6758, 0x6219,
-	0x621e, 0x1078, 0x6010, 0x1078, 0x6109, 0x007c, 0x157e, 0x137e,
-	0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044, 0x10c8, 0x1328,
-	0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x623b, 0x7900, 0xd1f4,
-	0x0040, 0x6237, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x6240, 0x2009,
-	0x0000, 0x0078, 0x6240, 0xa1f8, 0x293f, 0x2f0c, 0xa18c, 0x00ff,
-	0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x00c8, 0x6292,
-	0x1079, 0x6250, 0x0f7f, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c,
-	0x62f8, 0x6340, 0x6368, 0x6403, 0x6433, 0x643b, 0x6462, 0x6473,
-	0x6484, 0x648c, 0x64a4, 0x648c, 0x650f, 0x6473, 0x6530, 0x6538,
-	0x6484, 0x6538, 0x6549, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290,
-	0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6290, 0x6d05, 0x6d2a,
-	0x6d3f, 0x6d62, 0x6d83, 0x6462, 0x6290, 0x6462, 0x648c, 0x6290,
-	0x6368, 0x6403, 0x6290, 0x72ac, 0x648c, 0x6290, 0x72cc, 0x648c,
-	0x6290, 0x6290, 0x62f3, 0x62a1, 0x6290, 0x72f1, 0x7368, 0x7450,
-	0x6290, 0x7461, 0x645c, 0x747d, 0x6290, 0x6d98, 0x6290, 0x6290,
-	0x1078, 0x1328, 0x2100, 0x1079, 0x629b, 0x0f7f, 0x0c7f, 0x147f,
-	0x137f, 0x157f, 0x007c, 0x629f, 0x629f, 0x629f, 0x62d5, 0x1078,
-	0x1328, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6567, 0x7810, 0x2068,
-	0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0018, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x0d7e, 0x7818,
-	0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x62d2, 0xa085, 0x0001,
-	0x0d7f, 0x007c, 0xa006, 0x0078, 0x62d0, 0x0d7e, 0x20a1, 0x020b,
-	0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8,
-	0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814,
-	0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x1078,
-	0x6c2d, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078, 0x6c2d, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x5200, 0x20a3, 0x0000,
-	0x0d7e, 0x2069, 0xa351, 0x6804, 0xd084, 0x0040, 0x6312, 0x6828,
-	0x20a3, 0x0000, 0x017e, 0x1078, 0x24fa, 0x21a2, 0x017f, 0x0d7f,
-	0x0078, 0x6317, 0x0d7f, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
-	0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
-	0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048,
-	0x6331, 0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078,
-	0x6337, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x0500, 0x20a3, 0x0000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0048, 0x6358,
-	0x2001, 0xa31a, 0x20a6, 0x2001, 0xa31b, 0x20a6, 0x0078, 0x635e,
-	0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004,
-	0x2099, 0xa305, 0x53a6, 0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x6567, 0x0c7e, 0x7818, 0x2060, 0x2001,
-	0x0000, 0x1078, 0x48a2, 0x0c7f, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x007e, 0x00c0, 0x6383, 0x20a3, 0x0400, 0x620c, 0xc2b4,
-	0x620e, 0x0078, 0x6385, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x63d2, 0x2099,
-	0xa58c, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff,
-	0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0xa305, 0x53a6,
-	0x20a9, 0x0004, 0x2099, 0xa301, 0x53a6, 0x20a9, 0x0010, 0x20a3,
-	0x0000, 0x00f0, 0x63af, 0x2099, 0xa594, 0x3304, 0xc0dd, 0x20a2,
-	0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040, 0x63ca, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9, 0x0004,
-	0x0078, 0x63cc, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0, 0x63cc,
-	0x0078, 0x63f2, 0x2099, 0xa58c, 0x20a9, 0x0008, 0x53a6, 0x20a9,
-	0x0004, 0x2099, 0xa305, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa301,
-	0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e3, 0x20a9,
-	0x0008, 0x20a3, 0x0000, 0x00f0, 0x63e9, 0x2099, 0xa594, 0x20a9,
-	0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x63f4,
-	0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x63fa, 0x60c3, 0x0074,
-	0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
-	0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351,
-	0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x641f, 0xa085, 0x0020, 0xd1a4,
-	0x0040, 0x6424, 0xa085, 0x0010, 0xa085, 0x0002, 0x0d7e, 0x0078,
-	0x64ed, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
-	0x5000, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3,
-	0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65ef,
-	0x0078, 0x6466, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
-	0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3,
-	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
-	0x0008, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
-	0x20a3, 0x0200, 0x0078, 0x6385, 0x20a1, 0x020b, 0x1078, 0x65f8,
-	0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0040, 0x649b,
-	0x20a2, 0x0078, 0x649d, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3,
-	0x0008, 0x1078, 0x6c2d, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
-	0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818,
-	0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x64ca, 0x6998, 0xa184,
-	0xc000, 0x00c0, 0x64c6, 0xd1ec, 0x0040, 0x64c2, 0x20a3, 0x2100,
-	0x0078, 0x64cc, 0x20a3, 0x0100, 0x0078, 0x64cc, 0x20a3, 0x0400,
-	0x0078, 0x64cc, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa351, 0x7904, 0x0f7f, 0xd1ac,
-	0x00c0, 0x64dc, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x64e1, 0xa085,
-	0x0010, 0x2009, 0xa373, 0x210c, 0xd184, 0x0040, 0x64eb, 0x699c,
-	0xd18c, 0x0040, 0x64ed, 0xa085, 0x0002, 0x027e, 0x2009, 0xa371,
-	0x210c, 0xd1e4, 0x0040, 0x64fb, 0xc0c5, 0xa094, 0x0030, 0xa296,
-	0x0010, 0x0040, 0x6505, 0xd1ec, 0x0040, 0x6505, 0xa094, 0x0030,
-	0xa296, 0x0010, 0x0040, 0x6505, 0xc0bd, 0x027f, 0x20a2, 0x20a2,
-	0x20a2, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1,
-	0x020b, 0x1078, 0x65f8, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x6c2d, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x0078, 0x62fe,
-	0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x6c2d,
-	0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078,
-	0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
-	0x0000, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x027e, 0x037e,
-	0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078, 0x656e, 0x027e,
-	0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e,
-	0x00c0, 0x6581, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x0078,
-	0x65b6, 0xa286, 0x007f, 0x00c0, 0x658d, 0x0d7e, 0xa385, 0x00ff,
-	0x20a2, 0x20a3, 0xfffd, 0x0078, 0x65a4, 0xd2bc, 0x0040, 0x65ac,
-	0xa286, 0x0080, 0x0d7e, 0x00c0, 0x659c, 0xa385, 0x00ff, 0x20a2,
-	0x20a3, 0xfffc, 0x0078, 0x65a4, 0xa2e8, 0xa434, 0x2d6c, 0x6810,
-	0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x65ba, 0x0d7e, 0xa2e8, 0xa434, 0x2d6c,
-	0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f, 0x037f, 0x20a3,
-	0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
-	0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011, 0xfffc,
-	0x22a2, 0x0d7e, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x65c1, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x007c, 0x027e,
-	0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800, 0x0078, 0x65ff,
-	0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092,
-	0x007e, 0x0048, 0x661c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
-	0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x662a, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
-	0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x047f,
-	0x037f, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
-	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e,
-	0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a, 0x008c,
-	0x10c8, 0x1328, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x665d,
-	0x7900, 0xd1f4, 0x0040, 0x6659, 0x7914, 0xa18c, 0x00ff, 0x0078,
-	0x6662, 0x2009, 0x0000, 0x0078, 0x6662, 0xa1f8, 0x293f, 0x2f0c,
-	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085,
-	0x1079, 0x666d, 0x0f7f, 0x0c7f, 0x007c, 0x6676, 0x6681, 0x669c,
-	0x6674, 0x6674, 0x6674, 0x6676, 0x1078, 0x1328, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x66af, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
-	0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x66e3, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
-	0x1078, 0x6c2d, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x6724, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0004, 0x1078, 0x6c2d, 0x147f, 0x007c, 0x027e,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa092, 0x007e, 0x0048, 0x66ce, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
-	0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x66dd, 0x0d7e, 0xa0e8,
-	0xa434, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
-	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3,
-	0x0000, 0x0078, 0x65c1, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6702,
-	0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x6711, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
-	0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
-	0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2,
-	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048,
-	0x6743, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x8500,
-	0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
-	0x0d7f, 0x0078, 0x6752, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
-	0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x0078, 0x6715,
-	0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x1048, 0x1328,
-	0xa08a, 0x0053, 0x10c8, 0x1328, 0x7918, 0x2160, 0x61a0, 0xd1bc,
-	0x0040, 0x6777, 0x6100, 0xd1f4, 0x0040, 0x6773, 0x6114, 0xa18c,
-	0x00ff, 0x0078, 0x677c, 0x2009, 0x0000, 0x0078, 0x677c, 0xa1e0,
-	0x293f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0xa082,
-	0x0040, 0x1079, 0x6786, 0x0f7f, 0x0c7f, 0x007c, 0x679b, 0x68a9,
-	0x684a, 0x6a59, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799, 0x6799,
-	0x6799, 0x6f5e, 0x6f6f, 0x6f80, 0x6f91, 0x6799, 0x748e, 0x6799,
-	0x6f4d, 0x1078, 0x1328, 0x0d7e, 0x157e, 0x147e, 0x780b, 0xffff,
-	0x20a1, 0x020b, 0x1078, 0x6806, 0x7910, 0x2168, 0x6948, 0x7922,
-	0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x000f,
-	0x00c0, 0x67b6, 0x2001, 0x0005, 0x0078, 0x67c0, 0xd184, 0x0040,
-	0x67bd, 0x2001, 0x0004, 0x0078, 0x67c0, 0xa084, 0x0006, 0x8004,
-	0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007, 0xa105, 0x017f,
-	0x20a2, 0xd1ac, 0x0040, 0x67d0, 0x20a3, 0x0002, 0x0078, 0x67dc,
-	0xd1b4, 0x0040, 0x67d7, 0x20a3, 0x0001, 0x0078, 0x67dc, 0x20a3,
-	0x0000, 0x2230, 0x0078, 0x67de, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
-	0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x67e2,
-	0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084,
-	0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa5c7, 0x2003, 0x07d0,
-	0x2001, 0xa5c6, 0x2003, 0x0009, 0x2001, 0xa5cc, 0x2003, 0x0002,
-	0x1078, 0x157e, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
-	0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc,
-	0x0040, 0x682c, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085,
-	0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x683b, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
-	0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3,
-	0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2,
-	0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x686a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
-	0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x147f, 0x137f, 0x157f,
-	0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6888, 0x0d7e, 0xa0e8,
-	0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6897,
-	0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
-	0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
-	0x0889, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
-	0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810, 0xa06d, 0x1078,
-	0x488f, 0x0040, 0x68bd, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020,
-	0x00c0, 0x68bd, 0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078,
-	0x6a12, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
-	0xa084, 0xf000, 0x00c0, 0x68d4, 0x7810, 0xa084, 0x0700, 0x8007,
-	0x1079, 0x68dc, 0x0078, 0x68d7, 0xa006, 0x1079, 0x68dc, 0x147f,
-	0x137f, 0x157f, 0x0d7f, 0x007c, 0x68e6, 0x697e, 0x6989, 0x69b3,
-	0x69c7, 0x69e3, 0x69ee, 0x68e4, 0x1078, 0x1328, 0x017e, 0x037e,
-	0x694c, 0xa18c, 0x0003, 0x0040, 0x68f1, 0xa186, 0x0003, 0x00c0,
-	0x6900, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x68f7, 0xc3e5, 0x23a2,
-	0x6868, 0x20a2, 0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x69be,
-	0xa186, 0x0001, 0x10c0, 0x1328, 0x6b78, 0x7824, 0xd0cc, 0x0040,
-	0x690a, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
-	0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
-	0x0300, 0x0040, 0x6978, 0xd3c4, 0x0040, 0x6920, 0x687c, 0xa108,
-	0xd3cc, 0x0040, 0x6925, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d,
-	0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x692a,
-	0x157f, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6978,
-	0x20a1, 0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6958, 0x0d7e, 0xa0e8,
-	0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6967,
-	0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f,
-	0x7b24, 0xd3cc, 0x0040, 0x6970, 0x20a3, 0x0889, 0x0078, 0x6972,
-	0x20a3, 0x0898, 0x20a2, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
-	0x61c2, 0x037f, 0x017f, 0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008,
-	0x7824, 0xd0cc, 0x0040, 0x6985, 0xc2e5, 0x22a2, 0xa016, 0x0078,
-	0x69bc, 0x2011, 0x0302, 0x7824, 0xd0cc, 0x0040, 0x6990, 0xc2e5,
-	0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2,
-	0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000,
-	0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3,
-	0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032,
-	0x1078, 0x6c2d, 0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040,
-	0x69ba, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x6c2d, 0x007c, 0x2011,
-	0x0100, 0x7824, 0xd0cc, 0x0040, 0x69ce, 0xc2e5, 0x22a2, 0xa016,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2,
-	0x7834, 0xa084, 0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
-	0x1078, 0x6c2d, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040,
-	0x69ea, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x69bc, 0x037e, 0x7b10,
-	0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6a01,
-	0x7824, 0xd0cc, 0x0040, 0x69fd, 0xc2e5, 0x22a2, 0x037f, 0x0078,
-	0x69bc, 0x047e, 0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f,
-	0x0040, 0x6a0b, 0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f,
-	0x0078, 0x69be, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a30, 0x0d7e, 0xa0e8,
-	0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a3f,
-	0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824,
-	0xd0cc, 0x0040, 0x6a47, 0x20a3, 0x0889, 0x0078, 0x6a49, 0x20a3,
-	0x0898, 0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
-	0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810,
-	0xa084, 0x0700, 0x8007, 0x1079, 0x6a6c, 0x037f, 0x017f, 0x147f,
-	0x137f, 0x157f, 0x0d7f, 0x007c, 0x6a74, 0x6a74, 0x6a76, 0x6a74,
-	0x6a74, 0x6a74, 0x6a9b, 0x6a74, 0x1078, 0x1328, 0x7910, 0xa18c,
-	0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
-	0x1078, 0x6aa5, 0x0d7e, 0x2069, 0xa351, 0x6804, 0xd0bc, 0x0040,
-	0x6a90, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6a92,
-	0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001,
-	0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078,
-	0x6aa5, 0x20a3, 0x7f00, 0x0078, 0x6a93, 0x027e, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040,
-	0x6ac3, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810, 0xa085, 0x0100,
-	0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a, 0x2da6, 0x8d68, 0x2da6,
-	0x0d7f, 0x0078, 0x6ad2, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c, 0x6810,
-	0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078,
-	0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e,
-	0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071, 0xa300, 0x6130,
-	0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6afc, 0x6910,
-	0x6a14, 0x6430, 0x0078, 0x6b00, 0x6910, 0x6a14, 0x7368, 0x746c,
-	0x781c, 0xa086, 0x0006, 0x0040, 0x6b5f, 0xd5bc, 0x0040, 0x6b10,
-	0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6b17,
-	0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073,
-	0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
-	0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
-	0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
-	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
-	0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6b49, 0x6a00, 0xd2f4,
-	0x0040, 0x6b47, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6b49, 0x2011,
-	0x0000, 0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084,
-	0xfff0, 0xa005, 0x0040, 0x6b56, 0x2009, 0x1b58, 0x1078, 0x595f,
-	0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810,
-	0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6bb7,
-	0xd5bc, 0x0040, 0x6b73, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x0078, 0x6b7a, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b,
-	0x0000, 0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
-	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
-	0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
-	0x60c6, 0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080,
-	0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
-	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x6bb2, 0x6a00,
-	0xd2f4, 0x0040, 0x6bb0, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6bb2,
-	0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x6b4c, 0xd5bc,
-	0x0040, 0x6bc2, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
-	0x0078, 0x6bc9, 0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000,
-	0x646e, 0x1078, 0x488f, 0x0040, 0x6bdf, 0x0d7e, 0x7810, 0xa06d,
-	0x684c, 0x0d7f, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6bdf,
-	0x7824, 0xc0cd, 0x7826, 0x6073, 0x0889, 0x0078, 0x6be1, 0x6073,
-	0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
-	0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082,
-	0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
-	0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xa582, 0x0080, 0x0048, 0x6c0f, 0x6a00, 0xd2f4, 0x0040, 0x6c0d,
-	0x6a14, 0xa294, 0x00ff, 0x0078, 0x6c0f, 0x2011, 0x0000, 0x629e,
-	0x7824, 0xd0cc, 0x0040, 0x6c18, 0x6017, 0x0016, 0x0078, 0x6b4c,
-	0x6017, 0x0012, 0x0078, 0x6b4c, 0x7a18, 0xa280, 0x0023, 0x2014,
-	0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069,
-	0xa5ab, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3,
-	0x0056, 0x60a7, 0x9575, 0x1078, 0x6c38, 0x1078, 0x594f, 0x007c,
-	0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f,
-	0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004,
-	0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e,
-	0x017e, 0x027e, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194,
-	0x4000, 0x0040, 0x6c89, 0x1078, 0x6c41, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x0c7e, 0x2061, 0xa5ab, 0x6128, 0xa192, 0x00c8, 0x00c8,
-	0x6c76, 0x8108, 0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6c84,
-	0x1078, 0x594f, 0x1078, 0x6c38, 0x0078, 0x6c84, 0x6124, 0xa1e5,
-	0x0000, 0x0040, 0x6c81, 0x1078, 0xa241, 0x2009, 0x0014, 0x1078,
-	0x756c, 0x0c7f, 0x0078, 0x6c84, 0x027f, 0x017f, 0x0d7f, 0x0c7f,
-	0x007c, 0x2001, 0xa5c7, 0x2004, 0xa005, 0x00c0, 0x6c84, 0x0c7e,
-	0x2061, 0xa5ab, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6c76, 0x8108,
-	0x612a, 0x0c7f, 0x1078, 0x594f, 0x1078, 0x4171, 0x0078, 0x6c84,
-	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5967, 0x2071,
-	0xa5ab, 0x713c, 0x81ff, 0x0040, 0x6cca, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6cd0, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x037f,
-	0x713c, 0x2160, 0x1078, 0xa241, 0x2009, 0x004a, 0x1078, 0x756c,
-	0x0078, 0x6cca, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
-	0x0078, 0x6cba, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e, 0x047e,
-	0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071,
-	0xa5ab, 0x7018, 0x2068, 0x8dff, 0x0040, 0x6cfc, 0x68a0, 0xa406,
-	0x0040, 0x6cee, 0x6854, 0x2068, 0x0078, 0x6ce3, 0x6010, 0x2060,
-	0x643c, 0x6540, 0x6e48, 0x2d60, 0x1078, 0x466a, 0x0040, 0x6cfc,
-	0x1078, 0x7045, 0xa085, 0x0001, 0x127f, 0x007f, 0x047f, 0x057f,
-	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x6567, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
-	0xa086, 0x0004, 0x00c0, 0x6d17, 0x6098, 0x0078, 0x6d18, 0x6030,
-	0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
-	0x20a2, 0x00f0, 0x6d20, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x1078,
-	0x6c2d, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6567,
-	0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
-	0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c, 0x157e,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0200, 0x20a3,
-	0x0000, 0x20a9, 0x0006, 0x2011, 0xa340, 0x2019, 0xa341, 0x23a6,
-	0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0, 0x6d4f, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078, 0x6c2d, 0x147f,
-	0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b,
-	0x1078, 0x65cf, 0x1078, 0x65e6, 0x7810, 0xa080, 0x0000, 0x2004,
-	0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
-	0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6c2d, 0x027f, 0x017f,
-	0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x6567, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
-	0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x147f, 0x157f, 0x007c,
-	0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x6567,
-	0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
-	0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x1078, 0x6c2d,
-	0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e, 0x0c7e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x700c, 0x2060, 0x8cff,
-	0x0040, 0x6dd1, 0x1078, 0x8c3b, 0x00c0, 0x6dc8, 0x1078, 0x7a05,
-	0x600c, 0x007e, 0x1078, 0x753d, 0x1078, 0x7045, 0x0c7f, 0x0078,
-	0x6dbf, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f, 0x007f, 0x0c7f,
-	0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e,
-	0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079,
-	0x0140, 0x2071, 0xa5ab, 0x7024, 0x2060, 0x8cff, 0x0040, 0x6e2a,
-	0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x595a, 0x2009, 0x0013,
-	0x1078, 0x756c, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x6e0d,
-	0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6e1f, 0x7803,
-	0x1000, 0x7803, 0x0000, 0x0078, 0x6e1f, 0xd084, 0x0040, 0x6e14,
-	0x6827, 0x0001, 0x0078, 0x6e16, 0x00f0, 0x6dfc, 0x7804, 0xa084,
-	0x1000, 0x0040, 0x6e1f, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
-	0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
-	0x127f, 0x007c, 0x2001, 0xa300, 0x2004, 0xa096, 0x0001, 0x0040,
-	0x6e62, 0xa096, 0x0004, 0x0040, 0x6e62, 0x6817, 0x0008, 0x68c3,
-	0x0000, 0x2011, 0x4129, 0x1078, 0x58d4, 0x20a9, 0x01f4, 0x6824,
-	0xd094, 0x0040, 0x6e50, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000,
-	0x0040, 0x6e62, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x6e62,
-	0xd084, 0x0040, 0x6e57, 0x6827, 0x0001, 0x0078, 0x6e59, 0x00f0,
-	0x6e3f, 0x7804, 0xa084, 0x1000, 0x0040, 0x6e62, 0x7803, 0x0100,
-	0x7803, 0x0000, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x157f, 0x127f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e,
-	0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069,
-	0x0100, 0x2079, 0x0140, 0x2071, 0xa5ab, 0x703c, 0x2060, 0x8cff,
-	0x0040, 0x6ee8, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0,
-	0x6e86, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x1078, 0x5967, 0x1078,
-	0x1f31, 0x047e, 0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5,
-	0x2021, 0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
-	0x6eb7, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079,
-	0x0020, 0x2071, 0xa602, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012,
-	0x6816, 0x7803, 0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a,
-	0x057f, 0x047f, 0xa39d, 0x0000, 0x00c0, 0x6ec2, 0x2009, 0x0049,
-	0x1078, 0x756c, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x6ed5,
-	0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x6ee7, 0x7803,
-	0x1000, 0x7803, 0x0000, 0x0078, 0x6ee7, 0xd08c, 0x0040, 0x6edc,
-	0x6827, 0x0002, 0x0078, 0x6ede, 0x00f0, 0x6ec4, 0x7804, 0xa084,
-	0x1000, 0x0040, 0x6ee7, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
-	0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f,
-	0x127f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa5ab,
-	0x6a06, 0x127f, 0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000,
-	0x2069, 0xa5ab, 0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e,
-	0x0c7e, 0x067e, 0x007e, 0x127e, 0x2071, 0xa5ab, 0x7614, 0x2660,
-	0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x6f46, 0x601c, 0xa206,
-	0x00c0, 0x6f41, 0x7014, 0xac36, 0x00c0, 0x6f20, 0x660c, 0x7616,
-	0x7010, 0xac36, 0x00c0, 0x6f2e, 0x2c00, 0xaf36, 0x0040, 0x6f2c,
-	0x2f00, 0x7012, 0x0078, 0x6f2e, 0x7013, 0x0000, 0x660c, 0x067e,
-	0x2c00, 0xaf06, 0x0040, 0x6f37, 0x7e0e, 0x0078, 0x6f38, 0x2678,
-	0x600f, 0x0000, 0x1078, 0x8c01, 0x1078, 0x7045, 0x0c7f, 0x0078,
-	0x6f13, 0x2c78, 0x600c, 0x2060, 0x0078, 0x6f13, 0x127f, 0x007f,
-	0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0078, 0x6fa0, 0x157e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0078, 0x6fa0, 0x157e,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2, 0xa006,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x6fa0,
-	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810, 0x20a2,
-	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078,
-	0x6fa0, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x6806, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
-	0x1078, 0x7050, 0x60c3, 0x0020, 0x1078, 0x6c2d, 0x147f, 0x157f,
-	0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120,
-	0xd1b4, 0x00c0, 0x6fb8, 0xd1bc, 0x00c0, 0x7002, 0x0078, 0x7042,
-	0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069,
-	0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000,
-	0x0040, 0x6ff9, 0x6020, 0xd0b4, 0x0040, 0x6ff9, 0x6024, 0xd094,
-	0x00c0, 0x6ff9, 0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0,
-	0x6ff9, 0x00f0, 0x6fc5, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107,
-	0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b,
-	0xbc91, 0x6043, 0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024,
-	0xd094, 0x00c0, 0x6ff8, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x6fef,
-	0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000,
-	0x0078, 0x7042, 0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e,
-	0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804,
-	0xa084, 0x4000, 0x0040, 0x703b, 0x6020, 0xd0bc, 0x0040, 0x703b,
-	0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x703b, 0x00f0,
-	0x700f, 0x027e, 0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c,
-	0x00ff, 0xa10d, 0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043,
-	0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000,
-	0x00c0, 0x7035, 0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f,
-	0x200b, 0x0000, 0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa5ab,
-	0x7020, 0xa005, 0x0040, 0x704e, 0x8001, 0x7022, 0x0e7f, 0x007c,
-	0x20a9, 0x0008, 0x20a2, 0x00f0, 0x7052, 0x20a2, 0x20a2, 0x007c,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e,
-	0x2091, 0x8000, 0x2071, 0xa5ab, 0x7614, 0x2660, 0x2678, 0x2039,
-	0x0001, 0x87ff, 0x0040, 0x70f4, 0x8cff, 0x0040, 0x70f4, 0x601c,
-	0xa086, 0x0006, 0x00c0, 0x70ef, 0x88ff, 0x0040, 0x707f, 0x2800,
-	0xac06, 0x00c0, 0x70ef, 0x2039, 0x0000, 0x0078, 0x708a, 0x6018,
-	0xa206, 0x00c0, 0x70ef, 0x85ff, 0x0040, 0x708a, 0x6020, 0xa106,
-	0x00c0, 0x70ef, 0x7024, 0xac06, 0x00c0, 0x70ba, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x70b5, 0x1078, 0x595a, 0x6817, 0x0008,
-	0x68c3, 0x0000, 0x1078, 0x7188, 0x7027, 0x0000, 0x037e, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x70aa, 0x6803, 0x0100,
-	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x70b2,
-	0x6827, 0x0001, 0x037f, 0x0078, 0x70ba, 0x6003, 0x0009, 0x630a,
-	0x0078, 0x70ef, 0x7014, 0xac36, 0x00c0, 0x70c0, 0x660c, 0x7616,
-	0x7010, 0xac36, 0x00c0, 0x70ce, 0x2c00, 0xaf36, 0x0040, 0x70cc,
-	0x2f00, 0x7012, 0x0078, 0x70ce, 0x7013, 0x0000, 0x660c, 0x067e,
-	0x2c00, 0xaf06, 0x0040, 0x70d7, 0x7e0e, 0x0078, 0x70d8, 0x2678,
-	0x89ff, 0x00c0, 0x70e7, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x70e5, 0x1078, 0x9e70, 0x1078, 0x8c01, 0x1078,
-	0x7045, 0x88ff, 0x00c0, 0x70fe, 0x0c7f, 0x0078, 0x7069, 0x2c78,
-	0x600c, 0x2060, 0x0078, 0x7069, 0xa006, 0x127f, 0x007f, 0x067f,
-	0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000,
-	0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x70f5, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0xa5ab, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x7177, 0x601c,
-	0xa086, 0x0006, 0x00c0, 0x7172, 0x87ff, 0x0040, 0x7125, 0x2700,
-	0xac06, 0x00c0, 0x7172, 0x0078, 0x7130, 0x6018, 0xa206, 0x00c0,
-	0x7172, 0x85ff, 0x0040, 0x7130, 0x6020, 0xa106, 0x00c0, 0x7172,
-	0x703c, 0xac06, 0x00c0, 0x7142, 0x037e, 0x2019, 0x0001, 0x1078,
-	0x6e6c, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047,
-	0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7148, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x00c0, 0x7156, 0x2c00, 0xaf36, 0x0040, 0x7154,
-	0x2f00, 0x7036, 0x0078, 0x7156, 0x7037, 0x0000, 0x660c, 0x067e,
-	0x2c00, 0xaf06, 0x0040, 0x715f, 0x7e0e, 0x0078, 0x7160, 0x2678,
-	0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x716a,
-	0x1078, 0x9e70, 0x1078, 0x8c01, 0x87ff, 0x00c0, 0x7181, 0x0c7f,
-	0x0078, 0x7114, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7114, 0xa006,
-	0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7178,
-	0x0e7e, 0x2071, 0xa5ab, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002,
-	0x00c0, 0x7196, 0x7007, 0x0005, 0x0078, 0x7198, 0x7007, 0x0000,
-	0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0xa5ab, 0x2c10, 0x7638, 0x2660,
-	0x2678, 0x8cff, 0x0040, 0x71d8, 0x2200, 0xac06, 0x00c0, 0x71d3,
-	0x7038, 0xac36, 0x00c0, 0x71b6, 0x660c, 0x763a, 0x7034, 0xac36,
-	0x00c0, 0x71c4, 0x2c00, 0xaf36, 0x0040, 0x71c2, 0x2f00, 0x7036,
-	0x0078, 0x71c4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040,
-	0x71cc, 0x7e0e, 0x0078, 0x71cd, 0x2678, 0x600f, 0x0000, 0xa085,
-	0x0001, 0x0078, 0x71d8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x71a9,
-	0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091,
-	0x8000, 0x2071, 0xa5ab, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040,
-	0x7279, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7274,
-	0x7024, 0xac06, 0x00c0, 0x721f, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x724d, 0x1078, 0x6c41, 0x68c3, 0x0000, 0x1078, 0x7188,
-	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x7216, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x721e, 0x6827, 0x0001, 0x037f, 0x700c,
-	0xac36, 0x00c0, 0x7225, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0,
-	0x7233, 0x2c00, 0xaf36, 0x0040, 0x7231, 0x2f00, 0x700a, 0x0078,
-	0x7233, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
-	0x723c, 0x7e0e, 0x0078, 0x723d, 0x2678, 0x600f, 0x0000, 0x1078,
-	0x8c27, 0x00c0, 0x7251, 0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0,
-	0x726d, 0x1078, 0x7a05, 0x0078, 0x726d, 0x1078, 0x7188, 0x0078,
-	0x721f, 0x1078, 0x8c3b, 0x00c0, 0x7259, 0x1078, 0x7a05, 0x0078,
-	0x726d, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x726d, 0x601c,
-	0xa086, 0x0003, 0x00c0, 0x7281, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x1078, 0x8c01, 0x1078,
-	0x7045, 0x0c7f, 0x0078, 0x71ee, 0x2c78, 0x600c, 0x2060, 0x0078,
-	0x71ee, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x726d, 0x1078, 0x9e70,
-	0x0078, 0x726d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006,
-	0xa190, 0x0020, 0x221c, 0xa39e, 0x260c, 0x00c0, 0x729b, 0x8210,
-	0x8000, 0x0078, 0x7292, 0xa005, 0x0040, 0x72a7, 0x20a9, 0x0020,
-	0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f,
-	0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
-	0x65f8, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x2099, 0xa5a3, 0x20a9, 0x0004, 0x53a6,
-	0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x1078, 0x6c2d, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x65f8,
-	0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084,
-	0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6c2d,
-	0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x8ef5,
-	0x00c0, 0x7361, 0x20a1, 0x020b, 0x1078, 0x6567, 0x20a3, 0x1300,
-	0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040,
-	0x733d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
-	0x7317, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7352, 0xa286,
-	0x007f, 0x00c0, 0x7321, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078,
-	0x7352, 0xd2bc, 0x0040, 0x7337, 0xa286, 0x0080, 0x00c0, 0x732e,
-	0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7352, 0xa2e8, 0xa434,
-	0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7352, 0x20a3,
-	0x0000, 0x6098, 0x20a2, 0x0078, 0x7352, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa082, 0x007e, 0x0048, 0x734e, 0x0d7e, 0x2069, 0xa31a,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7352, 0x20a3, 0x0000,
-	0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6c2d, 0x017f, 0x0d7f,
-	0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c,
-	0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040,
-	0x738a, 0xa186, 0x0003, 0x0040, 0x73e5, 0xa186, 0x0005, 0x0040,
-	0x73c8, 0xa186, 0x0004, 0x0040, 0x73b8, 0xa186, 0x0008, 0x0040,
-	0x73d2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7450, 0x027f,
-	0x0d7f, 0x007c, 0x1078, 0x740d, 0x2009, 0x4000, 0x6800, 0x0079,
-	0x7391, 0x73a4, 0x73b2, 0x73a6, 0x73b2, 0x73ad, 0x73a4, 0x73a4,
-	0x73b2, 0x73b2, 0x73b2, 0x73b2, 0x73a4, 0x73a4, 0x73a4, 0x73a4,
-	0x73a4, 0x73b2, 0x73a4, 0x73b2, 0x1078, 0x1328, 0x6824, 0xd0e4,
-	0x0040, 0x73ad, 0xd0cc, 0x0040, 0x73b0, 0xa00e, 0x0078, 0x73b2,
-	0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x7403,
-	0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
-	0x6a00, 0xa286, 0x0002, 0x00c0, 0x73c6, 0xa00e, 0x0078, 0x7403,
-	0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
-	0x0078, 0x7403, 0x1078, 0x740d, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x73e2, 0xa286, 0x0002,
-	0x00c0, 0x73e3, 0xa00e, 0x0078, 0x7403, 0x1078, 0x740d, 0x6810,
-	0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2,
-	0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040,
-	0x7401, 0xa08e, 0x0004, 0x0040, 0x7401, 0x2009, 0x4000, 0x0078,
-	0x7403, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018,
-	0x1078, 0x6c2d, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e,
-	0x067e, 0x20a1, 0x020b, 0x1078, 0x65f8, 0xa006, 0x20a3, 0x0200,
-	0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa092, 0x007e, 0x0048, 0x7433, 0x0d7e, 0x2069, 0xa31a,
-	0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa434, 0x2d6c, 0x6b10, 0x6c14,
-	0x0d7f, 0x0078, 0x7439, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000,
-	0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x7447, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x744b, 0x23a2,
-	0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x65f8, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x655e, 0x20a3, 0x1400, 0x20a3,
-	0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c,
-	0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000,
-	0x60c3, 0x0010, 0x1078, 0x6c2d, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x65ef, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810,
-	0x20a2, 0x60c3, 0x0008, 0x1078, 0x6c2d, 0x007c, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x7499, 0x60c3, 0x0000, 0x1078, 0x6c2d, 0x147f,
-	0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x74b6, 0x0d7e, 0xa0e8, 0xa434, 0x2d6c,
-	0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa31a,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x74be, 0x20a3, 0x0300,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819,
-	0x20a3, 0x0000, 0x1078, 0x6c1c, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
-	0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061,
-	0xaa00, 0x2a70, 0x7060, 0x7046, 0x704b, 0xaa00, 0x007c, 0x0e7e,
-	0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582, 0x0010,
-	0x0048, 0x7509, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040,
-	0x74f5, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x74f1, 0x0078,
-	0x74e4, 0x2061, 0xaa00, 0x0078, 0x74e4, 0x6003, 0x0008, 0x8529,
-	0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x7505, 0x754a,
-	0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00, 0x0078,
-	0x7500, 0xa006, 0x0078, 0x7502, 0x0e7e, 0x2071, 0xa300, 0x7544,
-	0xa582, 0x0010, 0x0048, 0x753a, 0x7048, 0x2060, 0x6000, 0xa086,
-	0x0000, 0x0040, 0x7527, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
-	0x7523, 0x0078, 0x7516, 0x2061, 0xaa00, 0x0078, 0x7516, 0x6003,
-	0x0008, 0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8,
-	0x7536, 0x754a, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704b, 0xaa00,
-	0x0078, 0x7532, 0xa006, 0x0078, 0x7534, 0xac82, 0xaa00, 0x1048,
-	0x1328, 0x2001, 0xa315, 0x2004, 0xac02, 0x10c8, 0x1328, 0xa006,
-	0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000,
-	0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036,
-	0x603a, 0x603e, 0x2061, 0xa300, 0x6044, 0x8000, 0x6046, 0xa086,
-	0x0001, 0x0040, 0x7564, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x6109, 0x127f, 0x0078, 0x7563, 0x601c, 0xa084, 0x000f, 0x0079,
-	0x7571, 0x757a, 0x758b, 0x75a7, 0x75c3, 0x8f2d, 0x8f49, 0x8f65,
-	0x757a, 0x758b, 0xa186, 0x0013, 0x00c0, 0x7583, 0x1078, 0x6010,
-	0x1078, 0x6109, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x758a, 0xa016,
-	0x1078, 0x15ec, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x1328, 0x1079, 0x7595, 0x067f, 0x007c, 0x75a5, 0x7891, 0x7a34,
-	0x75a5, 0x7ab8, 0x75df, 0x75a5, 0x75a5, 0x7823, 0x7e6d, 0x75a5,
-	0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x75a5, 0x1078, 0x1328, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079, 0x75b1, 0x067f,
-	0x007c, 0x75c1, 0x8522, 0x75c1, 0x75c1, 0x75c1, 0x75c1, 0x75c1,
-	0x75c1, 0x84c5, 0x86a8, 0x75c1, 0x8552, 0x85d8, 0x8552, 0x85d8,
-	0x75c1, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x1328, 0x1079, 0x75cd, 0x067f, 0x007c, 0x75dd, 0x7eb4, 0x7f81,
-	0x80c6, 0x8242, 0x75dd, 0x75dd, 0x75dd, 0x7e8d, 0x846d, 0x8471,
-	0x75dd, 0x75dd, 0x75dd, 0x75dd, 0x84a1, 0x1078, 0x1328, 0xa1b6,
-	0x0015, 0x00c0, 0x75e7, 0x1078, 0x753d, 0x0078, 0x75ed, 0xa1b6,
-	0x0016, 0x10c0, 0x1328, 0x1078, 0x753d, 0x007c, 0x20a9, 0x000e,
-	0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
-	0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
-	0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x75fc,
-	0x0e7e, 0x1078, 0x8a44, 0x0040, 0x7613, 0x6010, 0x2070, 0x7007,
-	0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c, 0x0d7e,
-	0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7624, 0x6018, 0x2068,
-	0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x762e,
-	0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x753d,
-	0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c,
-	0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a,
-	0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3,
-	0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078,
-	0x753d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68,
-	0x017e, 0x2009, 0x0035, 0x1078, 0x8ef5, 0x017f, 0x00c0, 0x766f,
-	0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xa88c, 0x6b1c, 0xa386,
-	0x0003, 0x0040, 0x7673, 0xa386, 0x0006, 0x0040, 0x7677, 0x1078,
-	0x753d, 0x0078, 0x7679, 0x1078, 0x767c, 0x0078, 0x7679, 0x1078,
-	0x771e, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186,
-	0x0015, 0x0040, 0x7705, 0xa18e, 0x0016, 0x00c0, 0x771c, 0x700c,
-	0xa084, 0xff00, 0xa086, 0x1700, 0x00c0, 0x76e0, 0x8fff, 0x0040,
-	0x771a, 0x6808, 0xa086, 0xffff, 0x00c0, 0x7709, 0x784c, 0xa084,
-	0x0060, 0xa086, 0x0020, 0x00c0, 0x76a7, 0x797c, 0x7810, 0xa106,
-	0x00c0, 0x7709, 0x7980, 0x7814, 0xa106, 0x00c0, 0x7709, 0x1078,
-	0x8bf4, 0x6830, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e,
-	0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x1078, 0x5a98, 0x7854,
-	0xa20a, 0x0048, 0x76bc, 0x8011, 0x7a56, 0x82ff, 0x027f, 0x00c0,
-	0x76c8, 0x0c7e, 0x2d60, 0x1078, 0x8832, 0x0c7f, 0x0078, 0x771a,
-	0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc, 0x00c0, 0x76d3, 0x1078,
-	0x4290, 0x0078, 0x76d5, 0x1078, 0x436e, 0x0d7f, 0x0c7f, 0x00c0,
-	0x7709, 0x0c7e, 0x2d60, 0x1078, 0x753d, 0x0c7f, 0x0078, 0x771a,
-	0x7008, 0xa086, 0x000b, 0x00c0, 0x76fa, 0x6018, 0x200c, 0xc1bc,
-	0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003,
-	0x000b, 0x601f, 0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f,
-	0x0078, 0x771a, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7709, 0x2001,
-	0xa5a2, 0x2004, 0x683e, 0x0078, 0x771a, 0x1078, 0x7739, 0x0078,
-	0x771c, 0x8fff, 0x1040, 0x1328, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68,
-	0x684b, 0x0003, 0x1078, 0x8726, 0x1078, 0x8bf4, 0x1078, 0x8c01,
-	0x0d7f, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0xa186, 0x0015,
-	0x00c0, 0x7728, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x7736,
-	0xa18e, 0x0016, 0x00c0, 0x7738, 0x0c7e, 0x2d00, 0x2060, 0x1078,
-	0xa134, 0x1078, 0x5a41, 0x1078, 0x753d, 0x0c7f, 0x1078, 0x753d,
-	0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80, 0x7b7c, 0xd2f4,
-	0x0040, 0x7748, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x0078, 0x77ac,
-	0x0c7e, 0x2d60, 0x1078, 0x874a, 0x0c7f, 0x6804, 0xa086, 0x0050,
-	0x00c0, 0x7760, 0x0c7e, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
-	0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x77ac,
-	0x6800, 0xa086, 0x000f, 0x0040, 0x7782, 0x8fff, 0x1040, 0x1328,
-	0x6824, 0xd0dc, 0x00c0, 0x7782, 0x6800, 0xa086, 0x0004, 0x00c0,
-	0x7787, 0x784c, 0xd0ac, 0x0040, 0x7787, 0x784c, 0xc0dc, 0xc0f4,
-	0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001, 0x0001, 0x682e,
-	0x0078, 0x77a6, 0x2001, 0x0007, 0x682e, 0x0078, 0x77a6, 0x784c,
-	0xd0b4, 0x00c0, 0x7794, 0xd0ac, 0x0040, 0x7782, 0x784c, 0xd0f4,
-	0x00c0, 0x7782, 0x0078, 0x7775, 0xd2ec, 0x00c0, 0x7782, 0x7024,
-	0xa306, 0x00c0, 0x779f, 0x7020, 0xa406, 0x0040, 0x7782, 0x7020,
-	0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x1078, 0x8d2b,
-	0x1078, 0x6109, 0x0078, 0x77ae, 0x1078, 0x753d, 0x047f, 0x037f,
-	0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034, 0x2068, 0x6a1c,
-	0xa286, 0x0007, 0x0040, 0x7806, 0xa286, 0x0002, 0x0040, 0x7806,
-	0xa286, 0x0000, 0x0040, 0x7806, 0x6808, 0x6338, 0xa306, 0x00c0,
-	0x7806, 0x2071, 0xa88c, 0xa186, 0x0015, 0x0040, 0x7800, 0xa18e,
-	0x0016, 0x00c0, 0x77e8, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001,
-	0x00c0, 0x77e8, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x77e8, 0x6034,
-	0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102, 0x0078, 0x7800,
-	0x0c7e, 0x6034, 0x2060, 0x6010, 0x2068, 0x1078, 0x8a44, 0x1040,
-	0x1328, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
-	0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7f, 0x0078, 0x7806,
-	0x6034, 0x2068, 0x2001, 0xa5a2, 0x2004, 0x683e, 0x1078, 0x753d,
-	0x027f, 0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98,
-	0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7820, 0x6018,
-	0x2068, 0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802,
-	0x0d7f, 0x0078, 0x7608, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1328,
-	0xa1b2, 0x0040, 0x00c8, 0x7888, 0x0079, 0x782e, 0x787c, 0x7870,
-	0x787c, 0x787c, 0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e,
-	0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
-	0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
-	0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x787c,
-	0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x787c, 0x786e,
-	0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
-	0x787c, 0x787c, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e, 0x786e,
-	0x786e, 0x786e, 0x786e, 0x787c, 0x786e, 0x786e, 0x1078, 0x1328,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x5c45, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x5c45, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c,
-	0x2600, 0x0079, 0x788b, 0x788f, 0x788f, 0x788f, 0x787c, 0x1078,
-	0x1328, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328, 0xa1b6, 0x0013,
-	0x00c0, 0x78a1, 0xa0b2, 0x0040, 0x00c8, 0x79fb, 0x2008, 0x0079,
-	0x7941, 0xa1b6, 0x0027, 0x00c0, 0x78fe, 0x1078, 0x6010, 0x6004,
-	0x1078, 0x8c27, 0x0040, 0x78be, 0x1078, 0x8c3b, 0x0040, 0x78f6,
-	0xa08e, 0x0021, 0x0040, 0x78fa, 0xa08e, 0x0022, 0x0040, 0x78f6,
-	0xa08e, 0x003d, 0x0040, 0x78fa, 0x0078, 0x78f1, 0x1078, 0x2839,
-	0x2001, 0x0007, 0x1078, 0x443f, 0x6018, 0xa080, 0x0028, 0x200c,
-	0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x78d3, 0x2001, 0xa332,
-	0x2014, 0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019,
-	0x0028, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078, 0x5c78,
-	0x0c7e, 0x6018, 0xa065, 0x0040, 0x78e7, 0x1078, 0x471b, 0x0c7f,
-	0x2c08, 0x1078, 0x9c38, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078,
-	0x44bc, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x7a05,
-	0x0078, 0x78f1, 0x1078, 0x7a28, 0x0078, 0x78f1, 0xa186, 0x0014,
-	0x00c0, 0x78f5, 0x1078, 0x6010, 0x1078, 0x2813, 0x1078, 0x8c27,
-	0x00c0, 0x791d, 0x1078, 0x2839, 0x6018, 0xa080, 0x0028, 0x200c,
-	0x1078, 0x7a05, 0xa186, 0x007e, 0x00c0, 0x791b, 0x2001, 0xa332,
-	0x200c, 0xc185, 0x2102, 0x0078, 0x78f1, 0x1078, 0x8c3b, 0x00c0,
-	0x7925, 0x1078, 0x7a05, 0x0078, 0x78f1, 0x6004, 0xa08e, 0x0032,
-	0x00c0, 0x7936, 0x0e7e, 0x0f7e, 0x2071, 0xa381, 0x2079, 0x0000,
-	0x1078, 0x2b56, 0x0f7f, 0x0e7f, 0x0078, 0x78f1, 0x6004, 0xa08e,
-	0x0021, 0x0040, 0x7921, 0xa08e, 0x0022, 0x1040, 0x7a05, 0x0078,
-	0x78f1, 0x7983, 0x7985, 0x7989, 0x798d, 0x7991, 0x7995, 0x7981,
-	0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
-	0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
-	0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981, 0x7999,
-	0x79ab, 0x7981, 0x79ad, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981,
-	0x7981, 0x79ab, 0x79ab, 0x7981, 0x7981, 0x7981, 0x7981, 0x7981,
-	0x7981, 0x7981, 0x7981, 0x79de, 0x79ab, 0x7981, 0x79a5, 0x7981,
-	0x7981, 0x7981, 0x79a7, 0x7981, 0x7981, 0x7981, 0x79ab, 0x7981,
-	0x7981, 0x1078, 0x1328, 0x0078, 0x79ab, 0x2001, 0x000b, 0x0078,
-	0x79b8, 0x2001, 0x0003, 0x0078, 0x79b8, 0x2001, 0x0005, 0x0078,
-	0x79b8, 0x2001, 0x0001, 0x0078, 0x79b8, 0x2001, 0x0009, 0x0078,
-	0x79b8, 0x1078, 0x6010, 0x6003, 0x0005, 0x2001, 0xa5a2, 0x2004,
-	0x603e, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0078, 0x79ab, 0x0078,
-	0x79ab, 0x1078, 0x443f, 0x0078, 0x79f0, 0x1078, 0x6010, 0x6003,
-	0x0004, 0x2001, 0xa5a0, 0x2004, 0x6016, 0x1078, 0x6109, 0x007c,
-	0x1078, 0x443f, 0x1078, 0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e,
-	0x6003, 0x0002, 0x037e, 0x2019, 0xa35c, 0x2304, 0xa084, 0xff00,
-	0x00c0, 0x79cf, 0x2019, 0xa5a0, 0x231c, 0x0078, 0x79d8, 0x8007,
-	0xa09a, 0x0004, 0x0048, 0x79ca, 0x8003, 0x801b, 0x831b, 0xa318,
-	0x6316, 0x037f, 0x1078, 0x6109, 0x0078, 0x79b7, 0x0e7e, 0x0f7e,
-	0x2071, 0xa381, 0x2079, 0x0000, 0x1078, 0x2b56, 0x0f7f, 0x0e7f,
-	0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x0078, 0x79b7,
-	0x1078, 0x6010, 0x6003, 0x0002, 0x2001, 0xa5a0, 0x2004, 0x6016,
-	0x1078, 0x6109, 0x007c, 0x2600, 0x2008, 0x0079, 0x79ff, 0x7a03,
-	0x7a03, 0x7a03, 0x79f0, 0x1078, 0x1328, 0x0e7e, 0x1078, 0x8a44,
-	0x0040, 0x7a21, 0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7a21,
-	0x7007, 0x0000, 0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7a23,
-	0xa08e, 0x003d, 0x0040, 0x7a23, 0x017f, 0x7037, 0x0103, 0x7033,
-	0x0100, 0x0e7f, 0x007c, 0x017f, 0x1078, 0x7a28, 0x0078, 0x7a21,
-	0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103,
-	0x7023, 0x8001, 0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804,
-	0xa084, 0x00ff, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0x6604,
-	0xa6b6, 0x0043, 0x00c0, 0x7a48, 0x1078, 0x8e6d, 0x0078, 0x7aa7,
-	0x6604, 0xa6b6, 0x0033, 0x00c0, 0x7a51, 0x1078, 0x8e11, 0x0078,
-	0x7aa7, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x7a5a, 0x1078, 0x8c6a,
-	0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7a63, 0x1078,
-	0x8c84, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7a6c,
-	0x1078, 0x75ee, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0000, 0x00c0,
-	0x7a75, 0x1078, 0x780c, 0x0078, 0x7aa7, 0x6604, 0xa6b6, 0x0022,
-	0x00c0, 0x7a7e, 0x1078, 0x7617, 0x0078, 0x7aa7, 0x6604, 0xa6b6,
-	0x0035, 0x00c0, 0x7a87, 0x1078, 0x7653, 0x0078, 0x7aa7, 0x6604,
-	0xa6b6, 0x0039, 0x00c0, 0x7a90, 0x1078, 0x77b2, 0x0078, 0x7aa7,
-	0x6604, 0xa6b6, 0x003d, 0x00c0, 0x7a99, 0x1078, 0x7633, 0x0078,
-	0x7aa7, 0xa1b6, 0x0015, 0x00c0, 0x7aa1, 0x1079, 0x7aac, 0x0078,
-	0x7aa7, 0xa1b6, 0x0016, 0x00c0, 0x7aa8, 0x1079, 0x7bfd, 0x007c,
-	0x1078, 0x7583, 0x0078, 0x7aa7, 0x7ad0, 0x7ad3, 0x7ad0, 0x7b1e,
-	0x7ad0, 0x7b91, 0x7c09, 0x7ad0, 0x7ad0, 0x7bd5, 0x7ad0, 0x7beb,
-	0xa1b6, 0x0048, 0x0040, 0x7ac4, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x15ec, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74,
-	0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x753d, 0x007c,
-	0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086,
-	0x0074, 0x00c0, 0x7b07, 0x1078, 0x9c0c, 0x00c0, 0x7af9, 0x0d7e,
-	0x6018, 0x2068, 0x7030, 0xd08c, 0x0040, 0x7aec, 0x6800, 0xd0bc,
-	0x0040, 0x7aec, 0xc0c5, 0x6802, 0x1078, 0x7b0b, 0x0d7f, 0x2001,
-	0x0006, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078,
-	0x7b09, 0x2001, 0x000a, 0x1078, 0x443f, 0x1078, 0x2839, 0x6003,
-	0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7b09, 0x1078,
-	0x7b81, 0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x7b1d, 0x2001,
-	0x0000, 0x1078, 0x442b, 0x2069, 0xa351, 0x6804, 0xd0a4, 0x0040,
-	0x7b1d, 0x2001, 0x0006, 0x1078, 0x4472, 0x007c, 0x0d7e, 0x2011,
-	0xa31f, 0x2204, 0xa086, 0x0074, 0x00c0, 0x7b7d, 0x6018, 0x2068,
-	0x6aa0, 0xa286, 0x007e, 0x00c0, 0x7b31, 0x1078, 0x7d17, 0x0078,
-	0x7b7f, 0x1078, 0x7d0d, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014,
-	0xa286, 0x0080, 0x00c0, 0x7b55, 0x6813, 0x00ff, 0x6817, 0xfffc,
-	0x6010, 0xa005, 0x0040, 0x7b4b, 0x2068, 0x6807, 0x0000, 0x6837,
-	0x0103, 0x6833, 0x0200, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
-	0x2839, 0x1078, 0x753d, 0x0078, 0x7b7f, 0x0e7e, 0x2071, 0xa332,
-	0x2e04, 0xd09c, 0x0040, 0x7b70, 0x2071, 0xa880, 0x7108, 0x720c,
-	0xa18c, 0x00ff, 0x00c0, 0x7b68, 0xa284, 0xff00, 0x0040, 0x7b70,
-	0x6018, 0x2070, 0x70a0, 0xd0bc, 0x00c0, 0x7b70, 0x7112, 0x7216,
-	0x0e7f, 0x2001, 0x0004, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
-	0x0003, 0x1078, 0x5c45, 0x0078, 0x7b7f, 0x1078, 0x7b81, 0x0d7f,
-	0x007c, 0x2001, 0xa300, 0x2004, 0xa086, 0x0003, 0x0040, 0x7b8c,
-	0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x2839, 0x1078, 0x753d,
-	0x007c, 0x0e7e, 0x2071, 0xa300, 0x707c, 0xa086, 0x0014, 0x00c0,
-	0x7bcf, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7ba4, 0x6010, 0xa005,
-	0x00c0, 0x7ba4, 0x1078, 0x35f7, 0x0d7e, 0x6018, 0x2068, 0x1078,
-	0x457d, 0x1078, 0x7b0b, 0x0d7f, 0x1078, 0x7dba, 0x00c0, 0x7bcf,
-	0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x7bcf,
-	0x2001, 0x0006, 0x1078, 0x443f, 0x0e7e, 0x6010, 0xa005, 0x0040,
-	0x7bc8, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200,
-	0x0e7f, 0x1078, 0x2839, 0x1078, 0x753d, 0x0078, 0x7bd3, 0x1078,
-	0x7a05, 0x1078, 0x7b81, 0x0e7f, 0x007c, 0x2011, 0xa31f, 0x2204,
-	0xa086, 0x0014, 0x00c0, 0x7be8, 0x2001, 0x0002, 0x1078, 0x443f,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7bea,
-	0x1078, 0x7b81, 0x007c, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0004,
-	0x00c0, 0x7bfa, 0x2001, 0x0007, 0x1078, 0x443f, 0x1078, 0x753d,
-	0x0078, 0x7bfc, 0x1078, 0x7b81, 0x007c, 0x7ad0, 0x7c11, 0x7ad0,
-	0x7c4e, 0x7ad0, 0x7cc0, 0x7c09, 0x7ad0, 0x7ad0, 0x7cd5, 0x7ad0,
-	0x7ce8, 0x6604, 0xa6b6, 0x001e, 0x00c0, 0x7c10, 0x1078, 0x753d,
-	0x007c, 0x0d7e, 0x0c7e, 0x1078, 0x7cfb, 0x00c0, 0x7c27, 0x2001,
-	0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x0078, 0x7c4b, 0x2009,
-	0xa88e, 0x2104, 0xa086, 0x0009, 0x00c0, 0x7c3c, 0x6018, 0x2068,
-	0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x7c49, 0x8001, 0x6842,
-	0x6017, 0x000a, 0x0078, 0x7c4b, 0x2009, 0xa88f, 0x2104, 0xa084,
-	0xff00, 0xa086, 0x1900, 0x00c0, 0x7c49, 0x1078, 0x753d, 0x0078,
-	0x7c4b, 0x1078, 0x7b81, 0x0c7f, 0x0d7f, 0x007c, 0x1078, 0x7d0a,
-	0x00c0, 0x7c62, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002,
-	0x1078, 0x443f, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x5c45,
-	0x0078, 0x7c8e, 0x1078, 0x7a05, 0x2009, 0xa88e, 0x2134, 0xa6b4,
-	0x00ff, 0xa686, 0x0005, 0x0040, 0x7c8f, 0xa686, 0x000b, 0x0040,
-	0x7c8c, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0x00c0, 0x7c7c,
-	0xa686, 0x0009, 0x0040, 0x7c8f, 0xa086, 0x1900, 0x00c0, 0x7c8c,
-	0xa686, 0x0009, 0x0040, 0x7c8f, 0x2001, 0x0004, 0x1078, 0x443f,
-	0x1078, 0x753d, 0x0078, 0x7c8e, 0x1078, 0x7b81, 0x007c, 0x0d7e,
-	0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x7c9d, 0x6838, 0xd0fc,
-	0x0040, 0x7c9d, 0x0d7f, 0x0078, 0x7c8c, 0x6018, 0x2068, 0x6840,
-	0xa084, 0x00ff, 0xa005, 0x0040, 0x7cae, 0x8001, 0x6842, 0x6017,
-	0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x7c8e, 0x68a0, 0xa086,
-	0x007e, 0x00c0, 0x7cbb, 0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5,
-	0x0e7f, 0x0078, 0x7cbd, 0x1078, 0x2813, 0x0d7f, 0x0078, 0x7c8c,
-	0x1078, 0x7d0a, 0x00c0, 0x7cd0, 0x2001, 0x0004, 0x1078, 0x443f,
-	0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x5c45, 0x0078, 0x7cd4,
-	0x1078, 0x7a05, 0x1078, 0x7b81, 0x007c, 0x1078, 0x7d0a, 0x00c0,
-	0x7ce5, 0x2001, 0x0008, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
-	0x0005, 0x1078, 0x5c45, 0x0078, 0x7ce7, 0x1078, 0x7b81, 0x007c,
-	0x1078, 0x7d0a, 0x00c0, 0x7cf8, 0x2001, 0x000a, 0x1078, 0x443f,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5c45, 0x0078, 0x7cfa,
-	0x1078, 0x7b81, 0x007c, 0x2009, 0xa88e, 0x2104, 0xa086, 0x0003,
-	0x00c0, 0x7d09, 0x2009, 0xa88f, 0x2104, 0xa084, 0xff00, 0xa086,
-	0x2a00, 0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88,
-	0x0006, 0x2164, 0x1078, 0x4513, 0x017f, 0x0c7f, 0x007c, 0x0f7e,
-	0x0e7e, 0x0d7e, 0x037e, 0x017e, 0x6018, 0x2068, 0x2071, 0xa332,
-	0x2e04, 0xa085, 0x0003, 0x2072, 0x1078, 0x7d8b, 0x0040, 0x7d50,
-	0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x7d39, 0xa006, 0x2020,
-	0x2009, 0x002a, 0x1078, 0x9ec0, 0x2001, 0xa30c, 0x200c, 0xc195,
-	0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x27e2, 0x2071,
-	0xa300, 0x1078, 0x260d, 0x0c7e, 0x157e, 0x20a9, 0x0081, 0x2009,
-	0x007f, 0x1078, 0x2921, 0x8108, 0x00f0, 0x7d49, 0x157f, 0x0c7f,
-	0x1078, 0x7d0d, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071, 0xa880,
-	0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa31a, 0x206a,
-	0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa31b, 0x206a, 0x78ea,
-	0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa325, 0x200a, 0x2069,
-	0xa88e, 0x2071, 0xa59c, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
-	0x700a, 0x681c, 0x700e, 0x1078, 0x8da9, 0x2001, 0x0006, 0x1078,
-	0x443f, 0x1078, 0x2839, 0x1078, 0x753d, 0x017f, 0x037f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e, 0x2019,
-	0xa325, 0x231c, 0x83ff, 0x0040, 0x7db5, 0x2071, 0xa880, 0x2e14,
-	0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x00c0,
-	0x7db5, 0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078,
-	0x7e55, 0x00c0, 0x7db5, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9,
-	0x0004, 0x1078, 0x7e55, 0x00c0, 0x7db5, 0x157f, 0x0e7f, 0x037f,
-	0x027f, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7004, 0xa086, 0x0014,
-	0x00c0, 0x7ddd, 0x7008, 0xa086, 0x0800, 0x00c0, 0x7ddd, 0x700c,
-	0xd0ec, 0x0040, 0x7ddb, 0xa084, 0x0f00, 0xa086, 0x0100, 0x00c0,
-	0x7ddb, 0x7024, 0xd0a4, 0x00c0, 0x7dd8, 0xd0ac, 0x0040, 0x7ddb,
-	0xa006, 0x0078, 0x7ddd, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x0e7e,
-	0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e, 0x127e,
-	0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba, 0x2424,
-	0x2061, 0xaa00, 0x2071, 0xa300, 0x7244, 0x7060, 0xa202, 0x00c8,
-	0x7e43, 0x1078, 0x9ee5, 0x0040, 0x7e3b, 0x671c, 0xa786, 0x0001,
-	0x0040, 0x7e3b, 0xa786, 0x0007, 0x0040, 0x7e3b, 0x2500, 0xac06,
-	0x0040, 0x7e3b, 0x2400, 0xac06, 0x0040, 0x7e3b, 0x0c7e, 0x6000,
-	0xa086, 0x0004, 0x00c0, 0x7e16, 0x1078, 0x1749, 0xa786, 0x0008,
-	0x00c0, 0x7e25, 0x1078, 0x8c3b, 0x00c0, 0x7e25, 0x0c7f, 0x1078,
-	0x7a05, 0x1078, 0x8c01, 0x0078, 0x7e3b, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x7e38, 0xa786, 0x0003, 0x00c0, 0x7e4d, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4,
-	0x1078, 0x8c01, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
-	0x7e43, 0x0078, 0x7df4, 0x127f, 0x007f, 0x027f, 0x047f, 0x057f,
-	0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
-	0x7e2f, 0x1078, 0x9e70, 0x0078, 0x7e38, 0x220c, 0x2304, 0xa106,
-	0x00c0, 0x7e60, 0x8210, 0x8318, 0x00f0, 0x7e55, 0xa006, 0x007c,
-	0x2304, 0xa102, 0x0048, 0x7e68, 0x2001, 0x0001, 0x0078, 0x7e6a,
-	0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a, 0x0044,
-	0x10c8, 0x1328, 0x1078, 0x8c27, 0x0040, 0x7e7c, 0x1078, 0x8c3b,
-	0x0040, 0x7e89, 0x0078, 0x7e82, 0x1078, 0x2839, 0x1078, 0x8c3b,
-	0x0040, 0x7e89, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
-	0x007c, 0x1078, 0x7a05, 0x0078, 0x7e82, 0xa182, 0x0040, 0x0079,
-	0x7e91, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4,
-	0x7ea4, 0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x7ea6, 0x7ea6, 0x7ea6,
-	0x7ea4, 0x7ea4, 0x7ea4, 0x7ea6, 0x1078, 0x1328, 0x600b, 0xffff,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x6109, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x7ebd,
-	0x6004, 0xa082, 0x0040, 0x0079, 0x7f48, 0xa186, 0x0027, 0x00c0,
-	0x7edf, 0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168,
-	0x1078, 0x8a44, 0x0040, 0x7ed9, 0x6837, 0x0103, 0x684b, 0x0029,
-	0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4982, 0x1078,
-	0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0xa186,
-	0x0014, 0x00c0, 0x7ee8, 0x6004, 0xa082, 0x0040, 0x0079, 0x7f10,
-	0xa186, 0x0046, 0x0040, 0x7ef4, 0xa186, 0x0045, 0x0040, 0x7ef4,
-	0xa186, 0x0047, 0x10c0, 0x1328, 0x2001, 0x0109, 0x2004, 0xd084,
-	0x0040, 0x7f0d, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e,
-	0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086,
-	0x0002, 0x00c0, 0x7f0d, 0x0078, 0x7f81, 0x1078, 0x7583, 0x007c,
-	0x7f25, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23, 0x7f23,
-	0x7f23, 0x7f23, 0x7f23, 0x7f41, 0x7f41, 0x7f41, 0x7f41, 0x7f23,
-	0x7f41, 0x7f23, 0x7f41, 0x1078, 0x1328, 0x1078, 0x6010, 0x0d7e,
-	0x6110, 0x2168, 0x1078, 0x8a44, 0x0040, 0x7f3b, 0x6837, 0x0103,
-	0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x1078,
-	0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109,
-	0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109, 0x007c,
-	0x7f5d, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b, 0x7f5b,
-	0x7f5b, 0x7f5b, 0x7f5b, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f6f, 0x7f5b,
-	0x7f7a, 0x7f5b, 0x7f6f, 0x1078, 0x1328, 0x1078, 0x6010, 0x2001,
-	0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x6109, 0x6010,
-	0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078,
-	0x6010, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x000f, 0x1078,
-	0x6109, 0x007c, 0x1078, 0x6010, 0x1078, 0x753d, 0x1078, 0x6109,
-	0x007c, 0xa182, 0x0040, 0x0079, 0x7f85, 0x7f98, 0x7f98, 0x7f98,
-	0x7f98, 0x7f98, 0x7f9a, 0x8095, 0x80b7, 0x7f98, 0x7f98, 0x7f98,
-	0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98, 0x7f98,
-	0x1078, 0x1328, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2071, 0xa880,
-	0x7124, 0x610a, 0x2071, 0xa88c, 0x6110, 0x2168, 0x7614, 0xa6b4,
-	0x0fff, 0x86ff, 0x0040, 0x8058, 0xa68c, 0x0c00, 0x0040, 0x7fd1,
-	0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x7fcd, 0x684c,
-	0xd0ac, 0x0040, 0x7fcd, 0x6024, 0xd0dc, 0x00c0, 0x7fcd, 0x6850,
-	0xd0bc, 0x00c0, 0x7fcd, 0x7318, 0x6814, 0xa306, 0x00c0, 0x806f,
-	0x731c, 0x6810, 0xa306, 0x00c0, 0x806f, 0x7318, 0x6b62, 0x731c,
-	0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x8004, 0xa186,
-	0x0028, 0x00c0, 0x7fe1, 0x1078, 0x8c15, 0x684b, 0x001c, 0x0078,
-	0x8006, 0xd6dc, 0x0040, 0x7ffd, 0x684b, 0x0015, 0x684c, 0xd0ac,
-	0x0040, 0x7ffb, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x7ffb,
-	0x7018, 0xa106, 0x00c0, 0x7ff8, 0x701c, 0xa206, 0x0040, 0x7ffb,
-	0x6962, 0x6a5e, 0xc6dc, 0x0078, 0x8006, 0xd6d4, 0x0040, 0x8004,
-	0x684b, 0x0007, 0x0078, 0x8006, 0x684b, 0x0000, 0x6837, 0x0103,
-	0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x802f, 0xa686, 0x0100, 0x00c0,
-	0x801a, 0x2001, 0xa899, 0x2004, 0xa005, 0x00c0, 0x801a, 0xc6c4,
-	0x0078, 0x7fa9, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x802f,
-	0xa38a, 0x0009, 0x0048, 0x8026, 0x2019, 0x0008, 0x037e, 0x2308,
-	0x2019, 0xa898, 0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc,
-	0x0040, 0x8085, 0x7124, 0x695a, 0x81ff, 0x0040, 0x8085, 0xa192,
-	0x0021, 0x00c8, 0x8046, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18,
-	0xad90, 0x001d, 0x1078, 0x8739, 0x0078, 0x8085, 0x6838, 0xd0fc,
-	0x0040, 0x804f, 0x2009, 0x0020, 0x695a, 0x0078, 0x803b, 0x0f7e,
-	0x2d78, 0x1078, 0x86d1, 0x0f7f, 0x1078, 0x8726, 0x0078, 0x8087,
-	0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8075, 0x684c,
-	0xd0ac, 0x0040, 0x8075, 0x6024, 0xd0dc, 0x00c0, 0x8075, 0x6850,
-	0xd0bc, 0x00c0, 0x8075, 0x684c, 0xd0f4, 0x00c0, 0x8075, 0x1078,
-	0x8cfa, 0x0d7f, 0x0e7f, 0x0078, 0x8094, 0x684b, 0x0000, 0x6837,
-	0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x8085, 0x6810, 0x6914,
-	0xa115, 0x0040, 0x8085, 0x1078, 0x8233, 0x1078, 0x4982, 0x6218,
-	0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x1078, 0x8cc4, 0x0d7f, 0x0e7f,
-	0x00c0, 0x8094, 0x1078, 0x753d, 0x007c, 0x0f7e, 0x6003, 0x0003,
-	0x2079, 0xa88c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
-	0x784c, 0xd0ac, 0x0040, 0x80a8, 0x6003, 0x0002, 0x0f7f, 0x007c,
-	0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x603f, 0x0000, 0x2c10,
-	0x1078, 0x1cab, 0x1078, 0x5c64, 0x1078, 0x61d3, 0x007c, 0x2001,
-	0xa5a2, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x80ca, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80dd, 0x80df,
-	0x8182, 0x80dd, 0x80dd, 0x8198, 0x8209, 0x80dd, 0x80dd, 0x80dd,
-	0x80dd, 0x8218, 0x80dd, 0x80dd, 0x80dd, 0x1078, 0x1328, 0x077e,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xa88c, 0x6110, 0x2178, 0x7614,
-	0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268,
-	0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x817d, 0xa694, 0xff00,
-	0xa284, 0x0c00, 0x0040, 0x8100, 0x7018, 0x7862, 0x701c, 0x785e,
-	0xa284, 0x0300, 0x0040, 0x817d, 0x1078, 0x1381, 0x1040, 0x1328,
-	0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
-	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
-	0x0040, 0x811e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
-	0xa186, 0x0002, 0x0040, 0x813a, 0xa186, 0x0028, 0x00c0, 0x812c,
-	0x684b, 0x001c, 0x0078, 0x813c, 0xd6dc, 0x0040, 0x8133, 0x684b,
-	0x0015, 0x0078, 0x813c, 0xd6d4, 0x0040, 0x813a, 0x684b, 0x0007,
-	0x0078, 0x813c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
-	0x6856, 0xa01e, 0xd6c4, 0x0040, 0x815a, 0x7328, 0x732c, 0x6b56,
-	0x83ff, 0x0040, 0x815a, 0xa38a, 0x0009, 0x0048, 0x8151, 0x2019,
-	0x0008, 0x037e, 0x2308, 0x2019, 0xa898, 0xad90, 0x0019, 0x1078,
-	0x8739, 0x037f, 0xd6cc, 0x0040, 0x817d, 0x7124, 0x695a, 0x81ff,
-	0x0040, 0x817d, 0xa192, 0x0021, 0x00c8, 0x8171, 0x2071, 0xa898,
-	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x8739, 0x0078,
-	0x817d, 0x7838, 0xd0fc, 0x0040, 0x817a, 0x2009, 0x0020, 0x695a,
-	0x0078, 0x8166, 0x2d78, 0x1078, 0x86d1, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xa88c, 0x7c04,
-	0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a,
-	0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x6c26, 0x007c,
-	0x0d7e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x81a4,
-	0x2001, 0xa5a2, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x60b8,
-	0x1078, 0x61d3, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x8207,
-	0xd1cc, 0x0040, 0x81de, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x81d6,
-	0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198,
-	0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
-	0x8210, 0x00f0, 0x81c5, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e,
-	0x017f, 0x2168, 0x1078, 0x13aa, 0x0078, 0x8201, 0x017e, 0x1078,
-	0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8201, 0x6837, 0x0103,
-	0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x81fd, 0xa086,
-	0x0028, 0x00c0, 0x81ef, 0x684b, 0x001c, 0x0078, 0x81ff, 0xd1dc,
-	0x0040, 0x81f6, 0x684b, 0x0015, 0x0078, 0x81ff, 0xd1d4, 0x0040,
-	0x81fd, 0x684b, 0x0007, 0x0078, 0x81ff, 0x684b, 0x0000, 0x1078,
-	0x4982, 0x1078, 0x8cc4, 0x00c0, 0x8207, 0x1078, 0x753d, 0x0d7f,
-	0x007c, 0x2019, 0x0001, 0x1078, 0x6e6c, 0x6003, 0x0002, 0x2001,
-	0xa5a2, 0x2004, 0x603e, 0x1078, 0x60b8, 0x1078, 0x61d3, 0x007c,
-	0x1078, 0x60b8, 0x1078, 0x2813, 0x0d7e, 0x6110, 0x2168, 0x1078,
-	0x8a44, 0x0040, 0x822d, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847,
-	0x0000, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
-	0x1078, 0x61d3, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x823f,
-	0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
-	0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x8246, 0x8259, 0x8259,
-	0x8259, 0x8259, 0x8259, 0x825b, 0x8259, 0x8333, 0x833f, 0x8259,
-	0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259, 0x8259,
-	0x8259, 0x1078, 0x1328, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071,
-	0xa88c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78,
-	0x1078, 0x4893, 0x0f7f, 0x0040, 0x827e, 0xa684, 0x00ff, 0x00c0,
-	0x827e, 0x6024, 0xd0f4, 0x00c0, 0x827a, 0x7808, 0xa086, 0x0000,
-	0x00c0, 0x827e, 0x1078, 0x8cfa, 0x0078, 0x832e, 0x7e46, 0x7f4c,
-	0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff,
-	0x0040, 0x8323, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x8294,
-	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x8320,
-	0xa686, 0x0100, 0x00c0, 0x82a6, 0x2001, 0xa899, 0x2004, 0xa005,
-	0x00c0, 0x82a6, 0xc6c4, 0x7e46, 0x0078, 0x8287, 0x1078, 0x1381,
-	0x1040, 0x1328, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e,
-	0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842,
-	0x6e46, 0xa68c, 0x0c00, 0x0040, 0x82c1, 0x7318, 0x6b62, 0x731c,
-	0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x82dd, 0xa186,
-	0x0028, 0x00c0, 0x82cf, 0x684b, 0x001c, 0x0078, 0x82df, 0xd6dc,
-	0x0040, 0x82d6, 0x684b, 0x0015, 0x0078, 0x82df, 0xd6d4, 0x0040,
-	0x82dd, 0x684b, 0x0007, 0x0078, 0x82df, 0x684b, 0x0000, 0x6f4e,
-	0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040, 0x82fd,
-	0x7328, 0x732c, 0x6b56, 0x83ff, 0x0040, 0x82fd, 0xa38a, 0x0009,
-	0x0048, 0x82f4, 0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xa898,
-	0xad90, 0x0019, 0x1078, 0x8739, 0x037f, 0xd6cc, 0x0040, 0x8320,
-	0x7124, 0x695a, 0x81ff, 0x0040, 0x8320, 0xa192, 0x0021, 0x00c8,
-	0x8314, 0x2071, 0xa898, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d,
-	0x1078, 0x8739, 0x0078, 0x8320, 0x7838, 0xd0fc, 0x0040, 0x831d,
-	0x2009, 0x0020, 0x695a, 0x0078, 0x8309, 0x2d78, 0x1078, 0x86d1,
-	0xd6dc, 0x00c0, 0x8326, 0xa006, 0x0078, 0x832c, 0x2001, 0x0001,
-	0x2071, 0xa88c, 0x7218, 0x731c, 0x1078, 0x1645, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x077f, 0x007c, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x20e1,
-	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x2001,
-	0xa5a2, 0x2004, 0x603e, 0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168,
-	0x694c, 0xd1e4, 0x0040, 0x846b, 0x603f, 0x0000, 0x0f7e, 0x2c78,
-	0x1078, 0x4893, 0x0f7f, 0x0040, 0x8385, 0x6814, 0x6910, 0xa115,
-	0x0040, 0x8385, 0x6a60, 0xa206, 0x00c0, 0x8362, 0x685c, 0xa106,
-	0x0040, 0x8385, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863,
-	0x0000, 0x685f, 0x0000, 0x6024, 0xd0f4, 0x00c0, 0x837a, 0x697c,
-	0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6024,
-	0xc0f5, 0x6026, 0x0d7e, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
-	0x0d7f, 0x1078, 0x8cfa, 0x0078, 0x846b, 0x694c, 0xd1cc, 0x0040,
-	0x8430, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x83ea, 0x017e, 0x684c,
-	0x007e, 0x6850, 0x007e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x0040, 0x83bf, 0xa086, 0x0028, 0x00c0, 0x83a6,
-	0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x83ca, 0xd1dc, 0x0040,
-	0x83b6, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
-	0x83b4, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x83ca, 0xd1d4, 0x0040,
-	0x83bf, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x83ca, 0x684c,
-	0xd0ac, 0x0040, 0x83ca, 0x6810, 0x6914, 0xa115, 0x0040, 0x83ca,
-	0x1078, 0x8233, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e,
-	0xad90, 0x000d, 0xaf98, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8,
-	0x2304, 0x2012, 0x8318, 0x8210, 0x00f0, 0x83d8, 0x157f, 0x0f7f,
-	0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168, 0x1078, 0x13aa,
-	0x0078, 0x8465, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x0040, 0x8417, 0xa086, 0x0028, 0x00c0, 0x83fe,
-	0x684b, 0x001c, 0x784b, 0x001c, 0x0078, 0x8422, 0xd1dc, 0x0040,
-	0x840e, 0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x8ea5, 0x0040,
-	0x840c, 0x7944, 0xc1dc, 0x7946, 0x0078, 0x8422, 0xd1d4, 0x0040,
-	0x8417, 0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x8422, 0x684c,
-	0xd0ac, 0x0040, 0x8422, 0x6810, 0x6914, 0xa115, 0x0040, 0x8422,
-	0x1078, 0x8233, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e,
-	0x0f7f, 0x1078, 0x13aa, 0x0d7f, 0x1078, 0x8726, 0x0078, 0x8465,
-	0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040,
-	0x8456, 0xa086, 0x0028, 0x00c0, 0x8441, 0x684b, 0x001c, 0x0078,
-	0x8463, 0xd1dc, 0x0040, 0x844f, 0x684b, 0x0015, 0x1078, 0x8ea5,
-	0x0040, 0x844d, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8463, 0xd1d4,
-	0x0040, 0x8456, 0x684b, 0x0007, 0x0078, 0x8463, 0x684b, 0x0000,
-	0x684c, 0xd0ac, 0x0040, 0x8463, 0x6810, 0x6914, 0xa115, 0x0040,
-	0x8463, 0x1078, 0x8233, 0x1078, 0x4982, 0x1078, 0x8cc4, 0x00c0,
-	0x846b, 0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x6010, 0x0078,
-	0x8473, 0x1078, 0x60b8, 0x1078, 0x8a44, 0x0040, 0x8492, 0x0d7e,
-	0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa30c, 0x210c, 0xd18c,
-	0x00c0, 0x849d, 0xd184, 0x00c0, 0x8499, 0x6108, 0x694a, 0xa18e,
-	0x0029, 0x00c0, 0x848d, 0x1078, 0xa181, 0x6847, 0x0000, 0x1078,
-	0x4982, 0x0d7f, 0x1078, 0x753d, 0x1078, 0x6109, 0x1078, 0x61d3,
-	0x007c, 0x684b, 0x0004, 0x0078, 0x848d, 0x684b, 0x0004, 0x0078,
-	0x848d, 0xa182, 0x0040, 0x0079, 0x84a5, 0x84b8, 0x84b8, 0x84b8,
-	0x84b8, 0x84b8, 0x84ba, 0x84b8, 0x84bd, 0x84b8, 0x84b8, 0x84b8,
-	0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8, 0x84b8,
-	0x1078, 0x1328, 0x1078, 0x753d, 0x007c, 0x007e, 0x027e, 0xa016,
-	0x1078, 0x15ec, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079,
-	0x84c9, 0x84d2, 0x84d0, 0x84d0, 0x84de, 0x84d0, 0x84d0, 0x84d0,
-	0x1078, 0x1328, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x057e,
-	0x0d7e, 0x0e7e, 0x2071, 0xa880, 0x7224, 0x6212, 0x7220, 0x1078,
-	0x8a30, 0x0040, 0x8503, 0x2268, 0x6800, 0xa086, 0x0000, 0x0040,
-	0x8503, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x8503, 0x0c7e, 0x2d60,
-	0x1078, 0x874a, 0x0c7f, 0x0040, 0x8503, 0x6803, 0x0002, 0x6007,
-	0x0086, 0x0078, 0x8505, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078,
-	0x5bf8, 0x1078, 0x6109, 0x0f7e, 0x2278, 0x1078, 0x4893, 0x0f7f,
-	0x0040, 0x851d, 0x6824, 0xd0ec, 0x0040, 0x851d, 0x0c7e, 0x2260,
-	0x603f, 0x0000, 0x1078, 0x8cfa, 0x0c7f, 0x0e7f, 0x0d7f, 0x057f,
-	0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x8533, 0x6004, 0xa08a,
-	0x0085, 0x1048, 0x1328, 0xa08a, 0x008c, 0x10c8, 0x1328, 0xa082,
-	0x0085, 0x0079, 0x8542, 0xa186, 0x0027, 0x0040, 0x853b, 0xa186,
-	0x0014, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
-	0x6109, 0x007c, 0x8549, 0x854b, 0x854b, 0x8549, 0x8549, 0x8549,
-	0x8549, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
-	0x6109, 0x007c, 0xa186, 0x0013, 0x00c0, 0x855c, 0x6004, 0xa082,
-	0x0085, 0x2008, 0x0078, 0x8597, 0xa186, 0x0027, 0x00c0, 0x857f,
-	0x1078, 0x6010, 0x1078, 0x2813, 0x0d7e, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
-	0x0029, 0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d,
-	0x1078, 0x6109, 0x007c, 0x1078, 0x7583, 0x0078, 0x857a, 0xa186,
-	0x0014, 0x00c0, 0x857b, 0x1078, 0x6010, 0x0d7e, 0x6010, 0x2068,
-	0x1078, 0x8a44, 0x0040, 0x8575, 0x6837, 0x0103, 0x6847, 0x0000,
-	0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8571, 0x0079,
-	0x8599, 0x85a2, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85a0, 0x85bd,
-	0x1078, 0x1328, 0x1078, 0x6010, 0x6030, 0xa08c, 0xff00, 0x810f,
-	0xa186, 0x0039, 0x0040, 0x85b0, 0xa186, 0x0035, 0x00c0, 0x85b4,
-	0x2001, 0xa5a0, 0x0078, 0x85b6, 0x2001, 0xa5a1, 0x2004, 0x6016,
-	0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x6030,
-	0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x85cb, 0xa186,
-	0x0035, 0x00c0, 0x85cf, 0x2001, 0xa5a0, 0x0078, 0x85d1, 0x2001,
-	0xa5a1, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x6109, 0x007c,
-	0xa182, 0x008c, 0x00c8, 0x85e2, 0xa182, 0x0085, 0x0048, 0x85e2,
-	0x0079, 0x85e5, 0x1078, 0x7583, 0x007c, 0x85ec, 0x85ec, 0x85ec,
-	0x85ec, 0x85ee, 0x8643, 0x85ec, 0x1078, 0x1328, 0x0f7e, 0x2c78,
-	0x1078, 0x4893, 0x0f7f, 0x0040, 0x8601, 0x6030, 0xa08c, 0xff00,
-	0x810f, 0xa186, 0x0039, 0x0040, 0x865a, 0xa186, 0x0035, 0x0040,
-	0x865a, 0x0d7e, 0x1078, 0x8bf4, 0x1078, 0x8a44, 0x0040, 0x8625,
-	0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x8616,
-	0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x8621, 0xd0bc, 0x0040,
-	0x861d, 0x684b, 0x0002, 0x0078, 0x8621, 0x684b, 0x0005, 0x1078,
-	0x8cc0, 0x6847, 0x0000, 0x1078, 0x4982, 0x2c68, 0x1078, 0x74d7,
-	0x0040, 0x863e, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xa88e,
-	0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x6918, 0x611a,
-	0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5bf8, 0x2d60, 0x1078,
-	0x753d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f,
-	0x0040, 0x8680, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
-	0x0040, 0x865a, 0xa186, 0x001e, 0x0040, 0x865a, 0xa186, 0x0039,
-	0x00c0, 0x8680, 0x0d7e, 0x2c68, 0x1078, 0x8ef5, 0x00c0, 0x86a4,
-	0x1078, 0x74d7, 0x0040, 0x867d, 0x6106, 0x6003, 0x0001, 0x601f,
-	0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930,
-	0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6920,
-	0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x2d60, 0x0078, 0x86a4,
-	0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86a4, 0x6837,
-	0x0103, 0x6850, 0xd0b4, 0x0040, 0x8693, 0xc0ec, 0x6852, 0x684b,
-	0x0006, 0x0078, 0x869e, 0xd0bc, 0x0040, 0x869a, 0x684b, 0x0002,
-	0x0078, 0x869e, 0x684b, 0x0005, 0x1078, 0x8cc0, 0x6847, 0x0000,
-	0x1078, 0x4982, 0x1078, 0x8bf4, 0x0d7f, 0x1078, 0x753d, 0x007c,
-	0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x86b8,
-	0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078, 0x4982,
-	0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x86ca, 0xa186, 0x0014,
-	0x0040, 0x86ca, 0xa186, 0x0027, 0x0040, 0x86ca, 0x1078, 0x7583,
-	0x0078, 0x86d0, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
-	0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182,
-	0x0101, 0x00c8, 0x86dd, 0x0078, 0x86df, 0x2009, 0x0100, 0x2130,
-	0x2069, 0xa898, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
-	0x001d, 0x1078, 0x8739, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
-	0x86f3, 0x1078, 0x13aa, 0x1078, 0x1381, 0x0040, 0x871d, 0x8528,
-	0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d,
-	0x00c8, 0x8709, 0x2608, 0xad90, 0x000f, 0x1078, 0x8739, 0x0078,
-	0x871d, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
-	0x1078, 0x8739, 0x0078, 0x86f3, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
-	0x7d36, 0xa5ac, 0x0000, 0x0078, 0x8722, 0x0f7f, 0x852f, 0xa5ad,
-	0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff,
-	0x0040, 0x8737, 0x6804, 0xa07d, 0x0040, 0x8735, 0x6807, 0x0000,
-	0x1078, 0x4982, 0x2f68, 0x0078, 0x872a, 0x1078, 0x4982, 0x0f7f,
-	0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x873f, 0x8108, 0x810c,
-	0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x8741,
-	0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031, 0x0001,
-	0x601c, 0xa084, 0x000f, 0x1079, 0x8766, 0x127f, 0x067f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c, 0xa084,
-	0x000f, 0x1079, 0x8766, 0x067f, 0x127f, 0x007c, 0x8780, 0x876e,
-	0x877b, 0x879c, 0x876e, 0x877b, 0x879c, 0x877b, 0x1078, 0x1328,
-	0x037e, 0x2019, 0x0010, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003,
-	0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
-	0x0d7e, 0x86ff, 0x00c0, 0x8797, 0x6010, 0x2068, 0x1078, 0x8a44,
-	0x0040, 0x8799, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4a60, 0x1078,
-	0x8cc0, 0x1078, 0x4982, 0x1078, 0x753d, 0xa085, 0x0001, 0x0d7f,
-	0x007c, 0xa006, 0x0078, 0x8797, 0x6000, 0xa08a, 0x0010, 0x10c8,
-	0x1328, 0x1079, 0x87a4, 0x007c, 0x87b4, 0x87d4, 0x87b6, 0x87f7,
-	0x87d0, 0x87b4, 0x877b, 0x8780, 0x8780, 0x877b, 0x877b, 0x877b,
-	0x877b, 0x877b, 0x877b, 0x877b, 0x1078, 0x1328, 0x86ff, 0x00c0,
-	0x87cd, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x87c2,
-	0x1078, 0x8cc0, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
-	0x0002, 0x1078, 0x5bf8, 0x1078, 0x6109, 0xa085, 0x0001, 0x007c,
-	0x1078, 0x1749, 0x0078, 0x87b6, 0x0e7e, 0x2071, 0xa5ab, 0x7024,
-	0xac06, 0x00c0, 0x87dd, 0x1078, 0x6dda, 0x601c, 0xa084, 0x000f,
-	0xa086, 0x0006, 0x00c0, 0x87ef, 0x087e, 0x097e, 0x2049, 0x0001,
-	0x2c40, 0x1078, 0x7058, 0x097f, 0x087f, 0x0078, 0x87f1, 0x1078,
-	0x6cd2, 0x0e7f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c, 0x037e,
-	0x0e7e, 0x2071, 0xa5ab, 0x703c, 0xac06, 0x00c0, 0x8807, 0x2019,
-	0x0000, 0x1078, 0x6e6c, 0x0e7f, 0x037f, 0x0078, 0x87b6, 0x1078,
-	0x719a, 0x0e7f, 0x037f, 0x00c0, 0x87b6, 0x1078, 0x877b, 0x007c,
-	0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x8818, 0x0c7f, 0x007c,
-	0x8827, 0x8895, 0x89cd, 0x8832, 0x8c01, 0x8827, 0x9a5b, 0x753d,
-	0x8895, 0x1078, 0x8c3b, 0x00c0, 0x8827, 0x1078, 0x7a05, 0x007c,
-	0x1078, 0x6010, 0x1078, 0x6109, 0x1078, 0x753d, 0x007c, 0x6017,
-	0x0001, 0x007c, 0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a,
-	0x0010, 0x10c8, 0x1328, 0x1079, 0x883e, 0x007c, 0x884e, 0x8850,
-	0x8872, 0x8884, 0x8891, 0x884e, 0x8827, 0x8827, 0x8827, 0x8884,
-	0x8884, 0x884e, 0x884e, 0x884e, 0x884e, 0x888e, 0x1078, 0x1328,
-	0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0xa5ab,
-	0x7024, 0xac06, 0x0040, 0x886e, 0x1078, 0x6cd2, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa5a1, 0x2004, 0x6016,
-	0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x6017, 0x0001,
-	0x0078, 0x886c, 0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852,
-	0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078,
-	0x5bf8, 0x1078, 0x6109, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010,
-	0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x753d,
-	0x007c, 0x1078, 0x1749, 0x0078, 0x8872, 0x6000, 0xa08a, 0x0010,
-	0x10c8, 0x1328, 0x1079, 0x889d, 0x007c, 0x88ad, 0x882f, 0x88af,
-	0x88ad, 0x88af, 0x88af, 0x8828, 0x88ad, 0x8821, 0x8821, 0x88ad,
-	0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x88ad, 0x1078, 0x1328, 0x0d7e,
-	0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c,
-	0x10c8, 0x1328, 0x1079, 0x88bd, 0x007c, 0x88c9, 0x8971, 0x88cb,
-	0x890b, 0x88cb, 0x890b, 0x88cb, 0x88d8, 0x88c9, 0x890b, 0x88c9,
-	0x88f5, 0x1078, 0x1328, 0x6004, 0xa08e, 0x0016, 0x0040, 0x8906,
-	0xa08e, 0x0004, 0x0040, 0x8906, 0xa08e, 0x0002, 0x0040, 0x8906,
-	0x6004, 0x1078, 0x8c3b, 0x0040, 0x898c, 0xa08e, 0x0021, 0x0040,
-	0x8990, 0xa08e, 0x0022, 0x0040, 0x898c, 0xa08e, 0x003d, 0x0040,
-	0x8990, 0xa08e, 0x0039, 0x0040, 0x8994, 0xa08e, 0x0035, 0x0040,
-	0x8994, 0xa08e, 0x001e, 0x0040, 0x8908, 0xa08e, 0x0001, 0x00c0,
-	0x8904, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
-	0xa086, 0x0006, 0x0040, 0x8906, 0x1078, 0x2813, 0x1078, 0x7a05,
-	0x1078, 0x8c01, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016,
-	0x0040, 0x8961, 0xa186, 0x0002, 0x00c0, 0x8934, 0x6018, 0x2068,
-	0x68a0, 0xd0bc, 0x00c0, 0x89b8, 0x6840, 0xa084, 0x00ff, 0xa005,
-	0x0040, 0x8934, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007,
-	0x6017, 0x0398, 0x1078, 0x74d7, 0x0040, 0x8934, 0x2d00, 0x601a,
-	0x601f, 0x0001, 0x0078, 0x8961, 0x0d7f, 0x0c7f, 0x6004, 0xa08e,
-	0x0002, 0x00c0, 0x8952, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086,
-	0x007e, 0x00c0, 0x8952, 0x2009, 0xa332, 0x2104, 0xc085, 0x200a,
-	0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x0e7f, 0x1078, 0x7a05,
-	0x0078, 0x8956, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x2839, 0x127f, 0x0e7f, 0x1078, 0x8c01,
-	0x007c, 0x2001, 0x0002, 0x1078, 0x443f, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0d7f, 0x0c7f, 0x0078,
-	0x8960, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x8961,
-	0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x8934,
-	0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5c45, 0x1078, 0x6109,
-	0x0d7f, 0x0c7f, 0x0078, 0x8960, 0x1078, 0x7a05, 0x0078, 0x8908,
-	0x1078, 0x7a28, 0x0078, 0x8908, 0x0d7e, 0x2c68, 0x6104, 0x1078,
-	0x8ef5, 0x0d7f, 0x0040, 0x89a0, 0x1078, 0x753d, 0x0078, 0x89b7,
-	0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007,
-	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001,
-	0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c,
-	0x0d7f, 0x0c7f, 0x1078, 0x7a05, 0x1078, 0x2813, 0x0e7e, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x2839, 0x6013, 0x0000, 0x601f, 0x0007,
-	0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000, 0xa08a, 0x0010,
-	0x10c8, 0x1328, 0x1079, 0x89d5, 0x007c, 0x89e5, 0x89e5, 0x89e5,
-	0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x89e5, 0x8827, 0x89e5,
-	0x882f, 0x89e7, 0x882f, 0x89f5, 0x89e5, 0x1078, 0x1328, 0x6004,
-	0xa086, 0x008b, 0x0040, 0x89f5, 0x6007, 0x008b, 0x6003, 0x000d,
-	0x1078, 0x5bf8, 0x1078, 0x6109, 0x007c, 0x1078, 0x8bf4, 0x1078,
-	0x8a44, 0x0040, 0x8a2d, 0x1078, 0x2813, 0x0d7e, 0x1078, 0x8a44,
-	0x0040, 0x8a0f, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
-	0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078, 0x4982, 0x2c68,
-	0x1078, 0x74d7, 0x0040, 0x8a1d, 0x6818, 0x601a, 0x0c7e, 0x2d60,
-	0x1078, 0x8c01, 0x0c7f, 0x0078, 0x8a1e, 0x2d60, 0x0d7f, 0x6013,
-	0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
-	0x5c45, 0x1078, 0x6109, 0x0078, 0x8a2f, 0x1078, 0x8c01, 0x007c,
-	0xa284, 0x000f, 0x00c0, 0x8a41, 0xa282, 0xaa00, 0x0048, 0x8a41,
-	0x2001, 0xa315, 0x2004, 0xa202, 0x00c8, 0x8a41, 0xa085, 0x0001,
-	0x007c, 0xa006, 0x0078, 0x8a40, 0x027e, 0x0e7e, 0x2071, 0xa300,
-	0x6210, 0x7058, 0xa202, 0x0048, 0x8a56, 0x705c, 0xa202, 0x00c8,
-	0x8a56, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c, 0xa006, 0x0078,
-	0x8a53, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0x2061, 0xaa00, 0x2071, 0xa300, 0x7344, 0x7060, 0xa302, 0x00c8,
-	0x8a83, 0x601c, 0xa206, 0x00c0, 0x8a7b, 0x1078, 0x8d66, 0x0040,
-	0x8a7b, 0x1078, 0x8c3b, 0x00c0, 0x8a77, 0x1078, 0x7a05, 0x0c7e,
-	0x1078, 0x753d, 0x0c7f, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8,
-	0x8a83, 0x0078, 0x8a64, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f,
-	0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa434, 0x210c, 0x81ff,
-	0x0040, 0x8aa1, 0x2061, 0xaa00, 0x2071, 0xa300, 0x017e, 0x1078,
-	0x74d7, 0x017f, 0x0040, 0x8aa4, 0x611a, 0x1078, 0x2813, 0x1078,
-	0x753d, 0xa006, 0x0078, 0x8aa6, 0xa085, 0x0001, 0x017f, 0x0c7f,
-	0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
-	0x1078, 0x74d7, 0x057f, 0x0040, 0x8ac3, 0x6612, 0x651a, 0x601f,
-	0x0003, 0x2009, 0x004b, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
-	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8abf, 0x0c7e, 0x057e,
-	0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x74d7, 0x057f,
-	0x0040, 0x8af1, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
-	0x2560, 0x1078, 0x471b, 0x0c7f, 0x1078, 0x5d53, 0x077e, 0x2039,
-	0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2009,
-	0x004c, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f,
-	0x007c, 0xa006, 0x0078, 0x8aed, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e,
-	0x1078, 0x74d7, 0x2c78, 0x0c7f, 0x0040, 0x8b0e, 0x7e12, 0x2c00,
-	0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60,
-	0x2009, 0x004d, 0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f,
-	0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7,
-	0x2c78, 0x0c7f, 0x0040, 0x8b2c, 0x7e12, 0x2c00, 0x781a, 0x781f,
-	0x0003, 0x2021, 0x0005, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x004e,
-	0x1078, 0x756c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c,
-	0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x74d7, 0x2c78, 0x0c7f,
-	0x0040, 0x8b4a, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021,
-	0x0004, 0x1078, 0x8b4e, 0x2f60, 0x2009, 0x0052, 0x1078, 0x756c,
-	0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c, 0x097e, 0x077e,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x46a7, 0x0040, 0x8b5b, 0x2001,
-	0x8b53, 0x0078, 0x8b61, 0x1078, 0x466d, 0x0040, 0x8b6a, 0x2001,
-	0x8b5b, 0x007e, 0xa00e, 0x2400, 0x1078, 0x4a60, 0x1078, 0x4982,
-	0x007f, 0x007a, 0x2418, 0x1078, 0x5fa7, 0x62a0, 0x087e, 0x2041,
-	0x0001, 0x2039, 0x0001, 0x2608, 0x1078, 0x5d6d, 0x087f, 0x1078,
-	0x5c78, 0x2f08, 0x2648, 0x1078, 0x9c38, 0x613c, 0x81ff, 0x1040,
-	0x5e21, 0x127f, 0x077f, 0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8b9e, 0x660a,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x1078,
-	0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x8b9b, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
-	0x017f, 0x0040, 0x8bba, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00,
-	0x6012, 0x2009, 0x0021, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
-	0x0c7f, 0x007c, 0xa006, 0x0078, 0x8bb7, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8bd6, 0x660a,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x1078,
-	0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x8bd3, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7,
-	0x017f, 0x0040, 0x8bf1, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
-	0x2009, 0x0000, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f,
-	0x007c, 0xa006, 0x0078, 0x8bee, 0x027e, 0x0d7e, 0x6218, 0x2268,
-	0x6a3c, 0x82ff, 0x0040, 0x8bfe, 0x8211, 0x6a3e, 0x0d7f, 0x027f,
-	0x007c, 0x007e, 0x6000, 0xa086, 0x0000, 0x0040, 0x8c13, 0x6013,
-	0x0000, 0x601f, 0x0007, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078,
-	0xa134, 0x603f, 0x0000, 0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e,
-	0x2031, 0xa352, 0x2634, 0xd6e4, 0x0040, 0x8c23, 0x6618, 0x2660,
-	0x6e48, 0x1078, 0x461b, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e,
-	0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x8c38, 0xa08e, 0x0003,
-	0x0040, 0x8c38, 0xa08e, 0x0004, 0x0040, 0x8c38, 0xa085, 0x0001,
-	0x017f, 0x007f, 0x007c, 0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040,
-	0x8c48, 0x6838, 0xd0fc, 0x0040, 0x8c48, 0xa006, 0x0078, 0x8c4a,
-	0xa085, 0x0001, 0x0d7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8c67, 0x611a,
-	0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x2813, 0x2009, 0x0028,
-	0x1078, 0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
-	0x0078, 0x8c64, 0xa186, 0x0015, 0x00c0, 0x8c7f, 0x2011, 0xa31f,
-	0x2204, 0xa086, 0x0074, 0x00c0, 0x8c7f, 0x1078, 0x7d0d, 0x6003,
-	0x0001, 0x6007, 0x0029, 0x1078, 0x5c45, 0x0078, 0x8c83, 0x1078,
-	0x7a05, 0x1078, 0x753d, 0x007c, 0xa186, 0x0016, 0x00c0, 0x8c8e,
-	0x2001, 0x0004, 0x1078, 0x443f, 0x0078, 0x8caf, 0xa186, 0x0015,
-	0x00c0, 0x8cb3, 0x2011, 0xa31f, 0x2204, 0xa086, 0x0014, 0x00c0,
-	0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x457d, 0x0d7f, 0x1078,
-	0x7dba, 0x00c0, 0x8cb3, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f,
-	0xa005, 0x0040, 0x8cb3, 0x2001, 0x0006, 0x1078, 0x443f, 0x1078,
-	0x7608, 0x0078, 0x8cb7, 0x1078, 0x7a05, 0x1078, 0x753d, 0x007c,
-	0x6848, 0xa086, 0x0005, 0x00c0, 0x8cbf, 0x1078, 0x8cc0, 0x007c,
-	0x6850, 0xc0ad, 0x6852, 0x007c, 0x0e7e, 0x2071, 0xa88c, 0x7014,
-	0xd0e4, 0x0040, 0x8cd5, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007,
-	0x0050, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x007c, 0x0c7e,
-	0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x0040, 0x8ce4, 0x601c,
-	0xa084, 0x000f, 0x1079, 0x8ce6, 0x0c7f, 0x007c, 0x8827, 0x8cf1,
-	0x8cf4, 0x8cf7, 0x9f00, 0x9f1c, 0x9f1f, 0x8827, 0x8827, 0x1078,
-	0x1328, 0x0005, 0x0005, 0x007c, 0x0005, 0x0005, 0x007c, 0x1078,
-	0x8cfa, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0040, 0x8d29,
-	0x1078, 0x74d7, 0x00c0, 0x8d0a, 0x2001, 0xa5a2, 0x2004, 0x783e,
-	0x0078, 0x8d29, 0x7818, 0x601a, 0x781c, 0xa086, 0x0003, 0x0040,
-	0x8d17, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0078, 0x8d1b, 0x7808,
-	0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007, 0x0035,
-	0x6003, 0x0001, 0x7920, 0x6122, 0x1078, 0x5bf8, 0x1078, 0x6109,
-	0x2f60, 0x0f7f, 0x007c, 0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e,
-	0x0001, 0x0040, 0x8d3c, 0xa086, 0x0005, 0x0040, 0x8d40, 0xa006,
-	0x602a, 0x602e, 0x0078, 0x8d51, 0x6824, 0xc0f4, 0xc0d5, 0x6826,
-	0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103,
-	0x00c8, 0x8d37, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a,
-	0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6920,
-	0x6122, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x1078,
-	0x5bf8, 0x6803, 0x0002, 0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e,
-	0x6004, 0xa08e, 0x0034, 0x0040, 0x8d8b, 0xa08e, 0x0035, 0x0040,
-	0x8d8b, 0xa08e, 0x0036, 0x0040, 0x8d8b, 0xa08e, 0x0037, 0x0040,
-	0x8d8b, 0xa08e, 0x0038, 0x0040, 0x8d8b, 0xa08e, 0x0039, 0x0040,
-	0x8d8b, 0xa08e, 0x003a, 0x0040, 0x8d8b, 0xa08e, 0x003b, 0x0040,
-	0x8d8b, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78,
-	0x1078, 0x4893, 0x00c0, 0x8d98, 0xa085, 0x0001, 0x0078, 0x8da7,
-	0x6024, 0xd0f4, 0x00c0, 0x8da6, 0xc0f5, 0x6026, 0x6010, 0x2078,
-	0x7828, 0x603a, 0x782c, 0x6036, 0x1078, 0x1749, 0xa006, 0x0f7f,
-	0x007c, 0x007e, 0x017e, 0x027e, 0x037e, 0x0e7e, 0x2001, 0xa59c,
-	0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x1078, 0x5a98, 0x2001,
-	0xa5a0, 0x82ff, 0x00c0, 0x8dbe, 0x2011, 0x0002, 0x2202, 0x2001,
-	0xa59e, 0x200c, 0x8000, 0x2014, 0x2071, 0xa58c, 0x711a, 0x721e,
-	0x2001, 0x0064, 0x1078, 0x5a98, 0x2001, 0xa5a1, 0x82ff, 0x00c0,
-	0x8dd3, 0x2011, 0x0002, 0x2202, 0x2009, 0xa5a2, 0xa280, 0x000a,
-	0x200a, 0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e,
-	0x0e7e, 0x2001, 0xa5a0, 0x2003, 0x0028, 0x2001, 0xa5a1, 0x2003,
-	0x0014, 0x2071, 0xa58c, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
-	0xa5a2, 0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x74d7, 0x017f, 0x0040, 0x8e0e,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078,
-	0x756c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x8e0b, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa300, 0xa186, 0x0015,
-	0x00c0, 0x8e40, 0x707c, 0xa086, 0x0018, 0x00c0, 0x8e40, 0x6010,
-	0x2068, 0x6a3c, 0xd2e4, 0x00c0, 0x8e34, 0x2c78, 0x1078, 0x62c6,
-	0x0040, 0x8e48, 0x7068, 0x6a50, 0xa206, 0x00c0, 0x8e3c, 0x706c,
-	0x6a54, 0xa206, 0x00c0, 0x8e3c, 0x6218, 0xa290, 0x0028, 0x2214,
-	0x2009, 0x0000, 0x1078, 0x285b, 0x1078, 0x7608, 0x0078, 0x8e44,
-	0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c,
-	0x704c, 0xa080, 0x293f, 0x2004, 0x6a54, 0xa206, 0x0040, 0x8e34,
-	0x0078, 0x8e3c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
-	0x74d7, 0x017f, 0x0040, 0x8e6a, 0x611a, 0x601f, 0x0001, 0x2d00,
-	0x6012, 0x2009, 0x0043, 0x1078, 0x756c, 0xa085, 0x0001, 0x127f,
-	0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e67, 0x0d7e, 0x0e7e, 0x0f7e,
-	0x2071, 0xa300, 0xa186, 0x0015, 0x00c0, 0x8e93, 0x707c, 0xa086,
-	0x0004, 0x00c0, 0x8e93, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078,
-	0x62c6, 0x0040, 0x8e9b, 0x7068, 0x6a08, 0xa206, 0x00c0, 0x8e8f,
-	0x706c, 0x6a0c, 0xa206, 0x00c0, 0x8e8f, 0x1078, 0x2813, 0x1078,
-	0x7608, 0x0078, 0x8e97, 0x1078, 0x7a05, 0x1078, 0x753d, 0x0f7f,
-	0x0e7f, 0x0d7f, 0x007c, 0x704c, 0xa080, 0x293f, 0x2004, 0x6a0c,
-	0xa206, 0x0040, 0x8e8d, 0x0078, 0x8e8f, 0x017e, 0x027e, 0x684c,
-	0xd0ac, 0x0040, 0x8ebd, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040,
-	0x8ebd, 0x6860, 0xa106, 0x00c0, 0x8eb9, 0x685c, 0xa206, 0x0040,
-	0x8ebd, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c,
-	0x0e7e, 0x127e, 0x2071, 0xa300, 0x2091, 0x8000, 0x7544, 0xa582,
-	0x0001, 0x0048, 0x8ef2, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x8ede, 0xace0, 0x0010, 0x7054, 0xac02, 0x00c8, 0x8eda,
-	0x0078, 0x8ecd, 0x2061, 0xaa00, 0x0078, 0x8ecd, 0x6003, 0x0008,
-	0x8529, 0x7546, 0xaca8, 0x0010, 0x7054, 0xa502, 0x00c8, 0x8eee,
-	0x754a, 0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704b, 0xaa00,
-	0x0078, 0x8ee9, 0xa006, 0x0078, 0x8eeb, 0x0c7e, 0x027e, 0x017e,
-	0xa186, 0x0035, 0x0040, 0x8eff, 0x6a34, 0x0078, 0x8f00, 0x6a28,
-	0x1078, 0x8a30, 0x0040, 0x8f29, 0x2260, 0x611c, 0xa186, 0x0003,
-	0x0040, 0x8f0e, 0xa186, 0x0006, 0x00c0, 0x8f25, 0x6834, 0xa206,
-	0x0040, 0x8f1d, 0x6838, 0xa206, 0x00c0, 0x8f25, 0x6108, 0x6834,
-	0xa106, 0x00c0, 0x8f25, 0x0078, 0x8f22, 0x6008, 0x6938, 0xa106,
-	0x00c0, 0x8f25, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f,
-	0x007c, 0xa085, 0x0001, 0x0078, 0x8f25, 0x067e, 0x6000, 0xa0b2,
-	0x0010, 0x10c8, 0x1328, 0x1079, 0x8f37, 0x067f, 0x007c, 0x8f47,
-	0x93bb, 0x94d3, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f81,
-	0x955e, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x8f47, 0x1078,
-	0x1328, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1328, 0x1079,
-	0x8f53, 0x067f, 0x007c, 0x8f63, 0x99f6, 0x8f63, 0x8f63, 0x8f63,
-	0x8f63, 0x8f63, 0x8f63, 0x99b4, 0x9a44, 0x8f63, 0xa053, 0xa087,
-	0xa053, 0xa087, 0x8f63, 0x1078, 0x1328, 0x067e, 0x6000, 0xa0b2,
-	0x0010, 0x10c8, 0x1328, 0x1079, 0x8f6f, 0x067f, 0x007c, 0x8f7f,
-	0x969f, 0x976a, 0x9798, 0x9813, 0x8f7f, 0x9919, 0x98c1, 0x956a,
-	0x9988, 0x999e, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x8f7f, 0x1078,
-	0x1328, 0xa1b2, 0x0044, 0x10c8, 0x1328, 0x2100, 0x0079, 0x8f88,
-	0x8fc8, 0x919a, 0x8fc8, 0x8fc8, 0x8fc8, 0x91a2, 0x8fc8, 0x8fc8,
-	0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8,
-	0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fca,
-	0x902d, 0x9038, 0x9081, 0x909c, 0x911b, 0x918b, 0x8fc8, 0x8fc8,
-	0x91a6, 0x8fc8, 0x8fc8, 0x91b5, 0x91bc, 0x8fc8, 0x8fc8, 0x8fc8,
-	0x8fc8, 0x8fc8, 0x91ea, 0x8fc8, 0x8fc8, 0x91f5, 0x8fc8, 0x8fc8,
-	0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x920a, 0x8fc8, 0x8fc8, 0x8fc8,
-	0x9291, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x8fc8, 0x9305,
-	0x1078, 0x1328, 0x1078, 0x4897, 0x00c0, 0x8fd7, 0x2001, 0xa332,
-	0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x8fdf, 0x6007,
-	0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195, 0x1078,
-	0x4887, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270,
-	0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039,
-	0x0000, 0x1078, 0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x017f,
-	0x2e60, 0x1078, 0x471b, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
-	0x6618, 0x0c7e, 0x2660, 0x1078, 0x4513, 0x0c7f, 0xa6b0, 0x0001,
-	0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x901f, 0x1078,
-	0x9b6c, 0x00c0, 0x907b, 0x1078, 0x9afd, 0x00c0, 0x901b, 0x6007,
-	0x0008, 0x0078, 0x9195, 0x6007, 0x0009, 0x0078, 0x9195, 0x1078,
-	0x9d45, 0x0040, 0x9029, 0x1078, 0x9b6c, 0x0040, 0x9013, 0x0078,
-	0x907b, 0x6013, 0x1900, 0x0078, 0x901b, 0x6106, 0x1078, 0x9aa8,
-	0x6007, 0x0006, 0x0078, 0x9195, 0x6007, 0x0007, 0x0078, 0x9195,
-	0x1078, 0xa0bf, 0x00c0, 0x9340, 0x0d7e, 0x6618, 0x2668, 0x6e04,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x905d, 0xa686,
-	0x0004, 0x0040, 0x905d, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
-	0x0040, 0x905d, 0xa686, 0x0004, 0x0040, 0x905d, 0xa686, 0x0005,
-	0x0040, 0x905d, 0x0d7f, 0x0078, 0x907b, 0x1078, 0x9bd2, 0x00c0,
-	0x9076, 0xa686, 0x0006, 0x00c0, 0x906f, 0x027e, 0x6218, 0xa290,
-	0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f, 0x1078,
-	0x457d, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x9195, 0x6007, 0x000b,
-	0x0d7f, 0x0078, 0x9195, 0x1078, 0x2813, 0x6007, 0x0001, 0x0078,
-	0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x6618, 0x0d7e, 0x2668,
-	0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x907b, 0x027e, 0x6218,
-	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078, 0x285b, 0x027f,
-	0x6007, 0x000c, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x90a9,
-	0x2001, 0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0,
-	0x90b1, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078,
-	0x9195, 0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
-	0x00ff, 0xa082, 0x0006, 0x0048, 0x90f5, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0004, 0x0040, 0x90c8, 0xa686, 0x0006, 0x00c0, 0x907b,
-	0x1078, 0x9be1, 0x00c0, 0x90d0, 0x6007, 0x000e, 0x0078, 0x9195,
-	0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427,
-	0x047e, 0x1078, 0x2813, 0x047f, 0x017e, 0xa006, 0x2009, 0xa352,
-	0x210c, 0xd1a4, 0x0040, 0x90ef, 0x2009, 0x0029, 0x1078, 0x9ec0,
-	0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f,
-	0x047f, 0x6007, 0x0001, 0x0078, 0x9195, 0x2001, 0x0001, 0x1078,
-	0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
-	0xa305, 0x2011, 0xa890, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
-	0x157f, 0xa005, 0x0040, 0x9115, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x0040, 0x90c8, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
-	0x0009, 0x0078, 0x9195, 0x1078, 0x4897, 0x00c0, 0x9128, 0x2001,
-	0xa332, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x00c0, 0x9130,
-	0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0078, 0x9195,
-	0x1078, 0x4887, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
-	0xa082, 0x0006, 0x0048, 0x9178, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0004, 0x0040, 0x9147, 0xa686, 0x0006, 0x00c0, 0x907b, 0x1078,
-	0x9c0c, 0x00c0, 0x9153, 0x1078, 0x9afd, 0x00c0, 0x9153, 0x6007,
-	0x0010, 0x0078, 0x9195, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424,
-	0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2813, 0x047f, 0x017e,
-	0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040, 0x9172, 0x2009,
-	0x0029, 0x1078, 0x9ec0, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5,
-	0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x9195,
-	0x1078, 0x9d45, 0x0040, 0x9185, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x0040, 0x9147, 0x0078, 0x907b, 0x6013, 0x1900, 0x6007,
-	0x0009, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0, 0x9340, 0x1078,
-	0x9343, 0x00c0, 0x907b, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078,
-	0x5c45, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5c45,
-	0x0078, 0x9199, 0x6007, 0x0005, 0x0078, 0x919c, 0x1078, 0xa0bf,
-	0x00c0, 0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6007, 0x0020,
-	0x6003, 0x0001, 0x1078, 0x5c45, 0x007c, 0x6007, 0x0023, 0x6003,
-	0x0001, 0x1078, 0x5c45, 0x007c, 0x1078, 0xa0bf, 0x00c0, 0x9340,
-	0x1078, 0x9343, 0x00c0, 0x907b, 0x017e, 0x027e, 0x2011, 0xa890,
-	0x2214, 0x2c08, 0x1078, 0x9e8c, 0x00c0, 0x91de, 0x2160, 0x6007,
-	0x0026, 0x6013, 0x1700, 0x2011, 0xa889, 0x2214, 0xa296, 0xffff,
-	0x00c0, 0x91e3, 0x6007, 0x0025, 0x0078, 0x91e3, 0x1078, 0x753d,
-	0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5c45, 0x027f,
-	0x017f, 0x007c, 0x6106, 0x1078, 0x9363, 0x6007, 0x002b, 0x0078,
-	0x9195, 0x6007, 0x002c, 0x0078, 0x9195, 0x1078, 0xa0bf, 0x00c0,
-	0x9340, 0x1078, 0x9343, 0x00c0, 0x907b, 0x6106, 0x1078, 0x9368,
-	0x00c0, 0x9206, 0x6007, 0x002e, 0x0078, 0x9195, 0x6007, 0x002f,
-	0x0078, 0x9195, 0x0e7e, 0x0d7e, 0x0c7e, 0x6018, 0xa080, 0x0001,
-	0x200c, 0xa184, 0x00ff, 0xa086, 0x0006, 0x0040, 0x9223, 0xa184,
-	0xff00, 0x8007, 0xa086, 0x0006, 0x0040, 0x9223, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x0078, 0x919a, 0x2001, 0xa371, 0x2004, 0xd0e4, 0x0040,
-	0x928d, 0x2071, 0xa88c, 0x7010, 0x6036, 0x7014, 0x603a, 0x7108,
-	0x720c, 0x2001, 0xa352, 0x2004, 0xd0a4, 0x0040, 0x9241, 0x6018,
-	0x2068, 0x6810, 0xa106, 0x00c0, 0x9241, 0x6814, 0xa206, 0x0040,
-	0x9265, 0x2001, 0xa352, 0x2004, 0xd0ac, 0x00c0, 0x9281, 0x2069,
-	0xa300, 0x686c, 0xa206, 0x00c0, 0x9281, 0x6868, 0xa106, 0x00c0,
-	0x9281, 0x7210, 0x1078, 0x8a30, 0x0040, 0x9287, 0x1078, 0x9f31,
-	0x0040, 0x9287, 0x622a, 0x6007, 0x0036, 0x6003, 0x0001, 0x1078,
-	0x5bf8, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7214, 0xa286, 0xffff,
-	0x0040, 0x9277, 0x1078, 0x8a30, 0x0040, 0x9287, 0xa280, 0x0002,
-	0x2004, 0x7110, 0xa106, 0x00c0, 0x9287, 0x0078, 0x9252, 0x7210,
-	0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x2160, 0x0040, 0x9287, 0x0078,
-	0x9252, 0x6007, 0x0037, 0x6013, 0x1500, 0x0078, 0x925d, 0x6007,
-	0x0037, 0x6013, 0x1700, 0x0078, 0x925d, 0x6007, 0x0012, 0x0078,
-	0x925d, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007,
-	0xa086, 0x0006, 0x00c0, 0x919a, 0x0e7e, 0x0d7e, 0x0c7e, 0x2001,
-	0xa371, 0x2004, 0xd0e4, 0x0040, 0x92fd, 0x2069, 0xa300, 0x2071,
-	0xa88c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x00c0,
-	0x92ba, 0x7208, 0x0c7e, 0x2c08, 0x1078, 0x9e8c, 0x2c10, 0x0c7f,
-	0x0040, 0x92f1, 0x1078, 0x8a30, 0x0040, 0x92f1, 0x0c7e, 0x027e,
-	0x2260, 0x1078, 0x874a, 0x027f, 0x0c7f, 0x7118, 0xa18c, 0xff00,
-	0x810f, 0xa186, 0x0001, 0x0040, 0x92db, 0xa186, 0x0005, 0x0040,
-	0x92d5, 0xa186, 0x0007, 0x00c0, 0x92e5, 0xa280, 0x0004, 0x2004,
-	0xa005, 0x0040, 0x92e5, 0x057e, 0x7510, 0x7614, 0x1078, 0x9f46,
-	0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x6007, 0x003b, 0x602b,
-	0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x0078,
-	0x92e1, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700, 0x6003,
-	0x0001, 0x1078, 0x5bf8, 0x0078, 0x92e1, 0x6007, 0x003b, 0x602b,
-	0x000b, 0x6013, 0x0000, 0x0078, 0x925d, 0x0e7e, 0x027e, 0x1078,
-	0x4897, 0x0040, 0x933a, 0x1078, 0x4887, 0x1078, 0xa148, 0x00c0,
-	0x9338, 0x2071, 0xa300, 0x70c8, 0xc085, 0x70ca, 0x0f7e, 0x2079,
-	0x0100, 0x7294, 0xa284, 0x00ff, 0x706a, 0x78e6, 0xa284, 0xff00,
-	0x726c, 0xa205, 0x706e, 0x78ea, 0x0f7f, 0x70d3, 0x0000, 0x2001,
-	0xa352, 0x2004, 0xd0a4, 0x0040, 0x9331, 0x2011, 0xa5c4, 0x2013,
-	0x07d0, 0xd0ac, 0x00c0, 0x933a, 0x1078, 0x260d, 0x0078, 0x933a,
-	0x1078, 0xa178, 0x027f, 0x0e7f, 0x1078, 0x753d, 0x0078, 0x9199,
-	0x1078, 0x753d, 0x007c, 0x0d7e, 0x067e, 0x6618, 0x2668, 0x6e04,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x9360, 0xa686,
-	0x0004, 0x0040, 0x9360, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006,
-	0x0040, 0x9360, 0xa686, 0x0004, 0x0040, 0x9360, 0xa085, 0x0001,
-	0x067f, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x9397, 0x0d7f, 0x007c,
-	0x0d7e, 0x1078, 0x93a6, 0x00c0, 0x9390, 0x680c, 0xa08c, 0xff00,
-	0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4,
-	0x0040, 0x937e, 0x2009, 0x0001, 0x0078, 0x938c, 0xd1ec, 0x0040,
-	0x9390, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x1078, 0x24e3, 0x00c0,
-	0x9390, 0x2110, 0x2009, 0x0000, 0x1078, 0x285b, 0x0078, 0x9394,
-	0xa085, 0x0001, 0x0078, 0x9395, 0xa006, 0x0d7f, 0x007c, 0x2069,
-	0xa88d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x93a4, 0x6013, 0x0000,
-	0xa085, 0x0001, 0x0078, 0x93a5, 0xa006, 0x007c, 0x6013, 0x0000,
-	0x2069, 0xa88c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x00c0,
-	0x93ba, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0040, 0x93ba,
-	0xa08e, 0x0010, 0x007c, 0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1328,
-	0xa1b6, 0x0013, 0x00c0, 0x93c7, 0x2008, 0x0079, 0x93da, 0xa1b6,
-	0x0027, 0x0040, 0x93cf, 0xa1b6, 0x0014, 0x10c0, 0x1328, 0x2001,
-	0x0007, 0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
-	0x6109, 0x007c, 0x941a, 0x941c, 0x941a, 0x941a, 0x941a, 0x941c,
-	0x9424, 0x94ae, 0x9471, 0x94ae, 0x9485, 0x94ae, 0x9424, 0x94ae,
-	0x94a6, 0x94ae, 0x94a6, 0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a,
-	0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a,
-	0x941c, 0x941a, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x941a, 0x94ae,
-	0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a,
-	0x94ae, 0x94ae, 0x941a, 0x941a, 0x941a, 0x941a, 0x941a, 0x941c,
-	0x94ae, 0x94ae, 0x941a, 0x941a, 0x94ae, 0x94ae, 0x941a, 0x941a,
-	0x941a, 0x941a, 0x1078, 0x1328, 0x1078, 0x6010, 0x6003, 0x0002,
-	0x1078, 0x6109, 0x0078, 0x94b4, 0x0f7e, 0x2079, 0xa351, 0x7804,
-	0x0f7f, 0xd0ac, 0x00c0, 0x94ae, 0x2001, 0x0000, 0x1078, 0x442b,
-	0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x94ae,
-	0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9448, 0x6010,
-	0xa005, 0x0040, 0x9448, 0x0c7f, 0x1078, 0x35f7, 0x0078, 0x94ae,
-	0x0c7f, 0x2001, 0xa300, 0x2004, 0xa086, 0x0002, 0x00c0, 0x9457,
-	0x0f7e, 0x2079, 0xa300, 0x788c, 0x8000, 0x788e, 0x0f7f, 0x2001,
-	0x0002, 0x1078, 0x443f, 0x1078, 0x6010, 0x601f, 0x0001, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x1078, 0x5c45, 0x1078, 0x6109, 0x0c7e,
-	0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x58e1, 0x0c7f, 0x0078,
-	0x94b4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0xa686, 0x0004, 0x0040,
-	0x94ae, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0xa300, 0x2004,
-	0xa086, 0x0003, 0x00c0, 0x948e, 0x1078, 0x35f7, 0x2001, 0x0006,
-	0x1078, 0x94b5, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x94ae, 0x2001, 0x0006,
-	0x0078, 0x94ac, 0x2001, 0x0004, 0x0078, 0x94ac, 0x2001, 0x0006,
-	0x1078, 0x94b5, 0x0078, 0x94ae, 0x1078, 0x4472, 0x1078, 0x6010,
-	0x1078, 0x753d, 0x1078, 0x6109, 0x007c, 0x017e, 0x0d7e, 0x6118,
-	0x2168, 0x6900, 0xd184, 0x0040, 0x94d0, 0x6104, 0xa18e, 0x000a,
-	0x00c0, 0x94c8, 0x699c, 0xd1a4, 0x00c0, 0x94c8, 0x2001, 0x0007,
-	0x1078, 0x443f, 0x2001, 0x0000, 0x1078, 0x442b, 0x1078, 0x2839,
-	0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084,
-	0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1328, 0xa1b6,
-	0x0015, 0x00c0, 0x94e7, 0x1079, 0x94ee, 0x0078, 0x94ed, 0xa1b6,
-	0x0016, 0x10c0, 0x1328, 0x1079, 0x94fa, 0x007c, 0x7ad0, 0x7ad0,
-	0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x9547, 0x9506, 0x7ad0, 0x7ad0,
-	0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0,
-	0x9547, 0x954f, 0x7ad0, 0x7ad0, 0x7ad0, 0x7ad0, 0x0f7e, 0x2079,
-	0xa351, 0x7804, 0xd0ac, 0x00c0, 0x952d, 0x6018, 0xa07d, 0x0040,
-	0x952d, 0x7800, 0xd0f4, 0x00c0, 0x9519, 0x7810, 0xa005, 0x00c0,
-	0x952d, 0x2001, 0x0000, 0x1078, 0x442b, 0x2001, 0x0002, 0x1078,
-	0x443f, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
-	0x5c45, 0x1078, 0x6109, 0x0078, 0x9545, 0x2011, 0xa883, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x24e3, 0x00c0, 0x9545, 0x0c7e, 0x1078,
-	0x4501, 0x0040, 0x9540, 0x0c7f, 0x1078, 0x753d, 0x0078, 0x9545,
-	0x1078, 0x4235, 0x0c7f, 0x1078, 0x753d, 0x0f7f, 0x007c, 0x6604,
-	0xa6b6, 0x001e, 0x00c0, 0x954e, 0x1078, 0x753d, 0x007c, 0x1078,
-	0x7d0a, 0x00c0, 0x955b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
-	0x5c45, 0x0078, 0x955d, 0x1078, 0x753d, 0x007c, 0x6004, 0xa08a,
-	0x0044, 0x10c8, 0x1328, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078,
-	0x6109, 0x007c, 0xa182, 0x0040, 0x0079, 0x956e, 0x9581, 0x9581,
-	0x9581, 0x9581, 0x9583, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
-	0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581, 0x9581,
-	0x9581, 0x1078, 0x1328, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e,
-	0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x9594,
-	0x2021, 0x0000, 0x1078, 0xa111, 0x6106, 0x2071, 0xa880, 0x7444,
-	0xa4a4, 0xff00, 0x0040, 0x95eb, 0xa486, 0x2000, 0x00c0, 0x95a6,
-	0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5a6d, 0x1078, 0x1381,
-	0x1040, 0x1328, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803,
-	0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2,
-	0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084,
-	0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4982,
-	0x017f, 0xa486, 0x2000, 0x00c0, 0x95d3, 0x2019, 0x0017, 0x1078,
-	0x9e3b, 0x0078, 0x9645, 0xa486, 0x0400, 0x00c0, 0x95dd, 0x2019,
-	0x0002, 0x1078, 0x9dec, 0x0078, 0x9645, 0xa486, 0x0200, 0x00c0,
-	0x95e3, 0x1078, 0x9dd1, 0xa486, 0x1000, 0x00c0, 0x95e9, 0x1078,
-	0x9e20, 0x0078, 0x9645, 0x2069, 0xa62d, 0x6a00, 0xd284, 0x0040,
-	0x969b, 0xa284, 0x0300, 0x00c0, 0x9693, 0x6804, 0xa005, 0x0040,
-	0x9683, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1366, 0x0040, 0x964c,
-	0x7800, 0xd08c, 0x00c0, 0x9607, 0x7804, 0x8001, 0x7806, 0x6013,
-	0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008,
-	0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0x6986, 0x6846, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286,
-	0x0002, 0x00c0, 0x9627, 0x684f, 0x0040, 0x0078, 0x9631, 0xa286,
-	0x0001, 0x00c0, 0x962f, 0x684f, 0x0080, 0x0078, 0x9631, 0x684f,
-	0x0000, 0x20a9, 0x000a, 0x2001, 0xa890, 0xad90, 0x0015, 0x200c,
-	0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x9637, 0x200c, 0x6982,
-	0x8000, 0x200c, 0x697e, 0x1078, 0x4982, 0x027f, 0x047f, 0x157f,
-	0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001,
-	0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645,
-	0x2069, 0xa892, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0,
-	0x9677, 0x2069, 0xa880, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110,
-	0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007,
-	0x0043, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0078, 0x9645, 0x6013,
-	0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
-	0x6109, 0x0078, 0x9645, 0x6013, 0x0300, 0x0078, 0x9689, 0x6013,
-	0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5bf8, 0x1078,
-	0x6109, 0x0078, 0x9645, 0x6013, 0x0500, 0x0078, 0x9689, 0x6013,
-	0x0600, 0x0078, 0x9658, 0x6013, 0x0200, 0x0078, 0x9658, 0xa186,
-	0x0013, 0x00c0, 0x96b1, 0x6004, 0xa08a, 0x0040, 0x1048, 0x1328,
-	0xa08a, 0x0053, 0x10c8, 0x1328, 0xa082, 0x0040, 0x2008, 0x0079,
-	0x9725, 0xa186, 0x0051, 0x0040, 0x96be, 0xa186, 0x0047, 0x00c0,
-	0x96d7, 0x6004, 0xa086, 0x0041, 0x0040, 0x96e5, 0x2001, 0x0109,
-	0x2004, 0xd084, 0x0040, 0x96e5, 0x127e, 0x2091, 0x2200, 0x007e,
-	0x017e, 0x027e, 0x1078, 0x5ad2, 0x027f, 0x017f, 0x007f, 0x127f,
-	0x6000, 0xa086, 0x0002, 0x00c0, 0x96e5, 0x0078, 0x976a, 0xa186,
-	0x0027, 0x0040, 0x96df, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6004,
-	0xa082, 0x0040, 0x2008, 0x0079, 0x96e8, 0x1078, 0x7583, 0x007c,
-	0x96fb, 0x96fd, 0x96fd, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
-	0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb, 0x96fb,
-	0x96fb, 0x96fb, 0x96fb, 0x1078, 0x1328, 0x1078, 0x6010, 0x1078,
-	0x6109, 0x037e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x9722, 0xad84,
-	0xf000, 0x0040, 0x9722, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc,
-	0x00c0, 0x9722, 0x2019, 0x0004, 0x1078, 0x9e70, 0x6013, 0x0000,
-	0x6014, 0xa005, 0x00c0, 0x9720, 0x2001, 0xa5a1, 0x2004, 0x6016,
-	0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c, 0x9738, 0x9757, 0x9741,
-	0x9764, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
-	0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738, 0x9738,
-	0x1078, 0x1328, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
-	0x200a, 0x1078, 0x6010, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4,
-	0x0040, 0x9752, 0x6003, 0x0007, 0x2009, 0x0043, 0x1078, 0x756c,
-	0x0078, 0x9754, 0x6003, 0x0002, 0x1078, 0x6109, 0x007c, 0x1078,
-	0x6010, 0x1078, 0xa0c6, 0x00c0, 0x9761, 0x1078, 0x5a41, 0x1078,
-	0x753d, 0x1078, 0x6109, 0x007c, 0x1078, 0x6010, 0x2009, 0x0041,
-	0x0078, 0x98c1, 0xa182, 0x0040, 0x0079, 0x976e, 0x9781, 0x9783,
-	0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9784, 0x9781, 0x9781,
-	0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x9781, 0x978f,
-	0x9781, 0x1078, 0x1328, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1,
-	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15ec, 0x007c, 0x0d7e,
-	0x1078, 0x5a41, 0x0d7f, 0x1078, 0xa134, 0x1078, 0x753d, 0x007c,
-	0xa182, 0x0040, 0x0079, 0x979c, 0x97af, 0x97af, 0x97af, 0x97af,
-	0x97af, 0x97af, 0x97af, 0x97b1, 0x97af, 0x97b4, 0x97df, 0x97af,
-	0x97af, 0x97af, 0x97af, 0x97df, 0x97af, 0x97af, 0x97af, 0x1078,
-	0x1328, 0x1078, 0x7583, 0x007c, 0x1078, 0x60b8, 0x1078, 0x61d3,
-	0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x97ca, 0xa08c,
-	0x0003, 0xa18e, 0x0002, 0x0040, 0x97d2, 0x2009, 0x0041, 0x0d7f,
-	0x0078, 0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41,
-	0x0d7f, 0x007c, 0x1078, 0xa0c6, 0x0040, 0x97d8, 0x0d7f, 0x007c,
-	0x1078, 0x5a41, 0x1078, 0x753d, 0x0d7f, 0x0078, 0x97d1, 0x037e,
-	0x1078, 0x60b8, 0x1078, 0x61d3, 0x6010, 0x0d7e, 0x2068, 0x6018,
-	0x2004, 0xd0bc, 0x0040, 0x97ff, 0x684c, 0xa084, 0x0003, 0xa086,
-	0x0002, 0x0040, 0x97fb, 0x687c, 0x632c, 0xa31a, 0x632e, 0x6880,
-	0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0078, 0x9810, 0x2019,
-	0x0004, 0x1078, 0x9e70, 0x6014, 0xa005, 0x00c0, 0x980c, 0x2001,
-	0xa5a1, 0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007,
-	0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9821, 0x6004,
-	0xa086, 0x0042, 0x10c0, 0x1328, 0x1078, 0x6010, 0x1078, 0x6109,
-	0x007c, 0xa186, 0x0027, 0x0040, 0x9829, 0xa186, 0x0014, 0x00c0,
-	0x9839, 0x6004, 0xa086, 0x0042, 0x10c0, 0x1328, 0x2001, 0x0007,
-	0x1078, 0x4472, 0x1078, 0x6010, 0x1078, 0x8c01, 0x1078, 0x6109,
-	0x007c, 0xa182, 0x0040, 0x0079, 0x983d, 0x9850, 0x9850, 0x9850,
-	0x9850, 0x9850, 0x9850, 0x9850, 0x9852, 0x985e, 0x9850, 0x9850,
-	0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850,
-	0x1078, 0x1328, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x15ec, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e,
-	0x2068, 0x6810, 0x6a14, 0x6118, 0x210c, 0xd1bc, 0x0040, 0x987d,
-	0x6124, 0xd1f4, 0x00c0, 0x987d, 0x007e, 0x047e, 0x057e, 0x6c7c,
-	0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028,
-	0xa529, 0x652a, 0x057f, 0x047f, 0x007f, 0xa20d, 0x00c0, 0x9891,
-	0x684c, 0xd0fc, 0x0040, 0x9889, 0x2009, 0x0041, 0x0d7f, 0x0078,
-	0x98c1, 0x6003, 0x0007, 0x6017, 0x0000, 0x1078, 0x5a41, 0x0d7f,
-	0x007c, 0x007e, 0x0f7e, 0x2c78, 0x1078, 0x4893, 0x0f7f, 0x007f,
-	0x0040, 0x989e, 0x6003, 0x0002, 0x0d7f, 0x007c, 0x2009, 0xa30d,
-	0x210c, 0xd19c, 0x0040, 0x98a8, 0x6003, 0x0007, 0x0078, 0x98aa,
-	0x6003, 0x0006, 0x1078, 0x98b0, 0x1078, 0x5a43, 0x0d7f, 0x007c,
-	0xd2fc, 0x0040, 0x98bc, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000,
-	0x2009, 0x0009, 0x0078, 0x98be, 0x2009, 0x0015, 0x6a6a, 0x6866,
-	0x007c, 0xa182, 0x0040, 0x0048, 0x98c7, 0x0079, 0x98d4, 0xa186,
-	0x0013, 0x0040, 0x98cf, 0xa186, 0x0014, 0x10c0, 0x1328, 0x6024,
-	0xd0dc, 0x1040, 0x1328, 0x007c, 0x98e7, 0x98ee, 0x98fa, 0x9906,
-	0x98e7, 0x98e7, 0x98e7, 0x9915, 0x98e7, 0x98e9, 0x98e9, 0x98e7,
-	0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x98e7, 0x1078,
-	0x1328, 0x6024, 0xd0dc, 0x1040, 0x1328, 0x007c, 0x6003, 0x0001,
-	0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091, 0x8000, 0x1078, 0x6109,
-	0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x6003, 0x0003,
-	0x6106, 0x2c10, 0x1078, 0x1cab, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x5c64, 0x1078, 0x61d3, 0x127f, 0x007c, 0xa016, 0x1078, 0x15ec,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040,
-	0x1079, 0x9926, 0x0d7f, 0x037f, 0x127f, 0x007c, 0x9936, 0x9938,
-	0x994d, 0x996c, 0x9936, 0x9936, 0x9936, 0x9984, 0x9936, 0x9936,
-	0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x9936, 0x1078, 0x1328,
-	0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003,
-	0xa39e, 0x0003, 0x0040, 0x9962, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x5bf8, 0x1078, 0x6109, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c,
-	0xd0fc, 0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040,
-	0x9962, 0x6003, 0x0001, 0x6106, 0x1078, 0x5bf8, 0x1078, 0x6109,
-	0x0078, 0x9987, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004,
-	0x1078, 0x9e70, 0x0078, 0x9987, 0x6010, 0x2068, 0x684c, 0xd0fc,
-	0x0040, 0x9962, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9962,
-	0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x1cab, 0x1078, 0x5c64,
-	0x1078, 0x61d3, 0x0078, 0x9987, 0xa016, 0x1078, 0x15ec, 0x007c,
-	0x1078, 0x6010, 0x6110, 0x81ff, 0x0040, 0x9999, 0x0d7e, 0x2168,
-	0x1078, 0xa181, 0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f,
-	0x0d7f, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x1078, 0x60b8,
-	0x6110, 0x81ff, 0x0040, 0x99af, 0x0d7e, 0x2168, 0x1078, 0xa181,
-	0x037e, 0x2019, 0x0029, 0x1078, 0x9e70, 0x037f, 0x0d7f, 0x1078,
-	0x8c01, 0x1078, 0x61d3, 0x007c, 0xa182, 0x0085, 0x0079, 0x99b8,
-	0x99c1, 0x99bf, 0x99bf, 0x99cd, 0x99bf, 0x99bf, 0x99bf, 0x1078,
-	0x1328, 0x6003, 0x000b, 0x6106, 0x1078, 0x5bf8, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x6109, 0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078,
-	0xa0bf, 0x0040, 0x99d7, 0x1078, 0x753d, 0x0078, 0x99f3, 0x2071,
-	0xa880, 0x7224, 0x6212, 0x7220, 0x1078, 0x9d10, 0x0040, 0x99e4,
-	0x6007, 0x0086, 0x0078, 0x99ed, 0x6007, 0x0087, 0x7224, 0xa296,
-	0xffff, 0x00c0, 0x99ed, 0x6007, 0x0086, 0x6003, 0x0001, 0x1078,
-	0x5bf8, 0x1078, 0x6109, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013,
-	0x00c0, 0x9a07, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1328, 0xa08a,
-	0x008c, 0x10c8, 0x1328, 0xa082, 0x0085, 0x0079, 0x9a1e, 0xa186,
-	0x0027, 0x0040, 0x9a13, 0xa186, 0x0014, 0x0040, 0x9a13, 0x1078,
-	0x7583, 0x0078, 0x9a1d, 0x2001, 0x0007, 0x1078, 0x4472, 0x1078,
-	0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0x9a25, 0x9a27,
-	0x9a27, 0x9a25, 0x9a25, 0x9a25, 0x9a25, 0x1078, 0x1328, 0x1078,
-	0x6010, 0x1078, 0x8c01, 0x1078, 0x6109, 0x007c, 0xa182, 0x0085,
-	0x1048, 0x1328, 0xa182, 0x008c, 0x10c8, 0x1328, 0xa182, 0x0085,
-	0x0079, 0x9a3a, 0x9a41, 0x9a41, 0x9a41, 0x9a43, 0x9a41, 0x9a41,
-	0x9a41, 0x1078, 0x1328, 0x007c, 0xa186, 0x0013, 0x0040, 0x9a54,
-	0xa186, 0x0014, 0x0040, 0x9a54, 0xa186, 0x0027, 0x0040, 0x9a54,
-	0x1078, 0x7583, 0x0078, 0x9a5a, 0x1078, 0x6010, 0x1078, 0x8c01,
-	0x1078, 0x6109, 0x007c, 0x037e, 0x1078, 0xa134, 0x603f, 0x0000,
-	0x2019, 0x000b, 0x1078, 0x9a6a, 0x601f, 0x0006, 0x6003, 0x0007,
-	0x037f, 0x007c, 0x127e, 0x037e, 0x2091, 0x8000, 0x087e, 0x2c40,
-	0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x00c0,
-	0x9aa5, 0x077e, 0x2c38, 0x1078, 0x7105, 0x077f, 0x00c0, 0x9aa5,
-	0x6000, 0xa086, 0x0000, 0x0040, 0x9aa5, 0x601c, 0xa086, 0x0007,
-	0x0040, 0x9aa5, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x9a96,
-	0x1078, 0xa134, 0x601f, 0x0007, 0x1078, 0x1749, 0x6010, 0x2068,
-	0x1078, 0x8a44, 0x0040, 0x9a9e, 0x1078, 0x9e70, 0x0d7f, 0x6013,
-	0x0000, 0x1078, 0xa134, 0x601f, 0x0007, 0x037f, 0x127f, 0x007c,
-	0x0f7e, 0x0c7e, 0x037e, 0x157e, 0x2079, 0xa880, 0x7938, 0x783c,
-	0x1078, 0x24e3, 0x00c0, 0x9af6, 0x017e, 0x0c7e, 0x1078, 0x4501,
-	0x00c0, 0x9af6, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9, 0x0004,
-	0x1078, 0x7e55, 0x00c0, 0x9af6, 0x017f, 0x027f, 0x027e, 0x017e,
-	0x2019, 0x0029, 0x1078, 0x71e0, 0x1078, 0x5d53, 0x077e, 0x2039,
-	0x0000, 0x1078, 0x5c78, 0x077f, 0x017f, 0x077e, 0x2039, 0x0000,
-	0x1078, 0x9c38, 0x077f, 0x1078, 0x471b, 0x027e, 0x6204, 0xa294,
-	0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9aea, 0xa286, 0x0004,
-	0x00c0, 0x9aed, 0x62a0, 0x1078, 0x28d5, 0x027f, 0x017f, 0x1078,
-	0x4235, 0x6612, 0x6516, 0xa006, 0x0078, 0x9af8, 0x0c7f, 0x017f,
-	0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x0e7e,
-	0x017e, 0x2009, 0xa31f, 0x2104, 0xa086, 0x0074, 0x00c0, 0x9b60,
-	0x2069, 0xa88e, 0x690c, 0xa182, 0x0100, 0x0048, 0x9b50, 0x6908,
-	0xa184, 0x8000, 0x0040, 0x9b5c, 0x6018, 0x2070, 0x7010, 0xa084,
-	0x00ff, 0x0040, 0x9b1f, 0x7000, 0xd0f4, 0x0040, 0x9b23, 0xa184,
-	0x0800, 0x0040, 0x9b5c, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54,
-	0x6914, 0x2069, 0xa8ae, 0x6904, 0x81ff, 0x00c0, 0x9b48, 0x690c,
-	0xa182, 0x0100, 0x0048, 0x9b50, 0x6908, 0x81ff, 0x00c0, 0x9b4c,
-	0x6910, 0xa18a, 0x0001, 0x0048, 0x9b54, 0x6918, 0xa18a, 0x0001,
-	0x0048, 0x9b5c, 0x0078, 0x9b66, 0x6013, 0x0100, 0x0078, 0x9b62,
-	0x6013, 0x0300, 0x0078, 0x9b62, 0x6013, 0x0500, 0x0078, 0x9b62,
-	0x6013, 0x0700, 0x0078, 0x9b62, 0x6013, 0x0900, 0x0078, 0x9b62,
-	0x6013, 0x0b00, 0x0078, 0x9b62, 0x6013, 0x0f00, 0x0078, 0x9b62,
-	0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x9b67, 0xa006, 0x017f,
-	0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e,
-	0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006,
-	0x0040, 0x9b90, 0xa286, 0x0004, 0x0040, 0x9b90, 0xa394, 0xff00,
-	0x8217, 0xa286, 0x0006, 0x0040, 0x9b90, 0xa286, 0x0004, 0x0040,
-	0x9b90, 0x0c7e, 0x2d60, 0x1078, 0x4513, 0x0c7f, 0x0078, 0x9bcb,
-	0x2011, 0xa896, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55,
-	0x00c0, 0x9bcc, 0x2011, 0xa89a, 0xad98, 0x0006, 0x20a9, 0x0004,
-	0x1078, 0x7e55, 0x00c0, 0x9bcc, 0x047e, 0x017e, 0x6aa0, 0xa294,
-	0x00ff, 0x8227, 0xa006, 0x2009, 0xa352, 0x210c, 0xd1a4, 0x0040,
-	0x9bb8, 0x2009, 0x0029, 0x1078, 0x9ec0, 0x6800, 0xc0e5, 0x6802,
-	0x2019, 0x0029, 0x1078, 0x5d53, 0x077e, 0x2039, 0x0000, 0x1078,
-	0x5c78, 0x2c08, 0x1078, 0x9c38, 0x077f, 0x2001, 0x0007, 0x1078,
-	0x4472, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f,
-	0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xa88e, 0x6800, 0xa086, 0x0800,
-	0x0040, 0x9bde, 0x6013, 0x0000, 0x0078, 0x9bdf, 0xa006, 0x0d7f,
-	0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079,
-	0xa88c, 0x7930, 0x7834, 0x1078, 0x24e3, 0x00c0, 0x9c05, 0x1078,
-	0x4501, 0x00c0, 0x9c05, 0x2011, 0xa890, 0xac98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x7e55, 0x00c0, 0x9c05, 0x2011, 0xa894, 0xac98,
-	0x0006, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x157f, 0x037f, 0x027f,
-	0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e,
-	0x037e, 0x157e, 0x2011, 0xa883, 0x2204, 0x8211, 0x220c, 0x1078,
-	0x24e3, 0x00c0, 0x9c31, 0x1078, 0x4501, 0x00c0, 0x9c31, 0x2011,
-	0xa896, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
-	0x9c31, 0x2011, 0xa89a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078,
-	0x7e55, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c,
-	0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e,
-	0x127e, 0x2091, 0x8000, 0x2740, 0x2029, 0xa5b4, 0x252c, 0x2021,
-	0xa5ba, 0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060,
-	0x81ff, 0x0040, 0x9c59, 0x8001, 0xa602, 0x00c8, 0x9cc3, 0x0078,
-	0x9c5c, 0xa606, 0x0040, 0x9cc3, 0x2100, 0xac06, 0x0040, 0x9cb9,
-	0x1078, 0x9ee5, 0x0040, 0x9cb9, 0x671c, 0xa786, 0x0001, 0x0040,
-	0x9cde, 0xa786, 0x0004, 0x0040, 0x9cde, 0xa786, 0x0007, 0x0040,
-	0x9cb9, 0x2500, 0xac06, 0x0040, 0x9cb9, 0x2400, 0xac06, 0x0040,
-	0x9cb9, 0x1078, 0x9ef9, 0x00c0, 0x9cb9, 0x88ff, 0x0040, 0x9c84,
-	0x6020, 0xa906, 0x00c0, 0x9cb9, 0x0d7e, 0x6000, 0xa086, 0x0004,
-	0x00c0, 0x9c8e, 0x017e, 0x1078, 0x1749, 0x017f, 0xa786, 0x0008,
-	0x00c0, 0x9c9d, 0x1078, 0x8c3b, 0x00c0, 0x9c9d, 0x1078, 0x7a05,
-	0x0d7f, 0x1078, 0x8c01, 0x0078, 0x9cb9, 0x6010, 0x2068, 0x1078,
-	0x8a44, 0x0040, 0x9cb6, 0xa786, 0x0003, 0x00c0, 0x9ccd, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa181, 0x017e, 0x1078,
-	0x8cb8, 0x1078, 0x4982, 0x017f, 0x1078, 0x8bf4, 0x0d7f, 0x1078,
-	0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
-	0x9cc3, 0x0078, 0x9c4c, 0x127f, 0x027f, 0x047f, 0x057f, 0x067f,
-	0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0,
-	0x9ca7, 0xa386, 0x0005, 0x0040, 0x9cdb, 0x1078, 0xa181, 0x1078,
-	0x9e70, 0x0078, 0x9cb6, 0x0d7f, 0x0078, 0x9cb9, 0x1078, 0x9ef9,
-	0x00c0, 0x9cb9, 0x81ff, 0x0040, 0x9cb9, 0xa180, 0x0001, 0x2004,
-	0xa086, 0x0018, 0x0040, 0x9cf3, 0xa180, 0x0001, 0x2004, 0xa086,
-	0x002d, 0x00c0, 0x9cb9, 0x6000, 0xa086, 0x0002, 0x00c0, 0x9cb9,
-	0x1078, 0x8c27, 0x0040, 0x9d04, 0x1078, 0x8c3b, 0x00c0, 0x9cb9,
-	0x1078, 0x7a05, 0x0078, 0x9d0c, 0x1078, 0x2839, 0x1078, 0x8c3b,
-	0x00c0, 0x9d0c, 0x1078, 0x7a05, 0x1078, 0x8c01, 0x0078, 0x9cb9,
-	0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x9e8c, 0x017f,
-	0x0040, 0x9d1f, 0x601c, 0xa084, 0x000f, 0x1079, 0x9d22, 0x0e7f,
-	0x0c7f, 0x007c, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a, 0x9d2a,
-	0x9d2c, 0x9d2a, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080,
-	0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020,
-	0x1078, 0x9ec0, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078,
-	0x9a6a, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078,
-	0x442b, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019,
-	0xa305, 0x2011, 0xa896, 0x1078, 0x7e55, 0x037f, 0x027f, 0x017f,
-	0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x087e, 0x077e,
-	0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2061, 0xaa00,
-	0x2079, 0x0001, 0x8fff, 0x0040, 0x9dc3, 0x2071, 0xa300, 0x7644,
-	0x7060, 0x8001, 0xa602, 0x00c8, 0x9dc3, 0x88ff, 0x0040, 0x9d7e,
-	0x2800, 0xac06, 0x00c0, 0x9db9, 0x2079, 0x0000, 0x1078, 0x9ee5,
-	0x0040, 0x9db9, 0x2400, 0xac06, 0x0040, 0x9db9, 0x671c, 0xa786,
-	0x0006, 0x00c0, 0x9db9, 0xa786, 0x0007, 0x0040, 0x9db9, 0x88ff,
-	0x00c0, 0x9d9d, 0x6018, 0xa206, 0x00c0, 0x9db9, 0x85ff, 0x0040,
-	0x9d9d, 0x6020, 0xa106, 0x00c0, 0x9db9, 0x0d7e, 0x6000, 0xa086,
-	0x0004, 0x00c0, 0x9da9, 0x1078, 0xa134, 0x601f, 0x0007, 0x1078,
-	0x1749, 0x6010, 0x2068, 0x1078, 0x8a44, 0x0040, 0x9db3, 0x047e,
-	0x1078, 0x9e70, 0x047f, 0x0d7f, 0x1078, 0x8c01, 0x88ff, 0x00c0,
-	0x9dcd, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02, 0x00c8,
-	0x9dc3, 0x0078, 0x9d6a, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f,
-	0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078,
-	0x9dc4, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
-	0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049, 0x0000, 0x1078,
-	0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x1078,
-	0x9d5b, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e,
-	0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000,
-	0x017e, 0x037e, 0x1078, 0x4501, 0x00c0, 0x9e14, 0x2c10, 0x057e,
-	0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x097e, 0x2049,
-	0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078,
-	0x7105, 0x1078, 0x9d5b, 0x057f, 0x037f, 0x017f, 0x8108, 0x00f0,
-	0x9df8, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
-	0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000, 0x2029, 0x0001,
-	0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078, 0x7058, 0x097f,
-	0x087f, 0x2039, 0x0000, 0x1078, 0x7105, 0x2c20, 0x1078, 0x9d5b,
-	0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e, 0x077e, 0x0c7e,
-	0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x037e,
-	0x1078, 0x4501, 0x00c0, 0x9e64, 0x2c10, 0x087e, 0x2041, 0x0000,
-	0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa111, 0x047f, 0x097e,
-	0x2049, 0x0000, 0x1078, 0x7058, 0x097f, 0x087f, 0x2039, 0x0000,
-	0x1078, 0x7105, 0x1078, 0x9d5b, 0x037f, 0x017f, 0x8108, 0x00f0,
-	0x9e46, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f, 0x027f, 0x007c,
-	0x017e, 0x0f7e, 0xad82, 0xca00, 0x0048, 0x9e89, 0xad82, 0xffff,
-	0x00c8, 0x9e89, 0x6800, 0xa07d, 0x0040, 0x9e86, 0x6803, 0x0000,
-	0x6b52, 0x1078, 0x4982, 0x2f68, 0x0078, 0x9e7a, 0x6b52, 0x1078,
-	0x4982, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
-	0xaa00, 0x2071, 0xa300, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
-	0x9ebb, 0x2100, 0xac06, 0x0040, 0x9ead, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x9ead, 0x6008, 0xa206, 0x00c0, 0x9ead, 0x6018, 0xa1a0,
-	0x0006, 0x2424, 0xa406, 0x0040, 0x9eb7, 0xace0, 0x0010, 0x2001,
-	0xa315, 0x2004, 0xac02, 0x00c8, 0x9ebb, 0x0078, 0x9e91, 0xa085,
-	0x0001, 0x0078, 0x9ebc, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c,
-	0x0d7e, 0x007e, 0x1078, 0x1381, 0x007f, 0x1040, 0x1328, 0x6837,
-	0x010d, 0x685e, 0x027e, 0x2010, 0x1078, 0x8a30, 0x2001, 0x0000,
-	0x0040, 0x9ed6, 0x2200, 0xa080, 0x0008, 0x2004, 0x027f, 0x684a,
-	0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802, 0x683a,
-	0x685a, 0x1078, 0x4982, 0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000,
-	0x0040, 0x9ef8, 0xa786, 0x0001, 0x0040, 0x9ef8, 0xa786, 0x000a,
-	0x0040, 0x9ef8, 0xa786, 0x0009, 0x0040, 0x9ef8, 0xa085, 0x0001,
-	0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c,
-	0x017e, 0x6004, 0xa08e, 0x001e, 0x00c0, 0x9f1a, 0x8007, 0x6130,
-	0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0005, 0x2001, 0xa5a1, 0x2004, 0x6016, 0x1078, 0x5bf8,
-	0x1078, 0x6109, 0x017f, 0x007c, 0x0005, 0x0005, 0x007c, 0x6024,
-	0xd0e4, 0x0040, 0x9f30, 0xd0cc, 0x0040, 0x9f2a, 0x1078, 0x8cfa,
-	0x0078, 0x9f30, 0x1078, 0xa134, 0x1078, 0x5a41, 0x1078, 0x753d,
-	0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0079, 0x9f38,
-	0x9f41, 0x9f41, 0x9f41, 0x9f43, 0x9f41, 0x9f43, 0x9f43, 0x9f41,
-	0x9f43, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa280, 0x0007,
-	0x2004, 0xa084, 0x000f, 0x0079, 0x9f4d, 0x9f56, 0x9f56, 0x9f56,
-	0x9f56, 0x9f56, 0x9f56, 0x9f61, 0x9f56, 0x9f56, 0x6007, 0x003b,
-	0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x1078, 0x5bf8,
-	0x007c, 0x0c7e, 0x2260, 0x1078, 0xa134, 0x603f, 0x0000, 0x6024,
-	0xc0f4, 0xc0cc, 0x6026, 0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007,
-	0x00c0, 0x9fc2, 0x6810, 0xa005, 0x0040, 0x9f7f, 0xa080, 0x0013,
-	0x2004, 0xd0fc, 0x00c0, 0x9f7f, 0x0d7f, 0x0078, 0x9f56, 0x6007,
-	0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109, 0x0c7e,
-	0x2d60, 0x6100, 0xa186, 0x0002, 0x00c0, 0xa050, 0x6010, 0xa005,
-	0x00c0, 0x9f99, 0x6000, 0xa086, 0x0007, 0x10c0, 0x1328, 0x0078,
-	0xa050, 0xa08c, 0xf000, 0x00c0, 0x9fa5, 0x0078, 0x9fa5, 0x2068,
-	0x6800, 0xa005, 0x00c0, 0x9f9f, 0x2d00, 0xa080, 0x0013, 0x2004,
-	0xa084, 0x0003, 0xa086, 0x0002, 0x00c0, 0x9fbe, 0x6010, 0x2068,
-	0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852,
-	0x2009, 0x0043, 0x1078, 0x98c1, 0x0078, 0xa050, 0x2009, 0x0041,
-	0x0078, 0xa04a, 0xa186, 0x0005, 0x00c0, 0xa009, 0x6810, 0xa080,
-	0x0013, 0x2004, 0xd0bc, 0x00c0, 0x9fd0, 0x0d7f, 0x0078, 0x9f56,
-	0xd0b4, 0x0040, 0x9fd8, 0xd0fc, 0x1040, 0x1328, 0x0078, 0x9f72,
-	0x6007, 0x003a, 0x6003, 0x0001, 0x1078, 0x5bf8, 0x1078, 0x6109,
-	0x0c7e, 0x2d60, 0x6100, 0xa186, 0x0002, 0x0040, 0x9feb, 0xa186,
-	0x0004, 0x00c0, 0xa050, 0x2071, 0xa5e1, 0x7000, 0xa086, 0x0003,
-	0x00c0, 0x9ff8, 0x7004, 0xac06, 0x00c0, 0x9ff8, 0x7003, 0x0000,
-	0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
-	0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078,
-	0xa04a, 0x037e, 0x0d7e, 0x0d7e, 0x1078, 0x1381, 0x037f, 0x1040,
-	0x1328, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
-	0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
-	0x2360, 0x6024, 0xc0dd, 0x6026, 0x6018, 0xa080, 0x0028, 0x2004,
-	0xa084, 0x00ff, 0x8007, 0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000,
-	0x6d6a, 0x6e66, 0x686f, 0x0001, 0x1078, 0x4982, 0x2019, 0x0045,
-	0x6008, 0x2068, 0x1078, 0x9a6a, 0x2d00, 0x600a, 0x601f, 0x0006,
-	0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f,
-	0x0078, 0xa051, 0x603f, 0x0000, 0x6003, 0x0007, 0x1078, 0x98c1,
-	0x0c7f, 0x0d7f, 0x007c, 0xa186, 0x0013, 0x00c0, 0xa05d, 0x6004,
-	0xa082, 0x0085, 0x2008, 0x0079, 0xa077, 0xa186, 0x0027, 0x00c0,
-	0xa070, 0x1078, 0x6010, 0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019,
-	0x0004, 0x1078, 0x9e70, 0x0d7f, 0x037f, 0x1078, 0x6109, 0x007c,
-	0xa186, 0x0014, 0x0040, 0xa061, 0x1078, 0x7583, 0x007c, 0xa080,
-	0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa07e, 0xa080, 0x1078, 0x1328,
-	0x1078, 0x6010, 0x6003, 0x000c, 0x1078, 0x6109, 0x007c, 0xa182,
-	0x008c, 0x00c8, 0xa091, 0xa182, 0x0085, 0x0048, 0xa091, 0x0079,
-	0xa094, 0x1078, 0x7583, 0x007c, 0xa09b, 0xa09b, 0xa09b, 0xa09b,
-	0xa09d, 0xa0bc, 0xa09b, 0x1078, 0x1328, 0x0d7e, 0x2c68, 0x1078,
-	0x74d7, 0x0040, 0xa0b7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009,
-	0xa88e, 0x210c, 0x6136, 0x2009, 0xa88f, 0x210c, 0x613a, 0x600b,
-	0xffff, 0x6918, 0x611a, 0x601f, 0x0004, 0x1078, 0x5bf8, 0x2d60,
-	0x1078, 0x753d, 0x0d7f, 0x007c, 0x1078, 0x753d, 0x007c, 0x0e7e,
-	0x6018, 0x2070, 0x7000, 0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa080,
-	0x0013, 0x200c, 0xd1ec, 0x0040, 0xa110, 0x2001, 0xa371, 0x2004,
-	0xd0ec, 0x0040, 0xa110, 0x6003, 0x0002, 0x6024, 0xc0e5, 0x6026,
-	0xd1ac, 0x0040, 0xa0ee, 0x0f7e, 0x2c78, 0x1078, 0x488f, 0x0f7f,
-	0x0040, 0xa0ee, 0x2001, 0xa5a2, 0x2004, 0x603e, 0x2009, 0xa371,
-	0x210c, 0xd1f4, 0x00c0, 0xa10e, 0x0078, 0xa100, 0x2009, 0xa371,
-	0x210c, 0xd1f4, 0x0040, 0xa0fa, 0x6024, 0xc0e4, 0x6026, 0xa006,
-	0x0078, 0xa110, 0x2001, 0xa5a2, 0x200c, 0x8103, 0xa100, 0x603e,
-	0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa10b, 0xa088,
-	0x0003, 0x0078, 0xa103, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001,
-	0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b, 0x2e04,
-	0x2060, 0x8cff, 0x0040, 0xa130, 0x84ff, 0x00c0, 0xa123, 0x6020,
-	0xa106, 0x00c0, 0xa12b, 0x600c, 0x2072, 0x1078, 0x5a41, 0x1078,
-	0x753d, 0x0078, 0xa12d, 0xacf0, 0x0003, 0x2e64, 0x0078, 0xa119,
-	0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8, 0x002b,
-	0x2d04, 0xa005, 0x0040, 0xa146, 0xac06, 0x0040, 0xa144, 0x2d04,
-	0xa0e8, 0x0003, 0x0078, 0xa138, 0x600c, 0x206a, 0x0d7f, 0x007c,
-	0x027e, 0x037e, 0x157e, 0x2011, 0xa325, 0x2204, 0xa084, 0x00ff,
-	0x2019, 0xa88e, 0x2334, 0xa636, 0x00c0, 0xa174, 0x8318, 0x2334,
-	0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa174, 0x2011, 0xa890,
-	0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x7e55, 0x00c0,
-	0xa174, 0x2011, 0xa894, 0x6018, 0xa098, 0x0006, 0x20a9, 0x0004,
-	0x1078, 0x7e55, 0x00c0, 0xa174, 0x157f, 0x037f, 0x027f, 0x007c,
-	0x0e7e, 0x2071, 0xa300, 0x1078, 0x41f5, 0x1078, 0x260d, 0x0e7f,
-	0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040, 0xa18a,
-	0x1078, 0xa18c, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852, 0x007c,
-	0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x017e,
-	0x127e, 0x2091, 0x8000, 0x2029, 0xa5b4, 0x252c, 0x2021, 0xa5ba,
-	0x2424, 0x2061, 0xaa00, 0x2071, 0xa300, 0x7644, 0x7060, 0xa606,
-	0x0040, 0xa1e4, 0x671c, 0xa786, 0x0001, 0x0040, 0xa1b3, 0xa786,
-	0x0008, 0x00c0, 0xa1da, 0x2500, 0xac06, 0x0040, 0xa1da, 0x2400,
-	0xac06, 0x0040, 0xa1da, 0x1078, 0x9ee5, 0x0040, 0xa1da, 0x1078,
-	0x9ef9, 0x00c0, 0xa1da, 0x6000, 0xa086, 0x0004, 0x00c0, 0xa1cc,
-	0x017e, 0x1078, 0x1749, 0x017f, 0x1078, 0x8c27, 0x00c0, 0xa1d2,
-	0x1078, 0x2839, 0x1078, 0x8c3b, 0x00c0, 0xa1d8, 0x1078, 0x7a05,
-	0x1078, 0x8c01, 0xace0, 0x0010, 0x2001, 0xa315, 0x2004, 0xac02,
-	0x00c8, 0xa1e4, 0x0078, 0xa1a3, 0x127f, 0x017f, 0x027f, 0x047f,
-	0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x007e,
-	0x0e7e, 0x2091, 0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa1fb,
-	0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa201, 0x7030, 0x8000,
-	0x7032, 0xd5ac, 0x0040, 0xa208, 0x2071, 0xa34a, 0x1078, 0xa237,
-	0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
-	0x8000, 0x2071, 0xa340, 0xd5a4, 0x0040, 0xa219, 0x7034, 0x8000,
-	0x7036, 0xd5b4, 0x0040, 0xa21f, 0x7030, 0x8000, 0x7032, 0xd5ac,
-	0x0040, 0xa226, 0x2071, 0xa34a, 0x1078, 0xa237, 0x0e7f, 0x007f,
-	0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
-	0xa342, 0x1078, 0xa237, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04,
-	0x8000, 0x2072, 0x00c8, 0xa240, 0x8e70, 0x2e04, 0x8000, 0x2072,
-	0x007c, 0x0e7e, 0x2071, 0xa340, 0x1078, 0xa237, 0x0e7f, 0x007c,
-	0x0e7e, 0x2071, 0xa344, 0x1078, 0xa237, 0x0e7f, 0x007c, 0x0001,
-	0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
-	0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x6286
-};
-
-/************************************************************************
- *									*
- *               --- ISP2200 Initiator/Target Firmware ---              *
- *             with Fabric (Public Loop), Point-point, and              *
- *             expanded LUN addressing for FCTAPE                       *
- *									*
- ************************************************************************
-  Copyright (C) 2000 and 2100 Qlogic Corporation 
-  (www.qlogic.com)
-
-  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.
-************************************************************************/
-
-/*
- *	Firmware Version 2.01.27 (11:07 Dec 18, 2000)
- */
-
-static unsigned short risc_code_length2200 = 0x9cbf;
-static unsigned short risc_code2200[] = { 
-	0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b,
-	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
-	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x322e, 0x3031, 0x2e32, 0x3720, 0x2020, 0x2020, 0x2400, 0x20c1,
-	0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xb1ff, 0x2091,
-	0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x27b5,
-	0x2051, 0xad00, 0x2a70, 0x2029, 0xe400, 0x2031, 0xffff, 0x2039,
-	0xe3e9, 0x2021, 0x0200, 0x0804, 0x1449, 0x20a1, 0xacbf, 0xa00e,
-	0x20a9, 0x0741, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
-	0x746a, 0x20a1, 0xb400, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
-	0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4,
-	0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218,
-	0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xad00,
-	0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
-	0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
-	0x2009, 0xad00, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
-	0x41a4, 0x080c, 0x13fc, 0x080c, 0x1613, 0x080c, 0x17ac, 0x080c,
-	0x1e67, 0x080c, 0x492e, 0x080c, 0x801a, 0x080c, 0x159c, 0x080c,
-	0x2ce6, 0x080c, 0x5a01, 0x080c, 0x5045, 0x080c, 0x6487, 0x080c,
-	0x236a, 0x080c, 0x6686, 0x080c, 0x5fae, 0x080c, 0x226b, 0x080c,
-	0x2338, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820,
-	0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b,
-	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
-	0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3c98, 0x080c,
-	0x2d0d, 0x080c, 0x5a4f, 0x080c, 0x51f4, 0x080c, 0x64a2, 0x0c80,
-	0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1203, 0x10e2, 0x12cc, 0x13f9,
-	0x13fa, 0x13fb, 0x080c, 0x14f6, 0x0005, 0x0126, 0x00f6, 0x2091,
-	0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11d1, 0x080c, 0x1569,
-	0x080c, 0x574f, 0x0150, 0x080c, 0x5775, 0x1580, 0x2079, 0x0100,
-	0x7828, 0xa085, 0x1800, 0x782a, 0x0448, 0x080c, 0x569a, 0x7000,
-	0xa086, 0x0001, 0x1904, 0x11d1, 0x7088, 0xa086, 0x0028, 0x1904,
-	0x11d1, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0xa295, 0x1e2f,
-	0x7a2a, 0x2011, 0x566e, 0x080c, 0x650d, 0x2011, 0x567b, 0x080c,
-	0x650d, 0x2011, 0x481b, 0x080c, 0x650d, 0x2011, 0x8030, 0x2019,
-	0x0000, 0x7087, 0x0000, 0x080c, 0x1d0f, 0x00e8, 0x080c, 0x41d1,
-	0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11d1, 0x2011, 0x481b,
-	0x080c, 0x650d, 0x2011, 0x567b, 0x080c, 0x650d, 0x080c, 0x1d0f,
-	0x2001, 0xaf8c, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842,
-	0x2011, 0x8010, 0x73c8, 0x080c, 0x3c5c, 0x7238, 0xc284, 0x723a,
-	0x2001, 0xad0c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x79bd, 0x2011,
-	0x0004, 0x080c, 0x959c, 0x080c, 0x4f71, 0x080c, 0x574f, 0x0158,
-	0x080c, 0x4917, 0x0140, 0x7087, 0x0001, 0x70c3, 0x0000, 0x080c,
-	0x436e, 0x0804, 0x11d1, 0x080c, 0x502d, 0x0120, 0x7a0c, 0xc2b4,
-	0x7a0e, 0x0050, 0x080c, 0x9937, 0x70d0, 0xd09c, 0x1128, 0x709c,
-	0xa005, 0x0110, 0x080c, 0x48f5, 0x70db, 0x0000, 0x70d7, 0x0000,
-	0x72d0, 0x080c, 0x574f, 0x1178, 0x2011, 0x0000, 0x0016, 0x080c,
-	0x2744, 0x2019, 0xaf8e, 0x211a, 0x001e, 0x704f, 0xffff, 0x7053,
-	0x00ef, 0x7073, 0x0000, 0x2079, 0xad51, 0x7804, 0xd0ac, 0x0108,
-	0xc295, 0x72d2, 0x080c, 0x574f, 0x0118, 0xa296, 0x0004, 0x0508,
-	0x2011, 0x0001, 0x080c, 0x959c, 0x7097, 0x0000, 0x709b, 0xffff,
-	0x7003, 0x0002, 0x00fe, 0x080c, 0x28fa, 0x2011, 0x0005, 0x080c,
-	0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148, 0x00c6, 0x2061,
-	0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e, 0x00ce, 0x012e,
-	0x00d0, 0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011,
-	0x0005, 0x080c, 0x7adf, 0x080c, 0x6c50, 0x080c, 0x574f, 0x0148,
-	0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2744, 0x61e2, 0x001e,
-	0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1118,
-	0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x574f, 0x1118,
-	0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x0016, 0x0026, 0x0036,
-	0x2110, 0x0026, 0x2019, 0x0029, 0x080c, 0x7cf4, 0x002e, 0x080c,
-	0xac07, 0x003e, 0x002e, 0x001e, 0x080c, 0x2bc9, 0x8108, 0x1f04,
-	0x11e5, 0x00ce, 0x706f, 0x0000, 0x7070, 0xa084, 0x00ff, 0x7072,
-	0x709f, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x7000, 0xa086,
-	0x0002, 0x1904, 0x12ca, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c,
-	0x28fa, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d0, 0xd0ac, 0x1110,
-	0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016, 0x2001, 0x0103,
-	0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e, 0xd08c, 0x01d0,
-	0x70d4, 0xa086, 0xffff, 0x0190, 0x080c, 0x2a56, 0x080c, 0x6c50,
-	0x70d0, 0xd094, 0x1904, 0x12ca, 0x2011, 0x0001, 0x2019, 0x0000,
-	0x080c, 0x2a8c, 0x080c, 0x6c50, 0x0804, 0x12ca, 0x70d8, 0xa005,
-	0x1904, 0x12ca, 0x7094, 0xa005, 0x1904, 0x12ca, 0x70d0, 0xd0a4,
-	0x0118, 0xd0b4, 0x0904, 0x12ca, 0x080c, 0x502d, 0x1904, 0x12ca,
-	0x2001, 0xad52, 0x2004, 0xd0ac, 0x01c8, 0x0156, 0x00c6, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1118, 0x6000,
-	0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x125b, 0x00ce, 0x015e,
-	0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12ca, 0x0006, 0x0016,
-	0x2001, 0x0103, 0x2009, 0xaf8c, 0x210c, 0x2102, 0x001e, 0x000e,
-	0xa006, 0x2009, 0x0700, 0x20a9, 0x0002, 0x20a1, 0xafb5, 0x40a1,
-	0x706c, 0x8007, 0x7170, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x2009,
-	0x0000, 0x080c, 0x14dc, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002,
-	0x40a1, 0xa006, 0x2009, 0x0200, 0x20a9, 0x0002, 0x20a1, 0xafc5,
-	0x40a1, 0x7030, 0xc08c, 0x7032, 0x7003, 0x0003, 0x709b, 0xffff,
-	0x080c, 0x1562, 0xa006, 0x080c, 0x261e, 0x080c, 0x3cce, 0x00f6,
-	0x2079, 0x0100, 0x080c, 0x5775, 0x0150, 0x080c, 0x574f, 0x7828,
-	0x0118, 0xa084, 0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe,
-	0x2001, 0xafc8, 0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000,
-	0x080c, 0x7adf, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c, 0x6c50,
-	0x080c, 0x6d0d, 0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126,
-	0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0xad33, 0x2104, 0xa005,
-	0x1110, 0x080c, 0x2770, 0x2009, 0x00f7, 0x080c, 0x48de, 0x7940,
-	0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040,
-	0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954,
-	0xd1ac, 0x1904, 0x133a, 0x080c, 0x5761, 0x0158, 0x080c, 0x5775,
-	0x1128, 0x2001, 0xaf9d, 0x2003, 0x0000, 0x0070, 0x080c, 0x5757,
-	0x0dc0, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
-	0x0001, 0x080c, 0x569a, 0x0058, 0x080c, 0x574f, 0x0140, 0x2009,
-	0x00f8, 0x080c, 0x48de, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
-	0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c, 0x574f, 0x0138, 0x7824,
-	0xd0ac, 0x1904, 0x13e0, 0x1f04, 0x1319, 0x0070, 0x7824, 0x080c,
-	0x576b, 0x0118, 0xd0ac, 0x1904, 0x13e0, 0xa084, 0x1800, 0x0d98,
-	0x7003, 0x0001, 0x0804, 0x13e0, 0x2001, 0x0001, 0x080c, 0x261e,
-	0x0804, 0x13ef, 0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020,
-	0x20a9, 0x0046, 0x1d04, 0x1342, 0x2091, 0x6000, 0x1f04, 0x1342,
-	0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000,
-	0x080c, 0x5761, 0x0158, 0x080c, 0x5775, 0x1128, 0x2001, 0xaf9d,
-	0x2003, 0x0000, 0x0070, 0x080c, 0x5757, 0x0dc0, 0x2001, 0xaf9d,
-	0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x080c, 0x569a,
-	0x0020, 0x2009, 0x00f8, 0x080c, 0x48de, 0x20a9, 0x000e, 0xe000,
-	0x1f04, 0x136f, 0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852,
-	0x080c, 0x574f, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021,
-	0xe678, 0x2019, 0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x574f,
-	0x05b8, 0x7824, 0xd0ac, 0x1904, 0x13e0, 0x080c, 0x5775, 0x1508,
-	0x0046, 0x2021, 0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8,
-	0x7827, 0x0048, 0x20a9, 0x01f4, 0x1d04, 0x139c, 0x2091, 0x6000,
-	0x1f04, 0x139c, 0x7824, 0xa084, 0x0068, 0x15a8, 0x2001, 0xaf9d,
-	0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x7003, 0x0001,
-	0x0478, 0x8319, 0x1980, 0x2009, 0xad33, 0x2104, 0x8000, 0x200a,
-	0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c, 0x2770, 0x00d8,
-	0x080c, 0x5761, 0x1140, 0xa4a2, 0x0064, 0x1128, 0x080c, 0x5726,
-	0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000, 0xe000, 0x7824,
-	0x080c, 0x576b, 0x0110, 0xd0ac, 0x1158, 0xa084, 0x1800, 0x09c8,
-	0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c, 0x261e, 0x0048,
-	0x2001, 0xad33, 0x2003, 0x0000, 0x7827, 0x0048, 0x7828, 0xc09d,
-	0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852, 0x015e,
-	0x003e, 0x000e, 0x080c, 0x1539, 0x012e, 0x00fe, 0x004e, 0x001e,
-	0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2001, 0xaf9d, 0x2003,
-	0x0000, 0x7087, 0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002,
-	0x0218, 0x704f, 0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff,
-	0x706f, 0x0000, 0x7073, 0x0000, 0x080c, 0x9937, 0x2061, 0xaf8d,
-	0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200,
-	0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0,
-	0x2061, 0xaf95, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000,
-	0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001,
-	0x601f, 0x0000, 0x2061, 0xafa6, 0x6003, 0x514c, 0x6007, 0x4f47,
-	0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xad27, 0x2003, 0x0000,
-	0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570, 0xa186, 0x0001,
-	0x1148, 0x2031, 0x8fff, 0x2039, 0xcc01, 0x2021, 0x0100, 0x2029,
-	0xcc00, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011, 0x0000, 0x00b8,
-	0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088, 0xa186, 0x0009,
-	0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a, 0x1118, 0x2011,
-	0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011, 0x0003, 0x3800,
-	0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d, 0xa00e, 0x2011,
-	0x0003, 0x2019, 0x1485, 0x0804, 0x14d6, 0x2019, 0xaaaa, 0x2061,
-	0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0xa306, 0x2262,
-	0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019, 0x1498, 0x04f0,
-	0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000,
-	0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04, 0x2061, 0xffff,
-	0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185, 0x2011, 0x0002,
-	0x2019, 0x14b3, 0x0418, 0x2061, 0xffff, 0x2019, 0xaaaa, 0x2c14,
-	0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306, 0x1180, 0x2c14,
-	0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0x2c04, 0x2061,
-	0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008, 0xc19d, 0x2011,
-	0x0001, 0x2019, 0x14d4, 0x0010, 0x0804, 0x144a, 0x3800, 0xa084,
-	0xfffc, 0xa205, 0x20c0, 0x0837, 0x2011, 0x0000, 0x080c, 0x4cdc,
-	0x1178, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0128, 0xa0c4,
-	0xff00, 0xa8c6, 0x0600, 0x1120, 0xa186, 0x0080, 0x0108, 0x8210,
-	0x8108, 0xa186, 0x0100, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000,
-	0x0e04, 0x14f8, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084,
-	0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900,
-	0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0126,
-	0x0156, 0x0146, 0x20a9, 0x0010, 0x20a1, 0xb0c8, 0x2091, 0x2000,
-	0x40a1, 0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010,
-	0x2091, 0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1,
-	0x20a9, 0x0010, 0x2091, 0x2800, 0x40a1, 0x014e, 0x015e, 0x012e,
-	0x2079, 0xad00, 0x7803, 0x0005, 0x2091, 0x4080, 0x04c9, 0x0cf8,
-	0x0005, 0x0006, 0x080c, 0x1584, 0x1518, 0x00f6, 0x2079, 0xad23,
-	0x2f04, 0x8000, 0x207a, 0xa082, 0x000f, 0x0258, 0xa006, 0x207a,
-	0x2079, 0xad25, 0x2f04, 0xa084, 0x0001, 0xa086, 0x0001, 0x207a,
-	0x0070, 0x2079, 0xad25, 0x2f7c, 0x8fff, 0x1128, 0x2001, 0x0c03,
-	0x2003, 0x0040, 0x0020, 0x2001, 0x0c03, 0x2003, 0x00c0, 0x00fe,
-	0x000e, 0x0005, 0x0409, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0080,
-	0x0005, 0x00d1, 0x1120, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0005,
-	0x0006, 0x0091, 0x1178, 0x2001, 0x0c03, 0x2003, 0x0040, 0x2009,
-	0x0fff, 0x00a1, 0x2001, 0x0c03, 0x2003, 0x0080, 0x2009, 0x0fff,
-	0x0069, 0x0c88, 0x000e, 0x0005, 0x00c6, 0x2061, 0x0c00, 0x2c04,
-	0xa084, 0x00ff, 0xa086, 0x00aa, 0x00ce, 0x0005, 0x0156, 0x0126,
-	0xa18c, 0x0fff, 0x21a8, 0x1d04, 0x1593, 0x2091, 0x6000, 0x1f04,
-	0x1593, 0x012e, 0x015e, 0x0005, 0x2071, 0xad00, 0x715c, 0x712e,
-	0x2021, 0x0001, 0xa190, 0x0030, 0xa298, 0x0030, 0x0240, 0x7060,
-	0xa302, 0x1228, 0x220a, 0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800,
-	0xd08c, 0x0148, 0x7060, 0xa086, 0xad00, 0x0128, 0x7063, 0xad00,
-	0x2011, 0x1000, 0x0c48, 0x200b, 0x0000, 0x74ae, 0x74b2, 0x0005,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x70b0, 0xa0ea,
-	0x0010, 0x0268, 0x8001, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e,
-	0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e,
-	0x0cd8, 0x00e6, 0x2071, 0xad00, 0x0126, 0x2091, 0x8000, 0x70b0,
-	0x8001, 0x0260, 0x70b2, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b,
-	0x0000, 0x6807, 0x0000, 0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00, 0x702c, 0x206a,
-	0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x012e, 0x00ee, 0x0005,
-	0x8dff, 0x0138, 0x6804, 0x6807, 0x0000, 0x0006, 0x0c49, 0x00de,
-	0x0cb8, 0x0005, 0x00e6, 0x2071, 0xad00, 0x70b0, 0xa08a, 0x0010,
-	0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7007, 0x0000,
-	0x701b, 0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085,
-	0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6, 0x2270, 0x700b, 0x0000,
-	0x2071, 0xafec, 0x7018, 0xa088, 0xaff5, 0x220a, 0x8000, 0xa084,
-	0x0007, 0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010,
-	0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xafec, 0x7004,
-	0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee,
-	0x0005, 0x7000, 0x0002, 0x164f, 0x16b3, 0x16d0, 0x16d0, 0x7018,
-	0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180,
-	0xaff5, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e,
-	0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a,
-	0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de,
-	0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002,
-	0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182,
-	0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822,
-	0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016,
-	0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014,
-	0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210,
-	0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
-	0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e,
-	0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xadf9,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
-	0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
-	0x7002, 0x700b, 0xadf4, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
-	0x0136, 0x0146, 0x0156, 0x2001, 0xae28, 0x209c, 0x20a1, 0x0014,
-	0x7803, 0x0026, 0x2001, 0xae29, 0x20ac, 0x53a6, 0x2099, 0xae2a,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
-	0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
-	0x7002, 0x700b, 0xae25, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
-	0x0016, 0x00e6, 0x2071, 0xafec, 0x00f6, 0x2079, 0x0010, 0x7904,
-	0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023,
-	0x00fe, 0x00ee, 0x001e, 0x0005, 0x1649, 0x1713, 0x1741, 0x176b,
-	0x179b, 0x1712, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146,
-	0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010,
-	0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c,
-	0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x167a,
-	0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000,
-	0x080c, 0x1649, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
-	0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830,
-	0x7832, 0x7834, 0x7836, 0x080c, 0x168f, 0x0005, 0x7008, 0xa080,
-	0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005,
-	0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
-	0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000,
-	0x080c, 0x1649, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146,
-	0x0156, 0x2001, 0xadf7, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099,
-	0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xadf9,
-	0x2004, 0xd0bc, 0x0148, 0x2001, 0xae02, 0x2004, 0xa080, 0x000d,
-	0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007,
-	0x0000, 0x080c, 0x5ae6, 0x080c, 0x1649, 0x0005, 0x2011, 0x8003,
-	0x080c, 0x3c5c, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xae27,
-	0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1649, 0x0005, 0x2011,
-	0x8004, 0x080c, 0x3c5c, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079,
-	0x0030, 0x2071, 0xaffd, 0x7003, 0x0000, 0x700f, 0xb003, 0x7013,
-	0xb003, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934,
-	0xa184, 0x0007, 0x0002, 0x17cb, 0x1809, 0x17cb, 0x17cb, 0x17cb,
-	0x17f1, 0x17d8, 0x17cf, 0xa085, 0x0001, 0x0804, 0x1823, 0x684c,
-	0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8,
-	0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58,
-	0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832, 0x6858,
-	0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac,
-	0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
-	0xa080, 0x2186, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858,
-	0x0080, 0x684c, 0xd0ac, 0x0904, 0x17cb, 0xa006, 0x682e, 0x682a,
-	0x6858, 0xa18c, 0x000f, 0xa188, 0x2186, 0x210d, 0x6932, 0x2d08,
-	0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
-	0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000,
-	0x2001, 0x020a, 0x2004, 0x82ff, 0x01a8, 0xa280, 0x0004, 0x00d6,
-	0x206c, 0x684c, 0xd0dc, 0x1150, 0x080c, 0x17bf, 0x0138, 0x00de,
-	0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000,
-	0x680a, 0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200,
-	0x002e, 0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a,
-	0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb01e, 0x0210,
-	0x2009, 0xb003, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118,
-	0xa080, 0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005,
-	0x7206, 0x2001, 0x1866, 0x0006, 0x2260, 0x0804, 0x197a, 0x0126,
-	0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e,
-	0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62,
-	0x6b5e, 0xa005, 0x0904, 0x18c8, 0x6808, 0xa005, 0x0904, 0x18ff,
-	0x7000, 0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904,
-	0x1907, 0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c,
-	0x0168, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010, 0xa080,
-	0x0002, 0x2004, 0xa005, 0x0904, 0x18ff, 0x0c10, 0x2001, 0x0207,
-	0x2004, 0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086,
-	0x6000, 0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004,
-	0x1904, 0x1907, 0x2009, 0x0048, 0x080c, 0x80a7, 0x0804, 0x1907,
-	0x6808, 0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110,
-	0xa106, 0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004,
-	0xd08c, 0x0160, 0x0046, 0x080c, 0x1a6c, 0x004e, 0x2460, 0x6010,
-	0xa080, 0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207,
-	0x2004, 0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50,
-	0x7804, 0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818,
-	0x6812, 0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100,
-	0xa18e, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x80a7, 0x00ce,
-	0x00de, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046,
-	0x0056, 0x080c, 0x1d86, 0x0026, 0x0056, 0x2071, 0xaffd, 0x7000,
-	0xa086, 0x0000, 0x0580, 0x7004, 0xac06, 0x11f8, 0x2079, 0x0030,
-	0x7000, 0xa086, 0x0003, 0x01c8, 0x7804, 0xd0fc, 0x1198, 0x2001,
-	0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803, 0x0004, 0x7804, 0xd0ac,
-	0x1de8, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007,
-	0x0000, 0x0018, 0x080c, 0x1a6c, 0x08d0, 0x0156, 0x20a9, 0x0009,
-	0x2009, 0xb003, 0x2104, 0xac06, 0x1108, 0x200a, 0xa188, 0x0003,
-	0x1f04, 0x1942, 0x015e, 0x005e, 0x002e, 0x2001, 0x015d, 0x201c,
-	0x831a, 0x2302, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202,
-	0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c,
-	0x7110, 0xa106, 0x0904, 0x19dd, 0x2104, 0x7006, 0x2060, 0x8108,
-	0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb01e, 0x0210, 0x2009,
-	0xb003, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2744, 0x2001,
-	0x0138, 0x2102, 0x8cff, 0x0588, 0x6010, 0x2068, 0x2d58, 0x6828,
-	0xa406, 0x1580, 0x682c, 0xa306, 0x1568, 0x7004, 0x2060, 0x6020,
-	0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813,
-	0xffff, 0x00d8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810,
-	0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
-	0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x04c9, 0x0118,
-	0x2009, 0x0001, 0x04a9, 0x2d58, 0x0005, 0x080c, 0x1ced, 0x0904,
-	0x195f, 0x0cd0, 0x6020, 0xd0d4, 0x01b8, 0x6038, 0xa402, 0x6034,
-	0xa303, 0x0108, 0x1288, 0x643a, 0x6336, 0x6c2a, 0x6b2e, 0x0046,
-	0x0036, 0x2400, 0x6c7c, 0xa402, 0x6812, 0x2300, 0x6b80, 0xa303,
-	0x6816, 0x003e, 0x004e, 0x0018, 0x080c, 0x98cb, 0x09f0, 0x601c,
-	0xa08e, 0x0008, 0x0904, 0x1985, 0xa08e, 0x000a, 0x0904, 0x1985,
-	0x080c, 0x21a6, 0x1990, 0x0804, 0x1985, 0x7003, 0x0000, 0x0005,
-	0x8aff, 0x0904, 0x1a46, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8,
-	0xd0f4, 0x1528, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1a30,
-	0x1a15, 0x1a15, 0x1a30, 0x1a30, 0x1a29, 0x1a30, 0x1a15, 0x1a30,
-	0x1a1a, 0x1a1a, 0x1a30, 0x1a30, 0x1a30, 0x1a21, 0x1a1a, 0x7803,
-	0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6,
-	0xd99c, 0x0548, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0420, 0xc0f4,
-	0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0428, 0x6b08, 0x6a0c, 0x6d00,
-	0x6c04, 0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c,
-	0x0090, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
-	0x1138, 0x00de, 0x080c, 0x2148, 0x1904, 0x19e0, 0xa00e, 0x00b0,
-	0x00de, 0x080c, 0x14f6, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
-	0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300,
-	0x682a, 0x682c, 0xa201, 0x682e, 0x080c, 0x2148, 0x0005, 0x080c,
-	0x14f6, 0x080c, 0x1e1a, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068,
-	0x7003, 0x0000, 0x080c, 0x1d22, 0x080c, 0x9596, 0x0170, 0x6808,
-	0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff,
-	0x682f, 0xffff, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c,
-	0x0804, 0x1c5e, 0x080c, 0x14f6, 0x0126, 0x2091, 0x2200, 0x0006,
-	0x0016, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
-	0x0700, 0x1978, 0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000,
-	0x0002, 0x1a89, 0x1a8f, 0x1b92, 0x1c39, 0x1c4d, 0x1a89, 0x1a89,
-	0x1a89, 0x7804, 0xd09c, 0x1904, 0x1c5e, 0x080c, 0x14f6, 0x8001,
-	0x7002, 0xa184, 0x0880, 0x1190, 0xd19c, 0x1904, 0x1b20, 0x8aff,
-	0x0904, 0x1b20, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0904, 0x1c5e,
-	0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7803, 0x0004,
-	0x7003, 0x0000, 0xd1bc, 0x1904, 0x1b00, 0x0026, 0x0036, 0x7c20,
-	0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001,
-	0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803,
-	0x0009, 0x7003, 0x0004, 0x0010, 0x080c, 0x1c62, 0x6b28, 0x6a2c,
-	0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e,
-	0x00c6, 0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236,
-	0x00ce, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x215e, 0x2a00,
-	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
-	0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004,
-	0x2060, 0x2009, 0x0048, 0x080c, 0x80a7, 0x7000, 0xa086, 0x0004,
-	0x0904, 0x1c5e, 0x7003, 0x0000, 0x080c, 0x195f, 0x0804, 0x1c5e,
-	0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xac73, 0x005e, 0x080c,
-	0x1d22, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5029, 0x0118, 0x7820,
-	0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f, 0xffff, 0x6808,
-	0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804, 0x1c5e,
-	0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4, 0x0128, 0x6808,
-	0x8001, 0x680a, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x7a1c, 0x6a16,
-	0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007, 0x2004,
-	0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1aa6, 0x684c, 0xc0f5,
-	0x684e, 0x7814, 0xa005, 0x1180, 0x7003, 0x0000, 0x6808, 0x8001,
-	0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x80a7,
-	0x080c, 0x195f, 0x0804, 0x1c5e, 0x7818, 0x6812, 0x781c, 0x6816,
-	0x7814, 0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214,
-	0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b,
-	0x810b, 0x080c, 0x1da5, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803,
-	0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803, 0x0004,
-	0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
-	0x080c, 0x80a7, 0x080c, 0x1dd7, 0x0958, 0x7908, 0xd1ec, 0x1118,
-	0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902, 0x7003, 0x0003,
-	0x0804, 0x1c5e, 0x8001, 0x7002, 0xd194, 0x01a8, 0x7804, 0xd0fc,
-	0x1904, 0x1c2c, 0xd09c, 0x0130, 0x7804, 0xd0fc, 0x1904, 0x1a74,
-	0xd09c, 0x11a8, 0x8aff, 0x0904, 0x1c5e, 0x2009, 0x0001, 0x080c,
-	0x19e0, 0x0804, 0x1c5e, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904,
-	0x1c5e, 0x2009, 0x0001, 0x080c, 0x19e0, 0x0804, 0x1c5e, 0x7818,
-	0x6812, 0x7a1c, 0x6a16, 0xa205, 0x0904, 0x1b3e, 0x7803, 0x0004,
-	0x7003, 0x0000, 0xd1bc, 0x1904, 0x1c0f, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x0029, 0x1118, 0xd19c, 0x1904, 0x1b3e, 0x0026, 0x0036,
-	0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816,
-	0x2001, 0x0201, 0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128,
-	0x7803, 0x0009, 0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1c62,
-	0x001e, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6, 0x2805, 0xac68,
-	0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020,
-	0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x1ac8,
-	0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001,
-	0x680a, 0x6b2a, 0x6a2e, 0x003e, 0x002e, 0x0804, 0x1b50, 0x0056,
-	0x7d0c, 0x080c, 0xac73, 0x005e, 0x080c, 0x1d22, 0x00f6, 0x7004,
-	0x2078, 0x080c, 0x5029, 0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe,
-	0x682b, 0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c,
-	0x791a, 0x6980, 0x791e, 0x0490, 0x7804, 0xd09c, 0x0904, 0x1a74,
-	0x7c20, 0x7824, 0xa405, 0x1904, 0x1a74, 0x7803, 0x0002, 0x0804,
-	0x1bb7, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0150,
-	0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009, 0x0048,
-	0x080c, 0x80a7, 0x080c, 0x195f, 0x0088, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068, 0x6808,
-	0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x197a, 0x001e, 0x000e,
-	0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ce1, 0x7004,
-	0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ce1, 0x00d6, 0x00c6,
-	0x216c, 0x2d00, 0xa005, 0x0904, 0x1cdf, 0x6820, 0xd0d4, 0x1904,
-	0x1cdf, 0x6810, 0x2068, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104,
-	0x6b2c, 0xa306, 0x1904, 0x1cdf, 0x8108, 0x2104, 0x6a28, 0xa206,
-	0x1904, 0x1cdf, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822,
-	0x6870, 0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060,
-	0x6034, 0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808,
-	0x783a, 0x680c, 0x783e, 0x00de, 0x04a0, 0xa006, 0x783a, 0x783e,
-	0x0480, 0x8108, 0x2104, 0xa005, 0x1590, 0x8108, 0x2104, 0xa005,
-	0x1570, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160,
-	0xa180, 0x000d, 0x2004, 0xd09c, 0x1170, 0x6008, 0x7822, 0x686e,
-	0x600c, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0xa006,
-	0x783a, 0x783e, 0x0070, 0x6010, 0x7822, 0x686e, 0x6014, 0x7826,
-	0x6872, 0x6000, 0x7832, 0x6004, 0x7836, 0x6008, 0x783a, 0x600c,
-	0x783e, 0x6810, 0x781a, 0x6814, 0x781e, 0x7803, 0x0011, 0x00ce,
-	0x00de, 0x0005, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005,
-	0x1118, 0x8109, 0x1dd8, 0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908,
-	0xd1ec, 0x1160, 0x080c, 0x1dd7, 0x0148, 0x7803, 0x0009, 0x7904,
-	0xd1fc, 0x0de8, 0x7803, 0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4,
-	0x1150, 0x7007, 0x0000, 0x080c, 0x1dd7, 0x0140, 0x7803, 0x0019,
-	0x7003, 0x0003, 0x0018, 0x00b1, 0xa085, 0x0001, 0x0005, 0x0126,
-	0x2091, 0x2200, 0x7000, 0xa086, 0x0003, 0x1150, 0x700c, 0x7110,
-	0xa106, 0x0130, 0x20e1, 0x9028, 0x700f, 0xb003, 0x7013, 0xb003,
-	0x012e, 0x0005, 0x00c6, 0x080c, 0x574f, 0x1550, 0x2001, 0x0160,
-	0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8,
-	0xe000, 0xe000, 0x8211, 0x1de0, 0x080c, 0x1d7e, 0x700c, 0x7110,
-	0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060,
-	0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0xb01e, 0x0210,
-	0x2009, 0xb003, 0x7112, 0x0c50, 0x080c, 0x57d1, 0x00ce, 0x0005,
-	0x04a9, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01d0, 0x2104,
-	0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
-	0xa188, 0x0003, 0xa182, 0xb01e, 0x0210, 0x2009, 0xb003, 0x7112,
-	0x700c, 0xa106, 0x1d40, 0x080c, 0x2744, 0x2001, 0x0138, 0x2102,
-	0x0c10, 0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x2001, 0x0160,
-	0x2502, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x20e1, 0x9028,
-	0x2001, 0x015d, 0x200c, 0x810a, 0x2102, 0x0005, 0x2001, 0x0138,
-	0x2014, 0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000,
-	0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
-	0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c,
-	0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200,
-	0x7808, 0xa084, 0xf000, 0xa10d, 0x08c9, 0x2019, 0x5000, 0x8319,
-	0x0168, 0x2001, 0xb01e, 0x2004, 0xa086, 0x0000, 0x0138, 0x2001,
-	0x0021, 0xd0fc, 0x0da0, 0x080c, 0x1ff4, 0x0c78, 0x20e1, 0x7000,
-	0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
-	0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
-	0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x00ee, 0x0005, 0x7908,
-	0xa18c, 0x0fff, 0xa182, 0x0009, 0x0218, 0xa085, 0x0001, 0x0088,
-	0x2001, 0x020a, 0x81ff, 0x0130, 0x20e1, 0x6000, 0x200c, 0x200c,
-	0x200c, 0x200c, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003, 0x0000,
-	0xa006, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xaffd,
-	0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8,
-	0x8211, 0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904,
-	0xa18c, 0x0780, 0x0016, 0x080c, 0x1a6c, 0x001e, 0x81ff, 0x1118,
-	0x2011, 0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee,
-	0x00fe, 0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac,
-	0x0904, 0x1e66, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a,
-	0x0003, 0x0a0c, 0x14f6, 0x080c, 0x20f2, 0x00e6, 0x00f6, 0x2071,
-	0xafec, 0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800,
-	0x0006, 0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838,
-	0x0006, 0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079,
-	0x0030, 0x7804, 0xd0ac, 0x190c, 0x14f6, 0x2079, 0x0010, 0x000e,
-	0x783e, 0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e,
-	0x7822, 0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee,
-	0x7804, 0xd0ac, 0x190c, 0x14f6, 0x080c, 0x6d0d, 0x0005, 0x00e6,
-	0x2071, 0xb01e, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280,
-	0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1ee4, 0x6934, 0xa184,
-	0x0007, 0x0002, 0x1e82, 0x1ecf, 0x1e82, 0x1e82, 0x1e82, 0x1eb6,
-	0x1e95, 0x1e84, 0x080c, 0x14f6, 0x684c, 0xd0b4, 0x0904, 0x1fcc,
-	0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a,
-	0x6880, 0x680e, 0x6958, 0x0804, 0x1ed7, 0x6834, 0xa084, 0x00ff,
-	0xa086, 0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6860,
-	0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880,
-	0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
-	0xa080, 0x2186, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff,
-	0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1fcc, 0x6804,
-	0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2186,
-	0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c,
-	0xd0b4, 0x0904, 0x1a47, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00,
-	0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x2186, 0x2005, 0x6832,
-	0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079,
-	0x0020, 0x7804, 0xd0fc, 0x190c, 0x1ff4, 0x00e6, 0x00d6, 0x2071,
-	0xb01e, 0x7000, 0xa005, 0x1904, 0x1f4c, 0x00c6, 0x7206, 0xa280,
-	0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6,
-	0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079,
-	0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de,
-	0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034,
-	0xa0cc, 0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a,
-	0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120,
-	0x6928, 0x6810, 0xa106, 0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10,
-	0x080c, 0x21a6, 0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff,
-	0x1120, 0x00ce, 0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000,
-	0x2079, 0x0020, 0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001,
-	0x0039, 0x012e, 0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x0076, 0x0066, 0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904,
-	0x1fc5, 0x700c, 0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04,
-	0x1fc4, 0xa705, 0x0904, 0x1fc4, 0xa03e, 0x2730, 0x6850, 0xd0fc,
-	0x11a8, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x1fa7, 0x1f8c,
-	0x1f8c, 0x1fa7, 0x1fa7, 0x1fa0, 0x1fa7, 0x1f8c, 0x1fa7, 0x1f91,
-	0x1f91, 0x1fa7, 0x1fa7, 0x1fa7, 0x1f98, 0x1f91, 0xc0fc, 0x6852,
-	0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805,
-	0xac68, 0x6f08, 0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04,
-	0x00c8, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090,
-	0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138,
-	0x00de, 0x080c, 0x2148, 0x1904, 0x1f56, 0xa00e, 0x00f0, 0x00de,
-	0x080c, 0x14f6, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a,
-	0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a,
-	0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201,
-	0x7012, 0x080c, 0x2148, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e,
-	0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x14f6, 0x0026, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596,
-	0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x929c, 0x20e1,
-	0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x080c,
-	0x6d0d, 0x002e, 0x0804, 0x20ad, 0x0126, 0x2091, 0x2400, 0x0006,
-	0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071,
-	0xb01e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184,
-	0x0700, 0x1920, 0x7000, 0x0002, 0x20ad, 0x2010, 0x2080, 0x20ab,
-	0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0, 0x2009, 0x0001,
-	0x080c, 0x1f50, 0x0904, 0x20ad, 0x2009, 0x0001, 0x080c, 0x1f50,
-	0x0804, 0x20ad, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc,
-	0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e, 0x00b8, 0x0026,
-	0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a, 0x7824, 0x6872,
-	0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a, 0x6a2e, 0x003e,
-	0x002e, 0x080c, 0x215e, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826,
-	0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0804, 0x20ad,
-	0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006, 0x2079, 0x0100,
-	0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816, 0x0036, 0x2019,
-	0x1000, 0x8319, 0x090c, 0x14f6, 0x7820, 0xd0bc, 0x1dd0, 0x003e,
-	0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016, 0x79c4, 0x000e,
-	0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184, 0xa085, 0x0012,
-	0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003, 0x0000, 0x0468,
-	0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc, 0x1904, 0x2004,
-	0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001, 0x080c, 0x1f50,
-	0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c, 0x215e, 0x00d6,
-	0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808, 0xa31a, 0x680c,
-	0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213, 0x00de, 0x0804,
-	0x2033, 0x0804, 0x202f, 0x080c, 0x14f6, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x2071,
-	0xb01e, 0x7000, 0xa086, 0x0000, 0x0590, 0x2079, 0x0020, 0x0016,
-	0x2009, 0x0207, 0x210c, 0xd194, 0x0158, 0x2009, 0x020c, 0x210c,
-	0xa184, 0x0003, 0x0128, 0x20e1, 0x9040, 0x2001, 0x020c, 0x2102,
-	0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0xa106, 0x1110,
-	0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0d18, 0x080c, 0x1ff4, 0x7000,
-	0xa086, 0x0000, 0x19e8, 0x001e, 0x7803, 0x0004, 0x7804, 0xd0ac,
-	0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x00ee,
-	0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2071,
-	0xb01e, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0540, 0x7004,
-	0x2060, 0x6010, 0x2068, 0x080c, 0x9596, 0x0158, 0x6850, 0xc0b5,
-	0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808, 0x7a18, 0xa206,
-	0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c, 0x929c, 0x20e1,
-	0x9040, 0x080c, 0x7cb8, 0x2011, 0x0000, 0x080c, 0x7ae9, 0x00fe,
-	0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810, 0x6a14, 0xa205,
-	0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c, 0x1e6e, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
-	0x0000, 0x2069, 0xafc7, 0x6833, 0x0000, 0x683f, 0x0000, 0x08f8,
-	0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005, 0x0168, 0x681a,
-	0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2186, 0x2045, 0x88ff,
-	0x090c, 0x14f6, 0x8a51, 0x0005, 0x2050, 0x0005, 0x8a50, 0x8841,
-	0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120, 0x6000, 0xa005,
-	0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
-	0x2196, 0x2045, 0x88ff, 0x090c, 0x14f6, 0x0005, 0x0000, 0x0011,
-	0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
-	0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x217b,
-	0x2177, 0x0000, 0x0000, 0x2185, 0x0000, 0x217b, 0x0000, 0x2182,
-	0x217f, 0x0000, 0x0000, 0x0000, 0x2185, 0x2182, 0x0000, 0x217d,
-	0x217d, 0x0000, 0x0000, 0x2185, 0x0000, 0x217d, 0x0000, 0x2183,
-	0x2183, 0x0000, 0x0000, 0x0000, 0x2185, 0x2183, 0x00a6, 0x0096,
-	0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904, 0x2237, 0x2d60,
-	0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2186, 0xa986, 0x0007, 0x0130,
-	0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422,
-	0x6060, 0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2237,
-	0x6004, 0xa065, 0x0904, 0x2237, 0x0c18, 0x2805, 0xa005, 0x01a8,
-	0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020,
-	0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150,
-	0x8a51, 0x0904, 0x2237, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904,
-	0x2237, 0x0830, 0x8a51, 0x0904, 0x2237, 0x8840, 0x2805, 0xa005,
-	0x1158, 0x6004, 0xa065, 0x0904, 0x2237, 0x6034, 0xa0cc, 0x000f,
-	0xa9c0, 0x2186, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852,
-	0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68,
-	0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122,
-	0x690c, 0x2300, 0xa11b, 0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804,
-	0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b,
-	0x0a0c, 0x14f6, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e,
-	0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832,
-	0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e,
-	0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004,
-	0xa084, 0x0007, 0x0002, 0x224b, 0x224c, 0x224f, 0x2252, 0x2257,
-	0x225a, 0x225f, 0x2264, 0x0005, 0x080c, 0x1ff4, 0x0005, 0x080c,
-	0x1a6c, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4, 0x0005, 0x080c,
-	0x16f8, 0x0005, 0x080c, 0x1ff4, 0x080c, 0x16f8, 0x0005, 0x080c,
-	0x1a6c, 0x080c, 0x16f8, 0x0005, 0x080c, 0x1a6c, 0x080c, 0x1ff4,
-	0x080c, 0x16f8, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200,
-	0x2071, 0xb280, 0x2069, 0xad00, 0x2009, 0x0004, 0x7912, 0x7817,
-	0x0004, 0x080c, 0x2651, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x2283, 0x20e1,
-	0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126,
-	0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x2335, 0xa084, 0x0007,
-	0x0002, 0x22b3, 0x22a1, 0x22a4, 0x22a7, 0x22ac, 0x22ae, 0x22b0,
-	0x22b2, 0x080c, 0x5fb7, 0x0078, 0x080c, 0x5ff0, 0x0060, 0x080c,
-	0x5fb7, 0x080c, 0x5ff0, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018,
-	0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026,
-	0x7930, 0xa184, 0x0003, 0x0118, 0x20e1, 0x9040, 0x04a0, 0xa184,
-	0x0030, 0x01e0, 0x6a00, 0xa286, 0x0003, 0x1108, 0x00a0, 0x080c,
-	0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
-	0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
-	0x0010, 0x080c, 0x485e, 0x20e1, 0x9010, 0x00a8, 0xa184, 0x00c0,
-	0x0168, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c,
-	0x1d22, 0x005e, 0x004e, 0x003e, 0x00ee, 0x0028, 0xa184, 0x0300,
-	0x0110, 0x20e1, 0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005,
-	0x0016, 0x00e6, 0x00f6, 0x2071, 0xad00, 0x7128, 0x2001, 0xaf90,
-	0x2102, 0x2001, 0xaf98, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009,
-	0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0,
-	0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349,
-	0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009,
-	0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010,
-	0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c,
-	0x2651, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x14f6,
-	0x0126, 0x2091, 0x2800, 0x2061, 0x0100, 0x2071, 0xad00, 0x6024,
-	0x6026, 0x6053, 0x0030, 0x080c, 0x2690, 0x6050, 0xa084, 0xfe7f,
-	0x6052, 0x2009, 0x00ef, 0x6132, 0x6136, 0x080c, 0x26a0, 0x60e7,
-	0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000,
-	0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0e9f, 0x601b, 0x001e,
-	0x600f, 0x00ff, 0x2001, 0xaf8c, 0x2003, 0x00ff, 0x602b, 0x002f,
-	0x012e, 0x0005, 0x2001, 0xad31, 0x2003, 0x0000, 0x2001, 0xad30,
-	0x2003, 0x0001, 0x0005, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016,
-	0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118, 0xa184, 0x0007, 0x002a,
-	0xa195, 0x0004, 0xa284, 0x0007, 0x0002, 0x23a7, 0x238d, 0x2390,
-	0x2393, 0x2398, 0x239a, 0x239e, 0x23a2, 0x080c, 0x6699, 0x00b8,
-	0x080c, 0x6774, 0x00a0, 0x080c, 0x6774, 0x080c, 0x6699, 0x0078,
-	0x0099, 0x0068, 0x080c, 0x6699, 0x0079, 0x0048, 0x080c, 0x6774,
-	0x0059, 0x0028, 0x080c, 0x6774, 0x080c, 0x6699, 0x0029, 0x002e,
-	0x001e, 0x000e, 0x012e, 0x0005, 0x6124, 0xd19c, 0x1904, 0x25bf,
-	0x080c, 0x574f, 0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024,
-	0xa084, 0x1800, 0x0178, 0x080c, 0x5775, 0x0118, 0x080c, 0x5761,
-	0x1148, 0x6027, 0x0020, 0x6043, 0x0000, 0x2001, 0xaf9d, 0x2003,
-	0xaaaa, 0x0458, 0x080c, 0x5775, 0x15d0, 0x6024, 0xa084, 0x1800,
-	0x1108, 0x04a8, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e,
-	0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a,
-	0x0804, 0x25bf, 0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4,
-	0x1188, 0xd0d4, 0x11a0, 0xd0cc, 0x0130, 0x7088, 0xa086, 0x0028,
-	0x1110, 0x080c, 0x58da, 0x0804, 0x25bf, 0x2001, 0xaf9e, 0x2003,
-	0x0000, 0x0048, 0x2001, 0xaf9e, 0x2003, 0x0002, 0x0020, 0x080c,
-	0x584d, 0x0804, 0x25bf, 0x080c, 0x597a, 0x0804, 0x25bf, 0xd1ac,
-	0x0904, 0x2507, 0x080c, 0x574f, 0x11d8, 0x6027, 0x0020, 0x0006,
-	0x0026, 0x0036, 0x080c, 0x576b, 0x1170, 0x2001, 0xaf9e, 0x2003,
-	0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c, 0x569a, 0x003e,
-	0x002e, 0x000e, 0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5726,
-	0x0016, 0x0046, 0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061,
-	0x0100, 0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74ca, 0xa48c,
-	0xff00, 0x7034, 0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x7038,
-	0xd084, 0x1148, 0xc085, 0x703a, 0x0036, 0x2418, 0x2011, 0x8016,
-	0x080c, 0x3c5c, 0x003e, 0xa196, 0xff00, 0x05b8, 0x7050, 0xa084,
-	0x00ff, 0x810f, 0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011,
-	0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xad52,
-	0x2214, 0xd2ac, 0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248,
-	0xa294, 0xff00, 0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904,
-	0x24d2, 0x7034, 0xd08c, 0x1140, 0x2001, 0xad0c, 0x200c, 0xd1ac,
-	0x1904, 0x24d2, 0xc1ad, 0x2102, 0x0036, 0x73c8, 0x2011, 0x8013,
-	0x080c, 0x3c5c, 0x003e, 0x0804, 0x24d2, 0x7034, 0xd08c, 0x1140,
-	0x2001, 0xad0c, 0x200c, 0xd1ac, 0x1904, 0x24d2, 0xc1ad, 0x2102,
-	0x0036, 0x73c8, 0x2011, 0x8013, 0x080c, 0x3c5c, 0x003e, 0x7130,
-	0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x01d0, 0x0016,
-	0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019, 0x000e,
-	0x080c, 0xa8eb, 0xa484, 0x00ff, 0xa080, 0x2be6, 0x200d, 0xa18c,
-	0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xa96c,
-	0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004,
-	0x080c, 0x2aac, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x080c, 0x4cdc, 0x1110, 0x080c, 0x493a, 0x8108, 0x1f04,
-	0x24c9, 0x015e, 0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x7adf,
-	0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581,
-	0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3, 0x0000,
-	0x001e, 0x2001, 0xad00, 0x2014, 0xa296, 0x0004, 0x1128, 0xd19c,
-	0x1118, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xad22,
-	0x2003, 0x0000, 0x6027, 0x0020, 0x080c, 0x5775, 0x1140, 0x0016,
-	0x2009, 0x07d0, 0x2011, 0x567b, 0x080c, 0x6593, 0x001e, 0xd194,
-	0x0904, 0x25bf, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2570, 0x080c,
-	0x6581, 0x080c, 0x7834, 0x6027, 0x0004, 0x00f6, 0x2019, 0xafd0,
-	0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6,
-	0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
-	0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0,
-	0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a,
-	0x080c, 0x6b73, 0x080c, 0x6c50, 0x7810, 0x2070, 0x7037, 0x0103,
-	0x2f60, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e,
-	0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
-	0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061,
-	0xafc7, 0x6028, 0xa09a, 0x00c8, 0x1238, 0x8000, 0x602a, 0x00ce,
-	0x080c, 0x7827, 0x0804, 0x25be, 0x2019, 0xafd0, 0x2304, 0xa065,
-	0x0120, 0x2009, 0x0027, 0x080c, 0x80a7, 0x00ce, 0x0804, 0x25be,
-	0xd2bc, 0x0904, 0x25be, 0x080c, 0x658e, 0x6014, 0xa084, 0x0184,
-	0xa085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069, 0x0140,
-	0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803, 0x0000,
-	0x00de, 0x00c6, 0x2061, 0xafc7, 0x6044, 0xa09a, 0x00c8, 0x12f0,
-	0x8000, 0x6046, 0x603c, 0x00ce, 0xa005, 0x0540, 0x2009, 0x07d0,
-	0x080c, 0x6586, 0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x1138,
-	0x6114, 0xa18c, 0x0184, 0xa18d, 0x0012, 0x6116, 0x00b8, 0x6114,
-	0xa18c, 0x0184, 0xa18d, 0x0016, 0x6116, 0x0080, 0x0036, 0x2019,
-	0x0001, 0x080c, 0x7a64, 0x003e, 0x2019, 0xafd6, 0x2304, 0xa065,
-	0x0120, 0x2009, 0x004f, 0x080c, 0x80a7, 0x00ce, 0x001e, 0xd19c,
-	0x0904, 0x261a, 0x7034, 0xd0ac, 0x1560, 0x0016, 0x0156, 0x6027,
-	0x0008, 0x602f, 0x0020, 0x20a9, 0x0006, 0x1d04, 0x25cd, 0x2091,
-	0x6000, 0x1f04, 0x25cd, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400,
-	0x6052, 0x20a9, 0x0366, 0x1d04, 0x25db, 0x2091, 0x6000, 0x6020,
-	0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0490,
-	0x080c, 0x2760, 0x1f04, 0x25db, 0x015e, 0x6152, 0x001e, 0x6027,
-	0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c,
-	0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c, 0x79e1, 0x080c,
-	0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64, 0x003e, 0x60e3,
-	0x0000, 0x080c, 0xac8d, 0x080c, 0xaca8, 0xa085, 0x0001, 0x080c,
-	0x5793, 0x2001, 0xad00, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c,
-	0x12cc, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005, 0x0006, 0x0016,
-	0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0xad00,
-	0x71c0, 0x70c2, 0xa116, 0x01f0, 0x81ff, 0x0128, 0x2011, 0x8011,
-	0x080c, 0x3c5c, 0x00b8, 0x2011, 0x8012, 0x080c, 0x3c5c, 0x2001,
-	0xad71, 0x2004, 0xd0fc, 0x1170, 0x0036, 0x00c6, 0x080c, 0x26eb,
-	0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0000, 0x080c, 0x2aac,
-	0x00ce, 0x003e, 0x012e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e,
-	0x0005, 0x00c6, 0x00f6, 0x0006, 0x0026, 0x2061, 0x0100, 0xa190,
-	0x2664, 0x2205, 0x60f2, 0x2011, 0x2671, 0x2205, 0x60ee, 0x002e,
-	0x000e, 0x00fe, 0x00ce, 0x0005, 0x0840, 0x0840, 0x0840, 0x0580,
-	0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8,
-	0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c,
-	0x00ff, 0x2130, 0xa094, 0xff00, 0x1110, 0x81ff, 0x0118, 0x080c,
-	0x6278, 0x0038, 0xa080, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f,
-	0xa006, 0x0005, 0xa080, 0x2be6, 0x200d, 0xa18c, 0x00ff, 0x0005,
-	0x00d6, 0x2069, 0x0140, 0x2001, 0xad14, 0x2003, 0x00ef, 0x20a9,
-	0x0010, 0xa006, 0x6852, 0x6856, 0x1f04, 0x269b, 0x00de, 0x0005,
-	0x0006, 0x00d6, 0x0026, 0x2069, 0x0140, 0x2001, 0xad14, 0x2102,
-	0x8114, 0x8214, 0x8214, 0x8214, 0x20a9, 0x0010, 0x6853, 0x0000,
-	0xa006, 0x82ff, 0x1128, 0xa184, 0x000f, 0xa080, 0xacae, 0x2005,
-	0x6856, 0x8211, 0x1f04, 0x26b0, 0x002e, 0x00de, 0x000e, 0x0005,
-	0x00c6, 0x2061, 0xad00, 0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c,
-	0x6032, 0x00ce, 0x0005, 0x0156, 0x00d6, 0x0026, 0x0016, 0x0006,
-	0x2069, 0x0140, 0x6980, 0xa116, 0x0180, 0xa112, 0x1230, 0x8212,
-	0x8210, 0x22a8, 0x2001, 0x0402, 0x0018, 0x22a8, 0x2001, 0x0404,
-	0x680e, 0x1f04, 0x26e0, 0x680f, 0x0000, 0x000e, 0x001e, 0x002e,
-	0x00de, 0x015e, 0x0005, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
-	0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002e, 0x080c,
-	0xa96c, 0x004e, 0x0005, 0x00f6, 0x0016, 0x0026, 0x2079, 0x0140,
-	0x78c4, 0xd0dc, 0x0548, 0xa084, 0x0700, 0xa08e, 0x0300, 0x1520,
-	0x2011, 0x0000, 0x2009, 0x0002, 0x2300, 0xa080, 0x0020, 0x2018,
-	0x2300, 0x080c, 0x6665, 0x2011, 0x0030, 0x2200, 0x8007, 0xa085,
-	0x004c, 0x78c2, 0x2009, 0x0204, 0x210c, 0x2200, 0xa100, 0x2009,
-	0x0138, 0x200a, 0x080c, 0x574f, 0x1118, 0x2009, 0xaf8e, 0x200a,
-	0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126,
-	0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c,
-	0x8000, 0x2014, 0xa184, 0x0003, 0x0110, 0x0804, 0x1a6a, 0x002e,
-	0x001e, 0x000e, 0x012e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004,
-	0xa082, 0x0005, 0x000e, 0x0268, 0x2001, 0x0170, 0x200c, 0xa18c,
-	0x00ff, 0xa18e, 0x004c, 0x1128, 0x200c, 0xa18c, 0xff00, 0x810f,
-	0x0010, 0x2009, 0x0000, 0x2001, 0x0204, 0x2004, 0xa108, 0x0005,
-	0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854,
-	0xd08c, 0x1110, 0x1f04, 0x2767, 0x00fe, 0x015e, 0x000e, 0x0005,
-	0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x6030, 0x0006, 0x6048,
-	0x0006, 0x60e4, 0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60f0,
-	0x0006, 0x60ec, 0x0006, 0x600c, 0x0006, 0x6004, 0x0006, 0x6028,
-	0x0006, 0x60e0, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xe000,
-	0xe000, 0xe000, 0xe000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e,
-	0x60e2, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e,
-	0x60ee, 0x000e, 0x60f2, 0x000e, 0x6052, 0x000e, 0x60ea, 0x000e,
-	0x60e6, 0x000e, 0x604a, 0x000e, 0x6032, 0x6036, 0x2008, 0x080c,
-	0x26a0, 0x000e, 0x00ce, 0x001e, 0x0005, 0x2845, 0x2849, 0x284d,
-	0x2853, 0x2859, 0x285f, 0x2865, 0x286d, 0x2875, 0x287b, 0x2881,
-	0x2889, 0x2891, 0x2899, 0x28a1, 0x28ab, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b7, 0x28b7, 0x28bc,
-	0x28bc, 0x28c3, 0x28c3, 0x28ca, 0x28ca, 0x28d3, 0x28d3, 0x28da,
-	0x28da, 0x28e3, 0x28e3, 0x28ec, 0x28ec, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5,
-	0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x28b5, 0x0106, 0x0006, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
-	0x2373, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106,
-	0x0006, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
-	0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
-	0x2373, 0x080c, 0x223d, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c,
-	0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x228f, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x228f, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x223d, 0x080c, 0x228f, 0x0804,
-	0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c, 0x223d, 0x080c,
-	0x228f, 0x0804, 0x28f7, 0x0106, 0x0006, 0x080c, 0x2373, 0x080c,
-	0x223d, 0x080c, 0x228f, 0x0804, 0x28f7, 0xe000, 0x0cf0, 0x0106,
-	0x0006, 0x080c, 0x272f, 0x04d8, 0x0106, 0x0006, 0x080c, 0x272f,
-	0x080c, 0x2373, 0x04a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
-	0x223d, 0x0468, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
-	0x080c, 0x223d, 0x0420, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
-	0x228f, 0x00e8, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c, 0x2373,
-	0x080c, 0x228f, 0x00a0, 0x0106, 0x0006, 0x080c, 0x272f, 0x080c,
-	0x223d, 0x080c, 0x228f, 0x0058, 0x0106, 0x0006, 0x080c, 0x272f,
-	0x080c, 0x2373, 0x080c, 0x223d, 0x080c, 0x228f, 0x0000, 0x000e,
-	0x010e, 0x000d, 0x00c6, 0x0026, 0x0046, 0x2021, 0x0000, 0x080c,
-	0x502d, 0x1904, 0x29d4, 0x72d0, 0x2001, 0xaf9d, 0x2004, 0xa005,
-	0x1110, 0xd29c, 0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x29d4,
-	0x080c, 0x29d8, 0x0804, 0x29d4, 0x080c, 0x574f, 0x1120, 0x709b,
-	0xffff, 0x0804, 0x29d4, 0xd294, 0x0120, 0x709b, 0xffff, 0x0804,
-	0x29d4, 0x2001, 0xad14, 0x203c, 0x7284, 0xd284, 0x0904, 0x2976,
-	0xd28c, 0x1904, 0x2976, 0x0036, 0x7398, 0xa38e, 0xffff, 0x1110,
-	0x2019, 0x0001, 0x8314, 0xa2e0, 0xb3c0, 0x2c04, 0xa38c, 0x0001,
-	0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e,
-	0x0560, 0xa08e, 0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230,
-	0xd284, 0x1538, 0x7284, 0xc28d, 0x7286, 0x709b, 0xffff, 0x003e,
-	0x0428, 0x2009, 0x0000, 0x080c, 0x2676, 0x080c, 0x4c80, 0x11b8,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c,
-	0x0118, 0x6000, 0xd0bc, 0x0120, 0x080c, 0x29eb, 0x0140, 0x0028,
-	0x080c, 0x2b1a, 0x080c, 0x2a19, 0x0110, 0x8318, 0x0818, 0x739a,
-	0x0010, 0x709b, 0xffff, 0x003e, 0x0804, 0x29d4, 0xa780, 0x2be6,
-	0x203d, 0xa7bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x7098, 0xa096,
-	0xffff, 0x1120, 0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220,
-	0x2008, 0xa802, 0x20a8, 0x0020, 0x709b, 0xffff, 0x0804, 0x29d4,
-	0x2700, 0x0156, 0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x4cdc,
-	0x0120, 0x080c, 0x4c80, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000,
-	0xd0bc, 0x11d0, 0x7284, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff,
-	0xa082, 0x0006, 0x02b0, 0xd484, 0x1118, 0x080c, 0x4c9f, 0x0028,
-	0x080c, 0x2b9c, 0x0170, 0x080c, 0x2bc9, 0x0058, 0x080c, 0x2b1a,
-	0x080c, 0x2a19, 0x0170, 0x0028, 0x080c, 0x2b9c, 0x0110, 0x0419,
-	0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x2990, 0x709b, 0xffff,
-	0x0018, 0x001e, 0x015e, 0x719a, 0x004e, 0x002e, 0x00ce, 0x0005,
-	0x00c6, 0x0016, 0x709b, 0x0000, 0x2009, 0x007e, 0x080c, 0x4c80,
-	0x1138, 0x080c, 0x2b1a, 0x04a9, 0x0118, 0x70d0, 0xc0bd, 0x70d2,
-	0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68,
-	0x2001, 0xad56, 0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807,
-	0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2001,
-	0x0000, 0x080c, 0x4c1e, 0x2001, 0x0000, 0x080c, 0x4c30, 0x0126,
-	0x2091, 0x8000, 0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004,
-	0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
-	0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xad56,
-	0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9807, 0x0550, 0x2d00,
-	0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140,
-	0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2ad9,
-	0x080c, 0x9956, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e,
-	0x2001, 0x0002, 0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x7094,
-	0x8000, 0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
-	0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026,
-	0x2009, 0x0080, 0x080c, 0x4c80, 0x1120, 0x0031, 0x0110, 0x70d7,
-	0xffff, 0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6,
-	0x2c68, 0x080c, 0x8022, 0x01d8, 0x2d00, 0x601a, 0x080c, 0x9956,
-	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002,
-	0x080c, 0x4c30, 0x0126, 0x2091, 0x8000, 0x70d8, 0x8000, 0x70da,
-	0x012e, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085, 0x0001, 0x00ce,
-	0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091,
-	0x8000, 0x2009, 0x007f, 0x080c, 0x4c80, 0x1190, 0x2c68, 0x080c,
-	0x8022, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
-	0x080c, 0x9956, 0x2009, 0x0022, 0x080c, 0x80a7, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036,
-	0x0026, 0x080c, 0x68f3, 0x080c, 0x689d, 0x080c, 0x8a15, 0x2130,
-	0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1120, 0x080c,
-	0x4ecf, 0x080c, 0x493a, 0x001e, 0x8108, 0x1f04, 0x2ac3, 0x86ff,
-	0x1110, 0x080c, 0x11d4, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee,
-	0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270,
-	0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
-	0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x001e,
-	0x2e60, 0x080c, 0x4ecf, 0x6210, 0x6314, 0x080c, 0x493a, 0x6212,
-	0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6,
-	0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150,
-	0x2071, 0xad00, 0x7094, 0xa005, 0x0110, 0x8001, 0x7096, 0x000e,
-	0x00ee, 0x0005, 0x2071, 0xad00, 0x70d8, 0xa005, 0x0dc0, 0x8001,
-	0x70da, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6,
-	0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118,
-	0x20a9, 0x0001, 0x0098, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0150,
-	0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c,
-	0xa96c, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e,
-	0x007e, 0x05c8, 0xa28e, 0x007f, 0x05b0, 0xa28e, 0x0080, 0x0598,
-	0xa288, 0xae34, 0x210c, 0x81ff, 0x0570, 0x8fff, 0x05c1, 0x00c6,
-	0x2160, 0x2001, 0x0001, 0x080c, 0x5037, 0x00ce, 0x2019, 0x0029,
-	0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x00c6,
-	0x0026, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x1118,
-	0x6007, 0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0xa215, 0x6206,
-	0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c, 0xa712, 0x001e, 0x007e,
-	0x2160, 0x080c, 0x4ecf, 0x002e, 0x8210, 0x1f04, 0x2b3e, 0x015e,
-	0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046,
-	0x0026, 0x0016, 0x2001, 0xad52, 0x2004, 0xd0c4, 0x0148, 0xd0a4,
-	0x0138, 0xa006, 0x2220, 0x8427, 0x2009, 0x0029, 0x080c, 0xa96c,
-	0x001e, 0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6,
-	0x7284, 0x82ff, 0x01f8, 0x2011, 0xad52, 0x2214, 0xd2ac, 0x11d0,
-	0x2100, 0x080c, 0x268a, 0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314,
-	0xa2e0, 0xb3c0, 0x2c04, 0xd384, 0x0120, 0xa084, 0xff00, 0x8007,
-	0x0010, 0xa084, 0x00ff, 0xa116, 0x0138, 0xa096, 0x00ff, 0x0110,
-	0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x0005, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0xa180, 0xae34,
-	0x2004, 0xa065, 0x0178, 0x0016, 0x00c6, 0x080c, 0x9807, 0x001e,
-	0x090c, 0x14f6, 0x611a, 0x080c, 0x2ad9, 0x080c, 0x8078, 0x001e,
-	0x080c, 0x4c9f, 0x012e, 0x00ce, 0x001e, 0x0005, 0x7eef, 0x7de8,
-	0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6,
-	0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc,
-	0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc,
-	0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1,
-	0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6,
-	0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797,
-	0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c,
-	0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071,
-	0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66,
-	0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454,
-	0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a,
-	0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039,
-	0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d,
-	0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123,
-	0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f,
-	0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700,
-	0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000,
-	0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000,
-	0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700,
-	0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100,
-	0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00,
-	0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400,
-	0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00,
-	0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800,
-	0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400,
-	0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0xad81,
-	0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e, 0x7033,
-	0xad91, 0x7037, 0xad91, 0x7007, 0x0001, 0x2061, 0xadd1, 0x6003,
-	0x0002, 0x0005, 0x1004, 0x2d0c, 0x0e04, 0x2d0c, 0x2071, 0xad81,
-	0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60, 0x7820, 0xa08e, 0x0069,
-	0x1904, 0x2df1, 0x0804, 0x2d8a, 0x0005, 0x2071, 0xad81, 0x7004,
-	0x0002, 0x2d15, 0x2d16, 0x2d1f, 0x2d30, 0x0005, 0x1004, 0x2d1e,
-	0x0e04, 0x2d1e, 0x2b78, 0x7818, 0xd084, 0x01e8, 0x0005, 0x2b78,
-	0x2061, 0xadd1, 0x6008, 0xa08e, 0x0100, 0x0128, 0xa086, 0x0200,
-	0x0904, 0x2deb, 0x0005, 0x7014, 0x2068, 0x2a60, 0x7018, 0x0807,
-	0x7010, 0x2068, 0x6834, 0xa086, 0x0103, 0x0108, 0x0005, 0x2a60,
-	0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x1210,
-	0x61c0, 0x0042, 0x2100, 0xa08a, 0x003f, 0x1a04, 0x2de8, 0x61c0,
-	0x0804, 0x2d8a, 0x2dcc, 0x2df7, 0x2dff, 0x2e03, 0x2e0b, 0x2e11,
-	0x2e15, 0x2e21, 0x2e24, 0x2e2e, 0x2e31, 0x2de8, 0x2de8, 0x2de8,
-	0x2e34, 0x2de8, 0x2e43, 0x2e5a, 0x2e71, 0x2ee8, 0x2eed, 0x2f16,
-	0x2f67, 0x2f78, 0x2f96, 0x2fcd, 0x2fd7, 0x2fe4, 0x2ff7, 0x3018,
-	0x3021, 0x3057, 0x305d, 0x2de8, 0x3086, 0x2de8, 0x2de8, 0x2de8,
-	0x2de8, 0x2de8, 0x308d, 0x3097, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
-	0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x309f, 0x2de8, 0x2de8, 0x2de8,
-	0x2de8, 0x2de8, 0x30b1, 0x30b9, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
-	0x2de8, 0x2de8, 0x0002, 0x30cb, 0x311f, 0x317a, 0x318a, 0x2de8,
-	0x31a4, 0x35cb, 0x3fbb, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x2de8,
-	0x2de8, 0x2de8, 0x2de8, 0x2e2e, 0x2e31, 0x35cd, 0x2de8, 0x35da,
-	0x403c, 0x4097, 0x40fb, 0x2de8, 0x415a, 0x4180, 0x419f, 0x2de8,
-	0x2de8, 0x2de8, 0x2de8, 0x35de, 0x376b, 0x3785, 0x37a3, 0x3804,
-	0x3858, 0x3863, 0x389a, 0x38a9, 0x38b8, 0x38bb, 0x38de, 0x3928,
-	0x398e, 0x399b, 0x3a9c, 0x3bb3, 0x3bdc, 0x3cda, 0x3cfc, 0x3d08,
-	0x3d41, 0x3e05, 0x2de8, 0x2de8, 0x2de8, 0x2de8, 0x3e6d, 0x3e88,
-	0x3efa, 0x3fac, 0x713c, 0x0000, 0x2021, 0x4000, 0x080c, 0x3c39,
-	0x0126, 0x2091, 0x8000, 0x0e04, 0x2dd8, 0x7818, 0xd084, 0x0110,
-	0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a, 0x7b2e, 0x781b, 0x0001,
-	0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x012e, 0x0005,
-	0x2021, 0x4001, 0x0c18, 0x2021, 0x4002, 0x0c00, 0x2021, 0x4003,
-	0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021, 0x4006, 0x08b8, 0xa02e,
-	0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3c46, 0x7823,
-	0x0004, 0x7824, 0x0807, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
-	0x7930, 0x0804, 0x3c49, 0x7924, 0x7828, 0x2114, 0x200a, 0x0804,
-	0x2dcc, 0x7924, 0x2114, 0x0804, 0x2dcc, 0x2099, 0x0009, 0x20a1,
-	0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0804,
-	0x2dcc, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0001,
-	0x2019, 0x001b, 0x783b, 0x0017, 0x0804, 0x2dcc, 0x7d38, 0x7c3c,
-	0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061, 0x1000, 0xe10c, 0xa006,
-	0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904,
-	0x2dcc, 0x0804, 0x2dee, 0x2069, 0xad51, 0x7824, 0x7930, 0xa11a,
-	0x1a04, 0x2df4, 0x8019, 0x0904, 0x2df4, 0x684a, 0x6942, 0x782c,
-	0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x5a1c,
-	0x0804, 0x2dcc, 0x2069, 0xad51, 0x7824, 0x7934, 0xa11a, 0x1a04,
-	0x2df4, 0x8019, 0x0904, 0x2df4, 0x684e, 0x6946, 0x782c, 0x6862,
-	0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x50d9, 0x0804,
-	0x2dcc, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2df1, 0x7924, 0x7b28,
-	0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xad88, 0x41a1, 0x080c, 0x3c05,
-	0x0904, 0x2df1, 0x2009, 0x0020, 0x080c, 0x3c46, 0x701b, 0x2e89,
-	0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120,
-	0xa096, 0x0019, 0x1904, 0x2df1, 0x810f, 0xa18c, 0x00ff, 0x0904,
-	0x2df1, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3c05,
-	0x0904, 0x2df1, 0x2009, 0x0020, 0x2061, 0xadd1, 0x6224, 0x6328,
-	0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000,
-	0xa5a9, 0x0000, 0x080c, 0x3c46, 0x701b, 0x2eb7, 0x0005, 0x6834,
-	0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904,
-	0x2df1, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c,
-	0x4b7c, 0x1128, 0x7007, 0x0003, 0x701b, 0x2ed1, 0x0005, 0x080c,
-	0x51df, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xad88,
-	0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3c49,
-	0x61a8, 0x7824, 0x60aa, 0x0804, 0x2dcc, 0x2091, 0x8000, 0x7823,
-	0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
-	0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
-	0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
-	0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
-	0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904,
-	0x2df1, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x1904,
-	0x2df4, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804,
-	0x2df4, 0x7c28, 0x7d2c, 0x080c, 0x4e96, 0xd28c, 0x1118, 0x080c,
-	0x4e41, 0x0010, 0x080c, 0x4e6f, 0x1518, 0x2061, 0xb400, 0x0126,
-	0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d,
-	0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e,
-	0xace0, 0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1a04, 0x2df1,
-	0x0c30, 0x080c, 0x929c, 0x012e, 0x0904, 0x2df1, 0x0804, 0x2dcc,
-	0xa00e, 0x2001, 0x0005, 0x080c, 0x51df, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x9803, 0x080c, 0x510c, 0x012e, 0x0804, 0x2dcc, 0x81ff,
-	0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96,
-	0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0904, 0x2df1, 0x0804, 0x2dcc,
-	0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
-	0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0005, 0x080c, 0x4ebd, 0x0904,
-	0x2df1, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x8003, 0x800b,
-	0x810b, 0xa108, 0x080c, 0x6519, 0x0804, 0x2dcc, 0x0126, 0x2091,
-	0x8000, 0x81ff, 0x0118, 0x2009, 0x0001, 0x0448, 0x2029, 0x00ff,
-	0x644c, 0x2400, 0xa506, 0x01f0, 0x2508, 0x080c, 0x4cdc, 0x11d0,
-	0x080c, 0x4f0d, 0x1128, 0x2009, 0x0002, 0x62b0, 0x2518, 0x00b8,
-	0x2019, 0x0004, 0x080c, 0x4ebd, 0x1118, 0x2009, 0x0006, 0x0078,
-	0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108,
-	0x080c, 0x6519, 0x8529, 0x1ae8, 0x012e, 0x0804, 0x2dcc, 0x012e,
-	0x0804, 0x2df1, 0x012e, 0x0804, 0x2df4, 0x080c, 0x3c1a, 0x0904,
-	0x2df4, 0x080c, 0x4dfc, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff,
-	0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4ded,
-	0x080c, 0x4e96, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c,
-	0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e71, 0x0904, 0x2df1, 0x080c,
-	0x4bc0, 0x080c, 0x4e3a, 0x080c, 0x4e96, 0x0804, 0x2dcc, 0x080c,
-	0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x62a0,
-	0x2019, 0x0005, 0x00c6, 0x080c, 0x4ecf, 0x2061, 0x0000, 0x080c,
-	0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2009, 0x0000,
-	0x080c, 0xa712, 0x007e, 0x00ce, 0x080c, 0x4e96, 0x0804, 0x2dcc,
-	0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4e96, 0x2208, 0x0804,
-	0x2dcc, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xae13, 0x6810, 0x6914,
-	0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019,
-	0x0000, 0x20a9, 0x007e, 0x2069, 0xae34, 0x2d04, 0xa075, 0x0130,
-	0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04,
-	0x3035, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2dcc,
-	0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c,
-	0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069,
-	0xae13, 0x6910, 0x62ac, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1,
-	0x614c, 0xa190, 0x2be6, 0x2215, 0xa294, 0x00ff, 0x636c, 0x83ff,
-	0x0108, 0x6270, 0x67d0, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090,
-	0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031,
-	0x0002, 0x0040, 0x080c, 0x574f, 0x1118, 0x2031, 0x0004, 0x0010,
-	0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2dcc, 0x613c, 0x6240,
-	0x2019, 0xafa3, 0x231c, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
-	0x6134, 0xa006, 0x2010, 0x2018, 0x012e, 0x0804, 0x2dcc, 0x080c,
-	0x3c2a, 0x0904, 0x2df4, 0x6244, 0x6338, 0x0804, 0x2dcc, 0x613c,
-	0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0xad51, 0x831f,
-	0xa305, 0x6816, 0x782c, 0x2069, 0xafa3, 0x2d1c, 0x206a, 0x0804,
-	0x2dcc, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x012e, 0x0804,
-	0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x7828, 0xa00d, 0x0904,
-	0x2df4, 0x782c, 0xa005, 0x0904, 0x2df4, 0x6244, 0x6146, 0x6338,
-	0x603a, 0x0804, 0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003,
-	0x1904, 0x2df1, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
-	0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xad14, 0x2004, 0xa085,
-	0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188, 0x2be6, 0x210d,
-	0xa18c, 0x00ff, 0x2001, 0xad14, 0x2004, 0xa116, 0x0550, 0x810f,
-	0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x8022, 0x000e,
-	0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3c05,
-	0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x701b, 0x3173, 0x2d00, 0x6012, 0x2009, 0x0032,
-	0x080c, 0x80a7, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804,
-	0x2df1, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x8078, 0x0cb0, 0x2001,
-	0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00c6, 0x2061,
-	0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130,
-	0x2001, 0xad14, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f,
-	0x16a0, 0xa188, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xad14,
-	0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000,
-	0x0006, 0x080c, 0x8022, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05,
-	0x601f, 0x0001, 0x080c, 0x3c05, 0x01d8, 0x6837, 0x0000, 0x7007,
-	0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x3173,
-	0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x80a7, 0x012e, 0x00ce,
-	0x0005, 0x012e, 0x00ce, 0x0804, 0x2df1, 0x00ce, 0x0804, 0x2df4,
-	0x080c, 0x8078, 0x0cb0, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1,
-	0x0804, 0x2dcc, 0x2061, 0xb048, 0x0126, 0x2091, 0x8000, 0x6000,
-	0xd084, 0x0128, 0x6104, 0x6208, 0x012e, 0x0804, 0x2dcc, 0x012e,
-	0x0804, 0x2df4, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0904,
-	0x2df1, 0x0126, 0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248,
-	0xa085, 0x0001, 0x080c, 0x26c0, 0x080c, 0x436e, 0x012e, 0x0804,
-	0x2dcc, 0x012e, 0x0804, 0x2df4, 0x0126, 0x2091, 0x8000, 0x7824,
-	0xa084, 0x0007, 0x0002, 0x31b6, 0x31bf, 0x31c6, 0x31b3, 0x31b3,
-	0x31b3, 0x31b3, 0x31b3, 0x012e, 0x0804, 0x2df4, 0x2009, 0x0114,
-	0x2104, 0xa085, 0x0800, 0x200a, 0x080c, 0x332f, 0x0070, 0x2009,
-	0x010b, 0x200b, 0x0010, 0x080c, 0x332f, 0x0038, 0x81ff, 0x0128,
-	0x012e, 0x2021, 0x400b, 0x0804, 0x2dce, 0x0086, 0x0096, 0x00a6,
-	0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c,
-	0x0016, 0x2001, 0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001,
-	0x007a, 0x2034, 0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050,
-	0x2058, 0x080c, 0x3570, 0x080c, 0x34da, 0xa03e, 0x2720, 0x00f6,
-	0x00e6, 0x00c6, 0x2d60, 0x2071, 0xb01e, 0x2079, 0x0020, 0x00d6,
-	0x2069, 0x0000, 0x6824, 0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004,
-	0x783e, 0x2001, 0x007c, 0x2004, 0x783a, 0x00de, 0x2011, 0x0001,
-	0x080c, 0x3486, 0x080c, 0x3486, 0x00ce, 0x00ee, 0x00fe, 0x080c,
-	0x33d5, 0x080c, 0x34ae, 0x080c, 0x342b, 0x080c, 0x3394, 0x080c,
-	0x33c5, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x0530, 0x7814,
-	0xa084, 0x0184, 0xa085, 0x0010, 0x7816, 0x2079, 0x0140, 0x080c,
-	0x330d, 0x1110, 0x00fe, 0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079,
-	0x0100, 0x7827, 0x0086, 0x7814, 0xa084, 0x0184, 0xa085, 0x0032,
-	0x7816, 0x080c, 0x330d, 0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc,
-	0x0dc0, 0x7827, 0x0080, 0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130,
-	0x8b58, 0x080c, 0x3317, 0x00fe, 0x0804, 0x32d7, 0x00fe, 0x080c,
-	0x330d, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001, 0x007b,
-	0x2502, 0x080c, 0x3317, 0x0088, 0x87ff, 0x0140, 0x2001, 0x0201,
-	0x2004, 0xa005, 0x1904, 0x3211, 0x8739, 0x0038, 0x2001, 0xaffd,
-	0x2004, 0xa086, 0x0000, 0x1904, 0x3211, 0x2001, 0x0033, 0x2003,
-	0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904, 0x32d7,
-	0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904, 0x32d7,
-	0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac,
-	0x1148, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
-	0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004, 0xa005,
-	0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a,
-	0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6,
-	0x20a9, 0x0004, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001, 0x0203,
-	0x2004, 0x1f04, 0x32ac, 0x00ce, 0x0040, 0x6827, 0x0001, 0x2001,
-	0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079,
-	0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072, 0x2004,
-	0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004, 0x601e,
-	0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x31ef, 0x2061,
-	0x0100, 0x6027, 0x0002, 0x001e, 0x61e2, 0x001e, 0x6106, 0x7824,
-	0xa084, 0x0003, 0xa086, 0x0002, 0x0188, 0x20e1, 0x9028, 0x6050,
-	0xa084, 0xf7ef, 0x6052, 0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e,
-	0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908, 0x2a10,
-	0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804, 0x2dcc,
-	0x012e, 0x2021, 0x400c, 0x0804, 0x2dce, 0xa085, 0x0001, 0x1d04,
-	0x3316, 0x2091, 0x6000, 0x8420, 0xa486, 0x0064, 0x0005, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001,
-	0x0020, 0x2003, 0x0004, 0x2001, 0xaffd, 0x2003, 0x0000, 0x2001,
-	0xb01e, 0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6,
-	0x2079, 0x0100, 0x2001, 0xad14, 0x200c, 0x7932, 0x7936, 0x080c,
-	0x26a0, 0x7850, 0xa084, 0x0980, 0xa085, 0x0030, 0x7852, 0x2019,
-	0x01f4, 0x8319, 0x1df0, 0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad,
-	0x782e, 0x20a9, 0x0046, 0x1d04, 0x334b, 0x2091, 0x6000, 0x1f04,
-	0x334b, 0x7850, 0xa085, 0x0400, 0x7852, 0x2001, 0x0009, 0x2004,
-	0xa084, 0x0003, 0xa086, 0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e,
-	0x784b, 0xf7f7, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x000e,
-	0xe000, 0x1f04, 0x3368, 0x7850, 0xa085, 0x1400, 0x7852, 0x2019,
-	0x61a8, 0x7854, 0xe000, 0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8,
-	0x7827, 0x0048, 0x7850, 0xa085, 0x0400, 0x7852, 0x7843, 0x0040,
-	0x2019, 0x01f4, 0xe000, 0xe000, 0x8319, 0x1de0, 0x2001, 0x0140,
-	0x2003, 0x0100, 0x7827, 0x0020, 0x7843, 0x0000, 0x2003, 0x0000,
-	0x7827, 0x0048, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6,
-	0x00e6, 0x2071, 0xaffd, 0x2079, 0x0030, 0x2001, 0x0201, 0x2004,
-	0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc,
-	0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe,
-	0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a, 0x260a,
-	0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108,
-	0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200,
-	0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001,
-	0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100,
-	0x2009, 0xad14, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166, 0x719e,
-	0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078, 0xa080,
-	0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa, 0xa006,
-	0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af, 0x95d5,
-	0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032, 0x7016,
-	0x080c, 0x34ae, 0x080c, 0x330d, 0x1110, 0x8421, 0x0028, 0x7024,
-	0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071, 0xaffd,
-	0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4, 0x0120,
-	0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011, 0x080c,
-	0x3486, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ee, 0x00fe, 0x7017,
-	0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xaffd, 0x2079,
-	0x0030, 0x7904, 0xd1fc, 0x0904, 0x3483, 0x7803, 0x0002, 0xa026,
-	0xd19c, 0x1904, 0x347f, 0x7000, 0x0002, 0x3483, 0x3441, 0x3465,
-	0x347f, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011,
-	0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820,
-	0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c,
-	0x81ff, 0x0de8, 0x080c, 0x33b1, 0x2009, 0x0001, 0x7808, 0xd0ec,
-	0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184,
-	0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1,
-	0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000,
-	0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005,
-	0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832,
-	0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804,
-	0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802,
-	0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a,
-	0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6,
-	0x00c6, 0x2071, 0xb01e, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0,
-	0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x34d6, 0x34c1,
-	0x34cd, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c,
-	0x3486, 0x0160, 0x080c, 0x3486, 0x0048, 0x8001, 0x7002, 0x7804,
-	0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x3486, 0x00ce, 0x00ee,
-	0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b,
-	0x0004, 0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085,
-	0x0200, 0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038,
-	0x2001, 0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3c05,
-	0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
-	0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
-	0x000d, 0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3c05,
-	0x6833, 0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001,
-	0x0076, 0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061,
-	0x0020, 0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001,
-	0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001,
-	0x0073, 0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006,
-	0x603a, 0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071,
-	0x0010, 0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336,
-	0xa006, 0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122,
-	0x7003, 0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003,
-	0x0040, 0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6,
-	0x2d60, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x6018, 0x2070, 0x2d00,
-	0x7006, 0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005,
-	0x00e6, 0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001,
-	0x0078, 0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3c05, 0x2d60,
-	0x6833, 0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220,
-	0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080,
-	0x000d, 0x080c, 0x353e, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c,
-	0x3c05, 0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00,
-	0x601a, 0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004,
-	0x7006, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001,
-	0x0073, 0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824,
-	0xd0ac, 0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027,
-	0x0000, 0x2001, 0xaffd, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003,
-	0x0009, 0x00ee, 0x0005, 0x0804, 0x2dcc, 0x0126, 0x2091, 0x8000,
-	0x20a9, 0x0011, 0x2001, 0xad40, 0x20a0, 0xa006, 0x40a4, 0x012e,
-	0x0804, 0x2dcc, 0x7d38, 0x7c3c, 0x0804, 0x2e73, 0x080c, 0x3c05,
-	0x0904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c, 0x491f, 0x2009,
-	0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b,
-	0x35f2, 0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x2df4,
-	0x6804, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x2df4, 0xd094, 0x00c6,
-	0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218,
-	0xa18c, 0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c,
-	0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010,
-	0xa18c, 0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a,
-	0x0002, 0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04,
-	0x2df4, 0xa288, 0x2be6, 0x210d, 0xa18c, 0x00ff, 0x6156, 0xd0dc,
-	0x0130, 0x6828, 0xa08a, 0x007f, 0x1a04, 0x2df4, 0x604e, 0x6808,
-	0xa08a, 0x0100, 0x0a04, 0x2df4, 0xa08a, 0x0841, 0x1a04, 0x2df4,
-	0xa084, 0x0007, 0x1904, 0x2df4, 0x680c, 0xa005, 0x0904, 0x2df4,
-	0x6810, 0xa005, 0x0904, 0x2df4, 0x6848, 0x6940, 0xa10a, 0x1a04,
-	0x2df4, 0x8001, 0x0904, 0x2df4, 0x684c, 0x6944, 0xa10a, 0x1a04,
-	0x2df4, 0x8001, 0x0904, 0x2df4, 0x6804, 0xd0fc, 0x0560, 0x080c,
-	0x3c05, 0x0904, 0x2df1, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3c46, 0x701b,
-	0x3672, 0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069,
-	0xad6d, 0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xad71,
-	0x200c, 0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085,
-	0x0b00, 0x6006, 0x00ce, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xad51,
-	0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084,
-	0x00ff, 0x6042, 0x080c, 0x5a1c, 0x080c, 0x5070, 0x080c, 0x50d9,
-	0x6000, 0xa086, 0x0000, 0x1904, 0x3755, 0x6808, 0x602a, 0x080c,
-	0x22f8, 0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e,
-	0x0268, 0x2009, 0x0170, 0x200b, 0x0080, 0xe000, 0xe000, 0x200b,
-	0x0000, 0x0036, 0x6b08, 0x080c, 0x26fb, 0x003e, 0x6818, 0x691c,
-	0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a,
-	0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38,
-	0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0xa084, 0xf0ff,
-	0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x20a9, 0x0004, 0x20a1, 0xafad, 0x40a1, 0x080c, 0x659c, 0x6904,
-	0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001, 0x6b70,
-	0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c,
-	0x5fa9, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007,
-	0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003,
-	0x0010, 0x6003, 0x0001, 0x1f04, 0x36f3, 0x00ce, 0x2069, 0xad51,
-	0x2001, 0xaf9d, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000, 0x0170,
-	0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0140, 0x2003, 0xaaaa,
-	0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x0008, 0x2102, 0x00c6,
-	0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c,
-	0x574f, 0x0128, 0x080c, 0x3e5f, 0x0110, 0x080c, 0x26c0, 0x60c4,
-	0xa005, 0x01b0, 0x6003, 0x0001, 0x2009, 0x373f, 0x00c0, 0x080c,
-	0x574f, 0x1158, 0x2011, 0x566e, 0x080c, 0x650d, 0x2001, 0xaf9e,
-	0x2003, 0x0000, 0x080c, 0x569a, 0x0040, 0x080c, 0x485e, 0x0028,
-	0x6003, 0x0004, 0x2009, 0x3755, 0x0010, 0x0804, 0x2dcc, 0x2001,
-	0x0100, 0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004,
-	0xa084, 0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817,
-	0x2091, 0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x2df1,
-	0x2069, 0xad51, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc,
-	0x0118, 0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0xa006, 0x080c, 0x26c0,
-	0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x1178, 0x2001, 0xaf9e,
-	0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085, 0x0001,
-	0x080c, 0x5793, 0x080c, 0x569a, 0x0020, 0x080c, 0x491f, 0x080c,
-	0x485e, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f,
-	0x1110, 0x0804, 0x2df1, 0x6184, 0x81ff, 0x0198, 0x703f, 0x0000,
-	0x2001, 0xb3c0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x3c49, 0x701b, 0x2dca, 0x012e,
-	0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0xb3c0, 0x20a9, 0x0040,
-	0x20a1, 0xb3c0, 0x2019, 0xffff, 0x43a4, 0x654c, 0xa588, 0x2be6,
-	0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100,
-	0xa506, 0x01a8, 0x080c, 0x4cdc, 0x1190, 0x6014, 0x821c, 0x0238,
-	0xa398, 0xb3c0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0038, 0xa398,
-	0xb3c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108,
-	0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007, 0x2d0c, 0xa105,
-	0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb3c0,
-	0x080c, 0x48be, 0x0804, 0x37b0, 0x080c, 0x3c2a, 0x0904, 0x2df4,
-	0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x2df1, 0x2001, 0xad52, 0x2004, 0xd0b4, 0x01f0, 0x6000, 0xd08c,
-	0x11d8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x970b, 0x1120, 0x2009,
-	0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3830, 0x0005,
-	0x080c, 0x3c2a, 0x0904, 0x2df4, 0x20a9, 0x002b, 0x2c98, 0xade8,
-	0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098,
-	0xad80, 0x0006, 0x20a0, 0x080c, 0x48be, 0x20a9, 0x0004, 0xac80,
-	0x000a, 0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x48be, 0x2d00,
-	0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
-	0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4, 0x080c,
-	0x4eab, 0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x7828, 0xa08a,
-	0x1000, 0x1a04, 0x2df4, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x080c,
-	0x4f0d, 0x0904, 0x2df1, 0x2019, 0x0004, 0x080c, 0x4ebd, 0x7924,
-	0x810f, 0x7a28, 0x0011, 0x0804, 0x2dcc, 0xa186, 0x00ff, 0x0110,
-	0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xad00, 0x644c, 0x2400,
-	0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c,
-	0x4cdc, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c,
-	0x6519, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904,
-	0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4eb4, 0x0804,
-	0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c1a, 0x0904, 0x2df4,
-	0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c, 0x4ea2, 0x0804, 0x2dcc,
-	0x6100, 0x0804, 0x2dcc, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x2001,
-	0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x00d6, 0xace8,
-	0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
-	0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
-	0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2dcc, 0x7824, 0xa09c,
-	0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2df1, 0x624c, 0xa294, 0x00ff,
-	0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0xad40, 0x2009,
-	0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x81ff,
-	0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
-	0x00ce, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x080c, 0x96b7, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3919,
-	0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0xad80, 0x000e,
-	0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49,
-	0xa006, 0x080c, 0x26c0, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff,
-	0x0118, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x574f, 0x0110, 0x080c,
-	0x491f, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2df4, 0x7924, 0xa18c,
-	0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04,
-	0x2df4, 0x2100, 0x080c, 0x268a, 0x0026, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c,
-	0x574f, 0x1178, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00,
-	0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a,
-	0x00a0, 0x2061, 0x0100, 0x2001, 0xad14, 0x2004, 0xa084, 0x00ff,
-	0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
-	0x002d, 0x2011, 0x4883, 0x080c, 0x6593, 0x7924, 0xa18c, 0xff00,
-	0x810f, 0x080c, 0x574f, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c,
-	0x387d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x2dcc, 0x7924, 0xa18c,
-	0xff00, 0x810f, 0x00c6, 0x080c, 0x4c80, 0x2c08, 0x00ce, 0x1904,
-	0x2df4, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x2df1, 0x60d0, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005,
-	0x0804, 0x2df1, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x2df1, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46,
-	0x701b, 0x39bb, 0x0005, 0x2009, 0x0080, 0x080c, 0x4cdc, 0x1130,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a,
-	0x0804, 0x2dce, 0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c,
-	0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3a32,
-	0xa0be, 0x0112, 0x0904, 0x3a32, 0xa0be, 0x0113, 0x0904, 0x3a32,
-	0xa0be, 0x0114, 0x0904, 0x3a32, 0xa0be, 0x0117, 0x0904, 0x3a32,
-	0xa0be, 0x011a, 0x0904, 0x3a32, 0xa0be, 0x011c, 0x0904, 0x3a32,
-	0xa0be, 0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171,
-	0x05c8, 0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830,
-	0x8007, 0x6832, 0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213,
-	0x0528, 0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be,
-	0x021a, 0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300,
-	0x01c8, 0x00de, 0x0804, 0x2df4, 0xad80, 0x0010, 0x20a9, 0x0007,
-	0x080c, 0x3a78, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3a78,
-	0x0048, 0xad80, 0x000c, 0x080c, 0x3a86, 0x0050, 0xad80, 0x000e,
-	0x080c, 0x3a86, 0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3a78,
-	0x00c6, 0x080c, 0x3c05, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837,
-	0x0119, 0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b,
-	0x697e, 0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996,
-	0x689b, 0x0000, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x96d3, 0x1120,
-	0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3a6f,
-	0x0005, 0x00ce, 0x00de, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6820,
-	0xa086, 0x8001, 0x1904, 0x2dcc, 0x2009, 0x0004, 0x0804, 0x2df1,
-	0x0016, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108,
-	0x280a, 0x8108, 0x1f04, 0x3a7a, 0x001e, 0x0005, 0x0016, 0x00a6,
-	0x00b6, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000,
-	0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a,
-	0x00be, 0x00ae, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x2df1, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d0,
-	0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182, 0x00ff,
-	0x1a04, 0x2df4, 0x7a2c, 0x7b28, 0x606c, 0xa306, 0x1140, 0x6070,
-	0xa24e, 0x0904, 0x2df4, 0xa9cc, 0xff00, 0x0904, 0x2df4, 0x00c6,
-	0x080c, 0x3b58, 0x2c68, 0x00ce, 0x0538, 0xa0c6, 0x4000, 0x1180,
-	0x00c6, 0x0006, 0x2d60, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108,
-	0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce, 0x0088,
-	0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008, 0x1118,
-	0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010, 0x2001,
-	0x4006, 0x2020, 0x0804, 0x2dce, 0x2d00, 0x7022, 0x0016, 0x00b6,
-	0x00c6, 0x00e6, 0x2c70, 0x080c, 0x8022, 0x05d8, 0x2d00, 0x601a,
-	0x080c, 0x9956, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x3c05,
-	0x00ce, 0x2b70, 0x1150, 0x080c, 0x8078, 0x00ee, 0x00ce, 0x00be,
-	0x001e, 0x2009, 0x0002, 0x0804, 0x2df1, 0x6837, 0x0000, 0x683b,
-	0x0000, 0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c,
-	0x0108, 0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9,
-	0x012e, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001,
-	0x0002, 0x080c, 0x4c30, 0x2009, 0x0002, 0x080c, 0x80a7, 0xa085,
-	0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3b3f, 0x0005, 0x6830,
-	0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204,
-	0xa294, 0x00ff, 0x0804, 0x2df1, 0x2009, 0x0000, 0x080c, 0x4f6e,
-	0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x2dcc,
-	0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001, 0xad34, 0x2004, 0xd0ac,
-	0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34, 0x0030,
-	0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xaeb4, 0x2e04, 0xa005,
-	0x1130, 0x2100, 0xa406, 0x1548, 0x2428, 0xc5fd, 0x0430, 0x2068,
-	0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600, 0xa206, 0x1190,
-	0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0540, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1510, 0x2001, 0x4000, 0x0400, 0x2001,
-	0x4007, 0x00e8, 0x2400, 0xa106, 0x1140, 0x6e14, 0x87ff, 0x1110,
-	0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04,
-	0x3b6e, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001,
-	0x0030, 0x080c, 0x4c80, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005,
-	0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x080c, 0x3c05,
-	0x0904, 0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824,
-	0xa005, 0x0904, 0x2df4, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004,
-	0x1a04, 0x2df4, 0x2010, 0x2d18, 0x080c, 0x2a8c, 0x0904, 0x2df1,
-	0x7007, 0x0003, 0x701b, 0x3bd5, 0x0005, 0x6830, 0xa086, 0x0100,
-	0x0904, 0x2df1, 0x0804, 0x2dcc, 0x7924, 0xa18c, 0xff00, 0x810f,
-	0x60d0, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2df4, 0xa182,
-	0x00ff, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x080c, 0x95c6,
-	0x1188, 0xa190, 0xae34, 0x2204, 0xa065, 0x0160, 0x080c, 0x493a,
-	0x2001, 0xad34, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e,
-	0x0804, 0x2dcc, 0x012e, 0x0804, 0x2df1, 0x080c, 0x15d9, 0x0188,
-	0xa006, 0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016,
-	0x0030, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80,
-	0x000d, 0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
-	0x1130, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066,
-	0x8cff, 0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x4cdc,
-	0x1128, 0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff,
-	0x0005, 0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c,
-	0x15f0, 0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001,
-	0x0010, 0x2031, 0x0000, 0x2061, 0xadd1, 0x6606, 0x6112, 0x600e,
-	0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007,
-	0x0002, 0x701b, 0x2dcc, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000,
-	0x2079, 0x0000, 0x2001, 0xad8f, 0x2004, 0xa005, 0x1168, 0x0e04,
-	0x3c74, 0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b,
-	0x0001, 0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071,
-	0xad81, 0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078,
-	0x7030, 0xa0e0, 0x0004, 0xac82, 0xadd1, 0x0210, 0x2061, 0xad91,
-	0x2c00, 0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262,
-	0x6306, 0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005,
-	0x00e6, 0x2071, 0xad81, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091,
-	0x8000, 0x0e04, 0x3ccb, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084,
-	0x1508, 0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826,
-	0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001,
-	0x703a, 0xa005, 0x1130, 0x7033, 0xad91, 0x7037, 0xad91, 0x00ce,
-	0x0048, 0xac80, 0x0004, 0xa0fa, 0xadd1, 0x0210, 0x2001, 0xad91,
-	0x7036, 0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001,
-	0xad52, 0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3c5c,
-	0x002e, 0x0005, 0x81ff, 0x1904, 0x2df1, 0x0126, 0x2091, 0x8000,
-	0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x574f, 0x1178,
-	0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001,
-	0xa085, 0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x0010, 0x080c,
-	0x485e, 0x012e, 0x0804, 0x2dcc, 0x7824, 0x2008, 0xa18c, 0xfffd,
-	0x1128, 0x61dc, 0xa10d, 0x61de, 0x0804, 0x2dcc, 0x0804, 0x2df4,
-	0x81ff, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x1904, 0x2df1,
-	0x2001, 0xad52, 0x2004, 0xd0ac, 0x1904, 0x2df1, 0x080c, 0x3c2a,
-	0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120,
-	0x7828, 0xa005, 0x0904, 0x2dcc, 0x00c6, 0x080c, 0x3c05, 0x00ce,
-	0x0904, 0x2df1, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x080c, 0x979c, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
-	0x3d3a, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2df1, 0x0804,
-	0x2dcc, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1,
-	0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c05, 0x0904,
-	0x2df1, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f,
-	0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x4cdc, 0x1904,
-	0x3db4, 0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4,
-	0xff00, 0xa8c6, 0x0600, 0x1904, 0x3db4, 0x2001, 0xad52, 0x2004,
-	0xd0ac, 0x1128, 0x080c, 0x4f6e, 0x1110, 0xd79c, 0x05e8, 0xd794,
-	0x1110, 0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9,
-	0x0004, 0x53a3, 0x080c, 0x3a86, 0xd794, 0x0148, 0xac80, 0x000a,
-	0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3a86, 0x21a2,
-	0xd794, 0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002,
-	0x53a3, 0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098,
-	0x3400, 0x20a9, 0x0002, 0x53a3, 0x080c, 0x3a78, 0xac80, 0x0026,
-	0x2098, 0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110,
-	0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xad34, 0x2004,
-	0xd0ac, 0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186,
-	0x0100, 0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118,
-	0xa686, 0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x3d5d,
-	0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x702f, 0x0001,
-	0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xadd1, 0x6007,
-	0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
-	0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b, 0x3df0, 0x0005,
-	0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031,
-	0x0000, 0x2061, 0xadd1, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804,
-	0x3d5d, 0x7120, 0x810b, 0x0804, 0x2dcc, 0x2029, 0x007e, 0x7924,
-	0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020,
-	0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa184, 0x00ff, 0xa0e2,
-	0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa284, 0xff00,
-	0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4,
-	0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04,
-	0x2df4, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2df4,
-	0xa502, 0x0a04, 0x2df4, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04,
-	0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0xff00, 0x8007, 0xa0e2,
-	0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0xa484, 0x00ff,
-	0xa0e2, 0x0020, 0x0a04, 0x2df4, 0xa502, 0x0a04, 0x2df4, 0x2061,
-	0xafa6, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2dcc, 0x0006,
-	0x2001, 0xad52, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001,
-	0xad71, 0x2004, 0xd0bc, 0x000e, 0x0005, 0x6164, 0x7a24, 0x6300,
-	0x82ff, 0x1118, 0x7926, 0x0804, 0x2dcc, 0x83ff, 0x1904, 0x2df4,
-	0x2001, 0xfff0, 0xa200, 0x1a04, 0x2df4, 0x2019, 0xffff, 0x6068,
-	0xa302, 0xa200, 0x0a04, 0x2df4, 0x7926, 0x6266, 0x0804, 0x2dcc,
-	0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1904, 0x2df1, 0x7c28,
-	0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x2009,
-	0x0000, 0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
-	0x0003, 0x7026, 0x20a0, 0xa1e0, 0xae34, 0x2c64, 0x8cff, 0x01b8,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084,
-	0xff00, 0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010,
-	0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108,
-	0xa182, 0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff,
-	0x1120, 0x7120, 0x810c, 0x0804, 0x2dcc, 0x702f, 0x0001, 0x711e,
-	0x7020, 0xa300, 0x7022, 0x2061, 0xadd1, 0x6007, 0x0000, 0x6312,
-	0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c,
-	0x1624, 0x7007, 0x0002, 0x701b, 0x3ee6, 0x0005, 0x702c, 0xa005,
-	0x1168, 0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xadd1,
-	0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3ea3, 0x7120, 0x810c,
-	0x0804, 0x2dcc, 0x81ff, 0x1904, 0x2df1, 0x60d0, 0xd0ac, 0x1118,
-	0xd09c, 0x0904, 0x2df1, 0x080c, 0x3c05, 0x0904, 0x2df1, 0x7924,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3c46, 0x701b, 0x3f11,
-	0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148,
-	0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804,
-	0x2df4, 0x6820, 0x6924, 0x080c, 0x2676, 0x1510, 0x080c, 0x4c80,
-	0x11f8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3c05,
-	0x01b8, 0x080c, 0x3c05, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c,
-	0x96ef, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b, 0x3f4b, 0x0005,
-	0x00de, 0x0804, 0x2df1, 0x7120, 0x080c, 0x2bc9, 0x6820, 0xa086,
-	0x8001, 0x0904, 0x2df1, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002,
-	0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x48be, 0x000e,
-	0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xadd1,
-	0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018,
-	0xa7c6, 0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2df4, 0x2009,
-	0x0004, 0x0804, 0x3c49, 0xa7c6, 0x7200, 0x1904, 0x2df4, 0xa6c2,
-	0x0054, 0x0a04, 0x2df4, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a,
-	0x642e, 0x6532, 0x2c10, 0x080c, 0x1624, 0x7007, 0x0002, 0x701b,
-	0x3f92, 0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004,
-	0xa080, 0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c,
-	0x48be, 0x000e, 0x2009, 0x002a, 0x2061, 0xadd1, 0x6224, 0x6328,
-	0x642c, 0x6530, 0x0804, 0x3c49, 0x81ff, 0x1904, 0x2df1, 0x080c,
-	0x3c1a, 0x0904, 0x2df4, 0x080c, 0x4d96, 0x0904, 0x2df1, 0x080c,
-	0x4ec6, 0x0804, 0x2dcc, 0x7824, 0xd084, 0x0904, 0x3804, 0x080c,
-	0x3c2a, 0x0904, 0x2df4, 0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120,
-	0x2009, 0x0002, 0x0804, 0x2df1, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005, 0x1508,
-	0x2001, 0xad52, 0x2004, 0xd0b4, 0x0904, 0x3834, 0x6000, 0xd08c,
-	0x1904, 0x3834, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c,
-	0x970b, 0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003,
-	0x701b, 0x3ff3, 0x0005, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x0804,
-	0x3834, 0x2009, 0xad30, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x2df1, 0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x0120,
-	0x2009, 0x0007, 0x0804, 0x2df1, 0x2001, 0xad52, 0x2004, 0xd0ac,
-	0x0120, 0x2009, 0x0008, 0x0804, 0x2df1, 0x609c, 0xd0a4, 0x1118,
-	0xd0ac, 0x1904, 0x3834, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x080c, 0x979c, 0x1120, 0x2009, 0x0003, 0x0804,
-	0x2df1, 0x7007, 0x0003, 0x701b, 0x402e, 0x0005, 0x6830, 0xa086,
-	0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x2df1, 0x080c, 0x3c2a,
-	0x0904, 0x2df4, 0x0804, 0x3fd8, 0x81ff, 0x2009, 0x0001, 0x1904,
-	0x2df1, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x2df1,
-	0x2001, 0xad52, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x2df1,
-	0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x2009, 0x0009, 0x1904, 0x2df1, 0x00c6, 0x080c, 0x3c05,
-	0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1, 0x6837, 0x0000, 0x6833,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c,
-	0x00ff, 0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956,
-	0x0048, 0xa28e, 0x0100, 0x1904, 0x2df4, 0xc0e5, 0x6853, 0x0000,
-	0x6857, 0x0000, 0x683e, 0x080c, 0x9957, 0x2009, 0x0003, 0x0904,
-	0x2df1, 0x7007, 0x0003, 0x701b, 0x408e, 0x0005, 0x6830, 0xa086,
-	0x0100, 0x2009, 0x0004, 0x0904, 0x2df1, 0x0804, 0x2dcc, 0x81ff,
-	0x2009, 0x0001, 0x1904, 0x2df1, 0x6000, 0xa086, 0x0003, 0x2009,
-	0x0007, 0x1904, 0x2df1, 0x080c, 0x3c2a, 0x0904, 0x2df4, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x2df1,
-	0x00c6, 0x080c, 0x3c05, 0x00ce, 0x2009, 0x0002, 0x0904, 0x2df1,
-	0xad80, 0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x080c, 0x3c46, 0x701b, 0x40c5, 0x0005, 0x00d6, 0xade8, 0x000f,
-	0x6800, 0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808,
-	0xa084, 0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x2df4, 0x00de,
-	0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6,
-	0x080c, 0x3c2a, 0x1118, 0x00ce, 0x0804, 0x2df4, 0x080c, 0x99a6,
-	0x2009, 0x0003, 0x00ce, 0x0904, 0x2df1, 0x7007, 0x0003, 0x701b,
-	0x40f2, 0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904,
-	0x2df1, 0x0804, 0x2dcc, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x2df1, 0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804,
-	0x2df1, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c,
-	0x4cdc, 0x1904, 0x2df4, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x2df1,
-	0x00c6, 0x080c, 0x3c05, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x2df1, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9726,
-	0x1120, 0x2009, 0x0003, 0x0804, 0x2df1, 0x7007, 0x0003, 0x701b,
-	0x413a, 0x0005, 0x6808, 0x8007, 0xa086, 0x0100, 0x1120, 0x2009,
-	0x0004, 0x0804, 0x2df1, 0x68b0, 0x6836, 0x6810, 0x8007, 0xa084,
-	0x00ff, 0x808e, 0x6814, 0x8007, 0xa084, 0x00ff, 0x8086, 0xa080,
-	0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0804, 0x3c49, 0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x2df1, 0x7924, 0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff,
-	0x0110, 0x0804, 0x2df4, 0x2009, 0x001a, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x080c, 0x3c46, 0x701b, 0x4176, 0x0005, 0xad80, 0x000d,
-	0x2098, 0x20a9, 0x001a, 0x20a1, 0xafad, 0x53a3, 0x0804, 0x2dcc,
-	0x080c, 0x3c05, 0x1120, 0x2009, 0x0002, 0x0804, 0x2df1, 0x7924,
-	0xa194, 0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804,
-	0x2df4, 0x2099, 0xafad, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009,
-	0x001a, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3c49, 0x7824,
-	0xa08a, 0x1000, 0x1a04, 0x2df4, 0x0126, 0x2091, 0x8000, 0x8003,
-	0x800b, 0x810b, 0xa108, 0x00c6, 0x2061, 0xafda, 0x6142, 0x00ce,
-	0x012e, 0x0804, 0x2dcc, 0x00c6, 0x080c, 0x574f, 0x1188, 0x2001,
-	0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0xa085,
-	0x0001, 0x080c, 0x5793, 0x080c, 0x569a, 0x080c, 0x14f6, 0x0038,
-	0x2061, 0xad00, 0x6030, 0xc09d, 0x6032, 0x080c, 0x485e, 0x00ce,
-	0x0005, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
-	0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x4348, 0x0068,
-	0xd08c, 0x0118, 0x080c, 0x4269, 0x0040, 0xd094, 0x0118, 0x080c,
-	0x423a, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e,
-	0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e,
-	0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0,
-	0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0xa294,
-	0xff00, 0xa296, 0xf700, 0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240,
-	0xa295, 0x0100, 0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7,
-	0x080c, 0x48de, 0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040,
-	0x6042, 0x6043, 0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b7,
-	0x0000, 0x70d3, 0x0000, 0x2009, 0xb3c0, 0x200b, 0x0000, 0x7087,
-	0x0000, 0x707b, 0x000a, 0x2009, 0x000a, 0x2011, 0x4814, 0x080c,
-	0x6593, 0x0005, 0x0156, 0x2001, 0xad73, 0x2004, 0xd08c, 0x0110,
-	0x704f, 0xffff, 0x7078, 0xa005, 0x1510, 0x2011, 0x4814, 0x080c,
-	0x650d, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9,
-	0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04, 0x4251, 0x6242, 0x708b,
-	0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242,
-	0x0030, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e,
-	0x0005, 0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c,
-	0x14f6, 0x0005, 0x4275, 0x42c5, 0x4347, 0x00f6, 0x707f, 0x0001,
-	0x20e1, 0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x22f8, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x2079, 0xb200, 0x207b, 0x2200, 0x7807,
-	0x00ef, 0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817,
-	0x0000, 0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827,
-	0xffff, 0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0xb20c, 0x207b,
-	0x1101, 0x7807, 0x0000, 0x2099, 0xad05, 0x20a1, 0xb20e, 0x20a9,
-	0x0004, 0x53a3, 0x2079, 0xb212, 0x207b, 0x0000, 0x7807, 0x0000,
-	0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3,
-	0x000c, 0x600f, 0x0000, 0x080c, 0x4845, 0x00fe, 0x7083, 0x0000,
-	0x6043, 0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083,
-	0x0000, 0xa025, 0x0904, 0x432f, 0x6020, 0xd0b4, 0x1904, 0x432d,
-	0x7190, 0x81ff, 0x0904, 0x431d, 0xa486, 0x000c, 0x1904, 0x4328,
-	0xa480, 0x0018, 0x8004, 0x20a8, 0x2011, 0xb280, 0x2019, 0xb200,
-	0x220c, 0x2304, 0xa106, 0x11b8, 0x8210, 0x8318, 0x1f04, 0x42e0,
-	0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006,
-	0x707f, 0x0002, 0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x481b,
-	0x080c, 0x6593, 0x0490, 0x2069, 0xb280, 0x6930, 0xa18e, 0x1101,
-	0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118,
-	0x6804, 0xa005, 0x0190, 0x2011, 0xb28e, 0x2019, 0xad05, 0x20a9,
-	0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210, 0x8318,
-	0x1f04, 0x4311, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6,
-	0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00de, 0x0005, 0x6040,
-	0xa085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c,
-	0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x0c30, 0x0005,
-	0x7088, 0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x14f6,
-	0x0005, 0x437b, 0x438a, 0x43b2, 0x43cb, 0x43ef, 0x4417, 0x443b,
-	0x446c, 0x4490, 0x44b8, 0x44ef, 0x4517, 0x4533, 0x4549, 0x4569,
-	0x457c, 0x4584, 0x45b1, 0x45d5, 0x45fd, 0x4621, 0x4652, 0x468f,
-	0x46be, 0x46da, 0x4719, 0x4739, 0x4752, 0x4753, 0x00c6, 0x2061,
-	0xad00, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9,
-	0x6006, 0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043,
-	0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x481b, 0x080c,
-	0x6593, 0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1508, 0x6043,
-	0x0000, 0x6020, 0xd0b4, 0x11e0, 0x2079, 0xb280, 0x7a30, 0xa296,
-	0x1102, 0x11a0, 0x7834, 0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128,
-	0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x2011, 0x481b, 0x080c,
-	0x650d, 0x708b, 0x0010, 0x080c, 0x4584, 0x0010, 0x080c, 0x485e,
-	0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x481b,
-	0x080c, 0x650d, 0x080c, 0x48c6, 0x20a3, 0x1102, 0x20a3, 0x0000,
-	0x20a9, 0x000a, 0x20a3, 0x0000, 0x1f04, 0x43c2, 0x60c3, 0x0014,
-	0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011,
-	0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280,
-	0x7a30, 0xa296, 0x1102, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38,
-	0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b,
-	0x0004, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
-	0x0005, 0x080c, 0x48c6, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430,
-	0x2011, 0xb28e, 0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148,
-	0x714c, 0xa186, 0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c,
-	0x48f5, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6,
-	0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
-	0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1103, 0x1178,
-	0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
-	0x1110, 0x70b7, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010, 0x080c,
-	0x485e, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x48c6, 0x20a3,
-	0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917,
-	0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170,
-	0xa180, 0x2be6, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df,
-	0x0128, 0x080c, 0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008,
-	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0,
-	0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8, 0x2079,
-	0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005, 0x1160,
-	0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
-	0x708b, 0x0008, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005,
-	0x708b, 0x0009, 0x080c, 0x48c6, 0x20a3, 0x1105, 0x20a3, 0x0100,
-	0x3430, 0x080c, 0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c,
-	0x4754, 0x1170, 0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008,
-	0x2099, 0xb28e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005,
-	0x00f6, 0x7080, 0xa005, 0x0588, 0x2011, 0x481b, 0x080c, 0x650d,
-	0xa086, 0x0014, 0x1540, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1105,
-	0x1510, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc,
-	0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x000a,
-	0x00b1, 0x0098, 0xa005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b4,
-	0xa005, 0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e,
-	0x080c, 0x4569, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b,
-	0x000b, 0x2011, 0xb20e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff,
-	0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x48c6,
-	0x20a3, 0x1106, 0x20a3, 0x0000, 0x080c, 0x4917, 0x0118, 0x2013,
-	0x0000, 0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9,
-	0x0042, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x4845, 0x0005, 0x00f6,
-	0x7080, 0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086,
-	0x0084, 0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138,
-	0x7834, 0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c,
-	0x485e, 0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x48c6, 0x20a3,
-	0x1107, 0x20a3, 0x0000, 0x2099, 0xb28e, 0x20a9, 0x0040, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
-	0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
-	0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
-	0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
-	0x48b8, 0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
-	0x0005, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f,
-	0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011,
-	0x481b, 0x080c, 0x6501, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011,
-	0x481b, 0x080c, 0x650d, 0x0005, 0x708b, 0x0011, 0x080c, 0x4917,
-	0x1188, 0x716c, 0x81ff, 0x0170, 0x2009, 0x0000, 0x7070, 0xa084,
-	0x00ff, 0x080c, 0x2676, 0xa186, 0x0080, 0x0120, 0x2011, 0xb28e,
-	0x080c, 0x47df, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
-	0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
-	0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4845,
-	0x0005, 0x00f6, 0x7080, 0xa005, 0x01f0, 0x2011, 0x481b, 0x080c,
-	0x650d, 0xa086, 0x0014, 0x11a8, 0x2079, 0xb280, 0x7a30, 0xa296,
-	0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
-	0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001, 0x708b, 0x0012, 0x0029,
-	0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c,
-	0x48d2, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xb28e,
-	0x080c, 0x4917, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186,
-	0xffff, 0x0128, 0x080c, 0x47df, 0x0110, 0x080c, 0x48f5, 0x20a9,
-	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x4845, 0x0005, 0x00f6, 0x7080, 0xa005,
-	0x01f0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0014, 0x11a8,
-	0x2079, 0xb280, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005,
-	0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7,
-	0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
-	0x0005, 0x708b, 0x0015, 0x080c, 0x48d2, 0x20a3, 0x1104, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0xb28e, 0x080c, 0x4917, 0x11a8, 0x7074,
-	0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2be6,
-	0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x47df, 0x0128, 0x080c,
-	0x3e66, 0x0110, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2298, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
-	0x4845, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05b8, 0x2011, 0x481b,
-	0x080c, 0x650d, 0xa086, 0x0014, 0x1570, 0x2079, 0xb280, 0x7a30,
-	0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148,
-	0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005, 0x1110, 0x70b7, 0x0001,
-	0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b4, 0xa005,
-	0x1110, 0x70b7, 0x0001, 0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0138,
-	0x2001, 0xad73, 0x2004, 0xd0a4, 0x1110, 0x70d3, 0x0008, 0x708b,
-	0x0016, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe, 0x0005, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x2099, 0xb280, 0x20a1, 0x020b, 0x20a9,
-	0x000e, 0x53a6, 0x3430, 0x2011, 0xb28e, 0x708b, 0x0017, 0x080c,
-	0x4917, 0x1150, 0x7074, 0xa005, 0x1138, 0x080c, 0x4754, 0x1170,
-	0xa085, 0x0001, 0x080c, 0x26c0, 0x20a9, 0x0008, 0x2099, 0xb28e,
-	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x080c, 0x4845, 0x0010, 0x080c, 0x436e, 0x0005, 0x00f6, 0x7080,
-	0xa005, 0x01b0, 0x2011, 0x481b, 0x080c, 0x650d, 0xa086, 0x0084,
-	0x1168, 0x2079, 0xb280, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
-	0xa005, 0x1120, 0x708b, 0x0018, 0x0029, 0x0010, 0x080c, 0x485e,
-	0x00fe, 0x0005, 0x708b, 0x0019, 0x080c, 0x48d2, 0x20a3, 0x1106,
-	0x20a3, 0x0000, 0x3430, 0x2099, 0xb28e, 0x2039, 0xb20e, 0x27a0,
-	0x20a9, 0x0040, 0x53a3, 0x080c, 0x4917, 0x11e8, 0x2728, 0x2514,
-	0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
-	0xa205, 0x202a, 0x7050, 0x2310, 0x8214, 0xa2a0, 0xb20e, 0x2414,
-	0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff,
-	0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4845,
-	0x0005, 0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x481b, 0x080c,
-	0x650d, 0xa086, 0x0084, 0x1188, 0x2079, 0xb280, 0x7a30, 0xa296,
-	0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c,
-	0x48b8, 0x708b, 0x001a, 0x0029, 0x0010, 0x080c, 0x485e, 0x00fe,
-	0x0005, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
-	0xb280, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007,
-	0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c,
-	0x4845, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xad52,
-	0x252c, 0x20a9, 0x0008, 0x2041, 0xb20e, 0x28a0, 0x2099, 0xb28e,
-	0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011,
-	0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4,
-	0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4769, 0x0804, 0x47d7,
-	0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020,
-	0xa1a6, 0x3fff, 0x0904, 0x47d7, 0xa18d, 0xc000, 0x20a9, 0x0010,
-	0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4,
-	0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319,
-	0x0008, 0x8318, 0x1f04, 0x478f, 0x04d0, 0x23a8, 0x2021, 0x0001,
-	0x8426, 0x8425, 0x1f04, 0x47a1, 0x2328, 0x8529, 0xa2be, 0x0007,
-	0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8,
-	0xa5a8, 0x0010, 0x1f04, 0x47b0, 0x754e, 0xa5c8, 0x2be6, 0x292d,
-	0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c,
-	0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405,
-	0x201a, 0x7077, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006,
-	0x0018, 0xa006, 0x080c, 0x14f6, 0x009e, 0x008e, 0x0005, 0x2118,
-	0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420,
-	0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421,
-	0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8,
-	0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x714e, 0xa1a0,
-	0x2be6, 0x242d, 0xa5ac, 0x00ff, 0x7572, 0x6532, 0x6536, 0x0016,
-	0x2508, 0x080c, 0x26a0, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7077,
-	0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x707b,
-	0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071,
-	0x0140, 0x080c, 0x7834, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003,
-	0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000, 0x2071, 0xad22,
-	0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c,
-	0x48de, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42,
-	0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x2011, 0xafd1, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1,
-	0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x782b, 0x2009,
-	0x07d0, 0x2011, 0x481b, 0x080c, 0x6593, 0x0005, 0x0016, 0x0026,
-	0x00c6, 0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x48de,
-	0x2061, 0xafda, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xad00,
-	0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010,
-	0x2009, 0x002d, 0x2011, 0x4883, 0x080c, 0x6501, 0x012e, 0x00ce,
-	0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000,
-	0x2071, 0x0100, 0x080c, 0x7834, 0x2071, 0x0140, 0x7004, 0xa084,
-	0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x5757,
-	0x01a8, 0x080c, 0x5775, 0x1190, 0x2001, 0xaf9d, 0x2003, 0xaaaa,
-	0x0016, 0x080c, 0x2744, 0x2001, 0xaf8e, 0x2102, 0x001e, 0x2001,
-	0xaf9e, 0x2003, 0x0000, 0x080c, 0x569a, 0x0030, 0x2001, 0x0001,
-	0x080c, 0x261e, 0x080c, 0x485e, 0x012e, 0x000e, 0x00ee, 0x0005,
-	0x20a9, 0x0040, 0x20a1, 0xb3c0, 0x2099, 0xb28e, 0x3304, 0x8007,
-	0x20a2, 0x9398, 0x94a0, 0x1f04, 0x48be, 0x0005, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x2099, 0xb200, 0x20a1, 0x020b, 0x20a9, 0x000c,
-	0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xb280,
-	0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006,
-	0x2061, 0x0100, 0x810f, 0x2001, 0xad30, 0x2004, 0xa005, 0x1138,
-	0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
-	0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001,
-	0xad52, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
-	0x080c, 0xa96c, 0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019,
-	0x002a, 0x2009, 0x0000, 0x080c, 0x2aac, 0x004e, 0x001e, 0x0005,
-	0x080c, 0x485e, 0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006,
-	0x2001, 0xad0c, 0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006,
-	0x0016, 0x0126, 0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d,
-	0x0006, 0x2102, 0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9,
-	0x00ff, 0x2009, 0xae34, 0xa006, 0x200a, 0x8108, 0x1f04, 0x4934,
-	0x015e, 0x0005, 0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069,
-	0xad51, 0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012,
-	0xa198, 0x2be6, 0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004,
-	0xac98, 0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a,
-	0x23a0, 0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a,
-	0x605e, 0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a,
-	0x607e, 0x6082, 0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a,
-	0x609e, 0x60ae, 0x61a2, 0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c,
-	0x15f0, 0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0,
-	0x60ab, 0x0000, 0x00de, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c,
-	0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x014e, 0x013e, 0x015e,
-	0x003e, 0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0x6944, 0x6e48,
-	0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04, 0x4a49, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x00ff, 0x1a04, 0x4a4e, 0x2001, 0xad0c, 0x2004,
-	0xa084, 0x0003, 0x01c0, 0x2001, 0xad0c, 0x2004, 0xd084, 0x1904,
-	0x4a31, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904, 0x4a31, 0x6004,
-	0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a31, 0x6000, 0xd0c4,
-	0x0904, 0x4a31, 0x0068, 0xa188, 0xae34, 0x2104, 0xa065, 0x0904,
-	0x4a15, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x1904, 0x4a1a,
-	0x60a4, 0xa00d, 0x0118, 0x080c, 0x4ef9, 0x05d0, 0x60a8, 0xa00d,
-	0x0188, 0x080c, 0x4f43, 0x1170, 0x694c, 0xd1fc, 0x1118, 0x080c,
-	0x4c11, 0x0448, 0x080c, 0x4bd3, 0x694c, 0xd1ec, 0x1520, 0x080c,
-	0x4ded, 0x0408, 0x694c, 0xa184, 0xa000, 0x0178, 0xd1ec, 0x0140,
-	0xd1fc, 0x0118, 0x080c, 0x4dfc, 0x0028, 0x080c, 0x4dfc, 0x0028,
-	0xd1fc, 0x0118, 0x080c, 0x4bd3, 0x0070, 0x6050, 0xa00d, 0x0130,
-	0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0028, 0x2d00, 0x6052,
-	0x604e, 0x6803, 0x0000, 0x080c, 0x67c5, 0xa006, 0x012e, 0x0005,
-	0x2001, 0x0005, 0x2009, 0x0000, 0x04e8, 0x2001, 0x0028, 0x2009,
-	0x0000, 0x04c0, 0xa082, 0x0006, 0x12a0, 0x2001, 0xad34, 0x2004,
-	0xd0ac, 0x1160, 0x60a0, 0xd0bc, 0x1148, 0x6100, 0xd1fc, 0x0904,
-	0x49d0, 0x2001, 0x0029, 0x2009, 0x1000, 0x0420, 0x2001, 0x0028,
-	0x00a8, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004,
-	0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029,
-	0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0060, 0x2009, 0x0000,
-	0x0048, 0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029,
-	0x2009, 0x0000, 0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x6844, 0x8007, 0xa084, 0x00ff, 0x2008, 0xa182, 0x00ff,
-	0x1a04, 0x4aa8, 0xa188, 0xae34, 0x2104, 0xa065, 0x01c0, 0x6004,
-	0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8, 0x2c70, 0x080c, 0x8022,
-	0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012, 0x600b, 0xffff, 0x601f,
-	0x000a, 0x2009, 0x0003, 0x080c, 0x80a7, 0xa006, 0x0460, 0x2001,
-	0x0028, 0x0440, 0xa082, 0x0006, 0x1298, 0x2001, 0xad34, 0x2004,
-	0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140, 0x6100, 0xd1fc, 0x09e8,
-	0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090,
-	0x2009, 0xad0c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010,
-	0x2001, 0x0029, 0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c,
-	0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2011, 0x0000,
-	0x2079, 0xad00, 0x6944, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
-	0x1a04, 0x4b77, 0x2001, 0xad0c, 0x2004, 0xa084, 0x0003, 0x1904,
-	0x4b65, 0x080c, 0x4cdc, 0x1180, 0x6004, 0xa084, 0x00ff, 0xa082,
-	0x0006, 0x1250, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1904, 0x4b60,
-	0x60a0, 0xd0bc, 0x1904, 0x4b60, 0x6864, 0xa0c6, 0x006f, 0x0118,
-	0x2008, 0x0804, 0x4b28, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f,
-	0x78d0, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff,
-	0x16b8, 0x6a70, 0x6b6c, 0x786c, 0xa306, 0x1160, 0x7870, 0xa24e,
-	0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208,
-	0x2310, 0x0430, 0x080c, 0x3b58, 0x2c70, 0x0550, 0x2009, 0x0000,
-	0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c,
-	0x4f6e, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e,
-	0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
-	0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
-	0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0458,
-	0x080c, 0x8022, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011,
-	0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0x9956, 0x2d00, 0x6012,
-	0x601f, 0x0001, 0xa006, 0xd88c, 0x0110, 0x2001, 0x4000, 0x683a,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x2ad9, 0x012e, 0x2001, 0x0000,
-	0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x2009, 0x0002,
-	0x080c, 0x80a7, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005,
-	0x2001, 0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xad0c, 0x210c,
-	0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001,
-	0x0029, 0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff,
-	0xa082, 0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff,
-	0x12e0, 0xa188, 0xae34, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084,
-	0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c,
-	0x4dfc, 0x04c9, 0x0030, 0x04b9, 0x684c, 0xd0fc, 0x0110, 0x080c,
-	0x4ded, 0x080c, 0x4e3a, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009,
-	0x0000, 0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20,
-	0x2001, 0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009,
-	0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a,
-	0x6803, 0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e,
-	0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005,
-	0x0170, 0x00e6, 0x2071, 0xafc7, 0x7004, 0xa086, 0x0002, 0x0168,
-	0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00,
-	0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80,
-	0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800,
-	0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c,
-	0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05,
-	0x0005, 0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a,
-	0x6086, 0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6,
-	0x0026, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110,
-	0xc285, 0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005,
-	0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006,
-	0xa086, 0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xad52,
-	0x2004, 0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007,
-	0x1110, 0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206,
-	0x0006, 0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c,
-	0x14f6, 0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091,
-	0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178,
-	0x609c, 0xd0a4, 0x0160, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1138,
-	0xa284, 0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e,
-	0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005,
-	0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190,
-	0xae34, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15c0,
-	0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000,
-	0x60ab, 0x0000, 0x080c, 0x493a, 0xa006, 0x002e, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001,
-	0x0480, 0x00d6, 0xa190, 0xae34, 0x2204, 0xa06d, 0x0540, 0x2013,
-	0x0000, 0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c,
-	0x15f0, 0x60a8, 0xa06d, 0x0110, 0x080c, 0x15f0, 0x00ce, 0x00de,
-	0x00d6, 0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006,
-	0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x1600, 0x080c,
-	0x8078, 0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x15f0, 0x00de,
-	0xa006, 0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218,
-	0xa085, 0x0001, 0x0030, 0xa188, 0xae34, 0x2104, 0xa065, 0x0dc0,
-	0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b,
-	0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x574f,
-	0x1538, 0x60a0, 0xa086, 0x007e, 0x2069, 0xb290, 0x0130, 0x2001,
-	0xad34, 0x2004, 0xd0ac, 0x11e0, 0x0098, 0x2d04, 0xd0e4, 0x01c0,
-	0x00d6, 0x2069, 0xb28e, 0x00c6, 0x2061, 0xaf9f, 0x6810, 0x2062,
-	0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de,
-	0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0xad00, 0x68a2,
-	0x2069, 0xb28e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138, 0xa10a,
-	0x0208, 0x603a, 0x6814, 0x6066, 0x2099, 0xb296, 0xac88, 0x000a,
-	0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xb29a, 0xac88, 0x0006,
-	0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xb2ae, 0x6808, 0x606a,
-	0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076, 0xa182, 0x0211,
-	0x1218, 0x2009, 0x0008, 0x0400, 0xa182, 0x0259, 0x1218, 0x2009,
-	0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0,
-	0xa182, 0x0349, 0x1218, 0x2009, 0x0005, 0x0070, 0xa182, 0x0421,
-	0x1218, 0x2009, 0x0004, 0x0040, 0xa182, 0x0581, 0x1218, 0x2009,
-	0x0003, 0x0010, 0x2009, 0x0002, 0x6192, 0x014e, 0x013e, 0x015e,
-	0x00de, 0x0005, 0x0016, 0x0026, 0x00e6, 0x2071, 0xb28d, 0x2e04,
-	0x6896, 0x2071, 0xb28e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00,
-	0x2009, 0xad71, 0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad,
-	0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4, 0x0110, 0xc2bd, 0x0008,
-	0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0126,
-	0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540,
-	0x6a04, 0xa282, 0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010,
-	0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x4da8, 0x080c,
-	0x14f6, 0x260a, 0x8210, 0x6a06, 0x0098, 0x080c, 0x15d9, 0x01a8,
-	0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010,
-	0x200b, 0xffff, 0x8108, 0x1f04, 0x4dc0, 0x6807, 0x0001, 0x6e12,
-	0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126,
-	0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800,
-	0xa005, 0x1160, 0x080c, 0x4ef9, 0x1168, 0x200b, 0xffff, 0x6804,
-	0xa08a, 0x0002, 0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x15f0,
-	0x60a7, 0x0000, 0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x4f56, 0x0010, 0x080c, 0x4bc0, 0x080c, 0x4e71, 0x1dd8,
-	0x080c, 0x4e3a, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
-	0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282,
-	0x0010, 0x1670, 0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086,
-	0xffff, 0x0128, 0x8108, 0x1f04, 0x4e0e, 0x080c, 0x14f6, 0x260a,
-	0x8210, 0x6a56, 0x0098, 0x080c, 0x15d9, 0x01d0, 0x2d00, 0x60aa,
-	0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff,
-	0x8108, 0x1f04, 0x4e26, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c,
-	0x4c11, 0x0089, 0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005,
-	0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x080c, 0x67c5, 0x012e,
-	0x0005, 0xa01e, 0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091,
-	0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8,
-	0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
-	0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
-	0x6a00, 0x604c, 0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000,
-	0x2202, 0x82ff, 0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e,
-	0x0010, 0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8,
-	0x83ff, 0x0120, 0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406,
-	0x1118, 0x6840, 0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70,
-	0x6a00, 0x6080, 0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000,
-	0x2202, 0x82ff, 0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c,
-	0x4ef3, 0x1110, 0x2011, 0x0001, 0x080c, 0x4f3d, 0x1110, 0xa295,
-	0x0002, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x964b, 0x0010,
-	0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c, 0x95e4,
-	0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118, 0x080c,
-	0x962e, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e, 0x0118,
-	0x080c, 0x9600, 0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x4f6e,
-	0x0118, 0x080c, 0x9667, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126,
-	0x0006, 0x00d6, 0x2091, 0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800,
-	0x0006, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd,
-	0x0006, 0x6000, 0xd0fc, 0x0110, 0x080c, 0xac03, 0x000e, 0x080c,
-	0x510c, 0x000e, 0x0c50, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de,
-	0x000e, 0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001,
-	0x0005, 0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010,
-	0xae88, 0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4f02,
-	0xa085, 0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091,
-	0x8000, 0x60a4, 0xa06d, 0x1128, 0x080c, 0x15d9, 0x01a0, 0x2d00,
-	0x60a6, 0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9,
-	0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x4f21, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091,
-	0x8000, 0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x15f0,
-	0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118,
-	0xa085, 0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160,
-	0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108,
-	0x1f04, 0x4f4c, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068,
-	0x6854, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c,
-	0x15f0, 0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4,
-	0x0005, 0x00f6, 0x080c, 0x574f, 0x01b0, 0x71b4, 0x81ff, 0x1198,
-	0x71d0, 0xd19c, 0x0180, 0x2001, 0x007e, 0xa080, 0xae34, 0x2004,
-	0xa07d, 0x0148, 0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118,
-	0x7800, 0xc0ed, 0x7802, 0x2079, 0xad51, 0x7804, 0xd0a4, 0x01e8,
-	0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c,
-	0x4cdc, 0x1168, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
-	0x0118, 0xa086, 0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e,
-	0x8108, 0x1f04, 0x4f96, 0x00ce, 0x015e, 0x080c, 0x502d, 0x0120,
-	0x2001, 0xafa2, 0x200c, 0x0038, 0x2079, 0xad51, 0x7804, 0xd0a4,
-	0x0130, 0x2009, 0x07d0, 0x2011, 0x4fc1, 0x080c, 0x6593, 0x00fe,
-	0x0005, 0x2011, 0x4fc1, 0x080c, 0x650d, 0x080c, 0x502d, 0x01f0,
-	0x2001, 0xaeb2, 0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102,
-	0x2001, 0xad52, 0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011,
-	0x4fc1, 0x080c, 0x6593, 0x00e6, 0x2071, 0xad00, 0x706f, 0x0000,
-	0x7073, 0x0000, 0x080c, 0x28fa, 0x00ee, 0x04b0, 0x0156, 0x00c6,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4cdc, 0x1530,
-	0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227,
-	0xa006, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6000, 0xc0e5, 0xc0ec,
-	0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019,
-	0x0029, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d,
-	0x2009, 0x0000, 0x080c, 0xa712, 0x007e, 0x004e, 0x001e, 0x8108,
-	0x1f04, 0x4fec, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060,
-	0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac,
-	0x0005, 0x7818, 0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xaeb2,
-	0x2004, 0xa07d, 0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126,
-	0x0026, 0x2091, 0x8000, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008,
-	0xc2fc, 0x6202, 0x002e, 0x012e, 0x0005, 0x2071, 0xae13, 0x7003,
-	0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b,
-	0x0000, 0x701f, 0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f,
-	0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071,
-	0xaf7c, 0x7003, 0xae13, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
-	0xaf5c, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
-	0x0016, 0x00e6, 0x2071, 0xaf34, 0xa00e, 0x7186, 0x718a, 0x7097,
-	0x0001, 0x2001, 0xad52, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xad52,
-	0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x50d6,
-	0x2001, 0xad71, 0x200c, 0xa184, 0x000f, 0x2009, 0xad72, 0x210c,
-	0x0002, 0x507e, 0x50b1, 0x50b8, 0x50c2, 0x50c7, 0x507e, 0x507e,
-	0x507e, 0x50a1, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e,
-	0x507e, 0x7003, 0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
-	0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
-	0x0428, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030,
-	0x708f, 0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097,
-	0x0001, 0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007,
-	0x0121, 0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184,
-	0xff00, 0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e,
-	0x0005, 0x00e6, 0x2071, 0xae13, 0x684c, 0xa005, 0x1130, 0x7028,
-	0xc085, 0x702a, 0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64,
-	0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
-	0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000,
-	0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
-	0x2100, 0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007,
-	0x0001, 0xa006, 0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838,
-	0xd0fc, 0x1904, 0x5165, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071,
-	0xad00, 0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00,
-	0x81ff, 0x1dc8, 0x702e, 0x70b0, 0xa200, 0x70b2, 0x00de, 0x2071,
-	0xae13, 0x701c, 0xa005, 0x1904, 0x5175, 0x20a9, 0x0032, 0x0f04,
-	0x5173, 0x0e04, 0x512f, 0x2071, 0xaf34, 0x7200, 0x82ff, 0x05d8,
-	0x6934, 0xa186, 0x0103, 0x1904, 0x5183, 0x6948, 0x6844, 0xa105,
-	0x1540, 0x2009, 0x8020, 0x2200, 0x0002, 0x5173, 0x514a, 0x519b,
-	0x51a7, 0x5173, 0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x5173,
-	0x7018, 0xd084, 0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a,
-	0x701b, 0x0001, 0x2091, 0x4080, 0x2071, 0xad00, 0x702c, 0x206a,
-	0x2d00, 0x702e, 0x70b0, 0x8000, 0x70b2, 0x002e, 0x00ee, 0x015e,
-	0x0005, 0x6844, 0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118,
-	0x2009, 0x8020, 0x0880, 0x2071, 0xae13, 0x2d08, 0x206b, 0x0000,
-	0x7010, 0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902,
-	0x0008, 0x711e, 0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130,
-	0xa186, 0x001e, 0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc,
-	0x0d10, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009,
-	0x8021, 0x0804, 0x5143, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98,
-	0x7186, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084,
-	0x8008, 0xa092, 0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003,
-	0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a,
-	0x0a04, 0x515c, 0x718c, 0x7084, 0xa10a, 0x0a04, 0x515c, 0x2071,
-	0x0000, 0x7018, 0xd084, 0x1904, 0x515c, 0x2071, 0xaf34, 0x7000,
-	0xa086, 0x0002, 0x1150, 0x080c, 0x5426, 0x2071, 0x0000, 0x701b,
-	0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x080c, 0x5450, 0x2071,
-	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x515c, 0x0006,
-	0x684c, 0x0006, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011,
-	0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e,
-	0x000e, 0x684a, 0x6952, 0x0005, 0x2071, 0xae13, 0x7004, 0x0002,
-	0x5202, 0x5213, 0x5411, 0x5412, 0x541f, 0x5425, 0x5203, 0x5402,
-	0x5398, 0x53ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5212,
-	0x2009, 0x000d, 0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001,
-	0x700b, 0x0000, 0x012e, 0x2069, 0xafda, 0x683c, 0xa005, 0x03f8,
-	0x11f0, 0x0126, 0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001,
-	0xae1f, 0x2004, 0xa10a, 0x0170, 0x0e04, 0x5236, 0x2069, 0x0000,
-	0x6818, 0xd084, 0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001,
-	0x2091, 0x4080, 0x2069, 0xafda, 0x683f, 0xffff, 0x012e, 0x2069,
-	0xad00, 0x6844, 0x6964, 0xa102, 0x2069, 0xaf34, 0x688a, 0x6984,
-	0x701c, 0xa06d, 0x0120, 0x81ff, 0x0904, 0x528c, 0x00a0, 0x81ff,
-	0x0904, 0x5352, 0x2071, 0xaf34, 0x7184, 0x7088, 0xa10a, 0x1258,
-	0x7190, 0x2071, 0xafda, 0x7038, 0xa005, 0x0128, 0x1b04, 0x5352,
-	0x713a, 0x0804, 0x5352, 0x2071, 0xaf34, 0x718c, 0x0126, 0x2091,
-	0x8000, 0x7084, 0xa10a, 0x0a04, 0x536d, 0x0e04, 0x530e, 0x2071,
-	0x0000, 0x7018, 0xd084, 0x1904, 0x530e, 0x2001, 0xffff, 0x2071,
-	0xafda, 0x703a, 0x2071, 0xaf34, 0x7000, 0xa086, 0x0002, 0x1150,
-	0x080c, 0x5426, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x0804, 0x530e, 0x080c, 0x5450, 0x2071, 0x0000, 0x701b, 0x0001,
-	0x2091, 0x4080, 0x0804, 0x530e, 0x2071, 0xaf34, 0x7000, 0xa005,
-	0x0904, 0x5334, 0x6934, 0xa186, 0x0103, 0x1904, 0x5311, 0x684c,
-	0xd0bc, 0x1904, 0x5334, 0x6948, 0x6844, 0xa105, 0x1904, 0x5329,
-	0x2009, 0x8020, 0x2071, 0xaf34, 0x7000, 0x0002, 0x5334, 0x52f4,
-	0x52cc, 0x52de, 0x52ab, 0x0136, 0x0146, 0x0156, 0x2099, 0xad75,
-	0x20a1, 0xaf85, 0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e,
-	0x2071, 0xaf7c, 0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007,
-	0x0002, 0x700b, 0x0000, 0x2e10, 0x080c, 0x1624, 0x2071, 0xae13,
-	0x7007, 0x0009, 0x0804, 0x5352, 0x7084, 0x8008, 0xa092, 0x001e,
-	0x1a04, 0x5352, 0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186,
-	0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x7084, 0x8008,
-	0xa092, 0x000f, 0x1a04, 0x5352, 0xae90, 0x0003, 0x8003, 0xa210,
-	0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xae13,
-	0x080c, 0x54a7, 0x0804, 0x5352, 0x0126, 0x2091, 0x8000, 0x0e04,
-	0x530e, 0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c,
-	0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e,
-	0x2071, 0xae13, 0x080c, 0x54a7, 0x0804, 0x5352, 0x012e, 0x0804,
-	0x5352, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e,
-	0x0118, 0xa18e, 0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850,
-	0xa084, 0x00ff, 0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804,
-	0x52a2, 0x6844, 0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120,
-	0x2009, 0x8020, 0x0804, 0x52a2, 0x2071, 0xae13, 0x080c, 0x54b9,
-	0x01c8, 0x2071, 0xae13, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff,
-	0xa086, 0x0003, 0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108,
-	0x710e, 0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100,
-	0x0904, 0x5412, 0x0126, 0x2091, 0x8000, 0x2071, 0xae13, 0x7008,
-	0xa086, 0x0001, 0x1180, 0x0e04, 0x536b, 0x2009, 0x000d, 0x7030,
-	0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006,
-	0x1110, 0x7007, 0x0001, 0x012e, 0x0005, 0x2071, 0xae13, 0x080c,
-	0x54b9, 0x0518, 0x2071, 0xaf34, 0x7084, 0x700a, 0x20a9, 0x0020,
-	0x2099, 0xaf35, 0x20a1, 0xaf5c, 0x53a3, 0x7087, 0x0000, 0x2071,
-	0xae13, 0x2069, 0xaf7c, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074,
-	0x682e, 0x7078, 0x6832, 0x2d10, 0x080c, 0x1624, 0x7007, 0x0008,
-	0x2001, 0xffff, 0x2071, 0xafda, 0x703a, 0x012e, 0x0804, 0x5352,
-	0x2069, 0xaf7c, 0x6808, 0xa08e, 0x0000, 0x0904, 0x53ed, 0xa08e,
-	0x0200, 0x0904, 0x53eb, 0xa08e, 0x0100, 0x1904, 0x53ed, 0x0126,
-	0x2091, 0x8000, 0x0e04, 0x53e9, 0x2069, 0x0000, 0x6818, 0xd084,
-	0x15c0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
-	0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e,
-	0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b,
-	0x0000, 0x2001, 0xaf59, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069,
-	0xaf34, 0x689c, 0x699e, 0x2069, 0xafda, 0xa102, 0x1118, 0x683c,
-	0xa005, 0x1368, 0x2001, 0xaf5a, 0x200c, 0x810d, 0x693e, 0x0038,
-	0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007,
-	0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xaf7e,
-	0x2004, 0xa08e, 0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x54a7,
-	0x0005, 0xa08e, 0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007,
-	0x0005, 0x0005, 0x701c, 0xa06d, 0x0158, 0x080c, 0x54b9, 0x0140,
-	0x7007, 0x0003, 0x080c, 0x54d2, 0x7050, 0xa086, 0x0100, 0x0110,
-	0x0005, 0x0005, 0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004,
-	0x0030, 0xa086, 0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c,
-	0x5475, 0x7006, 0x080c, 0x54a7, 0x0005, 0x0005, 0x00e6, 0x0156,
-	0x2071, 0xaf34, 0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80,
-	0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04,
-	0x544a, 0x2014, 0x722a, 0x8000, 0x0f04, 0x544a, 0x2014, 0x722e,
-	0x8000, 0x0f04, 0x544a, 0x2014, 0x723a, 0x8000, 0x0f04, 0x544a,
-	0x2014, 0x723e, 0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005,
-	0x00e6, 0x0156, 0x2071, 0xaf34, 0x7184, 0x81ff, 0x01d8, 0xa006,
-	0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226,
-	0x8000, 0x2014, 0x722a, 0x8000, 0x0f04, 0x546c, 0x2014, 0x723a,
-	0x8000, 0x2014, 0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001,
-	0x8042, 0x7022, 0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048,
-	0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000,
-	0x7072, 0x7132, 0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091,
-	0x8000, 0x0e04, 0x54a1, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080,
-	0x2001, 0x0001, 0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007,
-	0x0005, 0x2001, 0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c,
-	0xa06d, 0x0170, 0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012,
-	0x2d04, 0x701e, 0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x15f0,
-	0x0005, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304,
-	0x230c, 0xa10e, 0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130,
-	0xa102, 0x1118, 0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008,
-	0x8002, 0x0005, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053,
-	0x0000, 0x0126, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc08d,
-	0x200a, 0x012e, 0x080c, 0x163c, 0x0005, 0x7088, 0xa08a, 0x0029,
-	0x1220, 0xa082, 0x001d, 0x0033, 0x0010, 0x080c, 0x14f6, 0x6027,
-	0x1e00, 0x0005, 0x55c1, 0x555b, 0x5571, 0x5595, 0x55b4, 0x55e6,
-	0x55f8, 0x5571, 0x55d2, 0x54ff, 0x552d, 0x54fe, 0x0005, 0x00d6,
-	0x2069, 0x0200, 0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518,
-	0x708b, 0x0028, 0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x584d,
-	0x6028, 0xa085, 0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069,
-	0xafac, 0x2d04, 0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6,
-	0x0036, 0x0046, 0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e,
-	0x004e, 0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200,
-	0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708b, 0x0028,
-	0x2069, 0xafac, 0x2d04, 0x7002, 0x080c, 0x58da, 0x6028, 0xa085,
-	0x0600, 0x602a, 0x00b0, 0x708b, 0x0028, 0x2069, 0xafac, 0x2d04,
-	0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046,
-	0x0056, 0x2071, 0xaffd, 0x080c, 0x1d22, 0x005e, 0x004e, 0x003e,
-	0x00ee, 0x00de, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1180,
-	0x080c, 0x5663, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140,
-	0x708b, 0x0020, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f,
-	0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x11c8, 0xd1dc, 0x11a0,
-	0xd1e4, 0x1178, 0xa184, 0x1e00, 0x11b8, 0x60e3, 0x0001, 0x600c,
-	0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x708b, 0x0028,
-	0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b,
-	0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3, 0x0001, 0x600c,
-	0xc0b4, 0x600e, 0x080c, 0x577f, 0x6803, 0x0080, 0x6124, 0xd1d4,
-	0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0xa184, 0x1e00, 0x1158,
-	0x708b, 0x0028, 0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d,
-	0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1dc,
-	0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d,
-	0x0005, 0x080c, 0x568d, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x5663,
-	0xd1d4, 0x1128, 0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b,
-	0x001f, 0x0005, 0x6803, 0x00a0, 0x6124, 0xd1d4, 0x1160, 0xd1cc,
-	0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028,
-	0x708b, 0x001d, 0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x568d,
-	0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b,
-	0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005,
-	0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc,
-	0x1128, 0xd1e4, 0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d,
-	0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x0016,
-	0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140,
-	0x2071, 0xad00, 0x2091, 0x8000, 0x080c, 0x574f, 0x11e8, 0x2001,
-	0xad0c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4, 0x2102, 0x6027, 0x0200,
-	0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158, 0x6803, 0x00a0, 0x2001,
-	0xaf9e, 0x2003, 0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0428,
-	0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x576b, 0x0150, 0x080c,
-	0x5761, 0x1138, 0x2001, 0x0001, 0x080c, 0x261e, 0x080c, 0x5726,
-	0x00a0, 0x080c, 0x568a, 0x0178, 0x2001, 0x0001, 0x080c, 0x261e,
-	0x7088, 0xa086, 0x001e, 0x0120, 0x7088, 0xa086, 0x0022, 0x1118,
-	0x708b, 0x0025, 0x0010, 0x708b, 0x0021, 0x012e, 0x00ee, 0x00de,
-	0x00ce, 0x001e, 0x0005, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011,
-	0x566e, 0x080c, 0x6501, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6,
-	0x0016, 0x080c, 0x7834, 0x2071, 0xad00, 0x080c, 0x560f, 0x001e,
-	0x00fe, 0x00ee, 0x0005, 0x2001, 0xad00, 0x2004, 0xa086, 0x0004,
-	0x0140, 0x2001, 0xaf9d, 0x2003, 0xaaaa, 0x2001, 0xaf9e, 0x2003,
-	0x0000, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6803, 0x00c0, 0x0156,
-	0x20a9, 0x002d, 0x1d04, 0x5692, 0x2091, 0x6000, 0x1f04, 0x5692,
-	0x015e, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x2071, 0xad00, 0x2001, 0xaf9e, 0x200c, 0xa186, 0x0000,
-	0x0158, 0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186,
-	0x0003, 0x0158, 0x0804, 0x5714, 0x708b, 0x0022, 0x0040, 0x708b,
-	0x0021, 0x0028, 0x708b, 0x0023, 0x0020, 0x708b, 0x0024, 0x6043,
-	0x0000, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c,
-	0x26cb, 0x0026, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002,
-	0x080c, 0x7ae9, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b,
-	0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000,
-	0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0118, 0x012e, 0x015e, 0x04d0,
-	0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130,
-	0x6803, 0x0100, 0x1f04, 0x56e2, 0x080c, 0x57a0, 0x012e, 0x015e,
-	0x080c, 0x5761, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006,
-	0xa085, 0x0020, 0x6052, 0x080c, 0x57a0, 0xa006, 0x8001, 0x1df0,
-	0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x57a0,
-	0x2001, 0xaf9e, 0x2003, 0x0004, 0x080c, 0x54e5, 0x080c, 0x5761,
-	0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100, 0x2001, 0xaf9e,
-	0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
-	0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x2001,
-	0xaf9d, 0x2003, 0x0000, 0x2001, 0xaf8e, 0x2003, 0x0000, 0x708b,
-	0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000, 0x080c,
-	0x26cb, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027,
-	0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006,
-	0x2001, 0xaf9d, 0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006,
-	0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e,
-	0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084, 0x0030, 0xa086,
-	0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71, 0x2004, 0xa084,
-	0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0xad71,
-	0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001,
-	0xad0c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x26eb, 0x0036, 0x0016,
-	0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2aac, 0x001e, 0x003e,
-	0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xad0c, 0x2e04, 0x0118,
-	0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072, 0x00ee, 0x0005,
-	0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006,
-	0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000,
-	0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a, 0x000e, 0x6006,
-	0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x60e3, 0x0000,
-	0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x26cb, 0x6800, 0xa084,
-	0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e, 0x6052, 0x6050,
-	0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6,
-	0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xad00, 0x6020, 0xa084,
-	0x0080, 0x0138, 0x2001, 0xad0c, 0x200c, 0xc1bd, 0x2102, 0x0804,
-	0x5845, 0x2001, 0xad0c, 0x200c, 0xc1bc, 0x2102, 0x6028, 0xa084,
-	0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090, 0x20a9, 0x0384,
-	0x6024, 0xd0cc, 0x1518, 0x1d04, 0x57f8, 0x2091, 0x6000, 0x1f04,
-	0x57f8, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
-	0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
-	0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
-	0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x0438, 0x60e3, 0x0000,
-	0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x6803, 0x0080,
-	0x20a9, 0x0384, 0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024,
-	0xa10c, 0x0138, 0x1d04, 0x582a, 0x2091, 0x6000, 0x1f04, 0x582a,
-	0x0840, 0x6028, 0xa085, 0x1e00, 0x602a, 0x70a0, 0xa005, 0x1118,
-	0x6887, 0x0001, 0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce,
-	0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xad00,
-	0x2069, 0x0140, 0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005,
-	0x1904, 0x58a1, 0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000,
-	0x2001, 0x0000, 0x080c, 0x26cb, 0x2069, 0x0200, 0x6804, 0xa005,
-	0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a,
-	0x6027, 0x0400, 0x2069, 0xafac, 0x7000, 0x206a, 0x708b, 0x0026,
-	0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5884, 0x2091, 0x6000,
-	0x1f04, 0x5884, 0x0804, 0x58d2, 0x2069, 0x0140, 0x20a9, 0x0384,
-	0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0530,
-	0xa084, 0x1a00, 0x1518, 0x1d04, 0x5890, 0x2091, 0x6000, 0x1f04,
-	0x5890, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
-	0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
-	0x7a64, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003, 0x0001, 0x2001,
-	0xad00, 0x2003, 0x0001, 0xa085, 0x0001, 0x00a0, 0x6803, 0x0080,
-	0x2069, 0x0140, 0x60e3, 0x0000, 0x70a0, 0xa005, 0x1118, 0x6887,
-	0x0001, 0x0008, 0x6886, 0x2001, 0xaf8e, 0x2004, 0x080c, 0x26cb,
-	0x60e2, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6,
-	0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x6020, 0xa084, 0x00c0,
-	0x01f0, 0x2011, 0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c,
-	0x7ae9, 0x080c, 0x79e1, 0x080c, 0x6581, 0x2019, 0x0000, 0x080c,
-	0x7a64, 0x2069, 0x0140, 0x6803, 0x00a0, 0x2001, 0xaf9e, 0x2003,
-	0x0001, 0x2001, 0xad00, 0x2003, 0x0001, 0x0804, 0x5972, 0x2001,
-	0xad0c, 0x200c, 0xd1b4, 0x1150, 0xc1b5, 0x2102, 0x080c, 0x5663,
-	0x2069, 0x0140, 0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200,
-	0x6804, 0xa005, 0x1118, 0x6808, 0xa005, 0x01b8, 0x6028, 0xa084,
-	0xfdff, 0x602a, 0x6027, 0x0200, 0x2069, 0xafac, 0x7000, 0x206a,
-	0x708b, 0x0027, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x592e,
-	0x2091, 0x6000, 0x1f04, 0x592e, 0x04e8, 0x6027, 0x1e00, 0x2009,
-	0x1e00, 0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0,
-	0x1d04, 0x5935, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c,
-	0x64a2, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071,
-	0xafda, 0x7018, 0x00ee, 0xa005, 0x1d00, 0x01e0, 0x0026, 0x2011,
-	0x566e, 0x080c, 0x650d, 0x002e, 0x2069, 0x0140, 0x60e3, 0x0000,
-	0x70a0, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x2001,
-	0xaf8e, 0x2004, 0x080c, 0x26cb, 0x60e2, 0x2001, 0xad0c, 0x200c,
-	0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6,
-	0x00e6, 0x2061, 0x0100, 0x2071, 0xad00, 0x7130, 0xd184, 0x1180,
-	0x2011, 0xad52, 0x2214, 0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011,
-	0xad52, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c, 0x0904, 0x59df,
-	0x7130, 0xc185, 0x7132, 0x2011, 0xad52, 0x220c, 0xd1a4, 0x0530,
-	0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x663f, 0x2019,
-	0x000e, 0x080c, 0xa8eb, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000,
-	0xa186, 0x007e, 0x0170, 0xa186, 0x0080, 0x0158, 0x080c, 0x4cdc,
-	0x1140, 0x8127, 0xa006, 0x0016, 0x2009, 0x000e, 0x080c, 0xa96c,
-	0x001e, 0x8108, 0x1f04, 0x59b0, 0x015e, 0x001e, 0xd1ac, 0x1148,
-	0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2aac, 0x001e,
-	0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4cdc,
-	0x1110, 0x080c, 0x493a, 0x8108, 0x1f04, 0x59d6, 0x015e, 0x2011,
-	0x0003, 0x080c, 0x7adf, 0x2011, 0x0002, 0x080c, 0x7ae9, 0x080c,
-	0x79e1, 0x080c, 0x6581, 0x0036, 0x2019, 0x0000, 0x080c, 0x7a64,
-	0x003e, 0x60e3, 0x0000, 0x2001, 0xad00, 0x2003, 0x0001, 0x080c,
-	0x569a, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e, 0x015e,
-	0x0005, 0x2071, 0xade1, 0x7003, 0x0000, 0x7007, 0x0000, 0x700f,
-	0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001, 0x705f,
-	0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000, 0x708f,
-	0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0xade1, 0x6848,
-	0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0428,
-	0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c,
-	0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c,
-	0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0,
-	0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a,
-	0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005, 0x2b78,
-	0x2071, 0xade1, 0x7004, 0x0043, 0x700c, 0x0002, 0x5a5b, 0x5a52,
-	0x5a52, 0x5a52, 0x5a52, 0x0005, 0x5ab1, 0x5ab2, 0x5ae4, 0x5ae5,
-	0x5aaf, 0x5b33, 0x5b38, 0x5b69, 0x5b6a, 0x5b85, 0x5b86, 0x5b87,
-	0x5b88, 0x5b89, 0x5b8a, 0x5c40, 0x5c67, 0x700c, 0x0002, 0x5a74,
-	0x5aaf, 0x5aaf, 0x5ab0, 0x5ab0, 0x7830, 0x7930, 0xa106, 0x0120,
-	0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8, 0x1210,
-	0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x15c0, 0x01b0,
-	0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000,
-	0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0xafec, 0x2104, 0xc085,
-	0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x163c, 0x0005, 0x080c,
-	0x15c0, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x15c0, 0x1108, 0x0c10,
-	0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8, 0x0005,
-	0x0005, 0x0005, 0x700c, 0x0002, 0x5ab9, 0x5abc, 0x5aca, 0x5ae3,
-	0x5ae3, 0x080c, 0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058,
-	0x0006, 0x080c, 0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d,
-	0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058,
-	0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834,
-	0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218, 0x00db, 0x012e, 0x0005,
-	0x012e, 0x080c, 0x5b8b, 0x0005, 0x0005, 0x0005, 0x00e6, 0x2071,
-	0xade1, 0x700c, 0x0002, 0x5af0, 0x5af0, 0x5af0, 0x5af2, 0x5af5,
-	0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002, 0x00ee,
-	0x0005, 0x5b8b, 0x5b8b, 0x5ba7, 0x5b8b, 0x5d22, 0x5b8b, 0x5b8b,
-	0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x5d64, 0x5da7, 0x5df0, 0x5e04,
-	0x5b8b, 0x5b8b, 0x5bc3, 0x5ba7, 0x5b8b, 0x5b8b, 0x5c1d, 0x5ead,
-	0x5ec8, 0x5b8b, 0x5bc3, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5c13,
-	0x5ec8, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
-	0x5b8b, 0x5b8b, 0x5bd7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
-	0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b, 0x5b8b,
-	0x5b8b, 0x5b8b, 0x5bec, 0x7020, 0x2068, 0x080c, 0x15f0, 0x0005,
-	0x700c, 0x0002, 0x5b3f, 0x5b42, 0x5b50, 0x5b68, 0x5b68, 0x080c,
-	0x5a6d, 0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c,
-	0x5f90, 0x0120, 0x2091, 0x8000, 0x080c, 0x5a6d, 0x00de, 0x0048,
-	0x0126, 0x8001, 0x700e, 0x080c, 0x5f90, 0x7058, 0x2068, 0x7084,
-	0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff,
-	0xa08a, 0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419,
-	0x0005, 0x0005, 0x0005, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5ba7,
-	0x5b8b, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5ba7, 0x5ba7,
-	0x5ba7, 0x5ba7, 0x5ba7, 0x5b8b, 0x5ba7, 0x5d0e, 0x5b8b, 0x5b8b,
-	0x5ba7, 0x5b8b, 0x5b8b, 0x5b8b, 0x5ba7, 0x0005, 0x0005, 0x0005,
-	0x0005, 0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff,
-	0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e,
-	0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007,
-	0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838,
-	0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x510c, 0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988,
-	0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x5cd0, 0x7007, 0x0006,
-	0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5cd0, 0x0005, 0x6834,
-	0x8007, 0xa084, 0x00ff, 0x0904, 0x5b99, 0x8001, 0x1120, 0x7007,
-	0x0001, 0x0804, 0x5ced, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016,
-	0x701a, 0x704b, 0x5ced, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff,
-	0xa086, 0x0001, 0x1904, 0x5b99, 0x7007, 0x0001, 0x2009, 0xad30,
-	0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853,
-	0x0000, 0x080c, 0x4ab1, 0x1108, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x6837, 0x0139, 0x684a, 0x6952, 0x080c, 0x510c, 0x012e, 0x0ca0,
-	0x2001, 0x0028, 0x0c90, 0x684c, 0xa084, 0x00c0, 0xa086, 0x00c0,
-	0x1120, 0x7007, 0x0001, 0x0804, 0x5ee0, 0x2d00, 0x7016, 0x701a,
-	0x20a9, 0x0004, 0xa080, 0x0024, 0x2098, 0x20a1, 0xae0c, 0x53a3,
-	0x6858, 0x7012, 0xa082, 0x0401, 0x1a04, 0x5bb5, 0x6a84, 0xa28a,
-	0x0002, 0x1a04, 0x5bb5, 0x82ff, 0x1138, 0x6888, 0x698c, 0xa105,
-	0x0118, 0x2001, 0x5ca3, 0x0018, 0xa280, 0x5c99, 0x2005, 0x70c6,
-	0x7010, 0xa015, 0x0904, 0x5c85, 0x080c, 0x15c0, 0x1118, 0x7007,
-	0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836,
-	0xe004, 0xad00, 0x7096, 0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200,
-	0x7112, 0xe20c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0108, 0xa108,
-	0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x080c, 0x1624, 0x7090,
-	0xa08e, 0x0100, 0x0170, 0xa086, 0x0200, 0x0118, 0x7007, 0x0010,
-	0x0005, 0x7020, 0x2068, 0x080c, 0x15f0, 0x7014, 0x2068, 0x0804,
-	0x5bb5, 0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08,
-	0x2068, 0x6906, 0x711a, 0x0804, 0x5c40, 0x7014, 0x2068, 0x7007,
-	0x0001, 0x6884, 0xa005, 0x1128, 0x6888, 0x698c, 0xa105, 0x0108,
-	0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0904, 0x5ee0,
-	0x04b8, 0x5c9b, 0x5c9f, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a,
-	0x000f, 0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x00f6,
-	0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88, 0x6e8c, 0x6804, 0x2060,
-	0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816,
-	0x7008, 0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a,
-	0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0c78, 0x6004,
-	0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
-	0x2009, 0xad30, 0x210c, 0x81ff, 0x1198, 0x6838, 0xa084, 0x00ff,
-	0x683a, 0x080c, 0x4993, 0x1108, 0x0005, 0x080c, 0x51df, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x012e, 0x0ca0,
-	0x2001, 0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0xad30, 0x210c,
-	0x81ff, 0x11b0, 0x6858, 0xa005, 0x01b0, 0x6838, 0xa084, 0x00ff,
-	0x683a, 0x6853, 0x0000, 0x080c, 0x4a55, 0x1108, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x51df, 0x080c, 0x510c, 0x012e, 0x0cb0,
-	0x2001, 0x0028, 0x0ca0, 0x2001, 0x0000, 0x0c88, 0x7018, 0x6802,
-	0x2d08, 0x2068, 0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118,
-	0x7007, 0x0006, 0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048,
-	0x080f, 0x0005, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff,
-	0x6848, 0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0,
-	0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0178, 0xa005,
-	0x11f0, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4cdc, 0x11b8,
-	0x0066, 0x6e50, 0x080c, 0x4dcf, 0x006e, 0x0088, 0x0046, 0x2011,
-	0xad0c, 0x2224, 0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4cdc,
-	0x1110, 0x080c, 0x4f2d, 0x8108, 0x1f04, 0x5d4e, 0x00ce, 0x684c,
-	0xd084, 0x1118, 0x080c, 0x15f0, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x510c, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4, 0x0580, 0x2061, 0xb048,
-	0x6100, 0xd184, 0x0178, 0x6858, 0xa084, 0x00ff, 0x1550, 0x6000,
-	0xd084, 0x0520, 0x6004, 0xa005, 0x1538, 0x6003, 0x0000, 0x600b,
-	0x0000, 0x00c8, 0x2011, 0x0001, 0x6860, 0xa005, 0x1110, 0x2001,
-	0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff, 0x0178, 0x6006,
-	0x6858, 0x8007, 0xa084, 0x00ff, 0x0148, 0x600a, 0x6858, 0x8000,
-	0x1108, 0xc28d, 0x6202, 0x012e, 0x0804, 0x5f7f, 0x012e, 0x0804,
-	0x5f79, 0x012e, 0x0804, 0x5f73, 0x012e, 0x0804, 0x5f76, 0x0126,
-	0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xad52, 0x2004, 0xd0a4,
-	0x05e0, 0x2061, 0xb048, 0x6000, 0xd084, 0x05b8, 0x6204, 0x6308,
-	0xd08c, 0x1530, 0x6c48, 0xa484, 0x0003, 0x0170, 0x6958, 0xa18c,
-	0x00ff, 0x8001, 0x1120, 0x2100, 0xa210, 0x0620, 0x0028, 0x8001,
-	0x1508, 0x2100, 0xa212, 0x02f0, 0xa484, 0x000c, 0x0188, 0x6958,
-	0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x1120, 0x2100, 0xa318,
-	0x0288, 0x0030, 0xa082, 0x0004, 0x1168, 0x2100, 0xa31a, 0x0250,
-	0x6860, 0xa005, 0x0110, 0x8000, 0x6016, 0x6206, 0x630a, 0x012e,
-	0x0804, 0x5f7f, 0x012e, 0x0804, 0x5f7c, 0x012e, 0x0804, 0x5f79,
-	0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xb048, 0x6300,
-	0xd38c, 0x1120, 0x6308, 0x8318, 0x0220, 0x630a, 0x012e, 0x0804,
-	0x5f8d, 0x012e, 0x0804, 0x5f7c, 0x0126, 0x00c6, 0x2091, 0x8000,
-	0x7007, 0x0001, 0x684c, 0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb048,
-	0x6000, 0xa084, 0xfcff, 0x6002, 0x00ce, 0x0448, 0x6858, 0xa005,
-	0x05d0, 0x685c, 0xa065, 0x0598, 0x2001, 0xad30, 0x2004, 0xa005,
-	0x0118, 0x080c, 0x974e, 0x0068, 0x6013, 0x0400, 0x6057, 0x0000,
-	0x694c, 0xd1a4, 0x0110, 0x6950, 0x6156, 0x2009, 0x0041, 0x080c,
-	0x80a7, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000, 0x1140, 0x0026,
-	0x2009, 0x0000, 0x2011, 0xfdff, 0x080c, 0x663f, 0x002e, 0x684c,
-	0xd0c4, 0x0148, 0x2061, 0xb048, 0x6000, 0xd08c, 0x1120, 0x6008,
-	0x8000, 0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5f7f, 0x00ce,
-	0x012e, 0x0804, 0x5f79, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186,
-	0x002d, 0x0d28, 0xa186, 0x0045, 0x0510, 0xa186, 0x002a, 0x1130,
-	0x2001, 0xad0c, 0x200c, 0xc194, 0x2102, 0x08c8, 0xa186, 0x0020,
-	0x0170, 0xa186, 0x0029, 0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f,
-	0x080c, 0x4cdc, 0x1960, 0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c,
-	0xa065, 0x09a8, 0x2001, 0xafa3, 0x2004, 0x6016, 0x0800, 0x685c,
-	0xa065, 0x0968, 0x00e6, 0x6860, 0xa075, 0x2001, 0xad30, 0x2004,
-	0xa005, 0x0150, 0x080c, 0x974e, 0x8eff, 0x0118, 0x2e60, 0x080c,
-	0x974e, 0x00ee, 0x0804, 0x5e3f, 0x6020, 0xc0dc, 0xc0d5, 0x6022,
-	0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b,
-	0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x67a8,
-	0x080c, 0x6c50, 0x00ee, 0x0804, 0x5e3f, 0x2061, 0xb048, 0x6000,
-	0xd084, 0x0190, 0xd08c, 0x1904, 0x5f8d, 0x0126, 0x2091, 0x8000,
-	0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x5f8d, 0x012e,
-	0x6853, 0x0016, 0x0804, 0x5f86, 0x6853, 0x0007, 0x0804, 0x5f86,
-	0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5b99, 0x0078,
-	0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007,
-	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x5ee0, 0x0005,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x2009, 0xad30, 0x210c, 0x81ff,
-	0x1904, 0x5f5b, 0x2009, 0xad0c, 0x210c, 0xd194, 0x1904, 0x5f63,
-	0x6848, 0x2070, 0xae82, 0xb400, 0x0a04, 0x5f4f, 0x2001, 0xad16,
-	0x2004, 0xae02, 0x1a04, 0x5f4f, 0x2061, 0xb048, 0x6100, 0xa184,
-	0x0301, 0xa086, 0x0001, 0x15a8, 0x711c, 0xa186, 0x0006, 0x15b0,
-	0x7018, 0xa005, 0x0904, 0x5f5b, 0x2004, 0xd0e4, 0x1904, 0x5f5e,
-	0x7020, 0xd0dc, 0x1904, 0x5f66, 0x6853, 0x0000, 0x6803, 0x0000,
-	0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c, 0xd0f4, 0x1904,
-	0x5f69, 0x2e60, 0x080c, 0x65aa, 0x012e, 0x00ee, 0x0005, 0x2068,
-	0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x15c8,
-	0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee, 0x6853, 0x0006, 0x0804,
-	0x5f86, 0xd184, 0x0dc0, 0xd1c4, 0x11a8, 0x00b8, 0x6944, 0xa18c,
-	0xff00, 0x810f, 0x080c, 0x4cdc, 0x11c8, 0x6000, 0xd0e4, 0x11b0,
-	0x711c, 0xa186, 0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853,
-	0x0008, 0x0070, 0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040,
-	0x6853, 0x0035, 0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029,
-	0x012e, 0x00ee, 0x0418, 0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045,
-	0x0cb8, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x080c, 0xa566,
-	0x012e, 0x00ee, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004,
-	0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009,
-	0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x510c, 0x012e, 0x0005, 0x080c, 0x15f0, 0x0005,
-	0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x7072,
-	0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072, 0x1230,
-	0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132,
-	0x0005, 0x00d6, 0x080c, 0x65a1, 0x00de, 0x0005, 0x00d6, 0x2011,
-	0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1,
-	0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118,
-	0xa086, 0x1000, 0x1540, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00,
-	0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x1118, 0x080c, 0x61c6,
-	0x00b0, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84,
-	0x0007, 0x1188, 0xac82, 0xb400, 0x0270, 0x6858, 0xac02, 0x1258,
-	0x6120, 0xd1f4, 0x1160, 0x2009, 0x0047, 0x080c, 0x80a7, 0x7a1c,
-	0xd284, 0x1968, 0x0005, 0xa016, 0x080c, 0x1824, 0x0cc0, 0x0cd8,
-	0x781c, 0xd08c, 0x0500, 0x0156, 0x0136, 0x0146, 0x20e1, 0x3000,
-	0x3d20, 0x3e28, 0xa584, 0x0076, 0x1530, 0xa484, 0x7000, 0xa086,
-	0x1000, 0x11a8, 0x080c, 0x604e, 0x01f0, 0x20e1, 0x3000, 0x7828,
-	0x7828, 0x080c, 0x606a, 0x014e, 0x013e, 0x015e, 0x2009, 0xafcf,
-	0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6c50, 0x0ce0, 0xa484,
-	0x7000, 0x1518, 0x0499, 0x01b8, 0x7000, 0xa084, 0xff00, 0xa086,
-	0x8100, 0x0d18, 0x0080, 0xd5a4, 0x0158, 0x080c, 0x1d86, 0x20e1,
-	0x9010, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0048,
-	0x00e9, 0x6883, 0x0000, 0x080c, 0xac59, 0x20e1, 0x3000, 0x7828,
-	0x7828, 0x014e, 0x013e, 0x015e, 0x08b0, 0x0081, 0x1130, 0x7000,
-	0xa084, 0xff00, 0xa086, 0x8100, 0x1d70, 0x080c, 0xac59, 0x20e1,
-	0x3000, 0x7828, 0x7828, 0x080c, 0x642d, 0x0c58, 0xa484, 0x01ff,
-	0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac,
-	0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x0005, 0x20a9,
-	0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085,
-	0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007,
-	0xa196, 0x0000, 0x1118, 0x0804, 0x62cf, 0x0005, 0xa196, 0x2000,
-	0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c, 0x41d1, 0x0ca8,
-	0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c, 0x6372, 0x0c68,
-	0x00c6, 0x6a80, 0x82ff, 0x0904, 0x61c0, 0x7110, 0xa18c, 0xff00,
-	0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023, 0x1904, 0x61c0,
-	0xa08e, 0x0023, 0x1570, 0x080c, 0x6408, 0x0904, 0x61c0, 0x7124,
-	0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034, 0xa005, 0x1904,
-	0x61c0, 0x2009, 0x0015, 0x080c, 0x80a7, 0x0804, 0x61c0, 0xa08e,
-	0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c,
-	0x80a7, 0x0804, 0x61c0, 0xa08e, 0x0100, 0x1904, 0x61c0, 0x7034,
-	0xa005, 0x1904, 0x61c0, 0x2009, 0x0016, 0x080c, 0x80a7, 0x0804,
-	0x61c0, 0xa08e, 0x0022, 0x1904, 0x61c0, 0x7030, 0xa08e, 0x0300,
-	0x1580, 0x68d0, 0xd0a4, 0x0528, 0xc0b5, 0x68d2, 0x7100, 0xa18c,
-	0x00ff, 0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6,
-	0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26a0,
-	0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2676, 0x694e,
-	0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0xad00, 0x70a2,
-	0x00ee, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0017, 0x0804,
-	0x6193, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005, 0x1904, 0x61c0,
-	0x68d0, 0xc0a5, 0x68d2, 0x2009, 0x0030, 0x0804, 0x6193, 0xa08e,
-	0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0018,
-	0x0804, 0x6193, 0xa08e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804,
-	0x6193, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x6193,
-	0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904, 0x61c0, 0x2009,
-	0x001b, 0x0804, 0x6193, 0xa08e, 0x5000, 0x1140, 0x7034, 0xa005,
-	0x1904, 0x61c0, 0x2009, 0x001c, 0x0804, 0x6193, 0xa08e, 0x1300,
-	0x1120, 0x2009, 0x0034, 0x0804, 0x6193, 0xa08e, 0x1200, 0x1140,
-	0x7034, 0xa005, 0x1904, 0x61c0, 0x2009, 0x0024, 0x0804, 0x6193,
-	0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009, 0x002d, 0x04d8,
-	0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009, 0x002a, 0x0498,
-	0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468, 0xa08e, 0x5300,
-	0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011, 0xb28d, 0x8208,
-	0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015,
-	0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3c5c, 0x004e, 0x8108,
-	0x1f04, 0x6176, 0x2009, 0x0023, 0x0070, 0xa08e, 0x6000, 0x1118,
-	0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118, 0x2009, 0x0045,
-	0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xb283, 0x2204, 0x8211,
-	0x220c, 0x080c, 0x2676, 0x1530, 0x080c, 0x4c80, 0x1518, 0x6612,
-	0x6516, 0x86ff, 0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158,
-	0x686c, 0xa606, 0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118,
-	0x6000, 0xc0f5, 0x6002, 0x00c6, 0x080c, 0x8022, 0x0168, 0x001e,
-	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x80a7,
-	0x00ce, 0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046,
-	0x080c, 0x6221, 0x1904, 0x621e, 0xa184, 0xff00, 0x8007, 0xa086,
-	0x0008, 0x1904, 0x621e, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x6408,
-	0x0904, 0x621e, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140,
-	0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x80a7, 0x04b0,
-	0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016,
-	0x080c, 0x80a7, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e,
-	0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xb283, 0x2204,
-	0x8211, 0x220c, 0x080c, 0x2676, 0x11c0, 0x080c, 0x4c80, 0x11a8,
-	0x6612, 0x6516, 0x00c6, 0x080c, 0x8022, 0x0170, 0x001e, 0x611a,
-	0x080c, 0x9956, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c,
-	0x80a7, 0x080c, 0x6c50, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce,
-	0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156,
-	0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1df2,
-	0x1590, 0x080c, 0x1ce2, 0x05c8, 0x04d9, 0x1130, 0x7908, 0xa18c,
-	0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000,
-	0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a,
-	0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0401,
-	0x1120, 0xa08a, 0x0140, 0x1a0c, 0x14f6, 0x80ac, 0x20e1, 0x6000,
-	0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803,
-	0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e,
-	0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa085, 0x0001, 0x0c98,
-	0x0006, 0x2001, 0x0111, 0x2004, 0xa084, 0x0003, 0x000e, 0x0005,
-	0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0xa696, 0x00ff, 0x1198,
-	0xa596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x62ca, 0xa596,
-	0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8, 0xa596, 0xfffc, 0x1118,
-	0x2009, 0x0080, 0x04b8, 0x2011, 0x0000, 0x2019, 0xad34, 0x231c,
-	0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff, 0x2071, 0xae34,
-	0x0030, 0x2021, 0x0081, 0x20a9, 0x007e, 0x2071, 0xaeb5, 0x2e1c,
-	0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410, 0xc2fd, 0x0080, 0x2368,
-	0x6f10, 0x0006, 0x2100, 0xa706, 0x000e, 0x6b14, 0x1120, 0xa346,
-	0x1110, 0x2408, 0x0078, 0x87ff, 0x1110, 0x83ff, 0x0d58, 0x8420,
-	0x8e70, 0x1f04, 0x62a7, 0x82ff, 0x1118, 0xa085, 0x0001, 0x0018,
-	0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee, 0x004e, 0x0005, 0xa084,
-	0x0007, 0x000a, 0x0005, 0x62db, 0x62db, 0x62db, 0x641a, 0x62db,
-	0x62dc, 0x62f1, 0x635d, 0x0005, 0x7110, 0xd1bc, 0x0188, 0x7120,
-	0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a, 0xb400, 0x0248, 0x6858,
-	0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046, 0x080c, 0x80a7,
-	0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x6344, 0x2011, 0xb283,
-	0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1904, 0x6344, 0x080c,
-	0x4c80, 0x1904, 0x6344, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15e0,
-	0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c,
-	0x574f, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
-	0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0530,
-	0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x2009,
-	0x0044, 0x080c, 0x80a7, 0x00c0, 0x00c6, 0x080c, 0x8022, 0x001e,
-	0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
-	0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x67ee, 0x080c, 0x6c50, 0x00ce, 0x0005, 0x00c6, 0x080c,
-	0x9807, 0x001e, 0x0dc8, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
-	0x7130, 0x6152, 0x6013, 0x0300, 0x6003, 0x0001, 0x6007, 0x0041,
-	0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c38, 0x7110, 0xd1bc, 0x0188,
-	0x7020, 0x2060, 0xac84, 0x0007, 0x1160, 0xac82, 0xb400, 0x0248,
-	0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0045, 0x080c,
-	0x80a7, 0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000,
-	0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b, 0x0005,
-	0x6386, 0x6387, 0x6386, 0x6386, 0x63f0, 0x63fc, 0x0005, 0x7110,
-	0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x63ef, 0x700c, 0x7108,
-	0x080c, 0x2676, 0x1904, 0x63ef, 0x080c, 0x4c80, 0x1904, 0x63ef,
-	0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c, 0x00ff,
-	0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6, 0x080c,
-	0x6408, 0x00ce, 0x0904, 0x63ef, 0x00c6, 0x080c, 0x8022, 0x001e,
-	0x05f0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0002, 0x7120, 0x610a,
-	0x2009, 0x0088, 0x080c, 0x80a7, 0x0490, 0xa28c, 0x00ff, 0xa186,
-	0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00, 0x8217,
-	0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6, 0x080c,
-	0x8022, 0x001e, 0x01e0, 0x611a, 0x080c, 0x9956, 0x601f, 0x0005,
-	0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x80a7, 0x0080, 0x00c6,
-	0x080c, 0x8022, 0x001e, 0x0158, 0x611a, 0x080c, 0x9956, 0x601f,
-	0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x80a7, 0x0005,
-	0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a, 0x2009,
-	0x0089, 0x080c, 0x80a7, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x0041,
-	0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x80a7, 0x0005,
-	0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xb400, 0x0240,
-	0x2001, 0xad16, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001, 0x0005,
-	0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060, 0xac84,
-	0x0007, 0x1150, 0xac82, 0xb400, 0x0238, 0x6858, 0xac02, 0x1220,
-	0x2009, 0x0051, 0x080c, 0x80a7, 0x0005, 0x2031, 0x0105, 0x0069,
-	0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207, 0x0029,
-	0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6, 0x00f6,
-	0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c, 0x8022,
-	0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xb283, 0x2204, 0x8211,
-	0x220c, 0x080c, 0x2676, 0x1580, 0x080c, 0x4c80, 0x1568, 0x6612,
-	0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0x9956, 0x080c,
-	0x15d9, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837, 0x0000,
-	0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98, 0x53a3,
-	0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x67ee, 0x080c, 0x6c50, 0x00fe, 0x00de, 0x00ce, 0x0005,
-	0x080c, 0x8078, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x2071,
-	0xafda, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a, 0x7012,
-	0x7017, 0xb400, 0x7007, 0x0000, 0x7026, 0x702b, 0x7841, 0x7032,
-	0x7037, 0x789d, 0x703b, 0xffff, 0x703f, 0xffff, 0x7042, 0x7047,
-	0x41b3, 0x0005, 0x2071, 0xafda, 0x1d04, 0x64fc, 0x2091, 0x6000,
-	0x700c, 0x8001, 0x700e, 0x1180, 0x700f, 0x0361, 0x7007, 0x0001,
-	0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0148, 0x8109, 0x7142,
-	0x1130, 0x7044, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024,
-	0xa00d, 0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009,
-	0x8109, 0x7126, 0xa186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff,
-	0x1110, 0x7028, 0x080f, 0x7030, 0xa00d, 0x0158, 0x702c, 0x8001,
-	0x702e, 0x1138, 0x702f, 0x0009, 0x8109, 0x7132, 0x1110, 0x7034,
-	0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a, 0x703c,
-	0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x7018, 0xa00d, 0x0158,
-	0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a,
-	0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6522, 0x6523,
-	0x653b, 0x00e6, 0x2071, 0xafda, 0x7018, 0xa005, 0x1120, 0x711a,
-	0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071,
-	0xafda, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e, 0x00ee,
-	0x0005, 0x00e6, 0x2071, 0xafda, 0x6088, 0xa102, 0x0208, 0x618a,
-	0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x4cdc, 0x1158, 0x6088,
-	0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x6c50, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e, 0x7007,
-	0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000,
-	0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c, 0x9846,
-	0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c, 0xa186,
-	0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068, 0x6854,
-	0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a,
-	0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
-	0x0010, 0x080c, 0x9350, 0x012e, 0xac88, 0x0018, 0x7116, 0x2001,
-	0xe400, 0xa102, 0x0220, 0x7017, 0xb400, 0x7007, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0xafda, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee,
-	0x0005, 0x2001, 0xafe3, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071,
-	0xafda, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0xafe6,
-	0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xafda, 0x711a, 0x721e,
-	0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0xb048, 0x00ce,
-	0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb048,
-	0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
-	0xa005, 0x1150, 0x00c6, 0x2061, 0xb048, 0x6014, 0x00ce, 0xa005,
-	0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0,
-	0xa18e, 0x00c0, 0x05b0, 0xd0b4, 0x1138, 0xd0bc, 0x1528, 0x2009,
-	0x0006, 0x080c, 0x661a, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
-	0x0118, 0xa086, 0x0003, 0x15c0, 0x6020, 0xd0d4, 0x0130, 0xc0d4,
-	0x6022, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xad73, 0x2104,
-	0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x80a7, 0x0005, 0x2009,
-	0x0043, 0x080c, 0x80a7, 0x0005, 0xd0fc, 0x0130, 0xa084, 0x0003,
-	0x0118, 0xa086, 0x0003, 0x11c0, 0x2009, 0x0042, 0x080c, 0x80a7,
-	0x0005, 0xd0fc, 0x0150, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0138,
-	0x2009, 0x0041, 0x080c, 0x80a7, 0x0005, 0x0051, 0x0ce8, 0x2009,
-	0x0043, 0x080c, 0x80a7, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005,
-	0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068,
-	0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c, 0xa18c,
-	0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb048, 0x6200,
-	0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce, 0x080c,
-	0x510c, 0x6010, 0xa06d, 0x190c, 0x65aa, 0x00de, 0x0005, 0x0156,
-	0x00c6, 0x2061, 0xb048, 0x6000, 0x81ff, 0x0110, 0xa205, 0x0008,
-	0xa204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c, 0x1138,
-	0x6808, 0xa005, 0x0120, 0x8001, 0x680a, 0xa085, 0x0001, 0x0005,
-	0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
-	0x1f04, 0x665c, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
-	0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
-	0x1220, 0x1f04, 0x666c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
-	0x666c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
-	0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091,
-	0x2800, 0x2079, 0xafc7, 0x012e, 0x00d6, 0x2069, 0xafc7, 0x6803,
-	0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001, 0x206a, 0x00de,
-	0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084, 0x0007, 0x0002,
-	0x66aa, 0x66cb, 0x671e, 0x66b0, 0x66cb, 0x66aa, 0x66a8, 0x66a8,
-	0x080c, 0x14f6, 0x080c, 0x6581, 0x080c, 0x6c50, 0x00ce, 0x0005,
-	0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x481b, 0x080c,
-	0x650d, 0x7828, 0xa092, 0x00c8, 0x1228, 0x8000, 0x782a, 0x080c,
-	0x4855, 0x0c88, 0x080c, 0x481b, 0x7807, 0x0003, 0x7827, 0x0000,
-	0x782b, 0x0000, 0x0c40, 0x080c, 0x6581, 0x3c00, 0x0006, 0x2011,
-	0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178,
-	0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c,
-	0x14f6, 0x2009, 0x0013, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x3900,
-	0xa082, 0xb0e8, 0x1210, 0x080c, 0x7d8d, 0x00c6, 0x7824, 0xa065,
-	0x090c, 0x14f6, 0x7804, 0xa086, 0x0004, 0x0904, 0x675e, 0x7828,
-	0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce, 0x080c, 0x7827,
-	0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6, 0x2071, 0xad00,
-	0x70dc, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100,
-	0x2071, 0xad00, 0x080c, 0x485e, 0x00ee, 0x00ce, 0x080c, 0xaca2,
-	0x2009, 0x0014, 0x080c, 0x80a7, 0x00ce, 0x0838, 0x2001, 0xafe3,
-	0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824,
-	0xa065, 0x090c, 0x14f6, 0x2009, 0x0013, 0x080c, 0x80fb, 0x00ce,
-	0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0xb0e8, 0x1210, 0x080c,
-	0x7d8d, 0x7824, 0xa005, 0x090c, 0x14f6, 0x781c, 0xa06d, 0x090c,
-	0x14f6, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160, 0x080c, 0x8078,
-	0x693c, 0x81ff, 0x090c, 0x14f6, 0x8109, 0x693e, 0x6854, 0xa015,
-	0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827,
-	0x0000, 0x00de, 0x00ce, 0x080c, 0x6c50, 0x0888, 0x6104, 0xa186,
-	0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804, 0x66f7, 0x7808,
-	0xac06, 0x0904, 0x66f7, 0x080c, 0x6b73, 0x080c, 0x67ee, 0x00ce,
-	0x080c, 0x6c50, 0x0804, 0x66e5, 0x00c6, 0x6027, 0x0002, 0x62c8,
-	0x60c4, 0xa205, 0x1178, 0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009,
-	0x0049, 0x080c, 0x80a7, 0x00ce, 0x0005, 0x2011, 0xafe6, 0x2013,
-	0x0000, 0x0cc8, 0x3908, 0xa192, 0xb0e8, 0x1210, 0x080c, 0x7d8d,
-	0x793c, 0x81ff, 0x0d90, 0x793c, 0xa188, 0x0007, 0x210c, 0xa18e,
-	0x0006, 0x1138, 0x6014, 0xa084, 0x0184, 0xa085, 0x0012, 0x6016,
-	0x0c10, 0x6014, 0xa084, 0x0184, 0xa085, 0x0016, 0x6016, 0x08d8,
-	0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000,
-	0x2c08, 0x2061, 0xafc7, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
-	0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e,
-	0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xafc7,
-	0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
-	0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x6c56,
-	0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000,
-	0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xafc7, 0x0c18,
-	0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016,
-	0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
-	0xafc7, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080,
-	0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005,
-	0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061,
-	0xafc7, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136,
-	0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0076, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071,
-	0xafc7, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904,
-	0x6889, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x6884,
-	0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6884, 0x703c, 0xac06,
-	0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x7033, 0x0000,
-	0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x003e, 0x7038,
-	0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00,
-	0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
-	0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
-	0x0000, 0x080c, 0x9596, 0x0198, 0x6010, 0x2068, 0x601c, 0xa086,
-	0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
-	0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c, 0x9742, 0x080c,
-	0x974e, 0x00ce, 0x0804, 0x682e, 0x2c78, 0x600c, 0x2060, 0x0804,
-	0x682e, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e, 0x007e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19d0,
-	0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x0006, 0x0066, 0x00c6,
-	0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079,
-	0xafc7, 0x7838, 0xa065, 0x0558, 0x600c, 0x0006, 0x600f, 0x0000,
-	0x783c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64,
-	0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847, 0x0000,
-	0x003e, 0x080c, 0x9596, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086,
-	0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c,
-	0x510c, 0x080c, 0x9742, 0x080c, 0x974e, 0x000e, 0x0898, 0x7e3a,
-	0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005,
-	0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c60, 0x0016,
-	0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x69a9, 0x008e,
-	0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xafc7, 0x2091,
-	0x8000, 0x080c, 0x6a36, 0x080c, 0x6aa8, 0x012e, 0x00fe, 0x0005,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x8cff,
-	0x0904, 0x6985, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
-	0x6980, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6980, 0x7024,
-	0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
-	0x6581, 0x080c, 0x7834, 0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
-	0x04b8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
-	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
-	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9596, 0x0188,
-	0x601c, 0xa086, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa, 0x080c, 0x510c, 0x080c,
-	0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804, 0x690f,
-	0x2c78, 0x600c, 0x2060, 0x0804, 0x690f, 0x012e, 0x000e, 0x001e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
-	0x0006, 0x1128, 0x080c, 0xabfa, 0x080c, 0xa91f, 0x0c10, 0x601c,
-	0xa086, 0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x0968, 0x08c8,
-	0x601c, 0xa086, 0x0005, 0x19a8, 0x6004, 0xa086, 0x0085, 0x0d50,
-	0x0880, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0xa280, 0xae34,
-	0x2004, 0xa065, 0x0904, 0x6a32, 0x00f6, 0x00e6, 0x00d6, 0x0066,
-	0x2071, 0xafc7, 0x6654, 0x7018, 0xac06, 0x1108, 0x761a, 0x701c,
-	0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008, 0x761e,
-	0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000, 0x0110, 0x2f00,
-	0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
-	0x6002, 0x080c, 0x4c07, 0x0904, 0x6a2e, 0x7624, 0x86ff, 0x05e8,
-	0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834, 0x68c3,
-	0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
-	0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
-	0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660,
-	0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003,
-	0x0009, 0x630a, 0x00ce, 0x0804, 0x69d9, 0x8dff, 0x0158, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0xabfa,
-	0x080c, 0x510c, 0x080c, 0x7b88, 0x0804, 0x69d9, 0x006e, 0x00de,
-	0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066,
-	0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x6a88,
-	0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x6581, 0x080c, 0x7834,
-	0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
-	0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010,
-	0x2068, 0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
-	0x9742, 0x080c, 0x974e, 0x080c, 0x7b88, 0x000e, 0x0804, 0x6a3d,
-	0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c,
-	0xa086, 0x0006, 0x1118, 0x080c, 0xa91f, 0x0c58, 0x601c, 0xa086,
-	0x0002, 0x1128, 0x6004, 0xa086, 0x0085, 0x09d0, 0x0c10, 0x601c,
-	0xa086, 0x0005, 0x19f0, 0x6004, 0xa086, 0x0085, 0x0d60, 0x08c8,
-	0x0006, 0x0066, 0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6b0e,
-	0x6054, 0x0006, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4,
-	0xc0dc, 0x6002, 0x080c, 0x4c07, 0x0904, 0x6b0b, 0x7e24, 0x86ff,
-	0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x6581, 0x080c, 0x7834,
-	0x68c3, 0x0000, 0x080c, 0x7ca8, 0x7827, 0x0000, 0x0036, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
-	0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e,
-	0x2660, 0x080c, 0x974e, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660,
-	0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6aba, 0x8dff, 0x0138,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c,
-	0x7b88, 0x0804, 0x6aba, 0x000e, 0x0804, 0x6aad, 0x781e, 0x781a,
-	0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066,
-	0x6000, 0xd0dc, 0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606,
-	0x1158, 0x2071, 0xafc7, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004,
-	0x2004, 0xad06, 0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005,
-	0x00f6, 0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660,
-	0x6003, 0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7834, 0x78c3,
-	0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140,
-	0x7b04, 0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000,
-	0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c,
-	0x7ca8, 0x003e, 0x080c, 0x4c07, 0x00c6, 0x603c, 0xa005, 0x0110,
-	0x8001, 0x603e, 0x2660, 0x080c, 0x8078, 0x00ce, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x080c, 0x97fd, 0x080c, 0x510c, 0x080c,
-	0x7b88, 0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xafc7, 0x7004,
-	0xa084, 0x0007, 0x0002, 0x6b85, 0x6b88, 0x6b9e, 0x6bb7, 0x6bf0,
-	0x6b85, 0x6b83, 0x6b83, 0x080c, 0x14f6, 0x00ce, 0x00ee, 0x0005,
-	0x7024, 0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
-	0x0150, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000,
-	0x00ce, 0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060,
-	0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022,
-	0x0120, 0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027,
-	0x0000, 0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024,
-	0xa065, 0x0598, 0x700c, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c,
-	0xa015, 0x0120, 0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a,
-	0x0410, 0x7014, 0xac06, 0x1160, 0x080c, 0x7b88, 0x600c, 0xa015,
-	0x0120, 0x7216, 0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098,
-	0x6018, 0x2060, 0x080c, 0x4c07, 0x6000, 0xc0dc, 0x6002, 0x080c,
-	0x7b88, 0x701c, 0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e,
-	0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
-	0x7024, 0xa065, 0x0140, 0x080c, 0x7b88, 0x600c, 0xa015, 0x0150,
-	0x720e, 0x600f, 0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x00ce,
-	0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0xafc7,
-	0x6830, 0xa084, 0x0003, 0x0002, 0x6c12, 0x6c14, 0x6c38, 0x6c10,
-	0x080c, 0x14f6, 0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001,
-	0x01b8, 0x683c, 0xa065, 0x0130, 0x600c, 0xa015, 0x0170, 0x6a3a,
-	0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011, 0xafe6,
-	0x2013, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a, 0x6836, 0x0c90,
-	0x6843, 0x0000, 0x6838, 0xa065, 0x0d68, 0x6003, 0x0003, 0x0c50,
-	0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0168,
-	0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
-	0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce, 0x00de, 0x0005,
-	0x00d6, 0x2069, 0xafc7, 0x6804, 0xa084, 0x0007, 0x0002, 0x6c61,
-	0x6cfd, 0x6cfd, 0x6cfd, 0x6cfd, 0x6cff, 0x6c5f, 0x6c5f, 0x080c,
-	0x14f6, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6, 0x680c,
-	0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
-	0x6d49, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150, 0x6807,
-	0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x6d49, 0x00ce, 0x00de,
-	0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x6cf9,
-	0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054, 0xa075,
-	0x0120, 0xa20e, 0x0904, 0x6cf9, 0x0028, 0x6818, 0xa20e, 0x0904,
-	0x6cf9, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70,
-	0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c, 0x804f,
-	0x0904, 0x6cf9, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a, 0xa180,
-	0x0014, 0x2004, 0xa084, 0x00ff, 0x605a, 0xa180, 0x0014, 0x2003,
-	0x0000, 0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001,
-	0x1999, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6,
-	0x2c78, 0x71a0, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd1bc,
-	0x0150, 0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040,
-	0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c, 0x00ff,
-	0x2061, 0x0100, 0x619a, 0x080c, 0x736f, 0x7300, 0xc3dd, 0x7302,
-	0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003,
-	0x7803, 0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de,
-	0x0005, 0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6,
-	0x680c, 0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
-	0x080c, 0x6d49, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069,
-	0xafc7, 0x6830, 0xa086, 0x0000, 0x11c0, 0x2001, 0xad0c, 0x200c,
-	0xd1bc, 0x1550, 0x6838, 0xa07d, 0x0180, 0x6833, 0x0001, 0x683e,
-	0x6847, 0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c,
-	0x1ee6, 0x1130, 0x012e, 0x080c, 0x76a5, 0x00de, 0x00fe, 0x0005,
-	0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015,
-	0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000,
-	0x0c60, 0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x080c, 0x57d1,
-	0x0888, 0x601c, 0xa084, 0x000f, 0x000b, 0x0005, 0x6d57, 0x6d5c,
-	0x7210, 0x732c, 0x6d5c, 0x7210, 0x732c, 0x6d57, 0x6d5c, 0x080c,
-	0x6b73, 0x080c, 0x6c50, 0x0005, 0x0156, 0x0136, 0x0146, 0x00c6,
-	0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x6118, 0x2178,
-	0x79a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150,
-	0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009,
-	0x0000, 0x0028, 0xa1f8, 0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78,
-	0x2061, 0x0100, 0x619a, 0xa08a, 0x0040, 0x1a04, 0x6dd0, 0x0033,
-	0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x6e7c, 0x6ec7,
-	0x6ef4, 0x6fc1, 0x6fef, 0x6ff7, 0x701d, 0x702e, 0x703f, 0x7047,
-	0x705d, 0x7047, 0x70b7, 0x702e, 0x70d8, 0x70e0, 0x703f, 0x70e0,
-	0x70f1, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x6dce,
-	0x6dce, 0x6dce, 0x6dce, 0x6dce, 0x790d, 0x7932, 0x7947, 0x796a,
-	0x798b, 0x701d, 0x6dce, 0x701d, 0x7047, 0x6dce, 0x6ef4, 0x6fc1,
-	0x6dce, 0x7daa, 0x7047, 0x6dce, 0x7dca, 0x7047, 0x6dce, 0x703f,
-	0x6e75, 0x6de0, 0x6dce, 0x7def, 0x7e64, 0x7f3b, 0x6dce, 0x7f4c,
-	0x7018, 0x7f68, 0x6dce, 0x79a0, 0x7fc3, 0x6dce, 0x080c, 0x14f6,
-	0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005,
-	0x6dde, 0x6dde, 0x6dde, 0x6e14, 0x6e32, 0x6e48, 0x080c, 0x14f6,
-	0x00d6, 0x20a1, 0x020b, 0x080c, 0x710e, 0x7810, 0x2068, 0x20a3,
-	0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850,
-	0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0018, 0x080c, 0x7821, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068,
-	0x68a0, 0x2069, 0xad00, 0x6ad0, 0xd2ac, 0x1110, 0xd0bc, 0x0110,
-	0xa085, 0x0001, 0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c,
-	0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f,
-	0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2,
-	0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7821,
-	0x00de, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
-	0x20a3, 0x7800, 0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3,
-	0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
-	0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200,
-	0x20a3, 0x0000, 0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xad05,
-	0x20a9, 0x0004, 0x53a6, 0x2099, 0xad01, 0x20a9, 0x0004, 0x53a6,
-	0x2099, 0xafad, 0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398,
-	0x1f04, 0x6e64, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c,
-	0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x2001, 0xad14, 0x2004,
-	0x609a, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
-	0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0xad51, 0x6804,
-	0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x268a,
-	0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
-	0x2099, 0xad01, 0x53a6, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1138,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001,
-	0xad1b, 0x20a6, 0x2001, 0xad1c, 0x20a6, 0x0040, 0x20a3, 0x0000,
-	0x2001, 0xad14, 0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x710e, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001,
-	0xad34, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa082, 0x007f, 0x0238, 0x2001, 0xad1b, 0x20a6, 0x2001, 0xad1c,
-	0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xad14, 0x2004, 0xa084,
-	0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x60c3,
-	0x0010, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x710e,
-	0x00c6, 0x7818, 0x2060, 0x2001, 0x0000, 0x080c, 0x5037, 0x00ce,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3,
-	0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3,
-	0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904,
-	0x6f83, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xaf8d,
-	0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000,
-	0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001,
-	0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099,
-	0xaf8d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x574f,
-	0x1118, 0xa084, 0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398,
-	0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a9, 0x0004, 0x2099, 0xad05, 0x53a6, 0x20a9, 0x0004,
-	0x2099, 0xad01, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04,
-	0x6f5d, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6f63, 0x2099,
-	0xaf95, 0x3304, 0xc0dd, 0x20a2, 0x2001, 0xad71, 0x2004, 0xd0e4,
-	0x0158, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398,
-	0x33a6, 0x20a9, 0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000,
-	0x1f04, 0x6f7e, 0x0468, 0x2001, 0xad34, 0x2004, 0xd0a4, 0x0140,
-	0x2001, 0xaf8e, 0x2004, 0x60e3, 0x0000, 0x080c, 0x26cb, 0x60e2,
-	0x2099, 0xaf8d, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099,
-	0xad05, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xad01, 0x53a6, 0x20a9,
-	0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fa1, 0x20a9, 0x0008, 0x20a3,
-	0x0000, 0x1f04, 0x6fa7, 0x2099, 0xaf95, 0x20a9, 0x0008, 0x53a6,
-	0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x6fb2, 0x20a9, 0x000a,
-	0x20a3, 0x0000, 0x1f04, 0x6fb8, 0x60c3, 0x0074, 0x080c, 0x7821,
-	0x0005, 0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x2010, 0x20a3,
-	0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51, 0x7904, 0x00fe,
-	0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010,
-	0xa085, 0x0002, 0x00d6, 0x0804, 0x7099, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x710e, 0x20a3, 0x5000, 0x0804, 0x6f0f, 0x20a1,
-	0x020b, 0x080c, 0x710e, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
-	0x20a1, 0x020b, 0x080c, 0x71a2, 0x0020, 0x20a1, 0x020b, 0x080c,
-	0x71aa, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
-	0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6f0f, 0x20a1,
-	0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828,
-	0xa005, 0x0110, 0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2,
-	0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x00d6, 0x20a1, 0x020b,
-	0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
-	0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x1178, 0x6998, 0xa184,
-	0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100, 0x0040, 0x20a3,
-	0x0100, 0x0028, 0x20a3, 0x0400, 0x0010, 0x20a3, 0x0700, 0xa006,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0xad51,
-	0x7904, 0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110,
-	0xa085, 0x0010, 0x2009, 0xad73, 0x210c, 0xd184, 0x1110, 0xa085,
-	0x0002, 0x0026, 0x2009, 0xad71, 0x210c, 0xd1e4, 0x0130, 0xc0c5,
-	0xa094, 0x0030, 0xa296, 0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094,
-	0x0030, 0xa296, 0x0010, 0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2,
-	0x20a2, 0x60c3, 0x0014, 0x080c, 0x7821, 0x00de, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x71aa, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x7821, 0x0005,
-	0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x0804, 0x6e82,
-	0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x7821,
-	0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c,
-	0x71aa, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3,
-	0x0000, 0x60c3, 0x0008, 0x080c, 0x7821, 0x0005, 0x0026, 0x0036,
-	0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0038, 0x0026, 0x0036,
-	0x0046, 0x2019, 0x2200, 0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x11a0,
-	0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011,
-	0xad14, 0x2214, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x0118, 0x2011,
-	0xad1c, 0x2214, 0x22a2, 0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6,
-	0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0xad34,
-	0x2004, 0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6,
-	0x1130, 0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8,
-	0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069,
-	0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8,
-	0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de,
-	0x20a3, 0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0029,
-	0x20a2, 0x004e, 0x003e, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
-	0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x002e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0xad1b,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000,
-	0x08e0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3,
-	0x0000, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3300, 0x2021,
-	0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2300, 0x2021,
-	0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
-	0x02d8, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa305, 0x20a2,
-	0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005, 0x1128,
-	0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0xad1b, 0x2da6,
-	0x8d68, 0x2da6, 0x00de, 0x0080, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
-	0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
-	0x2011, 0xad14, 0x2214, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3,
-	0x0000, 0x004e, 0x003e, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
-	0x0005, 0x080c, 0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
-	0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
-	0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a,
-	0x008c, 0x1a0c, 0x14f6, 0x6118, 0x2178, 0x79a0, 0x2011, 0xad34,
-	0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120,
-	0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8,
-	0x2be6, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
-	0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7247, 0x7251,
-	0x726c, 0x7245, 0x7245, 0x7245, 0x7247, 0x080c, 0x14f6, 0x0146,
-	0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x7821, 0x014e,
-	0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x72b8, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
-	0x080c, 0x7821, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c,
-	0x72f2, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0004, 0x080c, 0x7821, 0x014e, 0x0005, 0x0026,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8100,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
-	0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804, 0x7175,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
-	0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x8400,
-	0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
-	0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
-	0x8400, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011,
-	0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000,
-	0x0804, 0x7201, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
-	0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
-	0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6,
-	0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c,
-	0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3,
-	0x0000, 0x2011, 0xad14, 0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2,
-	0x20a3, 0x0000, 0x0804, 0x7201, 0x00c6, 0x00f6, 0x2c78, 0x7804,
-	0xa08a, 0x0040, 0x0a0c, 0x14f6, 0xa08a, 0x0053, 0x1a0c, 0x14f6,
-	0x7918, 0x2160, 0x61a0, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
-	0xd1bc, 0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff,
-	0x0040, 0x2009, 0x0000, 0x0028, 0xa1e0, 0x2be6, 0x2c0d, 0xa18c,
-	0x00ff, 0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe,
-	0x00ce, 0x0005, 0x736f, 0x747b, 0x7418, 0x761a, 0x736d, 0x736d,
-	0x736d, 0x736d, 0x736d, 0x736d, 0x736d, 0x7b41, 0x7b51, 0x7b61,
-	0x7b71, 0x736d, 0x7f79, 0x736d, 0x7b30, 0x080c, 0x14f6, 0x00d6,
-	0x0156, 0x0146, 0x780b, 0xffff, 0x20a1, 0x020b, 0x080c, 0x73cf,
-	0x7910, 0x2168, 0x6948, 0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2,
-	0x22a2, 0x694c, 0xa184, 0x000f, 0x1118, 0x2001, 0x0005, 0x0040,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0xa084, 0x0006, 0x8004,
-	0x0016, 0x2008, 0x7858, 0xa084, 0x00ff, 0x8007, 0xa105, 0x001e,
-	0x20a2, 0xd1ac, 0x0118, 0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118,
-	0x20a3, 0x0001, 0x0020, 0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80,
-	0x6e7c, 0x20a9, 0x0008, 0x0136, 0xad88, 0x0017, 0x2198, 0x20a1,
-	0x021b, 0x53a6, 0x013e, 0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3,
-	0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009,
-	0x6016, 0x2001, 0xafe3, 0x2003, 0x07d0, 0x2001, 0xafe2, 0x2003,
-	0x0009, 0x080c, 0x17bf, 0x014e, 0x015e, 0x00de, 0x0005, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210,
-	0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004,
-	0x2019, 0xad34, 0x231c, 0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
-	0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814,
-	0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2,
-	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2009, 0xad14, 0x210c,
-	0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000,
-	0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005,
-	0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810,
-	0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c,
-	0x080c, 0x7821, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6,
-	0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814,
-	0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
-	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14, 0x2214,
-	0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2,
-	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x7810,
-	0xa06d, 0x080c, 0x5025, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086,
-	0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c,
-	0x75d0, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
-	0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043,
-	0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005,
-	0x74b2, 0x7547, 0x7550, 0x7579, 0x758c, 0x75a7, 0x75b0, 0x74b0,
-	0x080c, 0x14f6, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118,
-	0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5,
-	0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804,
-	0x7583, 0xa186, 0x0001, 0x190c, 0x14f6, 0x6b78, 0x7820, 0xd0cc,
-	0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
-	0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
-	0x0300, 0x0904, 0x7541, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc,
-	0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020,
-	0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x74f0, 0x015e, 0x22a2,
-	0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7541, 0x20a1, 0x020b,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
-	0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889,
-	0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7810, 0x22a2, 0x20a3,
-	0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7821, 0x0005, 0x2011,
-	0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0488,
-	0x2011, 0x0302, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016,
-	0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500,
-	0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7821,
-	0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2,
-	0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
-	0x0018, 0x080c, 0x7821, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc,
-	0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2,
-	0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7821, 0x0005, 0x2011,
-	0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888,
-	0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001,
-	0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808,
-	0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108,
-	0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7583,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0700,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
-	0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010,
-	0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7810, 0x22a2, 0x20a3,
-	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036,
-	0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e,
-	0x013e, 0x015e, 0x00de, 0x0005, 0x7634, 0x7634, 0x7636, 0x7634,
-	0x7634, 0x7634, 0x7658, 0x7634, 0x080c, 0x14f6, 0x7910, 0xa18c,
-	0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
-	0x00f9, 0x00d6, 0x2069, 0xad51, 0x6804, 0xd0bc, 0x0130, 0x682c,
-	0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de,
-	0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7821, 0x0005,
-	0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085, 0x0100,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xad14,
-	0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c,
-	0x7810, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6,
-	0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xad00, 0x7150,
-	0x7818, 0x2068, 0x68a0, 0x2028, 0x76d0, 0xd6ac, 0x1130, 0xd0bc,
-	0x1120, 0x6910, 0x6a14, 0x7450, 0x0020, 0x6910, 0x6a14, 0x736c,
-	0x7470, 0x781c, 0xa0be, 0x0006, 0x0904, 0x775b, 0xa0be, 0x000a,
-	0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073,
-	0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
-	0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
-	0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
-	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0x609f, 0x0000, 0x080c, 0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084,
-	0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6586, 0x003e,
-	0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d0, 0xd0ac,
-	0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
-	0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
-	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
-	0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
-	0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5,
-	0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120,
-	0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c,
-	0x8014, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110,
-	0x2009, 0x1b58, 0x080c, 0x6586, 0x003e, 0x004e, 0x005e, 0x00ce,
-	0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003,
-	0xa086, 0x0002, 0x0904, 0x77b1, 0x2001, 0xad34, 0x2004, 0xd0ac,
-	0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
-	0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
-	0x00ff, 0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086,
-	0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6,
-	0x707c, 0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928,
-	0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
-	0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8011, 0x0804,
-	0x7749, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138,
-	0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185,
-	0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5025,
-	0x0180, 0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020,
-	0xa086, 0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889,
-	0x0010, 0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084,
-	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086,
-	0x7808, 0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
-	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294,
-	0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120,
-	0x080c, 0x8014, 0x0804, 0x7749, 0x080c, 0x8011, 0x0804, 0x7749,
-	0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
-	0x8217, 0x0005, 0x00d6, 0x2069, 0xafc7, 0x6843, 0x0001, 0x00de,
-	0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019,
-	0x080c, 0x6578, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085,
-	0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6, 0x2061, 0x0100,
-	0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016, 0x00ce, 0x000e,
-	0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x080c, 0x574f, 0x1178, 0x2001, 0xafe3, 0x2004, 0xa005,
-	0x1598, 0x080c, 0x57d1, 0x1118, 0x080c, 0x6578, 0x0468, 0x00c6,
-	0x2061, 0xafc7, 0x00d8, 0x6904, 0xa194, 0x4000, 0x0550, 0x08a1,
-	0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061, 0xafc7, 0x6128,
-	0xa192, 0x00c8, 0x1258, 0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff,
-	0x0198, 0x080c, 0x6578, 0x080c, 0x782b, 0x0070, 0x6124, 0xa1e5,
-	0x0000, 0x0140, 0x080c, 0xaca2, 0x2009, 0x0014, 0x080c, 0x80a7,
-	0x080c, 0x6581, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce,
-	0x0005, 0x2001, 0xafe3, 0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061,
-	0xafc7, 0x6128, 0xa192, 0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce,
-	0x080c, 0x6578, 0x080c, 0x485e, 0x0c38, 0x00c6, 0x00d6, 0x00e6,
-	0x0016, 0x0026, 0x080c, 0x658e, 0x2071, 0xafc7, 0x713c, 0x81ff,
-	0x0570, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x574f, 0x1188,
-	0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c, 0x2160,
-	0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x080c, 0x57d1,
-	0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7a64, 0x003e, 0x713c,
-	0x2160, 0x080c, 0xaca2, 0x2009, 0x004a, 0x080c, 0x80a7, 0x002e,
-	0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x00e6, 0x00d6,
-	0x00c6, 0x0066, 0x0056, 0x0046, 0x0006, 0x0126, 0x2091, 0x8000,
-	0x6018, 0x2068, 0x6ca0, 0x2071, 0xafc7, 0x7018, 0x2068, 0x8dff,
-	0x0198, 0x68a0, 0xa406, 0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010,
-	0x2060, 0x643c, 0x6540, 0x6e48, 0x2d60, 0x080c, 0x4e41, 0x0120,
-	0x080c, 0x7b88, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e, 0x005e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x710e, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x781c,
-	0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xad14, 0x2004,
-	0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010, 0xa006,
-	0x20a2, 0x1f04, 0x7928, 0x20a2, 0x20a2, 0x60c3, 0x002c, 0x080c,
-	0x7821, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x710e,
-	0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
-	0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005, 0x0156,
-	0x0146, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0200, 0x20a3,
-	0x0000, 0x20a9, 0x0006, 0x2011, 0xad40, 0x2019, 0xad41, 0x23a6,
-	0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7957, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7821, 0x014e,
-	0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b,
-	0x080c, 0x7183, 0x080c, 0x7199, 0x7810, 0xa080, 0x0000, 0x2004,
-	0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6,
-	0xa080, 0x0004, 0x8003, 0x60c2, 0x080c, 0x7821, 0x002e, 0x001e,
-	0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c,
-	0x710e, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
-	0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
-	0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x710e,
-	0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808,
-	0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7821,
-	0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x700c, 0x2060, 0x8cff,
-	0x0178, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x600c, 0x0006,
-	0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x7b88, 0x00ce, 0x0c78,
-	0x700f, 0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee,
-	0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026,
-	0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140,
-	0x2071, 0xafc7, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7834,
-	0x68c3, 0x0000, 0x080c, 0x6581, 0x2009, 0x0013, 0x080c, 0x80a7,
-	0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804,
-	0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
-	0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x7a02, 0x7804,
-	0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824,
-	0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e,
-	0x012e, 0x0005, 0x2001, 0xad00, 0x2004, 0xa096, 0x0001, 0x0550,
-	0xa096, 0x0004, 0x0538, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011,
-	0x481b, 0x080c, 0x650d, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158,
-	0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000,
-	0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010,
-	0x1f04, 0x7a3d, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100,
-	0x7803, 0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6,
-	0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069,
-	0x0100, 0x2079, 0x0140, 0x2071, 0xafc7, 0x703c, 0x2060, 0x8cff,
-	0x0904, 0x7ad5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0,
-	0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x658e, 0x080c, 0x20b5,
-	0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169, 0x2404,
-	0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7, 0x0000, 0x68cb,
-	0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071, 0xb01e, 0x6814,
-	0xa084, 0x0184, 0xa085, 0x0012, 0x6816, 0x7803, 0x0008, 0x7003,
-	0x0000, 0x00fe, 0x00ee, 0x200b, 0x0000, 0x004e, 0xa39d, 0x0000,
-	0x1120, 0x2009, 0x0049, 0x080c, 0x80a7, 0x20a9, 0x03e8, 0x6824,
-	0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0,
-	0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd08c, 0x0118, 0x6827,
-	0x0002, 0x0010, 0x1f04, 0x7ab7, 0x7804, 0xa084, 0x1000, 0x0120,
-	0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
-	0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a06, 0x012e, 0x00de,
-	0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0xafc7, 0x6a32,
-	0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006,
-	0x0126, 0x2071, 0xafc7, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000,
-	0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110,
-	0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
-	0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
-	0x974e, 0x080c, 0x7b88, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060,
-	0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
-	0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810, 0x20a2,
-	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804,
-	0x7b80, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000,
-	0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000,
-	0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400,
-	0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x73cf, 0x7810,
-	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
-	0x0089, 0x60c3, 0x0020, 0x080c, 0x7821, 0x014e, 0x015e, 0x0005,
-	0x00e6, 0x2071, 0xafc7, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022,
-	0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7b94, 0x20a2,
-	0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x7614, 0x2660,
-	0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x7c24, 0x8cff, 0x0904,
-	0x7c24, 0x601c, 0xa086, 0x0006, 0x1904, 0x7c1f, 0x88ff, 0x0138,
-	0x2800, 0xac06, 0x1904, 0x7c1f, 0x2039, 0x0000, 0x0050, 0x6018,
-	0xa206, 0x1904, 0x7c1f, 0x85ff, 0x0120, 0x6050, 0xa106, 0x1904,
-	0x7c1f, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x01f0, 0x080c, 0x6581, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c,
-	0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384,
-	0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003,
-	0x0009, 0x630a, 0x0460, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616,
-	0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012,
-	0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000, 0x6010,
-	0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e,
-	0x080c, 0x7b88, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x7bab, 0x2c78,
-	0x600c, 0x2060, 0x0804, 0x7bab, 0xa006, 0x012e, 0x000e, 0x006e,
-	0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000,
-	0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
-	0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7,
-	0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x7c98, 0x601c, 0xa086,
-	0x0006, 0x1904, 0x7c93, 0x87ff, 0x0128, 0x2700, 0xac06, 0x1904,
-	0x7c93, 0x0040, 0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6050,
-	0xa106, 0x15c8, 0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001,
-	0x080c, 0x7a64, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000,
-	0x7047, 0x0000, 0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036,
-	0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c,
-	0x9596, 0x0110, 0x080c, 0xa91f, 0x080c, 0x974e, 0x87ff, 0x1190,
-	0x00ce, 0x0804, 0x7c43, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7c43,
-	0xa006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa7bd, 0x0001, 0x0c88,
-	0x00e6, 0x2071, 0xafc7, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002,
-	0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005,
-	0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0xafc7, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff,
-	0x0518, 0x2200, 0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c,
-	0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00,
-	0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020,
-	0x2c78, 0x600c, 0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e,
-	0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
-	0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xafc7, 0x760c,
-	0x2660, 0x2678, 0x8cff, 0x0904, 0x7d7e, 0x6018, 0xa080, 0x0028,
-	0x2004, 0xa206, 0x1904, 0x7d79, 0x7024, 0xac06, 0x1508, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x0904, 0x7d55, 0x080c, 0x7834, 0x68c3,
-	0x0000, 0x080c, 0x7ca8, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
-	0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e,
-	0x700c, 0xac36, 0x1110, 0x660c, 0x760e, 0x7008, 0xac36, 0x1140,
-	0x2c00, 0xaf36, 0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000,
-	0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678,
-	0x600f, 0x0000, 0x080c, 0x9778, 0x1158, 0x080c, 0x2aff, 0x080c,
-	0x9789, 0x11f0, 0x080c, 0x85f3, 0x00d8, 0x080c, 0x7ca8, 0x08c0,
-	0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0090, 0x6010, 0x2068,
-	0x080c, 0x9596, 0x0168, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742,
-	0x080c, 0x994e, 0x080c, 0x974e, 0x080c, 0x7b88, 0x00ce, 0x0804,
-	0x7d02, 0x2c78, 0x600c, 0x2060, 0x0804, 0x7d02, 0x012e, 0x000e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086,
-	0x0006, 0x1d30, 0x080c, 0xa91f, 0x0c18, 0x0036, 0x0156, 0x0136,
-	0x0146, 0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x28f9,
-	0x1118, 0x8210, 0x8000, 0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020,
-	0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e,
-	0x003e, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
-	0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x2099, 0xafa6, 0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004,
-	0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x080c, 0x7821,
-	0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3, 0x0214,
-	0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084, 0xff00, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7821, 0x0005, 0x00d6,
-	0x0016, 0x2f68, 0x2009, 0x0035, 0x080c, 0x9a34, 0x1904, 0x7e5d,
-	0x20a1, 0x020b, 0x080c, 0x710e, 0x20a3, 0x1300, 0x20a3, 0x0000,
-	0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0580, 0x7818, 0xa080,
-	0x0028, 0x2014, 0x2001, 0xad34, 0x2004, 0xd0ac, 0x11d0, 0xa286,
-	0x007e, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x04b8, 0xa286,
-	0x007f, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0478, 0xd2bc,
-	0x0180, 0xa286, 0x0080, 0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffc,
-	0x0428, 0xa2e8, 0xae34, 0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2,
-	0x00e8, 0x20a3, 0x0000, 0x6098, 0x20a2, 0x00c0, 0x2001, 0xad34,
-	0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082,
-	0x007e, 0x0240, 0x00d6, 0x2069, 0xad1b, 0x2da6, 0x8d68, 0x2da6,
-	0x00de, 0x0020, 0x20a3, 0x0000, 0x6034, 0x20a2, 0x7834, 0x20a2,
-	0x7838, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
-	0x080c, 0x7821, 0x001e, 0x00de, 0x0005, 0x7817, 0x0001, 0x7803,
-	0x0006, 0x001e, 0x00de, 0x0005, 0x00d6, 0x0026, 0x7928, 0x2168,
-	0x691c, 0xa186, 0x0006, 0x01c0, 0xa186, 0x0003, 0x0904, 0x7ed3,
-	0xa186, 0x0005, 0x0904, 0x7ebc, 0xa186, 0x0004, 0x05b8, 0xa186,
-	0x0008, 0x0904, 0x7ec4, 0x7807, 0x0037, 0x7813, 0x1700, 0x080c,
-	0x7f3b, 0x002e, 0x00de, 0x0005, 0x080c, 0x7ef7, 0x2009, 0x4000,
-	0x6800, 0x0002, 0x7e9d, 0x7ea8, 0x7e9f, 0x7ea8, 0x7ea4, 0x7e9d,
-	0x7e9d, 0x7ea8, 0x7ea8, 0x7ea8, 0x7ea8, 0x7e9d, 0x7e9d, 0x7e9d,
-	0x7e9d, 0x7e9d, 0x7ea8, 0x7e9d, 0x7ea8, 0x080c, 0x14f6, 0x6820,
-	0xd0e4, 0x0110, 0xd0cc, 0x0110, 0xa00e, 0x0010, 0x2009, 0x2000,
-	0x6828, 0x20a2, 0x682c, 0x20a2, 0x0804, 0x7eed, 0x080c, 0x7ef7,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x6a00, 0xa286,
-	0x0002, 0x1108, 0xa00e, 0x0488, 0x04d1, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x2009, 0x4000, 0x0448, 0x0491, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x2009, 0x4000, 0xa286, 0x0005, 0x0118, 0xa286, 0x0002,
-	0x1108, 0xa00e, 0x00d0, 0x0419, 0x6810, 0x2068, 0x697c, 0x6810,
-	0xa112, 0x6980, 0x6814, 0xa103, 0x20a2, 0x22a2, 0x7928, 0xa180,
-	0x0000, 0x2004, 0xa08e, 0x0002, 0x0130, 0xa08e, 0x0004, 0x0118,
-	0x2009, 0x4000, 0x0010, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000,
-	0x60c3, 0x0018, 0x080c, 0x7821, 0x002e, 0x00de, 0x0005, 0x0036,
-	0x0046, 0x0056, 0x0066, 0x20a1, 0x020b, 0x080c, 0x71aa, 0xa006,
-	0x20a3, 0x0200, 0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818,
-	0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1118,
-	0xa092, 0x007e, 0x0268, 0x00d6, 0x2069, 0xad1b, 0x2d2c, 0x8d68,
-	0x2d34, 0xa0e8, 0xae34, 0x2d6c, 0x6b10, 0x6c14, 0x00de, 0x0030,
-	0x2019, 0x0000, 0x6498, 0x2029, 0x0000, 0x6634, 0x7828, 0xa080,
-	0x0007, 0x2004, 0xa086, 0x0003, 0x1128, 0x25a2, 0x26a2, 0x23a2,
-	0x24a2, 0x0020, 0x23a2, 0x24a2, 0x25a2, 0x26a2, 0x006e, 0x005e,
-	0x004e, 0x003e, 0x0005, 0x20a1, 0x020b, 0x080c, 0x71aa, 0x20a3,
-	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3,
-	0x0008, 0x080c, 0x7821, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7106,
-	0x20a3, 0x1400, 0x20a3, 0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2,
-	0x7828, 0x20a2, 0x782c, 0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007,
-	0x20a2, 0x20a3, 0x0000, 0x60c3, 0x0010, 0x080c, 0x7821, 0x0005,
-	0x20a1, 0x020b, 0x080c, 0x71a2, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x7828, 0x20a2, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7821,
-	0x0005, 0x0146, 0x20a1, 0x020b, 0x0031, 0x60c3, 0x0000, 0x080c,
-	0x7821, 0x014e, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0x2011, 0xad34, 0x2214, 0xd2ac, 0x1110,
-	0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810, 0xa085,
-	0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xad1b, 0x2da6, 0x8d68,
-	0x2da6, 0x00de, 0x0078, 0x00d6, 0xa0e8, 0xae34, 0x2d6c, 0x6810,
-	0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000,
-	0x6234, 0x22a2, 0x20a3, 0x0819, 0x20a3, 0x0000, 0x080c, 0x7810,
-	0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x7a08, 0x22a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x0005, 0x20a1, 0x020b, 0x0079, 0x7910, 0x21a2,
-	0x20a3, 0x0000, 0x60c3, 0x0000, 0x20e1, 0x9080, 0x60a7, 0x9575,
-	0x080c, 0x782b, 0x080c, 0x6578, 0x0005, 0x0156, 0x0136, 0x0036,
-	0x00d6, 0x00e6, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7854, 0x2068,
-	0xadf0, 0x000f, 0x7210, 0xa296, 0x00c0, 0xa294, 0xfffd, 0x7212,
-	0x7214, 0xa294, 0x0300, 0x7216, 0x7100, 0xa194, 0x00ff, 0x7308,
-	0xa384, 0x00ff, 0xa08d, 0xc200, 0x7102, 0xa384, 0xff00, 0xa215,
-	0x720a, 0x7004, 0x720c, 0x700e, 0x7206, 0x20a9, 0x000a, 0x2e98,
-	0x53a6, 0x60a3, 0x0035, 0x6a38, 0xa294, 0x7000, 0xa286, 0x3000,
-	0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x003e, 0x013e, 0x015e,
-	0x0005, 0x2009, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036,
-	0x6116, 0x0005, 0x2061, 0xb400, 0x2a70, 0x7064, 0x7046, 0x704b,
-	0xb400, 0x0005, 0x00e6, 0x0126, 0x2071, 0xad00, 0x2091, 0x8000,
-	0x7544, 0xa582, 0x0010, 0x0608, 0x7048, 0x2060, 0x6000, 0xa086,
-	0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0,
-	0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8,
-	0x0018, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085, 0x0001, 0x012e,
-	0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6,
-	0x2071, 0xad00, 0x7544, 0xa582, 0x0010, 0x0600, 0x7048, 0x2060,
-	0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018, 0x7058, 0xac02,
-	0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98, 0x6003, 0x0008, 0x8529,
-	0x7546, 0xaca8, 0x0018, 0x7058, 0xa502, 0x1228, 0x754a, 0xa085,
-	0x0001, 0x00ee, 0x0005, 0x704b, 0xb400, 0x0cc8, 0xa006, 0x0cc8,
-	0xac82, 0xb400, 0x0a0c, 0x14f6, 0x2001, 0xad16, 0x2004, 0xac02,
-	0x1a0c, 0x14f6, 0xa006, 0x6006, 0x600a, 0x600e, 0x6012, 0x6016,
-	0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6052, 0x6056, 0x6022,
-	0x6026, 0x602a, 0x602e, 0x6032, 0x6036, 0x603a, 0x603e, 0x2061,
-	0xad00, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0cc0, 0x601c,
-	0xa084, 0x000f, 0x0002, 0x80b6, 0x80c5, 0x80e0, 0x80fb, 0x9a61,
-	0x9a7c, 0x9a97, 0x80b6, 0x80c5, 0x80b6, 0x8116, 0xa186, 0x0013,
-	0x1128, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x0005, 0xa18e, 0x0047,
-	0x1118, 0xa016, 0x080c, 0x1824, 0x0005, 0x0066, 0x6000, 0xa0b2,
-	0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x80de, 0x8478,
-	0x862d, 0x80de, 0x86a2, 0x81cf, 0x80de, 0x80de, 0x840a, 0x8a91,
-	0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x80de, 0x080c, 0x14f6,
-	0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e,
-	0x0005, 0x80f9, 0x909a, 0x80f9, 0x80f9, 0x80f9, 0x80f9, 0x80f9,
-	0x80f9, 0x9045, 0x9200, 0x80f9, 0x90c7, 0x913e, 0x90c7, 0x913e,
-	0x80f9, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
-	0x14f6, 0x0013, 0x006e, 0x0005, 0x8114, 0x8ad2, 0x8b98, 0x8cb8,
-	0x8e12, 0x8114, 0x8114, 0x8114, 0x8aac, 0x8ff5, 0x8ff8, 0x8114,
-	0x8114, 0x8114, 0x8114, 0x9022, 0x080c, 0x14f6, 0x0066, 0x6000,
-	0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x812f,
-	0x812f, 0x812f, 0x8152, 0x81a5, 0x812f, 0x812f, 0x812f, 0x8131,
-	0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x812f, 0x080c,
-	0x14f6, 0xa186, 0x0003, 0x190c, 0x14f6, 0x00d6, 0x6003, 0x0003,
-	0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a, 0x6880,
-	0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x00de, 0x2c10, 0x080c,
-	0x1e6e, 0x080c, 0x680b, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d0d,
-	0x012e, 0x0005, 0xa182, 0x0047, 0x0002, 0x815e, 0x815e, 0x8160,
-	0x817f, 0x815e, 0x815e, 0x815e, 0x815e, 0x8191, 0x080c, 0x14f6,
-	0x00d6, 0x0016, 0x080c, 0x6c05, 0x080c, 0x6d0d, 0x6003, 0x0004,
-	0x6110, 0x2168, 0x6854, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116,
-	0x684f, 0x0020, 0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882,
-	0x6897, 0x0000, 0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c,
-	0x6c05, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0120, 0x684b,
-	0x0006, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c, 0x6d0d,
-	0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110, 0x2168,
-	0x080c, 0x9596, 0x0120, 0x684b, 0x0029, 0x080c, 0x510c, 0x00de,
-	0x080c, 0x8078, 0x080c, 0x6d0d, 0x0005, 0xa182, 0x0047, 0x0002,
-	0x81b3, 0x81c2, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1, 0x81b1,
-	0x81b1, 0x080c, 0x14f6, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4,
-	0x684e, 0x00de, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c,
-	0x1824, 0x0005, 0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853,
-	0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x0005, 0xa1b6,
-	0x0015, 0x1118, 0x080c, 0x8078, 0x0030, 0xa1b6, 0x0016, 0x190c,
-	0x14f6, 0x080c, 0x8078, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010,
-	0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0,
-	0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002,
-	0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x81ea, 0x00e6, 0x080c,
-	0x9596, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
-	0x00ee, 0x080c, 0x8078, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386,
-	0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd,
-	0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103,
-	0x6b32, 0x080c, 0x8078, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9,
-	0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
-	0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080,
-	0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037,
-	0x0103, 0x00ee, 0x080c, 0x8078, 0x001e, 0x0005, 0x0016, 0x2009,
-	0x0000, 0x7030, 0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff,
-	0x808e, 0x703c, 0xa084, 0x00ff, 0x8086, 0xa080, 0x0004, 0xa108,
-	0x21a8, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0,
-	0x080c, 0x48be, 0x00e6, 0x080c, 0x9596, 0x0140, 0x6010, 0x2070,
-	0x7007, 0x0000, 0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c,
-	0x8078, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68,
-	0x0016, 0x2009, 0x0035, 0x080c, 0x9a34, 0x001e, 0x1168, 0x0026,
-	0x6228, 0x2268, 0x002e, 0x2071, 0xb28c, 0x6b1c, 0xa386, 0x0003,
-	0x0130, 0xa386, 0x0006, 0x0128, 0x080c, 0x8078, 0x0020, 0x0031,
-	0x0010, 0x080c, 0x8323, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810,
-	0x2078, 0xa186, 0x0015, 0x0904, 0x830c, 0xa18e, 0x0016, 0x1904,
-	0x8321, 0x700c, 0xa084, 0xff00, 0xa086, 0x1700, 0x1904, 0x82eb,
-	0x8fff, 0x0904, 0x831f, 0x6808, 0xa086, 0xffff, 0x1904, 0x830e,
-	0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810,
-	0xa106, 0x1904, 0x830e, 0x7980, 0x7814, 0xa106, 0x1904, 0x830e,
-	0x080c, 0x9742, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4,
-	0x784e, 0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6665,
-	0x7854, 0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138,
-	0x00c6, 0x2d60, 0x080c, 0x9374, 0x00ce, 0x0804, 0x831f, 0x00c6,
-	0x00d6, 0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4993, 0x0010,
-	0x080c, 0x4b7c, 0x00de, 0x00ce, 0x1548, 0x00c6, 0x2d60, 0x080c,
-	0x8078, 0x00ce, 0x04a0, 0x7008, 0xa086, 0x000b, 0x11a0, 0x6018,
-	0x200c, 0xc1bc, 0x2102, 0x00c6, 0x2d60, 0x7853, 0x0003, 0x6007,
-	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8, 0x080c,
-	0x6c50, 0x00ce, 0x00e0, 0x700c, 0xa086, 0x2a00, 0x1138, 0x2001,
-	0xafa5, 0x2004, 0x683e, 0x0098, 0x0471, 0x0098, 0x8fff, 0x090c,
-	0x14f6, 0x00c6, 0x00d6, 0x2d60, 0x2f68, 0x684b, 0x0003, 0x080c,
-	0x926f, 0x080c, 0x9742, 0x080c, 0x974e, 0x00de, 0x00ce, 0x080c,
-	0x8078, 0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xafa5,
-	0x2004, 0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00,
-	0x2060, 0x080c, 0xabb4, 0x080c, 0x6618, 0x080c, 0x8078, 0x00ce,
-	0x080c, 0x8078, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80,
-	0x7b7c, 0xd2f4, 0x0130, 0x2001, 0xafa5, 0x2004, 0x683e, 0x0804,
-	0x839d, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x6804, 0xa086,
-	0x0050, 0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007,
-	0x0050, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x04f0, 0x6800,
-	0xa086, 0x000f, 0x01c8, 0x8fff, 0x090c, 0x14f6, 0x6820, 0xd0dc,
-	0x1198, 0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180,
-	0x784c, 0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852,
-	0x2001, 0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0,
-	0x784c, 0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0,
-	0x0c38, 0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406,
-	0x0d58, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e,
-	0x080c, 0x9894, 0x080c, 0x6c50, 0x0010, 0x080c, 0x8078, 0x004e,
-	0x003e, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068,
-	0x6a1c, 0xa286, 0x0007, 0x0904, 0x83ee, 0xa286, 0x0002, 0x05f0,
-	0xa286, 0x0000, 0x05d8, 0x6808, 0x6338, 0xa306, 0x15b8, 0x2071,
-	0xb28c, 0xa186, 0x0015, 0x0560, 0xa18e, 0x0016, 0x1190, 0x6030,
-	0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c, 0xa086, 0x2a00,
-	0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd, 0xc1f5, 0x2102,
-	0x00b8, 0x00c6, 0x6034, 0x2060, 0x6010, 0x2068, 0x080c, 0x9596,
-	0x090c, 0x14f6, 0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ce, 0x0030,
-	0x6034, 0x2070, 0x2001, 0xafa5, 0x2004, 0x703e, 0x080c, 0x8078,
-	0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9, 0x000e, 0x2e98,
-	0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1148, 0x6018, 0x2068,
-	0x7038, 0x680a, 0x703c, 0x680e, 0x6800, 0xc08d, 0x6802, 0x00de,
-	0x0804, 0x81f6, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b2,
-	0x0040, 0x1a04, 0x846e, 0x0002, 0x8462, 0x8456, 0x8462, 0x8462,
-	0x8462, 0x8462, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
-	0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
-	0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
-	0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8462, 0x8462, 0x8454,
-	0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8454, 0x8454, 0x8454,
-	0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8462, 0x8462,
-	0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454, 0x8454,
-	0x8454, 0x8462, 0x8454, 0x8454, 0x080c, 0x14f6, 0x6003, 0x0001,
-	0x6106, 0x080c, 0x67ee, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
-	0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x67ee, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x2600, 0x0002,
-	0x8462, 0x8476, 0x8476, 0x8462, 0x8462, 0x8476, 0x080c, 0x14f6,
-	0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x0904,
-	0x8518, 0xa1b6, 0x0027, 0x1904, 0x84de, 0x080c, 0x6b73, 0x6004,
-	0x080c, 0x9778, 0x0188, 0x080c, 0x9789, 0x0904, 0x84d8, 0xa08e,
-	0x0021, 0x0904, 0x84db, 0xa08e, 0x0022, 0x0904, 0x84d8, 0xa08e,
-	0x003d, 0x0904, 0x84db, 0x04a8, 0x080c, 0x2aff, 0x2001, 0x0007,
-	0x080c, 0x4c30, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
-	0xa186, 0x007e, 0x1148, 0x2001, 0xad34, 0x2014, 0xc285, 0x080c,
-	0x574f, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110,
-	0x2019, 0x0028, 0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c,
-	0x681d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x4ecf, 0x00ce,
-	0x2c08, 0x080c, 0xa712, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c,
-	0x4c9f, 0x080c, 0x994e, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
-	0x080c, 0x85f3, 0x0cb0, 0x080c, 0x8621, 0x0c98, 0xa186, 0x0014,
-	0x1db0, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x080c, 0x9778, 0x1188,
-	0x080c, 0x2aff, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x85f3,
-	0xa186, 0x007e, 0x1128, 0x2001, 0xad34, 0x200c, 0xc185, 0x2102,
-	0x08c0, 0x080c, 0x9789, 0x1118, 0x080c, 0x85f3, 0x0890, 0x6004,
-	0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
-	0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e,
-	0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x85f3, 0x0804, 0x84d1,
-	0xa0b2, 0x0040, 0x1a04, 0x85db, 0x2008, 0x0002, 0x8560, 0x8561,
-	0x8564, 0x8567, 0x856a, 0x856d, 0x855e, 0x855e, 0x855e, 0x855e,
-	0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
-	0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
-	0x855e, 0x855e, 0x855e, 0x855e, 0x8570, 0x857f, 0x855e, 0x8581,
-	0x857f, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x857f, 0x857f,
-	0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e, 0x855e,
-	0x85bb, 0x857f, 0x855e, 0x857b, 0x855e, 0x855e, 0x855e, 0x857c,
-	0x855e, 0x855e, 0x855e, 0x857f, 0x85b2, 0x855e, 0x080c, 0x14f6,
-	0x00f0, 0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001,
-	0x0005, 0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400,
-	0x080c, 0x6b73, 0x6003, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e,
-	0x080c, 0x6c50, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4c30, 0x0804,
-	0x85cc, 0x080c, 0x6b73, 0x2001, 0xafa3, 0x2004, 0x6016, 0x2001,
-	0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x6c50, 0x0005,
-	0x080c, 0x4c30, 0x080c, 0x6b73, 0x6003, 0x0002, 0x2001, 0xafa5,
-	0x2004, 0x603e, 0x0036, 0x2019, 0xad5c, 0x2304, 0xa084, 0xff00,
-	0x1120, 0x2001, 0xafa3, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004,
-	0x0ec0, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c,
-	0x6c50, 0x08e8, 0x080c, 0x6b73, 0x080c, 0x994e, 0x080c, 0x8078,
-	0x080c, 0x6c50, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xad81, 0x2079,
-	0x0000, 0x080c, 0x2df1, 0x00fe, 0x00ee, 0x080c, 0x6b73, 0x080c,
-	0x8078, 0x080c, 0x6c50, 0x0818, 0x080c, 0x6b73, 0x2001, 0xafa5,
-	0x2004, 0x603e, 0x6003, 0x0002, 0x2001, 0xafa3, 0x2004, 0x6016,
-	0x080c, 0x6c50, 0x0005, 0x2600, 0x2008, 0x0002, 0x85e6, 0x85e4,
-	0x85e4, 0x85cc, 0x85cc, 0x85e4, 0x080c, 0x14f6, 0x080c, 0x6b73,
-	0x00d6, 0x6010, 0x2068, 0x080c, 0x15f0, 0x00de, 0x080c, 0x8078,
-	0x080c, 0x6c50, 0x0005, 0x00e6, 0x0026, 0x0016, 0x080c, 0x9596,
-	0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139, 0x1148, 0x2001,
-	0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c, 0x9a05, 0x0090,
-	0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016, 0x6004, 0xa08e,
-	0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e, 0x7037, 0x0103,
-	0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005, 0x001e, 0x0009,
-	0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037,
-	0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668,
-	0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x14f6,
-	0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0x99c1, 0x0804, 0x8692,
-	0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0x9971, 0x0804, 0x8692,
-	0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x97b9, 0x0804, 0x8692,
-	0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x97d0, 0x04d8, 0x6604,
-	0xa6b6, 0x001f, 0x1118, 0x080c, 0x81dc, 0x04a0, 0x6604, 0xa6b6,
-	0x0000, 0x1118, 0x080c, 0x83f4, 0x0468, 0x6604, 0xa6b6, 0x0022,
-	0x1118, 0x080c, 0x8204, 0x0430, 0x6604, 0xa6b6, 0x0035, 0x1118,
-	0x080c, 0x826b, 0x00f8, 0x6604, 0xa6b6, 0x0039, 0x1118, 0x080c,
-	0x83a3, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x821e,
-	0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c, 0x823e, 0x0050,
-	0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016, 0x1118,
-	0x0804, 0x883f, 0x0005, 0x080c, 0x80be, 0x0ce0, 0x86b9, 0x86bc,
-	0x86b9, 0x86fe, 0x86b9, 0x87cc, 0x884d, 0x86b9, 0x86b9, 0x881b,
-	0x86b9, 0x882f, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005, 0x3d18,
-	0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x00e6, 0xacf0, 0x0004,
-	0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x8078,
-	0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071, 0xad00, 0x7080,
-	0xa086, 0x0074, 0x1530, 0x080c, 0xa6e9, 0x11b0, 0x00d6, 0x6018,
-	0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc, 0x0110, 0xc0c5,
-	0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c,
-	0x2aff, 0x080c, 0x8078, 0x0078, 0x2001, 0x000a, 0x080c, 0x4c30,
-	0x080c, 0x2aff, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee,
-	0x0010, 0x080c, 0x87bd, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168,
-	0x2001, 0x0000, 0x080c, 0x4c1e, 0x2069, 0xad51, 0x6804, 0xd0a4,
-	0x0120, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x0005, 0x00d6, 0x2011,
-	0xad20, 0x2204, 0xa086, 0x0074, 0x1904, 0x87ba, 0x6018, 0x2068,
-	0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x894d, 0x0804, 0x875e,
-	0x080c, 0x8943, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286,
-	0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
-	0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
-	0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078,
-	0x0804, 0x87bb, 0x00e6, 0x2071, 0xad34, 0x2e04, 0xd09c, 0x0188,
-	0x2071, 0xb280, 0x7108, 0x720c, 0xa18c, 0x00ff, 0x1118, 0xa284,
-	0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc, 0x1110, 0x7112,
-	0x7216, 0x00ee, 0x6010, 0xa005, 0x0128, 0x2068, 0x6838, 0xd0f4,
-	0x0108, 0x0880, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
-	0x6007, 0x0003, 0x080c, 0x67ee, 0x0804, 0x87bb, 0x685c, 0xd0e4,
-	0x01d0, 0x080c, 0x9903, 0x080c, 0x574f, 0x0110, 0xd0dc, 0x1900,
-	0x2011, 0xad34, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xaf8e, 0x2004,
-	0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x26cb, 0x78e2,
-	0x00fe, 0x0804, 0x8728, 0x080c, 0x9937, 0x2011, 0xad34, 0x2204,
-	0xc0a5, 0x2012, 0x0006, 0x080c, 0xa801, 0x000e, 0x1904, 0x8728,
-	0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x00c6, 0x2009,
-	0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe,
-	0x080c, 0x26a0, 0x00f6, 0x2079, 0xad00, 0x7972, 0x2100, 0x2009,
-	0x0000, 0x080c, 0x2676, 0x794e, 0x00fe, 0x8108, 0x080c, 0x4c80,
-	0x2c00, 0x00ce, 0x1904, 0x8728, 0x601a, 0x2001, 0x0002, 0x080c,
-	0x4c30, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
-	0x67ee, 0x0008, 0x0011, 0x00de, 0x0005, 0x2001, 0xad00, 0x2004,
-	0xa086, 0x0003, 0x0120, 0x2001, 0x0007, 0x080c, 0x4c30, 0x080c,
-	0x2aff, 0x080c, 0x8078, 0x0005, 0x00e6, 0x0026, 0x0016, 0x2071,
-	0xad00, 0x7080, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086, 0x0003,
-	0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3cce, 0x00d6, 0x6018,
-	0x2068, 0x080c, 0x4d72, 0x080c, 0x86ed, 0x00de, 0x080c, 0x89f7,
-	0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005, 0x0518,
-	0x2001, 0x0006, 0x080c, 0x4c30, 0x00e6, 0x6010, 0xa075, 0x01a8,
-	0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001, 0x0000,
-	0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0x9a05, 0x0030, 0x7007,
-	0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2aff,
-	0x080c, 0x8078, 0x0020, 0x080c, 0x85f3, 0x080c, 0x87bd, 0x001e,
-	0x002e, 0x00ee, 0x0005, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
-	0x1158, 0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x080c, 0x67ee, 0x0010, 0x080c, 0x87bd, 0x0005, 0x2011,
-	0xad20, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007, 0x080c,
-	0x4c30, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x000b,
-	0x0005, 0x86b9, 0x8854, 0x86b9, 0x888a, 0x86b9, 0x88ff, 0x884d,
-	0x86b9, 0x86b9, 0x8912, 0x86b9, 0x8922, 0x6604, 0xa6b6, 0x001e,
-	0x1110, 0x080c, 0x8078, 0x0005, 0x00d6, 0x00c6, 0x080c, 0x8932,
-	0x1178, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
-	0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x00f8,
-	0x2009, 0xb28e, 0x2104, 0xa086, 0x0009, 0x1160, 0x6018, 0x2068,
-	0x6840, 0xa084, 0x00ff, 0xa005, 0x0180, 0x8001, 0x6842, 0x6017,
-	0x000a, 0x0068, 0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086,
-	0x1900, 0x1118, 0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x00ce,
-	0x00de, 0x0005, 0x080c, 0x8940, 0x00d6, 0x2069, 0xaf9d, 0x2d04,
-	0xa005, 0x0168, 0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138,
-	0x2069, 0xad1c, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de,
-	0x0078, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x2001, 0x0002, 0x080c,
-	0x4c30, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x0428,
-	0x080c, 0x85f3, 0x2009, 0xb28e, 0x2134, 0xa6b4, 0x00ff, 0xa686,
-	0x0005, 0x01e0, 0xa686, 0x000b, 0x01b0, 0x2009, 0xb28f, 0x2104,
-	0xa084, 0xff00, 0x1118, 0xa686, 0x0009, 0x0180, 0xa086, 0x1900,
-	0x1150, 0xa686, 0x0009, 0x0150, 0x2001, 0x0004, 0x080c, 0x4c30,
-	0x080c, 0x8078, 0x0010, 0x080c, 0x87bd, 0x0005, 0x00d6, 0x6010,
-	0x2068, 0x080c, 0x9596, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de,
-	0x0c90, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140,
-	0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28,
-	0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xad00, 0x080c,
-	0x48f5, 0x00ee, 0x0010, 0x080c, 0x2ad9, 0x00de, 0x08a0, 0x080c,
-	0x8940, 0x1158, 0x2001, 0x0004, 0x080c, 0x4c30, 0x6003, 0x0001,
-	0x6007, 0x0003, 0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c,
-	0x87bd, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c, 0x4c30,
-	0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x67ee, 0x0010, 0x080c,
-	0x87bd, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c, 0x4c30,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010, 0x080c,
-	0x87bd, 0x0005, 0x2009, 0xb28e, 0x2104, 0xa086, 0x0003, 0x1138,
-	0x2009, 0xb28f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x0005,
-	0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006, 0x2164,
-	0x080c, 0x4ceb, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6, 0x00d6,
-	0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xad34, 0x2e04, 0xa085,
-	0x0003, 0x2072, 0x080c, 0x89cc, 0x0538, 0x2001, 0xad52, 0x2004,
-	0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xa96c,
-	0x2001, 0xad0c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009,
-	0x0001, 0x080c, 0x2aac, 0x2071, 0xad00, 0x080c, 0x28fa, 0x00c6,
-	0x0156, 0x20a9, 0x0081, 0x2009, 0x007f, 0x080c, 0x2bc9, 0x8108,
-	0x1f04, 0x897d, 0x015e, 0x00ce, 0x080c, 0x8943, 0x6813, 0x00ff,
-	0x6817, 0xfffe, 0x2071, 0xb280, 0x2079, 0x0100, 0x2e04, 0xa084,
-	0x00ff, 0x2069, 0xad1b, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04,
-	0x2069, 0xad1c, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084,
-	0xff00, 0x001e, 0xa105, 0x2009, 0xad27, 0x200a, 0x2200, 0xa084,
-	0x00ff, 0x2008, 0x080c, 0x26a0, 0x080c, 0x574f, 0x0170, 0x2069,
-	0xb28e, 0x2071, 0xaf9f, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818,
-	0x700a, 0x681c, 0x700e, 0x080c, 0x9903, 0x0040, 0x2001, 0x0006,
-	0x080c, 0x4c30, 0x080c, 0x2aff, 0x080c, 0x8078, 0x001e, 0x003e,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156,
-	0x2019, 0xad27, 0x231c, 0x83ff, 0x01e8, 0x2071, 0xb280, 0x2e14,
-	0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190,
-	0x2011, 0xb296, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c,
-	0x1148, 0x2011, 0xb29a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c,
-	0x8a7c, 0x1100, 0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6,
-	0x2071, 0xb28c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086,
-	0x0800, 0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086,
-	0x0100, 0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006,
-	0x0010, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6,
-	0x0076, 0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000,
-	0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400,
-	0x2071, 0xad00, 0x7244, 0x7064, 0xa202, 0x16f0, 0x080c, 0xa990,
-	0x05a0, 0x671c, 0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568,
-	0x2500, 0xac06, 0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000,
-	0xa086, 0x0004, 0x1110, 0x080c, 0x190b, 0xa786, 0x0008, 0x1148,
-	0x080c, 0x9789, 0x1130, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x974e,
-	0x00a0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0160, 0xa786, 0x0003,
-	0x11e8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x510c,
-	0x080c, 0x9742, 0x080c, 0x974e, 0x00ce, 0xace0, 0x0018, 0x7058,
-	0xac02, 0x1210, 0x0804, 0x8a2a, 0x012e, 0x000e, 0x002e, 0x004e,
-	0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006,
-	0x1d00, 0x080c, 0xa91f, 0x0c30, 0x220c, 0x2304, 0xa106, 0x1130,
-	0x8210, 0x8318, 0x1f04, 0x8a7c, 0xa006, 0x0005, 0x2304, 0xa102,
-	0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0xa18d, 0x0001,
-	0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6, 0x080c, 0x9778,
-	0x0120, 0x080c, 0x9789, 0x0168, 0x0028, 0x080c, 0x2aff, 0x080c,
-	0x9789, 0x0138, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50,
-	0x0005, 0x080c, 0x85f3, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x8ac2,
-	0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2, 0x8ac2,
-	0x8ac2, 0x8ac2, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac4, 0x8ac2, 0x8ac2,
-	0x8ac2, 0x8ac4, 0x080c, 0x14f6, 0x600b, 0xffff, 0x6003, 0x0001,
-	0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50,
-	0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0040,
-	0x0804, 0x8b5e, 0xa186, 0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c,
-	0x2ad9, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9596, 0x0168, 0x6837,
-	0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e,
-	0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x080c,
-	0x6c50, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004, 0xa082, 0x0040,
-	0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045, 0x0120, 0xa186,
-	0x0047, 0x190c, 0x14f6, 0x2001, 0x0109, 0x2004, 0xd084, 0x0198,
-	0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
-	0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000, 0xa086, 0x0002,
-	0x1110, 0x0804, 0x8b98, 0x080c, 0x80be, 0x0005, 0x0002, 0x8b3c,
-	0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a, 0x8b3a,
-	0x8b3a, 0x8b3a, 0x8b57, 0x8b57, 0x8b57, 0x8b57, 0x8b3a, 0x8b57,
-	0x8b3a, 0x8b57, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x00d6, 0x6110,
-	0x2168, 0x080c, 0x9596, 0x0168, 0x6837, 0x0103, 0x684b, 0x0006,
-	0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c, 0x510c, 0x080c,
-	0x9742, 0x00de, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
-	0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x0002, 0x8b74,
-	0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72, 0x8b72,
-	0x8b72, 0x8b72, 0x8b86, 0x8b86, 0x8b86, 0x8b86, 0x8b72, 0x8b91,
-	0x8b72, 0x8b86, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x2001, 0xafa5,
-	0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c50, 0x6010, 0xa088,
-	0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005, 0x080c, 0x6b73,
-	0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x6c50,
-	0x0005, 0x080c, 0x6b73, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005,
-	0xa182, 0x0040, 0x0002, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
-	0x8bb0, 0x8c88, 0x8ca9, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae,
-	0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x8bae, 0x080c, 0x14f6,
-	0x00e6, 0x00d6, 0x603f, 0x0000, 0x2071, 0xb280, 0x7124, 0x610a,
-	0x2071, 0xb28c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff,
-	0x0904, 0x8c54, 0xa68c, 0x0c00, 0x01e8, 0x00f6, 0x2c78, 0x080c,
-	0x5029, 0x00fe, 0x0198, 0x684c, 0xd0ac, 0x0180, 0x6020, 0xd0dc,
-	0x1168, 0x6850, 0xd0bc, 0x1150, 0x7318, 0x6814, 0xa306, 0x1904,
-	0x8c66, 0x731c, 0x6810, 0xa306, 0x1904, 0x8c66, 0x7318, 0x6b62,
-	0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0518, 0xa186,
-	0x0028, 0x1128, 0x080c, 0x9767, 0x684b, 0x001c, 0x00e8, 0xd6dc,
-	0x01a0, 0x684b, 0x0015, 0x684c, 0xd0ac, 0x0170, 0x6914, 0x6a10,
-	0x2100, 0xa205, 0x0148, 0x7018, 0xa106, 0x1118, 0x701c, 0xa206,
-	0x0118, 0x6962, 0x6a5e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0x684b,
-	0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e,
-	0xd6c4, 0x01f0, 0xa686, 0x0100, 0x1140, 0x2001, 0xb299, 0x2004,
-	0xa005, 0x1118, 0xc6c4, 0x0804, 0x8bbf, 0x7328, 0x732c, 0x6b56,
-	0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036,
-	0x2308, 0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e,
-	0xd6cc, 0x0904, 0x8c79, 0x7124, 0x695a, 0x81ff, 0x0904, 0x8c79,
-	0xa192, 0x0021, 0x1250, 0x2071, 0xb298, 0x831c, 0x2300, 0xae18,
-	0xad90, 0x001d, 0x080c, 0x927f, 0x04a0, 0x6838, 0xd0fc, 0x0120,
-	0x2009, 0x0020, 0x695a, 0x0c78, 0x00f6, 0x2d78, 0x080c, 0x9224,
-	0x00fe, 0x080c, 0x926f, 0x0438, 0x00f6, 0x2c78, 0x080c, 0x5029,
-	0x00fe, 0x0188, 0x684c, 0xd0ac, 0x0170, 0x6020, 0xd0dc, 0x1158,
-	0x6850, 0xd0bc, 0x1140, 0x684c, 0xd0f4, 0x1128, 0x080c, 0x9866,
-	0x00de, 0x00ee, 0x00e0, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46,
-	0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c,
-	0x8e04, 0x080c, 0x510c, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x080c, 0x9834, 0x00de, 0x00ee, 0x1110, 0x080c, 0x8078, 0x0005,
-	0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00, 0x7e0c,
-	0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120, 0x6003, 0x0002,
-	0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x603f,
-	0x0000, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b, 0x080c, 0x6d0d,
-	0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x6003, 0x0004, 0x6110,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005,
-	0xa182, 0x0040, 0x0002, 0x8cce, 0x8cce, 0x8cce, 0x8cce, 0x8cce,
-	0x8cd0, 0x8d61, 0x8cce, 0x8cce, 0x8d77, 0x8ddb, 0x8cce, 0x8cce,
-	0x8cce, 0x8cce, 0x8dea, 0x8cce, 0x8cce, 0x8cce, 0x080c, 0x14f6,
-	0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c, 0x6110, 0x2178,
-	0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218,
-	0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x8d5c, 0xa694,
-	0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e,
-	0xa284, 0x0300, 0x0904, 0x8d5c, 0x080c, 0x15d9, 0x090c, 0x14f6,
-	0x2d00, 0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838,
-	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
-	0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
-	0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060,
-	0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
-	0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
-	0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff,
-	0x0170, 0xa38a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308,
-	0x2019, 0xb298, 0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc,
-	0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250,
-	0x2071, 0xb298, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c,
-	0x927f, 0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a,
-	0x0c78, 0x2d78, 0x080c, 0x9224, 0x00de, 0x00ee, 0x00fe, 0x007e,
-	0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0xb28c, 0x7c04, 0x7b00,
-	0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
-	0x00fe, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x781a, 0x0005, 0x00d6,
-	0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x2001, 0xafa5,
-	0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x6c05, 0x080c, 0x6d0d,
-	0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x8dd9, 0xd1cc, 0x0540,
-	0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850,
-	0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156,
-	0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x8da1, 0x015e,
-	0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600,
-	0x0418, 0x0016, 0x080c, 0x1600, 0x00de, 0x080c, 0x926f, 0x00e0,
-	0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180,
-	0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc, 0x0118,
-	0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0010,
-	0x684b, 0x0000, 0x080c, 0x510c, 0x080c, 0x9834, 0x1110, 0x080c,
-	0x8078, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x7a64, 0x6003,
-	0x0002, 0x2001, 0xafa5, 0x2004, 0x603e, 0x080c, 0x6c05, 0x080c,
-	0x6d0d, 0x0005, 0x080c, 0x6c05, 0x080c, 0x2ad9, 0x00d6, 0x6110,
-	0x2168, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
-	0x6847, 0x0000, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
-	0x8078, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0015, 0xd1fc, 0x0138,
-	0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962,
-	0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x8e28, 0x8e28, 0x8e28,
-	0x8e28, 0x8e28, 0x8e2a, 0x8e28, 0x8ee3, 0x8eef, 0x8e28, 0x8e28,
-	0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28, 0x8e28,
-	0x080c, 0x14f6, 0x0076, 0x00f6, 0x00e6, 0x00d6, 0x2071, 0xb28c,
-	0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x00f6, 0x2c78, 0x080c,
-	0x5029, 0x00fe, 0x0150, 0xa684, 0x00ff, 0x1138, 0x6020, 0xd0f4,
-	0x0120, 0x080c, 0x9866, 0x0804, 0x8ede, 0x7e46, 0x7f4c, 0xc7e5,
-	0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0904,
-	0x8ed4, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120, 0x7018, 0x7862,
-	0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x8ed2, 0xa686, 0x0100,
-	0x1140, 0x2001, 0xb299, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46,
-	0x0c28, 0x080c, 0x15d9, 0x090c, 0x14f6, 0x2d00, 0x784a, 0x7f4c,
-	0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
-	0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318,
-	0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180,
-	0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118,
-	0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010,
-	0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
-	0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a,
-	0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xb298,
-	0xad90, 0x0019, 0x080c, 0x927f, 0x003e, 0xd6cc, 0x01d8, 0x7124,
-	0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xb298,
-	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x927f, 0x0050,
-	0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78,
-	0x080c, 0x9224, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001, 0x0001,
-	0x2071, 0xb28c, 0x7218, 0x731c, 0x080c, 0x186f, 0x00de, 0x00ee,
-	0x00fe, 0x007e, 0x0005, 0x2001, 0xafa5, 0x2004, 0x603e, 0x20e1,
-	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824, 0x0005, 0x2001,
-	0xafa5, 0x2004, 0x603e, 0x00d6, 0x6003, 0x0002, 0x6110, 0x2168,
-	0x694c, 0xd1e4, 0x0904, 0x8ff3, 0x603f, 0x0000, 0x00f6, 0x2c78,
-	0x080c, 0x5029, 0x00fe, 0x0548, 0x6814, 0x6910, 0xa115, 0x0528,
-	0x6a60, 0xa206, 0x1118, 0x685c, 0xa106, 0x01f8, 0x684c, 0xc0e4,
-	0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000, 0x697c,
-	0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020,
-	0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
-	0x00de, 0x080c, 0x9866, 0x0804, 0x8ff3, 0x694c, 0xd1cc, 0x0904,
-	0x8fc3, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x8f88, 0x0016, 0x684c,
-	0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c,
-	0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b,
-	0x0015, 0x080c, 0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080,
-	0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c,
-	0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04,
-	0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d,
-	0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012,
-	0x8318, 0x8210, 0x1f04, 0x8f76, 0x015e, 0x00fe, 0x000e, 0x6852,
-	0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1600, 0x0804, 0x8fee,
-	0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
-	0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c, 0x784b, 0x001c,
-	0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b, 0x0015, 0x080c,
-	0x99ee, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080, 0xd1d4, 0x0128,
-	0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c, 0xd0ac, 0x0130,
-	0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x8e04, 0x6860, 0x7862,
-	0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c, 0x1600, 0x00de,
-	0x080c, 0x926f, 0x0458, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x01b0, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c,
-	0x00d8, 0xd1dc, 0x0148, 0x684b, 0x0015, 0x080c, 0x99ee, 0x0118,
-	0x6944, 0xc1dc, 0x6946, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007,
-	0x0058, 0x684b, 0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914,
-	0xa115, 0x0110, 0x080c, 0x8e04, 0x080c, 0x510c, 0x080c, 0x9834,
-	0x1110, 0x080c, 0x8078, 0x00de, 0x0005, 0x080c, 0x6b73, 0x0010,
-	0x080c, 0x6c05, 0x080c, 0x9596, 0x01c0, 0x00d6, 0x6110, 0x2168,
-	0x6837, 0x0103, 0x2009, 0xad0c, 0x210c, 0xd18c, 0x11c0, 0xd184,
-	0x1198, 0x6108, 0x694a, 0xa18e, 0x0029, 0x1110, 0x080c, 0xabfa,
-	0x6847, 0x0000, 0x080c, 0x510c, 0x00de, 0x080c, 0x8078, 0x080c,
-	0x6c50, 0x080c, 0x6d0d, 0x0005, 0x684b, 0x0004, 0x0c88, 0x684b,
-	0x0004, 0x0c70, 0xa182, 0x0040, 0x0002, 0x9038, 0x9038, 0x9038,
-	0x9038, 0x9038, 0x903a, 0x9038, 0x903d, 0x9038, 0x9038, 0x9038,
-	0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038, 0x9038,
-	0x080c, 0x14f6, 0x080c, 0x8078, 0x0005, 0x0006, 0x0026, 0xa016,
-	0x080c, 0x1824, 0x002e, 0x000e, 0x0005, 0xa182, 0x0085, 0x0002,
-	0x9051, 0x904f, 0x904f, 0x905d, 0x904f, 0x904f, 0x904f, 0x080c,
-	0x14f6, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x6c50, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6,
-	0x00e6, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0x9586,
-	0x01a0, 0x2268, 0x6800, 0xa086, 0x0000, 0x0178, 0x6018, 0x6d18,
-	0xa52e, 0x1158, 0x00c6, 0x2d60, 0x080c, 0x928f, 0x00ce, 0x0128,
-	0x6803, 0x0002, 0x6007, 0x0086, 0x0010, 0x6007, 0x0087, 0x6003,
-	0x0001, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x00f6, 0x2278, 0x080c,
-	0x5029, 0x00fe, 0x0150, 0x6820, 0xd0ec, 0x0138, 0x00c6, 0x2260,
-	0x603f, 0x0000, 0x080c, 0x9866, 0x00ce, 0x00ee, 0x00de, 0x005e,
-	0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085,
-	0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c, 0x14f6, 0xa082, 0x0085,
-	0x0072, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x14f6,
-	0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x90be,
-	0x90c0, 0x90c0, 0x90be, 0x90be, 0x90be, 0x90be, 0x080c, 0x14f6,
-	0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa186,
-	0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x04a8, 0xa186,
-	0x0027, 0x11e8, 0x080c, 0x6b73, 0x080c, 0x2ad9, 0x00d6, 0x6010,
-	0x2068, 0x080c, 0x9596, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000,
-	0x684b, 0x0029, 0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c,
-	0x8078, 0x080c, 0x6c50, 0x0005, 0x080c, 0x80be, 0x0ce0, 0xa186,
-	0x0014, 0x1dd0, 0x080c, 0x6b73, 0x00d6, 0x6010, 0x2068, 0x080c,
-	0x9596, 0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006,
-	0x6850, 0xc0ec, 0x6852, 0x08f0, 0x0002, 0x910e, 0x910c, 0x910c,
-	0x910c, 0x910c, 0x910c, 0x9126, 0x080c, 0x14f6, 0x080c, 0x6b73,
-	0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
-	0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
-	0x6016, 0x6003, 0x000c, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73,
-	0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
-	0x0035, 0x1118, 0x2001, 0xafa3, 0x0010, 0x2001, 0xafa4, 0x2004,
-	0x6016, 0x6003, 0x000e, 0x080c, 0x6c50, 0x0005, 0xa182, 0x008c,
-	0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x80be, 0x0005,
-	0x914f, 0x914f, 0x914f, 0x914f, 0x9151, 0x91a4, 0x914f, 0x080c,
-	0x14f6, 0x00d6, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x00fe, 0x0168,
-	0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
-	0x0035, 0x1118, 0x00de, 0x0804, 0x91b7, 0x080c, 0x9742, 0x080c,
-	0x9596, 0x01c8, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4,
-	0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048, 0xd0bc, 0x0118,
-	0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847,
-	0x0000, 0x080c, 0x510c, 0x2c68, 0x080c, 0x8022, 0x01c0, 0x6003,
-	0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009, 0xb28e, 0x210c,
-	0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x6918, 0x611a, 0x080c,
-	0x9956, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c, 0x67a8, 0x2d60,
-	0x080c, 0x8078, 0x00de, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029,
-	0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0035,
-	0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039, 0x1530, 0x00d6,
-	0x2c68, 0x080c, 0x9a34, 0x1904, 0x91fc, 0x080c, 0x8022, 0x01d8,
-	0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918, 0x611a, 0x6928,
-	0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934,
-	0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c, 0x9956, 0x080c,
-	0x67a8, 0x080c, 0x6c50, 0x2d60, 0x00f8, 0x00d6, 0x6010, 0x2068,
-	0x080c, 0x9596, 0x01c8, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0128,
-	0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
-	0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9803, 0x6847, 0x0000,
-	0x080c, 0x510c, 0x080c, 0x9742, 0x00de, 0x080c, 0x8078, 0x0005,
-	0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0140, 0x6837,
-	0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c, 0x510c, 0x00de,
-	0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
-	0x0027, 0x0118, 0x080c, 0x80be, 0x0030, 0x080c, 0x6b73, 0x080c,
-	0x974e, 0x080c, 0x6c50, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6,
-	0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100,
-	0x2130, 0x2069, 0xb298, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020,
-	0xaf90, 0x001d, 0x080c, 0x927f, 0xa6b2, 0x0020, 0x7804, 0xa06d,
-	0x0110, 0x080c, 0x1600, 0x080c, 0x15d9, 0x0500, 0x8528, 0x6837,
-	0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228,
-	0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009,
-	0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f,
-	0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f,
-	0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6,
-	0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c,
-	0x510c, 0x2f68, 0x0cb8, 0x080c, 0x510c, 0x00fe, 0x0005, 0x0156,
-	0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007,
-	0x2012, 0x8318, 0x8210, 0x1f04, 0x9286, 0x015e, 0x0005, 0x0066,
-	0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c, 0xa084, 0x000f,
-	0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066,
-	0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b, 0x006e, 0x012e,
-	0x0005, 0x92c3, 0x92c3, 0x92be, 0x92e5, 0x92b1, 0x92be, 0x92e5,
-	0x92be, 0x080c, 0x14f6, 0x0036, 0x2019, 0x0010, 0x080c, 0xa566,
-	0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0xa006, 0x0005,
-	0xa085, 0x0001, 0x0005, 0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068,
-	0x080c, 0x9596, 0x01c0, 0x6834, 0xa086, 0x0139, 0x1128, 0x684b,
-	0x0005, 0x6853, 0x0000, 0x0028, 0xa00e, 0x2001, 0x0005, 0x080c,
-	0x51df, 0x080c, 0x9803, 0x080c, 0x510c, 0x080c, 0x8078, 0xa085,
-	0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010,
-	0x1a0c, 0x14f6, 0x000b, 0x0005, 0x92fc, 0x9319, 0x92fe, 0x9338,
-	0x9316, 0x92fc, 0x92be, 0x92c3, 0x92c3, 0x92be, 0x92be, 0x92be,
-	0x92be, 0x92be, 0x92be, 0x92be, 0x080c, 0x14f6, 0x86ff, 0x1198,
-	0x00d6, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0x9803,
-	0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c,
-	0x67a8, 0x080c, 0x6c50, 0xa085, 0x0001, 0x0005, 0x080c, 0x190b,
-	0x0c28, 0x00e6, 0x2071, 0xafc7, 0x7024, 0xac06, 0x1110, 0x080c,
-	0x79e1, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150, 0x0086,
-	0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x7b9a, 0x009e, 0x008e,
-	0x0010, 0x080c, 0x78de, 0x00ee, 0x1948, 0x080c, 0x92be, 0x0005,
-	0x0036, 0x00e6, 0x2071, 0xafc7, 0x703c, 0xac06, 0x1140, 0x2019,
-	0x0000, 0x080c, 0x7a64, 0x00ee, 0x003e, 0x0804, 0x92fe, 0x080c,
-	0x7cb8, 0x00ee, 0x003e, 0x1904, 0x92fe, 0x080c, 0x92be, 0x0005,
-	0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9369,
-	0x93d3, 0x9501, 0x9374, 0x974e, 0x9369, 0xa558, 0x8078, 0x93d3,
-	0x9362, 0x955f, 0x080c, 0x14f6, 0x080c, 0x9789, 0x1110, 0x080c,
-	0x85f3, 0x0005, 0x080c, 0x6b73, 0x080c, 0x6c50, 0x080c, 0x8078,
-	0x0005, 0x6017, 0x0001, 0x0005, 0x6010, 0xa080, 0x0019, 0x2c02,
-	0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x938f,
-	0x9391, 0x93b1, 0x93c3, 0x93d0, 0x938f, 0x9369, 0x9369, 0x9369,
-	0x93c3, 0x93c3, 0x938f, 0x938f, 0x938f, 0x938f, 0x93cd, 0x080c,
-	0x14f6, 0x00e6, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071,
-	0xafc7, 0x7024, 0xac06, 0x0190, 0x080c, 0x78de, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xafa4, 0x2004, 0x6016,
-	0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x6017, 0x0001,
-	0x0cd8, 0x00d6, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
-	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x67a8,
-	0x080c, 0x6c50, 0x0005, 0x00d6, 0x6017, 0x0001, 0x6010, 0x2068,
-	0x6850, 0xc0b5, 0x6852, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005,
-	0x080c, 0x190b, 0x08f0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6,
-	0x000b, 0x0005, 0x93ea, 0x9371, 0x93ec, 0x93ea, 0x93ec, 0x93ec,
-	0x936a, 0x93ea, 0x9364, 0x9364, 0x93ea, 0x93ea, 0x93ea, 0x93ea,
-	0x93ea, 0x93ea, 0x080c, 0x14f6, 0x00d6, 0x6018, 0x2068, 0x6804,
-	0xa084, 0x00ff, 0x00de, 0xa08a, 0x000c, 0x1a0c, 0x14f6, 0x000b,
-	0x0005, 0x9405, 0x94a7, 0x9407, 0x9441, 0x9407, 0x9441, 0x9407,
-	0x9411, 0x9405, 0x9441, 0x9405, 0x942d, 0x080c, 0x14f6, 0x6004,
-	0xa08e, 0x0016, 0x0588, 0xa08e, 0x0004, 0x0570, 0xa08e, 0x0002,
-	0x0558, 0x6004, 0x080c, 0x9789, 0x0904, 0x94c0, 0xa08e, 0x0021,
-	0x0904, 0x94c4, 0xa08e, 0x0022, 0x0904, 0x94c0, 0xa08e, 0x003d,
-	0x0904, 0x94c4, 0xa08e, 0x0039, 0x0904, 0x94c8, 0xa08e, 0x0035,
-	0x0904, 0x94c8, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150,
-	0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086,
-	0x0006, 0x0110, 0x080c, 0x2ad9, 0x080c, 0x85f3, 0x080c, 0x974e,
-	0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9498,
-	0xa186, 0x0002, 0x1518, 0x6018, 0x2068, 0x2001, 0xad34, 0x2004,
-	0xd0ac, 0x1904, 0x94ea, 0x68a0, 0xd0bc, 0x1904, 0x94ea, 0x6840,
-	0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x8022,
-	0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce,
-	0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x007e, 0x1170, 0x2009, 0xad34, 0x2104, 0xc085, 0x200a,
-	0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x00ee, 0x080c, 0x85f3,
-	0x0020, 0x080c, 0x85f3, 0x080c, 0x2ad9, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x2aff, 0x012e, 0x00ee, 0x080c, 0x974e, 0x0005,
-	0x2001, 0x0002, 0x080c, 0x4c30, 0x6003, 0x0001, 0x6007, 0x0002,
-	0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x0c80, 0x00c6,
-	0x00d6, 0x6104, 0xa186, 0x0016, 0x0d58, 0x6018, 0x2068, 0x6840,
-	0xa084, 0x00ff, 0xa005, 0x0904, 0x946e, 0x8001, 0x6842, 0x6003,
-	0x0001, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00de, 0x00ce, 0x08b8,
-	0x080c, 0x85f3, 0x0804, 0x943e, 0x080c, 0x8621, 0x0804, 0x943e,
-	0x00d6, 0x2c68, 0x6104, 0x080c, 0x9a34, 0x00de, 0x0118, 0x080c,
-	0x8078, 0x00b8, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105,
-	0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038,
-	0x600a, 0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c,
-	0x6c50, 0x0005, 0x00de, 0x00ce, 0x080c, 0x85f3, 0x080c, 0x2ad9,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2aff, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x012e, 0x00ee,
-	0x0005, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005,
-	0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518, 0x9518,
-	0x9518, 0x9369, 0x9518, 0x9371, 0x951a, 0x9371, 0x9527, 0x9518,
-	0x080c, 0x14f6, 0x6004, 0xa086, 0x008b, 0x0148, 0x6007, 0x008b,
-	0x6003, 0x000d, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0005, 0x080c,
-	0x9742, 0x080c, 0x9596, 0x0580, 0x080c, 0x2ad9, 0x00d6, 0x080c,
-	0x9596, 0x0168, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
-	0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x080c, 0x510c, 0x2c68,
-	0x080c, 0x8022, 0x0150, 0x6818, 0x601a, 0x080c, 0x9956, 0x00c6,
-	0x2d60, 0x080c, 0x974e, 0x00ce, 0x0008, 0x2d60, 0x00de, 0x6013,
-	0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
-	0x67ee, 0x080c, 0x6c50, 0x0010, 0x080c, 0x974e, 0x0005, 0x6000,
-	0xa08a, 0x0010, 0x1a0c, 0x14f6, 0x000b, 0x0005, 0x9576, 0x9576,
-	0x9576, 0x9578, 0x9579, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576,
-	0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x9576, 0x080c, 0x14f6,
-	0x0005, 0x080c, 0x7cb8, 0x190c, 0x14f6, 0x6110, 0x2168, 0x684b,
-	0x0006, 0x080c, 0x510c, 0x080c, 0x8078, 0x0005, 0xa284, 0x0007,
-	0x1158, 0xa282, 0xb400, 0x0240, 0x2001, 0xad16, 0x2004, 0xa202,
-	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
-	0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x2061, 0xb400, 0x2071, 0xad00, 0x7344,
-	0x7064, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0x98e3,
-	0x0148, 0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x00c6, 0x080c,
-	0x8078, 0x00ce, 0xace0, 0x0018, 0x7058, 0xac02, 0x1208, 0x0c38,
-	0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6,
-	0x0016, 0xa188, 0xae34, 0x210c, 0x81ff, 0x0170, 0x2061, 0xb400,
-	0x2071, 0xad00, 0x0016, 0x080c, 0x8022, 0x001e, 0x0138, 0x611a,
-	0x080c, 0x2ad9, 0x080c, 0x8078, 0xa006, 0x0010, 0xa085, 0x0001,
-	0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091,
-	0x8000, 0x00c6, 0x080c, 0x8022, 0x005e, 0x0180, 0x6612, 0x651a,
-	0x080c, 0x9956, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x80a7,
-	0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0,
-	0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c,
-	0x8022, 0x005e, 0x0508, 0x6013, 0x0000, 0x651a, 0x080c, 0x9956,
-	0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x4ecf, 0x00ce, 0x080c,
-	0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c,
-	0xa712, 0x007e, 0x2009, 0x004c, 0x080c, 0x80a7, 0xa085, 0x0001,
-	0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6,
-	0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0180, 0x7e12,
-	0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9683,
-	0x2f60, 0x2009, 0x004d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
-	0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c,
-	0x8022, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f,
-	0x0003, 0x2021, 0x0005, 0x0439, 0x2f60, 0x2009, 0x004e, 0x080c,
-	0x80a7, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6,
-	0x00c6, 0x0046, 0x00c6, 0x080c, 0x8022, 0x2c78, 0x00ce, 0x0178,
-	0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x0059,
-	0x2f60, 0x2009, 0x0052, 0x080c, 0x80a7, 0xa085, 0x0001, 0x004e,
-	0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x4e71, 0x0118, 0x2001, 0x9688, 0x0028, 0x080c, 0x4e43,
-	0x0158, 0x2001, 0x968e, 0x0006, 0xa00e, 0x2400, 0x080c, 0x51df,
-	0x080c, 0x510c, 0x000e, 0x0807, 0x2418, 0x080c, 0x6b15, 0x62a0,
-	0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x6900,
-	0x008e, 0x080c, 0x681d, 0x2f08, 0x2648, 0x080c, 0xa712, 0x613c,
-	0x81ff, 0x090c, 0x69a9, 0x012e, 0x007e, 0x009e, 0x0005, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
-	0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
-	0x2009, 0x001f, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
-	0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
-	0x080c, 0x8022, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0x9956,
-	0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x080c, 0x80a7,
-	0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188,
-	0x660a, 0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012,
-	0x2009, 0x003d, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce,
-	0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
-	0x080c, 0x9807, 0x001e, 0x0180, 0x611a, 0x080c, 0x9956, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x80a7, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0188, 0x660a,
-	0x611a, 0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
-	0x0044, 0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
-	0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff,
-	0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e, 0x0005, 0x0006, 0x6000,
-	0xa086, 0x0000, 0x0190, 0x6013, 0x0000, 0x601f, 0x0007, 0x2001,
-	0xafa3, 0x2004, 0x0006, 0xa082, 0x0051, 0x000e, 0x0208, 0x8004,
-	0x6016, 0x080c, 0xabb4, 0x603f, 0x0000, 0x000e, 0x0005, 0x0066,
-	0x00c6, 0x00d6, 0x2031, 0xad52, 0x2634, 0xd6e4, 0x0128, 0x6618,
-	0x2660, 0x6e48, 0x080c, 0x4dfc, 0x00de, 0x00ce, 0x006e, 0x0005,
-	0x0006, 0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003,
-	0x0128, 0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e,
-	0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d, 0x0148, 0x6834, 0xa086,
-	0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110, 0xa006, 0x0010, 0xa085,
-	0x0001, 0x00de, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x00c6, 0x080c, 0x8022, 0x001e, 0x0190, 0x611a, 0x080c, 0x9956,
-	0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x2ad9, 0x2009, 0x0028,
-	0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
-	0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0xad20, 0x2204, 0xa086,
-	0x0074, 0x1148, 0x080c, 0x8943, 0x6003, 0x0001, 0x6007, 0x0029,
-	0x080c, 0x67ee, 0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x0005,
-	0xa186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x4c30, 0x00e8,
-	0xa186, 0x0015, 0x11e8, 0x2011, 0xad20, 0x2204, 0xa086, 0x0014,
-	0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c, 0x4d72, 0x00de, 0x080c,
-	0x89f7, 0x1170, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005,
-	0x0138, 0x2001, 0x0006, 0x080c, 0x4c30, 0x080c, 0x81f6, 0x0020,
-	0x080c, 0x85f3, 0x080c, 0x8078, 0x0005, 0x6848, 0xa086, 0x0005,
-	0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852, 0x0005, 0x00e6,
-	0x0126, 0x2071, 0xad00, 0x2091, 0x8000, 0x7544, 0xa582, 0x0001,
-	0x0608, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0,
-	0x0018, 0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xb400, 0x0c98,
-	0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0018, 0x7058, 0xa502,
-	0x1230, 0x754a, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704b,
-	0xb400, 0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb28c, 0x7014,
-	0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050,
-	0x080c, 0x67a8, 0x080c, 0x6c50, 0x00ee, 0x0005, 0x00c6, 0x00f6,
-	0x2c78, 0x080c, 0x5029, 0x00fe, 0x0120, 0x601c, 0xa084, 0x000f,
-	0x0013, 0x00ce, 0x0005, 0x9369, 0x985e, 0x9861, 0x9864, 0xa9a7,
-	0xa9c2, 0xa9c5, 0x9369, 0x9369, 0x080c, 0x14f6, 0xe000, 0xe000,
-	0x0005, 0xe000, 0xe000, 0x0005, 0x0009, 0x0005, 0x00f6, 0x2c78,
-	0x080c, 0x5029, 0x0538, 0x080c, 0x8022, 0x1128, 0x2001, 0xafa5,
-	0x2004, 0x783e, 0x00f8, 0x7818, 0x601a, 0x080c, 0x9956, 0x781c,
-	0xa086, 0x0003, 0x0128, 0x7808, 0x6036, 0x2f00, 0x603a, 0x0020,
-	0x7808, 0x603a, 0x2f00, 0x6036, 0x602a, 0x601f, 0x0001, 0x6007,
-	0x0035, 0x6003, 0x0001, 0x7950, 0x6152, 0x080c, 0x67a8, 0x080c,
-	0x6c50, 0x2f60, 0x00fe, 0x0005, 0x0016, 0x00f6, 0x682c, 0x6032,
-	0xa08e, 0x0001, 0x0138, 0xa086, 0x0005, 0x0140, 0xa006, 0x602a,
-	0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5, 0x6822, 0x6810, 0x2078,
-	0x787c, 0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x1e78, 0x6834,
-	0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036,
-	0x6808, 0x603a, 0x6918, 0x611a, 0x6950, 0x6152, 0x601f, 0x0001,
-	0x6007, 0x0039, 0x6003, 0x0001, 0x080c, 0x67a8, 0x6803, 0x0002,
-	0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78, 0x080c, 0x5029, 0x1118,
-	0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4, 0x1150, 0xc0f5, 0x6022,
-	0x6010, 0x2078, 0x7828, 0x603a, 0x782c, 0x6036, 0x080c, 0x190b,
-	0xa006, 0x00fe, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0034,
-	0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e, 0x0036, 0x0188, 0xa08e,
-	0x0037, 0x0170, 0xa08e, 0x0038, 0x0158, 0xa08e, 0x0039, 0x0140,
-	0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b, 0x0110, 0xa085, 0x0001,
-	0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6,
-	0x2001, 0xaf9f, 0x200c, 0x8000, 0x2014, 0x2001, 0x0032, 0x080c,
-	0x6665, 0x2001, 0xafa3, 0x82ff, 0x1110, 0x2011, 0x0002, 0x2202,
-	0x2001, 0xafa1, 0x200c, 0x8000, 0x2014, 0x2071, 0xaf8d, 0x711a,
-	0x721e, 0x2001, 0x0064, 0x080c, 0x6665, 0x2001, 0xafa4, 0x82ff,
-	0x1110, 0x2011, 0x0002, 0x2202, 0x2009, 0xafa5, 0xa280, 0x000a,
-	0x200a, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006,
-	0x00e6, 0x2001, 0xafa3, 0x2003, 0x0028, 0x2001, 0xafa4, 0x2003,
-	0x0014, 0x2071, 0xaf8d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001,
-	0xafa5, 0x2003, 0x001e, 0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054,
-	0xa06d, 0x0110, 0x080c, 0x15f0, 0x00de, 0x0005, 0x0005, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0178,
-	0x611a, 0x0ca1, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033,
-	0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
-	0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
-	0x1500, 0x7080, 0xa086, 0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c,
-	0xd2e4, 0x1160, 0x2c78, 0x080c, 0x6e05, 0x01d8, 0x706c, 0x6a50,
-	0xa206, 0x1160, 0x7070, 0x6a54, 0xa206, 0x1140, 0x6218, 0xa290,
-	0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2b1e, 0x080c, 0x81f6,
-	0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
-	0x0005, 0x7050, 0x6a54, 0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x00c6, 0x080c, 0x8022, 0x001e, 0x0180, 0x611a,
-	0x080c, 0x9956, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0043,
-	0x080c, 0x80a7, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
-	0x0cd8, 0x00d6, 0x00e6, 0x00f6, 0x2071, 0xad00, 0xa186, 0x0015,
-	0x11c0, 0x7080, 0xa086, 0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f,
-	0x2c78, 0x080c, 0x6e05, 0x01a8, 0x706c, 0x6a08, 0xa206, 0x1130,
-	0x7070, 0x6a0c, 0xa206, 0x1110, 0x080c, 0x2ad9, 0x080c, 0x81f6,
-	0x0020, 0x080c, 0x85f3, 0x080c, 0x8078, 0x00fe, 0x00ee, 0x00de,
-	0x0005, 0x7050, 0x6a0c, 0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026,
-	0x684c, 0xd0ac, 0x0178, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0150,
-	0x6860, 0xa106, 0x1118, 0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e,
-	0xa085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00d6, 0x0036, 0x6310,
-	0x2368, 0x684a, 0x6952, 0xa29e, 0x4000, 0x1188, 0x00c6, 0x6318,
-	0x2360, 0x2009, 0x0000, 0x080c, 0x4f6e, 0x1108, 0xc185, 0x6000,
-	0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66,
-	0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6,
-	0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c,
-	0x510c, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026, 0x0016, 0xa186,
-	0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c, 0x9586, 0x01f0,
-	0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x1190,
-	0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160, 0x6108, 0x6834,
-	0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106, 0x1118, 0x6018,
-	0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005, 0xa085, 0x0001,
-	0x0cc8, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013,
-	0x006e, 0x0005, 0x9a7a, 0x9eff, 0xa027, 0x9a7a, 0x9a7a, 0x9a7a,
-	0x9a7a, 0x9a7a, 0x9ab2, 0xa0a3, 0x9a7a, 0x9a7a, 0x9a7a, 0x9a7a,
-	0x9a7a, 0x9a7a, 0x080c, 0x14f6, 0x0066, 0x6000, 0xa0b2, 0x0010,
-	0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005, 0x9a95, 0xa4fd, 0x9a95,
-	0x9a95, 0x9a95, 0x9a95, 0x9a95, 0x9a95, 0xa4c1, 0xa545, 0x9a95,
-	0xaaea, 0xab1a, 0xaaea, 0xab1a, 0x9a95, 0x080c, 0x14f6, 0x0066,
-	0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x14f6, 0x0013, 0x006e, 0x0005,
-	0x9ab0, 0xa1d8, 0xa295, 0xa2c2, 0xa346, 0x9ab0, 0xa433, 0xa3de,
-	0xa0af, 0xa497, 0xa4ac, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0, 0x9ab0,
-	0x080c, 0x14f6, 0xa1b2, 0x0080, 0x1a0c, 0x14f6, 0x2100, 0xa1b2,
-	0x0040, 0x1a04, 0x9e79, 0x0002, 0x9afc, 0x9cab, 0x9afc, 0x9afc,
-	0x9afc, 0x9cb2, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
-	0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc,
-	0x9afc, 0x9afc, 0x9afc, 0x9afe, 0x9b5a, 0x9b65, 0x9ba6, 0x9bc0,
-	0x9c3e, 0x9c9c, 0x9afc, 0x9afc, 0x9cb5, 0x9afc, 0x9afc, 0x9cc4,
-	0x9ccb, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9afc, 0x9d42, 0x9afc,
-	0x9afc, 0x9d4d, 0x9afc, 0x9afc, 0x9d18, 0x9afc, 0x9afc, 0x9afc,
-	0x9d61, 0x9afc, 0x9afc, 0x9afc, 0x9dd5, 0x9afc, 0x9afc, 0x9afc,
-	0x9afc, 0x9afc, 0x9afc, 0x9e40, 0x080c, 0x14f6, 0x080c, 0x502d,
-	0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
-	0x1140, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804,
-	0x9ca6, 0x080c, 0x501d, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016,
-	0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x68e7,
-	0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712,
-	0x007e, 0x001e, 0x2e60, 0x080c, 0x4ecf, 0x001e, 0x002e, 0x003e,
-	0x00ce, 0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4ceb, 0x00ce,
-	0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278,
-	0x080c, 0xa656, 0x1904, 0x9ba0, 0x080c, 0xa5f6, 0x1120, 0x6007,
-	0x0008, 0x0804, 0x9ca6, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c,
-	0xa801, 0x0128, 0x080c, 0xa656, 0x0d78, 0x0804, 0x9ba0, 0x6013,
-	0x1900, 0x0c88, 0x6106, 0x080c, 0xa5a6, 0x6007, 0x0006, 0x0804,
-	0x9ca6, 0x6007, 0x0007, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
-	0x9e76, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4,
-	0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686,
-	0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xa6b4, 0x11a0, 0xa686,
-	0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
-	0x0000, 0x080c, 0x2b1e, 0x002e, 0x080c, 0x4d72, 0x6007, 0x000a,
-	0x00de, 0x0804, 0x9ca6, 0x6007, 0x000b, 0x00de, 0x0804, 0x9ca6,
-	0x080c, 0x2ad9, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x080c, 0xab4e,
-	0x1904, 0x9e76, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa686,
-	0x0707, 0x0d70, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
-	0x0000, 0x080c, 0x2b1e, 0x002e, 0x6007, 0x000c, 0x0804, 0x9ca6,
-	0x080c, 0x502d, 0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009,
-	0xa086, 0x0008, 0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618,
-	0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06e8,
-	0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x4c5d, 0x002e, 0x0050,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006,
-	0x1904, 0x9ba0, 0x080c, 0xa6c1, 0x1120, 0x6007, 0x000e, 0x0804,
-	0x9ca6, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
-	0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
-	0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
-	0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
-	0x004e, 0x6007, 0x0001, 0x0804, 0x9ca6, 0x2001, 0x0001, 0x080c,
-	0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
-	0xad05, 0x2011, 0xb290, 0x080c, 0x8a7c, 0x003e, 0x002e, 0x001e,
-	0x015e, 0xa005, 0x0168, 0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004,
-	0x0a04, 0x9ba0, 0xa682, 0x0007, 0x0a04, 0x9bea, 0x0804, 0x9ba0,
-	0x6013, 0x1900, 0x6007, 0x0009, 0x0804, 0x9ca6, 0x080c, 0x502d,
-	0x1140, 0x2001, 0xad34, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
-	0x1110, 0x0804, 0x9b09, 0x080c, 0x501d, 0x6618, 0xa6b0, 0x0001,
-	0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x06b0, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x9ba0,
-	0x080c, 0xa6e9, 0x1130, 0x080c, 0xa5f6, 0x1118, 0x6007, 0x0010,
-	0x04e8, 0x0046, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff,
-	0x8427, 0x0046, 0x080c, 0x2ad9, 0x004e, 0x0016, 0xa006, 0x2009,
-	0xad52, 0x210c, 0xd1a4, 0x0158, 0x2009, 0x0029, 0x080c, 0xa96c,
-	0x6018, 0x00d6, 0x2068, 0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e,
-	0x004e, 0x6007, 0x0001, 0x00d0, 0x080c, 0xa801, 0x0140, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0006, 0x0958, 0x0804, 0x9ba0, 0x6013,
-	0x1900, 0x6007, 0x0009, 0x0050, 0x080c, 0xab4e, 0x1904, 0x9e76,
-	0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0012, 0x6003, 0x0001,
-	0x080c, 0x67ee, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
-	0x67ee, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xab4e, 0x1904,
-	0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6007, 0x0020, 0x6003,
-	0x0001, 0x080c, 0x67ee, 0x0005, 0x6007, 0x0023, 0x6003, 0x0001,
-	0x080c, 0x67ee, 0x0005, 0x080c, 0xab4e, 0x1904, 0x9e76, 0x080c,
-	0x9e98, 0x1904, 0x9ba0, 0x0016, 0x0026, 0x2011, 0xb291, 0x2214,
-	0xa286, 0xffff, 0x0190, 0x2c08, 0x080c, 0x9586, 0x01d8, 0x2260,
-	0x2011, 0xb290, 0x2214, 0x6008, 0xa206, 0x11a0, 0x6018, 0xa190,
-	0x0006, 0x2214, 0xa206, 0x01e0, 0x0068, 0x2011, 0xb290, 0x2214,
-	0x2c08, 0x080c, 0xa940, 0x11a0, 0x2011, 0xb291, 0x2214, 0xa286,
-	0xffff, 0x01a0, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011,
-	0xb289, 0x2214, 0xa296, 0xffff, 0x1160, 0x6007, 0x0025, 0x0048,
-	0x601c, 0xa086, 0x0007, 0x1d70, 0x080c, 0x8078, 0x2160, 0x6007,
-	0x0025, 0x6003, 0x0001, 0x080c, 0x67ee, 0x002e, 0x001e, 0x0005,
-	0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026, 0x0036,
-	0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c, 0x8a7c,
-	0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804,
-	0x9ca6, 0x080c, 0x87bd, 0x080c, 0x574f, 0x1158, 0x0006, 0x0026,
-	0x0036, 0x080c, 0x576b, 0x0110, 0x080c, 0x5726, 0x003e, 0x002e,
-	0x000e, 0x0005, 0x6106, 0x080c, 0x9eb4, 0x6007, 0x002b, 0x0804,
-	0x9ca6, 0x6007, 0x002c, 0x0804, 0x9ca6, 0x080c, 0xab4e, 0x1904,
-	0x9e76, 0x080c, 0x9e98, 0x1904, 0x9ba0, 0x6106, 0x080c, 0x9eb8,
-	0x1120, 0x6007, 0x002e, 0x0804, 0x9ca6, 0x6007, 0x002f, 0x0804,
-	0x9ca6, 0x00e6, 0x00d6, 0x00c6, 0x6018, 0xa080, 0x0001, 0x200c,
-	0xa184, 0x00ff, 0xa086, 0x0006, 0x0158, 0xa184, 0xff00, 0x8007,
-	0xa086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0x9cab,
-	0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904, 0x9dd2, 0x2071, 0xb28c,
-	0x7010, 0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xad52,
-	0x2004, 0xd0a4, 0x0140, 0x6018, 0x2068, 0x6810, 0xa106, 0x1118,
-	0x6814, 0xa206, 0x01f8, 0x2001, 0xad52, 0x2004, 0xd0ac, 0x1580,
-	0x2069, 0xad00, 0x6870, 0xa206, 0x1558, 0x686c, 0xa106, 0x1540,
-	0x7210, 0x080c, 0x9586, 0x0548, 0x080c, 0xa9d4, 0x0530, 0x622a,
-	0x6007, 0x0036, 0x6003, 0x0001, 0x080c, 0x67a8, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x7214, 0xa286, 0xffff, 0x0150, 0x080c, 0x9586,
-	0x01a0, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x1170, 0x0c08,
-	0x7210, 0x2c08, 0x080c, 0xa940, 0x2c10, 0x2160, 0x0130, 0x08c8,
-	0x6007, 0x0037, 0x6013, 0x1500, 0x08e8, 0x6007, 0x0037, 0x6013,
-	0x1700, 0x08c0, 0x6007, 0x0012, 0x08a8, 0x6018, 0xa080, 0x0001,
-	0x2004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006, 0x1904, 0x9cab,
-	0x00e6, 0x00d6, 0x00c6, 0x2001, 0xad71, 0x2004, 0xd0e4, 0x0904,
-	0x9e38, 0x2069, 0xad00, 0x2071, 0xb28c, 0x7008, 0x6036, 0x720c,
-	0x623a, 0xa286, 0xffff, 0x1140, 0x7208, 0x00c6, 0x2c08, 0x080c,
-	0xa940, 0x2c10, 0x00ce, 0x0588, 0x080c, 0x9586, 0x0570, 0x00c6,
-	0x0026, 0x2260, 0x080c, 0x928f, 0x002e, 0x00ce, 0x7118, 0xa18c,
-	0xff00, 0x810f, 0xa186, 0x0001, 0x0158, 0xa186, 0x0005, 0x0118,
-	0xa186, 0x0007, 0x1178, 0xa280, 0x0004, 0x2004, 0xa005, 0x0150,
-	0x0056, 0x7510, 0x7614, 0x080c, 0xa9eb, 0x005e, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
-	0x6003, 0x0001, 0x080c, 0x67a8, 0x0c88, 0x6007, 0x003b, 0x602b,
-	0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x080c, 0x67a8, 0x0c30,
-	0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0804, 0x9daa,
-	0x00e6, 0x0026, 0x080c, 0x502d, 0x0558, 0x080c, 0x501d, 0x080c,
-	0xabc5, 0x1520, 0x2071, 0xad00, 0x70d0, 0xc085, 0x70d2, 0x00f6,
-	0x2079, 0x0100, 0x729c, 0xa284, 0x00ff, 0x706e, 0x78e6, 0xa284,
-	0xff00, 0x7270, 0xa205, 0x7072, 0x78ea, 0x00fe, 0x70db, 0x0000,
-	0x2001, 0xad52, 0x2004, 0xd0a4, 0x0120, 0x2011, 0xafe0, 0x2013,
-	0x07d0, 0xd0ac, 0x1128, 0x080c, 0x28fa, 0x0010, 0x080c, 0xabf1,
-	0x002e, 0x00ee, 0x080c, 0x8078, 0x0804, 0x9caa, 0x080c, 0x8078,
-	0x0005, 0x2600, 0x0002, 0x9e81, 0x9e81, 0x9e81, 0x9e81, 0x9e81,
-	0x9e83, 0x080c, 0x14f6, 0x080c, 0xab4e, 0x1d80, 0x0089, 0x1138,
-	0x6007, 0x0045, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005, 0x080c,
-	0x2ad9, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x67ee, 0x0005,
-	0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0170, 0xa686, 0x0004, 0x0158, 0x6e04, 0xa6b4,
-	0x00ff, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085,
-	0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0449, 0x00de, 0x0005,
-	0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084,
-	0x00ff, 0xa115, 0x6212, 0x6824, 0x602a, 0xd1e4, 0x0118, 0x2009,
-	0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824,
-	0x080c, 0x2676, 0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x2b1e,
-	0x0018, 0xa085, 0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069,
-	0xb28d, 0x6800, 0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085,
-	0x0001, 0x0008, 0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0xb28c,
-	0x6808, 0xa084, 0xff00, 0xa086, 0x0800, 0x1140, 0x6800, 0xa084,
-	0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e, 0x0010, 0x0005, 0x6004,
-	0xa0b2, 0x0080, 0x1a0c, 0x14f6, 0xa1b6, 0x0013, 0x1130, 0x2008,
-	0xa1b2, 0x0040, 0x1a04, 0x9ffb, 0x0092, 0xa1b6, 0x0027, 0x0120,
-	0xa1b6, 0x0014, 0x190c, 0x14f6, 0x2001, 0x0007, 0x080c, 0x4c5d,
-	0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0x9f5f,
-	0x9f61, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f6f, 0x9ff4, 0x9fbf,
-	0x9ff4, 0x9fd0, 0x9ff4, 0x9f6f, 0x9ff4, 0x9fec, 0x9ff4, 0x9fec,
-	0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f,
-	0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f61, 0x9f5f, 0x9ff4,
-	0x9f5f, 0x9f5f, 0x9ff4, 0x9f5f, 0x9ff1, 0x9ff4, 0x9f5f, 0x9f5f,
-	0x9f5f, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f,
-	0x9f69, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x9ff0, 0x9ff4, 0x9f5f,
-	0x9f5f, 0x9ff4, 0x9ff4, 0x9f5f, 0x9f5f, 0x9f5f, 0x9f5f, 0x080c,
-	0x14f6, 0x080c, 0x6b73, 0x6003, 0x0002, 0x080c, 0x6c50, 0x0804,
-	0x9ffa, 0x2001, 0x0000, 0x080c, 0x4c1e, 0x0804, 0x9ff4, 0x00f6,
-	0x2079, 0xad51, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0x9ff4, 0x2001,
-	0x0000, 0x080c, 0x4c1e, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086,
-	0x00ff, 0x1140, 0x00f6, 0x2079, 0xad00, 0x7894, 0x8000, 0x7896,
-	0x00fe, 0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140,
-	0x6010, 0xa005, 0x0128, 0x00ce, 0x080c, 0x3cce, 0x0804, 0x9ff4,
-	0x00ce, 0x2001, 0xad00, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6,
-	0x2079, 0xad00, 0x7894, 0x8000, 0x7896, 0x00fe, 0x2001, 0x0002,
-	0x080c, 0x4c30, 0x080c, 0x6b73, 0x601f, 0x0001, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00c6, 0x6118,
-	0x2160, 0x2009, 0x0001, 0x080c, 0x6519, 0x00ce, 0x04d8, 0x6618,
-	0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410,
-	0x2001, 0xad00, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3cce,
-	0x2001, 0x0006, 0x0489, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006,
-	0x0048, 0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x00e9, 0x0020,
-	0x0018, 0x0010, 0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x8078,
-	0x080c, 0x6c50, 0x0005, 0x2600, 0x0002, 0xa003, 0xa003, 0xa003,
-	0xa003, 0xa003, 0xa005, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x080c,
-	0x8078, 0x080c, 0x6c50, 0x0005, 0x0016, 0x00d6, 0x6118, 0x2168,
-	0x6900, 0xd184, 0x0188, 0x6104, 0xa18e, 0x000a, 0x1128, 0x699c,
-	0xd1a4, 0x1110, 0x2001, 0x0007, 0x080c, 0x4c30, 0x2001, 0x0000,
-	0x080c, 0x4c1e, 0x080c, 0x2aff, 0x00de, 0x001e, 0x0005, 0x00d6,
-	0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2,
-	0x000c, 0x1a0c, 0x14f6, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028,
-	0xa1b6, 0x0016, 0x190c, 0x14f6, 0x006b, 0x0005, 0x86b9, 0x86b9,
-	0x86b9, 0x86b9, 0x86b9, 0x86b9, 0xa08f, 0xa056, 0x86b9, 0x86b9,
-	0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x86b9,
-	0xa08f, 0xa096, 0x86b9, 0x86b9, 0x86b9, 0x86b9, 0x00f6, 0x2079,
-	0xad51, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8, 0x7800,
-	0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000, 0x080c,
-	0x4c1e, 0x2001, 0x0002, 0x080c, 0x4c30, 0x601f, 0x0001, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x080c, 0x67ee, 0x080c, 0x6c50, 0x00a8,
-	0x2011, 0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x1168,
-	0x00c6, 0x080c, 0x4cdc, 0x0120, 0x00ce, 0x080c, 0x8078, 0x0028,
-	0x080c, 0x493a, 0x00ce, 0x080c, 0x8078, 0x00fe, 0x0005, 0x6604,
-	0xa6b6, 0x001e, 0x1110, 0x080c, 0x8078, 0x0005, 0x080c, 0x8940,
-	0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x67ee, 0x0010,
-	0x080c, 0x8078, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x14f6,
-	0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005, 0xa182,
-	0x0040, 0x0002, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c7, 0xa0c5,
-	0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5,
-	0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0xa0c5, 0x080c, 0x14f6, 0x00d6,
-	0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280, 0x002b,
-	0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xab96, 0x6106,
-	0x2071, 0xb280, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa129, 0xa486,
-	0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c, 0x663f,
-	0x080c, 0x15d9, 0x090c, 0x14f6, 0x6003, 0x0007, 0x2d00, 0x6837,
-	0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e,
-	0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a,
-	0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036,
-	0x080c, 0x510c, 0x001e, 0xa486, 0x2000, 0x1130, 0x2019, 0x0017,
-	0x080c, 0xa8eb, 0x0804, 0xa186, 0xa486, 0x0400, 0x1130, 0x2019,
-	0x0002, 0x080c, 0xa89d, 0x0804, 0xa186, 0xa486, 0x0200, 0x1110,
-	0x080c, 0xa882, 0xa486, 0x1000, 0x1110, 0x080c, 0xa8d0, 0x0804,
-	0xa186, 0x2069, 0xb048, 0x6a00, 0xd284, 0x0904, 0xa1d5, 0xa284,
-	0x0300, 0x1904, 0xa1cf, 0x6804, 0xa005, 0x0904, 0xa1c0, 0x2d78,
-	0x6003, 0x0007, 0x080c, 0x15c0, 0x0904, 0xa18d, 0x7800, 0xd08c,
-	0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803, 0x0000,
-	0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00, 0x684a,
-	0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846, 0x7928,
-	0x698a, 0x792c, 0x698e, 0x7930, 0x6992, 0x7934, 0x6996, 0x6853,
-	0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118, 0x684f,
-	0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080, 0x0010,
-	0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0xb290, 0xad90, 0x0015,
-	0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0xa178, 0x200c,
-	0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x510c, 0x002e, 0x004e,
-	0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0c70,
-	0x2069, 0xb292, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x11a8,
-	0x2069, 0xb280, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110, 0xa18c,
-	0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043,
-	0x080c, 0x67a8, 0x080c, 0x6c50, 0x0888, 0x6013, 0x0200, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0830,
-	0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007,
-	0x0041, 0x080c, 0x67a8, 0x080c, 0x6c50, 0x0804, 0xa186, 0x6013,
-	0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200, 0x0800,
-	0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c, 0x14f6,
-	0xa08a, 0x0053, 0x1a0c, 0x14f6, 0xa082, 0x0040, 0x2008, 0x0804,
-	0xa252, 0xa186, 0x0051, 0x0138, 0xa186, 0x0047, 0x11d8, 0x6004,
-	0xa086, 0x0041, 0x0518, 0x2001, 0x0109, 0x2004, 0xd084, 0x01f0,
-	0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x6699,
-	0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086, 0x0002, 0x1170,
-	0x0804, 0xa295, 0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c,
-	0x14f6, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a, 0x080c, 0x80be,
-	0x0005, 0xa22c, 0xa22e, 0xa22e, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
-	0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c, 0xa22c,
-	0xa22c, 0xa22c, 0xa22c, 0xa22c, 0x080c, 0x14f6, 0x080c, 0x6b73,
-	0x080c, 0x6c50, 0x0036, 0x00d6, 0x6010, 0xa06d, 0x01c0, 0xad84,
-	0xf000, 0x01a8, 0x6003, 0x0002, 0x6018, 0x2004, 0xd0bc, 0x1178,
-	0x2019, 0x0004, 0x080c, 0xa91f, 0x6013, 0x0000, 0x6014, 0xa005,
-	0x1120, 0x2001, 0xafa4, 0x2004, 0x6016, 0x6003, 0x0007, 0x00de,
-	0x003e, 0x0005, 0x0002, 0xa266, 0xa283, 0xa26f, 0xa28f, 0xa266,
-	0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266,
-	0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0xa266, 0x080c, 0x14f6,
-	0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x080c,
-	0x6b73, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0138, 0x6003,
-	0x0007, 0x2009, 0x0043, 0x080c, 0x80a7, 0x0010, 0x6003, 0x0002,
-	0x080c, 0x6c50, 0x0005, 0x080c, 0x6b73, 0x080c, 0xab55, 0x1120,
-	0x080c, 0x6618, 0x080c, 0x8078, 0x080c, 0x6c50, 0x0005, 0x080c,
-	0x6b73, 0x2009, 0x0041, 0x0804, 0xa3de, 0xa182, 0x0040, 0x0002,
-	0xa2ab, 0xa2ad, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ae,
-	0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab, 0xa2ab,
-	0xa2ab, 0xa2b9, 0xa2ab, 0x080c, 0x14f6, 0x0005, 0x6003, 0x0004,
-	0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1824,
-	0x0005, 0x00d6, 0x080c, 0x6618, 0x00de, 0x080c, 0xabb4, 0x080c,
-	0x8078, 0x0005, 0xa182, 0x0040, 0x0002, 0xa2d8, 0xa2d8, 0xa2d8,
-	0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa2da, 0xa2d8, 0xa2dd, 0xa316,
-	0xa2d8, 0xa2d8, 0xa2d8, 0xa2d8, 0xa316, 0xa2d8, 0xa2d8, 0xa2d8,
-	0x080c, 0x14f6, 0x080c, 0x80be, 0x0005, 0x2001, 0xad71, 0x2004,
-	0xd0e4, 0x0158, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x0228,
-	0x2001, 0x011f, 0x2004, 0x6036, 0x0010, 0x6037, 0x0000, 0x080c,
-	0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x684c, 0xd0fc,
-	0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0168, 0x2009, 0x0041,
-	0x00de, 0x0804, 0xa3de, 0x6003, 0x0007, 0x6017, 0x0000, 0x080c,
-	0x6618, 0x00de, 0x0005, 0x080c, 0xab55, 0x0110, 0x00de, 0x0005,
-	0x080c, 0x6618, 0x080c, 0x8078, 0x00de, 0x0ca0, 0x0036, 0x080c,
-	0x6c05, 0x080c, 0x6d0d, 0x6010, 0x00d6, 0x2068, 0x6018, 0x2004,
-	0xd0bc, 0x0188, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0140,
-	0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a,
-	0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xa91f, 0x6014,
-	0xa005, 0x1128, 0x2001, 0xafa4, 0x2004, 0x8003, 0x6016, 0x6013,
-	0x0000, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0xa186, 0x0013,
-	0x1150, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x080c, 0x6b73,
-	0x080c, 0x6c50, 0x0005, 0xa186, 0x0027, 0x0118, 0xa186, 0x0014,
-	0x1180, 0x6004, 0xa086, 0x0042, 0x190c, 0x14f6, 0x2001, 0x0007,
-	0x080c, 0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50,
-	0x0005, 0xa182, 0x0040, 0x0002, 0xa37f, 0xa37f, 0xa37f, 0xa37f,
-	0xa37f, 0xa37f, 0xa37f, 0xa381, 0xa38d, 0xa37f, 0xa37f, 0xa37f,
-	0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0xa37f, 0x080c,
-	0x14f6, 0x0036, 0x0046, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
-	0x080c, 0x1824, 0x004e, 0x003e, 0x0005, 0x6010, 0x00d6, 0x2068,
-	0x6810, 0x6a14, 0x0006, 0x0046, 0x0056, 0x6c7c, 0xa422, 0x6d80,
-	0x2200, 0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a,
-	0x005e, 0x004e, 0x000e, 0xa20d, 0x1178, 0x684c, 0xd0fc, 0x0120,
-	0x2009, 0x0041, 0x00de, 0x0490, 0x6003, 0x0007, 0x6017, 0x0000,
-	0x080c, 0x6618, 0x00de, 0x0005, 0x0006, 0x00f6, 0x2c78, 0x080c,
-	0x5029, 0x00fe, 0x000e, 0x0120, 0x6003, 0x0002, 0x00de, 0x0005,
-	0x2009, 0xad0d, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010,
-	0x6003, 0x0006, 0x0021, 0x080c, 0x661a, 0x00de, 0x0005, 0xd2fc,
-	0x0140, 0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009,
-	0x0010, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040,
-	0x0208, 0x0062, 0xa186, 0x0013, 0x0120, 0xa186, 0x0014, 0x190c,
-	0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005, 0xa401, 0xa408,
-	0xa414, 0xa420, 0xa401, 0xa401, 0xa401, 0xa42f, 0xa401, 0xa403,
-	0xa403, 0xa401, 0xa401, 0xa401, 0xa401, 0xa403, 0xa401, 0xa403,
-	0xa401, 0x080c, 0x14f6, 0x6020, 0xd0dc, 0x090c, 0x14f6, 0x0005,
-	0x6003, 0x0001, 0x6106, 0x080c, 0x67a8, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6c50, 0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c,
-	0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e, 0x0005,
-	0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x680b, 0x080c, 0x6d0d, 0x012e, 0x0005, 0xa016,
-	0x080c, 0x1824, 0x0005, 0x0126, 0x2091, 0x8000, 0x0036, 0x00d6,
-	0xa182, 0x0040, 0x0023, 0x00de, 0x003e, 0x012e, 0x0005, 0xa44f,
-	0xa451, 0xa463, 0xa47e, 0xa44f, 0xa44f, 0xa44f, 0xa493, 0xa44f,
-	0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0xa44f, 0x080c,
-	0x14f6, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x01f8, 0xa09c, 0x0003,
-	0xa39e, 0x0003, 0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x67a8,
-	0x080c, 0x6c50, 0x0498, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0168,
-	0xa09c, 0x0003, 0xa39e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106,
-	0x080c, 0x67a8, 0x080c, 0x6c50, 0x0408, 0x6013, 0x0000, 0x6017,
-	0x0000, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00c0, 0x6010, 0x2068,
-	0x684c, 0xd0fc, 0x0d90, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0d68,
-	0x6003, 0x0003, 0x6106, 0x2c10, 0x080c, 0x1e6e, 0x080c, 0x680b,
-	0x080c, 0x6d0d, 0x0018, 0xa016, 0x080c, 0x1824, 0x0005, 0x080c,
-	0x6b73, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa,
-	0x0036, 0x2019, 0x0029, 0x080c, 0xa91f, 0x003e, 0x00de, 0x080c,
-	0x974e, 0x080c, 0x6c50, 0x0005, 0x080c, 0x6c05, 0x6110, 0x81ff,
-	0x0158, 0x00d6, 0x2168, 0x080c, 0xabfa, 0x0036, 0x2019, 0x0029,
-	0x080c, 0xa91f, 0x003e, 0x00de, 0x080c, 0x974e, 0x080c, 0x6d0d,
-	0x0005, 0xa182, 0x0085, 0x0002, 0xa4cd, 0xa4cb, 0xa4cb, 0xa4d9,
-	0xa4cb, 0xa4cb, 0xa4cb, 0x080c, 0x14f6, 0x6003, 0x000b, 0x6106,
-	0x080c, 0x67a8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6c50, 0x012e,
-	0x0005, 0x0026, 0x00e6, 0x080c, 0xab4e, 0x0118, 0x080c, 0x8078,
-	0x00c8, 0x2071, 0xb280, 0x7224, 0x6212, 0x7220, 0x080c, 0xa7ce,
-	0x0118, 0x6007, 0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0xa296,
-	0xffff, 0x1110, 0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x67a8,
-	0x080c, 0x6c50, 0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160,
-	0x6004, 0xa08a, 0x0085, 0x0a0c, 0x14f6, 0xa08a, 0x008c, 0x1a0c,
-	0x14f6, 0xa082, 0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186,
-	0x0014, 0x0118, 0x080c, 0x80be, 0x0050, 0x2001, 0x0007, 0x080c,
-	0x4c5d, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
-	0xa527, 0xa529, 0xa529, 0xa527, 0xa527, 0xa527, 0xa527, 0x080c,
-	0x14f6, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
-	0xa182, 0x0085, 0x0a0c, 0x14f6, 0xa182, 0x008c, 0x1a0c, 0x14f6,
-	0xa182, 0x0085, 0x0002, 0xa542, 0xa542, 0xa542, 0xa544, 0xa542,
-	0xa542, 0xa542, 0x080c, 0x14f6, 0x0005, 0xa186, 0x0013, 0x0148,
-	0xa186, 0x0014, 0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x80be,
-	0x0030, 0x080c, 0x6b73, 0x080c, 0x974e, 0x080c, 0x6c50, 0x0005,
-	0x0036, 0x080c, 0xabb4, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031,
-	0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036,
-	0x2091, 0x8000, 0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c,
-	0x7b9a, 0x009e, 0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x7c34,
-	0x007e, 0x1548, 0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086,
-	0x0007, 0x0508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c,
-	0xabb4, 0x601f, 0x0007, 0x2001, 0xafa3, 0x2004, 0x6016, 0x080c,
-	0x190b, 0x6010, 0x2068, 0x080c, 0x9596, 0x0110, 0x080c, 0xa91f,
-	0x00de, 0x6013, 0x0000, 0x080c, 0xabb4, 0x601f, 0x0007, 0x2001,
-	0xafa3, 0x2004, 0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6,
-	0x0036, 0x0156, 0x2079, 0xb280, 0x7938, 0x783c, 0x080c, 0x2676,
-	0x1904, 0xa5f1, 0x0016, 0x00c6, 0x080c, 0x4cdc, 0x15c0, 0x2011,
-	0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1578,
-	0x001e, 0x002e, 0x0026, 0x0016, 0x2019, 0x0029, 0x080c, 0x7cf4,
-	0x080c, 0x68e7, 0x0076, 0x2039, 0x0000, 0x080c, 0x681d, 0x007e,
-	0x001e, 0x0076, 0x2039, 0x0000, 0x080c, 0xa712, 0x007e, 0x080c,
-	0x4ecf, 0x0026, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
-	0x0118, 0xa286, 0x0004, 0x1118, 0x62a0, 0x080c, 0x2b87, 0x002e,
-	0x001e, 0x080c, 0x493a, 0x6612, 0x6516, 0xa006, 0x0010, 0x00ce,
-	0x001e, 0x015e, 0x003e, 0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6,
-	0x00e6, 0x0016, 0x2009, 0xad20, 0x2104, 0xa086, 0x0074, 0x1904,
-	0xa64b, 0x2069, 0xb28e, 0x690c, 0xa182, 0x0100, 0x06c0, 0x6908,
-	0xa184, 0x8000, 0x05e8, 0x2001, 0xaf9d, 0x2004, 0xa005, 0x1160,
-	0x6018, 0x2070, 0x7010, 0xa084, 0x00ff, 0x0118, 0x7000, 0xd0f4,
-	0x0118, 0xa184, 0x0800, 0x0560, 0x6910, 0xa18a, 0x0001, 0x0610,
-	0x6914, 0x2069, 0xb2ae, 0x6904, 0x81ff, 0x1198, 0x690c, 0xa182,
-	0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178, 0x6910, 0xa18a, 0x0001,
-	0x0288, 0x6918, 0xa18a, 0x0001, 0x0298, 0x00d0, 0x6013, 0x0100,
-	0x00a0, 0x6013, 0x0300, 0x0088, 0x6013, 0x0500, 0x0070, 0x6013,
-	0x0700, 0x0058, 0x6013, 0x0900, 0x0040, 0x6013, 0x0b00, 0x0028,
-	0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0008,
-	0xa006, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6,
-	0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff,
-	0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178, 0xa394, 0xff00,
-	0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004, 0x0130, 0x00c6,
-	0x2d60, 0x080c, 0x4ceb, 0x00ce, 0x04c0, 0x2011, 0xb296, 0xad98,
-	0x000a, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1580, 0x2011, 0xb29a,
-	0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1538, 0x0046,
-	0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xad52,
-	0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xa96c, 0x6800,
-	0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x68e7, 0x0076, 0x2039,
-	0x0000, 0x080c, 0x681d, 0x2c08, 0x080c, 0xa712, 0x007e, 0x2001,
-	0x0007, 0x080c, 0x4c5d, 0x001e, 0x004e, 0xa006, 0x015e, 0x003e,
-	0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069, 0xb28e, 0x6800,
-	0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008, 0xa006, 0x00de,
-	0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079,
-	0xb28c, 0x7930, 0x7834, 0x080c, 0x2676, 0x11a0, 0x080c, 0x4cdc,
-	0x1188, 0x2011, 0xb290, 0xac98, 0x000a, 0x20a9, 0x0004, 0x080c,
-	0x8a7c, 0x1140, 0x2011, 0xb294, 0xac98, 0x0006, 0x20a9, 0x0004,
-	0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x00fe, 0x00ce,
-	0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036, 0x0156, 0x2011,
-	0xb283, 0x2204, 0x8211, 0x220c, 0x080c, 0x2676, 0x11a0, 0x080c,
-	0x4cdc, 0x1188, 0x2011, 0xb296, 0xac98, 0x000a, 0x20a9, 0x0004,
-	0x080c, 0x8a7c, 0x1140, 0x2011, 0xb29a, 0xac98, 0x0006, 0x20a9,
-	0x0004, 0x080c, 0x8a7c, 0x015e, 0x003e, 0x002e, 0x001e, 0x000e,
-	0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0056,
-	0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740, 0x2029, 0xafd0,
-	0x252c, 0x2021, 0xafd6, 0x2424, 0x2061, 0xb400, 0x2071, 0xad00,
-	0x7644, 0x7064, 0x81ff, 0x0128, 0x8001, 0xa602, 0x1a04, 0xa78e,
-	0x0018, 0xa606, 0x0904, 0xa78e, 0x2100, 0xac06, 0x0904, 0xa785,
-	0x080c, 0xa990, 0x0904, 0xa785, 0x671c, 0xa786, 0x0001, 0x0904,
-	0xa7a5, 0xa786, 0x0004, 0x0904, 0xa7a5, 0xa786, 0x0007, 0x05e8,
-	0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c, 0xa9a0,
-	0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6, 0x6000,
-	0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x190b, 0x001e, 0xa786,
-	0x0008, 0x1148, 0x080c, 0x9789, 0x1130, 0x080c, 0x85f3, 0x00de,
-	0x080c, 0x974e, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9596, 0x0190,
-	0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x080c, 0xabfa, 0x0016, 0x080c, 0x97fd, 0x080c, 0x510c, 0x001e,
-	0x080c, 0x9742, 0x00de, 0x080c, 0x974e, 0xace0, 0x0018, 0x2001,
-	0xad16, 0x2004, 0xac02, 0x1210, 0x0804, 0xa726, 0x012e, 0x002e,
-	0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005,
-	0xa786, 0x0006, 0x19c0, 0xa386, 0x0005, 0x0128, 0x080c, 0xabfa,
-	0x080c, 0xa91f, 0x08f8, 0x00de, 0x0c00, 0x080c, 0xa9a0, 0x19e8,
-	0x81ff, 0x09d8, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x0130,
-	0xa180, 0x0001, 0x2004, 0xa086, 0x002d, 0x1978, 0x6000, 0xa086,
-	0x0002, 0x1958, 0x080c, 0x9778, 0x0130, 0x080c, 0x9789, 0x1928,
-	0x080c, 0x85f3, 0x0038, 0x080c, 0x2aff, 0x080c, 0x9789, 0x1110,
-	0x080c, 0x85f3, 0x080c, 0x974e, 0x0804, 0xa785, 0x00c6, 0x00e6,
-	0x0016, 0x2c08, 0x2170, 0x080c, 0xa940, 0x001e, 0x0120, 0x601c,
-	0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xa7e6, 0xa7e6,
-	0xa7e6, 0xa7e6, 0xa7e6, 0xa7e6, 0xa7e8, 0xa7e6, 0xa006, 0x0005,
-	0x0046, 0x0016, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff,
-	0x8427, 0x2c00, 0x2009, 0x0020, 0x080c, 0xa96c, 0x001e, 0x004e,
-	0x0036, 0x2019, 0x0002, 0x080c, 0xa566, 0x003e, 0xa085, 0x0001,
-	0x0005, 0x2001, 0x0001, 0x080c, 0x4c1e, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x20a9, 0x0004, 0x2019, 0xad05, 0x2011, 0xb296, 0x080c,
-	0x8a7c, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6,
-	0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091,
-	0x8000, 0x2740, 0x2061, 0xb400, 0x2079, 0x0001, 0x8fff, 0x0904,
-	0xa875, 0x2071, 0xad00, 0x7644, 0x7064, 0x8001, 0xa602, 0x1a04,
-	0xa875, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000,
-	0x080c, 0xa990, 0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786,
-	0x0006, 0x1550, 0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018,
-	0xa206, 0x1510, 0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6,
-	0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xabb4, 0x601f, 0x0007,
-	0x2001, 0xafa3, 0x2004, 0x6016, 0x080c, 0x190b, 0x6010, 0x2068,
-	0x080c, 0x9596, 0x0120, 0x0046, 0x080c, 0xa91f, 0x004e, 0x00de,
-	0x080c, 0x974e, 0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xad16,
-	0x2004, 0xac02, 0x1210, 0x0804, 0xa826, 0xa006, 0x012e, 0x002e,
-	0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5,
-	0x0001, 0x0ca0, 0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029,
-	0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000,
-	0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x7c34,
-	0x080c, 0xa817, 0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056,
-	0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x0016, 0x0036, 0x080c, 0x4cdc, 0x11b0, 0x2c10, 0x0056,
-	0x0086, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049,
-	0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
-	0x7c34, 0x080c, 0xa817, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04,
-	0xa8a9, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005,
-	0x0076, 0x0056, 0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001,
-	0x2019, 0x0048, 0x0096, 0x2049, 0x0000, 0x080c, 0x7b9a, 0x009e,
-	0x008e, 0x2039, 0x0000, 0x080c, 0x7c34, 0x2c20, 0x080c, 0xa817,
-	0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6,
-	0x0156, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036,
-	0x080c, 0x4cdc, 0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828,
-	0x0046, 0x2021, 0x0001, 0x080c, 0xab96, 0x004e, 0x0096, 0x2049,
-	0x0000, 0x080c, 0x7b9a, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c,
-	0x7c34, 0x080c, 0xa817, 0x003e, 0x001e, 0x8108, 0x1f04, 0xa8f6,
-	0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016,
-	0x00f6, 0x3800, 0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82,
-	0xad00, 0x0230, 0xad82, 0xe400, 0x0280, 0xad82, 0xffff, 0x1268,
-	0x6800, 0xa07d, 0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x510c,
-	0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x510c, 0x00fe, 0x001e, 0x0005,
-	0x00e6, 0x0046, 0x0036, 0x2061, 0xb400, 0x2071, 0xad00, 0x7444,
-	0x7064, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000,
-	0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0,
-	0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xad16,
-	0x2004, 0xac02, 0x1220, 0x0c08, 0xa085, 0x0001, 0x0008, 0xa006,
-	0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15d9,
-	0x000e, 0x090c, 0x14f6, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010,
-	0x080c, 0x9586, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014,
-	0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006,
-	0x68b2, 0x6802, 0x683a, 0x685a, 0x080c, 0x510c, 0x00de, 0x0005,
-	0x6700, 0xa786, 0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786,
-	0x000a, 0x0128, 0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005,
-	0x00e6, 0x6018, 0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0x0016,
-	0x6004, 0xa08e, 0x001e, 0x11a0, 0x8007, 0x6130, 0xa18c, 0x00ff,
-	0xa105, 0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005,
-	0x2001, 0xafa4, 0x2004, 0x6016, 0x080c, 0x67a8, 0x080c, 0x6c50,
-	0x001e, 0x0005, 0xe000, 0xe000, 0x0005, 0x6020, 0xd0e4, 0x0158,
-	0xd0cc, 0x0118, 0x080c, 0x9866, 0x0030, 0x080c, 0xabb4, 0x080c,
-	0x6618, 0x080c, 0x8078, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084,
-	0x000f, 0x0002, 0xa9e3, 0xa9e3, 0xa9e3, 0xa9e8, 0xa9e3, 0xa9e5,
-	0xa9e5, 0xa9e3, 0xa9e5, 0xa006, 0x0005, 0x00c6, 0x2260, 0x00ce,
-	0xa085, 0x0001, 0x0005, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f,
-	0x0002, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xa9fa, 0xaa05,
-	0xa9fa, 0xa9fa, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00,
-	0x6003, 0x0001, 0x080c, 0x67a8, 0x0005, 0x00c6, 0x2260, 0x080c,
-	0xabb4, 0x603f, 0x0000, 0x6020, 0xc0f4, 0xc0cc, 0x6022, 0x6037,
-	0x0000, 0x00ce, 0x00d6, 0x2268, 0xa186, 0x0007, 0x1904, 0xaa60,
-	0x6810, 0xa005, 0x0138, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x1110,
-	0x00de, 0x08c0, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c, 0x67a8,
-	0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002, 0x1904,
-	0xaae7, 0x6010, 0xa005, 0x1138, 0x6000, 0xa086, 0x0007, 0x190c,
-	0x14f6, 0x0804, 0xaae7, 0xa08c, 0xf000, 0x1130, 0x0028, 0x2068,
-	0x6800, 0xa005, 0x1de0, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084,
-	0x0003, 0xa086, 0x0002, 0x1180, 0x6010, 0x2068, 0x684c, 0xc0dc,
-	0xc0f4, 0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043,
-	0x080c, 0xa3de, 0x0804, 0xaae7, 0x2009, 0x0041, 0x0804, 0xaae1,
-	0xa186, 0x0005, 0x15f0, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc,
-	0x1118, 0x00de, 0x0804, 0xa9fa, 0xd0b4, 0x0128, 0xd0fc, 0x090c,
-	0x14f6, 0x0804, 0xaa18, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c,
-	0x67a8, 0x080c, 0x6c50, 0x00c6, 0x2d60, 0x6100, 0xa186, 0x0002,
-	0x0120, 0xa186, 0x0004, 0x1904, 0xaae7, 0x2071, 0xaffd, 0x7000,
-	0xa086, 0x0003, 0x1128, 0x7004, 0xac06, 0x1110, 0x7003, 0x0000,
-	0x6810, 0xa080, 0x0013, 0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000,
-	0x200c, 0xc1f4, 0xc1fc, 0xc1bc, 0x2102, 0x2009, 0x0042, 0x0804,
-	0xaae1, 0x0036, 0x00d6, 0x00d6, 0x080c, 0x15d9, 0x003e, 0x090c,
-	0x14f6, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b,
-	0x0000, 0x6b5e, 0x6857, 0x0045, 0x2c00, 0x6862, 0x6034, 0x6872,
-	0x2360, 0x6020, 0xc0dd, 0x6022, 0x6018, 0xa080, 0x0028, 0x2004,
-	0xa084, 0x00ff, 0x8007, 0x6350, 0x6b4a, 0x6846, 0x684f, 0x0000,
-	0x6d6a, 0x6e66, 0x686f, 0x0001, 0x080c, 0x510c, 0x2019, 0x0045,
-	0x6008, 0x2068, 0x080c, 0xa566, 0x2d00, 0x600a, 0x601f, 0x0006,
-	0x6003, 0x0007, 0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e,
-	0x0038, 0x603f, 0x0000, 0x6003, 0x0007, 0x080c, 0xa3de, 0x00ce,
-	0x00de, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085,
-	0x2008, 0x00c2, 0xa186, 0x0027, 0x1178, 0x080c, 0x6b73, 0x0036,
-	0x00d6, 0x6010, 0x2068, 0x2019, 0x0004, 0x080c, 0xa91f, 0x00de,
-	0x003e, 0x080c, 0x6c50, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c,
-	0x80be, 0x0005, 0xab13, 0xab11, 0xab11, 0xab11, 0xab11, 0xab11,
-	0xab13, 0x080c, 0x14f6, 0x080c, 0x6b73, 0x6003, 0x000c, 0x080c,
-	0x6c50, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208,
-	0x001a, 0x080c, 0x80be, 0x0005, 0xab2b, 0xab2b, 0xab2b, 0xab2b,
-	0xab2d, 0xab4b, 0xab2b, 0x080c, 0x14f6, 0x00d6, 0x2c68, 0x080c,
-	0x8022, 0x01a0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xb28e,
-	0x210c, 0x6136, 0x2009, 0xb28f, 0x210c, 0x613a, 0x600b, 0xffff,
-	0x6918, 0x611a, 0x601f, 0x0004, 0x080c, 0x67a8, 0x2d60, 0x080c,
-	0x8078, 0x00de, 0x0005, 0x080c, 0x8078, 0x0005, 0x00e6, 0x6018,
-	0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa080, 0x0013,
-	0x200c, 0xd1ec, 0x05d0, 0x2001, 0xad71, 0x2004, 0xd0ec, 0x05a8,
-	0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac, 0x0180, 0x00f6,
-	0x2c78, 0x080c, 0x5025, 0x00fe, 0x0150, 0x2001, 0xafa5, 0x2004,
-	0x603e, 0x2009, 0xad71, 0x210c, 0xd1f4, 0x11e8, 0x0080, 0x2009,
-	0xad71, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4, 0x6022, 0xa006,
-	0x00a0, 0x2001, 0xafa5, 0x200c, 0x8103, 0xa100, 0x603e, 0x6018,
-	0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088, 0x0003, 0x0cd0,
-	0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005, 0x0016, 0x00c6,
-	0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060, 0x8cff, 0x0180,
-	0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c, 0x2072, 0x080c,
-	0x6618, 0x080c, 0x8078, 0x0010, 0xacf0, 0x0003, 0x2e64, 0x0c70,
-	0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018, 0xa0e8, 0x002b,
-	0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04, 0xa0e8, 0x0003,
-	0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026, 0x0036, 0x0156,
-	0x2011, 0xad27, 0x2204, 0xa084, 0x00ff, 0x2019, 0xb28e, 0x2334,
-	0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084, 0xff00, 0xa636,
-	0x11a0, 0x2011, 0xb290, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004,
-	0x080c, 0x8a7c, 0x1150, 0x2011, 0xb294, 0x6018, 0xa098, 0x0006,
-	0x20a9, 0x0004, 0x080c, 0x8a7c, 0x1100, 0x015e, 0x003e, 0x002e,
-	0x0005, 0x00e6, 0x2071, 0xad00, 0x080c, 0x48f5, 0x080c, 0x28fa,
-	0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0108,
-	0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852, 0x0005, 0x00e6,
-	0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126,
-	0x2091, 0x8000, 0x2029, 0xafd0, 0x252c, 0x2021, 0xafd6, 0x2424,
-	0x2061, 0xb400, 0x2071, 0xad00, 0x7644, 0x7064, 0xa606, 0x0578,
-	0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008, 0x1500, 0x2500,
-	0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c, 0xa990, 0x01b8,
-	0x080c, 0xa9a0, 0x11a0, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016,
-	0x080c, 0x190b, 0x001e, 0x080c, 0x9778, 0x1110, 0x080c, 0x2aff,
-	0x080c, 0x9789, 0x1110, 0x080c, 0x85f3, 0x080c, 0x974e, 0xace0,
-	0x0018, 0x2001, 0xad16, 0x2004, 0xac02, 0x1208, 0x0858, 0x012e,
-	0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00ee,
-	0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xad40,
-	0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030,
-	0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a, 0x0451, 0x00ee,
-	0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
-	0x2071, 0xad40, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4,
-	0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0xad4a,
-	0x0081, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6,
-	0x2091, 0x8000, 0x2071, 0xad42, 0x0021, 0x00ee, 0x000e, 0x012e,
-	0x0005, 0x2e04, 0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000,
-	0x2072, 0x0005, 0x00e6, 0x2071, 0xad40, 0x0c99, 0x00ee, 0x0005,
-	0x00e6, 0x2071, 0xad44, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002,
-	0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,
-	0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x8529
-};
-
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index fa901fd..d5fdcb9 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -378,7 +378,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= MV_USE_Q_DEPTH,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= MV_MAX_SG_CT / 2,
@@ -748,7 +747,7 @@
 	mv_dump_mem(mmio_base+0xf00, 0x4);
 	mv_dump_mem(mmio_base+0x1d00, 0x6c);
 	for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
-		hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+		hc_base = mv_hc_base(mmio_base, hc);
 		DPRINTK("HC regs (HC %i):\n", hc);
 		mv_dump_mem(hc_base, 0x1c);
 	}
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index f77bf18..9f55308 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -201,7 +201,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index cc928c6..7eb67a6 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -111,7 +111,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 9ffe1ef..886f344 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -132,7 +132,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= QS_MAX_PRD,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 18c296c..1066272 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -146,7 +146,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 068c98a..f7264fd 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -281,7 +281,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index acc8439..728530d 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -87,7 +87,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= ATA_MAX_PRD,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 724f0ed..53b0d5c 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -290,7 +290,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ae70f60..4139ad4 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -182,7 +182,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 7ac5a5f..38b52bd 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -81,7 +81,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 791bf65..9e7ae4e 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -94,7 +94,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 836bbbb..8a29ce3 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -263,7 +263,6 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 6913b06..73994e2 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -565,7 +565,8 @@
 	/* 
 	 * If SCSI-2 or lower, store the LUN value in cmnd.
 	 */
-	if (cmd->device->scsi_level <= SCSI_2) {
+	if (cmd->device->scsi_level <= SCSI_2 &&
+	    cmd->device->scsi_level != SCSI_UNKNOWN) {
 		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
 			       (cmd->device->lun << 5 & 0xe0);
 	}
@@ -1243,7 +1244,7 @@
 	if (error)
 		goto cleanup_sysctl;
 
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
 
 	printk(KERN_NOTICE "SCSI subsystem initialized\n");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 84c3937..c750d33 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -132,7 +132,9 @@
 	{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN},	/* CMD RAID Controller */
 	{"CNSI", "G7324", NULL, BLIST_SPARSELUN},	/* Chaparral G7324 RAID */
 	{"CNSi", "G8324", NULL, BLIST_SPARSELUN},	/* Chaparral G8324 RAID */
-	{"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN},
+	{"COMPAQ", "ARRAY CONTROLLER", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
+		BLIST_MAX_512 | BLIST_REPORTLUN2},	/* Compaq RA4x00 */
+	{"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN | BLIST_MAX_512}, /* Compaq RA4x00 */
 	{"COMPAQ", "CR3500", NULL, BLIST_FORCELUN},
 	{"COMPAQ", "MSA1000", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ", "MSA1000 VOLUME", NULL, BLIST_SPARSELUN | BLIST_NOSTARTONADD},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5f0fdfb..1c75646 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1537,8 +1537,8 @@
 		 * what we need to do to get it up and online again (if we can).
 		 * If we fail, we end up taking the thing offline.
 		 */
-		if (shost->hostt->eh_strategy_handler) 
-			shost->hostt->eh_strategy_handler(shost);
+		if (shost->transportt->eh_strategy_handler)
+			shost->transportt->eh_strategy_handler(shost);
 		else
 			scsi_unjam_host(shost);
 
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 36e9300..a89aff6 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -158,180 +158,6 @@
 EXPORT_SYMBOL(scsi_set_medium_removal);
 
 /*
- * This interface is deprecated - users should use the scsi generic (sg)
- * interface instead, as this is a more flexible approach to performing
- * generic SCSI commands on a device.
- *
- * The structure that we are passed should look like:
- *
- * struct sdata {
- *  unsigned int inlen;      [i] Length of data to be written to device 
- *  unsigned int outlen;     [i] Length of data to be read from device 
- *  unsigned char cmd[x];    [i] SCSI command (6 <= x <= 12).
- *                           [o] Data read from device starts here.
- *                           [o] On error, sense buffer starts here.
- *  unsigned char wdata[y];  [i] Data written to device starts here.
- * };
- * Notes:
- *   -  The SCSI command length is determined by examining the 1st byte
- *      of the given command. There is no way to override this.
- *   -  Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha).
- *   -  The length (x + y) must be at least OMAX_SB_LEN bytes long to
- *      accommodate the sense buffer when an error occurs.
- *      The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that
- *      old code will not be surprised.
- *   -  If a Unix error occurs (e.g. ENOMEM) then the user will receive
- *      a negative return and the Unix error code in 'errno'. 
- *      If the SCSI command succeeds then 0 is returned.
- *      Positive numbers returned are the compacted SCSI error codes (4 
- *      bytes in one int) where the lowest byte is the SCSI status.
- *      See the drivers/scsi/scsi.h file for more information on this.
- *
- */
-#define OMAX_SB_LEN 16		/* Old sense buffer length */
-
-int scsi_ioctl_send_command(struct scsi_device *sdev,
-			    struct scsi_ioctl_command __user *sic)
-{
-	char *buf;
-	unsigned char cmd[MAX_COMMAND_SIZE];
-	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
-	char __user *cmd_in;
-	unsigned char opcode;
-	unsigned int inlen, outlen, cmdlen;
-	unsigned int needed, buf_needed;
-	int timeout, retries, result;
-	int data_direction;
-	gfp_t gfp_mask = GFP_KERNEL;
-
-	if (!sic)
-		return -EINVAL;
-
-	if (sdev->host->unchecked_isa_dma)
-		gfp_mask |= GFP_DMA;
-
-	/*
-	 * Verify that we can read at least this much.
-	 */
-	if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
-		return -EFAULT;
-
-	if(__get_user(inlen, &sic->inlen))
-		return -EFAULT;
-		
-	if(__get_user(outlen, &sic->outlen))
-		return -EFAULT;
-
-	/*
-	 * We do not transfer more than MAX_BUF with this interface.
-	 * If the user needs to transfer more data than this, they
-	 * should use scsi_generics (sg) instead.
-	 */
-	if (inlen > MAX_BUF)
-		return -EINVAL;
-	if (outlen > MAX_BUF)
-		return -EINVAL;
-
-	cmd_in = sic->data;
-	if(get_user(opcode, cmd_in))
-		return -EFAULT;
-
-	needed = buf_needed = (inlen > outlen ? inlen : outlen);
-	if (buf_needed) {
-		buf_needed = (buf_needed + 511) & ~511;
-		if (buf_needed > MAX_BUF)
-			buf_needed = MAX_BUF;
-		buf = kzalloc(buf_needed, gfp_mask);
-		if (!buf)
-			return -ENOMEM;
-		if (inlen == 0) {
-			data_direction = DMA_FROM_DEVICE;
-		} else if (outlen == 0 ) {
-			data_direction = DMA_TO_DEVICE;
-		} else {
-			/*
-			 * Can this ever happen?
-			 */
-			data_direction = DMA_BIDIRECTIONAL;
-		}
-
-	} else {
-		buf = NULL;
-		data_direction = DMA_NONE;
-	}
-
-	/*
-	 * Obtain the command from the user's address space.
-	 */
-	cmdlen = COMMAND_SIZE(opcode);
-	
-	result = -EFAULT;
-
-	if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
-		goto error;
-
-	if(__copy_from_user(cmd, cmd_in, cmdlen))
-		goto error;
-
-	/*
-	 * Obtain the data to be sent to the device (if any).
-	 */
-
-	if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen))
-		goto error;
-
-	switch (opcode) {
-	case SEND_DIAGNOSTIC:
-	case FORMAT_UNIT:
-		timeout = FORMAT_UNIT_TIMEOUT;
-		retries = 1;
-		break;
-	case START_STOP:
-		timeout = START_STOP_TIMEOUT;
-		retries = NORMAL_RETRIES;
-		break;
-	case MOVE_MEDIUM:
-		timeout = MOVE_MEDIUM_TIMEOUT;
-		retries = NORMAL_RETRIES;
-		break;
-	case READ_ELEMENT_STATUS:
-		timeout = READ_ELEMENT_STATUS_TIMEOUT;
-		retries = NORMAL_RETRIES;
-		break;
-	case READ_DEFECT_DATA:
-		timeout = READ_DEFECT_DATA_TIMEOUT;
-		retries = 1;
-		break;
-	default:
-		timeout = IOCTL_NORMAL_TIMEOUT;
-		retries = NORMAL_RETRIES;
-		break;
-	}
-
-	result = scsi_execute(sdev, cmd, data_direction, buf, needed,
-			      sense, timeout, retries, 0);
-
-	/* 
-	 * If there was an error condition, pass the info back to the user. 
-	 */
-	if (result) {
-		int sb_len = sizeof(*sense);
-
-		sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len;
-		if (copy_to_user(cmd_in, sense, sb_len))
-			result = -EFAULT;
-	} else {
-		if (outlen && copy_to_user(cmd_in, buf, outlen))
-			result = -EFAULT;
-	}	
-
-error:
-	kfree(buf);
-	return result;
-}
-EXPORT_SYMBOL(scsi_ioctl_send_command);
-
-/*
  * The scsi_ioctl_get_pci() function places into arg the value
  * pci_dev::slot_name (8 characters) for the PCI device (if any).
  * Returns: 0 on success
@@ -409,7 +235,7 @@
 	case SCSI_IOCTL_SEND_COMMAND:
 		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 			return -EACCES;
-		return scsi_ioctl_send_command(sdev, arg);
+		return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg);
 	case SCSI_IOCTL_DOORLOCK:
 		return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
 	case SCSI_IOCTL_DOORUNLOCK:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 8f010a3..7b0f9a3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1479,6 +1479,8 @@
 static void scsi_kill_request(struct request *req, request_queue_t *q)
 {
 	struct scsi_cmnd *cmd = req->special;
+	struct scsi_device *sdev = cmd->device;
+	struct Scsi_Host *shost = sdev->host;
 
 	blkdev_dequeue_request(req);
 
@@ -1491,6 +1493,19 @@
 	scsi_init_cmd_errh(cmd);
 	cmd->result = DID_NO_CONNECT << 16;
 	atomic_inc(&cmd->device->iorequest_cnt);
+
+	/*
+	 * SCSI request completion path will do scsi_device_unbusy(),
+	 * bump busy counts.  To bump the counters, we need to dance
+	 * with the locks as normal issue path does.
+	 */
+	sdev->device_busy++;
+	spin_unlock(sdev->request_queue->queue_lock);
+	spin_lock(shost->host_lock);
+	shost->host_busy++;
+	spin_unlock(shost->host_lock);
+	spin_lock(sdev->request_queue->queue_lock);
+
 	__scsi_done(cmd);
 }
 
diff --git a/drivers/scsi/scsi_sas_internal.h b/drivers/scsi/scsi_sas_internal.h
new file mode 100644
index 0000000..d76e6e3
--- /dev/null
+++ b/drivers/scsi/scsi_sas_internal.h
@@ -0,0 +1,38 @@
+#ifndef _SCSI_SAS_INTERNAL_H
+#define _SCSI_SAS_INTERNAL_H
+
+#define SAS_HOST_ATTRS		0
+#define SAS_PORT_ATTRS		17
+#define SAS_RPORT_ATTRS		7
+#define SAS_END_DEV_ATTRS	3
+#define SAS_EXPANDER_ATTRS	7
+
+struct sas_internal {
+	struct scsi_transport_template t;
+	struct sas_function_template *f;
+	struct sas_domain_function_template *dft;
+
+	struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
+	struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
+	struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
+	struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
+	struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
+
+	struct transport_container phy_attr_cont;
+	struct transport_container rphy_attr_cont;
+	struct transport_container end_dev_attr_cont;
+	struct transport_container expander_attr_cont;
+
+	/*
+	 * The array of null terminated pointers to attributes
+	 * needed by scsi_sysfs.c
+	 */
+	struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
+	struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
+	struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
+	struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
+	struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
+};
+#define to_sas_internal(tmpl)	container_of(tmpl, struct sas_internal, t)
+
+#endif
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index f149459..1a5474b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -673,6 +673,7 @@
 	case TYPE_MEDIUM_CHANGER:
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
+	case TYPE_RAID:
 	case TYPE_RBC:
 		sdev->writeable = 1;
 		break;
@@ -738,6 +739,13 @@
 		sdev->select_no_atn = 1;
 
 	/*
+	 * Maximum 512 sector transfer length
+	 * broken RA4x00 Compaq Disk Array
+	 */
+	if (*bflags & BLIST_MAX_512)
+		blk_queue_max_sectors(sdev->request_queue, 512);
+
+	/*
 	 * Some devices may not want to have a start command automatically
 	 * issued when a device is added.
 	 */
@@ -1123,10 +1131,13 @@
 	 * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
 	 * support more than 8 LUNs.
 	 */
-	if ((bflags & BLIST_NOREPORTLUN) || 
-	     starget->scsi_level < SCSI_2 ||
-	    (starget->scsi_level < SCSI_3 && 
-	     (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+	if (bflags & BLIST_NOREPORTLUN)
+		return 1;
+	if (starget->scsi_level < SCSI_2 &&
+	    starget->scsi_level != SCSI_UNKNOWN)
+		return 1;
+	if (starget->scsi_level < SCSI_3 &&
+	    (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
 		return 1;
 	if (bflags & BLIST_NOLUN)
 		return 0;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 8db6562..95c5478 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -34,6 +34,8 @@
 #include <scsi/scsi_cmnd.h>
 #include "scsi_priv.h"
 
+static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
+
 /*
  * Redefine so that we can have same named attributes in the
  * sdev/starget/host objects.
@@ -213,10 +215,8 @@
 #define FC_MGMTSRVR_PORTID		0x00000a
 
 
-static void fc_shost_remove_rports(void  *data);
 static void fc_timeout_deleted_rport(void *data);
 static void fc_scsi_scan_rport(void *data);
-static void fc_rport_terminate(struct fc_rport  *rport);
 
 /*
  * Attribute counts pre object type...
@@ -288,42 +288,58 @@
 			 struct class_device *cdev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 
 	/* 
 	 * Set default values easily detected by the midlayer as
 	 * failure cases.  The scsi lldd is responsible for initializing
 	 * all transport attributes to valid values per host.
 	 */
-	fc_host_node_name(shost) = -1;
-	fc_host_port_name(shost) = -1;
-	fc_host_permanent_port_name(shost) = -1;
-	fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
-	memset(fc_host_supported_fc4s(shost), 0,
-		sizeof(fc_host_supported_fc4s(shost)));
-	memset(fc_host_symbolic_name(shost), 0,
-		sizeof(fc_host_symbolic_name(shost)));
-	fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
-	fc_host_maxframe_size(shost) = -1;
-	memset(fc_host_serial_number(shost), 0,
-		sizeof(fc_host_serial_number(shost)));
+	fc_host->node_name = -1;
+	fc_host->port_name = -1;
+	fc_host->permanent_port_name = -1;
+	fc_host->supported_classes = FC_COS_UNSPECIFIED;
+	memset(fc_host->supported_fc4s, 0,
+		sizeof(fc_host->supported_fc4s));
+	memset(fc_host->symbolic_name, 0,
+		sizeof(fc_host->symbolic_name));
+	fc_host->supported_speeds = FC_PORTSPEED_UNKNOWN;
+	fc_host->maxframe_size = -1;
+	memset(fc_host->serial_number, 0,
+		sizeof(fc_host->serial_number));
 
-	fc_host_port_id(shost) = -1;
-	fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
-	fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
-	memset(fc_host_active_fc4s(shost), 0,
-		sizeof(fc_host_active_fc4s(shost)));
-	fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
-	fc_host_fabric_name(shost) = -1;
+	fc_host->port_id = -1;
+	fc_host->port_type = FC_PORTTYPE_UNKNOWN;
+	fc_host->port_state = FC_PORTSTATE_UNKNOWN;
+	memset(fc_host->active_fc4s, 0,
+		sizeof(fc_host->active_fc4s));
+	fc_host->speed = FC_PORTSPEED_UNKNOWN;
+	fc_host->fabric_name = -1;
 
-	fc_host_tgtid_bind_type(shost) = FC_TGTID_BIND_BY_WWPN;
+	fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
 
-	INIT_LIST_HEAD(&fc_host_rports(shost));
-	INIT_LIST_HEAD(&fc_host_rport_bindings(shost));
-	fc_host_next_rport_number(shost) = 0;
-	fc_host_next_target_id(shost) = 0;
+	INIT_LIST_HEAD(&fc_host->rports);
+	INIT_LIST_HEAD(&fc_host->rport_bindings);
+	fc_host->next_rport_number = 0;
+	fc_host->next_target_id = 0;
 
-	fc_host_flags(shost) = 0;
-	INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
+	snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
+		shost->host_no);
+	fc_host->work_q = create_singlethread_workqueue(
+					fc_host->work_q_name);
+	if (!fc_host->work_q)
+		return -ENOMEM;
+
+	snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
+		shost->host_no);
+	fc_host->devloss_work_q = create_singlethread_workqueue(
+					fc_host->devloss_work_q_name);
+	if (!fc_host->devloss_work_q) {
+		destroy_workqueue(fc_host->work_q);
+		fc_host->work_q = NULL;
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
@@ -879,9 +895,9 @@
 		while (!list_empty(&fc_host_rport_bindings(shost))) {
 			get_list_head_entry(rport,
 				&fc_host_rport_bindings(shost), peers);
-			spin_unlock_irqrestore(shost->host_lock, flags);
-			fc_rport_terminate(rport);
-			spin_lock_irqsave(shost->host_lock, flags);
+			list_del(&rport->peers);
+			rport->port_state = FC_PORTSTATE_DELETED;
+			fc_queue_work(shost, &rport->rport_delete_work);
 		}
 		spin_unlock_irqrestore(shost->host_lock, flags);
 	}
@@ -1262,6 +1278,90 @@
 }
 EXPORT_SYMBOL(fc_release_transport);
 
+/**
+ * fc_queue_work - Queue work to the fc_host workqueue.
+ * @shost:	Pointer to Scsi_Host bound to fc_host.
+ * @work:	Work to queue for execution.
+ *
+ * Return value:
+ * 	0 on success / != 0 for error
+ **/
+static int
+fc_queue_work(struct Scsi_Host *shost, struct work_struct *work)
+{
+	if (unlikely(!fc_host_work_q(shost))) {
+		printk(KERN_ERR
+			"ERROR: FC host '%s' attempted to queue work, "
+			"when no workqueue created.\n", shost->hostt->name);
+		dump_stack();
+
+		return -EINVAL;
+	}
+
+	return queue_work(fc_host_work_q(shost), work);
+}
+
+/**
+ * fc_flush_work - Flush a fc_host's workqueue.
+ * @shost:	Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_work(struct Scsi_Host *shost)
+{
+	if (!fc_host_work_q(shost)) {
+		printk(KERN_ERR
+			"ERROR: FC host '%s' attempted to flush work, "
+			"when no workqueue created.\n", shost->hostt->name);
+		dump_stack();
+		return;
+	}
+
+	flush_workqueue(fc_host_work_q(shost));
+}
+
+/**
+ * fc_queue_devloss_work - Schedule work for the fc_host devloss workqueue.
+ * @shost:	Pointer to Scsi_Host bound to fc_host.
+ * @work:	Work to queue for execution.
+ * @delay:	jiffies to delay the work queuing
+ *
+ * Return value:
+ * 	0 on success / != 0 for error
+ **/
+static int
+fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work,
+				unsigned long delay)
+{
+	if (unlikely(!fc_host_devloss_work_q(shost))) {
+		printk(KERN_ERR
+			"ERROR: FC host '%s' attempted to queue work, "
+			"when no workqueue created.\n", shost->hostt->name);
+		dump_stack();
+
+		return -EINVAL;
+	}
+
+	return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay);
+}
+
+/**
+ * fc_flush_devloss - Flush a fc_host's devloss workqueue.
+ * @shost:	Pointer to Scsi_Host bound to fc_host.
+ **/
+static void
+fc_flush_devloss(struct Scsi_Host *shost)
+{
+	if (!fc_host_devloss_work_q(shost)) {
+		printk(KERN_ERR
+			"ERROR: FC host '%s' attempted to flush work, "
+			"when no workqueue created.\n", shost->hostt->name);
+		dump_stack();
+		return;
+	}
+
+	flush_workqueue(fc_host_devloss_work_q(shost));
+}
+
 
 /**
  * fc_remove_host - called to terminate any fc_transport-related elements
@@ -1283,36 +1383,103 @@
 fc_remove_host(struct Scsi_Host *shost)
 {
 	struct fc_rport *rport, *next_rport;
+	struct workqueue_struct *work_q;
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 
 	/* Remove any remote ports */
 	list_for_each_entry_safe(rport, next_rport,
-			&fc_host_rports(shost), peers)
-		fc_rport_terminate(rport);
+			&fc_host->rports, peers) {
+		list_del(&rport->peers);
+		rport->port_state = FC_PORTSTATE_DELETED;
+		fc_queue_work(shost, &rport->rport_delete_work);
+	}
+
 	list_for_each_entry_safe(rport, next_rport,
-			&fc_host_rport_bindings(shost), peers)
-		fc_rport_terminate(rport);
+			&fc_host->rport_bindings, peers) {
+		list_del(&rport->peers);
+		rport->port_state = FC_PORTSTATE_DELETED;
+		fc_queue_work(shost, &rport->rport_delete_work);
+	}
+
+	/* flush all scan work items */
+	scsi_flush_work(shost);
+
+	/* flush all stgt delete, and rport delete work items, then kill it  */
+	if (fc_host->work_q) {
+		work_q = fc_host->work_q;
+		fc_host->work_q = NULL;
+		destroy_workqueue(work_q);
+	}
+
+	/* flush all devloss work items, then kill it  */
+	if (fc_host->devloss_work_q) {
+		work_q = fc_host->devloss_work_q;
+		fc_host->devloss_work_q = NULL;
+		destroy_workqueue(work_q);
+	}
 }
 EXPORT_SYMBOL(fc_remove_host);
 
-/*
- * fc_rport_tgt_remove - Removes the scsi target on the remote port
- * @rport:	The remote port to be operated on
- */
+
+/**
+ * fc_starget_delete - called to delete the scsi decendents of an rport
+ *                  (target and all sdevs)
+ *
+ * @data:	remote port to be operated on.
+ **/
 static void
-fc_rport_tgt_remove(struct fc_rport *rport)
+fc_starget_delete(void *data)
 {
+	struct fc_rport *rport = (struct fc_rport *)data;
 	struct Scsi_Host *shost = rport_to_shost(rport);
+	unsigned long flags;
 
 	scsi_target_unblock(&rport->dev);
 
-	/* Stop anything on the workq */
-	if (!cancel_delayed_work(&rport->dev_loss_work))
-		flush_scheduled_work();
-	scsi_flush_work(shost);
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		if (!cancel_delayed_work(&rport->dev_loss_work))
+			fc_flush_devloss(shost);
+		spin_lock_irqsave(shost->host_lock, flags);
+		rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	scsi_remove_target(&rport->dev);
 }
 
+
+/**
+ * fc_rport_final_delete - finish rport termination and delete it.
+ *
+ * @data:	remote port to be deleted.
+ **/
+static void
+fc_rport_final_delete(void *data)
+{
+	struct fc_rport *rport = (struct fc_rport *)data;
+	struct device *dev = &rport->dev;
+	struct Scsi_Host *shost = rport_to_shost(rport);
+
+	/* Delete SCSI target and sdevs */
+	if (rport->scsi_target_id != -1)
+		fc_starget_delete(data);
+
+	/*
+	 * if a scan is pending, flush the SCSI Host work_q so that 
+	 * that we can reclaim the rport scan work element.
+	 */
+	if (rport->flags & FC_RPORT_SCAN_PENDING)
+		scsi_flush_work(shost);
+
+	transport_remove_device(dev);
+	device_del(dev);
+	transport_destroy_device(dev);
+	put_device(&shost->shost_gendev);
+}
+
+
 /**
  * fc_rport_create - allocates and creates a remote FC port.
  * @shost:	scsi host the remote port is connected to.
@@ -1330,8 +1497,7 @@
 fc_rport_create(struct Scsi_Host *shost, int channel,
 	struct fc_rport_identifiers  *ids)
 {
-	struct fc_host_attrs *fc_host =
-			(struct fc_host_attrs *)shost->shost_data;
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	struct fc_internal *fci = to_fc_internal(shost->transportt);
 	struct fc_rport *rport;
 	struct device *dev;
@@ -1360,6 +1526,8 @@
 
 	INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
 	INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
+	INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport);
+	INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport);
 
 	spin_lock_irqsave(shost->host_lock, flags);
 
@@ -1368,7 +1536,7 @@
 		rport->scsi_target_id = fc_host->next_target_id++;
 	else
 		rport->scsi_target_id = -1;
-	list_add_tail(&rport->peers, &fc_host_rports(shost));
+	list_add_tail(&rport->peers, &fc_host->rports);
 	get_device(&shost->shost_gendev);
 
 	spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1389,9 +1557,11 @@
 	transport_add_device(dev);
 	transport_configure_device(dev);
 
-	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+	if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
 		/* initiate a scan of the target */
+		rport->flags |= FC_RPORT_SCAN_PENDING;
 		scsi_queue_work(shost, &rport->scan_work);
+	}
 
 	return rport;
 
@@ -1451,10 +1621,14 @@
 	struct fc_rport_identifiers  *ids)
 {
 	struct fc_internal *fci = to_fc_internal(shost->transportt);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	struct fc_rport *rport;
 	unsigned long flags;
 	int match = 0;
 
+	/* ensure any stgt delete functions are done */
+	fc_flush_work(shost);
+
 	/*
 	 * Search the list of "active" rports, for an rport that has been
 	 * deleted, but we've held off the real delete while the target
@@ -1462,12 +1636,12 @@
 	 */
 	spin_lock_irqsave(shost->host_lock, flags);
 
-	list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+	list_for_each_entry(rport, &fc_host->rports, peers) {
 
 		if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
 			(rport->channel == channel)) {
 
-			switch (fc_host_tgtid_bind_type(shost)) {
+			switch (fc_host->tgtid_bind_type) {
 			case FC_TGTID_BIND_BY_WWPN:
 			case FC_TGTID_BIND_NONE:
 				if (rport->port_name == ids->port_name)
@@ -1521,27 +1695,34 @@
 				 * transaction.
 				 */
 				if (!cancel_delayed_work(work))
-					flush_scheduled_work();
+					fc_flush_devloss(shost);
+
+				spin_lock_irqsave(shost->host_lock, flags);
+
+				rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
 
 				/* initiate a scan of the target */
+				rport->flags |= FC_RPORT_SCAN_PENDING;
 				scsi_queue_work(shost, &rport->scan_work);
 
+				spin_unlock_irqrestore(shost->host_lock, flags);
+
 				return rport;
 			}
 		}
 	}
 
 	/* Search the bindings array */
-	if (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE) {
+	if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
 
 		/* search for a matching consistent binding */
 
-		list_for_each_entry(rport, &fc_host_rport_bindings(shost),
+		list_for_each_entry(rport, &fc_host->rport_bindings,
 					peers) {
 			if (rport->channel != channel)
 				continue;
 
-			switch (fc_host_tgtid_bind_type(shost)) {
+			switch (fc_host->tgtid_bind_type) {
 			case FC_TGTID_BIND_BY_WWPN:
 				if (rport->port_name == ids->port_name)
 					match = 1;
@@ -1559,8 +1740,7 @@
 			}
 
 			if (match) {
-				list_move_tail(&rport->peers,
-					&fc_host_rports(shost));
+				list_move_tail(&rport->peers, &fc_host->rports);
 				break;
 			}
 		}
@@ -1574,15 +1754,17 @@
 			rport->roles = ids->roles;
 			rport->port_state = FC_PORTSTATE_ONLINE;
 
-			spin_unlock_irqrestore(shost->host_lock, flags);
-
 			if (fci->f->dd_fcrport_size)
 				memset(rport->dd_data, 0,
 						fci->f->dd_fcrport_size);
 
-			if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+			if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) {
 				/* initiate a scan of the target */
+				rport->flags |= FC_RPORT_SCAN_PENDING;
 				scsi_queue_work(shost, &rport->scan_work);
+			}
+
+			spin_unlock_irqrestore(shost->host_lock, flags);
 
 			return rport;
 		}
@@ -1597,30 +1779,6 @@
 }
 EXPORT_SYMBOL(fc_remote_port_add);
 
-/*
- * fc_rport_terminate - this routine tears down and deallocates a remote port.
- * @rport:	The remote port to be terminated
- *
- * Notes:
- *	This routine assumes no locks are held on entry.
- */
-static void
-fc_rport_terminate(struct fc_rport  *rport)
-{
-	struct Scsi_Host *shost = rport_to_shost(rport);
-	struct device *dev = &rport->dev;
-	unsigned long flags;
-
-	fc_rport_tgt_remove(rport);
-
-	transport_remove_device(dev);
-	device_del(dev);
-	transport_destroy_device(dev);
-	spin_lock_irqsave(shost->host_lock, flags);
-	list_del(&rport->peers);
-	spin_unlock_irqrestore(shost->host_lock, flags);
-	put_device(&shost->shost_gendev);
-}
 
 /**
  * fc_remote_port_delete - notifies the fc transport that a remote
@@ -1675,20 +1833,39 @@
 void
 fc_remote_port_delete(struct fc_rport  *rport)
 {
+	struct Scsi_Host *shost = rport_to_shost(rport);
 	int timeout = rport->dev_loss_tmo;
+	unsigned long flags;
+
+	/*
+	 * No need to flush the fc_host work_q's, as all adds are synchronous.
+	 *
+	 * We do need to reclaim the rport scan work element, so eventually
+	 * (in fc_rport_final_delete()) we'll flush the scsi host work_q if
+	 * there's still a scan pending.
+	 */
+
+	spin_lock_irqsave(shost->host_lock, flags);
 
 	/* If no scsi target id mapping, delete it */
 	if (rport->scsi_target_id == -1) {
-		fc_rport_terminate(rport);
+		list_del(&rport->peers);
+		rport->port_state = FC_PORTSTATE_DELETED;
+		fc_queue_work(shost, &rport->rport_delete_work);
+		spin_unlock_irqrestore(shost->host_lock, flags);
 		return;
 	}
 
+	rport->port_state = FC_PORTSTATE_BLOCKED;
+
+	rport->flags |= FC_RPORT_DEVLOSS_PENDING;
+
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
 	scsi_target_block(&rport->dev);
 
 	/* cap the length the devices can be blocked until they are deleted */
-	schedule_delayed_work(&rport->dev_loss_work, timeout * HZ);
-
-	rport->port_state = FC_PORTSTATE_BLOCKED;
+	fc_queue_devloss_work(shost, &rport->dev_loss_work, timeout * HZ);
 }
 EXPORT_SYMBOL(fc_remote_port_delete);
 
@@ -1716,8 +1893,7 @@
 fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles)
 {
 	struct Scsi_Host *shost = rport_to_shost(rport);
-	struct fc_host_attrs *fc_host =
-			(struct fc_host_attrs *)shost->shost_data;
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	unsigned long flags;
 	int create = 0;
 
@@ -1729,10 +1905,11 @@
 		} else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
 			create = 1;
 	}
-	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	rport->roles = roles;
 
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
 	if (create) {
 		/*
 		 * There may have been a delete timer running on the
@@ -1747,10 +1924,20 @@
 		 * transaction.
 		 */
 		if (!cancel_delayed_work(&rport->dev_loss_work))
-			flush_scheduled_work();
+			fc_flush_devloss(shost);
+
+		spin_lock_irqsave(shost->host_lock, flags);
+		rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+		spin_unlock_irqrestore(shost->host_lock, flags);
+
+		/* ensure any stgt delete functions are done */
+		fc_flush_work(shost);
 
 		/* initiate a scan of the target */
+		spin_lock_irqsave(shost->host_lock, flags);
+		rport->flags |= FC_RPORT_SCAN_PENDING;
 		scsi_queue_work(shost, &rport->scan_work);
+		spin_unlock_irqrestore(shost->host_lock, flags);
 	}
 }
 EXPORT_SYMBOL(fc_remote_port_rolechg);
@@ -1767,22 +1954,24 @@
 {
 	struct fc_rport *rport = (struct fc_rport *)data;
 	struct Scsi_Host *shost = rport_to_shost(rport);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	unsigned long flags;
 
 	spin_lock_irqsave(shost->host_lock, flags);
 
+	rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
+
 	/*
-	 * If the port is ONLINE, then it came back, but was no longer an
-	 * FCP target. Thus we need to tear down the scsi_target on it.
+	 * If the port is ONLINE, then it came back. Validate it's still an
+	 * FCP target. If not, tear down the scsi_target on it.
 	 */
-	if (rport->port_state == FC_PORTSTATE_ONLINE) {
-		spin_unlock_irqrestore(shost->host_lock, flags);
-
+	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+	    !(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
 		dev_printk(KERN_ERR, &rport->dev,
-			"blocked FC remote port time out: removing target\n");
-
-		fc_rport_tgt_remove(rport);
-
+			"blocked FC remote port time out: no longer"
+			" a FCP target, removing starget\n");
+		fc_queue_work(shost, &rport->stgt_delete_work);
+		spin_unlock_irqrestore(shost->host_lock, flags);
 		return;
 	}
 
@@ -1793,11 +1982,13 @@
 		return;
 	}
 
-	if (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE) {
-		spin_unlock_irqrestore(shost->host_lock, flags);
+	if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) {
+		list_del(&rport->peers);
+		rport->port_state = FC_PORTSTATE_DELETED;
 		dev_printk(KERN_ERR, &rport->dev,
 			"blocked FC remote port time out: removing target\n");
-		fc_rport_terminate(rport);
+		fc_queue_work(shost, &rport->rport_delete_work);
+		spin_unlock_irqrestore(shost->host_lock, flags);
 		return;
 	}
 
@@ -1805,7 +1996,7 @@
 		"blocked FC remote port time out: removing target and "
 		"saving binding\n");
 
-	list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
+	list_move_tail(&rport->peers, &fc_host->rport_bindings);
 
 	/*
 	 * Note: We do not remove or clear the hostdata area. This allows
@@ -1819,10 +2010,10 @@
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
 	rport->roles = FC_RPORT_ROLE_UNKNOWN;
-	rport->port_state = FC_PORTSTATE_DELETED;
+	rport->port_state = FC_PORTSTATE_NOTPRESENT;
 
 	/* remove the identifiers that aren't used in the consisting binding */
-	switch (fc_host_tgtid_bind_type(shost)) {
+	switch (fc_host->tgtid_bind_type) {
 	case FC_TGTID_BIND_BY_WWPN:
 		rport->node_name = -1;
 		rport->port_id = -1;
@@ -1843,17 +2034,8 @@
 	 * As this only occurs if the remote port (scsi target)
 	 * went away and didn't come back - we'll remove
 	 * all attached scsi devices.
-	 *
-	 * We'll schedule the shost work item to perform the actual removal
-	 * to avoid recursion in the different flush calls if we perform
-	 * the removal in each target - and there are lots of targets
-	 * whose timeouts fire at the same time.
 	 */
-
-	if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
-		fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
-		scsi_queue_work(shost, &fc_host_rport_del_work(shost));
-	}
+	fc_queue_work(shost, &rport->stgt_delete_work);
 
 	spin_unlock_irqrestore(shost->host_lock, flags);
 }
@@ -1870,44 +2052,18 @@
 fc_scsi_scan_rport(void *data)
 {
 	struct fc_rport *rport = (struct fc_rport *)data;
-
-	scsi_target_unblock(&rport->dev);
-	scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id,
-			SCAN_WILD_CARD, 1);
-}
-
-
-/**
- * fc_shost_remove_rports - called to remove all rports that are marked
- *                       as in a deleted (not connected) state.
- * 
- * @data:	shost whose rports are to be looked at
- **/
-static void
-fc_shost_remove_rports(void  *data)
-{
-	struct Scsi_Host *shost = (struct Scsi_Host *)data;
-	struct fc_rport *rport, *next_rport;
+	struct Scsi_Host *shost = rport_to_shost(rport);
 	unsigned long flags;
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
-
-		fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
-
-restart_search:
-		list_for_each_entry_safe(rport, next_rport,
-				&fc_host_rport_bindings(shost), peers) {
-			if (rport->port_state == FC_PORTSTATE_DELETED) {
-				rport->port_state = FC_PORTSTATE_NOTPRESENT;
-				spin_unlock_irqrestore(shost->host_lock, flags);
-				fc_rport_tgt_remove(rport);
-				spin_lock_irqsave(shost->host_lock, flags);
-				goto restart_search;
-			}
-		}
-
+	if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+	    (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+		scsi_target_unblock(&rport->dev);
+		scsi_scan_target(&rport->dev, rport->channel,
+			rport->scsi_target_id, SCAN_WILD_CARD, 1);
 	}
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	rport->flags &= ~FC_RPORT_SCAN_PENDING;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 134c44c..8b6d65e 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -35,40 +35,7 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_sas.h>
 
-
-#define SAS_HOST_ATTRS		0
-#define SAS_PORT_ATTRS		17
-#define SAS_RPORT_ATTRS		7
-#define SAS_END_DEV_ATTRS	3
-#define SAS_EXPANDER_ATTRS	7
-
-struct sas_internal {
-	struct scsi_transport_template t;
-	struct sas_function_template *f;
-
-	struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];
-	struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];
-	struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];
-	struct class_device_attribute private_end_dev_attrs[SAS_END_DEV_ATTRS];
-	struct class_device_attribute private_expander_attrs[SAS_EXPANDER_ATTRS];
-
-	struct transport_container phy_attr_cont;
-	struct transport_container rphy_attr_cont;
-	struct transport_container end_dev_attr_cont;
-	struct transport_container expander_attr_cont;
-
-	/*
-	 * The array of null terminated pointers to attributes
-	 * needed by scsi_sysfs.c
-	 */
-	struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];
-	struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];
-	struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];
-	struct class_device_attribute *end_dev_attrs[SAS_END_DEV_ATTRS + 1];
-	struct class_device_attribute *expander_attrs[SAS_EXPANDER_ATTRS + 1];
-};
-#define to_sas_internal(tmpl)	container_of(tmpl, struct sas_internal, t)
-
+#include "scsi_sas_internal.h"
 struct sas_host_attrs {
 	struct list_head rphy_list;
 	struct mutex lock;
@@ -406,8 +373,6 @@
 	if (!phy)
 		return NULL;
 
-	get_device(parent);
-
 	phy->number = number;
 
 	device_initialize(&phy->dev);
@@ -459,10 +424,7 @@
 void sas_phy_free(struct sas_phy *phy)
 {
 	transport_destroy_device(&phy->dev);
-	put_device(phy->dev.parent);
-	put_device(phy->dev.parent);
-	put_device(phy->dev.parent);
-	kfree(phy);
+	put_device(&phy->dev);
 }
 EXPORT_SYMBOL(sas_phy_free);
 
@@ -484,7 +446,7 @@
 	transport_remove_device(dev);
 	device_del(dev);
 	transport_destroy_device(dev);
-	put_device(dev->parent);
+	put_device(dev);
 }
 EXPORT_SYMBOL(sas_phy_delete);
 
@@ -800,7 +762,6 @@
 
 	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
-		put_device(&parent->dev);
 		return NULL;
 	}
 
@@ -836,7 +797,6 @@
 
 	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
-		put_device(&parent->dev);
 		return NULL;
 	}
 
@@ -885,6 +845,8 @@
 	    (identify->target_port_protocols &
 	     (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
 		rphy->scsi_target_id = sas_host->next_target_id++;
+	else if (identify->device_type == SAS_END_DEVICE)
+		rphy->scsi_target_id = -1;
 	mutex_unlock(&sas_host->lock);
 
 	if (identify->device_type == SAS_END_DEVICE &&
@@ -910,6 +872,7 @@
  */
 void sas_rphy_free(struct sas_rphy *rphy)
 {
+	struct device *dev = &rphy->dev;
 	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
 	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
 
@@ -917,21 +880,9 @@
 	list_del(&rphy->list);
 	mutex_unlock(&sas_host->lock);
 
-	transport_destroy_device(&rphy->dev);
-	put_device(rphy->dev.parent);
-	put_device(rphy->dev.parent);
-	put_device(rphy->dev.parent);
-	if (rphy->identify.device_type == SAS_END_DEVICE) {
-		struct sas_end_device *edev = rphy_to_end_device(rphy);
+	transport_destroy_device(dev);
 
-		kfree(edev);
-	} else {
-		/* must be expander */
-		struct sas_expander_device *edev =
-			rphy_to_expander_device(rphy);
-
-		kfree(edev);
-	}
+	put_device(dev);
 }
 EXPORT_SYMBOL(sas_rphy_free);
 
@@ -971,7 +922,7 @@
 
 	parent->rphy = NULL;
 
-	put_device(&parent->dev);
+	put_device(dev);
 }
 EXPORT_SYMBOL(sas_rphy_delete);
 
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7405d0d..b098942 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -748,6 +748,7 @@
 		/*
 		 * most likely out of mem, but could also be a bad map
 		 */
+		sg_finish_rem_req(srp);
 		return -ENOMEM;
 	} else
 		return 0;
@@ -1044,7 +1045,7 @@
 			if (!sg_allow_access(opcode, sdp->device->type))
 				return -EPERM;
 		}
-		return scsi_ioctl_send_command(sdp->device, p);
+		return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
 	case SG_SET_DEBUG:
 		result = get_user(val, ip);
 		if (result)
@@ -1798,8 +1799,10 @@
 	res = st_map_user_pages(schp->buffer, mx_sc_elems,
 				(unsigned long)hp->dxferp, dxfer_len, 
 				(SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
-	if (res <= 0)
+	if (res <= 0) {
+		sg_remove_scat(schp);
 		return 1;
+	}
 	schp->k_use_sg = res;
 	schp->dio_in_use = 1;
 	hp->info |= SG_INFO_DIRECT_IO;
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 3659dd7..defccc4 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.2.2"
+#define SYM_VERSION "2.2.3"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 1fffd2b..9c83b4d 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -134,66 +134,17 @@
 	}
 }
 
-/*
- * We used to try to deal with 64-bit BARs here, but don't any more.
- * There are many parts of this driver which would need to be modified
- * to handle a 64-bit base address, including scripts.  I'm uncomfortable
- * with making those changes when I have no way of testing it, so I'm
- * just going to disable it.
- *
- * Note that some machines (eg HP rx8620 and Superdome) have bus addresses
- * below 4GB and physical addresses above 4GB.  These will continue to work.
- */
-static int __devinit
-pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
-{
-	u32 tmp;
-	unsigned long base;
-#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
-
-	pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
-	base = tmp;
-	if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-		pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
-		if (tmp > 0) {
-			dev_err(&pdev->dev,
-				"BAR %d is 64-bit, disabling\n", index - 1);
-			base = 0;
-		}
-	}
-
-	if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
-		base &= PCI_BASE_ADDRESS_IO_MASK;
-	} else {
-		base &= PCI_BASE_ADDRESS_MEM_MASK;
-	}
-
-	*basep = base;
-	return index;
-#undef PCI_BAR_OFFSET
-}
-
 static struct scsi_transport_template *sym2_transport_template = NULL;
 
 /*
- *  Used by the eh thread to wait for command completion.
- *  It is allocated on the eh thread stack.
- */
-struct sym_eh_wait {
-	struct completion done;
-	struct timer_list timer;
-	void (*old_done)(struct scsi_cmnd *);
-	int to_do;
-	int timed_out;
-};
-
-/*
  *  Driver private area in the SCSI command structure.
  */
 struct sym_ucmd {		/* Override the SCSI pointer structure */
-	dma_addr_t data_mapping;
-	u_char	data_mapped;
-	struct sym_eh_wait *eh_wait;
+	dma_addr_t	data_mapping;
+	unsigned char	data_mapped;
+	unsigned char	to_do;			/* For error handling */
+	void (*old_done)(struct scsi_cmnd *);	/* For error handling */
+	struct completion *eh_done;		/* For error handling */
 };
 
 #define SYM_UCMD_PTR(cmd)  ((struct sym_ucmd *)(&(cmd)->SCp))
@@ -514,8 +465,6 @@
  */
 int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
 {
-	struct sym_tcb *tp = &np->target[cp->target];
-	struct sym_lcb *lp = sym_lp(tp, cp->lun);
 	u32 lastp, goalp;
 	int dir;
 
@@ -596,7 +545,7 @@
 	/*
 	 *	activate this job.
 	 */
-	sym_start_next_ccbs(np, lp, 2);
+	sym_put_start_queue(np, cp);
 	return 0;
 
 out_abort:
@@ -751,80 +700,54 @@
  *  What we will do regarding the involved SCSI command.
  */
 #define SYM_EH_DO_IGNORE	0
-#define SYM_EH_DO_COMPLETE	1
 #define SYM_EH_DO_WAIT		2
 
 /*
- *  Our general completion handler.
+ *  scsi_done() alias when error recovery is in progress.
  */
-static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out)
+static void sym_eh_done(struct scsi_cmnd *cmd)
 {
-	struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait;
-	if (!ep)
-		return;
+	struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+	BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
 
-	/* Try to avoid a race here (not 100% safe) */
-	if (!timed_out) {
-		ep->timed_out = 0;
-		if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer))
-			return;
-	}
+	cmd->scsi_done = ucmd->old_done;
 
-	/* Revert everything */
-	SYM_UCMD_PTR(cmd)->eh_wait = NULL;
-	cmd->scsi_done = ep->old_done;
-
-	/* Wake up the eh thread if it wants to sleep */
-	if (ep->to_do == SYM_EH_DO_WAIT)
-		complete(&ep->done);
+	if (ucmd->to_do == SYM_EH_DO_WAIT)
+		complete(ucmd->eh_done);
 }
 
 /*
- *  scsi_done() alias when error recovery is in progress. 
- */
-static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); }
-
-/*
- *  Some timeout handler to avoid waiting too long.
- */
-static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); }
-
-/*
  *  Generic method for our eh processing.
  *  The 'op' argument tells what we have to do.
  */
 static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
 {
 	struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
+	struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+	struct Scsi_Host *host = cmd->device->host;
 	SYM_QUEHEAD *qp;
 	int to_do = SYM_EH_DO_IGNORE;
 	int sts = -1;
-	struct sym_eh_wait eh, *ep = &eh;
+	struct completion eh_done;
 
 	dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
 
+	spin_lock_irq(host->host_lock);
 	/* This one is queued in some place -> to wait for completion */
 	FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
 		struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
 		if (cp->cmd == cmd) {
 			to_do = SYM_EH_DO_WAIT;
-			goto prepare;
+			break;
 		}
 	}
 
-prepare:
-	/* Prepare stuff to either ignore, complete or wait for completion */
-	switch(to_do) {
-	default:
-	case SYM_EH_DO_IGNORE:
-		break;
-	case SYM_EH_DO_WAIT:
-		init_completion(&ep->done);
-		/* fall through */
-	case SYM_EH_DO_COMPLETE:
-		ep->old_done = cmd->scsi_done;
+	if (to_do == SYM_EH_DO_WAIT) {
+		init_completion(&eh_done);
+		ucmd->old_done = cmd->scsi_done;
+		ucmd->eh_done = &eh_done;
+		wmb();
 		cmd->scsi_done = sym_eh_done;
-		SYM_UCMD_PTR(cmd)->eh_wait = ep;
 	}
 
 	/* Try to proceed the operation we have been asked for */
@@ -851,29 +774,19 @@
 
 	/* On error, restore everything and cross fingers :) */
 	if (sts) {
-		SYM_UCMD_PTR(cmd)->eh_wait = NULL;
-		cmd->scsi_done = ep->old_done;
+		cmd->scsi_done = ucmd->old_done;
 		to_do = SYM_EH_DO_IGNORE;
 	}
 
-	ep->to_do = to_do;
-	/* Complete the command with locks held as required by the driver */
-	if (to_do == SYM_EH_DO_COMPLETE)
-		sym_xpt_done2(np, cmd, DID_ABORT);
+	ucmd->to_do = to_do;
+	spin_unlock_irq(host->host_lock);
 
-	/* Wait for completion with locks released, as required by kernel */
 	if (to_do == SYM_EH_DO_WAIT) {
-		init_timer(&ep->timer);
-		ep->timer.expires = jiffies + (5*HZ);
-		ep->timer.function = sym_eh_timeout;
-		ep->timer.data = (u_long)cmd;
-		ep->timed_out = 1;	/* Be pessimistic for once :) */
-		add_timer(&ep->timer);
-		spin_unlock_irq(np->s.host->host_lock);
-		wait_for_completion(&ep->done);
-		spin_lock_irq(np->s.host->host_lock);
-		if (ep->timed_out)
+		if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
+			ucmd->to_do = SYM_EH_DO_IGNORE;
+			wmb();
 			sts = -2;
+		}
 	}
 	dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
 			sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
@@ -886,46 +799,22 @@
  */
 static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
 {
-	int rc;
-
-	spin_lock_irq(cmd->device->host->host_lock);
-	rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
-
-	return rc;
+	return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
 }
 
 static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
 {
-	int rc;
-
-	spin_lock_irq(cmd->device->host->host_lock);
-	rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
-
-	return rc;
+	return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
 }
 
 static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
 {
-	int rc;
-
-	spin_lock_irq(cmd->device->host->host_lock);
-	rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
-
-	return rc;
+	return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
 }
 
 static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
 {
-	int rc;
-
-	spin_lock_irq(cmd->device->host->host_lock);
-	rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
-	spin_unlock_irq(cmd->device->host->host_lock);
-
-	return rc;
+	return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
 }
 
 /*
@@ -944,15 +833,12 @@
 	if (reqtags > lp->s.scdev_depth)
 		reqtags = lp->s.scdev_depth;
 
-	lp->started_limit = reqtags ? reqtags : 2;
-	lp->started_max   = 1;
 	lp->s.reqtags     = reqtags;
 
 	if (reqtags != oldtags) {
 		dev_info(&tp->starget->dev,
 		         "tagged command queuing %s, command queue depth %d.\n",
-		          lp->s.reqtags ? "enabled" : "disabled",
- 		          lp->started_limit);
+		          lp->s.reqtags ? "enabled" : "disabled", reqtags);
 	}
 }
 
@@ -1866,15 +1752,25 @@
 static void __devinit
 sym_init_device(struct pci_dev *pdev, struct sym_device *device)
 {
-	int i;
+	int i = 2;
+	struct pci_bus_region bus_addr;
 
 	device->host_id = SYM_SETUP_HOST_ID;
 	device->pdev = pdev;
 
-	i = pci_get_base_address(pdev, 1, &device->mmio_base);
-	pci_get_base_address(pdev, i, &device->ram_base);
+	pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
+	device->mmio_base = bus_addr.start;
 
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
+	/*
+	 * If the BAR is 64-bit, resource 2 will be occupied by the
+	 * upper 32 bits
+	 */
+	if (!pdev->resource[i].flags)
+		i++;
+	pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+	device->ram_base = bus_addr.start;
+
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
 	if (device->mmio_base)
 		device->s.ioaddr = pci_iomap(pdev, 1,
 						pci_resource_len(pdev, 1));
@@ -1978,7 +1874,8 @@
 	.eh_bus_reset_handler	= sym53c8xx_eh_bus_reset_handler,
 	.eh_host_reset_handler	= sym53c8xx_eh_host_reset_handler,
 	.this_id		= 7,
-	.use_clustering		= DISABLE_CLUSTERING,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.max_sectors		= 0xFFFF,
 #ifdef SYM_LINUX_PROC_INFO_SUPPORT
 	.proc_info		= sym53c8xx_proc_info,
 	.proc_name		= NAME53C8XX,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index cc92d0c..a446cda 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -68,7 +68,7 @@
  */
 #define	SYM_CONF_TIMER_INTERVAL		((HZ+1)/2)
 
-#define SYM_OPT_HANDLE_DEVICE_QUEUEING
+#undef SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 
 /*
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 60850cb..a671bdc 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -72,7 +72,10 @@
 
 static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
 {
-	sym_print_addr(cp->cmd, "%s: ", label);
+	if (label)
+		sym_print_addr(cp->cmd, "%s: ", label);
+	else
+		sym_print_addr(cp->cmd, "");
 
 	spi_print_msg(msg);
 	printf("\n");
@@ -472,7 +475,7 @@
  *  calculations more simple.
  */
 #define _5M 5000000
-static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
+static const u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M};
 
 /*
  *  Get clock factor and sync divisor for a given 
@@ -645,6 +648,37 @@
 }
 
 /*
+ *  Set SCSI BUS mode.
+ *  - LVD capable chips (895/895A/896/1010) report the current BUS mode
+ *    through the STEST4 IO register.
+ *  - For previous generation chips (825/825A/875), the user has to tell us
+ *    how to check against HVD, since a 100% safe algorithm is not possible.
+ */
+static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram)
+{
+	if (np->scsi_mode)
+		return;
+
+	np->scsi_mode = SMODE_SE;
+	if (np->features & (FE_ULTRA2|FE_ULTRA3))
+		np->scsi_mode = (np->sv_stest4 & SMODE);
+	else if	(np->features & FE_DIFF) {
+		if (SYM_SETUP_SCSI_DIFF == 1) {
+			if (np->sv_scntl3) {
+				if (np->sv_stest2 & 0x20)
+					np->scsi_mode = SMODE_HVD;
+			} else if (nvram->type == SYM_SYMBIOS_NVRAM) {
+				if (!(INB(np, nc_gpreg) & 0x08))
+					np->scsi_mode = SMODE_HVD;
+			}
+		} else if (SYM_SETUP_SCSI_DIFF == 2)
+			np->scsi_mode = SMODE_HVD;
+	}
+	if (np->scsi_mode == SMODE_HVD)
+		np->rv_stest2 |= 0x20;
+}
+
+/*
  *  Prepare io register values used by sym_start_up() 
  *  according to selected and supported features.
  */
@@ -654,10 +688,7 @@
 	u32	period;
 	int i;
 
-	/*
-	 *  Wide ?
-	 */
-	np->maxwide	= (np->features & FE_WIDE)? 1 : 0;
+	np->maxwide = (np->features & FE_WIDE) ? 1 : 0;
 
 	/*
 	 *  Guess the frequency of the chip's clock.
@@ -838,6 +869,7 @@
 	 *  Get parity checking, host ID and verbose mode from NVRAM
 	 */
 	np->myaddr = 255;
+	np->scsi_mode = 0;
 	sym_nvram_setup_host(shost, np, nvram);
 
 	/*
@@ -854,33 +886,7 @@
 	 */
 	sym_init_burst(np, burst_max);
 
-	/*
-	 *  Set SCSI BUS mode.
-	 *  - LVD capable chips (895/895A/896/1010) report the 
-	 *    current BUS mode through the STEST4 IO register.
-	 *  - For previous generation chips (825/825A/875), 
-	 *    user has to tell us how to check against HVD, 
-	 *    since a 100% safe algorithm is not possible.
-	 */
-	np->scsi_mode = SMODE_SE;
-	if (np->features & (FE_ULTRA2|FE_ULTRA3))
-		np->scsi_mode = (np->sv_stest4 & SMODE);
-	else if	(np->features & FE_DIFF) {
-		if (SYM_SETUP_SCSI_DIFF == 1) {
-			if (np->sv_scntl3) {
-				if (np->sv_stest2 & 0x20)
-					np->scsi_mode = SMODE_HVD;
-			}
-			else if (nvram->type == SYM_SYMBIOS_NVRAM) {
-				if (!(INB(np, nc_gpreg) & 0x08))
-					np->scsi_mode = SMODE_HVD;
-			}
-		}
-		else if	(SYM_SETUP_SCSI_DIFF == 2)
-			np->scsi_mode = SMODE_HVD;
-	}
-	if (np->scsi_mode == SMODE_HVD)
-		np->rv_stest2 |= 0x20;
+	sym_set_bus_mode(np, nvram);
 
 	/*
 	 *  Set LED support from SCRIPTS.
@@ -973,8 +979,8 @@
  *
  *  Has to be called with interrupts disabled.
  */
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
-static int sym_regtest (struct sym_hcb *np)
+#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
+static int sym_regtest(struct sym_hcb *np)
 {
 	register volatile u32 data;
 	/*
@@ -992,20 +998,25 @@
 #endif
 		printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
 			(unsigned) data);
-		return (0x10);
+		return 0x10;
 	}
-	return (0);
+	return 0;
+}
+#else
+static inline int sym_regtest(struct sym_hcb *np)
+{
+	return 0;
 }
 #endif
 
-static int sym_snooptest (struct sym_hcb *np)
+static int sym_snooptest(struct sym_hcb *np)
 {
-	u32	sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
-	int	i, err=0;
-#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
-	err |= sym_regtest (np);
-	if (err) return (err);
-#endif
+	u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
+	int i, err;
+
+	err = sym_regtest(np);
+	if (err)
+		return err;
 restart_test:
 	/*
 	 *  Enable Master Parity Checking as we intend 
@@ -1094,7 +1105,7 @@
 		err |= 4;
 	}
 
-	return (err);
+	return err;
 }
 
 /*
@@ -1464,7 +1475,7 @@
 /*
  *  Insert a job into the start queue.
  */
-static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
 {
 	u_short	qidx;
 
@@ -4481,7 +4492,7 @@
 			switch (np->msgin [2]) {
 			case M_X_MODIFY_DP:
 				if (DEBUG_FLAGS & DEBUG_POINTER)
-					sym_print_msg(cp,"modify DP",np->msgin);
+					sym_print_msg(cp, NULL, np->msgin);
 				tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + 
 				      (np->msgin[5]<<8)  + (np->msgin[6]);
 				sym_modify_dp(np, tp, cp, tmp);
@@ -4508,7 +4519,7 @@
 		 */
 		case M_IGN_RESIDUE:
 			if (DEBUG_FLAGS & DEBUG_POINTER)
-				sym_print_msg(cp,"ign wide residue", np->msgin);
+				sym_print_msg(cp, NULL, np->msgin);
 			if (cp->host_flags & HF_SENSE)
 				OUTL_DSP(np, SCRIPTA_BA(np, clrack));
 			else
@@ -4597,7 +4608,8 @@
 			 *  Debugging purpose.
 			 */
 #ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
-			assert(lp->busy_itl == 0);
+			if (lp->busy_itl != 0)
+				goto out_free;
 #endif
 			/*
 			 *  Allocate resources for tags if not yet.
@@ -4642,7 +4654,8 @@
 			 *  Debugging purpose.
 			 */
 #ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
-			assert(lp->busy_itl == 0 && lp->busy_itlq == 0);
+			if (lp->busy_itl != 0 || lp->busy_itlq != 0)
+				goto out_free;
 #endif
 			/*
 			 *  Count this nexus for this LUN.
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 2456090..79ab6a1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -1049,6 +1049,8 @@
 struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
+#else
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
 #endif
 void sym_start_up(struct sym_hcb *np, int reason);
 void sym_interrupt(struct sym_hcb *np);
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
index dfc1e86..043f50b 100644
--- a/drivers/serial/jsm/jsm.h
+++ b/drivers/serial/jsm/jsm.h
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  ***********************************************************************/
 
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index b1b66e7..b3e1f71 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  *
  ***********************************************************************/
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index 87e4e2c..a5fc589 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -20,7 +20,7 @@
  *
  * Contact Information:
  * Scott H Kilau <Scott_Kilau@digi.com>
- * Wendy Xiong   <wendyx@us.ltcfwd.linux.ibm.com>
+ * Wendy Xiong   <wendyx@us.ibm.com>
  *
  ***********************************************************************/
 #include <linux/delay.h>	/* For udelay */
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index e9c10c0..321a40f 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -1057,7 +1057,6 @@
 {
 	struct uart_sio_port *up = &m32r_sio_ports[co->index];
 	unsigned int ier;
-	int i;
 
 	/*
 	 *	First save the UER then disable the interrupts
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index c303336..2c70773 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -41,6 +41,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/serial_core.h>
+#include <linux/delay.h>
 #include <linux/major.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -97,11 +98,13 @@
 #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id))
 
 struct serial_info {
-	dev_link_t		link;
+	struct pcmcia_device	*p_dev;
 	int			ndev;
 	int			multi;
 	int			slave;
 	int			manfid;
+	int			prodid;
+	int			c950ctrl;
 	dev_node_t		node[4];
 	int			line[4];
 };
@@ -113,9 +116,36 @@
 };
 
 
-static void serial_config(dev_link_t * link);
+static int serial_config(struct pcmcia_device * link);
 
 
+static void wakeup_card(struct serial_info *info)
+{
+	int ctrl = info->c950ctrl;
+
+	if (info->manfid == MANFID_OXSEMI) {
+		outb(12, ctrl + 1);
+	} else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
+		/* request_region? oxsemi branch does no request_region too... */
+		/* This sequence is needed to properly initialize MC45 attached to OXCF950.
+		 * I tried decreasing these msleep()s, but it worked properly (survived
+		 * 1000 stop/start operations) with these timeouts (or bigger). */
+		outb(0xA, ctrl + 1);
+		msleep(100);
+		outb(0xE, ctrl + 1);
+		msleep(300);
+		outb(0xC, ctrl + 1);
+		msleep(100);
+		outb(0xE, ctrl + 1);
+		msleep(200);
+		outb(0xF, ctrl + 1);
+		msleep(100);
+		outb(0xE, ctrl + 1);
+		msleep(100);
+		outb(0xC, ctrl + 1);
+	}
+}
+
 /*======================================================================
 
     After a card is removed, serial_remove() will unregister
@@ -123,67 +153,45 @@
     
 ======================================================================*/
 
-static void serial_remove(dev_link_t *link)
+static void serial_remove(struct pcmcia_device *link)
 {
 	struct serial_info *info = link->priv;
 	int i;
 
-	link->state &= ~DEV_PRESENT;
-
 	DEBUG(0, "serial_release(0x%p)\n", link);
 
 	/*
 	 * Recheck to see if the device is still configured.
 	 */
-	if (info->link.state & DEV_CONFIG) {
-		for (i = 0; i < info->ndev; i++)
-			serial8250_unregister_port(info->line[i]);
+	for (i = 0; i < info->ndev; i++)
+		serial8250_unregister_port(info->line[i]);
 
-		info->link.dev = NULL;
+	info->p_dev->dev_node = NULL;
 
-		if (!info->slave) {
-			pcmcia_release_configuration(info->link.handle);
-			pcmcia_release_io(info->link.handle, &info->link.io);
-			pcmcia_release_irq(info->link.handle, &info->link.irq);
-		}
-
-		info->link.state &= ~DEV_CONFIG;
-	}
+	if (!info->slave)
+		pcmcia_disable_device(link);
 }
 
-static int serial_suspend(struct pcmcia_device *dev)
+static int serial_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
-	link->state |= DEV_SUSPEND;
+	struct serial_info *info = link->priv;
+	int i;
 
-	if (link->state & DEV_CONFIG) {
-		struct serial_info *info = link->priv;
-		int i;
-
-		for (i = 0; i < info->ndev; i++)
-			serial8250_suspend_port(info->line[i]);
-
-		if (!info->slave)
-			pcmcia_release_configuration(link->handle);
-	}
+	for (i = 0; i < info->ndev; i++)
+		serial8250_suspend_port(info->line[i]);
 
 	return 0;
 }
 
-static int serial_resume(struct pcmcia_device *dev)
+static int serial_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
-	link->state &= ~DEV_SUSPEND;
-
-	if (DEV_OK(link)) {
+	if (pcmcia_dev_present(link)) {
 		struct serial_info *info = link->priv;
 		int i;
 
-		if (!info->slave)
-			pcmcia_request_configuration(link->handle, &link->conf);
-
 		for (i = 0; i < info->ndev; i++)
 			serial8250_resume_port(info->line[i]);
+		wakeup_card(info);
 	}
 
 	return 0;
@@ -197,10 +205,9 @@
 
 ======================================================================*/
 
-static int serial_probe(struct pcmcia_device *p_dev)
+static int serial_probe(struct pcmcia_device *link)
 {
 	struct serial_info *info;
-	dev_link_t *link;
 
 	DEBUG(0, "serial_attach()\n");
 
@@ -209,7 +216,7 @@
 	if (!info)
 		return -ENOMEM;
 	memset(info, 0, sizeof (*info));
-	link = &info->link;
+	info->p_dev = link;
 	link->priv = info;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -223,12 +230,7 @@
 	}
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	serial_config(link);
-
-	return 0;
+	return serial_config(link);
 }
 
 /*======================================================================
@@ -240,9 +242,8 @@
 
 ======================================================================*/
 
-static void serial_detach(struct pcmcia_device *p_dev)
+static void serial_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct serial_info *info = link->priv;
 
 	DEBUG(0, "serial_detach(0x%p)\n", link);
@@ -263,7 +264,7 @@
 
 /*====================================================================*/
 
-static int setup_serial(client_handle_t handle, struct serial_info * info,
+static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
 			kio_addr_t iobase, int irq)
 {
 	struct uart_port port;
@@ -298,7 +299,7 @@
 /*====================================================================*/
 
 static int
-first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
 {
 	int i;
 	i = pcmcia_get_first_tuple(handle, tuple);
@@ -311,7 +312,7 @@
 }
 
 static int
-next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
+next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
 {
 	int i;
 	i = pcmcia_get_next_tuple(handle, tuple);
@@ -325,11 +326,10 @@
 
 /*====================================================================*/
 
-static int simple_config(dev_link_t *link)
+static int simple_config(struct pcmcia_device *link)
 {
 	static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	static const int size_table[2] = { 8, 16 };
-	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
 	struct serial_cfg_mem *cfg_mem;
 	tuple_t *tuple;
@@ -350,7 +350,7 @@
 	buf = cfg_mem->buf;
 
 	/* If the card is already configured, look up the port and irq */
-	i = pcmcia_get_configuration_info(handle, &config);
+	i = pcmcia_get_configuration_info(link, &config);
 	if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
 		kio_addr_t port = 0;
 		if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
@@ -363,10 +363,9 @@
 		}
 		if (info->slave) {
 			kfree(cfg_mem);
-			return setup_serial(handle, info, port, config.AssignedIRQ);
+			return setup_serial(link, info, port, config.AssignedIRQ);
 		}
 	}
-	link->conf.Vcc = config.Vcc;
 
 	/* First pass: look for a config entry that looks normal. */
 	tuple->TupleData = (cisdata_t *) buf;
@@ -377,12 +376,12 @@
 	/* Two tries: without IO aliases, then with aliases */
 	for (s = 0; s < 2; s++) {
 		for (try = 0; try < 2; try++) {
-			i = first_tuple(handle, tuple, parse);
+			i = first_tuple(link, tuple, parse);
 			while (i != CS_NO_MORE_ITEMS) {
 				if (i != CS_SUCCESS)
 					goto next_entry;
 				if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-					link->conf.Vpp1 = link->conf.Vpp2 =
+					link->conf.Vpp =
 					    cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 				if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
 					    (cf->io.win[0].base != 0)) {
@@ -390,19 +389,19 @@
 					link->io.BasePort1 = cf->io.win[0].base;
 					link->io.IOAddrLines = (try == 0) ?
 					    16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-					i = pcmcia_request_io(link->handle, &link->io);
+					i = pcmcia_request_io(link, &link->io);
 					if (i == CS_SUCCESS)
 						goto found_port;
 				}
 next_entry:
-				i = next_tuple(handle, tuple, parse);
+				i = next_tuple(link, tuple, parse);
 			}
 		}
 	}
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
-	i = first_tuple(handle, tuple, parse);
+	i = first_tuple(link, tuple, parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
 		    ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -410,50 +409,48 @@
 			for (j = 0; j < 5; j++) {
 				link->io.BasePort1 = base[j];
 				link->io.IOAddrLines = base[j] ? 16 : 3;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				if (i == CS_SUCCESS)
 					goto found_port;
 			}
 		}
-		i = next_tuple(handle, tuple, parse);
+		i = next_tuple(link, tuple, parse);
 	}
 
       found_port:
 	if (i != CS_SUCCESS) {
 		printk(KERN_NOTICE
 		       "serial_cs: no usable port range found, giving up\n");
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		kfree(cfg_mem);
 		return -1;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 	if (info->multi && (info->manfid == MANFID_3COM))
 		link->conf.ConfigIndex &= ~(0x08);
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		kfree(cfg_mem);
 		return -1;
 	}
 	kfree(cfg_mem);
-	return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+	return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
 }
 
-static int multi_config(dev_link_t * link)
+static int multi_config(struct pcmcia_device * link)
 {
-	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
 	struct serial_cfg_mem *cfg_mem;
 	tuple_t *tuple;
 	u_char *buf;
 	cisparse_t *parse;
 	cistpl_cftable_entry_t *cf;
-	config_info_t config;
 	int i, rc, base2 = 0;
 
 	cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
@@ -464,14 +461,6 @@
 	cf = &parse->cftable_entry;
 	buf = cfg_mem->buf;
 
-	i = pcmcia_get_configuration_info(handle, &config);
-	if (i != CS_SUCCESS) {
-		cs_error(handle, GetConfigurationInfo, i);
-		rc = -1;
-		goto free_cfg_mem;
-	}
-	link->conf.Vcc = config.Vcc;
-
 	tuple->TupleData = (cisdata_t *) buf;
 	tuple->TupleOffset = 0;
 	tuple->TupleDataMax = 255;
@@ -480,7 +469,7 @@
 
 	/* First, look for a generic full-sized window */
 	link->io.NumPorts1 = info->multi * 8;
-	i = first_tuple(handle, tuple, parse);
+	i = first_tuple(link, tuple, parse);
 	while (i != CS_NO_MORE_ITEMS) {
 		/* The quad port cards have bad CIS's, so just look for a
 		   window larger than 8 ports and assume it will be right */
@@ -490,19 +479,19 @@
 			link->io.BasePort1 = cf->io.win[0].base;
 			link->io.IOAddrLines =
 			    cf->io.flags & CISTPL_IO_LINES_MASK;
-			i = pcmcia_request_io(link->handle, &link->io);
+			i = pcmcia_request_io(link, &link->io);
 			base2 = link->io.BasePort1 + 8;
 			if (i == CS_SUCCESS)
 				break;
 		}
-		i = next_tuple(handle, tuple, parse);
+		i = next_tuple(link, tuple, parse);
 	}
 
 	/* If that didn't work, look for two windows */
 	if (i != CS_SUCCESS) {
 		link->io.NumPorts1 = link->io.NumPorts2 = 8;
 		info->multi = 2;
-		i = first_tuple(handle, tuple, parse);
+		i = first_tuple(link, tuple, parse);
 		while (i != CS_NO_MORE_ITEMS) {
 			if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
 				link->conf.ConfigIndex = cf->index;
@@ -510,26 +499,26 @@
 				link->io.BasePort2 = cf->io.win[1].base;
 				link->io.IOAddrLines =
 				    cf->io.flags & CISTPL_IO_LINES_MASK;
-				i = pcmcia_request_io(link->handle, &link->io);
+				i = pcmcia_request_io(link, &link->io);
 				base2 = link->io.BasePort2;
 				if (i == CS_SUCCESS)
 					break;
 			}
-			i = next_tuple(handle, tuple, parse);
+			i = next_tuple(link, tuple, parse);
 		}
 	}
 
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestIO, i);
+		cs_error(link, RequestIO, i);
 		rc = -1;
 		goto free_cfg_mem;
 	}
 
-	i = pcmcia_request_irq(link->handle, &link->irq);
+	i = pcmcia_request_irq(link, &link->irq);
 	if (i != CS_SUCCESS) {
 		printk(KERN_NOTICE
 		       "serial_cs: no usable port range found, giving up\n");
-		cs_error(link->handle, RequestIRQ, i);
+		cs_error(link, RequestIRQ, i);
 		link->irq.AssignedIRQ = 0;
 	}
 	/* Socket Dual IO: this enables irq's for second port */
@@ -537,35 +526,43 @@
 		link->conf.Present |= PRESENT_EXT_STATUS;
 		link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
 	}
-	i = pcmcia_request_configuration(link->handle, &link->conf);
+	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != CS_SUCCESS) {
-		cs_error(link->handle, RequestConfiguration, i);
+		cs_error(link, RequestConfiguration, i);
 		rc = -1;
 		goto free_cfg_mem;
 	}
 
 	/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
-	   8 registers are for the UART, the others are extra registers */
-	if (info->manfid == MANFID_OXSEMI) {
+	 * 8 registers are for the UART, the others are extra registers.
+	 * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
+	 */
+	if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
+				info->prodid == PRODID_POSSIO_GCC)) {
+		int err;
+
 		if (cf->index == 1 || cf->index == 3) {
-			setup_serial(handle, info, base2, link->irq.AssignedIRQ);
-			outb(12, link->io.BasePort1 + 1);
+			err = setup_serial(link, info, base2,
+					link->irq.AssignedIRQ);
+			base2 = link->io.BasePort1;
 		} else {
-			setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
-			outb(12, base2 + 1);
+			err = setup_serial(link, info, link->io.BasePort1,
+					link->irq.AssignedIRQ);
 		}
+		info->c950ctrl = base2;
+		wakeup_card(info);
 		rc = 0;
 		goto free_cfg_mem;
 	}
 
-	setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
+	setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
 	/* The Nokia cards are not really multiport cards */
 	if (info->manfid == MANFID_NOKIA) {
 		rc = 0;
 		goto free_cfg_mem;
 	}
 	for (i = 0; i < info->multi - 1; i++)
-		setup_serial(handle, info, base2 + (8 * i),
+		setup_serial(link, info, base2 + (8 * i),
 				link->irq.AssignedIRQ);
 	rc = 0;
 free_cfg_mem:
@@ -581,9 +578,8 @@
 
 ======================================================================*/
 
-void serial_config(dev_link_t * link)
+static int serial_config(struct pcmcia_device * link)
 {
-	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
 	struct serial_cfg_mem *cfg_mem;
 	tuple_t *tuple;
@@ -609,7 +605,7 @@
 	tuple->Attributes = 0;
 	/* Get configuration register information */
 	tuple->DesiredTuple = CISTPL_CONFIG;
-	last_ret = first_tuple(handle, tuple, parse);
+	last_ret = first_tuple(link, tuple, parse);
 	if (last_ret != CS_SUCCESS) {
 		last_fn = ParseTuple;
 		goto cs_failed;
@@ -617,18 +613,16 @@
 	link->conf.ConfigBase = parse->config.base;
 	link->conf.Present = parse->config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	/* Is this a compliant multifunction card? */
 	tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
 	tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
-	info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
+	info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
 
 	/* Is this a multiport card? */
 	tuple->DesiredTuple = CISTPL_MANFID;
-	if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+	if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
 		info->manfid = parse->manfid.manf;
+		info->prodid = le16_to_cpu(buf[1]);
 		for (i = 0; i < MULTI_COUNT; i++)
 			if ((info->manfid == multi_id[i].manfid) &&
 			    (parse->manfid.card == multi_id[i].prodid))
@@ -641,11 +635,11 @@
 	   multifunction cards that ask for appropriate IO port ranges */
 	tuple->DesiredTuple = CISTPL_FUNCID;
 	if ((info->multi == 0) &&
-	    ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
+	    ((first_tuple(link, tuple, parse) != CS_SUCCESS) ||
 	     (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
 	     (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
 		tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-		if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+		if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
 			if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
 				info->multi = cf->io.win[0].len >> 3;
 			if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,31 +658,30 @@
 
 	if (info->manfid == MANFID_IBM) {
 		conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
-		last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+		last_ret = pcmcia_access_configuration_register(link, &reg);
 		if (last_ret) {
 			last_fn = AccessConfigurationRegister;
 			goto cs_failed;
 		}
 		reg.Action = CS_WRITE;
 		reg.Value = reg.Value | 1;
-		last_ret = pcmcia_access_configuration_register(link->handle, &reg);
+		last_ret = pcmcia_access_configuration_register(link, &reg);
 		if (last_ret) {
 			last_fn = AccessConfigurationRegister;
 			goto cs_failed;
 		}
 	}
 
-	link->dev = &info->node[0];
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &info->node[0];
 	kfree(cfg_mem);
-	return;
+	return 0;
 
  cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
  failed:
 	serial_remove(link);
-	link->state &= ~DEV_CONFIG_PENDING;
 	kfree(cfg_mem);
+	return -ENODEV;
 }
 
 static struct pcmcia_device_id serial_ids[] = {
@@ -739,6 +732,7 @@
 	PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77),
 	PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
 	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301),
+	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276),
 	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039),
 	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006),
 	PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a),
@@ -757,6 +751,7 @@
 	PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef),
 	PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef),
 	PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0),
+	PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e),
 	PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a),
 	PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02),
 	PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa),
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 93449a1..0b49ff7 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
@@ -619,9 +620,9 @@
 	pci_set_master(pdev);
 
 #ifdef USE_64BIT_DMA
-        ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+        ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
         if (!ret) {
-                ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+                ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
                 if (ret < 0) {
                         printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
                                "for consistent allocations\n",
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index d3a7b0c..dda0ca4 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -35,73 +35,52 @@
 } ixj_info_t;
 
 static void ixj_detach(struct pcmcia_device *p_dev);
-static void ixj_config(dev_link_t * link);
-static void ixj_cs_release(dev_link_t * link);
+static int ixj_config(struct pcmcia_device * link);
+static void ixj_cs_release(struct pcmcia_device * link);
 
-static int ixj_attach(struct pcmcia_device *p_dev)
+static int ixj_probe(struct pcmcia_device *p_dev)
 {
-	dev_link_t *link;
-
 	DEBUG(0, "ixj_attach()\n");
 	/* Create new ixj device */
-	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-	if (!link)
-		return -ENOMEM;
-	memset(link, 0, sizeof(struct dev_link_t));
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	link->io.IOAddrLines = 3;
-	link->conf.Vcc = 50;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
-	if (!link->priv) {
-		kfree(link);
+	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+	p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+	p_dev->io.IOAddrLines = 3;
+	p_dev->conf.IntType = INT_MEMORY_AND_IO;
+	p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+	if (!p_dev->priv) {
 		return -ENOMEM;
 	}
-	memset(link->priv, 0, sizeof(struct ixj_info_t));
+	memset(p_dev->priv, 0, sizeof(struct ixj_info_t));
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	ixj_config(link);
-
-	return 0;
+	return ixj_config(p_dev);
 }
 
-static void ixj_detach(struct pcmcia_device *p_dev)
+static void ixj_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DEBUG(0, "ixj_detach(0x%p)\n", link);
 
-	link->state &= ~DEV_RELEASE_PENDING;
-	if (link->state & DEV_CONFIG)
-		ixj_cs_release(link);
+	ixj_cs_release(link);
 
         kfree(link->priv);
-        kfree(link);
 }
 
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void ixj_get_serial(dev_link_t * link, IXJ * j)
+static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
 {
-	client_handle_t handle;
 	tuple_t tuple;
 	u_short buf[128];
 	char *str;
 	int last_ret, last_fn, i, place;
-	handle = link->handle;
 	DEBUG(0, "ixj_get_serial(0x%p)\n", link);
 	tuple.TupleData = (cisdata_t *) buf;
 	tuple.TupleOffset = 0;
 	tuple.TupleDataMax = 80;
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_VERS_1;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
 	str = (char *) buf;
 	printk("PCMCIA Version %d.%d\n", str[0], str[1]);
 	str += 2;
@@ -149,22 +128,19 @@
 	return;
 }
 
-static void ixj_config(dev_link_t * link)
+static int ixj_config(struct pcmcia_device * link)
 {
 	IXJ *j;
-	client_handle_t handle;
 	ixj_info_t *info;
 	tuple_t tuple;
 	u_short buf[128];
 	cisparse_t parse;
-	config_info_t conf;
 	cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
 	cistpl_cftable_entry_t dflt =
 	{
 		0
 	};
 	int last_ret, last_fn;
-	handle = link->handle;
 	info = link->priv;
 	DEBUG(0, "ixj_config(0x%p)\n", link);
 	tuple.TupleData = (cisdata_t *) buf;
@@ -172,19 +148,17 @@
 	tuple.TupleDataMax = 255;
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
-	link->state |= DEV_CONFIG;
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	tuple.Attributes = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+				pcmcia_parse_tuple(link, &tuple, &parse) != 0)
 			goto next_entry;
 		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
 			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
@@ -195,7 +169,7 @@
 				link->io.BasePort2 = io->win[1].base;
 				link->io.NumPorts2 = io->win[1].len;
 			}
-			if (pcmcia_request_io(link->handle, &link->io) != 0)
+			if (pcmcia_request_io(link, &link->io) != 0)
 				goto next_entry;
 			/* If we've got this far, we're done */
 			break;
@@ -203,10 +177,10 @@
 	      next_entry:
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 			dflt = *cfg;
-		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
 	}
 
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	/*
  	 *	Register the card with the core.
@@ -215,46 +189,21 @@
 
 	info->ndev = 1;
 	info->node.major = PHONE_MAJOR;
-	link->dev = &info->node;
+	link->dev_node = &info->node;
 	ixj_get_serial(link, j);
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	return 0;
       cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 	ixj_cs_release(link);
+	return -ENODEV;
 }
 
-static void ixj_cs_release(dev_link_t *link)
+static void ixj_cs_release(struct pcmcia_device *link)
 {
 	ixj_info_t *info = link->priv;
 	DEBUG(0, "ixj_cs_release(0x%p)\n", link);
 	info->ndev = 0;
-	link->dev = NULL;
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	link->state &= ~DEV_CONFIG;
-}
-
-static int ixj_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
-	return 0;
-}
-
-static int ixj_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (DEV_OK(link))
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
+	pcmcia_disable_device(link);
 }
 
 static struct pcmcia_device_id ixj_ids[] = {
@@ -268,11 +217,9 @@
 	.drv		= {
 		.name	= "ixj_cs",
 	},
-	.probe		= ixj_attach,
+	.probe		= ixj_probe,
 	.remove		= ixj_detach,
 	.id_table	= ixj_ids,
-	.suspend	= ixj_suspend,
-	.resume		= ixj_resume,
 };
 
 static int __init ixj_pcmcia_init(void)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 830d2c9..b38990a 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -68,7 +68,7 @@
 
 #include "usbatm.h"
 
-#define EAGLEUSBVERSION "ueagle 1.2"
+#define EAGLEUSBVERSION "ueagle 1.3"
 
 
 /*
@@ -243,7 +243,7 @@
 #define BULK_TIMEOUT 300
 #define CTRL_TIMEOUT 1000
 
-#define ACK_TIMEOUT msecs_to_jiffies(1500)
+#define ACK_TIMEOUT msecs_to_jiffies(3000)
 
 #define UEA_INTR_IFACE_NO 	0
 #define UEA_US_IFACE_NO		1
@@ -314,6 +314,10 @@
 	 ((d) & 0xff) << 16 |						\
 	 ((a) & 0xff) << 8  |						\
 	 ((b) & 0xff))
+#define GETSA1(a) ((a >> 8) & 0xff)
+#define GETSA2(a) (a & 0xff)
+#define GETSA3(a) ((a >> 24) & 0xff)
+#define GETSA4(a) ((a >> 16) & 0xff)
 
 #define SA_CNTL MAKESA('C', 'N', 'T', 'L')
 #define SA_DIAG MAKESA('D', 'I', 'A', 'G')
@@ -728,11 +732,12 @@
 	uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
 	return;
 bad1:
-	uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+	uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
 }
 
 static inline void wake_up_cmv_ack(struct uea_softc *sc)
 {
+	BUG_ON(sc->cmv_ack);
 	sc->cmv_ack = 1;
 	wake_up(&sc->cmv_ack_wait);
 }
@@ -743,6 +748,9 @@
 						   sc->cmv_ack, ACK_TIMEOUT);
 	sc->cmv_ack = 0;
 
+	uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n",
+			jiffies_to_msecs(ret));
+
 	if (ret < 0)
 		return ret;
 
@@ -791,6 +799,12 @@
 	struct cmv cmv;
 	int ret;
 
+	uea_enters(INS_TO_USBDEV(sc));
+	uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+			"offset : 0x%04x, data : 0x%08x\n",
+			FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function),
+			GETSA1(address), GETSA2(address), GETSA3(address),
+			GETSA4(address), offset, data);
 	/* we send a request, but we expect a reply */
 	sc->cmv_function = function | 0x2;
 	sc->cmv_idx++;
@@ -808,7 +822,9 @@
 	ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
 	if (ret < 0)
 		return ret;
-	return wait_cmv_ack(sc);
+	ret = wait_cmv_ack(sc);
+	uea_leaves(INS_TO_USBDEV(sc));
+	return ret;
 }
 
 static inline int uea_read_cmv(struct uea_softc *sc,
@@ -922,7 +938,7 @@
 	 * we check the status again in order to detect the failure earlier
 	 */
 	if (sc->stats.phy.flags) {
-		uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+		uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
 		       sc->stats.phy.flags);
 		return 0;
 	}
@@ -1063,7 +1079,13 @@
 	uea_enters(INS_TO_USBDEV(sc));
 	uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
 
+	/* mask interrupt */
 	sc->booting = 1;
+	/* We need to set this here because, a ack timeout could have occured,
+	 * but before we start the reboot, the ack occurs and set this to 1.
+	 * So we will failed to wait Ready CMV.
+	 */
+	sc->cmv_ack = 0;
 	UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
 
 	/* reset statistics */
@@ -1089,6 +1111,7 @@
 
 	msleep(1000);
 	sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+	/* demask interrupt */
 	sc->booting = 0;
 
 	/* start loading DSP */
@@ -1101,6 +1124,8 @@
 	if (ret < 0)
 		return ret;
 
+	uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n");
+
 	/* Enter in R-IDLE (cmv) until instructed otherwise */
 	ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
 	if (ret < 0)
@@ -1121,6 +1146,7 @@
 	}
 	/* Enter in R-ACT-REQ */
 	ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+	uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
 out:
 	release_firmware(cmvs_fw);
 	sc->reset = 0;
@@ -1235,6 +1261,7 @@
 
 	if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
 		wake_up_cmv_ack(sc);
+		uea_leaves(INS_TO_USBDEV(sc));
 		return;
 	}
 
@@ -1249,6 +1276,7 @@
 	sc->data = sc->data << 16 | sc->data >> 16;
 
 	wake_up_cmv_ack(sc);
+	uea_leaves(INS_TO_USBDEV(sc));
 	return;
 
 bad2:
@@ -1256,12 +1284,14 @@
 			"Function : %d, Subfunction : %d\n",
 			FUNCTION_TYPE(cmv->bFunction),
 			FUNCTION_SUBTYPE(cmv->bFunction));
+	uea_leaves(INS_TO_USBDEV(sc));
 	return;
 
 bad1:
 	uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
 			"wPreamble %d, bDirection %d\n",
 			le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+	uea_leaves(INS_TO_USBDEV(sc));
 }
 
 /*
@@ -1346,7 +1376,7 @@
 	if (ret < 0) {
 		uea_err(INS_TO_USBDEV(sc),
 		       "urb submition failed with error %d\n", ret);
-		goto err1;
+		goto err;
 	}
 
 	sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
@@ -1360,10 +1390,10 @@
 
 err2:
 	usb_kill_urb(sc->urb_int);
-err1:
-	kfree(intr);
 err:
 	usb_free_urb(sc->urb_int);
+	sc->urb_int = NULL;
+	kfree(intr);
 	uea_leaves(INS_TO_USBDEV(sc));
 	return -ENOMEM;
 }
@@ -1508,7 +1538,7 @@
 	int ret = -ENODEV; 					\
 	struct uea_softc *sc; 					\
  								\
-	mutex_lock(&uea_mutex); 					\
+	mutex_lock(&uea_mutex); 				\
 	sc = dev_to_uea(dev);					\
 	if (!sc) 						\
 		goto out; 					\
@@ -1516,7 +1546,7 @@
 	if (reset)						\
 		sc->stats.phy.name = 0;				\
 out: 								\
-	mutex_unlock(&uea_mutex); 					\
+	mutex_unlock(&uea_mutex); 				\
 	return ret; 						\
 } 								\
 								\
@@ -1643,7 +1673,7 @@
 
 	sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
 	if (!sc) {
-		uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+		uea_err(usb, "uea_init: not enough memory !\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index ff03184..a08787e 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -99,4 +99,11 @@
 	  normal Linux-USB hosts do (other than the warning), and is
 	  convenient for many stages of product development.
 
+config USB_OTG_BLACKLIST_HUB
+	bool "Disable external hubs"
+	depends on USB_OTG
+	help
+	  If you say Y here, then Linux will refuse to enumerate
+	  external hubs.  OTG hosts are allowed to reduce hardware
+	  and software costs by not supporting external hubs.
 
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 0d2193b..66b7840 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -213,11 +213,9 @@
 
 	if (hcd->driver->suspend) {
 		retval = hcd->driver->suspend(hcd, message);
-		if (retval) {
-			dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n",
-				retval);
+		suspend_report_result(hcd->driver->suspend, retval);
+		if (retval)
 			goto done;
-		}
 	}
 	synchronize_irq(dev->irq);
 
@@ -263,6 +261,7 @@
 		 * some device state (e.g. as part of clock reinit).
 		 */
 		retval = pci_set_power_state (dev, PCI_D3hot);
+		suspend_report_result(pci_set_power_state, retval);
 		if (retval == 0) {
 			int wake = device_can_wakeup(&hcd->self.root_hub->dev);
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 8e65f7a..0c87f73 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -836,6 +836,13 @@
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
+#ifdef	CONFIG_USB_OTG_BLACKLIST_HUB
+	if (hdev->parent) {
+		dev_warn(&intf->dev, "ignoring external hub\n");
+		return -ENODEV;
+	}
+#endif
+
 	/* Some hubs have a subclass of 1, which AFAICT according to the */
 	/*  specs is not defined, but it works */
 	if ((desc->desc.bInterfaceSubClass != 0) &&
@@ -1022,7 +1029,6 @@
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
 }
-EXPORT_SYMBOL(usb_set_device_state);
 
 
 #ifdef CONFIG_PM
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index d7352aa..b7fdc1c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1194,7 +1194,6 @@
 EXPORT_SYMBOL_GPL(usb_get_intf);
 EXPORT_SYMBOL_GPL(usb_put_intf);
 
-EXPORT_SYMBOL(usb_alloc_dev);
 EXPORT_SYMBOL(usb_put_dev);
 EXPORT_SYMBOL(usb_get_dev);
 EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
@@ -1208,7 +1207,6 @@
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
 EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_disconnect);
 
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d80f718..363b2ad 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -69,11 +69,11 @@
 	   often need board-specific hooks.
 
 config USB_GADGET_NET2280
-	boolean "NetChip 2280"
+	boolean "NetChip 228x"
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	help
-	   NetChip 2280 is a PCI based USB peripheral controller which
+	   NetChip 2280 / 2282 is a PCI based USB peripheral controller which
 	   supports both full and high speed USB 2.0 data transfers.  
 	   
 	   It has six configurable endpoints, as well as endpoint zero
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 865858c..b8d0b78 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1709,7 +1709,7 @@
 }
 
 #ifdef CONFIG_PM
-static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level)
+static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg)
 {
 	struct at91_udc *udc = platform_get_drvdata(dev);
 
@@ -1731,7 +1731,7 @@
 	return 0;
 }
 
-static int at91udc_resume(struct platform_device *dev, u32 level)
+static int at91udc_resume(struct platform_device *dev)
 {
 	struct at91_udc *udc = platform_get_drvdata(dev);
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index c3d8e5c..9c4422a 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2338,6 +2338,9 @@
 		hs_subset_descriptors();
 	}
 
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+	usb_gadget_set_selfpowered (gadget);
+
 	/* For now RNDIS is always a second config */
 	if (rndis)
 		device_desc.bNumConfigurations = 2;
@@ -2361,9 +2364,6 @@
 #endif
 #endif	/* DUALSPEED */
 
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-	usb_gadget_set_selfpowered (gadget);
-
 	if (gadget->is_otg) {
 		otg_descriptor.bmAttributes |= USB_OTG_HNP,
 		eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index cf3be29..6f88747 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -71,6 +71,12 @@
  * requirement amounts to two 16K buffers, size configurable by a parameter.
  * Support is included for both full-speed and high-speed operation.
  *
+ * Note that the driver is slightly non-portable in that it assumes a
+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
+ * interrupt-in endpoints.  With most device controllers this isn't an
+ * issue, but there may be some with hardware restrictions that prevent
+ * a buffer from being used by more than one endpoint.
+ *
  * Module options:
  *
  *	file=filename[,filename...]
@@ -108,6 +114,14 @@
  * setting are not allowed when the medium is loaded.
  *
  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
+ * The driver's SCSI command interface was based on the "Information
+ * technology - Small Computer System Interface - 2" document from
+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
+ * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>.  The single exception
+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
+ * "Universal Serial Bus Mass Storage Class UFI Command Specification"
+ * document, Revision 1.0, December 14, 1998, available at
+ * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
  */
 
 
@@ -334,11 +348,9 @@
 
 #define MAX_LUNS	8
 
-	/* Arggh!  There should be a module_param_array_named macro! */
-static char		*file[MAX_LUNS];
-static int		ro[MAX_LUNS];
-
 static struct {
+	char		*file[MAX_LUNS];
+	int		ro[MAX_LUNS];
 	int		num_filenames;
 	int		num_ros;
 	unsigned int	nluns;
@@ -370,10 +382,11 @@
 	};
 
 
-module_param_array(file, charp, &mod_data.num_filenames, S_IRUGO);
+module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
+		S_IRUGO);
 MODULE_PARM_DESC(file, "names of backing files or devices");
 
-module_param_array(ro, bool, &mod_data.num_ros, S_IRUGO);
+module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
 module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
@@ -1795,6 +1808,7 @@
 			 * the bulk-out maxpacket size */
 			bh->outreq->length = bh->bulk_out_intended_length =
 					amount;
+			bh->outreq->short_not_ok = 1;
 			start_transfer(fsg, fsg->bulk_out, bh->outreq,
 					&bh->outreq_busy, &bh->state);
 			fsg->next_buffhd_to_fill = bh->next;
@@ -2398,6 +2412,7 @@
 			 * the bulk-out maxpacket size */
 			bh->outreq->length = bh->bulk_out_intended_length =
 					amount;
+			bh->outreq->short_not_ok = 1;
 			start_transfer(fsg, fsg->bulk_out, bh->outreq,
 					&bh->outreq_busy, &bh->state);
 			fsg->next_buffhd_to_fill = bh->next;
@@ -3029,6 +3044,7 @@
 
 		/* Queue a request to read a Bulk-only CBW */
 		set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+		bh->outreq->short_not_ok = 1;
 		start_transfer(fsg, fsg->bulk_out, bh->outreq,
 				&bh->outreq_busy, &bh->state);
 
@@ -3859,7 +3875,7 @@
 
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
-		curlun->ro = ro[i];
+		curlun->ro = mod_data.ro[i];
 		curlun->dev.parent = &gadget->dev;
 		curlun->dev.driver = &fsg_driver.driver;
 		dev_set_drvdata(&curlun->dev, fsg);
@@ -3876,8 +3892,9 @@
 			kref_get(&fsg->ref);
 		}
 
-		if (file[i] && *file[i]) {
-			if ((rc = open_backing_file(curlun, file[i])) != 0)
+		if (mod_data.file[i] && *mod_data.file[i]) {
+			if ((rc = open_backing_file(curlun,
+					mod_data.file[i])) != 0)
 				goto out;
 		} else if (!mod_data.removable) {
 			ERROR(fsg, "no file given for LUN%d\n", i);
@@ -3953,6 +3970,9 @@
 	for (i = 0; i < NUM_BUFFERS; ++i) {
 		struct fsg_buffhd	*bh = &fsg->buffhds[i];
 
+		/* Allocate for the bulk-in endpoint.  We assume that
+		 * the buffer will also work with the bulk-out (and
+		 * interrupt-in) endpoint. */
 		bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
 				&bh->dma, GFP_KERNEL);
 		if (!bh->buf)
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index c408140..aa80f09 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -100,9 +100,9 @@
 #define gadget_is_musbhsfc(g)	0
 #endif
 
-/* Mentor high speed "dual role" controller, peripheral mode */
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
-#define gadget_is_musbhdrc(g)	!strcmp("musbhdrc_udc", (g)->name)
+/* Mentor high speed "dual role" controller, in peripheral role */
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+#define gadget_is_musbhdrc(g)	!strcmp("musb_hdrc", (g)->name)
 #else
 #define gadget_is_musbhdrc(g)	0
 #endif
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 3f618ce..0eb010a 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -810,7 +810,7 @@
 		if (value == 0)
 			data->state = STATE_EP_ENABLED;
 		break;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	case USB_SPEED_HIGH:
 		/* fails if caller didn't provide that descriptor... */
 		value = usb_ep_enable (ep, &data->hs_desc);
@@ -982,7 +982,7 @@
 			/* assume that was SET_CONFIGURATION */
 			if (dev->current_config) {
 				unsigned power;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 				if (dev->gadget->speed == USB_SPEED_HIGH)
 					power = dev->hs_config->bMaxPower;
 				else
@@ -1262,7 +1262,7 @@
  * Unrecognized ep0 requests may be handled in user space.
  */
 
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 static void make_qualifier (struct dev_data *dev)
 {
 	struct usb_qualifier_descriptor		qual;
@@ -1291,7 +1291,7 @@
 config_buf (struct dev_data *dev, u8 type, unsigned index)
 {
 	int		len;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	int		hs;
 #endif
 
@@ -1299,7 +1299,7 @@
 	if (index > 0)
 		return -EINVAL;
 
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	hs = (dev->gadget->speed == USB_SPEED_HIGH);
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
@@ -1335,12 +1335,12 @@
 		dev->state = STATE_CONNECTED;
 		dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
 
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 		if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
 			ERROR (dev, "no high speed config??\n");
 			return -EINVAL;
 		}
-#endif	/* HIGHSPEED */
+#endif	/* CONFIG_USB_GADGET_DUALSPEED */
 
 		INFO (dev, "connected\n");
 		event = next_event (dev, GADGETFS_CONNECT);
@@ -1352,11 +1352,11 @@
 			/* ... down_trylock (&data->lock) ... */
 			if (data->state != STATE_EP_DEFER_ENABLE)
 				continue;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 			if (gadget->speed == USB_SPEED_HIGH)
 				value = usb_ep_enable (ep, &data->hs_desc);
 			else
-#endif	/* HIGHSPEED */
+#endif	/* CONFIG_USB_GADGET_DUALSPEED */
 				value = usb_ep_enable (ep, &data->desc);
 			if (value) {
 				ERROR (dev, "deferred %s enable --> %d\n",
@@ -1391,7 +1391,7 @@
 			value = min (w_length, (u16) sizeof *dev->dev);
 			req->buf = dev->dev;
 			break;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!dev->hs_config)
 				break;
@@ -1428,7 +1428,7 @@
 			// user mode expected to disable endpoints
 		} else {
 			u8	config, power;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 			if (gadget->speed == USB_SPEED_HIGH) {
 				config = dev->hs_config->bConfigurationValue;
 				power = dev->hs_config->bMaxPower;
@@ -1614,6 +1614,7 @@
 				data, &ep_config_operations,
 				&data->dentry);
 		if (!data->inode) {
+			usb_ep_free_request(ep, data->req);
 			kfree (data);
 			goto enomem;
 		}
@@ -1728,7 +1729,7 @@
 }
 
 static struct usb_gadget_driver gadgetfs_driver = {
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index fb73dc1..0b92934 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -26,6 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -71,8 +73,8 @@
 #include <asm/unaligned.h>
 
 
-#define	DRIVER_DESC		"PLX NET2280 USB Peripheral Controller"
-#define	DRIVER_VERSION		"2005 Feb 03"
+#define	DRIVER_DESC		"PLX NET228x USB Peripheral Controller"
+#define	DRIVER_VERSION		"2005 Sept 27"
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	EP_DONTUSE		13	/* nonzero */
@@ -118,7 +120,7 @@
 /* enable_suspend -- When enabled, the driver will respond to
  * USB suspend requests by powering down the NET2280.  Otherwise,
  * USB suspend requests will be ignored.  This is acceptible for
- * self-powered devices, and helps avoid some quirks.
+ * self-powered devices
  */
 static int enable_suspend = 0;
 
@@ -223,6 +225,11 @@
 	ep->is_in = (tmp & USB_DIR_IN) != 0;
 	if (!ep->is_in)
 		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
+	else if (dev->pdev->device != 0x2280) {
+		/* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+		writel ((1 << CLEAR_NAK_OUT_PACKETS)
+			| (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
+	}
 
 	writel (tmp, &ep->regs->ep_cfg);
 
@@ -232,8 +239,9 @@
 		writel (tmp, &dev->regs->pciirqenb0);
 
 		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-			| readl (&ep->regs->ep_irqenb);
+			| (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+		if (dev->pdev->device == 0x2280)
+			tmp |= readl (&ep->regs->ep_irqenb);
 		writel (tmp, &ep->regs->ep_irqenb);
 	} else {				/* dma, per-request */
 		tmp = (1 << (8 + ep->num));	/* completion */
@@ -314,10 +322,18 @@
 	/* init to our chosen defaults, notably so that we NAK OUT
 	 * packets until the driver queues a read (+note erratum 0112)
 	 */
-	tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
+	if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
+		tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
 		| (1 << SET_NAK_OUT_PACKETS)
 		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
 		| (1 << CLEAR_INTERRUPT_MODE);
+	} else {
+		/* added for 2282 */
+		tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
+		| (1 << CLEAR_NAK_OUT_PACKETS)
+		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
+		| (1 << CLEAR_INTERRUPT_MODE);
+	}
 
 	if (ep->num != 0) {
 		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
@@ -326,14 +342,18 @@
 	writel (tmp, &ep->regs->ep_rsp);
 
 	/* scrub most status bits, and flush any fifo state */
-	writel (  (1 << TIMEOUT)
+	if (ep->dev->pdev->device == 0x2280)
+		tmp = (1 << FIFO_OVERFLOW)
+			| (1 << FIFO_UNDERFLOW);
+	else
+		tmp = 0;
+
+	writel (tmp | (1 << TIMEOUT)
 		| (1 << USB_STALL_SENT)
 		| (1 << USB_IN_NAK_SENT)
 		| (1 << USB_IN_ACK_RCVD)
 		| (1 << USB_OUT_PING_NAK_SENT)
 		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_OVERFLOW)
-		| (1 << FIFO_UNDERFLOW)
 		| (1 << FIFO_FLUSH)
 		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 		| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
@@ -718,7 +738,7 @@
 	 */
 	if (ep->is_in)
 		dmacount |= (1 << DMA_DIRECTION);
-	else if ((dmacount % ep->ep.maxpacket) != 0)
+	if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
 		dmacount |= (1 << END_OF_CHAIN);
 
 	req->valid = valid;
@@ -760,9 +780,12 @@
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
 	struct net2280_dma_regs	__iomem *dma = ep->dma;
+	unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
 
-	writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
-			&dma->dmacount);
+	if (ep->dev->pdev->device != 0x2280)
+		tmp |= (1 << END_OF_CHAIN);
+
+	writel (tmp, &dma->dmacount);
 	writel (readl (&dma->dmastat), &dma->dmastat);
 
 	writel (td_dma, &dma->dmadesc);
@@ -2110,7 +2133,11 @@
 	VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
 			ep->ep.name, t, req ? &req->req : 0);
 #endif
-	writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+	if (!ep->is_in || ep->dev->pdev->device == 0x2280)
+		writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+	else
+		/* Added for 2282 */
+		writel (t, &ep->regs->ep_stat);
 
 	/* for ep0, monitor token irqs to catch data stage length errors
 	 * and to synchronize on status.
@@ -2139,7 +2166,7 @@
 					ep->stopped = 1;
 					set_halt (ep);
 					mode = 2;
-				} else if (!req && ep->stopped)
+				} else if (!req && !ep->stopped)
 					write_fifo (ep, NULL);
 			}
 		} else {
@@ -2214,7 +2241,8 @@
 			if (likely (req)) {
 				req->td->dmacount = 0;
 				t = readl (&ep->regs->ep_avail);
-				dma_done (ep, req, count, t);
+				dma_done (ep, req, count,
+					(ep->out_overflow || t) ? -EOVERFLOW : 0);
 			}
 
 			/* also flush to prevent erratum 0106 trouble */
@@ -2252,9 +2280,7 @@
 		/* if we wrote it all, we're usually done */
 		if (req->req.actual == req->req.length) {
 			if (ep->num == 0) {
-				/* wait for control status */
-				if (mode != 2)
-					req = NULL;
+				/* send zlps until the status stage */
 			} else if (!req->req.zero || len != ep->ep.maxpacket)
 				mode = 2;
 		}
@@ -2337,7 +2363,7 @@
 			u32			raw [2];
 			struct usb_ctrlrequest	r;
 		} u;
-		int				tmp = 0;
+		int				tmp;
 		struct net2280_request		*req;
 
 		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2390,19 @@
 		}
 		ep->stopped = 0;
 		dev->protocol_stall = 0;
-		writel (  (1 << TIMEOUT)
+
+		if (ep->dev->pdev->device == 0x2280)
+			tmp = (1 << FIFO_OVERFLOW)
+				| (1 << FIFO_UNDERFLOW);
+		else
+			tmp = 0;
+
+		writel (tmp | (1 << TIMEOUT)
 			| (1 << USB_STALL_SENT)
 			| (1 << USB_IN_NAK_SENT)
 			| (1 << USB_IN_ACK_RCVD)
 			| (1 << USB_OUT_PING_NAK_SENT)
 			| (1 << USB_OUT_ACK_SENT)
-			| (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW)
 			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
 			| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
@@ -2385,6 +2416,8 @@
 		cpu_to_le32s (&u.raw [0]);
 		cpu_to_le32s (&u.raw [1]);
 
+		tmp = 0;
+
 #define	w_value		le16_to_cpup (&u.r.wValue)
 #define	w_index		le16_to_cpup (&u.r.wIndex)
 #define	w_length	le16_to_cpup (&u.r.wLength)
@@ -2594,10 +2627,17 @@
 		writel (stat, &dev->regs->irqstat1);
 
 	/* some status we can just ignore */
-	stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-			| (1 << SUSPEND_REQUEST_INTERRUPT)
-			| (1 << RESUME_INTERRUPT)
-			| (1 << SOF_INTERRUPT));
+	if (dev->pdev->device == 0x2280)
+		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+			  | (1 << SUSPEND_REQUEST_INTERRUPT)
+			  | (1 << RESUME_INTERRUPT)
+			  | (1 << SOF_INTERRUPT));
+	else
+		stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+			  | (1 << RESUME_INTERRUPT)
+			  | (1 << SOF_DOWN_INTERRUPT)
+			  | (1 << SOF_INTERRUPT));
+
 	if (!stat)
 		return;
 	// DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2702,6 +2742,10 @@
 {
 	struct net2280		*dev = _dev;
 
+	/* shared interrupt, not ours */
+	if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
+		return IRQ_NONE;
+
 	spin_lock (&dev->lock);
 
 	/* handle disconnect, dma, and more */
@@ -2789,13 +2833,13 @@
 	}
 
 	/* alloc, and start init */
-	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+	dev = kzalloc (sizeof *dev, SLAB_KERNEL);
 	if (dev == NULL){
 		retval = -ENOMEM;
 		goto done;
 	}
 
-	memset (dev, 0, sizeof *dev);
+	pci_set_drvdata (pdev, dev);
 	spin_lock_init (&dev->lock);
 	dev->pdev = pdev;
 	dev->gadget.ops = &net2280_ops;
@@ -2908,7 +2952,6 @@
 	dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
 
 	/* done */
-	pci_set_drvdata (pdev, dev);
 	INFO (dev, "%s\n", driver_desc);
 	INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
 			bufp, base, dev->chiprev);
@@ -2939,6 +2982,13 @@
 	.device =	0x2280,
 	.subvendor =	PCI_ANY_ID,
 	.subdevice =	PCI_ANY_ID,
+}, {
+	.class = 	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask = 	~0,
+	.vendor =	0x17cc,
+	.device =	0x2282,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
 
 }, { /* end: all zeroes */ }
 };
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index fff4509..957d6df 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -22,420 +22,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-/*-------------------------------------------------------------------------*/
-
-/* NET2280 MEMORY MAPPED REGISTERS
- *
- * The register layout came from the chip documentation, and the bit
- * number definitions were extracted from chip specification.
- *
- * Use the shift operator ('<<') to build bit masks, with readl/writel
- * to access the registers through PCI.
- */
-
-/* main registers, BAR0 + 0x0000 */
-struct net2280_regs {
-	// offset 0x0000
-	u32		devinit;
-#define     LOCAL_CLOCK_FREQUENCY                               8
-#define     FORCE_PCI_RESET                                     7
-#define     PCI_ID                                              6
-#define     PCI_ENABLE                                          5
-#define     FIFO_SOFT_RESET                                     4
-#define     CFG_SOFT_RESET                                      3
-#define     PCI_SOFT_RESET                                      2
-#define     USB_SOFT_RESET                                      1
-#define     M8051_RESET                                         0
-	u32		eectl;
-#define     EEPROM_ADDRESS_WIDTH                                23
-#define     EEPROM_CHIP_SELECT_ACTIVE                           22
-#define     EEPROM_PRESENT                                      21
-#define     EEPROM_VALID                                        20
-#define     EEPROM_BUSY                                         19
-#define     EEPROM_CHIP_SELECT_ENABLE                           18
-#define     EEPROM_BYTE_READ_START                              17
-#define     EEPROM_BYTE_WRITE_START                             16
-#define     EEPROM_READ_DATA                                    8
-#define     EEPROM_WRITE_DATA                                   0
-	u32		eeclkfreq;
-	u32		_unused0;
-	// offset 0x0010
-
-	u32		pciirqenb0;		/* interrupt PCI master ... */
-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
-	u32		pciirqenb1;
-#define     PCI_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE          18
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-	u32		cpu_irqenb0;		/* ... or onboard 8051 */
-#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
-#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
-#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
-#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
-#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
-#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
-#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
-#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
-	u32		cpu_irqenb1;
-#define     CPU_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_INTA_INTERRUPT_ENABLE                           24
-#define     PCI_PME_INTERRUPT_ENABLE                            23
-#define     PCI_SERR_INTERRUPT_ENABLE                           22
-#define     PCI_PERR_INTERRUPT_ENABLE                           21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-
-	// offset 0x0020
-	u32		_unused1;
-	u32		usbirqenb1;
-#define     USB_INTERRUPT_ENABLE                                31
-#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
-#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
-#define     PCI_INTA_INTERRUPT_ENABLE                           24
-#define     PCI_PME_INTERRUPT_ENABLE                            23
-#define     PCI_SERR_INTERRUPT_ENABLE                           22
-#define     PCI_PERR_INTERRUPT_ENABLE                           21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
-#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
-#define     GPIO_INTERRUPT_ENABLE                               13
-#define     DMA_D_INTERRUPT_ENABLE                              12
-#define     DMA_C_INTERRUPT_ENABLE                              11
-#define     DMA_B_INTERRUPT_ENABLE                              10
-#define     DMA_A_INTERRUPT_ENABLE                              9
-#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
-#define     VBUS_INTERRUPT_ENABLE                               7
-#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
-#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
-#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
-#define     RESUME_INTERRUPT_ENABLE                             1
-#define     SOF_INTERRUPT_ENABLE                                0
-	u32		irqstat0;
-#define     INTA_ASSERTED                                       12
-#define     SETUP_PACKET_INTERRUPT                              7
-#define     ENDPOINT_F_INTERRUPT                                6
-#define     ENDPOINT_E_INTERRUPT                                5
-#define     ENDPOINT_D_INTERRUPT                                4
-#define     ENDPOINT_C_INTERRUPT                                3
-#define     ENDPOINT_B_INTERRUPT                                2
-#define     ENDPOINT_A_INTERRUPT                                1
-#define     ENDPOINT_0_INTERRUPT                                0
-	u32		irqstat1;
-#define     POWER_STATE_CHANGE_INTERRUPT                        27
-#define     PCI_ARBITER_TIMEOUT_INTERRUPT                       26
-#define     PCI_PARITY_ERROR_INTERRUPT                          25
-#define     PCI_INTA_INTERRUPT                                  24
-#define     PCI_PME_INTERRUPT                                   23
-#define     PCI_SERR_INTERRUPT                                  22
-#define     PCI_PERR_INTERRUPT                                  21
-#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT                 20
-#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
-#define     PCI_RETRY_ABORT_INTERRUPT                           17
-#define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
-#define     GPIO_INTERRUPT                                      13
-#define     DMA_D_INTERRUPT                                     12
-#define     DMA_C_INTERRUPT                                     11
-#define     DMA_B_INTERRUPT                                     10
-#define     DMA_A_INTERRUPT                                     9
-#define     EEPROM_DONE_INTERRUPT                               8
-#define     VBUS_INTERRUPT                                      7
-#define     CONTROL_STATUS_INTERRUPT                            6
-#define     ROOT_PORT_RESET_INTERRUPT                           4
-#define     SUSPEND_REQUEST_INTERRUPT                           3
-#define     SUSPEND_REQUEST_CHANGE_INTERRUPT                    2
-#define     RESUME_INTERRUPT                                    1
-#define     SOF_INTERRUPT                                       0
-	// offset 0x0030
-	u32		idxaddr;
-	u32		idxdata;
-	u32		fifoctl;
-#define     PCI_BASE2_RANGE                                     16
-#define     IGNORE_FIFO_AVAILABILITY                            3
-#define     PCI_BASE2_SELECT                                    2
-#define     FIFO_CONFIGURATION_SELECT                           0
-	u32		_unused2;
-	// offset 0x0040
-	u32		memaddr;
-#define     START                                               28
-#define     DIRECTION                                           27
-#define     FIFO_DIAGNOSTIC_SELECT                              24
-#define     MEMORY_ADDRESS                                      0
-	u32		memdata0;
-	u32		memdata1;
-	u32		_unused3;
-	// offset 0x0050
-	u32		gpioctl;
-#define     GPIO3_LED_SELECT                                    12
-#define     GPIO3_INTERRUPT_ENABLE                              11
-#define     GPIO2_INTERRUPT_ENABLE                              10
-#define     GPIO1_INTERRUPT_ENABLE                              9
-#define     GPIO0_INTERRUPT_ENABLE                              8
-#define     GPIO3_OUTPUT_ENABLE                                 7
-#define     GPIO2_OUTPUT_ENABLE                                 6
-#define     GPIO1_OUTPUT_ENABLE                                 5
-#define     GPIO0_OUTPUT_ENABLE                                 4
-#define     GPIO3_DATA                                          3
-#define     GPIO2_DATA                                          2
-#define     GPIO1_DATA                                          1
-#define     GPIO0_DATA                                          0
-	u32		gpiostat;
-#define     GPIO3_INTERRUPT                                     3
-#define     GPIO2_INTERRUPT                                     2
-#define     GPIO1_INTERRUPT                                     1
-#define     GPIO0_INTERRUPT                                     0
-} __attribute__ ((packed));
-
-/* usb control, BAR0 + 0x0080 */
-struct net2280_usb_regs {
-	// offset 0x0080
-	u32		stdrsp;
-#define     STALL_UNSUPPORTED_REQUESTS                          31
-#define     SET_TEST_MODE                                       16
-#define     GET_OTHER_SPEED_CONFIGURATION                       15
-#define     GET_DEVICE_QUALIFIER                                14
-#define     SET_ADDRESS                                         13
-#define     ENDPOINT_SET_CLEAR_HALT                             12
-#define     DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP               11
-#define     GET_STRING_DESCRIPTOR_2                             10
-#define     GET_STRING_DESCRIPTOR_1                             9
-#define     GET_STRING_DESCRIPTOR_0                             8
-#define     GET_SET_INTERFACE                                   6
-#define     GET_SET_CONFIGURATION                               5
-#define     GET_CONFIGURATION_DESCRIPTOR                        4
-#define     GET_DEVICE_DESCRIPTOR                               3
-#define     GET_ENDPOINT_STATUS                                 2
-#define     GET_INTERFACE_STATUS                                1
-#define     GET_DEVICE_STATUS                                   0
-	u32		prodvendid;
-#define     PRODUCT_ID                                          16
-#define     VENDOR_ID                                           0
-	u32		relnum;
-	u32		usbctl;
-#define     SERIAL_NUMBER_INDEX                                 16
-#define     PRODUCT_ID_STRING_ENABLE                            13
-#define     VENDOR_ID_STRING_ENABLE                             12
-#define     USB_ROOT_PORT_WAKEUP_ENABLE                         11
-#define     VBUS_PIN                                            10
-#define     TIMED_DISCONNECT                                    9
-#define     SUSPEND_IMMEDIATELY                                 7
-#define     SELF_POWERED_USB_DEVICE                             6
-#define     REMOTE_WAKEUP_SUPPORT                               5
-#define     PME_POLARITY                                        4
-#define     USB_DETECT_ENABLE                                   3
-#define     PME_WAKEUP_ENABLE                                   2
-#define     DEVICE_REMOTE_WAKEUP_ENABLE                         1
-#define     SELF_POWERED_STATUS                                 0
-	// offset 0x0090
-	u32		usbstat;
-#define     HIGH_SPEED                                          7
-#define     FULL_SPEED                                          6
-#define     GENERATE_RESUME                                     5
-#define     GENERATE_DEVICE_REMOTE_WAKEUP                       4
-	u32		xcvrdiag;
-#define     FORCE_HIGH_SPEED_MODE                               31
-#define     FORCE_FULL_SPEED_MODE                               30
-#define     USB_TEST_MODE                                       24
-#define     LINE_STATE                                          16
-#define     TRANSCEIVER_OPERATION_MODE                          2
-#define     TRANSCEIVER_SELECT                                  1
-#define     TERMINATION_SELECT                                  0
-	u32		setup0123;
-	u32		setup4567;
-	// offset 0x0090
-	u32		_unused0;
-	u32		ouraddr;
-#define     FORCE_IMMEDIATE                                     7
-#define     OUR_USB_ADDRESS                                     0
-	u32		ourconfig;
-} __attribute__ ((packed));
-
-/* pci control, BAR0 + 0x0100 */
-struct net2280_pci_regs {
-	// offset 0x0100
-	u32		 pcimstctl;
-#define     PCI_ARBITER_PARK_SELECT                             13
-#define     PCI_MULTI LEVEL_ARBITER                             12
-#define     PCI_RETRY_ABORT_ENABLE                              11
-#define     DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE              10
-#define     DMA_READ_MULTIPLE_ENABLE                            9
-#define     DMA_READ_LINE_ENABLE                                8
-#define     PCI_MASTER_COMMAND_SELECT                           6
-#define         MEM_READ_OR_WRITE                                   0
-#define         IO_READ_OR_WRITE                                    1
-#define         CFG_READ_OR_WRITE                                   2
-#define     PCI_MASTER_START                                    5
-#define     PCI_MASTER_READ_WRITE                               4
-#define         PCI_MASTER_WRITE                                    0
-#define         PCI_MASTER_READ                                     1
-#define     PCI_MASTER_BYTE_WRITE_ENABLES                       0
-	u32		 pcimstaddr;
-	u32		 pcimstdata;
-	u32		 pcimststat;
-#define     PCI_ARBITER_CLEAR                                   2
-#define     PCI_EXTERNAL_ARBITER                                1
-#define     PCI_HOST_MODE                                       0
-} __attribute__ ((packed));
-
-/* dma control, BAR0 + 0x0180 ... array of four structs like this,
- * for channels 0..3.  see also struct net2280_dma:  descriptor
- * that can be loaded into some of these registers.
- */
-struct net2280_dma_regs {	/* [11.7] */
-	// offset 0x0180, 0x01a0, 0x01c0, 0x01e0, 
-	u32		dmactl;
-#define     DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE            25
-#define     DMA_CLEAR_COUNT_ENABLE                              21
-#define     DESCRIPTOR_POLLING_RATE                             19
-#define         POLL_CONTINUOUS                                     0
-#define         POLL_1_USEC                                         1
-#define         POLL_100_USEC                                       2
-#define         POLL_1_MSEC                                         3
-#define     DMA_VALID_BIT_POLLING_ENABLE                        18
-#define     DMA_VALID_BIT_ENABLE                                17
-#define     DMA_SCATTER_GATHER_ENABLE                           16
-#define     DMA_OUT_AUTO_START_ENABLE                           4
-#define     DMA_PREEMPT_ENABLE                                  3
-#define     DMA_FIFO_VALIDATE                                   2
-#define     DMA_ENABLE                                          1
-#define     DMA_ADDRESS_HOLD                                    0
-	u32		dmastat;
-#define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
-#define     DMA_TRANSACTION_DONE_INTERRUPT                      24
-#define     DMA_ABORT                                           1
-#define     DMA_START                                           0
-	u32		_unused0 [2];
-	// offset 0x0190, 0x01b0, 0x01d0, 0x01f0, 
-	u32		dmacount;
-#define     VALID_BIT                                           31
-#define     DMA_DIRECTION                                       30
-#define     DMA_DONE_INTERRUPT_ENABLE                           29
-#define     END_OF_CHAIN                                        28
-#define         DMA_BYTE_COUNT_MASK                                 ((1<<24)-1)
-#define     DMA_BYTE_COUNT                                      0
-	u32		dmaaddr;
-	u32		dmadesc;
-	u32		_unused1;
-} __attribute__ ((packed));
-
-/* dedicated endpoint registers, BAR0 + 0x0200 */
-
-struct net2280_dep_regs {	/* [11.8] */
-	// offset 0x0200, 0x0210, 0x220, 0x230, 0x240
-	u32		dep_cfg;
-	// offset 0x0204, 0x0214, 0x224, 0x234, 0x244
-	u32		dep_rsp;
-	u32		_unused [2];
-} __attribute__ ((packed));
-
-/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
- * like this, for ep0 then the configurable endpoints A..F
- * ep0 reserved for control; E and F have only 64 bytes of fifo
- */
-struct net2280_ep_regs {	/* [11.9] */
-	// offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
-	u32		ep_cfg;
-#define     ENDPOINT_BYTE_COUNT                                 16
-#define     ENDPOINT_ENABLE                                     10
-#define     ENDPOINT_TYPE                                       8
-#define     ENDPOINT_DIRECTION                                  7
-#define     ENDPOINT_NUMBER                                     0
-	u32		ep_rsp;
-#define     SET_NAK_OUT_PACKETS                                 15
-#define     SET_EP_HIDE_STATUS_PHASE                            14
-#define     SET_EP_FORCE_CRC_ERROR                              13
-#define     SET_INTERRUPT_MODE                                  12
-#define     SET_CONTROL_STATUS_PHASE_HANDSHAKE                  11
-#define     SET_NAK_OUT_PACKETS_MODE                            10
-#define     SET_ENDPOINT_TOGGLE                                 9
-#define     SET_ENDPOINT_HALT                                   8
-#define     CLEAR_NAK_OUT_PACKETS                               7
-#define     CLEAR_EP_HIDE_STATUS_PHASE                          6
-#define     CLEAR_EP_FORCE_CRC_ERROR                            5
-#define     CLEAR_INTERRUPT_MODE                                4
-#define     CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE                3
-#define     CLEAR_NAK_OUT_PACKETS_MODE                          2
-#define     CLEAR_ENDPOINT_TOGGLE                               1
-#define     CLEAR_ENDPOINT_HALT                                 0
-	u32		ep_irqenb;
-#define     SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE              6
-#define     SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE           5
-#define     DATA_PACKET_RECEIVED_INTERRUPT_ENABLE               3
-#define     DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE            2
-#define     DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE                1
-#define     DATA_IN_TOKEN_INTERRUPT_ENABLE                      0
-	u32		ep_stat;
-#define     FIFO_VALID_COUNT                                    24
-#define     HIGH_BANDWIDTH_OUT_TRANSACTION_PID                  22
-#define     TIMEOUT                                             21
-#define     USB_STALL_SENT                                      20
-#define     USB_IN_NAK_SENT                                     19
-#define     USB_IN_ACK_RCVD                                     18
-#define     USB_OUT_PING_NAK_SENT                               17
-#define     USB_OUT_ACK_SENT                                    16
-#define     FIFO_OVERFLOW                                       13
-#define     FIFO_UNDERFLOW                                      12
-#define     FIFO_FULL                                           11
-#define     FIFO_EMPTY                                          10
-#define     FIFO_FLUSH                                          9
-#define     SHORT_PACKET_OUT_DONE_INTERRUPT                     6
-#define     SHORT_PACKET_TRANSFERRED_INTERRUPT                  5
-#define     NAK_OUT_PACKETS                                     4
-#define     DATA_PACKET_RECEIVED_INTERRUPT                      3
-#define     DATA_PACKET_TRANSMITTED_INTERRUPT                   2
-#define     DATA_OUT_PING_TOKEN_INTERRUPT                       1
-#define     DATA_IN_TOKEN_INTERRUPT                             0
-	// offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
-	u32		ep_avail;
-	u32		ep_data;
-	u32		_unused0 [2];
-} __attribute__ ((packed));
+#include <linux/usb/net2280.h>
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 51424f6..68e3d8f 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -572,9 +572,10 @@
 	switch (status) {
 
 	case 0: 			/* normal completion? */
-		if (ep == dev->out_ep)
+		if (ep == dev->out_ep) {
 			check_read_data (dev, ep, req);
-		else
+			memset (req->buf, 0x55, req->length);
+		} else
 			reinit_write_data (dev, ep, req);
 		break;
 
@@ -626,6 +627,8 @@
 
 	if (strcmp (ep->name, EP_IN_NAME) == 0)
 		reinit_write_data (ep->driver_data, ep, req);
+	else
+		memset (req->buf, 0x55, req->length);
 
 	status = usb_ep_queue (ep, req, gfp_flags);
 	if (status) {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1e03f1a..a1bd2be 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -350,7 +350,7 @@
 /* PCI driver selection metadata; PCI hotplugging uses this */
 static const struct pci_device_id pci_ids [] = { {
 	/* handle any USB 2.0 EHCI controller */
-	PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
+	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
 	.driver_data =	(unsigned long) &ehci_pci_hc_driver,
 	},
 	{ /* end: all zeroes */ }
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 980030d6..6b7350b 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -20,7 +20,7 @@
 #include <asm/arch/board.h>
 
 #ifndef CONFIG_ARCH_AT91RM9200
-#error "This file is AT91RM9200 bus glue.  CONFIG_ARCH_AT91RM9200 must be defined."
+#error "CONFIG_ARCH_AT91RM9200 must be defined."
 #endif
 
 /* interface and function clocks */
@@ -84,8 +84,6 @@
  * Allocates basic resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
  */
 int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev)
 {
@@ -148,7 +146,6 @@
 }
 
 
-/* may be called without controller electrically present */
 /* may be called with controller, bus, and devices active */
 
 /**
@@ -166,11 +163,11 @@
 	usb_remove_hcd(hcd);
 	at91_stop_hc(pdev);
 	iounmap(hcd->regs);
- 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
- 	clk_put(fclk);
- 	clk_put(iclk);
- 	fclk = iclk = NULL;
+	clk_put(fclk);
+	clk_put(iclk);
+	fclk = iclk = NULL;
 
 	dev_set_drvdata(&pdev->dev, NULL);
 	return 0;
@@ -235,8 +232,8 @@
 	.hub_control =		ohci_hub_control,
 
 #ifdef CONFIG_PM
-	.hub_suspend =		ohci_hub_suspend,
-	.hub_resume =		ohci_hub_resume,
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
 #endif
 	.start_port_reset =	ohci_start_port_reset,
 };
@@ -254,21 +251,21 @@
 }
 
 #ifdef CONFIG_PM
-static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level)
-{
-	printk("%s(%s:%d): not implemented yet\n",
-		__func__, __FILE__, __LINE__);
 
+/* REVISIT suspend/resume look "too" simple here */
+
+static int
+ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg)
+{
 	clk_disable(fclk);
+	clk_disable(iclk);
 
 	return 0;
 }
 
-static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state)
+static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
 {
-	printk("%s(%s:%d): not implemented yet\n",
-		__func__, __FILE__, __LINE__);
-
+	clk_enable(iclk);
 	clk_enable(fclk);
 
 	return 0;
@@ -278,6 +275,8 @@
 #define ohci_hcd_at91_drv_resume  NULL
 #endif
 
+MODULE_ALIAS("at91rm9200-ohci");
+
 static struct platform_driver ohci_hcd_at91_driver = {
 	.probe		= ohci_hcd_at91_drv_probe,
 	.remove		= ohci_hcd_at91_drv_remove,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 1bfe96f..b268537 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -206,7 +206,7 @@
 
 static const struct pci_device_id pci_ids [] = { {
 	/* handle any USB OHCI controller */
-	PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0),
+	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
 	.driver_data =	(unsigned long) &ohci_pci_hc_driver,
 	}, { /* end: all zeroes */ }
 };
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 682bf22..1da5de5 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -30,6 +30,7 @@
 /* clock device associated with the hcd */
 
 static struct clk *clk;
+static struct clk *usb_clk;
 
 /* forward definitions */
 
@@ -37,7 +38,7 @@
 
 /* conversion functions */
 
-struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
+static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd)
 {
 	return hcd->self.controller->platform_data;
 }
@@ -47,6 +48,10 @@
 	struct s3c2410_hcd_info *info = dev->dev.platform_data;
 
 	dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
+
+	clk_enable(usb_clk);
+	mdelay(2);			/* let the bus clock stabilise */
+
 	clk_enable(clk);
 
 	if (info != NULL) {
@@ -75,6 +80,7 @@
 	}
 
 	clk_disable(clk);
+	clk_disable(usb_clk);
 }
 
 /* ohci_s3c2410_hub_status_data
@@ -316,7 +322,8 @@
  *
 */
 
-void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
+static void
+usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
 {
 	usb_remove_hcd(hcd);
 	s3c2410_stop_hc(dev);
@@ -334,8 +341,8 @@
  * through the hotplug entry's driver_data.
  *
  */
-int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
-			   struct platform_device *dev)
+static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
+				  struct platform_device *dev)
 {
 	struct usb_hcd *hcd = NULL;
 	int retval;
@@ -353,14 +360,21 @@
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		dev_err(&dev->dev, "request_mem_region failed");
 		retval = -EBUSY;
-		goto err0;
+		goto err_put;
 	}
 
-	clk = clk_get(NULL, "usb-host");
+	clk = clk_get(&dev->dev, "usb-host");
 	if (IS_ERR(clk)) {
 		dev_err(&dev->dev, "cannot get usb-host clock\n");
 		retval = -ENOENT;
-		goto err1;
+		goto err_mem;
+	}
+
+	usb_clk = clk_get(&dev->dev, "upll");
+	if (IS_ERR(usb_clk)) {
+		dev_err(&dev->dev, "cannot get usb-host clock\n");
+		retval = -ENOENT;
+		goto err_clk;
 	}
 
 	s3c2410_start_hc(dev, hcd);
@@ -369,26 +383,29 @@
 	if (!hcd->regs) {
 		dev_err(&dev->dev, "ioremap failed\n");
 		retval = -ENOMEM;
-		goto err2;
+		goto err_ioremap;
 	}
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
 	if (retval != 0)
-		goto err2;
+		goto err_ioremap;
 
 	return 0;
 
- err2:
+ err_ioremap:
 	s3c2410_stop_hc(dev);
 	iounmap(hcd->regs);
+	clk_put(usb_clk);
+
+ err_clk:
 	clk_put(clk);
 
- err1:
+ err_mem:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
- err0:
+ err_put:
 	usb_put_hcd(hcd);
 	return retval;
 }
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 9e81c26..1045f84 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/acpi.h>
+#include "pci-quirks.h"
 
 
 #define UHCI_USBLEGSUP		0xc0		/* legacy support */
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
new file mode 100644
index 0000000..1564edf
--- /dev/null
+++ b/drivers/usb/host/pci-quirks.h
@@ -0,0 +1,7 @@
+#ifndef __LINUX_USB_PCI_QUIRKS_H
+#define __LINUX_USB_PCI_QUIRKS_H
+
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+
+#endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 134d200..302aa1e 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -67,11 +67,11 @@
 static const char driver_name[DEV_NAME_LEN]  = "sl811_cs";
 
 typedef struct local_info_t {
-	dev_link_t		link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t		node;
 } local_info_t;
 
-static void sl811_cs_release(dev_link_t * link);
+static void sl811_cs_release(struct pcmcia_device * link);
 
 /*====================================================================*/
 
@@ -138,41 +138,27 @@
 
 /*====================================================================*/
 
-static void sl811_cs_detach(struct pcmcia_device *p_dev)
+static void sl811_cs_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
-
 	DBG(0, "sl811_cs_detach(0x%p)\n", link);
 
-	link->state &= ~DEV_PRESENT;
-	if (link->state & DEV_CONFIG)
-		sl811_cs_release(link);
+	sl811_cs_release(link);
 
 	/* This points to the parent local_info_t struct */
 	kfree(link->priv);
 }
 
-static void sl811_cs_release(dev_link_t * link)
+static void sl811_cs_release(struct pcmcia_device * link)
 {
-
 	DBG(0, "sl811_cs_release(0x%p)\n", link);
 
-	/* Unlink the device chain */
-	link->dev = NULL;
-
+	pcmcia_disable_device(link);
 	platform_device_unregister(&platform_dev);
-	pcmcia_release_configuration(link->handle);
-	if (link->io.NumPorts1)
-		pcmcia_release_io(link->handle, &link->io);
-	if (link->irq.AssignedIRQ)
-		pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
 }
 
-static void sl811_cs_config(dev_link_t *link)
+static int sl811_cs_config(struct pcmcia_device *link)
 {
-	client_handle_t		handle = link->handle;
-	struct device		*parent = &handle_to_dev(handle);
+	struct device		*parent = &handle_to_dev(link);
 	local_info_t		*dev = link->priv;
 	tuple_t			tuple;
 	cisparse_t		parse;
@@ -188,27 +174,23 @@
 	tuple.TupleData = buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
 	link->conf.ConfigBase = parse.config.base;
 	link->conf.Present = parse.config.rmask[0];
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
 	/* Look up the current Vcc */
 	CS_CHECK(GetConfigurationInfo,
-			pcmcia_get_configuration_info(handle, &conf));
-	link->conf.Vcc = conf.Vcc;
+			pcmcia_get_configuration_info(link, &conf));
 
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
 	while (1) {
 		cistpl_cftable_entry_t	*cfg = &(parse.cftable_entry);
 
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0
-				|| pcmcia_parse_tuple(handle, &tuple, &parse)
+		if (pcmcia_get_tuple_data(link, &tuple) != 0
+				|| pcmcia_parse_tuple(link, &tuple, &parse)
 						!= 0)
 			goto next_entry;
 
@@ -234,10 +216,10 @@
 		}
 
 		if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 		else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-			link->conf.Vpp1 = link->conf.Vpp2 =
+			link->conf.Vpp =
 				dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 		/* we need an interrupt */
@@ -254,15 +236,14 @@
 			link->io.BasePort1 = io->win[0].base;
 			link->io.NumPorts1 = io->win[0].len;
 
-			if (pcmcia_request_io(link->handle, &link->io) != 0)
+			if (pcmcia_request_io(link, &link->io) != 0)
 				goto next_entry;
 		}
 		break;
 
 next_entry:
-		if (link->io.NumPorts1)
-			pcmcia_release_io(link->handle, &link->io);
-		last_ret = pcmcia_get_next_tuple(handle, &tuple);
+		pcmcia_disable_device(link);
+		last_ret = pcmcia_get_next_tuple(link, &tuple);
 	}
 
 	/* require an IRQ and two registers */
@@ -270,71 +251,46 @@
 		goto cs_failed;
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		CS_CHECK(RequestIRQ,
-			pcmcia_request_irq(link->handle, &link->irq));
+			pcmcia_request_irq(link, &link->irq));
 	else
 		goto cs_failed;
 
 	CS_CHECK(RequestConfiguration,
-		pcmcia_request_configuration(link->handle, &link->conf));
+		pcmcia_request_configuration(link, &link->conf));
 
 	sprintf(dev->node.dev_name, driver_name);
 	dev->node.major = dev->node.minor = 0;
-	link->dev = &dev->node;
+	link->dev_node = &dev->node;
 
-	printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
-	       dev->node.dev_name, link->conf.ConfigIndex,
-	       link->conf.Vcc/10, link->conf.Vcc%10);
-	if (link->conf.Vpp1)
-		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+	printk(KERN_INFO "%s: index 0x%02x: ",
+	       dev->node.dev_name, link->conf.ConfigIndex);
+	if (link->conf.Vpp)
+		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
 	printk(", irq %d", link->irq.AssignedIRQ);
 	printk(", io 0x%04x-0x%04x", link->io.BasePort1,
 	       link->io.BasePort1+link->io.NumPorts1-1);
 	printk("\n");
 
-	link->state &= ~DEV_CONFIG_PENDING;
-
 	if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
 			< 0) {
 cs_failed:
 		printk("sl811_cs_config failed\n");
-		cs_error(link->handle, last_fn, last_ret);
+		cs_error(link, last_fn, last_ret);
 		sl811_cs_release(link);
-		link->state &= ~DEV_CONFIG_PENDING;
+		return  -ENODEV;
 	}
-}
-
-static int sl811_suspend(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state |= DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
 	return 0;
 }
 
-static int sl811_resume(struct pcmcia_device *dev)
-{
-	dev_link_t *link = dev_to_instance(dev);
-
-	link->state &= ~DEV_SUSPEND;
-	if (link->state & DEV_CONFIG)
-		pcmcia_request_configuration(link->handle, &link->conf);
-
-	return 0;
-}
-
-static int sl811_cs_attach(struct pcmcia_device *p_dev)
+static int sl811_cs_probe(struct pcmcia_device *link)
 {
 	local_info_t *local;
-	dev_link_t *link;
 
 	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local)
 		return -ENOMEM;
 	memset(local, 0, sizeof(local_info_t));
-	link = &local->link;
+	local->p_dev = link;
 	link->priv = local;
 
 	/* Initialize */
@@ -343,16 +299,9 @@
 	link->irq.Handler = NULL;
 
 	link->conf.Attributes = 0;
-	link->conf.Vcc = 33;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
-	link->handle = p_dev;
-	p_dev->instance = link;
-
-	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	sl811_cs_config(link);
-
-	return 0;
+	return sl811_cs_config(link);
 }
 
 static struct pcmcia_device_id sl811_ids[] = {
@@ -366,11 +315,9 @@
 	.drv		= {
 		.name	= (char *)driver_name,
 	},
-	.probe		= sl811_cs_attach,
+	.probe		= sl811_cs_probe,
 	.remove		= sl811_cs_detach,
 	.id_table	= sl811_ids,
-	.suspend	= sl811_suspend,
-	.resume		= sl811_resume,
 };
 
 /*====================================================================*/
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 4edb833..d225e11 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -50,6 +50,7 @@
 
 #include "../core/hcd.h"
 #include "uhci-hcd.h"
+#include "pci-quirks.h"
 
 /*
  * Version Information
@@ -100,9 +101,6 @@
 #include "uhci-q.c"
 #include "uhci-hub.c"
 
-extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-
 /*
  * Finish up a host controller reset and update the recorded state.
  */
@@ -117,8 +115,7 @@
 	for (port = 0; port < uhci->rh_numports; ++port)
 		outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
 
-	uhci->port_c_suspend = uhci->suspended_ports =
-			uhci->resuming_ports = 0;
+	uhci->port_c_suspend = uhci->resuming_ports = 0;
 	uhci->rh_state = UHCI_RH_RESET;
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
@@ -861,7 +858,7 @@
 
 static const struct pci_device_id uhci_pci_ids[] = { {
 	/* handle any USB UHCI controller */
-	PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0),
+	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0),
 	.driver_data =	(unsigned long) &uhci_driver,
 	}, { /* end: all zeroes */ }
 };
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 4a69c7e..d5c8f4d 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -415,7 +415,6 @@
 
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
-	unsigned long suspended_ports;
 	unsigned long resuming_ports;
 	unsigned long ports_timeout;		/* Time to stop signalling */
 
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 152971d..c8451d9 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -85,11 +85,10 @@
 {
 	int status;
 
-	if (test_bit(port, &uhci->suspended_ports)) {
+	if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
 		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
-		clear_bit(port, &uhci->suspended_ports);
-		clear_bit(port, &uhci->resuming_ports);
-		set_bit(port, &uhci->port_c_suspend);
+		if (test_bit(port, &uhci->resuming_ports))
+			set_bit(port, &uhci->port_c_suspend);
 
 		/* The controller won't actually turn off the RD bit until
 		 * it has had a chance to send a low-speed EOP sequence,
@@ -97,6 +96,7 @@
 		 * slightly longer for good luck. */
 		udelay(4);
 	}
+	clear_bit(port, &uhci->resuming_ports);
 }
 
 /* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -265,8 +265,6 @@
 			wPortChange |= USB_PORT_STAT_C_SUSPEND;
 			lstatus |= 1;
 		}
-		if (test_bit(port, &uhci->suspended_ports))
-			lstatus |= 2;
 		if (test_bit(port, &uhci->resuming_ports))
 			lstatus |= 4;
 
@@ -309,7 +307,6 @@
 
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			set_bit(port, &uhci->suspended_ports);
 			SET_RH_PORTSTAT(USBPORTSC_SUSP);
 			OK(0);
 		case USB_PORT_FEAT_RESET:
@@ -343,8 +340,11 @@
 			CLR_RH_PORTSTAT(USBPORTSC_PEC);
 			OK(0);
 		case USB_PORT_FEAT_SUSPEND:
-			if (test_bit(port, &uhci->suspended_ports) &&
-					!test_and_set_bit(port,
+			if (!(inw(port_addr) & USBPORTSC_SUSP)) {
+
+				/* Make certain the port isn't suspended */
+				uhci_finish_suspend(uhci, port, port_addr);
+			} else if (!test_and_set_bit(port,
 						&uhci->resuming_ports)) {
 				SET_RH_PORTSTAT(USBPORTSC_RD);
 
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 5246b35..650103b 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -200,45 +200,41 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called powermate.
 
-config USB_MTOUCH
-	tristate "MicroTouch USB Touchscreen Driver"
+config USB_TOUCHSCREEN
+	tristate "USB Touchscreen Driver"
 	depends on USB && INPUT
 	---help---
-	  Say Y here if you want to use a MicroTouch (Now 3M) USB 
-	  Touchscreen controller.
-
-	  See <file:Documentation/usb/mtouch.txt> for additional information.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mtouchusb.
-
-config USB_ITMTOUCH
-	tristate "ITM Touch USB Touchscreen Driver"
-	depends on USB && INPUT
-	---help---
-	  Say Y here if you want to use a ITM Touch USB
-	  Touchscreen controller.
-
-	  This touchscreen is used in LG 1510SF monitors.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called itmtouch.
-
-config USB_EGALAX
-	tristate "eGalax TouchKit USB Touchscreen Driver"
-	depends on USB && INPUT
-	---help---
-	  Say Y here if you want to use a eGalax TouchKit USB
-	  Touchscreen controller.
-
-	  The driver has been tested on a Xenarc 700TSV monitor
-	  with eGalax touchscreen.
+	  USB Touchscreen driver for:
+	  - eGalax Touchkit USB
+	  - PanJit TouchSet USB
+	  - 3M MicroTouch USB
+	  - ITM
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called touchkitusb.
+	  module will be called usbtouchscreen.
+
+config USB_TOUCHSCREEN_EGALAX
+	default y
+	bool "eGalax device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
+config USB_TOUCHSCREEN_PANJIT
+	default y
+	bool "PanJit device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
+config USB_TOUCHSCREEN_3M
+	default y
+	bool "3M/Microtouch device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
+
+config USB_TOUCHSCREEN_ITM
+	default y
+	bool "ITM device support" if EMBEDDED
+	depends on USB_TOUCHSCREEN
 
 config USB_YEALINK
 	tristate "Yealink usb-p1k voip phone"
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index d512d9f..7641145 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_USB_MTOUCH)	+= mtouchusb.o
 obj-$(CONFIG_USB_ITMTOUCH)	+= itmtouch.o
 obj-$(CONFIG_USB_EGALAX)	+= touchkitusb.o
+obj-$(CONFIG_USB_TOUCHSCREEN)	+= usbtouchscreen.o
 obj-$(CONFIG_USB_POWERMATE)	+= powermate.o
 obj-$(CONFIG_USB_WACOM)		+= wacom.o
 obj-$(CONFIG_USB_ACECAD)	+= acecad.o
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index d4bf170..f419bd8 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1372,6 +1372,11 @@
 		usb_kill_urb(hid->urbin);
 }
 
+#define USB_VENDOR_ID_PANJIT		0x134c
+
+#define USB_VENDOR_ID_SILVERCREST	0x062a
+#define USB_DEVICE_ID_SILVERCREST_KB	0x0201
+
 /*
  * Initialize all reports
  */
@@ -1655,9 +1660,12 @@
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 
@@ -1675,6 +1683,7 @@
 	{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
 
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
@@ -1701,6 +1710,11 @@
 	{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
 
+	{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
+
 	{ 0, 0 }
 };
 
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index 72e6986..d5c91ee 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -34,12 +34,6 @@
 
 #include "hid.h"
 
-/* Drivers' initializing functions */
-extern int hid_lgff_init(struct hid_device* hid);
-extern int hid_lg3d_init(struct hid_device* hid);
-extern int hid_pid_init(struct hid_device* hid);
-extern int hid_tmff_init(struct hid_device* hid);
-
 /*
  * This table contains pointers to initializers. To add support for new
  * devices, you need to add the USB vendor and product ids here.
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 4e1b784..9c62837 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -533,3 +533,8 @@
 		return hid->ff_event(hid, input, type, code, value);
 	return -ENOSYS;
 }
+
+int hid_lgff_init(struct hid_device* hid);
+int hid_tmff_init(struct hid_device* hid);
+int hid_pid_init(struct hid_device* hid);
+
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index b4a051b..3d91197 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -297,6 +297,8 @@
 			remote->data.bits_left -= 6;
 		} else {
 			err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+			remote->stage = 0;
+			return;
 		}
 
 		keyspan_load_tester(remote, 5);
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
new file mode 100644
index 0000000..e9a07c1
--- /dev/null
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -0,0 +1,605 @@
+/******************************************************************************
+ * usbtouchscreen.c
+ * Driver for USB Touchscreens, supporting those devices:
+ *  - eGalax Touchkit
+ *  - 3M/Microtouch
+ *  - ITM
+ *  - PanJit TouchSet
+ *
+ * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
+ * Copyright (C) by Todd E. Johnson (mtouchusb.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * Driver is based on touchkitusb.c
+ * - ITM parts are from itmtouch.c
+ * - 3M parts are from mtouchusb.c
+ * - PanJit parts are from an unmerged driver by Lanslott Gish
+ *
+ *****************************************************************************/
+
+//#define DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb_input.h>
+
+
+#define DRIVER_VERSION		"v0.3"
+#define DRIVER_AUTHOR		"Daniel Ritz <daniel.ritz@gmx.ch>"
+#define DRIVER_DESC		"USB Touchscreen Driver"
+
+static int swap_xy;
+module_param(swap_xy, bool, 0644);
+MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
+
+/* device specifc data/functions */
+struct usbtouch_usb;
+struct usbtouch_device_info {
+	int min_xc, max_xc;
+	int min_yc, max_yc;
+	int min_press, max_press;
+	int rept_size;
+	int flags;
+
+	void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+	int  (*read_data)   (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+	int  (*init)        (struct usbtouch_usb *usbtouch);
+};
+
+#define USBTOUCH_FLG_BUFFER	0x01
+
+
+/* a usbtouch device */
+struct usbtouch_usb {
+	unsigned char *data;
+	dma_addr_t data_dma;
+	unsigned char *buffer;
+	int buf_len;
+	struct urb *irq;
+	struct usb_device *udev;
+	struct input_dev *input;
+	struct usbtouch_device_info *type;
+	char name[128];
+	char phys[64];
+};
+
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+                                 struct pt_regs *regs, unsigned char *pkt, int len);
+
+/* device types */
+enum {
+	DEVTPYE_DUMMY = -1,
+	DEVTYPE_EGALAX,
+	DEVTYPE_PANJIT,
+	DEVTYPE_3M,
+	DEVTYPE_ITM,
+};
+
+static struct usb_device_id usbtouch_devices[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+	{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
+	{USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+	{USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
+	{USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
+	{USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
+	{USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+	{USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+	{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
+#endif
+
+	{}
+};
+
+
+/*****************************************************************************
+ * eGalax part
+ */
+
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+
+#define EGALAX_PKT_TYPE_MASK		0xFE
+#define EGALAX_PKT_TYPE_REPT		0x80
+#define EGALAX_PKT_TYPE_DIAG		0x0A
+
+static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
+		return 0;
+
+	*x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+	*y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+	*touch = pkt[0] & 0x01;
+
+	return 1;
+
+}
+
+static int egalax_get_pkt_len(unsigned char *buf)
+{
+	switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
+	case EGALAX_PKT_TYPE_REPT:
+		return 5;
+
+	case EGALAX_PKT_TYPE_DIAG:
+		return buf[1] + 2;
+	}
+
+	return 0;
+}
+
+static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
+                           unsigned char *pkt, int len)
+{
+	unsigned char *buffer;
+	int pkt_len, buf_len, pos;
+
+	/* if the buffer contains data, append */
+	if (unlikely(usbtouch->buf_len)) {
+		int tmp;
+
+		/* if only 1 byte in buffer, add another one to get length */
+		if (usbtouch->buf_len == 1)
+			usbtouch->buffer[1] = pkt[0];
+
+		pkt_len = egalax_get_pkt_len(usbtouch->buffer);
+
+		/* unknown packet: drop everything */
+		if (!pkt_len)
+			return;
+
+		/* append, process */
+		tmp = pkt_len - usbtouch->buf_len;
+		memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
+		usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+
+		buffer = pkt + tmp;
+		buf_len = len - tmp;
+	} else {
+		buffer = pkt;
+		buf_len = len;
+	}
+
+	/* only one byte left in buffer */
+	if (unlikely(buf_len == 1)) {
+		usbtouch->buffer[0] = buffer[0];
+		usbtouch->buf_len = 1;
+		return;
+	}
+
+	/* loop over the buffer */
+	pos = 0;
+	while (pos < buf_len) {
+		/* get packet len */
+		pkt_len = egalax_get_pkt_len(buffer + pos);
+
+		/* unknown packet: drop everything */
+		if (unlikely(!pkt_len))
+			return;
+
+		/* full packet: process */
+		if (likely(pkt_len <= buf_len)) {
+			usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+		} else {
+			/* incomplete packet: save in buffer */
+			memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+			usbtouch->buf_len = buf_len - pos;
+		}
+		pos += pkt_len;
+	}
+}
+#endif
+
+
+/*****************************************************************************
+ * PanJit Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	*x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+	*y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+	*touch = pkt[0] & 0x01;
+
+	return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * 3M/Microtouch Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+
+#define MTOUCHUSB_ASYNC_REPORT          1
+#define MTOUCHUSB_RESET                 7
+#define MTOUCHUSB_REQ_CTRLLR_ID         10
+
+static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	*x = (pkt[8] << 8) | pkt[7];
+	*y = (pkt[10] << 8) | pkt[9];
+	*touch = (pkt[2] & 0x40) ? 1 : 0;
+
+	return 1;
+}
+
+static int mtouch_init(struct usbtouch_usb *usbtouch)
+{
+	int ret;
+
+	ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+	                      MTOUCHUSB_RESET,
+	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
+	    __FUNCTION__, ret);
+	if (ret < 0)
+		return ret;
+
+	ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+	                      MTOUCHUSB_ASYNC_REPORT,
+	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	                      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+	dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+	    __FUNCTION__, ret);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * ITM Part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+	*x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+	*x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+	*press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F);
+	*touch = ~pkt[7] & 0x20;
+
+	return 1;
+}
+#endif
+
+
+/*****************************************************************************
+ * the different device descriptors
+ */
+static struct usbtouch_device_info usbtouch_dev_info[] = {
+#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+	[DEVTYPE_EGALAX] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x07ff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x07ff,
+		.rept_size	= 16,
+		.flags		= USBTOUCH_FLG_BUFFER,
+		.process_pkt	= egalax_process,
+		.read_data	= egalax_read_data,
+	},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+	[DEVTYPE_PANJIT] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x0fff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x0fff,
+		.rept_size	= 8,
+		.read_data	= panjit_read_data,
+	},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_3M
+	[DEVTYPE_3M] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x4000,
+		.min_yc		= 0x0,
+		.max_yc		= 0x4000,
+		.rept_size	= 11,
+		.read_data	= mtouch_read_data,
+		.init		= mtouch_init,
+	},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+	[DEVTYPE_ITM] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x0fff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x0fff,
+		.max_press	= 0xff,
+		.rept_size	= 8,
+		.read_data	= itm_read_data,
+	},
+#endif
+};
+
+
+/*****************************************************************************
+ * Generic Part
+ */
+static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
+                                 struct pt_regs *regs, unsigned char *pkt, int len)
+{
+	int x, y, touch, press;
+	struct usbtouch_device_info *type = usbtouch->type;
+
+	if (!type->read_data(pkt, &x, &y, &touch, &press))
+			return;
+
+	input_regs(usbtouch->input, regs);
+	input_report_key(usbtouch->input, BTN_TOUCH, touch);
+
+	if (swap_xy) {
+		input_report_abs(usbtouch->input, ABS_X, y);
+		input_report_abs(usbtouch->input, ABS_Y, x);
+	} else {
+		input_report_abs(usbtouch->input, ABS_X, x);
+		input_report_abs(usbtouch->input, ABS_Y, y);
+	}
+	if (type->max_press)
+		input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+	input_sync(usbtouch->input);
+}
+
+
+static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct usbtouch_usb *usbtouch = urb->context;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ETIMEDOUT:
+		/* this urb is timing out */
+		dbg("%s - urb timed out - was the device unplugged?",
+		    __FUNCTION__);
+		return;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+		    __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+		    __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	usbtouch->type->process_pkt(usbtouch, regs, usbtouch->data, urb->actual_length);
+
+exit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		err("%s - usb_submit_urb failed with result: %d",
+		    __FUNCTION__, retval);
+}
+
+static int usbtouch_open(struct input_dev *input)
+{
+	struct usbtouch_usb *usbtouch = input->private;
+
+	usbtouch->irq->dev = usbtouch->udev;
+
+	if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void usbtouch_close(struct input_dev *input)
+{
+	struct usbtouch_usb *usbtouch = input->private;
+
+	usb_kill_urb(usbtouch->irq);
+}
+
+
+static void usbtouch_free_buffers(struct usb_device *udev,
+				  struct usbtouch_usb *usbtouch)
+{
+	if (usbtouch->data)
+		usb_buffer_free(udev, usbtouch->type->rept_size,
+		                usbtouch->data, usbtouch->data_dma);
+	kfree(usbtouch->buffer);
+}
+
+
+static int usbtouch_probe(struct usb_interface *intf,
+			  const struct usb_device_id *id)
+{
+	struct usbtouch_usb *usbtouch;
+	struct input_dev *input_dev;
+	struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usbtouch_device_info *type;
+	int err;
+
+	interface = intf->cur_altsetting;
+	endpoint = &interface->endpoint[0].desc;
+
+	usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!usbtouch || !input_dev)
+		goto out_free;
+
+	type = &usbtouch_dev_info[id->driver_info];
+	usbtouch->type = type;
+	if (!type->process_pkt)
+		type->process_pkt = usbtouch_process_pkt;
+
+	usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
+	                                  SLAB_KERNEL, &usbtouch->data_dma);
+	if (!usbtouch->data)
+		goto out_free;
+
+	if (type->flags & USBTOUCH_FLG_BUFFER) {
+		usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL);
+		if (!usbtouch->buffer)
+			goto out_free_buffers;
+	}
+
+	usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!usbtouch->irq) {
+		dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+		goto out_free_buffers;
+	}
+
+	usbtouch->udev = udev;
+	usbtouch->input = input_dev;
+
+	if (udev->manufacturer)
+		strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
+
+	if (udev->product) {
+		if (udev->manufacturer)
+			strlcat(usbtouch->name, " ", sizeof(usbtouch->name));
+		strlcat(usbtouch->name, udev->product, sizeof(usbtouch->name));
+	}
+
+	if (!strlen(usbtouch->name))
+		snprintf(usbtouch->name, sizeof(usbtouch->name),
+			"USB Touchscreen %04x:%04x",
+			 le16_to_cpu(udev->descriptor.idVendor),
+			 le16_to_cpu(udev->descriptor.idProduct));
+
+	usb_make_path(udev, usbtouch->phys, sizeof(usbtouch->phys));
+	strlcpy(usbtouch->phys, "/input0", sizeof(usbtouch->phys));
+
+	input_dev->name = usbtouch->name;
+	input_dev->phys = usbtouch->phys;
+	usb_to_input_id(udev, &input_dev->id);
+	input_dev->cdev.dev = &intf->dev;
+	input_dev->private = usbtouch;
+	input_dev->open = usbtouch_open;
+	input_dev->close = usbtouch_close;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0);
+	if (type->max_press)
+		input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
+		                     type->max_press, 0, 0);
+
+	usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
+			 usb_rcvintpipe(usbtouch->udev, 0x81),
+			 usbtouch->data, type->rept_size,
+			 usbtouch_irq, usbtouch, endpoint->bInterval);
+
+	usbtouch->irq->transfer_dma = usbtouch->data_dma;
+	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* device specific init */
+	if (type->init) {
+		err = type->init(usbtouch);
+		if (err) {
+			dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+			goto out_free_buffers;
+		}
+	}
+
+	err = input_register_device(usbtouch->input);
+	if (err) {
+		dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+		goto out_free_buffers;
+	}
+
+	usb_set_intfdata(intf, usbtouch);
+
+	return 0;
+
+out_free_buffers:
+	usbtouch_free_buffers(udev, usbtouch);
+out_free:
+	input_free_device(input_dev);
+	kfree(usbtouch);
+	return -ENOMEM;
+}
+
+static void usbtouch_disconnect(struct usb_interface *intf)
+{
+	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
+
+	dbg("%s - called", __FUNCTION__);
+
+	if (!usbtouch)
+		return;
+
+	dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+	usb_set_intfdata(intf, NULL);
+	usb_kill_urb(usbtouch->irq);
+	input_unregister_device(usbtouch->input);
+	usb_free_urb(usbtouch->irq);
+	usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
+	kfree(usbtouch);
+}
+
+MODULE_DEVICE_TABLE(usb, usbtouch_devices);
+
+static struct usb_driver usbtouch_driver = {
+	.name		= "usbtouchscreen",
+	.probe		= usbtouch_probe,
+	.disconnect	= usbtouch_disconnect,
+	.id_table	= usbtouch_devices,
+};
+
+static int __init usbtouch_init(void)
+{
+	return usb_register(&usbtouch_driver);
+}
+
+static void __exit usbtouch_cleanup(void)
+{
+	usb_deregister(&usbtouch_driver);
+}
+
+module_init(usbtouch_init);
+module_exit(usbtouch_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("touchkitusb");
+MODULE_ALIAS("itmtouch");
+MODULE_ALIAS("mtouchusb");
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index d3e15df..cf84c60 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -9,7 +9,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2005 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2002-2006 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -56,6 +56,8 @@
  *		   - Merged wacom_intuos3_irq into wacom_intuos_irq
  *	v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
  *		   - Report Device IDs
+ *	v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ *		   - Minor data report fix
  */
 
 /*
@@ -78,7 +80,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.44"
+#define DRIVER_VERSION "v1.45"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -99,6 +101,8 @@
 	PL,
 	INTUOS,
 	INTUOS3,
+	INTUOS312,
+	INTUOS319,
 	CINTIQ,
 	MAX_TYPE
 };
@@ -127,7 +131,19 @@
 	char phys[32];
 };
 
+#define USB_REQ_GET_REPORT	0x01
 #define USB_REQ_SET_REPORT	0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+				unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(interface_to_usbdev(intf),
+		usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+		USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+		buf, size, 100);
+}
+
 static int usb_set_report(struct usb_interface *intf, unsigned char type,
 				unsigned char id, void *buf, int size)
 {
@@ -206,7 +222,8 @@
 			wacom->tool[1] = BTN_TOOL_PEN;
 			id = STYLUS_DEVICE_ID;
 		}
-		input_report_key(dev, wacom->tool[1], id); /* report in proximity for tool */
+		input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
+		input_report_abs(dev, ABS_MISC, id); /* report tool id */
 		input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
 		input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
 		input_report_abs(dev, ABS_PRESSURE, pressure);
@@ -239,7 +256,7 @@
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
 	struct input_dev *dev = wacom->dev;
-	int retval;
+	int retval, id;
 
 	switch (urb->status) {
 	case 0:
@@ -263,12 +280,15 @@
 
 	input_regs(dev, regs);
 	if (data[1] & 0x04) {
-		input_report_key(dev, BTN_TOOL_RUBBER, (data[1] & 0x20) ? ERASER_DEVICE_ID : 0);
+		input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
 		input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
+		id = ERASER_DEVICE_ID;
 	} else {
-		input_report_key(dev, BTN_TOOL_PEN, (data[1] & 0x20) ? STYLUS_DEVICE_ID : 0);
+		input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
 		input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+		id = STYLUS_DEVICE_ID;
 	}
+	input_report_abs(dev, ABS_MISC, id); /* report tool id */
 	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
 	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
 	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
@@ -312,7 +332,8 @@
 	}
 
 	input_regs(dev, regs);
-	input_report_key(dev, BTN_TOOL_PEN, STYLUS_DEVICE_ID);
+	input_report_key(dev, BTN_TOOL_PEN, 1);
+	input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
 	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
 	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
 	input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
@@ -350,6 +371,8 @@
 		goto exit;
 	}
 
+	if (data[0] == 99) return; /* for Volito tablets */
+
 	if (data[0] != 2) {
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 		goto exit;
@@ -374,10 +397,10 @@
 			case 2: /* Mouse with wheel */
 				input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
 				if (wacom->features->type == WACOM_G4) {
-					rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
-					input_report_rel(dev, REL_WHEEL, rw);
+					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+					input_report_rel(dev, REL_WHEEL, -rw);
 				} else
-					input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+					input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
 				/* fall through */
 
 			case 3: /* Mouse without wheel */
@@ -406,39 +429,27 @@
 		}
 	}
 
-	input_report_key(dev, wacom->tool[0], (data[1] & 0x10) ? id : 0);
+	if (data[1] & 0x10)
+		input_report_abs(dev, ABS_MISC, id); /* report tool id */
+	else
+		input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
+	input_report_key(dev, wacom->tool[0], data[1] & 0x10);
 	input_sync(dev);
 
 	/* send pad data */
 	if (wacom->features->type == WACOM_G4) {
-		/* fist time sending pad data */
-		if (wacom->tool[1] != BTN_TOOL_FINGER) {
-			wacom->id[1] = 0;
-			wacom->serial[1] = (data[7] & 0x38) >> 2;
-		}
-		if (data[7] & 0xf8) {
+		if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
+			wacom->id[1] = 1;
+			wacom->serial[1] = (data[7] & 0xf8);
 			input_report_key(dev, BTN_0, (data[7] & 0x40));
 			input_report_key(dev, BTN_4, (data[7] & 0x80));
-			if (((data[7] & 0x38) >> 2) == (wacom->serial[1] & 0x0e))
-				/* alter REL_WHEEL value so X apps can get it */
-				wacom->serial[1] += (wacom->serial[1] & 0x01) ? -1 : 1;
-			else
-				 wacom->serial[1] = (data[7] & 0x38 ) >> 2;
-
-			/* don't alter the value when there is no wheel event */
-			if (wacom->serial[1] == 1)
-				wacom->serial[1] = 0;
-			rw = wacom->serial[1];
-			rw = (rw & 0x08) ? -(rw & 0x07) : (rw & 0x07);
+			rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
 			input_report_rel(dev, REL_WHEEL, rw);
-			wacom->tool[1] = BTN_TOOL_FINGER;
-			wacom->id[1] = data[7] & 0xf8;
-			input_report_key(dev, wacom->tool[1], 0xf0);
+			input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
 			input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
 			wacom->id[1] = 0;
-			wacom->serial[1] = 0;
-			input_report_key(dev, wacom->tool[1], 0);
+			input_report_key(dev, BTN_TOOL_FINGER, 0);
 			input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
 		}
 		input_sync(dev);
@@ -516,21 +527,31 @@
 			default: /* Unknown tool */
 				wacom->tool[idx] = BTN_TOOL_PEN;
 		}
-		input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
-		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		input_sync(dev);
+		if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+				((wacom->features->type == INTUOS312)
+					|| (wacom->features->type == INTUOS319)))) {
+			input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+			input_report_key(dev, wacom->tool[idx], 1);
+			input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+			input_sync(dev);
+		}
 		return 1;
 	}
 
 	/* Exit report */
 	if ((data[1] & 0xfe) == 0x80) {
 		input_report_key(dev, wacom->tool[idx], 0);
+		input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
 		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 		input_sync(dev);
 		return 1;
 	}
 
-	return 0;
+	if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
+			|| (wacom->features->type == INTUOS319)))
+		return 1;
+	else
+		return 0;
 }
 
 static void wacom_intuos_general(struct urb *urb)
@@ -600,10 +621,9 @@
 	/* pad packets. Works as a second tool and is always in prox */
 	if (data[0] == 12) {
 		/* initiate the pad as a device */
-		if (wacom->tool[1] != BTN_TOOL_FINGER) {
+		if (wacom->tool[1] != BTN_TOOL_FINGER)
 			wacom->tool[1] = BTN_TOOL_FINGER;
-			input_report_key(dev, wacom->tool[1], 1);
-		}
+
 		input_report_key(dev, BTN_0, (data[5] & 0x01));
 		input_report_key(dev, BTN_1, (data[5] & 0x02));
 		input_report_key(dev, BTN_2, (data[5] & 0x04));
@@ -614,6 +634,11 @@
 		input_report_key(dev, BTN_7, (data[6] & 0x08));
 		input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
 		input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+		if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+			input_report_key(dev, wacom->tool[1], 1);
+		else
+			input_report_key(dev, wacom->tool[1], 0);
 		input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
 		input_sync(dev);
 		goto exit;
@@ -676,8 +701,8 @@
 			input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
 			input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
 			input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
-			input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1)
-						 - (data[8] & 0x01));
+			input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
+						 - ((data[8] & 0x02) >> 1));
 
 			/* I3 2D mouse side buttons */
 			if (wacom->features->type == INTUOS3) {
@@ -695,7 +720,8 @@
 		}
 	}
 
-	input_report_key(dev, wacom->tool[idx], wacom->id[idx]);
+	input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_key(dev, wacom->tool[idx], 1);
 	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	input_sync(dev);
 
@@ -733,7 +759,8 @@
 	{ "Wacom PL800",         8,   7220,  5780,  511, 32, PL,         wacom_pl_irq },
 	{ "Wacom PL700",         8,   6758,  5406,  511, 32, PL,	 wacom_pl_irq },
 	{ "Wacom PL510",         8,   6282,  4762,  511, 32, PL,	 wacom_pl_irq },
-	{ "Wacom PL710",         8,  34080, 27660,  511, 32, PL,	 wacom_pl_irq },
+	{ "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,	 wacom_pl_irq },
+	{ "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
 	{ "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,	 wacom_pl_irq },
 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PL,         wacom_ptu_irq },
 	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
@@ -744,6 +771,8 @@
 	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,    wacom_intuos_irq },
 	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,    wacom_intuos_irq },
 	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,    wacom_intuos_irq },
+	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312,  wacom_intuos_irq },
+	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319,  wacom_intuos_irq },
 	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,    wacom_intuos_irq },
 	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,     wacom_intuos_irq },
 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
@@ -779,6 +808,7 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
@@ -788,6 +818,8 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
@@ -820,7 +852,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct wacom *wacom;
 	struct input_dev *input_dev;
-	char rep_data[2] = {0x02, 0x02};
+	char rep_data[2], limit = 0;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -857,6 +889,7 @@
 	input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
+	input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
 
 	switch (wacom->features->type) {
 		case WACOM_G4:
@@ -875,6 +908,8 @@
 			break;
 
 		case INTUOS3:
+		case INTUOS312:
+		case INTUOS319:
 		case CINTIQ:
 			input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
 			input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
@@ -916,10 +951,13 @@
 
 	input_register_device(wacom->dev);
 
-	/* ask the tablet to report tablet data */
-	usb_set_report(intf, 3, 2, rep_data, 2);
-	/* repeat once (not sure why the first call often fails) */
-	usb_set_report(intf, 3, 2, rep_data, 2);
+	/* Ask the tablet to report tablet data. Repeat until it succeeds */
+	do {
+		rep_data[0] = 2;
+		rep_data[1] = 2;
+		usb_set_report(intf, 3, 2, rep_data, 2);
+		usb_get_report(intf, 3, 2, rep_data, 2);
+	} while (rep_data[1] != 2 && limit++ < 5);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 9d59b90..ccc5e82 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -381,6 +381,7 @@
 
 	for (i = 0; i < nents; i++) {
 		char		*buf;
+		unsigned	j;
 
 		buf = kzalloc (size, SLAB_KERNEL);
 		if (!buf) {
@@ -391,6 +392,16 @@
 		/* kmalloc pages are always physically contiguous! */
 		sg_init_one(&sg[i], buf, size);
 
+		switch (pattern) {
+		case 0:
+			/* already zeroed */
+			break;
+		case 1:
+			for (j = 0; j < size; j++)
+				*buf++ = (u8) (j % 63);
+			break;
+		}
+
 		if (vary) {
 			size += vary;
 			size %= max;
@@ -425,6 +436,8 @@
 		usb_sg_wait (req);
 		retval = req->status;
 
+		/* FIXME check resulting data pattern */
+
 		/* FIXME if endpoint halted, clear halt (and log) */
 	}
 
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 3094970..12b599a 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -37,7 +37,6 @@
 
 #include "usbnet.h"
 
-
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 
 #define AX_CMD_SET_SW_MII		0x06
@@ -109,7 +108,7 @@
 #define AX_EEPROM_MAGIC			0xdeadbeef
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
-struct ax8817x_data {
+struct asix_data {
 	u8 multi_filter[AX_MCAST_FILTER_SIZE];
 };
 
@@ -121,7 +120,7 @@
 	u16 res3;
 } __attribute__ ((packed));
 
-static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			    u16 size, void *data)
 {
 	return usb_control_msg(
@@ -136,7 +135,7 @@
 		USB_CTRL_GET_TIMEOUT);
 }
 
-static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 			     u16 size, void *data)
 {
 	return usb_control_msg(
@@ -151,19 +150,80 @@
 		USB_CTRL_SET_TIMEOUT);
 }
 
-static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
+static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
 
 	if (urb->status < 0)
-		printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
+		printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
 			urb->status);
 
 	kfree(req);
 	usb_free_urb(urb);
 }
 
-static void ax8817x_status(struct usbnet *dev, struct urb *urb)
+static inline int asix_set_sw_mii(struct usbnet *dev)
+{
+	int ret;
+	ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
+	if (ret < 0)
+		devdbg(dev, "Failed to enable software MII access");
+	return ret;
+}
+
+static inline int asix_set_hw_mii(struct usbnet *dev)
+{
+	int ret;
+	ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
+	if (ret < 0)
+		devdbg(dev, "Failed to enable hardware MII access");
+	return ret;
+}
+
+static inline int asix_get_phyid(struct usbnet *dev)
+{
+	int ret = 0;
+	void *buf;
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		goto out1;
+
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
+				    0, 0, 2, buf)) < 2) {
+		devdbg(dev, "Error reading PHYID register: %02x", ret);
+		goto out2;
+	}
+	ret = *((u8 *)buf + 1);
+out2:
+	kfree(buf);
+out1:
+	return ret;
+}
+
+static int asix_sw_reset(struct usbnet *dev, u8 flags)
+{
+	int ret;
+
+        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
+	if (ret < 0)
+		devdbg(dev,"Failed to send software reset: %02x", ret);
+
+	return ret;
+}
+
+static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
+{
+	int ret;
+
+	ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
+	if (ret < 0)
+                devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+
+	return ret;
+}
+
+static void asix_status(struct usbnet *dev, struct urb *urb)
 {
 	struct ax88172_int_data *event;
 	int link;
@@ -179,12 +239,12 @@
 			usbnet_defer_kevent (dev, EVENT_LINK_RESET );
 		} else
 			netif_carrier_off(dev->net);
-		devdbg(dev, "ax8817x - Link Status is: %d", link);
+		devdbg(dev, "Link Status is: %d", link);
 	}
 }
 
 static void
-ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 				    u16 size, void *data)
 {
 	struct usb_ctrlrequest *req;
@@ -211,7 +271,7 @@
 	usb_fill_control_urb(urb, dev->udev,
 			     usb_sndctrlpipe(dev->udev, 0),
 			     (void *)req, data, size,
-			     ax8817x_async_cmd_callback, req);
+			     asix_async_cmd_callback, req);
 
 	if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
 		deverr(dev, "Error submitting the control message: status=%d",
@@ -221,10 +281,10 @@
 	}
 }
 
-static void ax8817x_set_multicast(struct net_device *net)
+static void asix_set_multicast(struct net_device *net)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
+	struct asix_data *data = (struct asix_data *)&dev->data;
 	u8 rx_ctl = 0x8c;
 
 	if (net->flags & IFF_PROMISC) {
@@ -255,53 +315,51 @@
 			mc_list = mc_list->next;
 		}
 
-		ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+		asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
 				   AX_MCAST_FILTER_SIZE, data->multi_filter);
 
 		rx_ctl |= 0x10;
 	}
 
-	ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+	asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
 }
 
-static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u16 res;
-	u8 buf[1];
 
-	ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
-	ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
+	asix_set_sw_mii(dev);
+	asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id,
 				(__u16)loc, 2, (u16 *)&res);
-	ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+	asix_set_hw_mii(dev);
 
 	return res & 0xffff;
 }
 
 /* same as above, but converts resulting value to cpu byte order */
-static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
+static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
 {
-	return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc));
+	return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
 }
 
 static void
-ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u16 res = val;
-	u8 buf[1];
 
-	ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
-	ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
+	asix_set_sw_mii(dev);
+	asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
 				(__u16)loc, 2, (u16 *)&res);
-	ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
+	asix_set_hw_mii(dev);
 }
 
 /* same as above, but converts new value to le16 byte order before writing */
 static void
-ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
 {
-	ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
+	asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
 }
 
 static int ax88172_link_reset(struct usbnet *dev)
@@ -312,23 +370,23 @@
 	u8 mode;
 
 	mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
-	lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-	adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+	lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+	adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
 	res = mii_nway_result(lpa|adv);
 	if (res & LPA_DUPLEX)
 		mode |= AX_MEDIUM_FULL_DUPLEX;
-	ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+	asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
 
 	return 0;
 }
 
 static void
-ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
 	struct usbnet *dev = netdev_priv(net);
 	u8 opt;
 
-	if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
+	if (asix_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
 		wolinfo->supported = 0;
 		wolinfo->wolopts = 0;
 		return;
@@ -344,7 +402,7 @@
 }
 
 static int
-ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
+asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
 	struct usbnet *dev = netdev_priv(net);
 	u8 opt = 0;
@@ -357,19 +415,19 @@
 	if (opt != 0)
 		opt |= AX_MONITOR_MODE;
 
-	if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
+	if (asix_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE,
 			      opt, 0, 0, &buf) < 0)
 		return -EINVAL;
 
 	return 0;
 }
 
-static int ax8817x_get_eeprom_len(struct net_device *net)
+static int asix_get_eeprom_len(struct net_device *net)
 {
 	return AX_EEPROM_LEN;
 }
 
-static int ax8817x_get_eeprom(struct net_device *net,
+static int asix_get_eeprom(struct net_device *net,
 			      struct ethtool_eeprom *eeprom, u8 *data)
 {
 	struct usbnet *dev = netdev_priv(net);
@@ -386,14 +444,14 @@
 
 	/* ax8817x returns 2 bytes from eeprom on read */
 	for (i=0; i < eeprom->len / 2; i++) {
-		if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+		if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
 			eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
 			return -EINVAL;
 	}
 	return 0;
 }
 
-static void ax8817x_get_drvinfo (struct net_device *net,
+static void asix_get_drvinfo (struct net_device *net,
 				 struct ethtool_drvinfo *info)
 {
 	/* Inherit standard device info */
@@ -401,14 +459,14 @@
 	info->eedump_len = 0x3e;
 }
 
-static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
 	struct usbnet *dev = netdev_priv(net);
 
 	return mii_ethtool_gset(&dev->mii,cmd);
 }
 
-static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
+static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
 	struct usbnet *dev = netdev_priv(net);
 
@@ -418,27 +476,27 @@
 /* We need to override some ethtool_ops so we require our
    own structure so we don't interfere with other usbnet
    devices that may be connected at the same time. */
-static struct ethtool_ops ax8817x_ethtool_ops = {
-	.get_drvinfo		= ax8817x_get_drvinfo,
+static struct ethtool_ops ax88172_ethtool_ops = {
+	.get_drvinfo		= asix_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
-	.get_wol		= ax8817x_get_wol,
-	.set_wol		= ax8817x_set_wol,
-	.get_eeprom_len		= ax8817x_get_eeprom_len,
-	.get_eeprom		= ax8817x_get_eeprom,
-	.get_settings		= ax8817x_get_settings,
-	.set_settings		= ax8817x_set_settings,
+	.get_wol		= asix_get_wol,
+	.set_wol		= asix_set_wol,
+	.get_eeprom_len		= asix_get_eeprom_len,
+	.get_eeprom		= asix_get_eeprom,
+	.get_settings		= asix_get_settings,
+	.set_settings		= asix_set_settings,
 };
 
-static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
 {
 	struct usbnet *dev = netdev_priv(net);
 
 	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
 }
 
-static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
+static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret = 0;
 	void *buf;
@@ -455,55 +513,39 @@
 
 	/* Toggle the GPIOs in a manufacturer/model specific way */
 	for (i = 2; i >= 0; i--) {
-		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+		if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
 					(gpio_bits >> (i * 8)) & 0xff, 0, 0,
 					buf)) < 0)
 			goto out2;
 		msleep(5);
 	}
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
-				0x80, 0, 0, buf)) < 0) {
-		dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+	if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
 		goto out2;
-	}
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
-	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID,
+	if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
 				0, 0, 6, buf)) < 0) {
 		dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
 		goto out2;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-	/* Get the PHY id */
-	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
-				0, 0, 2, buf)) < 0) {
-		dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
-		goto out2;
-	} else if (ret < 2) {
-		/* this should always return 2 bytes */
-		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
-				ret);
-		ret = -EIO;
-		goto out2;
-	}
-
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
-	dev->mii.mdio_read = ax8817x_mdio_read;
-	dev->mii.mdio_write = ax8817x_mdio_write;
+	dev->mii.mdio_read = asix_mdio_read;
+	dev->mii.mdio_write = asix_mdio_write;
 	dev->mii.phy_id_mask = 0x3f;
 	dev->mii.reg_num_mask = 0x1f;
-	dev->mii.phy_id = *((u8 *)buf + 1);
-	dev->net->do_ioctl = ax8817x_ioctl;
+	dev->mii.phy_id = asix_get_phyid(dev);
+	dev->net->do_ioctl = asix_ioctl;
 
-	dev->net->set_multicast_list = ax8817x_set_multicast;
-	dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+	dev->net->set_multicast_list = asix_set_multicast;
+	dev->net->ethtool_ops = &ax88172_ethtool_ops;
 
-	ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-	ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 		ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
 	mii_nway_restart(&dev->mii);
 
@@ -515,16 +557,16 @@
 }
 
 static struct ethtool_ops ax88772_ethtool_ops = {
-	.get_drvinfo		= ax8817x_get_drvinfo,
+	.get_drvinfo		= asix_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_msglevel		= usbnet_get_msglevel,
 	.set_msglevel		= usbnet_set_msglevel,
-	.get_wol		= ax8817x_get_wol,
-	.set_wol		= ax8817x_set_wol,
-	.get_eeprom_len		= ax8817x_get_eeprom_len,
-	.get_eeprom		= ax8817x_get_eeprom,
-	.get_settings		= ax8817x_get_settings,
-	.set_settings		= ax8817x_set_settings,
+	.get_wol		= asix_get_wol,
+	.set_wol		= asix_set_wol,
+	.get_eeprom_len		= asix_get_eeprom_len,
+	.get_eeprom		= asix_get_eeprom,
+	.get_settings		= asix_get_settings,
+	.set_settings		= asix_set_settings,
 };
 
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -541,62 +583,45 @@
 		goto out1;
 	}
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
 				     0x00B0, 0, 0, buf)) < 0)
 		goto out2;
 
 	msleep(5);
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
+	if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
 				0x0001, 0, 0, buf)) < 0) {
 		dbg("Select PHY #1 failed: %d", ret);
 		goto out2;
 	}
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD,
-				0, 0, buf)) < 0) {
-		dbg("Failed to power down internal PHY: %d", ret);
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD)) < 0)
 		goto out2;
-	}
 
 	msleep(150);
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR,
-				0, 0, buf)) < 0) {
-		dbg("Failed to perform software reset: %d", ret);
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0)
 		goto out2;
-	}
 
 	msleep(150);
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
-	     			AX_SWRESET_IPRL | AX_SWRESET_PRL,
-				0, 0, buf)) < 0) {
-		dbg("Failed to set Internal/External PHY reset control: %d",
-					ret);
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
 		goto out2;
-	}
 
 	msleep(150);
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
-				0x0000, 0, 0, buf)) < 0) {
-		dbg("Failed to reset RX_CTL: %d", ret);
+	if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
 		goto out2;
-	}
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
-	if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+	if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
 				0, 0, ETH_ALEN, buf)) < 0) {
 		dbg("Failed to read MAC address: %d", ret);
 		goto out2;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII,
-				0, 0, 0, buf)) < 0) {
-		dbg("Enabling software MII failed: %d", ret);
+	if ((ret = asix_set_sw_mii(dev)) < 0)
 		goto out2;
-	}
 
-	if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG,
+	if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
 	      			0x0010, 2, 2, buf)) < 0)
 			|| (*((u16 *)buf) != 0x003b)) {
 		dbg("Read PHY register 2 must be 0x3b00: %d", ret);
@@ -605,74 +630,49 @@
 
 	/* Initialize MII structure */
 	dev->mii.dev = dev->net;
-	dev->mii.mdio_read = ax8817x_mdio_read;
-	dev->mii.mdio_write = ax8817x_mdio_write;
+	dev->mii.mdio_read = asix_mdio_read;
+	dev->mii.mdio_write = asix_mdio_write;
 	dev->mii.phy_id_mask = 0xff;
 	dev->mii.reg_num_mask = 0xff;
-	dev->net->do_ioctl = ax8817x_ioctl;
+	dev->net->do_ioctl = asix_ioctl;
+	dev->mii.phy_id = asix_get_phyid(dev);
 
-	/* Get the PHY id */
-	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID,
-			0, 0, 2, buf)) < 0) {
-		dbg("Error reading PHY ID: %02x", ret);
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
 		goto out2;
-	} else if (ret < 2) {
-		/* this should always return 2 bytes */
-		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
-		    ret);
-		ret = -EIO;
-		goto out2;
-	}
-	dev->mii.phy_id = *((u8 *)buf + 1);
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL,
-				0, 0, buf)) < 0) {
-		dbg("Set external PHY reset pin level: %d", ret);
-		goto out2;
-	}
-	msleep(150);
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET,
-	     			AX_SWRESET_IPRL | AX_SWRESET_PRL,
-				0, 0, buf)) < 0) {
-		dbg("Set Internal/External PHY reset control: %d", ret);
-		goto out2;
-	}
 	msleep(150);
 
+	if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0)
+		goto out2;
 
-	dev->net->set_multicast_list = ax8817x_set_multicast;
+	msleep(150);
+
+	dev->net->set_multicast_list = asix_set_multicast;
 	dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-	ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-	ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+	asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
 			ADVERTISE_ALL | ADVERTISE_CSMA);
 	mii_nway_restart(&dev->mii);
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
 				AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
 		dbg("Write medium mode register: %d", ret);
 		goto out2;
 	}
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+	if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
 				AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
 				AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
 		dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
 		goto out2;
 	}
-	if ((ret =
-	     ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
-		dbg("Failed to set hardware MII: %02x", ret);
+	if ((ret = asix_set_hw_mii(dev)) < 0)
 		goto out2;
-	}
 
 	/* Set RX_CTL to default values with 2k buffer, and enable cactus */
-	if ((ret =
-	     ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
-			       buf)) < 0) {
-		dbg("Reset RX_CTL failed: %d", ret);
+	if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
 		goto out2;
-	}
 
 	kfree(buf);
 
@@ -794,23 +794,23 @@
 	u16 mode;
 
 	mode = AX88772_MEDIUM_DEFAULT;
-	lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-	adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+	lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
+	adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
 	res = mii_nway_result(lpa|adv);
 
 	if ((res & LPA_DUPLEX) == 0)
 		mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
 	if ((res & LPA_100) == 0)
 		mode &= ~AX88772_MEDIUM_100MB;
-	ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+	asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
 
 	return 0;
 }
 
 static const struct driver_info ax8817x_info = {
 	.description = "ASIX AX8817x USB 2.0 Ethernet",
-	.bind = ax8817x_bind,
-	.status = ax8817x_status,
+	.bind = ax88172_bind,
+	.status = asix_status,
 	.link_reset = ax88172_link_reset,
 	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
@@ -819,8 +819,8 @@
 
 static const struct driver_info dlink_dub_e100_info = {
 	.description = "DLink DUB-E100 USB Ethernet",
-	.bind = ax8817x_bind,
-	.status = ax8817x_status,
+	.bind = ax88172_bind,
+	.status = asix_status,
 	.link_reset = ax88172_link_reset,
 	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
@@ -829,8 +829,8 @@
 
 static const struct driver_info netgear_fa120_info = {
 	.description = "Netgear FA-120 USB Ethernet",
-	.bind = ax8817x_bind,
-	.status = ax8817x_status,
+	.bind = ax88172_bind,
+	.status = asix_status,
 	.link_reset = ax88172_link_reset,
 	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
@@ -839,8 +839,8 @@
 
 static const struct driver_info hawking_uf200_info = {
 	.description = "Hawking UF200 USB Ethernet",
-	.bind = ax8817x_bind,
-	.status = ax8817x_status,
+	.bind = ax88172_bind,
+	.status = asix_status,
 	.link_reset = ax88172_link_reset,
 	.reset = ax88172_link_reset,
 	.flags =  FLAG_ETHER,
@@ -850,13 +850,12 @@
 static const struct driver_info ax88772_info = {
 	.description = "ASIX AX88772 USB 2.0 Ethernet",
 	.bind = ax88772_bind,
-	.status = ax8817x_status,
+	.status = asix_status,
 	.link_reset = ax88772_link_reset,
 	.reset = ax88772_link_reset,
 	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
 	.rx_fixup = ax88772_rx_fixup,
 	.tx_fixup = ax88772_tx_fixup,
-	.data = 0x00130103,
 };
 
 static const struct usb_device_id	products [] = {
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 5b66756..2deb4c0 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -262,7 +262,7 @@
 	usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
 			     usb_sndctrlpipe(pegasus->usb, 0),
 			     (char *) &pegasus->dr,
-			     &tmp, 1, ctrl_callback, pegasus);
+			     tmp, 1, ctrl_callback, pegasus);
 
 	add_wait_queue(&pegasus->ctrl_wait, &wait);
 	set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 49991ac..94ddfe1 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -39,6 +39,20 @@
  * RNDIS is NDIS remoted over USB.  It's a MSFT variant of CDC ACM ... of
  * course ACM was intended for modems, not Ethernet links!  USB's standard
  * for Ethernet links is "CDC Ethernet", which is significantly simpler.
+ *
+ * NOTE that Microsoft's "RNDIS 1.0" specification is incomplete.  Issues
+ * include:
+ *    - Power management in particular relies on information that's scattered
+ *	through other documentation, and which is incomplete or incorrect even
+ *	there.
+ *    - There are various undocumented protocol requirements, such as the
+ *	need to send unused garbage in control-OUT messages.
+ *    - In some cases, MS-Windows will emit undocumented requests; this
+ *	matters more to peripheral implementations than host ones.
+ *
+ * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in
+ * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and
+ * currently rare) "Ethernet Emulation Model" (EEM).
  */
 
 /*
@@ -72,17 +86,17 @@
  */
 #define RNDIS_MSG_PACKET	ccpu2(0x00000001)	/* 1-N packets */
 #define RNDIS_MSG_INIT		ccpu2(0x00000002)
-#define RNDIS_MSG_INIT_C 	(RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_INIT_C	(RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
 #define RNDIS_MSG_HALT		ccpu2(0x00000003)
 #define RNDIS_MSG_QUERY		ccpu2(0x00000004)
-#define RNDIS_MSG_QUERY_C 	(RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_QUERY_C	(RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
 #define RNDIS_MSG_SET		ccpu2(0x00000005)
-#define RNDIS_MSG_SET_C 	(RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_SET_C		(RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
 #define RNDIS_MSG_RESET		ccpu2(0x00000006)
-#define RNDIS_MSG_RESET_C 	(RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_RESET_C	(RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
 #define RNDIS_MSG_INDICATE	ccpu2(0x00000007)
 #define RNDIS_MSG_KEEPALIVE	ccpu2(0x00000008)
-#define RNDIS_MSG_KEEPALIVE_C 	(RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
+#define RNDIS_MSG_KEEPALIVE_C	(RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
 
 /* codes for "status" field of completion messages */
 #define	RNDIS_STATUS_SUCCESS		ccpu2(0x00000000)
@@ -596,13 +610,13 @@
 
 static int __init rndis_init(void)
 {
- 	return usb_register(&rndis_driver);
+	return usb_register(&rndis_driver);
 }
 module_init(rndis_init);
 
 static void __exit rndis_exit(void)
 {
- 	usb_deregister(&rndis_driver);
+	usb_deregister(&rndis_driver);
 }
 module_exit(rndis_exit);
 
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 5a8a2c9..f96b73f 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -158,6 +158,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ftdi_sio.
 
+config USB_SERIAL_FUNSOFT
+	tristate "USB Fundamental Software Dongle Driver"
+	depends on USB_SERIAL
+	---help---
+	  Say Y here if you want to use the Fundamental Software dongle.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called funsoft.
+
 config USB_SERIAL_VISOR
 	tristate "USB Handspring Visor / Palm m50x / Sony Clie Driver"
 	depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index f7fe417..93c2124 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI)		+= io_ti.o
 obj-$(CONFIG_USB_SERIAL_EMPEG)			+= empeg.o
 obj-$(CONFIG_USB_SERIAL_FTDI_SIO)		+= ftdi_sio.o
+obj-$(CONFIG_USB_SERIAL_FUNSOFT)		+= funsoft.o
 obj-$(CONFIG_USB_SERIAL_GARMIN)			+= garmin_gps.o
 obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 167f8ec..8023bb7 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -54,7 +54,7 @@
  * serial.c code, except that the specifier is "ttyUSB" instead
  * of "ttyS".
  */
-static int __init usb_console_setup(struct console *co, char *options)
+static int usb_console_setup(struct console *co, char *options)
 {
 	struct usbcons_info *info = &usbcons_info;
 	int baud = 9600;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f3af81b..8215120 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -308,6 +308,7 @@
 
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
@@ -489,10 +490,14 @@
 	{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
 	{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
 	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8da773c..2c55a5e 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -39,6 +39,9 @@
 /* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
 #define FTDI_TTUSB_PID 0xFF20 /* Product Id */
 
+/* iPlus device */
+#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+
 /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
 /* they use the ftdi chipset for the USB interface and the vendor id is the same */
 #define FTDI_XF_632_PID 0xFC08	/* 632: 16x2 Character Display */
@@ -153,6 +156,11 @@
 #define ICOM_ID1_PID            0x0004
 
 /*
+ * ASK.fr devices
+ */
+#define FTDI_ASK_RDR400_PID	0xC991	/* ASK RDR 400 series card reader */
+
+/*
  * DSS-20 Sync Station for Sony Ericsson P800
  */
  
@@ -399,6 +407,26 @@
 #define FTDI_WESTREX_MODEL_777_PID	0xDC00	/* Model 777 */
 #define FTDI_WESTREX_MODEL_8900F_PID	0xDC01	/* Model 8900F */
 
+/*
+ * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
+ */
+#define FTDI_RRCIRKITS_LOCOBUFFER_PID	0xc7d0	/* LocoBuffer USB */
+
+/*
+ * Eclo (http://www.eclo.pt/) product IDs.
+ * PID 0xEA90 submitted by Martin Grill.
+ */
+#define FTDI_ECLO_COM_1WIRE_PID	0xEA90	/* COM to 1-Wire USB adaptor */
+
+/*
+ * Papouch products (http://www.papouch.com/)
+ * Submitted by Folkert van Heusden
+ */
+
+#define PAPOUCH_VID			0x5050	/* Vendor ID */
+#define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
+
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
new file mode 100644
index 0000000..803721b
--- /dev/null
+++ b/drivers/usb/serial/funsoft.c
@@ -0,0 +1,65 @@
+/*
+ * Funsoft Serial USB driver
+ *
+ * Copyright (C) 2006 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x1404, 0xcddc) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver funsoft_driver = {
+	.name =		"funsoft",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.no_dynamic_id = 	1,
+};
+
+static struct usb_serial_driver funsoft_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"funsoft",
+	},
+	.id_table =		id_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		NUM_DONT_CARE,
+	.num_bulk_out =		NUM_DONT_CARE,
+	.num_ports =		1,
+};
+
+static int __init funsoft_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&funsoft_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&funsoft_driver);
+	if (retval)
+		usb_serial_deregister(&funsoft_device);
+	return retval;
+}
+
+static void __exit funsoft_exit(void)
+{
+	usb_deregister(&funsoft_driver);
+	usb_serial_deregister(&funsoft_device);
+}
+
+module_init(funsoft_init);
+module_exit(funsoft_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 495db57..5cf2b80 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -28,6 +28,7 @@
   2005-09-10  v0.4.3 added HUAWEI E600 card and Audiovox AirCard
   2005-09-20  v0.4.4 increased recv buffer size: the card sometimes
                      wants to send >2000 bytes.
+  2006-04-10  v0.4.2 fixed two array overrun errors :-/
 
   Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
 
@@ -582,14 +583,14 @@
 	portdata = usb_get_serial_port_data(port);
 
 	/* Do indat endpoints first */
-	for (j = 0; j <= N_IN_URB; ++j) {
+	for (j = 0; j < N_IN_URB; ++j) {
 		portdata->in_urbs[j] = option_setup_urb (serial,
                   port->bulk_in_endpointAddress, USB_DIR_IN, port,
                   portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
 	}
 
 	/* outdat endpoints */
-	for (j = 0; j <= N_OUT_URB; ++j) {
+	for (j = 0; j < N_OUT_URB; ++j) {
 		portdata->out_urbs[j] = option_setup_urb (serial,
                   port->bulk_out_endpointAddress, USB_DIR_OUT, port,
                   portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index b3014fd..c96714b 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -61,6 +61,7 @@
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
 	{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
 	{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+	{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
 	{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
 	{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
@@ -78,6 +79,7 @@
 	{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
 	{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
 	{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
+	{ USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 77901d1..7f29e81 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -26,6 +26,7 @@
 
 #define ITEGNO_VENDOR_ID	0x0eba
 #define ITEGNO_PRODUCT_ID	0x1080
+#define ITEGNO_PRODUCT_ID_2080	0x2080
 
 #define MA620_VENDOR_ID		0x0df7
 #define MA620_PRODUCT_ID	0x0620
@@ -79,3 +80,7 @@
 /* USB GSM cable from Speed Dragon Multimedia, Ltd */
 #define SPEEDDRAGON_VENDOR_ID	0x0e55
 #define SPEEDDRAGON_PRODUCT_ID	0x110b
+
+/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
+#define OTI_VENDOR_ID	0x0ea0
+#define OTI_PRODUCT_ID	0x6858
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 097f4e8..071f86a 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -27,10 +27,10 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
-#include <asm/semaphore.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
 #include "pl2303.h"
@@ -192,7 +192,7 @@
 	if (!port)
 		return -ENODEV;
 
-	if (down_interruptible(&port->sem))
+	if (mutex_lock_interruptible(&port->mutex))
 		return -ERESTARTSYS;
 	 
 	++port->open_count;
@@ -219,7 +219,7 @@
 			goto bailout_module_put;
 	}
 
-	up(&port->sem);
+	mutex_unlock(&port->mutex);
 	return 0;
 
 bailout_module_put:
@@ -227,7 +227,7 @@
 bailout_kref_put:
 	kref_put(&serial->kref, destroy_serial);
 	port->open_count = 0;
-	up(&port->sem);
+	mutex_unlock(&port->mutex);
 	return retval;
 }
 
@@ -240,10 +240,10 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	down(&port->sem);
+	mutex_lock(&port->mutex);
 
 	if (port->open_count == 0) {
-		up(&port->sem);
+		mutex_unlock(&port->mutex);
 		return;
 	}
 
@@ -262,7 +262,7 @@
 		module_put(port->serial->type->driver.owner);
 	}
 
-	up(&port->sem);
+	mutex_unlock(&port->mutex);
 	kref_put(&port->serial->kref, destroy_serial);
 }
 
@@ -783,7 +783,7 @@
 		port->number = i + serial->minor;
 		port->serial = serial;
 		spin_lock_init(&port->lock);
-		sema_init(&port->sem, 1);
+		mutex_init(&port->mutex);
 		INIT_WORK(&port->work, usb_serial_port_softint, port);
 		serial->port[i] = port;
 	}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index d7d27c3..dc89d87 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,7 +16,7 @@
 
 #include <linux/config.h>
 #include <linux/kref.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
 #define SERIAL_TTY_MINORS	255	/* loads of devices :) */
@@ -31,7 +31,7 @@
  * @serial: pointer back to the struct usb_serial owner of this port.
  * @tty: pointer to the corresponding tty for this port.
  * @lock: spinlock to grab when updating portions of this structure.
- * @sem: semaphore used to synchronize serial_open() and serial_close()
+ * @mutex: mutex used to synchronize serial_open() and serial_close()
  *	access for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
@@ -63,7 +63,7 @@
 	struct usb_serial *	serial;
 	struct tty_struct *	tty;
 	spinlock_t		lock;
-	struct semaphore        sem;
+	struct mutex            mutex;
 	unsigned char		number;
 
 	unsigned char *		interrupt_in_buffer;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 557411c..f806553 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -508,6 +508,7 @@
 	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
 	err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
 	err("%s: please contact support@connecttech.com\n", serial->type->description);
+	kfree(result);
 	return -ENODEV;
 
 no_command_private:
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 92be101..be9eec2 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -48,7 +48,8 @@
 
 config USB_STORAGE_ISD200
 	bool "ISD-200 USB/ATA Bridge support"
-	depends on USB_STORAGE && BLK_DEV_IDE
+	depends on USB_STORAGE
+	depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
 	---help---
 	  Say Y here if you want to use USB Mass Store devices based
 	  on the In-Systems Design ISD-200 USB/ATA bridge.
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c4a9dcf..aec5ea8 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -411,7 +411,7 @@
 UNUSUAL_DEV(  0x0525, 0xa140, 0x0100, 0x0100,
 		"Iomega",
 		"USB Clik! 40",
-		US_SC_8070, US_PR_BULK, NULL,
+		US_SC_8070, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Yakumo Mega Image 37
@@ -773,6 +773,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+/* Reported by Olivier Blondeau <zeitoun@gmail.com> */
+UNUSUAL_DEV(  0x0727, 0x0306, 0x0100, 0x0100,
+		"ATMEL",
+		"SND1 Storage",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE),
+
 /* Submitted by Roman Hodek <roman@hodek.net> */
 UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200,
 		"Sandisk",
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f87c017..4587087 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -400,6 +400,8 @@
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Asiliant 69030 chipset
 
 config FB_IMSTT
 	bool "IMS Twin Turbo display support"
@@ -961,7 +963,7 @@
 
 config FB_ATY
 	tristate "ATI Mach64 display support" if PCI || ATARI
-	depends on FB
+	depends on FB && !SPARC32
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index b39e72d..d9d7d3c 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3400,7 +3400,7 @@
 	struct atyfb_par *par;
 	int i, rc = -ENOMEM;
 
-	for (i = ARRAY_SIZE(aty_chips); i >= 0; i--)
+	for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
 		if (pdev->device == aty_chips[i].pci_id)
 			break;
 
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 9a6b5b3..387a18a 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2265,7 +2265,7 @@
 };
 
 
-static int radeonfb_pci_register (struct pci_dev *pdev,
+static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
 	struct fb_info *info;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 944855b..372aa17 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -435,6 +435,11 @@
 			depth = info->var.green.length;
 	}
 
+	if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+		/* assume console colormap */
+		depth = 4;
+	}
+
 	if (depth >= 8) {
 		switch (info->fix.visual) {
 		case FB_VISUAL_TRUECOLOR:
@@ -669,13 +674,19 @@
 		total_size = info->fix.smem_len;
 
 	if (p > total_size)
-		return 0;
+		return -EFBIG;
 
-	if (count >= total_size)
+	if (count > total_size) {
+		err = -EFBIG;
 		count = total_size;
+	}
 
-	if (count + p > total_size)
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
 		count = total_size - p;
+	}
 
 	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
 			 GFP_KERNEL);
@@ -717,7 +728,7 @@
 
 	kfree(buffer);
 
-	return (err) ? err : cnt;
+	return (cnt) ? cnt : err;
 }
 
 #ifdef CONFIG_KMOD
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index b72b052..34e0739 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -305,94 +305,6 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
 }
 
-/* Format for cmap is "%02x%c%4x%4x%4x\n" */
-/* %02x entry %c transp %4x red %4x blue %4x green \n */
-/* 256 rows at 16 chars equals 4096, the normal page size */
-/* the code will automatically adjust for different page sizes */
-static ssize_t store_cmap(struct class_device *class_device, const char *buf,
-			  size_t count)
-{
-	struct fb_info *fb_info = class_get_devdata(class_device);
-	int rc, i, start, length, transp = 0;
-
-	if ((count > PAGE_SIZE) || ((count % 16) != 0))
-		return -EINVAL;
-
-	if (!fb_info->fbops->fb_setcolreg && !fb_info->fbops->fb_setcmap)
-		return -EINVAL;
-
-	sscanf(buf, "%02x", &start);
-	length = count / 16;
-
-	for (i = 0; i < length; i++)
-		if (buf[i * 16 + 2] != ' ')
-			transp = 1;
-
-	/* If we can batch, do it */
-	if (fb_info->fbops->fb_setcmap && length > 1) {
-		struct fb_cmap umap;
-
-		memset(&umap, 0, sizeof(umap));
-		if ((rc = fb_alloc_cmap(&umap, length, transp)))
-			return rc;
-
-		umap.start = start;
-		for (i = 0; i < length; i++) {
-			sscanf(&buf[i * 16 +  3], "%4hx", &umap.red[i]);
-			sscanf(&buf[i * 16 +  7], "%4hx", &umap.blue[i]);
-			sscanf(&buf[i * 16 + 11], "%4hx", &umap.green[i]);
-			if (transp)
-				umap.transp[i] = (buf[i * 16 +  2] != ' ');
-		}
-		rc = fb_info->fbops->fb_setcmap(&umap, fb_info);
-		fb_copy_cmap(&umap, &fb_info->cmap);
-		fb_dealloc_cmap(&umap);
-
-		return rc ?: count;
-	}
-	for (i = 0; i < length; i++) {
-		u16 red, blue, green, tsp;
-
-		sscanf(&buf[i * 16 +  3], "%4hx", &red);
-		sscanf(&buf[i * 16 +  7], "%4hx", &blue);
-		sscanf(&buf[i * 16 + 11], "%4hx", &green);
-		tsp = (buf[i * 16 +  2] != ' ');
-		if ((rc = fb_info->fbops->fb_setcolreg(start++,
-				      red, green, blue, tsp, fb_info)))
-			return rc;
-
-		fb_info->cmap.red[i] = red;
-		fb_info->cmap.blue[i] = blue;
-		fb_info->cmap.green[i] = green;
-		if (transp)
-			fb_info->cmap.transp[i] = tsp;
-	}
-	return count;
-}
-
-static ssize_t show_cmap(struct class_device *class_device, char *buf)
-{
-	struct fb_info *fb_info = class_get_devdata(class_device);
-	unsigned int i;
-
-	if (!fb_info->cmap.red || !fb_info->cmap.blue ||
-	   !fb_info->cmap.green)
-		return -EINVAL;
-
-	if (fb_info->cmap.len > PAGE_SIZE / 16)
-		return -EINVAL;
-
-	/* don't mess with the format, the buffer is PAGE_SIZE */
-	/* 256 entries at 16 chars per line equals 4096 = PAGE_SIZE */
-	for (i = 0; i < fb_info->cmap.len; i++) {
-		snprintf(&buf[ i * 16], PAGE_SIZE - i * 16, "%02x%c%4x%4x%4x\n", i + fb_info->cmap.start,
-			((fb_info->cmap.transp && fb_info->cmap.transp[i]) ? '*' : ' '),
-			fb_info->cmap.red[i], fb_info->cmap.blue[i],
-			fb_info->cmap.green[i]);
-	}
-	return 16 * fb_info->cmap.len;
-}
-
 static ssize_t store_blank(struct class_device *class_device, const char * buf,
 			   size_t count)
 {
@@ -502,10 +414,12 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
 }
 
+/* When cmap is added back in it should be a binary attribute
+ * not a text one. Consideration should also be given to converting
+ * fbdev to use configfs instead of sysfs */
 static struct class_device_attribute class_device_attrs[] = {
 	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
 	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
-	__ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
 	__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
 	__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
 	__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 5fe1979..4e96393 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -73,8 +73,8 @@
  * these flags allow the user to specify that requests for +ve sync
  * should be silently turned in -ve sync.
  */
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync;
+static int lowvsync;
 
 /*
  * The hardware state of the graphics card that isn't part of the
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 10e6b3a..0da624e 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -73,7 +73,7 @@
 /* --------------------------------------------------------------------- */
 
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 #ifdef MODULE
 
@@ -1545,7 +1545,7 @@
 	return 0;
 }
 
-static void __devinit savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio (struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 	DBG ("savage_unmap_mmio");
@@ -1597,7 +1597,7 @@
 	return 0;
 }
 
-static void __devinit savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video (struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 
@@ -1614,7 +1614,7 @@
 	}
 }
 
-static int __devinit savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw (struct savagefb_par *par)
 {
 	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
 
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 8982e54..b0b9acf 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,7 @@
 static void            (*pmi_start)(void);
 static void            (*pmi_pal)(void);
 static int             depth;
-
+static int             vga_compat;
 /* --------------------------------------------------------------------- */
 
 static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -83,9 +83,10 @@
 static void vesa_setpalette(int regno, unsigned red, unsigned green,
 			    unsigned blue)
 {
+	int shift = 16 - depth;
+
 #ifdef __i386__
 	struct { u_char blue, green, red, pad; } entry;
-	int shift = 16 - depth;
 
 	if (pmi_setpal) {
 		entry.red   = red   >> shift;
@@ -101,14 +102,20 @@
                   "d" (regno),          /* EDX */
                   "D" (&entry),         /* EDI */
                   "S" (&pmi_pal));      /* ESI */
-	} else {
-		/* without protected mode interface, try VGA registers... */
+		return;
+	}
+#endif
+
+/*
+ * without protected mode interface and if VGA compatible,
+ * try VGA registers...
+ */
+	if (vga_compat) {
 		outb_p(regno,       dac_reg);
 		outb_p(red   >> shift, dac_val);
 		outb_p(green >> shift, dac_val);
 		outb_p(blue  >> shift, dac_val);
 	}
-#endif
 }
 
 static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -214,6 +221,7 @@
 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
 		return -ENODEV;
 
+	vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
 	vesafb_fix.smem_start = screen_info.lfb_base;
 	vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
 	if (15 == vesafb_defined.bits_per_pixel)
@@ -318,6 +326,12 @@
 		}
 	}
 
+	if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
+		printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
+		                    "        colors may be incorrect\n");
+		vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+	}
+
 	vesafb_defined.xres_virtual = vesafb_defined.xres;
 	vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
 	if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
@@ -354,7 +368,8 @@
 	printk(KERN_INFO "vesafb: %s: "
 	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
 	       (vesafb_defined.bits_per_pixel > 8) ?
-	       "Truecolor" : "Pseudocolor",
+	       "Truecolor" : (vga_compat || pmi_setpal) ?
+	       "Pseudocolor" : "Static Pseudocolor",
 	       screen_info.rsvd_size,
 	       screen_info.red_size,
 	       screen_info.green_size,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index b0a0ae5..61c599b 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -127,12 +127,13 @@
 
 	if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
 		dprintk(DEBUG_ERROR, "problem initiating session\n");
-		kfree(v9ses);
-		return ERR_PTR(newfid);
+		sb = ERR_PTR(newfid);
+		goto out_free_session;
 	}
 
 	sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
-
+	if (IS_ERR(sb))
+		goto out_close_session;
 	v9fs_fill_super(sb, v9ses, flags);
 
 	inode = v9fs_get_inode(sb, S_IFDIR | mode);
@@ -185,6 +186,12 @@
 
 	return sb;
 
+out_close_session:
+	v9fs_session_close(v9ses);
+out_free_session:
+	kfree(v9ses);
+	return sb;
+
 put_back_sb:
 	/* deactivate_super calls v9fs_kill_super which will frees the rest */
 	up_write(&sb->s_umount);
diff --git a/fs/Kconfig b/fs/Kconfig
index e207be6..f9b5842 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -799,6 +799,7 @@
 config PROC_VMCORE
         bool "/proc/vmcore support (EXPERIMENTAL)"
         depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
+	default y
         help
         Exports the dump image of crashed kernel in ELF format.
 
@@ -841,6 +842,12 @@
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+	help
+	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
+	  ramfs. For architectures that support it, say Y here and read
+	  <file:Documentation/vm/hugetlbpage.txt> for details.
+
+	  If unsure, say N.
 
 config HUGETLB_PAGE
 	def_bool HUGETLBFS
@@ -861,7 +868,7 @@
 
 config CONFIGFS_FS
 	tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on SYSFS && EXPERIMENTAL
 	help
 	  configfs is a ram-based filesystem that provides the converse
 	  of sysfs's functionality. Where sysfs is a filesystem-based
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 8a2de03..1a27ecb 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,11 @@
 Version 1.42
 ------------
 Fix slow oplock break when mounted to different servers at the same time and
-the tids match and we try to find matching fid on wrong server.
+the tids match and we try to find matching fid on wrong server. Fix read
+looping when signing required by server (2.6.16 kernel only). Fix readdir
+vs. rename race which could cause each to hang. Return . and .. even
+if server does not.  Allow searches to skip first three entries and
+begin at any location. Fix oops in find_writeable_file.
 
 Version 1.41
 ------------
diff --git a/fs/cifs/README b/fs/cifs/README
index b2b4d08..0355003 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -511,6 +511,14 @@
 			support and want to map the uid and gid fields 
 			to values supplied at mount (rather than the 
 			actual values, then set this to zero. (default 1)
+Experimental            When set to 1 used to enable certain experimental
+			features (currently enables multipage writes
+			when signing is enabled, the multipage write
+			performance enhancement was disabled when
+			signing turned on in case buffer was modified
+			just before it was sent, also this flag will
+			be used to use the new experimental sessionsetup
+			code).
 
 These experimental features and tracing can be enabled by changing flags in 
 /proc/fs/cifs (after the cifs module has been installed or built into the 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d4b713e..c262d88 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -33,6 +33,7 @@
 #include <linux/vfs.h>
 #include <linux/mempool.h>
 #include <linux/delay.h>
+#include <linux/kthread.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -75,9 +76,6 @@
 module_param(cifs_max_pending, int, 0);
 MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
 
-static DECLARE_COMPLETION(cifs_oplock_exited);
-static DECLARE_COMPLETION(cifs_dnotify_exited);
-
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
@@ -841,10 +839,6 @@
 	__u16  netfid;
 	int rc;
 
-	daemonize("cifsoplockd");
-	allow_signal(SIGTERM);
-
-	oplockThread = current;
 	do {
 		if (try_to_freeze()) 
 			continue;
@@ -900,9 +894,9 @@
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(1);  /* yield in case q were corrupt */
 		}
-	} while(!signal_pending(current));
-	oplockThread = NULL;
-	complete_and_exit (&cifs_oplock_exited, 0);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static int cifs_dnotify_thread(void * dummyarg)
@@ -910,10 +904,6 @@
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
 
-	daemonize("cifsdnotifyd");
-	allow_signal(SIGTERM);
-
-	dnotifyThread = current;
 	do {
 		if(try_to_freeze())
 			continue;
@@ -931,8 +921,9 @@
 				wake_up_all(&ses->server->response_q);
 		}
 		read_unlock(&GlobalSMBSeslock);
-	} while(!signal_pending(current));
-	complete_and_exit (&cifs_dnotify_exited, 0);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static int __init
@@ -982,32 +973,48 @@
 	}
 
 	rc = cifs_init_inodecache();
-	if (!rc) {
-		rc = cifs_init_mids();
-		if (!rc) {
-			rc = cifs_init_request_bufs();
-			if (!rc) {
-				rc = register_filesystem(&cifs_fs_type);
-				if (!rc) {                
-					rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
-						CLONE_FS | CLONE_FILES | CLONE_VM);
-					if(rc > 0) {
-						rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
-							CLONE_FS | CLONE_FILES | CLONE_VM);
-						if(rc > 0)
-							return 0;
-						else
-							cERROR(1,("error %d create dnotify thread", rc));
-					} else {
-						cERROR(1,("error %d create oplock thread",rc));
-					}
-				}
-				cifs_destroy_request_bufs();
-			}
-			cifs_destroy_mids();
-		}
-		cifs_destroy_inodecache();
+	if (rc)
+		goto out_clean_proc;
+
+	rc = cifs_init_mids();
+	if (rc)
+		goto out_destroy_inodecache;
+
+	rc = cifs_init_request_bufs();
+	if (rc)
+		goto out_destroy_mids;
+
+	rc = register_filesystem(&cifs_fs_type);
+	if (rc)
+		goto out_destroy_request_bufs;
+
+	oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
+	if (IS_ERR(oplockThread)) {
+		rc = PTR_ERR(oplockThread);
+		cERROR(1,("error %d create oplock thread", rc));
+		goto out_unregister_filesystem;
 	}
+
+	dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
+	if (IS_ERR(dnotifyThread)) {
+		rc = PTR_ERR(dnotifyThread);
+		cERROR(1,("error %d create dnotify thread", rc));
+		goto out_stop_oplock_thread;
+	}
+
+	return 0;
+
+ out_stop_oplock_thread:
+	kthread_stop(oplockThread);
+ out_unregister_filesystem:
+	unregister_filesystem(&cifs_fs_type);
+ out_destroy_request_bufs:
+	cifs_destroy_request_bufs();
+ out_destroy_mids:
+	cifs_destroy_mids();
+ out_destroy_inodecache:
+	cifs_destroy_inodecache();
+ out_clean_proc:
 #ifdef CONFIG_PROC_FS
 	cifs_proc_clean();
 #endif
@@ -1025,14 +1032,8 @@
 	cifs_destroy_inodecache();
 	cifs_destroy_mids();
 	cifs_destroy_request_bufs();
-	if(oplockThread) {
-		send_sig(SIGTERM, oplockThread, 1);
-		wait_for_completion(&cifs_oplock_exited);
-	}
-	if(dnotifyThread) {
-		send_sig(SIGTERM, dnotifyThread, 1);
-		wait_for_completion(&cifs_dnotify_exited);
-	}
+	kthread_stop(oplockThread);
+	kthread_stop(dnotifyThread);
 }
 
 MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d705500..fd36892 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3119,7 +3119,7 @@
 				psrch_inf->endOfSearch = FALSE;
 
 			psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
-			psrch_inf->index_of_last_entry = 
+			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
 				psrch_inf->entries_in_buffer;
 			*pnetfid = parms->SearchHandle;
 		} else {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0b86d5c..d2ec806 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3447,6 +3447,12 @@
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
 			pSesInfo->server->timeZone));
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+		if(experimEnabled > 1)
+			rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
+					    &ntlmv2_flag, nls_info);	
+		else
+#endif
 		if (extended_security
 				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
 				&& (pSesInfo->server->secType == NTLMSSP)) {
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1d0ca3e..82315ed 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -139,9 +139,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -316,9 +314,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if(full_path == NULL)
 		rc = -ENOMEM;
 	else if (pTcon->ses->capabilities & CAP_UNIX) {
@@ -440,6 +436,20 @@
 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
+	/*
+	 * Don't allow the separator character in a path component.
+	 * The VFS will not allow "/", but "\" is allowed by posix.
+	 */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+		int i;
+		for (i = 0; i < direntry->d_name.len; i++)
+			if (direntry->d_name.name[i] == '\\') {
+				cFYI(1, ("Invalid file name"));
+				FreeXid(xid);
+				return ERR_PTR(-EINVAL);
+			}
+	}
+
 	/* can not grab the rename sem here since it would
 	deadlock in the cases (beginning of sys_rename itself)
 	in which we already have the sb rename sem */
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index ec4dfe9..633a938 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -86,9 +86,7 @@
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5c497c5..e152bf6 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -203,9 +203,7 @@
 		}
 	}
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -906,8 +904,7 @@
 				if (rc != 0)
 					break;
 			}
-			/* BB FIXME We can not sign across two buffers yet */
-			if((pTcon->ses->server->secMode & 
+			if(experimEnabled || (pTcon->ses->server->secMode & 
 			 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
 				struct kvec iov[2];
 				unsigned int len;
@@ -923,13 +920,13 @@
 						*poffset, &bytes_written,
 						iov, 1, long_op);
 			} else
-			/* BB FIXME fixup indentation of line below */
-			rc = CIFSSMBWrite(xid, pTcon,
-				 open_file->netfid,
-				 min_t(const int, cifs_sb->wsize, 
-				       write_size - total_written),
-				 *poffset, &bytes_written,
-				 write_data + total_written, NULL, long_op);
+				rc = CIFSSMBWrite(xid, pTcon,
+					 open_file->netfid,
+					 min_t(const int, cifs_sb->wsize,
+					       write_size - total_written),
+					 *poffset, &bytes_written,
+					 write_data + total_written,
+					 NULL, long_op);
 		}
 		if (rc || (bytes_written == 0)) {
 			if (total_written)
@@ -968,6 +965,16 @@
 	struct cifsFileInfo *open_file;
 	int rc;
 
+	/* Having a null inode here (because mapping->host was set to zero by
+	the VFS or MM) should not happen but we had reports of on oops (due to
+	it being zero) during stress testcases so we need to check for it */
+
+	if(cifs_inode == NULL) {
+		cERROR(1,("Null inode passed to cifs_writeable_file"));
+		dump_stack();
+		return NULL;
+	}
+
 	read_lock(&GlobalSMBSeslock);
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
 		if (open_file->closePend)
@@ -1093,12 +1100,11 @@
 	if (cifs_sb->wsize < PAGE_CACHE_SIZE)
 		return generic_writepages(mapping, wbc);
 
-	/* BB FIXME we do not have code to sign across multiple buffers yet,
-	   so go to older writepage style write which we can sign if needed */
 	if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
 		if(cifs_sb->tcon->ses->server->secMode &
                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			return generic_writepages(mapping, wbc);
+			if(!experimEnabled)
+				return generic_writepages(mapping, wbc);
 
 	/*
 	 * BB: Is this meaningful for a non-block-device file system?
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 957ddd1..4093764 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -722,9 +722,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -807,9 +805,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -1141,9 +1137,7 @@
 			rc = 0;
 	}
 		
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 	if (full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 9562f5b..2ec99f8 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -48,10 +48,8 @@
 /* No need to check for cross device links since server will do that
    BB note DFS case in future though (when we may have to check) */
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	fromName = build_path_from_dentry(old_file);
 	toName = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 	if((fromName == NULL) || (toName == NULL)) {
 		rc = -ENOMEM;
 		goto cifs_hl_exit;
@@ -103,9 +101,7 @@
 
 	xid = GetXid();
 
-	mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);
 
 	if (!full_path)
 		goto out_no_free;
@@ -164,9 +160,7 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		FreeXid(xid);
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
index 78866f9..115359c 100644
--- a/fs/cifs/ntlmssp.c
+++ b/fs/cifs/ntlmssp.c
@@ -121,6 +121,20 @@
 	}
 
 
+	/* copy session key */
+
+	/* if Unicode, align strings to two byte boundary */
+
+	/* copy user name */ /* BB Do we need to special case null user name? */
+
+	/* copy domain name */
+
+	/* copy Linux version */
+
+	/* copy network operating system name */
+
+	/* update bcc and smb buffer length */
+
 /*	rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
 	/* SMB request buf freed in SendReceive2 */
 
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 2f6e282..b689c50 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -404,9 +404,7 @@
 	if(pTcon == NULL)
 		return -EINVAL;
 
-	mutex_lock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(file->f_dentry);
-	mutex_unlock(&file->f_dentry->d_sb->s_vfs_rename_mutex);
 
 	if(full_path == NULL) {
 		return -ENOMEM;
@@ -592,6 +590,13 @@
 	first_entry_in_buffer = 
 		cifsFile->srch_inf.index_of_last_entry - 
 			cifsFile->srch_inf.entries_in_buffer;
+
+	/* if first entry in buf is zero then is first buffer
+	in search response data which means it is likely . and ..
+	will be in this buffer, although some servers do not return
+	. and .. for the root of a drive and for those we need
+	to start two entries earlier */
+
 /*	dump_cifs_file_struct(file, "In fce ");*/
 	if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
 	     is_dir_changed(file)) || 
@@ -634,23 +639,14 @@
 		char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 
 			smbCalcSize((struct smb_hdr *)
 				cifsFile->srch_inf.ntwrk_buf_start);
+
+		current_entry = cifsFile->srch_inf.srch_entries_start;
 		first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
 					- cifsFile->srch_inf.entries_in_buffer;
 		pos_in_buf = index_to_find - first_entry_in_buffer;
 		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 
-		current_entry = cifsFile->srch_inf.srch_entries_start;
 		for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
 			/* go entry by entry figuring out which is first */
-			/* if( . or ..)
-				skip */
-			rc = cifs_entry_is_dot(current_entry,cifsFile);
-			if(rc == 1) /* is . or .. so skip */ {
-				cFYI(1,("Entry is .")); /* BB removeme BB */
-				/* continue; */
-			} else if (rc == 2 ) {
-				cFYI(1,("Entry is ..")); /* BB removeme BB */
-				/* continue; */
-			}
 			current_entry = nxt_dir_entry(current_entry,end_of_smb);
 		}
 		if((current_entry == NULL) && (i < pos_in_buf)) {
@@ -770,6 +766,11 @@
 	if(file->f_dentry == NULL)
 		return -ENOENT;
 
+	rc = cifs_entry_is_dot(pfindEntry,pCifsF);
+	/* skip . and .. since we added them first */
+	if(rc != 0) 
+		return 0;
+
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 
 	qstring.name = scratch_buf;
@@ -898,22 +899,22 @@
 
 	switch ((int) file->f_pos) {
 	case 0:
-		/*if (filldir(direntry, ".", 1, file->f_pos,
+		if (filldir(direntry, ".", 1, file->f_pos,
 		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("Filldir for current dir failed "));
+			cERROR(1, ("Filldir for current dir failed"));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
+		file->f_pos++;
 	case 1:
-		/* if (filldir(direntry, "..", 2, file->f_pos,
+		if (filldir(direntry, "..", 2, file->f_pos,
 		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
 			cERROR(1, ("Filldir for parent dir failed "));
 			rc = -ENOMEM;
 			break;
 		}
-		file->f_pos++; */
-	case 2:
+		file->f_pos++;
+	default:
 		/* 1) If search is active, 
 			is in current search buffer? 
 			if it before then restart search
@@ -927,7 +928,6 @@
 				return rc;
 			}
 		}
-	default:
 		if(file->private_data == NULL) {
 			rc = -EINVAL;
 			FreeXid(xid);
@@ -947,8 +947,6 @@
 		kfree(cifsFile->search_resume_name);
 		cifsFile->search_resume_name = NULL; */
 
-		/* BB account for . and .. in f_pos as special case */
-
 		rc = find_cifs_entry(xid,pTcon, file,
 				&current_entry,&num_to_fill);
 		if(rc) {
@@ -977,7 +975,8 @@
 					  num_to_fill, i));
 				break;
 			}
-
+			/* if buggy server returns . and .. late do
+			we want to check for that here? */
 			rc = cifs_filldir(current_entry, file, 
 					filldir, direntry,tmp_buf);
 			file->f_pos++;
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 3938444..7754d64 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -62,9 +62,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
                                                                                      
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -116,9 +114,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -223,9 +219,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
@@ -341,9 +335,7 @@
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
-	mutex_lock(&sb->s_vfs_rename_mutex);
 	full_path = build_path_from_dentry(direntry);
-	mutex_unlock(&sb->s_vfs_rename_mutex);
 	if(full_path == NULL) {
 		FreeXid(xid);
 		return -ENOMEM;
diff --git a/fs/compat.c b/fs/compat.c
index 7f8e26e..2e32bd3 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1217,6 +1217,10 @@
 	if (ret < 0)
 		goto out;
 
+	ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE);
+	if (ret)
+		goto out;
+
 	fnv = NULL;
 	if (type == READ) {
 		fn = file->f_op->read;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 8ed9b06..5638c8f 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -504,7 +504,7 @@
 	int ret = 0;
 	int i;
 
-	if (group && group->default_groups) {
+	if (group->default_groups) {
 		/* FYI, we're faking mkdir here
 		 * I'm not sure we need this semaphore, as we're called
 		 * from our parent's mkdir.  That holds our parent's
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 910a8ed..b05d1b2 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -929,8 +929,7 @@
 			block_in_page += this_chunk_blocks;
 			dio->blocks_available -= this_chunk_blocks;
 next_block:
-			if (dio->block_in_file > dio->final_block_in_request)
-				BUG();
+			BUG_ON(dio->block_in_file > dio->final_block_in_request);
 			if (dio->block_in_file == dio->final_block_in_request)
 				break;
 		}
diff --git a/fs/dquot.c b/fs/dquot.c
index 6b38869..81d87a4 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -590,8 +590,7 @@
 	atomic_dec(&dquot->dq_count);
 #ifdef __DQUOT_PARANOIA
 	/* sanity check */
-	if (!list_empty(&dquot->dq_free))
-		BUG();
+	BUG_ON(!list_empty(&dquot->dq_free));
 #endif
 	put_dquot_last(dquot);
 	spin_unlock(&dq_list_lock);
@@ -666,8 +665,7 @@
 		return NODQUOT;
 	}
 #ifdef __DQUOT_PARANOIA
-	if (!dquot->dq_sb)	/* Has somebody invalidated entry under us? */
-		BUG();
+	BUG_ON(!dquot->dq_sb);	/* Has somebody invalidated entry under us? */
 #endif
 
 	return dquot;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 242fe1a..1b4491c 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -599,7 +599,7 @@
 	switch (op) {
 	case EPOLL_CTL_ADD:
 		if (!epi) {
-			epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+			epds.events |= POLLERR | POLLHUP;
 
 			error = ep_insert(ep, &epds, tfile, fd);
 		} else
@@ -613,7 +613,7 @@
 		break;
 	case EPOLL_CTL_MOD:
 		if (epi) {
-			epds.events |= POLLERR | POLLHUP | POLLRDHUP;
+			epds.events |= POLLERR | POLLHUP;
 			error = ep_modify(ep, epi, &epds);
 		} else
 			error = -ENOENT;
diff --git a/fs/exec.c b/fs/exec.c
index 950ebd4..3a79d97 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -561,7 +561,7 @@
 	arch_pick_mmap_layout(mm);
 	if (old_mm) {
 		up_read(&old_mm->mmap_sem);
-		if (active_mm != old_mm) BUG();
+		BUG_ON(active_mm != old_mm);
 		mmput(old_mm);
 		return 0;
 	}
@@ -665,9 +665,7 @@
 	 * and to assume its PID:
 	 */
 	if (!thread_group_leader(current)) {
-		struct task_struct *parent;
 		struct dentry *proc_dentry1, *proc_dentry2;
-		unsigned long ptrace;
 
 		/*
 		 * Wait for the thread group leader to be a zombie.
@@ -678,6 +676,18 @@
 		while (leader->exit_state != EXIT_ZOMBIE)
 			yield();
 
+		/*
+		 * The only record we have of the real-time age of a
+		 * process, regardless of execs it's done, is start_time.
+		 * All the past CPU time is accumulated in signal_struct
+		 * from sister threads now dead.  But in this non-leader
+		 * exec, nothing survives from the original leader thread,
+		 * whose birth marks the true age of this process now.
+		 * When we take on its identity by switching to its PID, we
+		 * also take its birthdate (always earlier than our own).
+		 */
+		current->start_time = leader->start_time;
+
 		spin_lock(&leader->proc_lock);
 		spin_lock(&current->proc_lock);
 		proc_dentry1 = proc_pid_unhash(current);
@@ -692,22 +702,6 @@
 		 * two threads with a switched PID, and release
 		 * the former thread group leader:
 		 */
-		ptrace = leader->ptrace;
-		parent = leader->parent;
-		if (unlikely(ptrace) && unlikely(parent == current)) {
-			/*
-			 * Joker was ptracing his own group leader,
-			 * and now he wants to be his own parent!
-			 * We can't have that.
-			 */
-			ptrace = 0;
-		}
-
-		ptrace_unlink(current);
-		ptrace_unlink(leader);
-		remove_parent(current);
-		remove_parent(leader);
-
 
 		/* Become a process group leader with the old leader's pid.
 		 * Note: The old leader also uses thispid until release_task
@@ -718,19 +712,15 @@
 		attach_pid(current, PIDTYPE_PID,  current->pid);
 		attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
 		attach_pid(current, PIDTYPE_SID,  current->signal->session);
-		list_add_tail(&current->tasks, &init_task.tasks);
+		list_add_tail_rcu(&current->tasks, &init_task.tasks);
 
-		current->parent = current->real_parent = leader->real_parent;
-		leader->parent = leader->real_parent = child_reaper;
 		current->group_leader = current;
-		leader->group_leader = leader;
+		leader->group_leader = current;
 
-		add_parent(current);
-		add_parent(leader);
-		if (ptrace) {
-			current->ptrace = ptrace;
-			__ptrace_link(current, parent);
-		}
+		/* Reduce leader to a thread */
+		detach_pid(leader, PIDTYPE_PGID);
+		detach_pid(leader, PIDTYPE_SID);
+		list_del_init(&leader->tasks);
 
 		current->exit_signal = SIGCHLD;
 
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index aaf1da1..8c22aa9 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -48,6 +48,7 @@
 		if (!S_ISDIR(inode->i_mode))
 			flags &= ~EXT3_DIRSYNC_FL;
 
+		mutex_lock(&inode->i_mutex);
 		oldflags = ei->i_flags;
 
 		/* The JOURNAL_DATA flag is modifiable only by root */
@@ -60,8 +61,10 @@
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
 		if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
-			if (!capable(CAP_LINUX_IMMUTABLE))
+			if (!capable(CAP_LINUX_IMMUTABLE)) {
+				mutex_unlock(&inode->i_mutex);
 				return -EPERM;
+			}
 		}
 
 		/*
@@ -69,14 +72,18 @@
 		 * the relevant capability.
 		 */
 		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
-			if (!capable(CAP_SYS_RESOURCE))
+			if (!capable(CAP_SYS_RESOURCE)) {
+				mutex_unlock(&inode->i_mutex);
 				return -EPERM;
+			}
 		}
 
 
 		handle = ext3_journal_start(inode, 1);
-		if (IS_ERR(handle))
+		if (IS_ERR(handle)) {
+			mutex_unlock(&inode->i_mutex);
 			return PTR_ERR(handle);
+		}
 		if (IS_SYNC(inode))
 			handle->h_sync = 1;
 		err = ext3_reserve_inode_write(handle, inode, &iloc);
@@ -93,11 +100,14 @@
 		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
 flags_err:
 		ext3_journal_stop(handle);
-		if (err)
+		if (err) {
+			mutex_unlock(&inode->i_mutex);
 			return err;
+		}
 
 		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
 			err = ext3_change_inode_journal_flag(inode, jflag);
+		mutex_unlock(&inode->i_mutex);
 		return err;
 	}
 	case EXT3_IOC_GETVERSION:
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 1041dab..8aac533 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -213,7 +213,7 @@
 			goto exit_bh;
 		}
 		lock_buffer(bh);
-		memcpy(gdb->b_data, sbi->s_group_desc[i], bh->b_size);
+		memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
 		set_buffer_uptodate(gdb);
 		unlock_buffer(bh);
 		ext3_journal_dirty_metadata(handle, gdb);
@@ -767,6 +767,7 @@
 	if (input->group != sbi->s_groups_count) {
 		ext3_warning(sb, __FUNCTION__,
 			     "multiple resizers run on filesystem!");
+		unlock_super(sb);
 		err = -EBUSY;
 		goto exit_journal;
 	}
@@ -974,6 +975,7 @@
 	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
 		ext3_warning(sb, __FUNCTION__,
 			     "multiple resizers run on filesystem!");
+		unlock_super(sb);
 		err = -EBUSY;
 		goto exit_put;
 	}
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 2a24791..d35cbc6 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -453,8 +453,7 @@
 			/* Make sure we are called with one of the POLL_*
 			   reasons, otherwise we could leak kernel stack into
 			   userspace.  */
-			if ((reason & __SI_MASK) != __SI_POLL)
-				BUG();
+			BUG_ON((reason & __SI_MASK) != __SI_POLL);
 			if (reason - POLL_IN >= NSIGPOLL)
 				si.si_band  = ~0L;
 			else
diff --git a/fs/fifo.c b/fs/fifo.c
index 889f722..49035b1 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -15,30 +15,35 @@
 #include <linux/fs.h>
 #include <linux/pipe_fs_i.h>
 
-static void wait_for_partner(struct inode* inode, unsigned int* cnt)
+static void wait_for_partner(struct inode* inode, unsigned int *cnt)
 {
 	int cur = *cnt;	
-	while(cur == *cnt) {
-		pipe_wait(inode);
-		if(signal_pending(current))
+
+	while (cur == *cnt) {
+		pipe_wait(inode->i_pipe);
+		if (signal_pending(current))
 			break;
 	}
 }
 
 static void wake_up_partner(struct inode* inode)
 {
-	wake_up_interruptible(PIPE_WAIT(*inode));
+	wake_up_interruptible(&inode->i_pipe->wait);
 }
 
 static int fifo_open(struct inode *inode, struct file *filp)
 {
+	struct pipe_inode_info *pipe;
 	int ret;
 
-	mutex_lock(PIPE_MUTEX(*inode));
-	if (!inode->i_pipe) {
+	mutex_lock(&inode->i_mutex);
+	pipe = inode->i_pipe;
+	if (!pipe) {
 		ret = -ENOMEM;
-		if(!pipe_new(inode))
+		pipe = alloc_pipe_info(inode);
+		if (!pipe)
 			goto err_nocleanup;
+		inode->i_pipe = pipe;
 	}
 	filp->f_version = 0;
 
@@ -53,18 +58,18 @@
 	 *  opened, even when there is no process writing the FIFO.
 	 */
 		filp->f_op = &read_fifo_fops;
-		PIPE_RCOUNTER(*inode)++;
-		if (PIPE_READERS(*inode)++ == 0)
+		pipe->r_counter++;
+		if (pipe->readers++ == 0)
 			wake_up_partner(inode);
 
-		if (!PIPE_WRITERS(*inode)) {
+		if (!pipe->writers) {
 			if ((filp->f_flags & O_NONBLOCK)) {
 				/* suppress POLLHUP until we have
 				 * seen a writer */
-				filp->f_version = PIPE_WCOUNTER(*inode);
+				filp->f_version = pipe->w_counter;
 			} else 
 			{
-				wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
+				wait_for_partner(inode, &pipe->w_counter);
 				if(signal_pending(current))
 					goto err_rd;
 			}
@@ -78,16 +83,16 @@
 	 *  errno=ENXIO when there is no process reading the FIFO.
 	 */
 		ret = -ENXIO;
-		if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
+		if ((filp->f_flags & O_NONBLOCK) && !pipe->readers)
 			goto err;
 
 		filp->f_op = &write_fifo_fops;
-		PIPE_WCOUNTER(*inode)++;
-		if (!PIPE_WRITERS(*inode)++)
+		pipe->w_counter++;
+		if (!pipe->writers++)
 			wake_up_partner(inode);
 
-		if (!PIPE_READERS(*inode)) {
-			wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
+		if (!pipe->readers) {
+			wait_for_partner(inode, &pipe->r_counter);
 			if (signal_pending(current))
 				goto err_wr;
 		}
@@ -102,11 +107,11 @@
 	 */
 		filp->f_op = &rdwr_fifo_fops;
 
-		PIPE_READERS(*inode)++;
-		PIPE_WRITERS(*inode)++;
-		PIPE_RCOUNTER(*inode)++;
-		PIPE_WCOUNTER(*inode)++;
-		if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
+		pipe->readers++;
+		pipe->writers++;
+		pipe->r_counter++;
+		pipe->w_counter++;
+		if (pipe->readers == 1 || pipe->writers == 1)
 			wake_up_partner(inode);
 		break;
 
@@ -116,27 +121,27 @@
 	}
 
 	/* Ok! */
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_unlock(&inode->i_mutex);
 	return 0;
 
 err_rd:
-	if (!--PIPE_READERS(*inode))
-		wake_up_interruptible(PIPE_WAIT(*inode));
+	if (!--pipe->readers)
+		wake_up_interruptible(&pipe->wait);
 	ret = -ERESTARTSYS;
 	goto err;
 
 err_wr:
-	if (!--PIPE_WRITERS(*inode))
-		wake_up_interruptible(PIPE_WAIT(*inode));
+	if (!--pipe->writers)
+		wake_up_interruptible(&pipe->wait);
 	ret = -ERESTARTSYS;
 	goto err;
 
 err:
-	if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode))
+	if (!pipe->readers && !pipe->writers)
 		free_pipe_info(inode);
 
 err_nocleanup:
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 76a0708..049500847 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -42,24 +42,21 @@
 static inline void
 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
 {
-	if (infp->vsi_fshino)
-		BUG();
+	BUG_ON(infp->vsi_fshino);
 	infp->vsi_fshino = fshp->olt_fsino[0];
 }
 
 static inline void
 vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
 {
-	if (infp->vsi_iext)
-		BUG();
+	BUG_ON(infp->vsi_iext);
 	infp->vsi_iext = ilistp->olt_iext[0]; 
 }
 
 static inline u_long
 vxfs_oblock(struct super_block *sbp, daddr_t block, u_long bsize)
 {
-	if (sbp->s_blocksize % bsize)
-		BUG();
+	BUG_ON(sbp->s_blocksize % bsize);
 	return (block * (sbp->s_blocksize / bsize));
 }
 
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 23d1f52..104a62d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
@@ -23,13 +23,11 @@
 
 static struct fuse_conn *fuse_get_conn(struct file *file)
 {
-	struct fuse_conn *fc;
-	spin_lock(&fuse_lock);
-	fc = file->private_data;
-	if (fc && !fc->connected)
-		fc = NULL;
-	spin_unlock(&fuse_lock);
-	return fc;
+	/*
+	 * Lockless access is OK, because file->private data is set
+	 * once during mount and is valid until the file is released.
+	 */
+	return file->private_data;
 }
 
 static void fuse_request_init(struct fuse_req *req)
@@ -74,10 +72,8 @@
  */
 void fuse_reset_request(struct fuse_req *req)
 {
-	int preallocated = req->preallocated;
 	BUG_ON(atomic_read(&req->count) != 1);
 	fuse_request_init(req);
-	req->preallocated = preallocated;
 }
 
 static void __fuse_get_request(struct fuse_req *req)
@@ -92,80 +88,64 @@
 	atomic_dec(&req->count);
 }
 
-static struct fuse_req *do_get_request(struct fuse_conn *fc)
+struct fuse_req *fuse_get_req(struct fuse_conn *fc)
 {
 	struct fuse_req *req;
-
-	spin_lock(&fuse_lock);
-	BUG_ON(list_empty(&fc->unused_list));
-	req = list_entry(fc->unused_list.next, struct fuse_req, list);
-	list_del_init(&req->list);
-	spin_unlock(&fuse_lock);
-	fuse_request_init(req);
-	req->preallocated = 1;
-	req->in.h.uid = current->fsuid;
-	req->in.h.gid = current->fsgid;
-	req->in.h.pid = current->pid;
-	return req;
-}
-
-/* This can return NULL, but only in case it's interrupted by a SIGKILL */
-struct fuse_req *fuse_get_request(struct fuse_conn *fc)
-{
-	int intr;
 	sigset_t oldset;
+	int intr;
+	int err;
 
 	atomic_inc(&fc->num_waiting);
 	block_sigs(&oldset);
-	intr = down_interruptible(&fc->outstanding_sem);
+	intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
 	restore_sigs(&oldset);
-	if (intr) {
-		atomic_dec(&fc->num_waiting);
-		return NULL;
-	}
-	return do_get_request(fc);
-}
+	err = -EINTR;
+	if (intr)
+		goto out;
 
-/* Must be called with fuse_lock held */
-static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
-{
-	if (req->preallocated) {
-		atomic_dec(&fc->num_waiting);
-		list_add(&req->list, &fc->unused_list);
-	} else
-		fuse_request_free(req);
+	req = fuse_request_alloc();
+	err = -ENOMEM;
+	if (!req)
+		goto out;
 
-	/* If we are in debt decrease that first */
-	if (fc->outstanding_debt)
-		fc->outstanding_debt--;
-	else
-		up(&fc->outstanding_sem);
+	req->in.h.uid = current->fsuid;
+	req->in.h.gid = current->fsgid;
+	req->in.h.pid = current->pid;
+	req->waiting = 1;
+	return req;
+
+ out:
+	atomic_dec(&fc->num_waiting);
+	return ERR_PTR(err);
 }
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	if (atomic_dec_and_test(&req->count)) {
-		spin_lock(&fuse_lock);
-		fuse_putback_request(fc, req);
-		spin_unlock(&fuse_lock);
+		if (req->waiting)
+			atomic_dec(&fc->num_waiting);
+		fuse_request_free(req);
 	}
 }
 
-static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
-{
-	if (atomic_dec_and_test(&req->count))
-		fuse_putback_request(fc, req);
-}
-
-void fuse_release_background(struct fuse_req *req)
+/*
+ * Called with sbput_sem held for read (request_end) or write
+ * (fuse_put_super).  By the time fuse_put_super() is finished, all
+ * inodes belonging to background requests must be released, so the
+ * iputs have to be done within the locked region.
+ */
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
 {
 	iput(req->inode);
 	iput(req->inode2);
-	if (req->file)
-		fput(req->file);
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	list_del(&req->bg_entry);
-	spin_unlock(&fuse_lock);
+	if (fc->num_background == FUSE_MAX_BACKGROUND) {
+		fc->blocked = 0;
+		wake_up_all(&fc->blocked_waitq);
+	}
+	fc->num_background--;
+	spin_unlock(&fc->lock);
 }
 
 /*
@@ -184,24 +164,29 @@
  * interrupted and put in the background, it will return with an error
  * and hence never be reset and reused.
  *
- * Called with fuse_lock, unlocks it
+ * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
 	list_del(&req->list);
 	req->state = FUSE_REQ_FINISHED;
 	if (!req->background) {
+		spin_unlock(&fc->lock);
 		wake_up(&req->waitq);
-		fuse_put_request_locked(fc, req);
-		spin_unlock(&fuse_lock);
+		fuse_put_request(fc, req);
 	} else {
 		void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
 		req->end = NULL;
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 		down_read(&fc->sbput_sem);
 		if (fc->mounted)
-			fuse_release_background(req);
+			fuse_release_background(fc, req);
 		up_read(&fc->sbput_sem);
+
+		/* fput must go outside sbput_sem, otherwise it can deadlock */
+		if (req->file)
+			fput(req->file);
+
 		if (end)
 			end(fc, req);
 		else
@@ -242,6 +227,9 @@
 {
 	req->background = 1;
 	list_add(&req->bg_entry, &fc->background);
+	fc->num_background++;
+	if (fc->num_background == FUSE_MAX_BACKGROUND)
+		fc->blocked = 1;
 	if (req->inode)
 		req->inode = igrab(req->inode);
 	if (req->inode2)
@@ -250,16 +238,16 @@
 		get_file(req->file);
 }
 
-/* Called with fuse_lock held.  Releases, and then reacquires it. */
+/* Called with fc->lock held.  Releases, and then reacquires it. */
 static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
 {
 	sigset_t oldset;
 
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 	block_sigs(&oldset);
 	wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
 	restore_sigs(&oldset);
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
 		return;
 
@@ -273,9 +261,9 @@
 		   locked state, there mustn't be any filesystem
 		   operation (e.g. page fault), since that could lead
 		   to deadlock */
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 		wait_event(req->waitq, !req->locked);
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 	}
 	if (req->state == FUSE_REQ_PENDING) {
 		list_del(&req->list);
@@ -304,19 +292,14 @@
 	req->in.h.unique = fc->reqctr;
 	req->in.h.len = sizeof(struct fuse_in_header) +
 		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
-	if (!req->preallocated) {
-		/* If request is not preallocated (either FORGET or
-		   RELEASE), then still decrease outstanding_sem, so
-		   user can't open infinite number of files while not
-		   processing the RELEASE requests.  However for
-		   efficiency do it without blocking, so if down()
-		   would block, just increase the debt instead */
-		if (down_trylock(&fc->outstanding_sem))
-			fc->outstanding_debt++;
-	}
 	list_add_tail(&req->list, &fc->pending);
 	req->state = FUSE_REQ_PENDING;
+	if (!req->waiting) {
+		req->waiting = 1;
+		atomic_inc(&fc->num_waiting);
+	}
 	wake_up(&fc->waitq);
+	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 }
 
 /*
@@ -325,7 +308,7 @@
 void request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
 	req->isreply = 1;
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	if (!fc->connected)
 		req->out.h.error = -ENOTCONN;
 	else if (fc->conn_error)
@@ -338,15 +321,16 @@
 
 		request_wait_answer(fc, req);
 	}
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 }
 
 static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
 {
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
+	background_request(fc, req);
 	if (fc->connected) {
 		queue_request(fc, req);
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 	} else {
 		req->out.h.error = -ENOTCONN;
 		request_end(fc, req);
@@ -362,9 +346,6 @@
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
 {
 	req->isreply = 1;
-	spin_lock(&fuse_lock);
-	background_request(fc, req);
-	spin_unlock(&fuse_lock);
 	request_send_nowait(fc, req);
 }
 
@@ -373,16 +354,16 @@
  * anything that could cause a page-fault.  If the request was already
  * interrupted bail out.
  */
-static int lock_request(struct fuse_req *req)
+static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	int err = 0;
 	if (req) {
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 		if (req->interrupted)
 			err = -ENOENT;
 		else
 			req->locked = 1;
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 	}
 	return err;
 }
@@ -392,18 +373,19 @@
  * requester thread is currently waiting for it to be unlocked, so
  * wake it up.
  */
-static void unlock_request(struct fuse_req *req)
+static void unlock_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	if (req) {
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 		req->locked = 0;
 		if (req->interrupted)
 			wake_up(&req->waitq);
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 	}
 }
 
 struct fuse_copy_state {
+	struct fuse_conn *fc;
 	int write;
 	struct fuse_req *req;
 	const struct iovec *iov;
@@ -416,11 +398,12 @@
 	unsigned len;
 };
 
-static void fuse_copy_init(struct fuse_copy_state *cs, int write,
-			   struct fuse_req *req, const struct iovec *iov,
-			   unsigned long nr_segs)
+static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
+			   int write, struct fuse_req *req,
+			   const struct iovec *iov, unsigned long nr_segs)
 {
 	memset(cs, 0, sizeof(*cs));
+	cs->fc = fc;
 	cs->write = write;
 	cs->req = req;
 	cs->iov = iov;
@@ -450,7 +433,7 @@
 	unsigned long offset;
 	int err;
 
-	unlock_request(cs->req);
+	unlock_request(cs->fc, cs->req);
 	fuse_copy_finish(cs);
 	if (!cs->seglen) {
 		BUG_ON(!cs->nr_segs);
@@ -473,7 +456,7 @@
 	cs->seglen -= cs->len;
 	cs->addr += cs->len;
 
-	return lock_request(cs->req);
+	return lock_request(cs->fc, cs->req);
 }
 
 /* Do as much copy to/from userspace buffer as we can */
@@ -585,9 +568,9 @@
 		if (signal_pending(current))
 			break;
 
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 		schedule();
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&fc->waitq, &wait);
@@ -606,18 +589,21 @@
 			      unsigned long nr_segs, loff_t *off)
 {
 	int err;
-	struct fuse_conn *fc;
 	struct fuse_req *req;
 	struct fuse_in *in;
 	struct fuse_copy_state cs;
 	unsigned reqsize;
+	struct fuse_conn *fc = fuse_get_conn(file);
+	if (!fc)
+		return -EPERM;
 
  restart:
-	spin_lock(&fuse_lock);
-	fc = file->private_data;
-	err = -EPERM;
-	if (!fc)
+	spin_lock(&fc->lock);
+	err = -EAGAIN;
+	if ((file->f_flags & O_NONBLOCK) && fc->connected &&
+	    list_empty(&fc->pending))
 		goto err_unlock;
+
 	request_wait(fc);
 	err = -ENODEV;
 	if (!fc->connected)
@@ -641,14 +627,14 @@
 		request_end(fc, req);
 		goto restart;
 	}
-	spin_unlock(&fuse_lock);
-	fuse_copy_init(&cs, 1, req, iov, nr_segs);
+	spin_unlock(&fc->lock);
+	fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);
 	err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
 	if (!err)
 		err = fuse_copy_args(&cs, in->numargs, in->argpages,
 				     (struct fuse_arg *) in->args, 0);
 	fuse_copy_finish(&cs);
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	req->locked = 0;
 	if (!err && req->interrupted)
 		err = -ENOENT;
@@ -663,12 +649,12 @@
 	else {
 		req->state = FUSE_REQ_SENT;
 		list_move_tail(&req->list, &fc->processing);
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 	}
 	return reqsize;
 
  err_unlock:
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 	return err;
 }
 
@@ -735,9 +721,9 @@
 	struct fuse_copy_state cs;
 	struct fuse_conn *fc = fuse_get_conn(file);
 	if (!fc)
-		return -ENODEV;
+		return -EPERM;
 
-	fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
+	fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs);
 	if (nbytes < sizeof(struct fuse_out_header))
 		return -EINVAL;
 
@@ -749,7 +735,7 @@
 	    oh.len != nbytes)
 		goto err_finish;
 
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	err = -ENOENT;
 	if (!fc->connected)
 		goto err_unlock;
@@ -760,9 +746,9 @@
 		goto err_unlock;
 
 	if (req->interrupted) {
-		spin_unlock(&fuse_lock);
+		spin_unlock(&fc->lock);
 		fuse_copy_finish(&cs);
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 		request_end(fc, req);
 		return -ENOENT;
 	}
@@ -770,12 +756,12 @@
 	req->out.h = oh;
 	req->locked = 1;
 	cs.req = req;
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 
 	err = copy_out_args(&cs, &req->out, nbytes);
 	fuse_copy_finish(&cs);
 
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	req->locked = 0;
 	if (!err) {
 		if (req->interrupted)
@@ -787,7 +773,7 @@
 	return err ? err : nbytes;
 
  err_unlock:
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
  err_finish:
 	fuse_copy_finish(&cs);
 	return err;
@@ -804,18 +790,19 @@
 
 static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
 {
-	struct fuse_conn *fc = fuse_get_conn(file);
 	unsigned mask = POLLOUT | POLLWRNORM;
-
+	struct fuse_conn *fc = fuse_get_conn(file);
 	if (!fc)
-		return -ENODEV;
+		return POLLERR;
 
 	poll_wait(file, &fc->waitq, wait);
 
-	spin_lock(&fuse_lock);
-	if (!list_empty(&fc->pending))
-                mask |= POLLIN | POLLRDNORM;
-	spin_unlock(&fuse_lock);
+	spin_lock(&fc->lock);
+	if (!fc->connected)
+		mask = POLLERR;
+	else if (!list_empty(&fc->pending))
+		mask |= POLLIN | POLLRDNORM;
+	spin_unlock(&fc->lock);
 
 	return mask;
 }
@@ -823,7 +810,7 @@
 /*
  * Abort all requests on the given list (pending or processing)
  *
- * This function releases and reacquires fuse_lock
+ * This function releases and reacquires fc->lock
  */
 static void end_requests(struct fuse_conn *fc, struct list_head *head)
 {
@@ -832,7 +819,7 @@
 		req = list_entry(head->next, struct fuse_req, list);
 		req->out.h.error = -ECONNABORTED;
 		request_end(fc, req);
-		spin_lock(&fuse_lock);
+		spin_lock(&fc->lock);
 	}
 }
 
@@ -863,10 +850,10 @@
 			req->end = NULL;
 			/* The end function will consume this reference */
 			__fuse_get_request(req);
-			spin_unlock(&fuse_lock);
+			spin_unlock(&fc->lock);
 			wait_event(req->waitq, !req->locked);
 			end(fc, req);
-			spin_lock(&fuse_lock);
+			spin_lock(&fc->lock);
 		}
 	}
 }
@@ -893,35 +880,44 @@
  */
 void fuse_abort_conn(struct fuse_conn *fc)
 {
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	if (fc->connected) {
 		fc->connected = 0;
 		end_io_requests(fc);
 		end_requests(fc, &fc->pending);
 		end_requests(fc, &fc->processing);
 		wake_up_all(&fc->waitq);
+		kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 	}
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 }
 
 static int fuse_dev_release(struct inode *inode, struct file *file)
 {
-	struct fuse_conn *fc;
-
-	spin_lock(&fuse_lock);
-	fc = file->private_data;
+	struct fuse_conn *fc = fuse_get_conn(file);
 	if (fc) {
+		spin_lock(&fc->lock);
 		fc->connected = 0;
 		end_requests(fc, &fc->pending);
 		end_requests(fc, &fc->processing);
-	}
-	spin_unlock(&fuse_lock);
-	if (fc)
+		spin_unlock(&fc->lock);
+		fasync_helper(-1, file, 0, &fc->fasync);
 		kobject_put(&fc->kobj);
+	}
 
 	return 0;
 }
 
+static int fuse_dev_fasync(int fd, struct file *file, int on)
+{
+	struct fuse_conn *fc = fuse_get_conn(file);
+	if (!fc)
+		return -EPERM;
+
+	/* No locking - fasync_helper does its own locking */
+	return fasync_helper(fd, file, on, &fc->fasync);
+}
+
 const struct file_operations fuse_dev_operations = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -931,6 +927,7 @@
 	.writev		= fuse_dev_writev,
 	.poll		= fuse_dev_poll,
 	.release	= fuse_dev_release,
+	.fasync		= fuse_dev_fasync,
 };
 
 static struct miscdevice fuse_miscdevice = {
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 256355b..8d7546e 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -117,8 +117,8 @@
 			return 0;
 
 		fc = get_fuse_conn(inode);
-		req = fuse_get_request(fc);
-		if (!req)
+		req = fuse_get_req(fc);
+		if (IS_ERR(req))
 			return 0;
 
 		fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
@@ -188,9 +188,9 @@
 	if (entry->d_name.len > FUSE_NAME_MAX)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return ERR_PTR(-EINTR);
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return ERR_PTR(PTR_ERR(req));
 
 	fuse_lookup_init(req, dir, entry, &outarg);
 	request_send(fc, req);
@@ -244,15 +244,14 @@
 	struct file *file;
 	int flags = nd->intent.open.flags - 1;
 
-	err = -ENOSYS;
 	if (fc->no_create)
-		goto out;
+		return -ENOSYS;
 
-	err = -EINTR;
-	req = fuse_get_request(fc);
-	if (!req)
-		goto out;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
+	err = -ENOMEM;
 	ff = fuse_file_alloc();
 	if (!ff)
 		goto out_put_request;
@@ -314,7 +313,6 @@
 	fuse_file_free(ff);
  out_put_request:
 	fuse_put_request(fc, req);
- out:
 	return err;
 }
 
@@ -375,9 +373,9 @@
 {
 	struct fuse_mknod_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.mode = mode;
@@ -407,9 +405,9 @@
 {
 	struct fuse_mkdir_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.mode = mode;
@@ -427,9 +425,9 @@
 {
 	struct fuse_conn *fc = get_fuse_conn(dir);
 	unsigned len = strlen(link) + 1;
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->in.h.opcode = FUSE_SYMLINK;
 	req->in.numargs = 2;
@@ -444,9 +442,9 @@
 {
 	int err;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->in.h.opcode = FUSE_UNLINK;
 	req->in.h.nodeid = get_node_id(dir);
@@ -476,9 +474,9 @@
 {
 	int err;
 	struct fuse_conn *fc = get_fuse_conn(dir);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->in.h.opcode = FUSE_RMDIR;
 	req->in.h.nodeid = get_node_id(dir);
@@ -504,9 +502,9 @@
 	int err;
 	struct fuse_rename_in inarg;
 	struct fuse_conn *fc = get_fuse_conn(olddir);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.newdir = get_node_id(newdir);
@@ -553,9 +551,9 @@
 	struct fuse_link_in inarg;
 	struct inode *inode = entry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.oldnodeid = get_node_id(inode);
@@ -583,9 +581,9 @@
 	int err;
 	struct fuse_attr_out arg;
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	struct fuse_req *req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->in.h.opcode = FUSE_GETATTR;
 	req->in.h.nodeid = get_node_id(inode);
@@ -673,9 +671,9 @@
 	if (fc->no_access)
 		return 0;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.mask = mask;
@@ -780,9 +778,9 @@
 	if (is_bad_inode(inode))
 		return -EIO;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	page = alloc_page(GFP_KERNEL);
 	if (!page) {
@@ -809,11 +807,11 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_request(fc);
+	struct fuse_req *req = fuse_get_req(fc);
 	char *link;
 
-	if (!req)
-		return ERR_PTR(-EINTR);
+	if (IS_ERR(req))
+		return ERR_PTR(PTR_ERR(req));
 
 	link = (char *) __get_free_page(GFP_KERNEL);
 	if (!link) {
@@ -933,9 +931,9 @@
 		}
 	}
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	iattr_to_fattr(attr, &inarg);
@@ -995,9 +993,9 @@
 	if (fc->no_setxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.size = size;
@@ -1035,9 +1033,9 @@
 	if (fc->no_getxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.size = size;
@@ -1085,9 +1083,9 @@
 	if (fc->no_listxattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.size = size;
@@ -1131,9 +1129,9 @@
 	if (fc->no_removexattr)
 		return -EOPNOTSUPP;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->in.h.opcode = FUSE_REMOVEXATTR;
 	req->in.h.nodeid = get_node_id(inode);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 975f269..fc342cf 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
@@ -22,9 +22,9 @@
 	struct fuse_req *req;
 	int err;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
@@ -184,9 +184,9 @@
 	if (fc->no_flush)
 		return 0;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
@@ -223,9 +223,9 @@
 	if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
 		return 0;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
@@ -297,9 +297,9 @@
 	if (is_bad_inode(inode))
 		goto out;
 
-	err = -EINTR;
-	req = fuse_get_request(fc);
-	if (!req)
+	req = fuse_get_req(fc);
+	err = PTR_ERR(req);
+	if (IS_ERR(req))
 		goto out;
 
 	req->out.page_zeroing = 1;
@@ -368,10 +368,10 @@
 	     (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
 	     req->pages[req->num_pages - 1]->index + 1 != page->index)) {
 		fuse_send_readpages(req, data->file, inode);
-		data->req = req = fuse_get_request(fc);
-		if (!req) {
+		data->req = req = fuse_get_req(fc);
+		if (IS_ERR(req)) {
 			unlock_page(page);
-			return -EINTR;
+			return PTR_ERR(req);
 		}
 	}
 	req->pages[req->num_pages] = page;
@@ -392,13 +392,17 @@
 
 	data.file = file;
 	data.inode = inode;
-	data.req = fuse_get_request(fc);
-	if (!data.req)
-		return -EINTR;
+	data.req = fuse_get_req(fc);
+	if (IS_ERR(data.req))
+		return PTR_ERR(data.req);
 
 	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
-	if (!err)
-		fuse_send_readpages(data.req, file, inode);
+	if (!err) {
+		if (data.req->num_pages)
+			fuse_send_readpages(data.req, file, inode);
+		else
+			fuse_put_request(fc, data.req);
+	}
 	return err;
 }
 
@@ -451,9 +455,9 @@
 	if (is_bad_inode(inode))
 		return -EIO;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	req->num_pages = 1;
 	req->pages[0] = page;
@@ -528,9 +532,9 @@
 	if (is_bad_inode(inode))
 		return -EIO;
 
-	req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	while (count) {
 		size_t nres;
@@ -561,8 +565,12 @@
 		buf += nres;
 		if (nres != nbytes)
 			break;
-		if (count)
-			fuse_reset_request(req);
+		if (count) {
+			fuse_put_request(fc, req);
+			req = fuse_get_req(fc);
+			if (IS_ERR(req))
+				break;
+		}
 	}
 	fuse_put_request(fc, req);
 	if (res > 0) {
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index a16a04f..0474202 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
@@ -18,8 +18,8 @@
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
 
-/** If more requests are outstanding, then the operation will block */
-#define FUSE_MAX_OUTSTANDING 10
+/** Maximum number of outstanding background requests */
+#define FUSE_MAX_BACKGROUND 10
 
 /** It could be as large as PATH_MAX, but would that have any uses? */
 #define FUSE_NAME_MAX 1024
@@ -131,8 +131,8 @@
  * A request to the client
  */
 struct fuse_req {
-	/** This can be on either unused_list, pending processing or
-	    io lists in fuse_conn */
+	/** This can be on either pending processing or io lists in
+	    fuse_conn */
 	struct list_head list;
 
 	/** Entry on the background list */
@@ -144,15 +144,12 @@
 	/*
 	 * The following bitfields are either set once before the
 	 * request is queued or setting/clearing them is protected by
-	 * fuse_lock
+	 * fuse_conn->lock
 	 */
 
 	/** True if the request has reply */
 	unsigned isreply:1;
 
-	/** The request is preallocated */
-	unsigned preallocated:1;
-
 	/** The request was interrupted */
 	unsigned interrupted:1;
 
@@ -162,6 +159,9 @@
 	/** Data is being copied to/from the request */
 	unsigned locked:1;
 
+	/** Request is counted as "waiting" */
+	unsigned waiting:1;
+
 	/** State of the request */
 	enum fuse_req_state state;
 
@@ -213,6 +213,9 @@
  * unmounted.
  */
 struct fuse_conn {
+	/** Lock protecting accessess to  members of this structure */
+	spinlock_t lock;
+
 	/** The user id for this mount */
 	uid_t user_id;
 
@@ -244,19 +247,20 @@
 	    interrupted request) */
 	struct list_head background;
 
-	/** Controls the maximum number of outstanding requests */
-	struct semaphore outstanding_sem;
+	/** Number of requests currently in the background */
+	unsigned num_background;
 
-	/** This counts the number of outstanding requests if
-	    outstanding_sem would go negative */
-	unsigned outstanding_debt;
+	/** Flag indicating if connection is blocked.  This will be
+	    the case before the INIT reply is received, and if there
+	    are too many outstading backgrounds requests */
+	int blocked;
+
+	/** waitq for blocked connection */
+	wait_queue_head_t blocked_waitq;
 
 	/** RW semaphore for exclusion with fuse_put_super() */
 	struct rw_semaphore sbput_sem;
 
-	/** The list of unused requests */
-	struct list_head unused_list;
-
 	/** The next unique request id */
 	u64 reqctr;
 
@@ -318,6 +322,9 @@
 
 	/** kobject */
 	struct kobject kobj;
+
+	/** O_ASYNC requests */
+	struct fasync_struct *fasync;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -349,21 +356,6 @@
 extern const struct file_operations fuse_dev_operations;
 
 /**
- * This is the single global spinlock which protects FUSE's structures
- *
- * The following data is protected by this lock:
- *
- *  - the private_data field of the device file
- *  - the s_fs_info field of the super block
- *  - unused_list, pending, processing lists in fuse_conn
- *  - background list in fuse_conn
- *  - the unique request ID counter reqctr in fuse_conn
- *  - the sb (super_block) field in fuse_conn
- *  - the file (device file) field in fuse_conn
- */
-extern spinlock_t fuse_lock;
-
-/**
  * Get a filled in inode
  */
 struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
@@ -461,11 +453,11 @@
 /**
  * Reserve a preallocated request
  */
-struct fuse_req *fuse_get_request(struct fuse_conn *fc);
+struct fuse_req *fuse_get_req(struct fuse_conn *fc);
 
 /**
- * Decrement reference count of a request.  If count goes to zero put
- * on unused list (preallocated) or free request (not preallocated).
+ * Decrement reference count of a request.  If count goes to zero free
+ * the request.
  */
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
 
@@ -487,7 +479,7 @@
 /**
  * Release inodes and file associated with background request
  */
-void fuse_release_background(struct fuse_req *req);
+void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req);
 
 /* Abort all requests */
 void fuse_abort_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 879e6fb..7627022 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
@@ -22,7 +22,6 @@
 MODULE_DESCRIPTION("Filesystem in Userspace");
 MODULE_LICENSE("GPL");
 
-spinlock_t fuse_lock;
 static kmem_cache_t *fuse_inode_cachep;
 static struct subsystem connections_subsys;
 
@@ -207,15 +206,17 @@
 
 	down_write(&fc->sbput_sem);
 	while (!list_empty(&fc->background))
-		fuse_release_background(list_entry(fc->background.next,
+		fuse_release_background(fc,
+					list_entry(fc->background.next,
 						   struct fuse_req, bg_entry));
 
-	spin_lock(&fuse_lock);
+	spin_lock(&fc->lock);
 	fc->mounted = 0;
 	fc->connected = 0;
-	spin_unlock(&fuse_lock);
+	spin_unlock(&fc->lock);
 	up_write(&fc->sbput_sem);
 	/* Flush all readers on this fs */
+	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 	wake_up_all(&fc->waitq);
 	kobject_del(&fc->kobj);
 	kobject_put(&fc->kobj);
@@ -242,9 +243,9 @@
 	struct fuse_statfs_out outarg;
 	int err;
 
-        req = fuse_get_request(fc);
-	if (!req)
-		return -EINTR;
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
 
 	memset(&outarg, 0, sizeof(outarg));
 	req->in.numargs = 0;
@@ -369,15 +370,7 @@
 
 static void fuse_conn_release(struct kobject *kobj)
 {
-	struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
-
-	while (!list_empty(&fc->unused_list)) {
-		struct fuse_req *req;
-		req = list_entry(fc->unused_list.next, struct fuse_req, list);
-		list_del(&req->list);
-		fuse_request_free(req);
-	}
-	kfree(fc);
+	kfree(get_fuse_conn_kobj(kobj));
 }
 
 static struct fuse_conn *new_conn(void)
@@ -386,64 +379,25 @@
 
 	fc = kzalloc(sizeof(*fc), GFP_KERNEL);
 	if (fc) {
-		int i;
+		spin_lock_init(&fc->lock);
 		init_waitqueue_head(&fc->waitq);
+		init_waitqueue_head(&fc->blocked_waitq);
 		INIT_LIST_HEAD(&fc->pending);
 		INIT_LIST_HEAD(&fc->processing);
 		INIT_LIST_HEAD(&fc->io);
-		INIT_LIST_HEAD(&fc->unused_list);
 		INIT_LIST_HEAD(&fc->background);
-		sema_init(&fc->outstanding_sem, 1); /* One for INIT */
 		init_rwsem(&fc->sbput_sem);
 		kobj_set_kset_s(fc, connections_subsys);
 		kobject_init(&fc->kobj);
 		atomic_set(&fc->num_waiting, 0);
-		for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
-			struct fuse_req *req = fuse_request_alloc();
-			if (!req) {
-				kobject_put(&fc->kobj);
-				return NULL;
-			}
-			list_add(&req->list, &fc->unused_list);
-		}
 		fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 		fc->bdi.unplug_io_fn = default_unplug_io_fn;
 		fc->reqctr = 0;
+		fc->blocked = 1;
 	}
 	return fc;
 }
 
-static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
-{
-	struct fuse_conn *fc;
-	int err;
-
-	err = -EINVAL;
-	if (file->f_op != &fuse_dev_operations)
-		goto out_err;
-
-	err = -ENOMEM;
-	fc = new_conn();
-	if (!fc)
-		goto out_err;
-
-	spin_lock(&fuse_lock);
-	err = -EINVAL;
-	if (file->private_data)
-		goto out_unlock;
-
-	kobject_get(&fc->kobj);
-	file->private_data = fc;
-	spin_unlock(&fuse_lock);
-	return fc;
-
- out_unlock:
-	spin_unlock(&fuse_lock);
-	kobject_put(&fc->kobj);
- out_err:
-	return ERR_PTR(err);
-}
-
 static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
 {
 	struct fuse_attr attr;
@@ -467,7 +421,6 @@
 
 static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
-	int i;
 	struct fuse_init_out *arg = &req->misc.init_out;
 
 	if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
@@ -486,22 +439,13 @@
 		fc->minor = arg->minor;
 		fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
 	}
-
-	/* After INIT reply is received other requests can go
-	   out.  So do (FUSE_MAX_OUTSTANDING - 1) number of
-	   up()s on outstanding_sem.  The last up() is done in
-	   fuse_putback_request() */
-	for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
-		up(&fc->outstanding_sem);
-
 	fuse_put_request(fc, req);
+	fc->blocked = 0;
+	wake_up_all(&fc->blocked_waitq);
 }
 
-static void fuse_send_init(struct fuse_conn *fc)
+static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
 {
-	/* This is called from fuse_read_super() so there's guaranteed
-	   to be exactly one request available */
-	struct fuse_req *req = fuse_get_request(fc);
 	struct fuse_init_in *arg = &req->misc.init_in;
 
 	arg->major = FUSE_KERNEL_VERSION;
@@ -525,12 +469,9 @@
 
 static unsigned long long conn_id(void)
 {
+	/* BKL is held for ->get_sb() */
 	static unsigned long long ctr = 1;
-	unsigned long long val;
-	spin_lock(&fuse_lock);
-	val = ctr++;
-	spin_unlock(&fuse_lock);
-	return val;
+	return ctr++;
 }
 
 static int fuse_fill_super(struct super_block *sb, void *data, int silent)
@@ -540,6 +481,7 @@
 	struct fuse_mount_data d;
 	struct file *file;
 	struct dentry *root_dentry;
+	struct fuse_req *init_req;
 	int err;
 
 	if (!parse_fuse_opt((char *) data, &d))
@@ -555,10 +497,12 @@
 	if (!file)
 		return -EINVAL;
 
-	fc = get_conn(file, sb);
-	fput(file);
-	if (IS_ERR(fc))
-		return PTR_ERR(fc);
+	if (file->f_op != &fuse_dev_operations)
+		return -EINVAL;
+
+	fc = new_conn();
+	if (!fc)
+		return -ENOMEM;
 
 	fc->flags = d.flags;
 	fc->user_id = d.user_id;
@@ -579,27 +523,48 @@
 		goto err;
 	}
 
+	init_req = fuse_request_alloc();
+	if (!init_req)
+		goto err_put_root;
+
 	err = kobject_set_name(&fc->kobj, "%llu", conn_id());
 	if (err)
-		goto err_put_root;
+		goto err_free_req;
 
 	err = kobject_add(&fc->kobj);
 	if (err)
-		goto err_put_root;
+		goto err_free_req;
+
+	/* Setting file->private_data can't race with other mount()
+	   instances, since BKL is held for ->get_sb() */
+	err = -EINVAL;
+	if (file->private_data)
+		goto err_kobject_del;
 
 	sb->s_root = root_dentry;
-	spin_lock(&fuse_lock);
 	fc->mounted = 1;
 	fc->connected = 1;
-	spin_unlock(&fuse_lock);
+	kobject_get(&fc->kobj);
+	file->private_data = fc;
+	/*
+	 * atomic_dec_and_test() in fput() provides the necessary
+	 * memory barrier for file->private_data to be visible on all
+	 * CPUs after this
+	 */
+	fput(file);
 
-	fuse_send_init(fc);
+	fuse_send_init(fc, init_req);
 
 	return 0;
 
+ err_kobject_del:
+	kobject_del(&fc->kobj);
+ err_free_req:
+	fuse_request_free(init_req);
  err_put_root:
 	dput(root_dentry);
  err:
+	fput(file);
 	kobject_put(&fc->kobj);
 	return err;
 }
@@ -753,7 +718,6 @@
 	printk("fuse init (API version %i.%i)\n",
 	       FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
 
-	spin_lock_init(&fuse_lock);
 	res = fuse_fs_init();
 	if (res)
 		goto err;
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 8f07e8f..746abc9 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -466,8 +466,7 @@
 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
 	     *p && *p != node; p = &(*p)->next_hash)
 		;
-	if (!*p)
-		BUG();
+	BUG_ON(!*p);
 	*p = node->next_hash;
 	node->tree->node_hash_cnt--;
 }
@@ -622,8 +621,7 @@
 
 		dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
 		       node->tree->cnid, node->this, atomic_read(&node->refcnt));
-		if (!atomic_read(&node->refcnt))
-			BUG();
+		BUG_ON(!atomic_read(&node->refcnt));
 		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
 			return;
 		for (i = 0; i < tree->pages_per_bnode; i++) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index a67edfa..effa899 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -269,8 +269,7 @@
 	u8 *data, byte, m;
 
 	dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this);
-	if (!node->this)
-		BUG();
+	BUG_ON(!node->this);
 	tree = node->tree;
 	nidx = node->this;
 	node = hfs_bnode_find(tree, 0);
diff --git a/fs/inode.c b/fs/inode.c
index 32b7c33..3a2446a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -172,8 +172,7 @@
 
 void destroy_inode(struct inode *inode) 
 {
-	if (inode_has_buffers(inode))
-		BUG();
+	BUG_ON(inode_has_buffers(inode));
 	security_inode_free(inode);
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
@@ -249,12 +248,9 @@
 	might_sleep();
 	invalidate_inode_buffers(inode);
        
-	if (inode->i_data.nrpages)
-		BUG();
-	if (!(inode->i_state & I_FREEING))
-		BUG();
-	if (inode->i_state & I_CLEAR)
-		BUG();
+	BUG_ON(inode->i_data.nrpages);
+	BUG_ON(!(inode->i_state & I_FREEING));
+	BUG_ON(inode->i_state & I_CLEAR);
 	wait_on_inode(inode);
 	DQUOT_DROP(inode);
 	if (inode->i_sb && inode->i_sb->s_op->clear_inode)
@@ -1054,8 +1050,7 @@
 	hlist_del_init(&inode->i_hash);
 	spin_unlock(&inode_lock);
 	wake_up_inode(inode);
-	if (inode->i_state != I_CLEAR)
-		BUG();
+	BUG_ON(inode->i_state != I_CLEAR);
 	destroy_inode(inode);
 }
 
diff --git a/fs/inotify.c b/fs/inotify.c
index 367c487..1f50302 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -538,7 +538,7 @@
 	WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
 	spin_lock(&entry->d_lock);
 	parent = entry->d_parent;
-	if (inotify_inode_watched(parent->d_inode))
+	if (parent->d_inode && inotify_inode_watched(parent->d_inode))
 		entry->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
 	spin_unlock(&entry->d_lock);
 }
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 7b77a95..ff2a872 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -35,8 +35,7 @@
 	pid_t pid;
 	int ret = 0;
 
-	if (c->gc_task)
-		BUG();
+	BUG_ON(c->gc_task);
 
 	init_completion(&c->gc_thread_start);
 	init_completion(&c->gc_thread_exit);
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index d2b66ba..3ef7391 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -650,7 +650,7 @@
 	svc_wake_up(block->b_daemon);
 }
 
-void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(void *data)
 {
 	struct nlm_rqst		*call = data;
 
diff --git a/fs/locks.c b/fs/locks.c
index dda83d6..efad7988 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2230,7 +2230,12 @@
 
 	lock_kernel();
 	j = 0;
-	rcu_read_lock();
+
+	/*
+	 * We are not taking a ref to the file structures, so
+	 * we need to acquire ->file_lock.
+	 */
+	spin_lock(&files->file_lock);
 	fdt = files_fdtable(files);
 	for (;;) {
 		unsigned long set;
@@ -2248,7 +2253,7 @@
 			set >>= 1;
 		}
 	}
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	unlock_kernel();
 }
 EXPORT_SYMBOL(steal_locks);
diff --git a/fs/namespace.c b/fs/namespace.c
index bf478ad..2c5f1f8 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -899,11 +899,13 @@
 /*
  * do loopback mount.
  */
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
 {
 	struct nameidata old_nd;
 	struct vfsmount *mnt = NULL;
+	int recurse = flags & MS_REC;
 	int err = mount_is_safe(nd);
+
 	if (err)
 		return err;
 	if (!old_name || !*old_name)
@@ -937,6 +939,7 @@
 		spin_unlock(&vfsmount_lock);
 		release_mounts(&umount_list);
 	}
+	mnt->mnt_flags = mnt_flags;
 
 out:
 	up_write(&namespace_sem);
@@ -1350,7 +1353,7 @@
 		retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
 				    data_page);
 	else if (flags & MS_BIND)
-		retval = do_loopback(&nd, dev_name, flags & MS_REC);
+		retval = do_loopback(&nd, dev_name, flags, mnt_flags);
 	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
 		retval = do_change_type(&nd, flags);
 	else if (flags & MS_MOVE)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a23f348..cae74dd 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -128,15 +128,14 @@
 static int
 nfs_opendir(struct inode *inode, struct file *filp)
 {
-	int res = 0;
+	int res;
 
 	dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
 			inode->i_sb->s_id, inode->i_ino);
 
 	lock_kernel();
 	/* Call generic open code in order to cache credentials */
-	if (!res)
-		res = nfs_open(inode, filp);
+	res = nfs_open(inode, filp);
 	unlock_kernel();
 	return res;
 }
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 0f583cb..3c72b0c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -112,10 +112,9 @@
  */
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
 {
-	struct dentry *dentry = iocb->ki_filp->f_dentry;
-
 	dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
-			dentry->d_name.name, (long long) pos, nr_segs);
+			iocb->ki_filp->f_dentry->d_name.name,
+			(long long) pos, nr_segs);
 
 	return -EINVAL;
 }
@@ -468,7 +467,6 @@
 static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 {
 	struct nfs_write_data *data = dreq->commit_data;
-	struct rpc_task *task = &data->task;
 
 	data->inode = dreq->inode;
 	data->cred = dreq->ctx->cred;
@@ -489,7 +487,7 @@
 	/* Note: task.tk_ops->rpc_release will free dreq->commit_data */
 	dreq->commit_data = NULL;
 
-	dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+	dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
 	lock_kernel();
 	rpc_execute(&data->task);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f1df2c8..fade02c 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -534,10 +534,9 @@
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
-	struct inode * inode = filp->f_mapping->host;
-
 	dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
-			inode->i_sb->s_id, inode->i_ino,
+			filp->f_dentry->d_inode->i_sb->s_id,
+			filp->f_dentry->d_inode->i_ino,
 			fl->fl_type, fl->fl_flags);
 
 	/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f7656b..d0b991a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -700,12 +700,9 @@
 	/*
 	 * Display superblock I/O counters
 	 */
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for_each_possible_cpu(cpu) {
 		struct nfs_iostats *stats;
 
-		if (!cpu_possible(cpu))
-			continue;
-
 		preempt_disable();
 		stats = per_cpu_ptr(nfss->io_stats, cpu);
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 47ece1d..d86c0db 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1218,7 +1218,7 @@
 	return status;
 }
 
-static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
 {
 	struct file *filp;
 
@@ -1227,8 +1227,10 @@
 		struct nfs_open_context *ctx;
 		ctx = (struct nfs_open_context *)filp->private_data;
 		ctx->state = state;
-	} else
-		nfs4_close_state(state, nd->intent.open.flags);
+		return 0;
+	}
+	nfs4_close_state(state, nd->intent.open.flags);
+	return PTR_ERR(filp);
 }
 
 struct dentry *
@@ -1835,7 +1837,7 @@
 			nfs_setattr_update_inode(state->inode, sattr);
 	}
 	if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
-		nfs4_intent_set_file(nd, dentry, state);
+		status = nfs4_intent_set_file(nd, dentry, state);
 	else
 		nfs4_close_state(state, flags);
 out:
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index cfe9ce8..6e92b0f 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -14,46 +14,46 @@
 
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
-	struct svc_cred	*cred = &rqstp->rq_cred;
+	struct svc_cred	cred = rqstp->rq_cred;
 	int i;
 	int ret;
 
 	if (exp->ex_flags & NFSEXP_ALLSQUASH) {
-		cred->cr_uid = exp->ex_anon_uid;
-		cred->cr_gid = exp->ex_anon_gid;
-		put_group_info(cred->cr_group_info);
-		cred->cr_group_info = groups_alloc(0);
+		cred.cr_uid = exp->ex_anon_uid;
+		cred.cr_gid = exp->ex_anon_gid;
+		cred.cr_group_info = groups_alloc(0);
 	} else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
 		struct group_info *gi;
-		if (!cred->cr_uid)
-			cred->cr_uid = exp->ex_anon_uid;
-		if (!cred->cr_gid)
-			cred->cr_gid = exp->ex_anon_gid;
-		gi = groups_alloc(cred->cr_group_info->ngroups);
+		if (!cred.cr_uid)
+			cred.cr_uid = exp->ex_anon_uid;
+		if (!cred.cr_gid)
+			cred.cr_gid = exp->ex_anon_gid;
+		gi = groups_alloc(cred.cr_group_info->ngroups);
 		if (gi)
-			for (i = 0; i < cred->cr_group_info->ngroups; i++) {
-				if (!GROUP_AT(cred->cr_group_info, i))
+			for (i = 0; i < cred.cr_group_info->ngroups; i++) {
+				if (!GROUP_AT(cred.cr_group_info, i))
 					GROUP_AT(gi, i) = exp->ex_anon_gid;
 				else
-					GROUP_AT(gi, i) = GROUP_AT(cred->cr_group_info, i);
+					GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i);
 			}
-		put_group_info(cred->cr_group_info);
-		cred->cr_group_info = gi;
-	}
+		cred.cr_group_info = gi;
+	} else
+		get_group_info(cred.cr_group_info);
 
-	if (cred->cr_uid != (uid_t) -1)
-		current->fsuid = cred->cr_uid;
+	if (cred.cr_uid != (uid_t) -1)
+		current->fsuid = cred.cr_uid;
 	else
 		current->fsuid = exp->ex_anon_uid;
-	if (cred->cr_gid != (gid_t) -1)
-		current->fsgid = cred->cr_gid;
+	if (cred.cr_gid != (gid_t) -1)
+		current->fsgid = cred.cr_gid;
 	else
 		current->fsgid = exp->ex_anon_gid;
 
-	if (!cred->cr_group_info)
+	if (!cred.cr_group_info)
 		return -ENOMEM;
-	ret = set_current_groups(cred->cr_group_info);
-	if ((cred->cr_uid)) {
+	ret = set_current_groups(cred.cr_group_info);
+	put_group_info(cred.cr_group_info);
+	if ((cred.cr_uid)) {
 		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
 	} else {
 		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c340be0..4e05781 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -422,7 +422,7 @@
 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
 		goto out;
 	err = path_lookup(buf, 0, &nd);
-	if (err) goto out;
+	if (err) goto out_no_path;
 
 	exp.h.flags = 0;
 	exp.ex_client = dom;
@@ -475,6 +475,7 @@
  out:
 	if (nd.dentry)
 		path_release(&nd);
+ out_no_path:
 	if (dom)
 		auth_domain_put(dom);
 	kfree(buf);
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 6d2dfed..f61142a 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -682,7 +682,7 @@
   PROC(lookup,	 dirop,		dirop,		fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
   PROC(access,	 access,	access,		fhandle,  RC_NOCACHE, ST+pAT+1),
   PROC(readlink, readlink,	readlink,	fhandle,  RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
-  PROC(read,	 read,		read,		fhandle,  RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+  PROC(read,	 read,		read,		fhandle,  RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4),
   PROC(write,	 write,		write,		fhandle,  RC_REPLBUFF, ST+WC+4),
   PROC(create,	 create,	create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
   PROC(mkdir,	 mkdir,		create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 7391f4a..edb107e 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -710,9 +710,9 @@
 		/* Also, the remaining entries are for named users and
 		 * groups, and come in threes (mask, allow, deny): */
 		if (n4acl->naces < 7)
-			return -1;
+			return -EINVAL;
 		if ((n4acl->naces - 7) % 3)
-			return -1;
+			return -EINVAL;
 		return 4 + (n4acl->naces - 7)/3;
 	}
 }
@@ -790,7 +790,7 @@
 			continue;
 
 		error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
-				ace->access_mask, ace->whotype, ace->who) == -1;
+				ace->access_mask, ace->whotype, ace->who);
 		if (error < 0)
 			goto out;
 
@@ -866,7 +866,7 @@
 	struct nfs4_ace *ace;
 
 	if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
-		return -1;
+		return -ENOMEM;
 
 	ace->type = type;
 	ace->flag = flag;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c872bd0..dbaf3f9 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -441,8 +441,9 @@
 		goto out_clnt;
 	}
 
-	/* the task holds a reference to the nfs4_client struct */
 	cb->cb_client = clnt;
+
+	/* the task holds a reference to the nfs4_client struct */
 	atomic_inc(&clp->cl_count);
 
 	msg.rpc_cred = nfsd4_lookupcred(clp,0);
@@ -460,13 +461,12 @@
 out_rpciod:
 	atomic_dec(&clp->cl_count);
 	rpciod_down();
+	cb->cb_client = NULL;
 out_clnt:
 	rpc_shutdown_client(clnt);
-	goto out_err;
 out_err:
 	dprintk("NFSD: warning: no callback path to client %.*s\n",
 		(int)clp->cl_name.len, clp->cl_name.data);
-	cb->cb_client = NULL;
 }
 
 static void
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6d63f1d..b0e095e 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -288,8 +288,6 @@
 	fh_put(current_fh);
 	status = exp_pseudoroot(rqstp->rq_client, current_fh,
 			      &rqstp->rq_chandle);
-	if (!status)
-		status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export));
 	return status;
 }
 
@@ -975,7 +973,7 @@
  */
 static struct svc_procedure		nfsd_procedures4[2] = {
   PROC(null,	 void,		void,		void,	  RC_NOCACHE, 1),
-  PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE)
+  PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE/4)
 };
 
 struct svc_version	nfsd_version4 = {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 47ec112..96c7578 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -147,6 +147,42 @@
 	kref_get(&fi->fi_ref);
 }
 
+static int num_delegations;
+
+/*
+ * Open owner state (share locks)
+ */
+
+/* hash tables for nfs4_stateowner */
+#define OWNER_HASH_BITS              8
+#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
+#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
+
+#define ownerid_hashval(id) \
+        ((id) & OWNER_HASH_MASK)
+#define ownerstr_hashval(clientid, ownername) \
+        (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
+
+static struct list_head	ownerid_hashtbl[OWNER_HASH_SIZE];
+static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
+
+/* hash table for nfs4_file */
+#define FILE_HASH_BITS                   8
+#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
+#define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
+/* hash table for (open)nfs4_stateid */
+#define STATEID_HASH_BITS              10
+#define STATEID_HASH_SIZE              (1 << STATEID_HASH_BITS)
+#define STATEID_HASH_MASK              (STATEID_HASH_SIZE - 1)
+
+#define file_hashval(x) \
+        hash_ptr(x, FILE_HASH_BITS)
+#define stateid_hashval(owner_id, file_id)  \
+        (((owner_id) + (file_id)) & STATEID_HASH_MASK)
+
+static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
+
 static struct nfs4_delegation *
 alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
 {
@@ -155,9 +191,12 @@
 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
 	dprintk("NFSD alloc_init_deleg\n");
+	if (num_delegations > STATEID_HASH_SIZE * 4)
+		return NULL;
 	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
 	if (dp == NULL)
 		return dp;
+	num_delegations++;
 	INIT_LIST_HEAD(&dp->dl_perfile);
 	INIT_LIST_HEAD(&dp->dl_perclnt);
 	INIT_LIST_HEAD(&dp->dl_recall_lru);
@@ -192,6 +231,7 @@
 		dprintk("NFSD: freeing dp %p\n",dp);
 		put_nfs4_file(dp->dl_file);
 		kmem_cache_free(deleg_slab, dp);
+		num_delegations--;
 	}
 }
 
@@ -330,22 +370,29 @@
 }
 
 static void
+shutdown_callback_client(struct nfs4_client *clp)
+{
+	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+
+	/* shutdown rpc client, ending any outstanding recall rpcs */
+	if (clnt) {
+		clp->cl_callback.cb_client = NULL;
+		rpc_shutdown_client(clnt);
+		rpciod_down();
+	}
+}
+
+static void
 expire_client(struct nfs4_client *clp)
 {
 	struct nfs4_stateowner *sop;
 	struct nfs4_delegation *dp;
-	struct nfs4_callback *cb = &clp->cl_callback;
-	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
 	struct list_head reaplist;
 
 	dprintk("NFSD: expire_client cl_count %d\n",
 	                    atomic_read(&clp->cl_count));
 
-	/* shutdown rpc client, ending any outstanding recall rpcs */
-	if (atomic_read(&cb->cb_set) == 1 && clnt) {
-		rpc_shutdown_client(clnt);
-		clnt = clp->cl_callback.cb_client = NULL;
-	}
+	shutdown_callback_client(clp);
 
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
@@ -936,40 +983,6 @@
 	return status;
 }
 
-/* 
- * Open owner state (share locks)
- */
-
-/* hash tables for nfs4_stateowner */
-#define OWNER_HASH_BITS              8
-#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
-#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
-
-#define ownerid_hashval(id) \
-        ((id) & OWNER_HASH_MASK)
-#define ownerstr_hashval(clientid, ownername) \
-        (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
-
-static struct list_head	ownerid_hashtbl[OWNER_HASH_SIZE];
-static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
-
-/* hash table for nfs4_file */
-#define FILE_HASH_BITS                   8
-#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
-#define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
-/* hash table for (open)nfs4_stateid */
-#define STATEID_HASH_BITS              10
-#define STATEID_HASH_SIZE              (1 << STATEID_HASH_BITS)
-#define STATEID_HASH_MASK              (STATEID_HASH_SIZE - 1)
-
-#define file_hashval(x) \
-        hash_ptr(x, FILE_HASH_BITS)
-#define stateid_hashval(owner_id, file_id)  \
-        (((owner_id) + (file_id)) & STATEID_HASH_MASK)
-
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
-static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
-
 /* OPEN Share state helper functions */
 static inline struct nfs4_file *
 alloc_init_file(struct inode *ino)
@@ -1186,8 +1199,7 @@
 {
 	dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
 
-	unhash_stateowner(sop);
-	list_add_tail(&sop->so_close_lru, &close_lru);
+	list_move_tail(&sop->so_close_lru, &close_lru);
 	sop->so_time = get_seconds();
 }
 
@@ -1916,8 +1928,7 @@
 		}
 		dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
 			sop->so_id);
-		list_del(&sop->so_close_lru);
-		nfs4_put_stateowner(sop);
+		release_stateowner(sop);
 	}
 	if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
 		clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -2495,36 +2506,27 @@
 		lock->fl_end = OFFSET_MAX;
 }
 
-static int
-nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
-{
-	struct nfs4_stateowner *local = NULL;
-	int status = 0;
-			        
-	if (hashval >= LOCK_HASH_SIZE)
-		goto out;
-	list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
-		if (local == sop) {
-			status = 1;
-			goto out;
-		}
-	}
-out:
-	return status;
-}
-
+/* Hack!: For now, we're defining this just so we can use a pointer to it
+ * as a unique cookie to identify our (NFSv4's) posix locks. */
+static struct lock_manager_operations nfsd_posix_mng_ops  = {
+};
 
 static inline void
 nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
 {
-	struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
-	unsigned int hval = lockownerid_hashval(sop->so_id);
+	struct nfs4_stateowner *sop;
+	unsigned int hval;
 
-	deny->ld_sop = NULL;
-	if (nfs4_verify_lock_stateowner(sop, hval)) {
+	if (fl->fl_lmops == &nfsd_posix_mng_ops) {
+		sop = (struct nfs4_stateowner *) fl->fl_owner;
+		hval = lockownerid_hashval(sop->so_id);
 		kref_get(&sop->so_ref);
 		deny->ld_sop = sop;
 		deny->ld_clientid = sop->so_client->cl_clientid;
+	} else {
+		deny->ld_sop = NULL;
+		deny->ld_clientid.cl_boot = 0;
+		deny->ld_clientid.cl_id = 0;
 	}
 	deny->ld_start = fl->fl_start;
 	deny->ld_length = ~(u64)0;
@@ -2736,6 +2738,7 @@
 	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX;
+	file_lock.fl_lmops = &nfsd_posix_mng_ops;
 
 	file_lock.fl_start = lock->lk_offset;
 	if ((lock->lk_length == ~(u64)0) || 
@@ -2841,6 +2844,7 @@
 		file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
 	file_lock.fl_pid = current->tgid;
 	file_lock.fl_flags = FL_POSIX;
+	file_lock.fl_lmops = &nfsd_posix_mng_ops;
 
 	file_lock.fl_start = lockt->lt_offset;
 	if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
@@ -2900,6 +2904,7 @@
 	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX; 
+	file_lock.fl_lmops = &nfsd_posix_mng_ops;
 	file_lock.fl_start = locku->lu_offset;
 
 	if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
@@ -3211,15 +3216,8 @@
 	int i;
 	struct nfs4_client *clp = NULL;
 	struct nfs4_delegation *dp = NULL;
-	struct nfs4_stateowner *sop = NULL;
 	struct list_head *pos, *next, reaplist;
 
-	list_for_each_safe(pos, next, &close_lru) {
-		sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
-		list_del(&sop->so_close_lru);
-		nfs4_put_stateowner(sop);
-	}
-
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		while (!list_empty(&conf_id_hashtbl[i])) {
 			clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
@@ -3244,8 +3242,6 @@
 	}
 
 	cancel_delayed_work(&laundromat_work);
-	flush_workqueue(laundry_wq);
-	destroy_workqueue(laundry_wq);
 	nfsd4_shutdown_recdir();
 	nfs4_init = 0;
 }
@@ -3253,6 +3249,8 @@
 void
 nfs4_state_shutdown(void)
 {
+	cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+	destroy_workqueue(laundry_wq);
 	nfs4_lock_state();
 	nfs4_release_reclaim();
 	__nfs4_state_shutdown();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 03857fd..de3998f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -299,11 +299,10 @@
 						buf, dummy32, &ace.who);
 			if (status)
 				goto out_nfserr;
-			if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
-				 ace.access_mask, ace.whotype, ace.who) != 0) {
-				status = -ENOMEM;
+			status = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+				 ace.access_mask, ace.whotype, ace.who);
+			if (status)
 				goto out_nfserr;
-			}
 		}
 	} else
 		*acl = NULL;
@@ -2085,27 +2084,20 @@
 	WRITE32(eof);
 	WRITE32(maxcount);
 	ADJUST_ARGS();
-	resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
-
+	resp->xbuf->head[0].iov_len = (char*)p
+					- (char*)resp->xbuf->head[0].iov_base;
 	resp->xbuf->page_len = maxcount;
 
-	/* read zero bytes -> don't set up tail */
-	if(!maxcount)
-		return 0;        
-
-	/* set up page for remaining responses */
-	svc_take_page(resp->rqstp);
-	resp->xbuf->tail[0].iov_base = 
-		page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
-	resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+	/* Use rest of head for padding and remaining ops: */
+	resp->rqstp->rq_restailpage = 0;
+	resp->xbuf->tail[0].iov_base = p;
 	resp->xbuf->tail[0].iov_len = 0;
-	resp->p = resp->xbuf->tail[0].iov_base;
-	resp->end = resp->p + PAGE_SIZE/4;
-
 	if (maxcount&3) {
-		*(resp->p)++ = 0;
+		RESERVE_SPACE(4);
+		WRITE32(0);
 		resp->xbuf->tail[0].iov_base += maxcount&3;
 		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+		ADJUST_ARGS();
 	}
 	return 0;
 }
@@ -2142,21 +2134,20 @@
 
 	WRITE32(maxcount);
 	ADJUST_ARGS();
-	resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
-
-	svc_take_page(resp->rqstp);
-	resp->xbuf->tail[0].iov_base = 
-		page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
-	resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
-	resp->xbuf->tail[0].iov_len = 0;
-	resp->p = resp->xbuf->tail[0].iov_base;
-	resp->end = resp->p + PAGE_SIZE/4;
-
+	resp->xbuf->head[0].iov_len = (char*)p
+				- (char*)resp->xbuf->head[0].iov_base;
 	resp->xbuf->page_len = maxcount;
+
+	/* Use rest of head for padding and remaining ops: */
+	resp->rqstp->rq_restailpage = 0;
+	resp->xbuf->tail[0].iov_base = p;
+	resp->xbuf->tail[0].iov_len = 0;
 	if (maxcount&3) {
-		*(resp->p)++ = 0;
+		RESERVE_SPACE(4);
+		WRITE32(0);
 		resp->xbuf->tail[0].iov_base += maxcount&3;
 		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
+		ADJUST_ARGS();
 	}
 	return 0;
 }
@@ -2166,7 +2157,7 @@
 {
 	int maxcount;
 	loff_t offset;
-	u32 *page, *savep;
+	u32 *page, *savep, *tailbase;
 	ENCODE_HEAD;
 
 	if (nfserr)
@@ -2182,6 +2173,7 @@
 	WRITE32(0);
 	ADJUST_ARGS();
 	resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+	tailbase = p;
 
 	maxcount = PAGE_SIZE;
 	if (maxcount > readdir->rd_maxcount)
@@ -2226,14 +2218,12 @@
 	*p++ = htonl(readdir->common.err == nfserr_eof);
 	resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
 
-	/* allocate a page for the tail */
-	svc_take_page(resp->rqstp);
-	resp->xbuf->tail[0].iov_base = 
-		page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
-	resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
+	/* Use rest of head for padding and remaining ops: */
+	resp->rqstp->rq_restailpage = 0;
+	resp->xbuf->tail[0].iov_base = tailbase;
 	resp->xbuf->tail[0].iov_len = 0;
 	resp->p = resp->xbuf->tail[0].iov_base;
-	resp->end = resp->p + PAGE_SIZE/4;
+	resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
 
 	return 0;
 err_no_verf:
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 3e6b75c..06cd0db 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -553,7 +553,7 @@
   PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
   PROC(lookup,	 diropargs,	diropres,	fhandle,	RC_NOCACHE, ST+FH+AT),
   PROC(readlink, readlinkargs,	readlinkres,	none,		RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
-  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
+  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE/4),
   PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
   PROC(write,	 writeargs,	attrstat,	fhandle,	RC_REPLBUFF, ST+AT),
   PROC(create,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, ST+FH+AT),
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 3101833..6aa92d0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -371,7 +371,6 @@
 static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
 {
 	ssize_t buflen;
-	int error;
 
 	buflen = vfs_getxattr(dentry, key, NULL, 0);
 	if (buflen <= 0)
@@ -381,10 +380,7 @@
 	if (!*buf)
 		return -ENOMEM;
 
-	error = vfs_getxattr(dentry, key, *buf, buflen);
-	if (error < 0)
-		return error;
-	return buflen;
+	return vfs_getxattr(dentry, key, *buf, buflen);
 }
 #endif
 
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index bff0f0d..21f38ac 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -153,6 +153,7 @@
 struct o2hb_bio_wait_ctxt {
 	atomic_t          wc_num_reqs;
 	struct completion wc_io_complete;
+	int               wc_error;
 };
 
 static void o2hb_write_timeout(void *arg)
@@ -186,6 +187,7 @@
 {
 	atomic_set(&wc->wc_num_reqs, num_ios);
 	init_completion(&wc->wc_io_complete);
+	wc->wc_error = 0;
 }
 
 /* Used in error paths too */
@@ -218,8 +220,10 @@
 {
 	struct o2hb_bio_wait_ctxt *wc = bio->bi_private;
 
-	if (error)
+	if (error) {
 		mlog(ML_ERROR, "IO Error %d\n", error);
+		wc->wc_error = error;
+	}
 
 	if (bio->bi_size)
 		return 1;
@@ -390,6 +394,8 @@
 
 bail_and_wait:
 	o2hb_wait_on_io(reg, &wc);
+	if (wc.wc_error && !status)
+		status = wc.wc_error;
 
 	if (bios) {
 		for(i = 0; i < num_bios; i++)
@@ -790,20 +796,24 @@
 	return highest;
 }
 
-static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
+static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 {
 	int i, ret, highest_node, change = 0;
 	unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
 	struct bio *write_bio;
 	struct o2hb_bio_wait_ctxt write_wc;
 
-	if (o2nm_configured_node_map(configured_nodes, sizeof(configured_nodes)))
-		return;
+	ret = o2nm_configured_node_map(configured_nodes,
+				       sizeof(configured_nodes));
+	if (ret) {
+		mlog_errno(ret);
+		return ret;
+	}
 
 	highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
 	if (highest_node >= O2NM_MAX_NODES) {
 		mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
-		return;
+		return -EINVAL;
 	}
 
 	/* No sense in reading the slots of nodes that don't exist
@@ -813,7 +823,7 @@
 	ret = o2hb_read_slots(reg, highest_node + 1);
 	if (ret < 0) {
 		mlog_errno(ret);
-		return;
+		return ret;
 	}
 
 	/* With an up to date view of the slots, we can check that no
@@ -831,7 +841,7 @@
 	ret = o2hb_issue_node_write(reg, &write_bio, &write_wc);
 	if (ret < 0) {
 		mlog_errno(ret);
-		return;
+		return ret;
 	}
 
 	i = -1;
@@ -847,6 +857,15 @@
 	 */
 	o2hb_wait_on_io(reg, &write_wc);
 	bio_put(write_bio);
+	if (write_wc.wc_error) {
+		/* Do not re-arm the write timeout on I/O error - we
+		 * can't be sure that the new block ever made it to
+		 * disk */
+		mlog(ML_ERROR, "Write error %d on device \"%s\"\n",
+		     write_wc.wc_error, reg->hr_dev_name);
+		return write_wc.wc_error;
+	}
+
 	o2hb_arm_write_timeout(reg);
 
 	/* let the person who launched us know when things are steady */
@@ -854,6 +873,8 @@
 		if (atomic_dec_and_test(&reg->hr_steady_iterations))
 			wake_up(&o2hb_steady_queue);
 	}
+
+	return 0;
 }
 
 /* Subtract b from a, storing the result in a. a *must* have a larger
@@ -913,7 +934,10 @@
 		 * likely to time itself out. */
 		do_gettimeofday(&before_hb);
 
-		o2hb_do_disk_heartbeat(reg);
+		i = 0;
+		do {
+			ret = o2hb_do_disk_heartbeat(reg);
+		} while (ret && ++i < 2);
 
 		do_gettimeofday(&after_hb);
 		elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index c3764f4..74ca4e5f 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -139,6 +139,10 @@
 		return;
 	}
 
+	mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE,
+			"Lockres %s, requested ivmode. flags 0x%x\n",
+			lockres->l_name, lockres->l_flags);
+
 	/* we're downconverting. */
 	if (lockres->l_requested < lockres->l_level) {
 		if (lockres->l_requested <=
@@ -229,23 +233,42 @@
 
 	mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name);
 
-	if (status != DLM_NORMAL)
+	if (status != DLM_NORMAL && status != DLM_CANCELGRANT)
 		mlog(ML_ERROR, "Dlm returns status %d\n", status);
 
 	spin_lock(&lockres->l_lock);
-	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN)
+	/* The teardown flag gets set early during the unlock process,
+	 * so test the cancel flag to make sure that this ast isn't
+	 * for a concurrent cancel. */
+	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
+	    && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
 		lockres->l_level = LKM_IVMODE;
-	else {
+	} else if (status == DLM_CANCELGRANT) {
+		mlog(0, "Lock %s, cancel fails, flags 0x%x\n",
+		     lockres->l_name, lockres->l_flags);
+		/* We tried to cancel a convert request, but it was
+		 * already granted. Don't clear the busy flag - the
+		 * ast should've done this already. */
+		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+		goto out_noclear;
+	} else {
+		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+		/* Cancel succeeded, we want to re-queue */
+		mlog(0, "Lock %s, cancel succeeds, flags 0x%x\n",
+		     lockres->l_name, lockres->l_flags);
 		lockres->l_requested = LKM_IVMODE; /* cancel an
 						    * upconvert
 						    * request. */
 		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
 		/* we want the unblock thread to look at it again
 		 * now. */
-		__user_dlm_queue_lockres(lockres);
+		if (lockres->l_flags & USER_LOCK_BLOCKED)
+			__user_dlm_queue_lockres(lockres);
 	}
 
 	lockres->l_flags &= ~USER_LOCK_BUSY;
+out_noclear:
 	spin_unlock(&lockres->l_lock);
 
 	wake_up(&lockres->l_event);
@@ -268,13 +291,26 @@
 
 	spin_lock(&lockres->l_lock);
 
-	BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
-	BUG_ON(!(lockres->l_flags & USER_LOCK_QUEUED));
+	mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED),
+			"Lockres %s, flags 0x%x\n",
+			lockres->l_name, lockres->l_flags);
 
-	/* notice that we don't clear USER_LOCK_BLOCKED here. That's
-	 * for user_ast to do. */
+	/* notice that we don't clear USER_LOCK_BLOCKED here. If it's
+	 * set, we want user_ast clear it. */
 	lockres->l_flags &= ~USER_LOCK_QUEUED;
 
+	/* It's valid to get here and no longer be blocked - if we get
+	 * several basts in a row, we might be queued by the first
+	 * one, the unblock thread might run and clear the queued
+	 * flag, and finally we might get another bast which re-queues
+	 * us before our ast for the downconvert is called. */
+	if (!(lockres->l_flags & USER_LOCK_BLOCKED)) {
+		mlog(0, "Lockres %s, flags 0x%x: queued but not blocking\n",
+			lockres->l_name, lockres->l_flags);
+		spin_unlock(&lockres->l_lock);
+		goto drop_ref;
+	}
+
 	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
 		mlog(0, "lock is in teardown so we do nothing\n");
 		spin_unlock(&lockres->l_lock);
@@ -282,7 +318,9 @@
 	}
 
 	if (lockres->l_flags & USER_LOCK_BUSY) {
-		mlog(0, "BUSY flag detected...\n");
+		mlog(0, "Cancel lock %s, flags 0x%x\n",
+		     lockres->l_name, lockres->l_flags);
+
 		if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
 			spin_unlock(&lockres->l_lock);
 			goto drop_ref;
@@ -296,14 +334,7 @@
 				   LKM_CANCEL,
 				   user_unlock_ast,
 				   lockres);
-		if (status == DLM_CANCELGRANT) {
-			/* If we got this, then the ast was fired
-			 * before we could cancel. We cleanup our
-			 * state, and restart the function. */
-			spin_lock(&lockres->l_lock);
-			lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
-			spin_unlock(&lockres->l_lock);
-		} else if (status != DLM_NORMAL)
+		if (status != DLM_NORMAL)
 			user_log_dlm_error("dlmunlock", status, lockres);
 		goto drop_ref;
 	}
@@ -581,6 +612,14 @@
 	mlog(0, "asked to destroy %s\n", lockres->l_name);
 
 	spin_lock(&lockres->l_lock);
+	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+		mlog(0, "Lock is already torn down\n");
+		spin_unlock(&lockres->l_lock);
+		return 0;
+	}
+
+	lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+
 	while (lockres->l_flags & USER_LOCK_BUSY) {
 		spin_unlock(&lockres->l_lock);
 
@@ -606,7 +645,6 @@
 
 	lockres->l_flags &= ~USER_LOCK_ATTACHED;
 	lockres->l_flags |= USER_LOCK_BUSY;
-	lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
 	spin_unlock(&lockres->l_lock);
 
 	mlog(0, "unlocking lockres %s\n", lockres->l_name);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 34e903a..581eb45 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -260,6 +260,17 @@
 	if (new_i_size == le64_to_cpu(fe->i_size))
 		goto bail;
 
+	/* This forces other nodes to sync and drop their pages. Do
+	 * this even if we have a truncate without allocation change -
+	 * ocfs2 cluster sizes can be much greater than page size, so
+	 * we have to truncate them anyway.  */
+	status = ocfs2_data_lock(inode, 1);
+	if (status < 0) {
+		mlog_errno(status);
+		goto bail;
+	}
+	ocfs2_data_unlock(inode, 1);
+
 	if (le32_to_cpu(fe->i_clusters) ==
 	    ocfs2_clusters_for_bytes(osb->sb, new_i_size)) {
 		mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n",
@@ -272,14 +283,6 @@
 		goto bail;
 	}
 
-	/* This forces other nodes to sync and drop their pages */
-	status = ocfs2_data_lock(inode, 1);
-	if (status < 0) {
-		mlog_errno(status);
-		goto bail;
-	}
-	ocfs2_data_unlock(inode, 1);
-
 	/* alright, we're going to need to do a full blown alloc size
 	 * change. Orphan the inode so that recovery can complete the
 	 * truncate if necessary. This does the task of marking
diff --git a/fs/open.c b/fs/open.c
index c32c89d..53ec28c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -331,7 +331,10 @@
 
 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
 {
-	return do_sys_ftruncate(fd, length, 1);
+	long ret = do_sys_ftruncate(fd, length, 1);
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 /* LFS versions of truncate are only needed on 32 bit machines */
@@ -343,7 +346,10 @@
 
 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
 {
-	return do_sys_ftruncate(fd, length, 0);
+	long ret = do_sys_ftruncate(fd, length, 0);
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 #endif
 
@@ -1093,20 +1099,30 @@
 
 asmlinkage long sys_open(const char __user *filename, int flags, int mode)
 {
+	long ret;
+
 	if (force_o_largefile())
 		flags |= O_LARGEFILE;
 
-	return do_sys_open(AT_FDCWD, filename, flags, mode);
+	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(sys_open);
 
 asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
 			   int mode)
 {
+	long ret;
+
 	if (force_o_largefile())
 		flags |= O_LARGEFILE;
 
-	return do_sys_open(dfd, filename, flags, mode);
+	ret = do_sys_open(dfd, filename, flags, mode);
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(sys_openat);
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index af0cb4b..45ae7dd 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -331,7 +331,9 @@
 	devfs_remove("%s/part%d", disk->devfs_name, part);
 	if (p->holder_dir)
 		kobject_unregister(p->holder_dir);
-	kobject_unregister(&p->kobj);
+	kobject_uevent(&p->kobj, KOBJ_REMOVE);
+	kobject_del(&p->kobj);
+	kobject_put(&p->kobj);
 }
 
 void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
@@ -357,7 +359,10 @@
 		snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part);
 	p->kobj.parent = &disk->kobj;
 	p->kobj.ktype = &ktype_part;
-	kobject_register(&p->kobj);
+	kobject_init(&p->kobj);
+	kobject_add(&p->kobj);
+	if (!disk->part_uevent_suppress)
+		kobject_uevent(&p->kobj, KOBJ_ADD);
 	partition_sysfs_add_subdir(p);
 	disk->part[part-1] = p;
 }
@@ -367,6 +372,7 @@
 	char *name;
 	static char *block_str = "block:";
 	int size;
+	char *s;
 
 	size = strlen(block_str) + strlen(disk->disk_name) + 1;
 	name = kmalloc(size, GFP_KERNEL);
@@ -374,6 +380,10 @@
 		return NULL;
 	strcpy(name, block_str);
 	strcat(name, disk->disk_name);
+	/* ewww... some of these buggers have / in name... */
+	s = strchr(name, '/');
+	if (s)
+		*s = '!';
 	return name;
 }
 
@@ -395,6 +405,8 @@
 {
 	struct block_device *bdev;
 	char *s;
+	int i;
+	struct hd_struct *p;
 	int err;
 
 	strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
@@ -406,13 +418,12 @@
 		return;
 	disk_sysfs_symlinks(disk);
  	disk_sysfs_add_subdirs(disk);
-	kobject_uevent(&disk->kobj, KOBJ_ADD);
 
 	/* No minors to use for partitions */
 	if (disk->minors == 1) {
 		if (disk->devfs_name[0] != '\0')
 			devfs_add_disk(disk);
-		return;
+		goto exit;
 	}
 
 	/* always add handle for the whole disk */
@@ -420,16 +431,32 @@
 
 	/* No such device (e.g., media were just removed) */
 	if (!get_capacity(disk))
-		return;
+		goto exit;
 
 	bdev = bdget_disk(disk, 0);
 	if (!bdev)
-		return;
+		goto exit;
 
+	/* scan partition table, but suppress uevents */
 	bdev->bd_invalidated = 1;
-	if (blkdev_get(bdev, FMODE_READ, 0) < 0)
-		return;
+	disk->part_uevent_suppress = 1;
+	err = blkdev_get(bdev, FMODE_READ, 0);
+	disk->part_uevent_suppress = 0;
+	if (err < 0)
+		goto exit;
 	blkdev_put(bdev);
+
+exit:
+	/* announce disk after possible partitions are already created */
+	kobject_uevent(&disk->kobj, KOBJ_ADD);
+
+	/* announce possible partitions */
+	for (i = 1; i < disk->minors; i++) {
+		p = disk->part[i-1];
+		if (!p || !p->nr_sects)
+			continue;
+		kobject_uevent(&p->kobj, KOBJ_ADD);
+	}
 }
 
 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
diff --git a/fs/pipe.c b/fs/pipe.c
index 109a102..7fefb10 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -36,7 +36,7 @@
  */
 
 /* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode)
+void pipe_wait(struct pipe_inode_info *pipe)
 {
 	DEFINE_WAIT(wait);
 
@@ -44,11 +44,14 @@
 	 * Pipes are system-local resources, so sleeping on them
 	 * is considered a noninteractive wait:
 	 */
-	prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
-	mutex_unlock(PIPE_MUTEX(*inode));
+	prepare_to_wait(&pipe->wait, &wait,
+			TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
+	if (pipe->inode)
+		mutex_unlock(&pipe->inode->i_mutex);
 	schedule();
-	finish_wait(PIPE_WAIT(*inode), &wait);
-	mutex_lock(PIPE_MUTEX(*inode));
+	finish_wait(&pipe->wait, &wait);
+	if (pipe->inode)
+		mutex_lock(&pipe->inode->i_mutex);
 }
 
 static int
@@ -91,49 +94,56 @@
 	return 0;
 }
 
-static void anon_pipe_buf_release(struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
+				  struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
 
+	buf->flags &= ~PIPE_BUF_FLAG_STOLEN;
+
 	/*
 	 * If nobody else uses this page, and we don't already have a
 	 * temporary page, let's keep track of it as a one-deep
-	 * allocation cache
+	 * allocation cache. (Otherwise just release our reference to it)
 	 */
-	if (page_count(page) == 1 && !info->tmp_page) {
-		info->tmp_page = page;
-		return;
-	}
-
-	/*
-	 * Otherwise just release our reference to it
-	 */
-	page_cache_release(page);
+	if (page_count(page) == 1 && !pipe->tmp_page)
+		pipe->tmp_page = page;
+	else
+		page_cache_release(page);
 }
 
-static void *anon_pipe_buf_map(struct file *file, struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe,
+				struct pipe_buffer *buf)
 {
 	return kmap(buf->page);
 }
 
-static void anon_pipe_buf_unmap(struct pipe_inode_info *info, struct pipe_buffer *buf)
+static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe,
+				struct pipe_buffer *buf)
 {
 	kunmap(buf->page);
 }
 
-static int anon_pipe_buf_steal(struct pipe_inode_info *info,
+static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
 			       struct pipe_buffer *buf)
 {
-	buf->stolen = 1;
+	buf->flags |= PIPE_BUF_FLAG_STOLEN;
 	return 0;
 }
 
+static void anon_pipe_buf_get(struct pipe_inode_info *info,
+			      struct pipe_buffer *buf)
+{
+	page_cache_get(buf->page);
+}
+
 static struct pipe_buf_operations anon_pipe_buf_ops = {
 	.can_merge = 1,
 	.map = anon_pipe_buf_map,
 	.unmap = anon_pipe_buf_unmap,
 	.release = anon_pipe_buf_release,
 	.steal = anon_pipe_buf_steal,
+	.get = anon_pipe_buf_get,
 };
 
 static ssize_t
@@ -141,7 +151,7 @@
 	   unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct pipe_inode_info *info;
+	struct pipe_inode_info *pipe;
 	int do_wakeup;
 	ssize_t ret;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -154,13 +164,13 @@
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(PIPE_MUTEX(*inode));
-	info = inode->i_pipe;
+	mutex_lock(&inode->i_mutex);
+	pipe = inode->i_pipe;
 	for (;;) {
-		int bufs = info->nrbufs;
+		int bufs = pipe->nrbufs;
 		if (bufs) {
-			int curbuf = info->curbuf;
-			struct pipe_buffer *buf = info->bufs + curbuf;
+			int curbuf = pipe->curbuf;
+			struct pipe_buffer *buf = pipe->bufs + curbuf;
 			struct pipe_buf_operations *ops = buf->ops;
 			void *addr;
 			size_t chars = buf->len;
@@ -169,16 +179,17 @@
 			if (chars > total_len)
 				chars = total_len;
 
-			addr = ops->map(filp, info, buf);
+			addr = ops->map(filp, pipe, buf);
 			if (IS_ERR(addr)) {
 				if (!ret)
 					ret = PTR_ERR(addr);
 				break;
 			}
 			error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
-			ops->unmap(info, buf);
+			ops->unmap(pipe, buf);
 			if (unlikely(error)) {
-				if (!ret) ret = -EFAULT;
+				if (!ret)
+					ret = -EFAULT;
 				break;
 			}
 			ret += chars;
@@ -186,10 +197,10 @@
 			buf->len -= chars;
 			if (!buf->len) {
 				buf->ops = NULL;
-				ops->release(info, buf);
+				ops->release(pipe, buf);
 				curbuf = (curbuf + 1) & (PIPE_BUFFERS-1);
-				info->curbuf = curbuf;
-				info->nrbufs = --bufs;
+				pipe->curbuf = curbuf;
+				pipe->nrbufs = --bufs;
 				do_wakeup = 1;
 			}
 			total_len -= chars;
@@ -198,9 +209,9 @@
 		}
 		if (bufs)	/* More to do? */
 			continue;
-		if (!PIPE_WRITERS(*inode))
+		if (!pipe->writers)
 			break;
-		if (!PIPE_WAITING_WRITERS(*inode)) {
+		if (!pipe->waiting_writers) {
 			/* syscall merging: Usually we must not sleep
 			 * if O_NONBLOCK is set, or if we got some data.
 			 * But if a writer sleeps in kernel space, then
@@ -214,20 +225,22 @@
 			}
 		}
 		if (signal_pending(current)) {
-			if (!ret) ret = -ERESTARTSYS;
+			if (!ret)
+				ret = -ERESTARTSYS;
 			break;
 		}
 		if (do_wakeup) {
-			wake_up_interruptible_sync(PIPE_WAIT(*inode));
- 			kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+			wake_up_interruptible_sync(&pipe->wait);
+ 			kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 		}
-		pipe_wait(inode);
+		pipe_wait(pipe);
 	}
-	mutex_unlock(PIPE_MUTEX(*inode));
-	/* Signal writers asynchronously that there is more room.  */
+	mutex_unlock(&inode->i_mutex);
+
+	/* Signal writers asynchronously that there is more room. */
 	if (do_wakeup) {
-		wake_up_interruptible(PIPE_WAIT(*inode));
-		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+		wake_up_interruptible(&pipe->wait);
+		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
 	if (ret > 0)
 		file_accessed(filp);
@@ -238,6 +251,7 @@
 pipe_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct iovec iov = { .iov_base = buf, .iov_len = count };
+
 	return pipe_readv(filp, &iov, 1, ppos);
 }
 
@@ -246,7 +260,7 @@
 	    unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct pipe_inode_info *info;
+	struct pipe_inode_info *pipe;
 	ssize_t ret;
 	int do_wakeup;
 	struct iovec *iov = (struct iovec *)_iov;
@@ -260,10 +274,10 @@
 
 	do_wakeup = 0;
 	ret = 0;
-	mutex_lock(PIPE_MUTEX(*inode));
-	info = inode->i_pipe;
+	mutex_lock(&inode->i_mutex);
+	pipe = inode->i_pipe;
 
-	if (!PIPE_READERS(*inode)) {
+	if (!pipe->readers) {
 		send_sig(SIGPIPE, current, 0);
 		ret = -EPIPE;
 		goto out;
@@ -271,23 +285,25 @@
 
 	/* We try to merge small writes */
 	chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
-	if (info->nrbufs && chars != 0) {
-		int lastbuf = (info->curbuf + info->nrbufs - 1) & (PIPE_BUFFERS-1);
-		struct pipe_buffer *buf = info->bufs + lastbuf;
+	if (pipe->nrbufs && chars != 0) {
+		int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
+							(PIPE_BUFFERS-1);
+		struct pipe_buffer *buf = pipe->bufs + lastbuf;
 		struct pipe_buf_operations *ops = buf->ops;
 		int offset = buf->offset + buf->len;
+
 		if (ops->can_merge && offset + chars <= PAGE_SIZE) {
 			void *addr;
 			int error;
 
-			addr = ops->map(filp, info, buf);
+			addr = ops->map(filp, pipe, buf);
 			if (IS_ERR(addr)) {
 				error = PTR_ERR(addr);
 				goto out;
 			}
 			error = pipe_iov_copy_from_user(offset + addr, iov,
 							chars);
-			ops->unmap(info, buf);
+			ops->unmap(pipe, buf);
 			ret = error;
 			do_wakeup = 1;
 			if (error)
@@ -302,16 +318,18 @@
 
 	for (;;) {
 		int bufs;
-		if (!PIPE_READERS(*inode)) {
+
+		if (!pipe->readers) {
 			send_sig(SIGPIPE, current, 0);
-			if (!ret) ret = -EPIPE;
+			if (!ret)
+				ret = -EPIPE;
 			break;
 		}
-		bufs = info->nrbufs;
+		bufs = pipe->nrbufs;
 		if (bufs < PIPE_BUFFERS) {
-			int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS-1);
-			struct pipe_buffer *buf = info->bufs + newbuf;
-			struct page *page = info->tmp_page;
+			int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS-1);
+			struct pipe_buffer *buf = pipe->bufs + newbuf;
+			struct page *page = pipe->tmp_page;
 			int error;
 
 			if (!page) {
@@ -320,9 +338,9 @@
 					ret = ret ? : -ENOMEM;
 					break;
 				}
-				info->tmp_page = page;
+				pipe->tmp_page = page;
 			}
-			/* Always wakeup, even if the copy fails. Otherwise
+			/* Always wake up, even if the copy fails. Otherwise
 			 * we lock up (O_NONBLOCK-)readers that sleep due to
 			 * syscall merging.
 			 * FIXME! Is this really true?
@@ -335,7 +353,8 @@
 			error = pipe_iov_copy_from_user(kmap(page), iov, chars);
 			kunmap(page);
 			if (unlikely(error)) {
-				if (!ret) ret = -EFAULT;
+				if (!ret)
+					ret = -EFAULT;
 				break;
 			}
 			ret += chars;
@@ -345,8 +364,8 @@
 			buf->ops = &anon_pipe_buf_ops;
 			buf->offset = 0;
 			buf->len = chars;
-			info->nrbufs = ++bufs;
-			info->tmp_page = NULL;
+			pipe->nrbufs = ++bufs;
+			pipe->tmp_page = NULL;
 
 			total_len -= chars;
 			if (!total_len)
@@ -355,27 +374,29 @@
 		if (bufs < PIPE_BUFFERS)
 			continue;
 		if (filp->f_flags & O_NONBLOCK) {
-			if (!ret) ret = -EAGAIN;
+			if (!ret)
+				ret = -EAGAIN;
 			break;
 		}
 		if (signal_pending(current)) {
-			if (!ret) ret = -ERESTARTSYS;
+			if (!ret)
+				ret = -ERESTARTSYS;
 			break;
 		}
 		if (do_wakeup) {
-			wake_up_interruptible_sync(PIPE_WAIT(*inode));
-			kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+			wake_up_interruptible_sync(&pipe->wait);
+			kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 			do_wakeup = 0;
 		}
-		PIPE_WAITING_WRITERS(*inode)++;
-		pipe_wait(inode);
-		PIPE_WAITING_WRITERS(*inode)--;
+		pipe->waiting_writers++;
+		pipe_wait(pipe);
+		pipe->waiting_writers--;
 	}
 out:
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_unlock(&inode->i_mutex);
 	if (do_wakeup) {
-		wake_up_interruptible(PIPE_WAIT(*inode));
-		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+		wake_up_interruptible(&pipe->wait);
+		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 	}
 	if (ret > 0)
 		file_update_time(filp);
@@ -387,6 +408,7 @@
 	   size_t count, loff_t *ppos)
 {
 	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+
 	return pipe_writev(filp, &iov, 1, ppos);
 }
 
@@ -397,7 +419,8 @@
 }
 
 static ssize_t
-bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
+bad_pipe_w(struct file *filp, const char __user *buf, size_t count,
+	   loff_t *ppos)
 {
 	return -EBADF;
 }
@@ -407,21 +430,22 @@
 	   unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct pipe_inode_info *info;
+	struct pipe_inode_info *pipe;
 	int count, buf, nrbufs;
 
 	switch (cmd) {
 		case FIONREAD:
-			mutex_lock(PIPE_MUTEX(*inode));
-			info =  inode->i_pipe;
+			mutex_lock(&inode->i_mutex);
+			pipe = inode->i_pipe;
 			count = 0;
-			buf = info->curbuf;
-			nrbufs = info->nrbufs;
+			buf = pipe->curbuf;
+			nrbufs = pipe->nrbufs;
 			while (--nrbufs >= 0) {
-				count += info->bufs[buf].len;
+				count += pipe->bufs[buf].len;
 				buf = (buf+1) & (PIPE_BUFFERS-1);
 			}
-			mutex_unlock(PIPE_MUTEX(*inode));
+			mutex_unlock(&inode->i_mutex);
+
 			return put_user(count, (int __user *)arg);
 		default:
 			return -EINVAL;
@@ -434,17 +458,17 @@
 {
 	unsigned int mask;
 	struct inode *inode = filp->f_dentry->d_inode;
-	struct pipe_inode_info *info = inode->i_pipe;
+	struct pipe_inode_info *pipe = inode->i_pipe;
 	int nrbufs;
 
-	poll_wait(filp, PIPE_WAIT(*inode), wait);
+	poll_wait(filp, &pipe->wait, wait);
 
 	/* Reading only -- no need for acquiring the semaphore.  */
-	nrbufs = info->nrbufs;
+	nrbufs = pipe->nrbufs;
 	mask = 0;
 	if (filp->f_mode & FMODE_READ) {
 		mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
-		if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
+		if (!pipe->writers && filp->f_version != pipe->w_counter)
 			mask |= POLLHUP;
 	}
 
@@ -454,7 +478,7 @@
 		 * Most Unices do not set POLLERR for FIFOs but on Linux they
 		 * behave exactly like pipes for poll().
 		 */
-		if (!PIPE_READERS(*inode))
+		if (!pipe->readers)
 			mask |= POLLERR;
 	}
 
@@ -464,17 +488,21 @@
 static int
 pipe_release(struct inode *inode, int decr, int decw)
 {
-	mutex_lock(PIPE_MUTEX(*inode));
-	PIPE_READERS(*inode) -= decr;
-	PIPE_WRITERS(*inode) -= decw;
-	if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
+	struct pipe_inode_info *pipe;
+
+	mutex_lock(&inode->i_mutex);
+	pipe = inode->i_pipe;
+	pipe->readers -= decr;
+	pipe->writers -= decw;
+
+	if (!pipe->readers && !pipe->writers) {
 		free_pipe_info(inode);
 	} else {
-		wake_up_interruptible(PIPE_WAIT(*inode));
-		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
-		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+		wake_up_interruptible(&pipe->wait);
+		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -485,9 +513,9 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 	int retval;
 
-	mutex_lock(PIPE_MUTEX(*inode));
-	retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
+	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers);
+	mutex_unlock(&inode->i_mutex);
 
 	if (retval < 0)
 		return retval;
@@ -502,9 +530,9 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 	int retval;
 
-	mutex_lock(PIPE_MUTEX(*inode));
-	retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
+	retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers);
+	mutex_unlock(&inode->i_mutex);
 
 	if (retval < 0)
 		return retval;
@@ -517,16 +545,17 @@
 pipe_rdwr_fasync(int fd, struct file *filp, int on)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
+	struct pipe_inode_info *pipe = inode->i_pipe;
 	int retval;
 
-	mutex_lock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
 
-	retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
+	retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
 
 	if (retval >= 0)
-		retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
+		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
 
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_unlock(&inode->i_mutex);
 
 	if (retval < 0)
 		return retval;
@@ -565,9 +594,9 @@
 {
 	/* We could have perhaps used atomic_t, but this and friends
 	   below are the only places.  So it doesn't seem worthwhile.  */
-	mutex_lock(PIPE_MUTEX(*inode));
-	PIPE_READERS(*inode)++;
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
+	inode->i_pipe->readers++;
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -575,9 +604,9 @@
 static int
 pipe_write_open(struct inode *inode, struct file *filp)
 {
-	mutex_lock(PIPE_MUTEX(*inode));
-	PIPE_WRITERS(*inode)++;
-	mutex_unlock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
+	inode->i_pipe->writers++;
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -585,12 +614,12 @@
 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
-	mutex_lock(PIPE_MUTEX(*inode));
+	mutex_lock(&inode->i_mutex);
 	if (filp->f_mode & FMODE_READ)
-		PIPE_READERS(*inode)++;
+		inode->i_pipe->readers++;
 	if (filp->f_mode & FMODE_WRITE)
-		PIPE_WRITERS(*inode)++;
-	mutex_unlock(PIPE_MUTEX(*inode));
+		inode->i_pipe->writers++;
+	mutex_unlock(&inode->i_mutex);
 
 	return 0;
 }
@@ -673,37 +702,38 @@
 	.fasync		= pipe_rdwr_fasync,
 };
 
-void free_pipe_info(struct inode *inode)
+struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
 {
-	int i;
-	struct pipe_inode_info *info = inode->i_pipe;
+	struct pipe_inode_info *pipe;
 
-	inode->i_pipe = NULL;
-	for (i = 0; i < PIPE_BUFFERS; i++) {
-		struct pipe_buffer *buf = info->bufs + i;
-		if (buf->ops)
-			buf->ops->release(info, buf);
+	pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+	if (pipe) {
+		init_waitqueue_head(&pipe->wait);
+		pipe->r_counter = pipe->w_counter = 1;
+		pipe->inode = inode;
 	}
-	if (info->tmp_page)
-		__free_page(info->tmp_page);
-	kfree(info);
+
+	return pipe;
 }
 
-struct inode* pipe_new(struct inode* inode)
+void __free_pipe_info(struct pipe_inode_info *pipe)
 {
-	struct pipe_inode_info *info;
+	int i;
 
-	info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
-	if (!info)
-		goto fail_page;
-	inode->i_pipe = info;
+	for (i = 0; i < PIPE_BUFFERS; i++) {
+		struct pipe_buffer *buf = pipe->bufs + i;
+		if (buf->ops)
+			buf->ops->release(pipe, buf);
+	}
+	if (pipe->tmp_page)
+		__free_page(pipe->tmp_page);
+	kfree(pipe);
+}
 
-	init_waitqueue_head(PIPE_WAIT(*inode));
-	PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
-
-	return inode;
-fail_page:
-	return NULL;
+void free_pipe_info(struct inode *inode)
+{
+	__free_pipe_info(inode->i_pipe);
+	inode->i_pipe = NULL;
 }
 
 static struct vfsmount *pipe_mnt __read_mostly;
@@ -711,6 +741,7 @@
 {
 	return 1;
 }
+
 static struct dentry_operations pipefs_dentry_operations = {
 	.d_delete	= pipefs_delete_dentry,
 };
@@ -718,13 +749,17 @@
 static struct inode * get_pipe_inode(void)
 {
 	struct inode *inode = new_inode(pipe_mnt->mnt_sb);
+	struct pipe_inode_info *pipe;
 
 	if (!inode)
 		goto fail_inode;
 
-	if(!pipe_new(inode))
+	pipe = alloc_pipe_info(inode);
+	if (!pipe)
 		goto fail_iput;
-	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+	inode->i_pipe = pipe;
+
+	pipe->readers = pipe->writers = 1;
 	inode->i_fop = &rdwr_pipe_fops;
 
 	/*
@@ -739,10 +774,12 @@
 	inode->i_gid = current->fsgid;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blksize = PAGE_SIZE;
+
 	return inode;
 
 fail_iput:
 	iput(inode);
+
 fail_inode:
 	return NULL;
 }
@@ -755,7 +792,7 @@
 	struct inode * inode;
 	struct file *f1, *f2;
 	int error;
-	int i,j;
+	int i, j;
 
 	error = -ENFILE;
 	f1 = get_empty_filp();
@@ -788,6 +825,7 @@
 	dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
 	if (!dentry)
 		goto close_f12_inode_i_j;
+
 	dentry->d_op = &pipefs_dentry_operations;
 	d_add(dentry, inode);
 	f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
@@ -811,6 +849,7 @@
 	fd_install(j, f2);
 	fd[0] = i;
 	fd[1] = j;
+
 	return 0;
 
 close_f12_inode_i_j:
@@ -835,8 +874,9 @@
  * d_name - pipe: will go nicely and kill the special-casing in procfs.
  */
 
-static struct super_block *pipefs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static struct super_block *
+pipefs_get_sb(struct file_system_type *fs_type, int flags,
+	      const char *dev_name, void *data)
 {
 	return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
 }
@@ -850,6 +890,7 @@
 static int __init init_pipe_fs(void)
 {
 	int err = register_filesystem(&pipe_fs_type);
+
 	if (!err) {
 		pipe_mnt = kern_mount(&pipe_fs_type);
 		if (IS_ERR(pipe_mnt)) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a3a3eec..6cc77dc 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -297,16 +297,20 @@
 
 	files = get_files_struct(task);
 	if (files) {
-		rcu_read_lock();
+		/*
+		 * We are not taking a ref to the file structure, so we must
+		 * hold ->file_lock.
+		 */
+		spin_lock(&files->file_lock);
 		file = fcheck_files(files, fd);
 		if (file) {
 			*mnt = mntget(file->f_vfsmnt);
 			*dentry = dget(file->f_dentry);
-			rcu_read_unlock();
+			spin_unlock(&files->file_lock);
 			put_files_struct(files);
 			return 0;
 		}
-		rcu_read_unlock();
+		spin_unlock(&files->file_lock);
 		put_files_struct(files);
 	}
 	return -ENOENT;
@@ -1523,7 +1527,12 @@
 	if (!files)
 		goto out_unlock;
 	inode->i_mode = S_IFLNK;
-	rcu_read_lock();
+
+	/*
+	 * We are not taking a ref to the file structure, so we must
+	 * hold ->file_lock.
+	 */
+	spin_lock(&files->file_lock);
 	file = fcheck_files(files, fd);
 	if (!file)
 		goto out_unlock2;
@@ -1531,7 +1540,7 @@
 		inode->i_mode |= S_IRUSR | S_IXUSR;
 	if (file->f_mode & 2)
 		inode->i_mode |= S_IWUSR | S_IXUSR;
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 	inode->i_op = &proc_pid_link_inode_operations;
 	inode->i_size = 64;
@@ -1541,7 +1550,7 @@
 	return NULL;
 
 out_unlock2:
-	rcu_read_unlock();
+	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 out_unlock:
 	iput(inode);
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 7efa73d..20d4b22 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -103,8 +103,8 @@
 				size_t buflen, loff_t *fpos)
 {
 	ssize_t acc = 0, tmp;
-	size_t tsz, nr_bytes;
-	u64 start;
+	size_t tsz;
+	u64 start, nr_bytes;
 	struct vmcore *curr_m = NULL;
 
 	if (buflen == 0 || *fpos >= vmcore_size)
diff --git a/fs/read_write.c b/fs/read_write.c
index 6256ca8..5bc0e92 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -202,7 +202,7 @@
 		goto Einval;
 
 	inode = file->f_dentry->d_inode;
-	if (inode->i_flock && MANDATORY_LOCK(inode)) {
+	if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
 		int retval = locks_mandatory_area(
 			read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
 			inode, file, pos, count);
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 58c418f..97ae1b9 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -408,8 +408,9 @@
 		acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
 		reiserfs_read_unlock_xattrs(inode->i_sb);
 		reiserfs_read_unlock_xattr_i(inode);
-		ret = acl ? 1 : 0;
-		posix_acl_release(acl);
+		ret = (acl && !IS_ERR(acl));
+		if (ret)
+			posix_acl_release(acl);
 	}
 
 	return ret;
diff --git a/fs/select.c b/fs/select.c
index 071660f..a8109ba 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -310,8 +310,9 @@
 			   fd_set __user *exp, s64 *timeout)
 {
 	fd_set_bits fds;
-	char *bits;
-	int ret, size, max_fdset;
+	void *bits;
+	int ret, max_fdset;
+	unsigned int size;
 	struct fdtable *fdt;
 	/* Allocate small arguments on the stack to save memory and be faster */
 	long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
@@ -333,20 +334,21 @@
 	 * since we used fdset we need to allocate memory in units of
 	 * long-words. 
 	 */
-	ret = -ENOMEM;
 	size = FDS_BYTES(n);
-	if (6*size < SELECT_STACK_ALLOC)
-		bits = stack_fds;
-	else
+	bits = stack_fds;
+	if (size > sizeof(stack_fds) / 6) {
+		/* Not enough space in on-stack array; must use kmalloc */
+		ret = -ENOMEM;
 		bits = kmalloc(6 * size, GFP_KERNEL);
-	if (!bits)
-		goto out_nofds;
-	fds.in      = (unsigned long *)  bits;
-	fds.out     = (unsigned long *) (bits +   size);
-	fds.ex      = (unsigned long *) (bits + 2*size);
-	fds.res_in  = (unsigned long *) (bits + 3*size);
-	fds.res_out = (unsigned long *) (bits + 4*size);
-	fds.res_ex  = (unsigned long *) (bits + 5*size);
+		if (!bits)
+			goto out_nofds;
+	}
+	fds.in      = bits;
+	fds.out     = bits +   size;
+	fds.ex      = bits + 2*size;
+	fds.res_in  = bits + 3*size;
+	fds.res_out = bits + 4*size;
+	fds.res_ex  = bits + 5*size;
 
 	if ((ret = get_fd_set(n, inp, fds.in)) ||
 	    (ret = get_fd_set(n, outp, fds.out)) ||
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index c56bd99..ed9a24d 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -178,11 +178,9 @@
 	unsigned offset = PAGE_CACHE_SIZE;
 	int err;
 
-	if (!mapping)
-		BUG();
+	BUG_ON(!mapping);
 	inode = mapping->host;
-	if (!inode)
-		BUG();
+	BUG_ON(!inode);
 
 	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 
diff --git a/fs/splice.c b/fs/splice.c
index 7c2bbf1..a46ddd2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -9,11 +9,12 @@
  * that transfers data buffers to or from a pipe buffer.
  *
  * Named by Larry McVoy, original implementation from Linus, extended by
- * Jens to support splicing to files and fixing the initial implementation
- * bugs.
+ * Jens to support splicing to files, network, direct splicing, etc and
+ * fixing lots of bugs.
  *
- * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
- * Copyright (C) 2005 Linus Torvalds <torvalds@osdl.org>
+ * Copyright (C) 2005-2006 Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2005-2006 Linus Torvalds <torvalds@osdl.org>
+ * Copyright (C) 2006 Ingo Molnar <mingo@elte.hu>
  *
  */
 #include <linux/fs.h>
@@ -22,40 +23,62 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/mm_inline.h>
 #include <linux/swap.h>
+#include <linux/writeback.h>
+#include <linux/buffer_head.h>
 #include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uio.h>
 
-/*
- * Passed to the actors
- */
-struct splice_desc {
-	unsigned int len, total_len;	/* current and remaining length */
-	unsigned int flags;		/* splice flags */
-	struct file *file;		/* file to read/write */
-	loff_t pos;			/* file position */
+struct partial_page {
+	unsigned int offset;
+	unsigned int len;
 };
 
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+	struct page **pages;		/* page map */
+	struct partial_page *partial;	/* pages[] may not be contig */
+	int nr_pages;			/* number of pages in map */
+	unsigned int flags;		/* splice flags */
+	struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+/*
+ * Attempt to steal a page from a pipe buffer. This should perhaps go into
+ * a vm helper function, it's already simplified quite a bit by the
+ * addition of remove_mapping(). If success is returned, the caller may
+ * attempt to reuse this page for another destination.
+ */
 static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
 				     struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
+	struct address_space *mapping = page_mapping(page);
 
-	WARN_ON(!PageLocked(page));
+	lock_page(page);
+
 	WARN_ON(!PageUptodate(page));
 
-	if (!remove_mapping(page_mapping(page), page))
+	/*
+	 * At least for ext2 with nobh option, we need to wait on writeback
+	 * completing on this page, since we'll remove it from the pagecache.
+	 * Otherwise truncate wont wait on the page, allowing the disk
+	 * blocks to be reused by someone else before we actually wrote our
+	 * data to them. fs corruption ensues.
+	 */
+	wait_on_page_writeback(page);
+
+	if (PagePrivate(page))
+		try_to_release_page(page, mapping_gfp_mask(mapping));
+
+	if (!remove_mapping(mapping, page)) {
+		unlock_page(page);
 		return 1;
-
-	if (PageLRU(page)) {
-		struct zone *zone = page_zone(page);
-
-		spin_lock_irq(&zone->lru_lock);
-		BUG_ON(!PageLRU(page));
-		__ClearPageLRU(page);
-		del_page_from_lru(zone, page);
-		spin_unlock_irq(&zone->lru_lock);
 	}
 
-	buf->stolen = 1;
+	buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
 	return 0;
 }
 
@@ -64,7 +87,7 @@
 {
 	page_cache_release(buf->page);
 	buf->page = NULL;
-	buf->stolen = 0;
+	buf->flags &= ~(PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU);
 }
 
 static void *page_cache_pipe_buf_map(struct file *file,
@@ -72,93 +95,142 @@
 				     struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
-
-	lock_page(page);
+	int err;
 
 	if (!PageUptodate(page)) {
+		lock_page(page);
+
+		/*
+		 * Page got truncated/unhashed. This will cause a 0-byte
+		 * splice, if this is the first page.
+		 */
+		if (!page->mapping) {
+			err = -ENODATA;
+			goto error;
+		}
+
+		/*
+		 * Uh oh, read-error from disk.
+		 */
+		if (!PageUptodate(page)) {
+			err = -EIO;
+			goto error;
+		}
+
+		/*
+		 * Page is ok afterall, fall through to mapping.
+		 */
 		unlock_page(page);
-		return ERR_PTR(-EIO);
 	}
 
-	if (!page->mapping) {
-		unlock_page(page);
-		return ERR_PTR(-ENODATA);
-	}
-
-	return kmap(buf->page);
+	return kmap(page);
+error:
+	unlock_page(page);
+	return ERR_PTR(err);
 }
 
 static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info,
 				      struct pipe_buffer *buf)
 {
-	if (!buf->stolen)
-		unlock_page(buf->page);
 	kunmap(buf->page);
 }
 
+static void *user_page_pipe_buf_map(struct file *file,
+				    struct pipe_inode_info *pipe,
+				    struct pipe_buffer *buf)
+{
+	return kmap(buf->page);
+}
+
+static void user_page_pipe_buf_unmap(struct pipe_inode_info *pipe,
+				     struct pipe_buffer *buf)
+{
+	kunmap(buf->page);
+}
+
+static void page_cache_pipe_buf_get(struct pipe_inode_info *info,
+				    struct pipe_buffer *buf)
+{
+	page_cache_get(buf->page);
+}
+
 static struct pipe_buf_operations page_cache_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = page_cache_pipe_buf_map,
 	.unmap = page_cache_pipe_buf_unmap,
 	.release = page_cache_pipe_buf_release,
 	.steal = page_cache_pipe_buf_steal,
+	.get = page_cache_pipe_buf_get,
 };
 
-static ssize_t move_to_pipe(struct inode *inode, struct page **pages,
-			    int nr_pages, unsigned long offset,
-			    unsigned long len)
+static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
+				    struct pipe_buffer *buf)
 {
-	struct pipe_inode_info *info;
-	int ret, do_wakeup, i;
+	return 1;
+}
+
+static struct pipe_buf_operations user_page_pipe_buf_ops = {
+	.can_merge = 0,
+	.map = user_page_pipe_buf_map,
+	.unmap = user_page_pipe_buf_unmap,
+	.release = page_cache_pipe_buf_release,
+	.steal = user_page_pipe_buf_steal,
+	.get = page_cache_pipe_buf_get,
+};
+
+/*
+ * Pipe output worker. This sets up our pipe format with the page cache
+ * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+ */
+static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+			      struct splice_pipe_desc *spd)
+{
+	int ret, do_wakeup, page_nr;
 
 	ret = 0;
 	do_wakeup = 0;
-	i = 0;
+	page_nr = 0;
 
-	mutex_lock(PIPE_MUTEX(*inode));
+	if (pipe->inode)
+		mutex_lock(&pipe->inode->i_mutex);
 
-	info = inode->i_pipe;
 	for (;;) {
-		int bufs;
-
-		if (!PIPE_READERS(*inode)) {
+		if (!pipe->readers) {
 			send_sig(SIGPIPE, current, 0);
 			if (!ret)
 				ret = -EPIPE;
 			break;
 		}
 
-		bufs = info->nrbufs;
-		if (bufs < PIPE_BUFFERS) {
-			int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1);
-			struct pipe_buffer *buf = info->bufs + newbuf;
-			struct page *page = pages[i++];
-			unsigned long this_len;
+		if (pipe->nrbufs < PIPE_BUFFERS) {
+			int newbuf = (pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 1);
+			struct pipe_buffer *buf = pipe->bufs + newbuf;
 
-			this_len = PAGE_CACHE_SIZE - offset;
-			if (this_len > len)
-				this_len = len;
+			buf->page = spd->pages[page_nr];
+			buf->offset = spd->partial[page_nr].offset;
+			buf->len = spd->partial[page_nr].len;
+			buf->ops = spd->ops;
+			pipe->nrbufs++;
+			page_nr++;
+			ret += buf->len;
 
-			buf->page = page;
-			buf->offset = offset;
-			buf->len = this_len;
-			buf->ops = &page_cache_pipe_buf_ops;
-			info->nrbufs = ++bufs;
-			do_wakeup = 1;
+			if (pipe->inode)
+				do_wakeup = 1;
 
-			ret += this_len;
-			len -= this_len;
-			offset = 0;
-			if (!--nr_pages)
+			if (!--spd->nr_pages)
 				break;
-			if (!len)
-				break;
-			if (bufs < PIPE_BUFFERS)
+			if (pipe->nrbufs < PIPE_BUFFERS)
 				continue;
 
 			break;
 		}
 
+		if (spd->flags & SPLICE_F_NONBLOCK) {
+			if (!ret)
+				ret = -EAGAIN;
+			break;
+		}
+
 		if (signal_pending(current)) {
 			if (!ret)
 				ret = -ERESTARTSYS;
@@ -166,137 +238,264 @@
 		}
 
 		if (do_wakeup) {
-			wake_up_interruptible_sync(PIPE_WAIT(*inode));
-			kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO,
-				    POLL_IN);
+			smp_mb();
+			if (waitqueue_active(&pipe->wait))
+				wake_up_interruptible_sync(&pipe->wait);
+			kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 			do_wakeup = 0;
 		}
 
-		PIPE_WAITING_WRITERS(*inode)++;
-		pipe_wait(inode);
-		PIPE_WAITING_WRITERS(*inode)--;
+		pipe->waiting_writers++;
+		pipe_wait(pipe);
+		pipe->waiting_writers--;
 	}
 
-	mutex_unlock(PIPE_MUTEX(*inode));
+	if (pipe->inode)
+		mutex_unlock(&pipe->inode->i_mutex);
 
 	if (do_wakeup) {
-		wake_up_interruptible(PIPE_WAIT(*inode));
-		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+		smp_mb();
+		if (waitqueue_active(&pipe->wait))
+			wake_up_interruptible(&pipe->wait);
+		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
 	}
 
-	while (i < nr_pages)
-		page_cache_release(pages[i++]);
+	while (page_nr < spd->nr_pages)
+		page_cache_release(spd->pages[page_nr++]);
 
 	return ret;
 }
 
-static int __generic_file_splice_read(struct file *in, struct inode *pipe,
-				      size_t len)
+static int
+__generic_file_splice_read(struct file *in, loff_t *ppos,
+			   struct pipe_inode_info *pipe, size_t len,
+			   unsigned int flags)
 {
 	struct address_space *mapping = in->f_mapping;
-	unsigned int offset, nr_pages;
-	struct page *pages[PIPE_BUFFERS], *shadow[PIPE_BUFFERS];
+	unsigned int loff, nr_pages;
+	struct page *pages[PIPE_BUFFERS];
+	struct partial_page partial[PIPE_BUFFERS];
 	struct page *page;
-	pgoff_t index, pidx;
-	int i, j;
+	pgoff_t index, end_index;
+	loff_t isize;
+	size_t total_len;
+	int error, page_nr;
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.partial = partial,
+		.flags = flags,
+		.ops = &page_cache_pipe_buf_ops,
+	};
 
-	index = in->f_pos >> PAGE_CACHE_SHIFT;
-	offset = in->f_pos & ~PAGE_CACHE_MASK;
-	nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	loff = *ppos & ~PAGE_CACHE_MASK;
+	nr_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 	if (nr_pages > PIPE_BUFFERS)
 		nr_pages = PIPE_BUFFERS;
 
 	/*
-	 * initiate read-ahead on this page range
+	 * Initiate read-ahead on this page range. however, don't call into
+	 * read-ahead if this is a non-zero offset (we are likely doing small
+	 * chunk splice and the page is already there) for a single page.
 	 */
-	do_page_cache_readahead(mapping, in, index, nr_pages);
+	if (!loff || nr_pages > 1)
+		page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
 
 	/*
-	 * Get as many pages from the page cache as possible..
-	 * Start IO on the page cache entries we create (we
-	 * can assume that any pre-existing ones we find have
-	 * already had IO started on them).
+	 * Now fill in the holes:
 	 */
-	i = find_get_pages(mapping, index, nr_pages, pages);
+	error = 0;
+	total_len = 0;
 
 	/*
-	 * common case - we found all pages and they are contiguous,
-	 * kick them off
+	 * Lookup the (hopefully) full range of pages we need.
 	 */
-	if (i && (pages[i - 1]->index == index + i - 1))
-		goto splice_them;
+	spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
 
 	/*
-	 * fill shadow[] with pages at the right locations, so we only
-	 * have to fill holes
+	 * If find_get_pages_contig() returned fewer pages than we needed,
+	 * allocate the rest.
 	 */
-	memset(shadow, 0, i * sizeof(struct page *));
-	for (j = 0, pidx = index; j < i; pidx++, j++)
-		shadow[pages[j]->index - pidx] = pages[j];
-
-	/*
-	 * now fill in the holes
-	 */
-	for (i = 0, pidx = index; i < nr_pages; pidx++, i++) {
-		int error;
-
-		if (shadow[i])
-			continue;
-
+	index += spd.nr_pages;
+	while (spd.nr_pages < nr_pages) {
 		/*
-		 * no page there, look one up / create it
+		 * Page could be there, find_get_pages_contig() breaks on
+		 * the first hole.
 		 */
-		page = find_or_create_page(mapping, pidx,
-						   mapping_gfp_mask(mapping));
-		if (!page)
-			break;
+		page = find_get_page(mapping, index);
+		if (!page) {
+			/*
+			 * page didn't exist, allocate one.
+			 */
+			page = page_cache_alloc_cold(mapping);
+			if (!page)
+				break;
 
-		if (PageUptodate(page))
-			unlock_page(page);
-		else {
-			error = mapping->a_ops->readpage(in, page);
-
+			error = add_to_page_cache_lru(page, mapping, index,
+					      mapping_gfp_mask(mapping));
 			if (unlikely(error)) {
 				page_cache_release(page);
 				break;
 			}
+			/*
+			 * add_to_page_cache() locks the page, unlock it
+			 * to avoid convoluting the logic below even more.
+			 */
+			unlock_page(page);
 		}
-		shadow[i] = page;
-	}
 
-	if (!i) {
-		for (i = 0; i < nr_pages; i++) {
-			 if (shadow[i])
-				page_cache_release(shadow[i]);
-		}
-		return 0;
+		pages[spd.nr_pages++] = page;
+		index++;
 	}
 
-	memcpy(pages, shadow, i * sizeof(struct page *));
-
 	/*
-	 * Now we splice them into the pipe..
+	 * Now loop over the map and see if we need to start IO on any
+	 * pages, fill in the partial map, etc.
 	 */
-splice_them:
-	return move_to_pipe(pipe, pages, i, offset, len);
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	nr_pages = spd.nr_pages;
+	spd.nr_pages = 0;
+	for (page_nr = 0; page_nr < nr_pages; page_nr++) {
+		unsigned int this_len;
+
+		if (!len)
+			break;
+
+		/*
+		 * this_len is the max we'll use from this page
+		 */
+		this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff);
+		page = pages[page_nr];
+
+		/*
+		 * If the page isn't uptodate, we may need to start io on it
+		 */
+		if (!PageUptodate(page)) {
+			/*
+			 * If in nonblock mode then dont block on waiting
+			 * for an in-flight io page
+			 */
+			if (flags & SPLICE_F_NONBLOCK)
+				break;
+
+			lock_page(page);
+
+			/*
+			 * page was truncated, stop here. if this isn't the
+			 * first page, we'll just complete what we already
+			 * added
+			 */
+			if (!page->mapping) {
+				unlock_page(page);
+				break;
+			}
+			/*
+			 * page was already under io and is now done, great
+			 */
+			if (PageUptodate(page)) {
+				unlock_page(page);
+				goto fill_it;
+			}
+
+			/*
+			 * need to read in the page
+			 */
+			error = mapping->a_ops->readpage(in, page);
+			if (unlikely(error)) {
+				/*
+				 * We really should re-lookup the page here,
+				 * but it complicates things a lot. Instead
+				 * lets just do what we already stored, and
+				 * we'll get it the next time we are called.
+				 */
+				if (error == AOP_TRUNCATED_PAGE)
+					error = 0;
+
+				break;
+			}
+
+			/*
+			 * i_size must be checked after ->readpage().
+			 */
+			isize = i_size_read(mapping->host);
+			end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+			if (unlikely(!isize || index > end_index))
+				break;
+
+			/*
+			 * if this is the last page, see if we need to shrink
+			 * the length and stop
+			 */
+			if (end_index == index) {
+				loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
+				if (total_len + loff > isize)
+					break;
+				/*
+				 * force quit after adding this page
+				 */
+				len = this_len;
+				this_len = min(this_len, loff);
+				loff = 0;
+			}
+		}
+fill_it:
+		partial[page_nr].offset = loff;
+		partial[page_nr].len = this_len;
+		len -= this_len;
+		total_len += this_len;
+		loff = 0;
+		spd.nr_pages++;
+		index++;
+	}
+
+	/*
+	 * Release any pages at the end, if we quit early. 'i' is how far
+	 * we got, 'nr_pages' is how many pages are in the map.
+	 */
+	while (page_nr < nr_pages)
+		page_cache_release(pages[page_nr++]);
+
+	if (spd.nr_pages)
+		return splice_to_pipe(pipe, &spd);
+
+	return error;
 }
 
-ssize_t generic_file_splice_read(struct file *in, struct inode *pipe,
-				 size_t len, unsigned int flags)
+/**
+ * generic_file_splice_read - splice data from file to a pipe
+ * @in:		file to splice from
+ * @pipe:	pipe to splice to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Will read pages from given file and fill them into a pipe.
+ */
+ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
+				 struct pipe_inode_info *pipe, size_t len,
+				 unsigned int flags)
 {
 	ssize_t spliced;
 	int ret;
 
 	ret = 0;
 	spliced = 0;
+
 	while (len) {
-		ret = __generic_file_splice_read(in, pipe, len);
+		ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 
-		if (ret <= 0)
+		if (ret < 0)
 			break;
+		else if (!ret) {
+			if (spliced)
+				break;
+			if (flags & SPLICE_F_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
+			}
+		}
 
-		in->f_pos += ret;
+		*ppos += ret;
 		len -= ret;
 		spliced += ret;
 	}
@@ -307,38 +506,38 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(generic_file_splice_read);
+
 /*
- * Send 'len' bytes to socket from 'file' at position 'pos' using sendpage().
+ * Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
+ * using sendpage(). Return the number of bytes sent.
  */
 static int pipe_to_sendpage(struct pipe_inode_info *info,
 			    struct pipe_buffer *buf, struct splice_desc *sd)
 {
 	struct file *file = sd->file;
 	loff_t pos = sd->pos;
-	unsigned int offset;
 	ssize_t ret;
 	void *ptr;
+	int more;
 
 	/*
-	 * sub-optimal, but we are limited by the pipe ->map. we don't
+	 * Sub-optimal, but we are limited by the pipe ->map. We don't
 	 * need a kmap'ed buffer here, we just want to make sure we
 	 * have the page pinned if the pipe page originates from the
-	 * page cache
+	 * page cache.
 	 */
 	ptr = buf->ops->map(file, info, buf);
 	if (IS_ERR(ptr))
 		return PTR_ERR(ptr);
 
-	offset = pos & ~PAGE_CACHE_MASK;
+	more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
 
-	ret = file->f_op->sendpage(file, buf->page, offset, sd->len, &pos,
-					sd->len < sd->total_len);
+	ret = file->f_op->sendpage(file, buf->page, buf->offset, sd->len,
+				   &pos, more);
 
 	buf->ops->unmap(info, buf);
-	if (ret == sd->len)
-		return 0;
-
-	return -EIO;
+	return ret;
 }
 
 /*
@@ -354,24 +553,27 @@
  *	- Destination page does not exist, we can add the pipe page to
  *	  the page cache and avoid the copy.
  *
- * For now we just do the slower thing and always copy pages over, it's
- * easier than migrating pages from the pipe to the target file. For the
- * case of doing file | file splicing, the migrate approach had some LRU
- * nastiness...
+ * If asked to move pages to the output file (SPLICE_F_MOVE is set in
+ * sd->flags), we attempt to migrate pages from the pipe to the output
+ * file address space page cache. This is possible if no one else has
+ * the pipe page referenced outside of the pipe and page cache. If
+ * SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
+ * a new page in the output file page cache and fill/dirty that.
  */
 static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
 			struct splice_desc *sd)
 {
 	struct file *file = sd->file;
 	struct address_space *mapping = file->f_mapping;
-	unsigned int offset;
+	gfp_t gfp_mask = mapping_gfp_mask(mapping);
+	unsigned int offset, this_len;
 	struct page *page;
 	pgoff_t index;
 	char *src;
 	int ret;
 
 	/*
-	 * after this, page will be locked and unmapped
+	 * make sure the data in this buffer is uptodate
 	 */
 	src = buf->ops->map(file, info, buf);
 	if (IS_ERR(src))
@@ -380,32 +582,54 @@
 	index = sd->pos >> PAGE_CACHE_SHIFT;
 	offset = sd->pos & ~PAGE_CACHE_MASK;
 
+	this_len = sd->len;
+	if (this_len + offset > PAGE_CACHE_SIZE)
+		this_len = PAGE_CACHE_SIZE - offset;
+
 	/*
-	 * reuse buf page, if SPLICE_F_MOVE is set
+	 * Reuse buf page, if SPLICE_F_MOVE is set.
 	 */
 	if (sd->flags & SPLICE_F_MOVE) {
+		/*
+		 * If steal succeeds, buf->page is now pruned from the vm
+		 * side (LRU and page cache) and we can reuse it. The page
+		 * will also be looked on successful return.
+		 */
 		if (buf->ops->steal(info, buf))
 			goto find_page;
 
 		page = buf->page;
-		if (add_to_page_cache_lru(page, mapping, index,
-						mapping_gfp_mask(mapping)))
+		if (add_to_page_cache(page, mapping, index, gfp_mask))
 			goto find_page;
+
+		if (!(buf->flags & PIPE_BUF_FLAG_LRU))
+			lru_cache_add(page);
 	} else {
 find_page:
-		ret = -ENOMEM;
-		page = find_or_create_page(mapping, index,
-						mapping_gfp_mask(mapping));
-		if (!page)
-			goto out;
+		page = find_lock_page(mapping, index);
+		if (!page) {
+			ret = -ENOMEM;
+			page = page_cache_alloc_cold(mapping);
+			if (unlikely(!page))
+				goto out_nomem;
+
+			/*
+			 * This will also lock the page
+			 */
+			ret = add_to_page_cache_lru(page, mapping, index,
+						    gfp_mask);
+			if (unlikely(ret))
+				goto out;
+		}
 
 		/*
-		 * If the page is uptodate, it is also locked. If it isn't
-		 * uptodate, we can mark it uptodate if we are filling the
-		 * full page. Otherwise we need to read it in first...
+		 * We get here with the page locked. If the page is also
+		 * uptodate, we don't need to do more. If it isn't, we
+		 * may need to bring it in if we are not going to overwrite
+		 * the full page.
 		 */
 		if (!PageUptodate(page)) {
-			if (sd->len < PAGE_CACHE_SIZE) {
+			if (this_len < PAGE_CACHE_SIZE) {
 				ret = mapping->a_ops->readpage(file, page);
 				if (unlikely(ret))
 					goto out;
@@ -414,7 +638,7 @@
 
 				if (!PageUptodate(page)) {
 					/*
-					 * page got invalidated, repeat
+					 * Page got invalidated, repeat.
 					 */
 					if (!page->mapping) {
 						unlock_page(page);
@@ -424,48 +648,58 @@
 					ret = -EIO;
 					goto out;
 				}
-			} else {
-				WARN_ON(!PageLocked(page));
+			} else
 				SetPageUptodate(page);
-			}
 		}
 	}
 
-	ret = mapping->a_ops->prepare_write(file, page, 0, sd->len);
-	if (ret)
+	ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
+	if (ret == AOP_TRUNCATED_PAGE) {
+		page_cache_release(page);
+		goto find_page;
+	} else if (ret)
 		goto out;
 
-	if (!buf->stolen) {
+	if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) {
 		char *dst = kmap_atomic(page, KM_USER0);
 
-		memcpy(dst + offset, src + buf->offset, sd->len);
+		memcpy(dst + offset, src + buf->offset, this_len);
 		flush_dcache_page(page);
 		kunmap_atomic(dst, KM_USER0);
 	}
 
-	ret = mapping->a_ops->commit_write(file, page, 0, sd->len);
-	if (ret < 0)
+	ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
+	if (ret == AOP_TRUNCATED_PAGE) {
+		page_cache_release(page);
+		goto find_page;
+	} else if (ret)
 		goto out;
 
-	set_page_dirty(page);
-	ret = write_one_page(page, 0);
+	/*
+	 * Return the number of bytes written.
+	 */
+	ret = this_len;
+	mark_page_accessed(page);
+	balance_dirty_pages_ratelimited(mapping);
 out:
-	if (ret < 0)
-		unlock_page(page);
-	if (!buf->stolen)
+	if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
 		page_cache_release(page);
+
+	unlock_page(page);
+out_nomem:
 	buf->ops->unmap(info, buf);
 	return ret;
 }
 
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
-			   struct splice_desc *);
-
-static ssize_t move_from_pipe(struct inode *inode, struct file *out,
-			      size_t len, unsigned int flags,
-			      splice_actor *actor)
+/*
+ * Pipe input worker. Most of this logic works like a regular pipe, the
+ * key here is the 'actor' worker passed in that actually moves the data
+ * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+ */
+ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
+			 loff_t *ppos, size_t len, unsigned int flags,
+			 splice_actor *actor)
 {
-	struct pipe_inode_info *info;
 	int ret, do_wakeup, err;
 	struct splice_desc sd;
 
@@ -475,58 +709,66 @@
 	sd.total_len = len;
 	sd.flags = flags;
 	sd.file = out;
-	sd.pos = out->f_pos;
+	sd.pos = *ppos;
 
-	mutex_lock(PIPE_MUTEX(*inode));
+	if (pipe->inode)
+		mutex_lock(&pipe->inode->i_mutex);
 
-	info = inode->i_pipe;
 	for (;;) {
-		int bufs = info->nrbufs;
-
-		if (bufs) {
-			int curbuf = info->curbuf;
-			struct pipe_buffer *buf = info->bufs + curbuf;
+		if (pipe->nrbufs) {
+			struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
 			struct pipe_buf_operations *ops = buf->ops;
 
 			sd.len = buf->len;
 			if (sd.len > sd.total_len)
 				sd.len = sd.total_len;
 
-			err = actor(info, buf, &sd);
-			if (err) {
+			err = actor(pipe, buf, &sd);
+			if (err <= 0) {
 				if (!ret && err != -ENODATA)
 					ret = err;
 
 				break;
 			}
 
-			ret += sd.len;
-			buf->offset += sd.len;
-			buf->len -= sd.len;
+			ret += err;
+			buf->offset += err;
+			buf->len -= err;
+
+			sd.len -= err;
+			sd.pos += err;
+			sd.total_len -= err;
+			if (sd.len)
+				continue;
+
 			if (!buf->len) {
 				buf->ops = NULL;
-				ops->release(info, buf);
-				curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1);
-				info->curbuf = curbuf;
-				info->nrbufs = --bufs;
-				do_wakeup = 1;
+				ops->release(pipe, buf);
+				pipe->curbuf = (pipe->curbuf + 1) & (PIPE_BUFFERS - 1);
+				pipe->nrbufs--;
+				if (pipe->inode)
+					do_wakeup = 1;
 			}
 
-			sd.pos += sd.len;
-			sd.total_len -= sd.len;
 			if (!sd.total_len)
 				break;
 		}
 
-		if (bufs)
+		if (pipe->nrbufs)
 			continue;
-		if (!PIPE_WRITERS(*inode))
+		if (!pipe->writers)
 			break;
-		if (!PIPE_WAITING_WRITERS(*inode)) {
+		if (!pipe->waiting_writers) {
 			if (ret)
 				break;
 		}
 
+		if (flags & SPLICE_F_NONBLOCK) {
+			if (!ret)
+				ret = -EAGAIN;
+			break;
+		}
+
 		if (signal_pending(current)) {
 			if (!ret)
 				ret = -ERESTARTSYS;
@@ -534,108 +776,487 @@
 		}
 
 		if (do_wakeup) {
-			wake_up_interruptible_sync(PIPE_WAIT(*inode));
-			kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT);
+			smp_mb();
+			if (waitqueue_active(&pipe->wait))
+				wake_up_interruptible_sync(&pipe->wait);
+			kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 			do_wakeup = 0;
 		}
 
-		pipe_wait(inode);
+		pipe_wait(pipe);
 	}
 
-	mutex_unlock(PIPE_MUTEX(*inode));
+	if (pipe->inode)
+		mutex_unlock(&pipe->inode->i_mutex);
 
 	if (do_wakeup) {
-		wake_up_interruptible(PIPE_WAIT(*inode));
-		kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
+		smp_mb();
+		if (waitqueue_active(&pipe->wait))
+			wake_up_interruptible(&pipe->wait);
+		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
 
-	mutex_lock(&out->f_mapping->host->i_mutex);
-	out->f_pos = sd.pos;
-	mutex_unlock(&out->f_mapping->host->i_mutex);
 	return ret;
-
 }
 
-ssize_t generic_file_splice_write(struct inode *inode, struct file *out,
-				  size_t len, unsigned int flags)
+/**
+ * generic_file_splice_write - splice data from a pipe to a file
+ * @pipe:	pipe info
+ * @out:	file to write to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file.
+ *
+ */
+ssize_t
+generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
+			  loff_t *ppos, size_t len, unsigned int flags)
 {
-	return move_from_pipe(inode, out, len, flags, pipe_to_file);
-}
+	struct address_space *mapping = out->f_mapping;
+	ssize_t ret;
 
-ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
-				size_t len, unsigned int flags)
-{
-	return move_from_pipe(inode, out, len, flags, pipe_to_sendpage);
+	ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+	if (ret > 0) {
+		struct inode *inode = mapping->host;
+
+		*ppos += ret;
+
+		/*
+		 * If file or inode is SYNC and we actually wrote some data,
+		 * sync it.
+		 */
+		if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+			int err;
+
+			mutex_lock(&inode->i_mutex);
+			err = generic_osync_inode(inode, mapping,
+						  OSYNC_METADATA|OSYNC_DATA);
+			mutex_unlock(&inode->i_mutex);
+
+			if (err)
+				ret = err;
+		}
+	}
+
+	return ret;
 }
 
 EXPORT_SYMBOL(generic_file_splice_write);
-EXPORT_SYMBOL(generic_file_splice_read);
 
-static long do_splice_from(struct inode *pipe, struct file *out, size_t len,
-			   unsigned int flags)
+/**
+ * generic_splice_sendpage - splice data from a pipe to a socket
+ * @inode:	pipe inode
+ * @out:	socket to write to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Will send @len bytes from the pipe to a network socket. No data copying
+ * is involved.
+ *
+ */
+ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
+				loff_t *ppos, size_t len, unsigned int flags)
 {
-	loff_t pos;
+	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage);
+}
+
+EXPORT_SYMBOL(generic_splice_sendpage);
+
+/*
+ * Attempt to initiate a splice from pipe to file.
+ */
+static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+			   loff_t *ppos, size_t len, unsigned int flags)
+{
 	int ret;
 
-	if (!out->f_op || !out->f_op->splice_write)
+	if (unlikely(!out->f_op || !out->f_op->splice_write))
 		return -EINVAL;
 
-	if (!(out->f_mode & FMODE_WRITE))
+	if (unlikely(!(out->f_mode & FMODE_WRITE)))
 		return -EBADF;
 
-	pos = out->f_pos;
-	ret = rw_verify_area(WRITE, out, &pos, len);
+	ret = rw_verify_area(WRITE, out, ppos, len);
 	if (unlikely(ret < 0))
 		return ret;
 
-	return out->f_op->splice_write(pipe, out, len, flags);
+	return out->f_op->splice_write(pipe, out, ppos, len, flags);
 }
 
-static long do_splice_to(struct file *in, struct inode *pipe, size_t len,
+/*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+static long do_splice_to(struct file *in, loff_t *ppos,
+			 struct pipe_inode_info *pipe, size_t len,
 			 unsigned int flags)
 {
-	loff_t pos, isize, left;
+	loff_t isize, left;
 	int ret;
 
-	if (!in->f_op || !in->f_op->splice_read)
+	if (unlikely(!in->f_op || !in->f_op->splice_read))
 		return -EINVAL;
 
-	if (!(in->f_mode & FMODE_READ))
+	if (unlikely(!(in->f_mode & FMODE_READ)))
 		return -EBADF;
 
-	pos = in->f_pos;
-	ret = rw_verify_area(READ, in, &pos, len);
+	ret = rw_verify_area(READ, in, ppos, len);
 	if (unlikely(ret < 0))
 		return ret;
 
 	isize = i_size_read(in->f_mapping->host);
-	if (unlikely(in->f_pos >= isize))
+	if (unlikely(*ppos >= isize))
 		return 0;
 	
-	left = isize - in->f_pos;
-	if (left < len)
+	left = isize - *ppos;
+	if (unlikely(left < len))
 		len = left;
 
-	return in->f_op->splice_read(in, pipe, len, flags);
+	return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 
-static long do_splice(struct file *in, struct file *out, size_t len,
-		      unsigned int flags)
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+		      size_t len, unsigned int flags)
 {
-	struct inode *pipe;
+	struct pipe_inode_info *pipe;
+	long ret, bytes;
+	loff_t out_off;
+	umode_t i_mode;
+	int i;
 
-	pipe = in->f_dentry->d_inode;
-	if (pipe->i_pipe)
-		return do_splice_from(pipe, out, len, flags);
+	/*
+	 * We require the input being a regular file, as we don't want to
+	 * randomly drop data for eg socket -> socket splicing. Use the
+	 * piped splicing for that!
+	 */
+	i_mode = in->f_dentry->d_inode->i_mode;
+	if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
+		return -EINVAL;
 
-	pipe = out->f_dentry->d_inode;
-	if (pipe->i_pipe)
-		return do_splice_to(in, pipe, len, flags);
+	/*
+	 * neither in nor out is a pipe, setup an internal pipe attached to
+	 * 'out' and transfer the wanted data from 'in' to 'out' through that
+	 */
+	pipe = current->splice_pipe;
+	if (unlikely(!pipe)) {
+		pipe = alloc_pipe_info(NULL);
+		if (!pipe)
+			return -ENOMEM;
+
+		/*
+		 * We don't have an immediate reader, but we'll read the stuff
+		 * out of the pipe right after the splice_to_pipe(). So set
+		 * PIPE_READERS appropriately.
+		 */
+		pipe->readers = 1;
+
+		current->splice_pipe = pipe;
+	}
+
+	/*
+	 * Do the splice.
+	 */
+	ret = 0;
+	bytes = 0;
+	out_off = 0;
+
+	while (len) {
+		size_t read_len, max_read_len;
+
+		/*
+		 * Do at most PIPE_BUFFERS pages worth of transfer:
+		 */
+		max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
+
+		ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
+		if (unlikely(ret < 0))
+			goto out_release;
+
+		read_len = ret;
+
+		/*
+		 * NOTE: nonblocking mode only applies to the input. We
+		 * must not do the output in nonblocking mode as then we
+		 * could get stuck data in the internal pipe:
+		 */
+		ret = do_splice_from(pipe, out, &out_off, read_len,
+				     flags & ~SPLICE_F_NONBLOCK);
+		if (unlikely(ret < 0))
+			goto out_release;
+
+		bytes += ret;
+		len -= ret;
+
+		/*
+		 * In nonblocking mode, if we got back a short read then
+		 * that was due to either an IO error or due to the
+		 * pagecache entry not being there. In the IO error case
+		 * the _next_ splice attempt will produce a clean IO error
+		 * return value (not a short read), so in both cases it's
+		 * correct to break out of the loop here:
+		 */
+		if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
+			break;
+	}
+
+	pipe->nrbufs = pipe->curbuf = 0;
+
+	return bytes;
+
+out_release:
+	/*
+	 * If we did an incomplete transfer we must release
+	 * the pipe buffers in question:
+	 */
+	for (i = 0; i < PIPE_BUFFERS; i++) {
+		struct pipe_buffer *buf = pipe->bufs + i;
+
+		if (buf->ops) {
+			buf->ops->release(pipe, buf);
+			buf->ops = NULL;
+		}
+	}
+	pipe->nrbufs = pipe->curbuf = 0;
+
+	/*
+	 * If we transferred some data, return the number of bytes:
+	 */
+	if (bytes > 0)
+		return bytes;
+
+	return ret;
+}
+
+EXPORT_SYMBOL(do_splice_direct);
+
+/*
+ * Determine where to splice to/from.
+ */
+static long do_splice(struct file *in, loff_t __user *off_in,
+		      struct file *out, loff_t __user *off_out,
+		      size_t len, unsigned int flags)
+{
+	struct pipe_inode_info *pipe;
+	loff_t offset, *off;
+	long ret;
+
+	pipe = in->f_dentry->d_inode->i_pipe;
+	if (pipe) {
+		if (off_in)
+			return -ESPIPE;
+		if (off_out) {
+			if (out->f_op->llseek == no_llseek)
+				return -EINVAL;
+			if (copy_from_user(&offset, off_out, sizeof(loff_t)))
+				return -EFAULT;
+			off = &offset;
+		} else
+			off = &out->f_pos;
+
+		ret = do_splice_from(pipe, out, off, len, flags);
+
+		if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+			ret = -EFAULT;
+
+		return ret;
+	}
+
+	pipe = out->f_dentry->d_inode->i_pipe;
+	if (pipe) {
+		if (off_out)
+			return -ESPIPE;
+		if (off_in) {
+			if (in->f_op->llseek == no_llseek)
+				return -EINVAL;
+			if (copy_from_user(&offset, off_in, sizeof(loff_t)))
+				return -EFAULT;
+			off = &offset;
+		} else
+			off = &in->f_pos;
+
+		ret = do_splice_to(in, off, pipe, len, flags);
+
+		if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+			ret = -EFAULT;
+
+		return ret;
+	}
 
 	return -EINVAL;
 }
 
-asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags)
+/*
+ * Map an iov into an array of pages and offset/length tupples. With the
+ * partial_page structure, we can map several non-contiguous ranges into
+ * our ones pages[] map instead of splitting that operation into pieces.
+ * Could easily be exported as a generic helper for other users, in which
+ * case one would probably want to add a 'max_nr_pages' parameter as well.
+ */
+static int get_iovec_page_array(const struct iovec __user *iov,
+				unsigned int nr_vecs, struct page **pages,
+				struct partial_page *partial)
+{
+	int buffers = 0, error = 0;
+
+	/*
+	 * It's ok to take the mmap_sem for reading, even
+	 * across a "get_user()".
+	 */
+	down_read(&current->mm->mmap_sem);
+
+	while (nr_vecs) {
+		unsigned long off, npages;
+		void __user *base;
+		size_t len;
+		int i;
+
+		/*
+		 * Get user address base and length for this iovec.
+		 */
+		error = get_user(base, &iov->iov_base);
+		if (unlikely(error))
+			break;
+		error = get_user(len, &iov->iov_len);
+		if (unlikely(error))
+			break;
+
+		/*
+		 * Sanity check this iovec. 0 read succeeds.
+		 */
+		if (unlikely(!len))
+			break;
+		error = -EFAULT;
+		if (unlikely(!base))
+			break;
+
+		/*
+		 * Get this base offset and number of pages, then map
+		 * in the user pages.
+		 */
+		off = (unsigned long) base & ~PAGE_MASK;
+		npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		if (npages > PIPE_BUFFERS - buffers)
+			npages = PIPE_BUFFERS - buffers;
+
+		error = get_user_pages(current, current->mm,
+				       (unsigned long) base, npages, 0, 0,
+				       &pages[buffers], NULL);
+
+		if (unlikely(error <= 0))
+			break;
+
+		/*
+		 * Fill this contiguous range into the partial page map.
+		 */
+		for (i = 0; i < error; i++) {
+			const int plen = min_t(size_t, len, PAGE_SIZE) - off;
+
+			partial[buffers].offset = off;
+			partial[buffers].len = plen;
+
+			off = 0;
+			len -= plen;
+			buffers++;
+		}
+
+		/*
+		 * We didn't complete this iov, stop here since it probably
+		 * means we have to move some of this into a pipe to
+		 * be able to continue.
+		 */
+		if (len)
+			break;
+
+		/*
+		 * Don't continue if we mapped fewer pages than we asked for,
+		 * or if we mapped the max number of pages that we have
+		 * room for.
+		 */
+		if (error < npages || buffers == PIPE_BUFFERS)
+			break;
+
+		nr_vecs--;
+		iov++;
+	}
+
+	up_read(&current->mm->mmap_sem);
+
+	if (buffers)
+		return buffers;
+
+	return error;
+}
+
+/*
+ * vmsplice splices a user address range into a pipe. It can be thought of
+ * as splice-from-memory, where the regular splice is splice-from-file (or
+ * to file). In both cases the output is a pipe, naturally.
+ *
+ * Note that vmsplice only supports splicing _from_ user memory to a pipe,
+ * not the other way around. Splicing from user memory is a simple operation
+ * that can be supported without any funky alignment restrictions or nasty
+ * vm tricks. We simply map in the user memory and fill them into a pipe.
+ * The reverse isn't quite as easy, though. There are two possible solutions
+ * for that:
+ *
+ *	- memcpy() the data internally, at which point we might as well just
+ *	  do a regular read() on the buffer anyway.
+ *	- Lots of nasty vm tricks, that are neither fast nor flexible (it
+ *	  has restriction limitations on both ends of the pipe).
+ *
+ * Alas, it isn't here.
+ *
+ */
+static long do_vmsplice(struct file *file, const struct iovec __user *iov,
+			unsigned long nr_segs, unsigned int flags)
+{
+	struct pipe_inode_info *pipe = file->f_dentry->d_inode->i_pipe;
+	struct page *pages[PIPE_BUFFERS];
+	struct partial_page partial[PIPE_BUFFERS];
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.partial = partial,
+		.flags = flags,
+		.ops = &user_page_pipe_buf_ops,
+	};
+
+	if (unlikely(!pipe))
+		return -EBADF;
+	if (unlikely(nr_segs > UIO_MAXIOV))
+		return -EINVAL;
+	else if (unlikely(!nr_segs))
+		return 0;
+
+	spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial);
+	if (spd.nr_pages <= 0)
+		return spd.nr_pages;
+
+	return splice_to_pipe(pipe, &spd);
+}
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags)
+{
+	struct file *file;
+	long error;
+	int fput;
+
+	error = -EBADF;
+	file = fget_light(fd, &fput);
+	if (file) {
+		if (file->f_mode & FMODE_WRITE)
+			error = do_vmsplice(file, iov, nr_segs, flags);
+
+		fput_light(file, fput);
+	}
+
+	return error;
+}
+
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+			   int fd_out, loff_t __user *off_out,
+			   size_t len, unsigned int flags)
 {
 	long error;
 	struct file *in, *out;
@@ -645,13 +1266,15 @@
 		return 0;
 
 	error = -EBADF;
-	in = fget_light(fdin, &fput_in);
+	in = fget_light(fd_in, &fput_in);
 	if (in) {
 		if (in->f_mode & FMODE_READ) {
-			out = fget_light(fdout, &fput_out);
+			out = fget_light(fd_out, &fput_out);
 			if (out) {
 				if (out->f_mode & FMODE_WRITE)
-					error = do_splice(in, out, len, flags);
+					error = do_splice(in, off_in,
+							  out, off_out,
+							  len, flags);
 				fput_light(out, fput_out);
 			}
 		}
@@ -661,3 +1284,192 @@
 
 	return error;
 }
+
+/*
+ * Link contents of ipipe to opipe.
+ */
+static int link_pipe(struct pipe_inode_info *ipipe,
+		     struct pipe_inode_info *opipe,
+		     size_t len, unsigned int flags)
+{
+	struct pipe_buffer *ibuf, *obuf;
+	int ret, do_wakeup, i, ipipe_first;
+
+	ret = do_wakeup = ipipe_first = 0;
+
+	/*
+	 * Potential ABBA deadlock, work around it by ordering lock
+	 * grabbing by inode address. Otherwise two different processes
+	 * could deadlock (one doing tee from A -> B, the other from B -> A).
+	 */
+	if (ipipe->inode < opipe->inode) {
+		ipipe_first = 1;
+		mutex_lock(&ipipe->inode->i_mutex);
+		mutex_lock(&opipe->inode->i_mutex);
+	} else {
+		mutex_lock(&opipe->inode->i_mutex);
+		mutex_lock(&ipipe->inode->i_mutex);
+	}
+
+	for (i = 0;; i++) {
+		if (!opipe->readers) {
+			send_sig(SIGPIPE, current, 0);
+			if (!ret)
+				ret = -EPIPE;
+			break;
+		}
+		if (ipipe->nrbufs - i) {
+			ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1));
+
+			/*
+			 * If we have room, fill this buffer
+			 */
+			if (opipe->nrbufs < PIPE_BUFFERS) {
+				int nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1);
+
+				/*
+				 * Get a reference to this pipe buffer,
+				 * so we can copy the contents over.
+				 */
+				ibuf->ops->get(ipipe, ibuf);
+
+				obuf = opipe->bufs + nbuf;
+				*obuf = *ibuf;
+
+				if (obuf->len > len)
+					obuf->len = len;
+
+				opipe->nrbufs++;
+				do_wakeup = 1;
+				ret += obuf->len;
+				len -= obuf->len;
+
+				if (!len)
+					break;
+				if (opipe->nrbufs < PIPE_BUFFERS)
+					continue;
+			}
+
+			/*
+			 * We have input available, but no output room.
+			 * If we already copied data, return that. If we
+			 * need to drop the opipe lock, it must be ordered
+			 * last to avoid deadlocks.
+			 */
+			if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			if (do_wakeup) {
+				smp_mb();
+				if (waitqueue_active(&opipe->wait))
+					wake_up_interruptible(&opipe->wait);
+				kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+				do_wakeup = 0;
+			}
+
+			opipe->waiting_writers++;
+			pipe_wait(opipe);
+			opipe->waiting_writers--;
+			continue;
+		}
+
+		/*
+		 * No input buffers, do the usual checks for available
+		 * writers and blocking and wait if necessary
+		 */
+		if (!ipipe->writers)
+			break;
+		if (!ipipe->waiting_writers) {
+			if (ret)
+				break;
+		}
+		/*
+		 * pipe_wait() drops the ipipe mutex. To avoid deadlocks
+		 * with another process, we can only safely do that if
+		 * the ipipe lock is ordered last.
+		 */
+		if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) {
+			if (!ret)
+				ret = -EAGAIN;
+			break;
+		}
+		if (signal_pending(current)) {
+			if (!ret)
+				ret = -ERESTARTSYS;
+			break;
+		}
+
+		if (waitqueue_active(&ipipe->wait))
+			wake_up_interruptible_sync(&ipipe->wait);
+		kill_fasync(&ipipe->fasync_writers, SIGIO, POLL_OUT);
+
+		pipe_wait(ipipe);
+	}
+
+	mutex_unlock(&ipipe->inode->i_mutex);
+	mutex_unlock(&opipe->inode->i_mutex);
+
+	if (do_wakeup) {
+		smp_mb();
+		if (waitqueue_active(&opipe->wait))
+			wake_up_interruptible(&opipe->wait);
+		kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN);
+	}
+
+	return ret;
+}
+
+/*
+ * This is a tee(1) implementation that works on pipes. It doesn't copy
+ * any data, it simply references the 'in' pages on the 'out' pipe.
+ * The 'flags' used are the SPLICE_F_* variants, currently the only
+ * applicable one is SPLICE_F_NONBLOCK.
+ */
+static long do_tee(struct file *in, struct file *out, size_t len,
+		   unsigned int flags)
+{
+	struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe;
+	struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe;
+
+	/*
+	 * Link ipipe to the two output pipes, consuming as we go along.
+	 */
+	if (ipipe && opipe)
+		return link_pipe(ipipe, opipe, len, flags);
+
+	return -EINVAL;
+}
+
+asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags)
+{
+	struct file *in;
+	int error, fput_in;
+
+	if (unlikely(!len))
+		return 0;
+
+	error = -EBADF;
+	in = fget_light(fdin, &fput_in);
+	if (in) {
+		if (in->f_mode & FMODE_READ) {
+			int fput_out;
+			struct file *out = fget_light(fdout, &fput_out);
+
+			if (out) {
+				if (out->f_mode & FMODE_WRITE)
+					error = do_tee(in, out, len, flags);
+				fput_light(out, fput_out);
+			}
+		}
+ 		fput_light(in, fput_in);
+ 	}
+
+	return error;
+}
diff --git a/fs/sync.c b/fs/sync.c
index 8616006..aab5ffe 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -61,7 +61,7 @@
  * will be available after a crash.
  */
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
-					int flags)
+					unsigned int flags)
 {
 	int ret;
 	struct file *file;
@@ -126,7 +126,7 @@
  * `endbyte' is inclusive
  */
 int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
-			int flags)
+			unsigned int flags)
 {
 	int ret;
 	struct address_space *mapping;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index f26880a..610b5bd 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -43,6 +43,7 @@
 
 	memset(sd, 0, sizeof(*sd));
 	atomic_set(&sd->s_count, 1);
+	atomic_set(&sd->s_event, 0);
 	INIT_LIST_HEAD(&sd->s_children);
 	list_add(&sd->s_sibling, &parent_sd->s_children);
 	sd->s_element = element;
@@ -50,7 +51,7 @@
 	return sd;
 }
 
-/**
+/*
  *
  * Return -EEXIST if there is already a sysfs element with the same name for
  * the same parent.
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 830f76f..cf37866 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -6,6 +6,7 @@
 #include <linux/fsnotify.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
+#include <linux/poll.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -57,6 +58,7 @@
 	struct sysfs_ops	* ops;
 	struct semaphore	sem;
 	int			needs_read_fill;
+	int			event;
 };
 
 
@@ -72,6 +74,7 @@
  */
 static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
 {
+	struct sysfs_dirent * sd = dentry->d_fsdata;
 	struct attribute * attr = to_attr(dentry);
 	struct kobject * kobj = to_kobj(dentry->d_parent);
 	struct sysfs_ops * ops = buffer->ops;
@@ -83,6 +86,7 @@
 	if (!buffer->page)
 		return -ENOMEM;
 
+	buffer->event = atomic_read(&sd->s_event);
 	count = ops->show(kobj,attr,buffer->page);
 	buffer->needs_read_fill = 0;
 	BUG_ON(count > (ssize_t)PAGE_SIZE);
@@ -183,7 +187,7 @@
 		return -ENOMEM;
 
 	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE;
+		count = PAGE_SIZE - 1;
 	error = copy_from_user(buffer->page,buf,count);
 	buffer->needs_read_fill = 1;
 	return error ? -EFAULT : count;
@@ -348,12 +352,84 @@
 	return 0;
 }
 
+/* Sysfs attribute files are pollable.  The idea is that you read
+ * the content and then you use 'poll' or 'select' to wait for
+ * the content to change.  When the content changes (assuming the
+ * manager for the kobject supports notification), poll will
+ * return POLLERR|POLLPRI, and select will return the fd whether
+ * it is waiting for read, write, or exceptions.
+ * Once poll/select indicates that the value has changed, you
+ * need to close and re-open the file, as simply seeking and reading
+ * again will not get new data, or reset the state of 'poll'.
+ * Reminder: this only works for attributes which actively support
+ * it, and it is not possible to test an attribute from userspace
+ * to see if it supports poll (Nether 'poll' or 'select' return
+ * an appropriate error code).  When in doubt, set a suitable timeout value.
+ */
+static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
+{
+	struct sysfs_buffer * buffer = filp->private_data;
+	struct kobject * kobj = to_kobj(filp->f_dentry->d_parent);
+	struct sysfs_dirent * sd = filp->f_dentry->d_fsdata;
+	int res = 0;
+
+	poll_wait(filp, &kobj->poll, wait);
+
+	if (buffer->event != atomic_read(&sd->s_event)) {
+		res = POLLERR|POLLPRI;
+		buffer->needs_read_fill = 1;
+	}
+
+	return res;
+}
+
+
+static struct dentry *step_down(struct dentry *dir, const char * name)
+{
+	struct dentry * de;
+
+	if (dir == NULL || dir->d_inode == NULL)
+		return NULL;
+
+	mutex_lock(&dir->d_inode->i_mutex);
+	de = lookup_one_len(name, dir, strlen(name));
+	mutex_unlock(&dir->d_inode->i_mutex);
+	dput(dir);
+	if (IS_ERR(de))
+		return NULL;
+	if (de->d_inode == NULL) {
+		dput(de);
+		return NULL;
+	}
+	return de;
+}
+
+void sysfs_notify(struct kobject * k, char *dir, char *attr)
+{
+	struct dentry *de = k->dentry;
+	if (de)
+		dget(de);
+	if (de && dir)
+		de = step_down(de, dir);
+	if (de && attr)
+		de = step_down(de, attr);
+	if (de) {
+		struct sysfs_dirent * sd = de->d_fsdata;
+		if (sd)
+			atomic_inc(&sd->s_event);
+		wake_up_interruptible(&k->poll);
+		dput(de);
+	}
+}
+EXPORT_SYMBOL_GPL(sysfs_notify);
+
 const struct file_operations sysfs_file_operations = {
 	.read		= sysfs_read_file,
 	.write		= sysfs_write_file,
 	.llseek		= generic_file_llseek,
 	.open		= sysfs_open_file,
 	.release	= sysfs_release,
+	.poll		= sysfs_poll,
 };
 
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4c29ac4..f0b347b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -175,8 +175,7 @@
 	struct bin_attribute * bin_attr;
 	struct sysfs_symlink  * sl;
 
-	if (!sd || !sd->s_element)
-		BUG();
+	BUG_ON(!sd || !sd->s_element);
 
 	switch (sd->s_type) {
 		case SYSFS_DIR:
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 32958a7..3651ffb 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -11,6 +11,7 @@
 
 extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
 extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
 
 extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
 extern void sysfs_remove_subdir(struct dentry *);
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 8c66e92..d707434 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -253,8 +253,7 @@
 
 	lock_page(page);
 	err = mapping->a_ops->prepare_write(NULL, page, from, to);
-	if (err)
-		BUG();
+	BUG_ON(err);
 	de->inode = 0;
 	err = dir_commit_chunk(page, from, to);
 	dir_put_page(page);
@@ -353,8 +352,7 @@
 
 	lock_page(page);
 	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
-	if (err)
-		BUG();
+	BUG_ON(err);
 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
 	err = dir_commit_chunk(page, from, to);
 	dir_put_page(page);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 81e0e84..2983afd 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -312,12 +312,10 @@
 	err = 0;
 
 	bh = inode_getblk(inode, block, &err, &phys, &new);
-	if (bh)
-		BUG();
+	BUG_ON(bh);
 	if (err)
 		goto abort;
-	if (!phys)
-		BUG();
+	BUG_ON(!phys);
 
 	if (new)
 		set_buffer_new(bh_result);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 6cbbd16..4d191ef 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -870,12 +870,14 @@
 	pgoff_t                 end_index, last_index, tlast;
 	ssize_t			size, len;
 	int			flags, err, iomap_valid = 0, uptodate = 1;
-	int			page_dirty, count = 0, trylock_flag = 0;
+	int			page_dirty, count = 0;
+	int			trylock = 0;
 	int			all_bh = unmapped;
 
-	/* wait for other IO threads? */
-	if (startio && (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking))
-		trylock_flag |= BMAPI_TRYLOCK;
+	if (startio) {
+		if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking)
+			trylock |= BMAPI_TRYLOCK;
+	}
 
 	/* Is this page beyond the end of the file? */
 	offset = i_size_read(inode);
@@ -956,15 +958,13 @@
 
 			if (buffer_unwritten(bh)) {
 				type = IOMAP_UNWRITTEN;
-				flags = BMAPI_WRITE|BMAPI_IGNSTATE;
+				flags = BMAPI_WRITE | BMAPI_IGNSTATE;
 			} else if (buffer_delay(bh)) {
 				type = IOMAP_DELAY;
-				flags = BMAPI_ALLOCATE;
-				if (!startio)
-					flags |= trylock_flag;
+				flags = BMAPI_ALLOCATE | trylock;
 			} else {
 				type = IOMAP_NEW;
-				flags = BMAPI_WRITE|BMAPI_MMAP;
+				flags = BMAPI_WRITE | BMAPI_MMAP;
 			}
 
 			if (!iomap_valid) {
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 9fb0312..26fed07 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -182,7 +182,7 @@
 {
 	a_list_t	*aentry;
 
-	aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC & ~__GFP_HIGH);
+	aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
 	if (likely(aentry)) {
 		spin_lock(&as_lock);
 		aentry->next = as_free_head;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 85997b1..c847416 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -69,7 +69,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_read(
 	struct kiocb		*iocb,
@@ -90,7 +89,6 @@
 	return __xfs_file_read(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_write(
 	struct kiocb	*iocb,
@@ -113,7 +111,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_aio_write(
 	struct kiocb		*iocb,
@@ -134,7 +131,6 @@
 	return __xfs_file_write(iocb, buf, IO_ISAIO|IO_INVIS, count, pos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_readv(
 	struct file		*file,
@@ -179,7 +175,6 @@
 	return __xfs_file_readv(file, iov, IO_INVIS, nr_segs, ppos);
 }
 
-
 STATIC inline ssize_t
 __xfs_file_writev(
 	struct file		*file,
@@ -204,7 +199,6 @@
 	return rval;
 }
 
-
 STATIC ssize_t
 xfs_file_writev(
 	struct file		*file,
@@ -228,7 +222,7 @@
 STATIC ssize_t
 xfs_file_sendfile(
 	struct file		*filp,
-	loff_t			*ppos,
+	loff_t			*pos,
 	size_t			count,
 	read_actor_t		actor,
 	void			*target)
@@ -236,10 +230,84 @@
 	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
 	ssize_t			rval;
 
-	VOP_SENDFILE(vp, filp, ppos, 0, count, actor, target, NULL, rval);
+	VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
 	return rval;
 }
 
+STATIC ssize_t
+xfs_file_sendfile_invis(
+	struct file		*filp,
+	loff_t			*pos,
+	size_t			count,
+	read_actor_t		actor,
+	void			*target)
+{
+	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read(
+	struct file		*infilp,
+	loff_t			*ppos,
+	struct pipe_inode_info	*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_read_invis(
+	struct file		*infilp,
+	loff_t			*ppos,
+	struct pipe_inode_info	*pipe,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write(
+	struct pipe_inode_info	*pipe,
+	struct file		*outfilp,
+	loff_t			*ppos,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
+	return rval;
+}
+
+STATIC ssize_t
+xfs_file_splice_write_invis(
+	struct pipe_inode_info	*pipe,
+	struct file		*outfilp,
+	loff_t			*ppos,
+	size_t			len,
+	unsigned int		flags)
+{
+	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
+	ssize_t			rval;
+
+	VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
+	return rval;
+}
 
 STATIC int
 xfs_file_open(
@@ -251,13 +319,10 @@
 
 	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EFBIG;
-
-	ASSERT(vp);
 	VOP_OPEN(vp, NULL, error);
 	return -error;
 }
 
-
 STATIC int
 xfs_file_release(
 	struct inode	*inode,
@@ -271,7 +336,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_fsync(
 	struct file	*filp,
@@ -285,21 +349,11 @@
 
 	if (datasync)
 		flags |= FSYNC_DATA;
-
-	ASSERT(vp);
 	VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
 	return -error;
 }
 
-/*
- * xfs_file_readdir maps to VOP_READDIR().
- * We need to build a uio, cred, ...
- */
-
-#define nextdp(dp)      ((struct xfs_dirent *)((char *)(dp) + (dp)->d_reclen))
-
 #ifdef CONFIG_XFS_DMAPI
-
 STATIC struct page *
 xfs_vm_nopage(
 	struct vm_area_struct	*area,
@@ -319,10 +373,8 @@
 
 	return filemap_nopage(area, address, type);
 }
-
 #endif /* CONFIG_XFS_DMAPI */
 
-
 STATIC int
 xfs_file_readdir(
 	struct file	*filp,
@@ -330,7 +382,7 @@
 	filldir_t	filldir)
 {
 	int		error = 0;
-	vnode_t		*vp;
+	vnode_t		*vp = vn_from_inode(filp->f_dentry->d_inode);
 	uio_t		uio;
 	iovec_t		iov;
 	int		eof = 0;
@@ -340,9 +392,6 @@
 	xfs_off_t	start_offset, curr_offset;
 	xfs_dirent_t	*dbp = NULL;
 
-	vp = vn_from_inode(filp->f_dentry->d_inode);
-	ASSERT(vp);
-
 	/* Try fairly hard to get memory */
 	do {
 		if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
@@ -387,7 +436,7 @@
 			}
 			size -= dbp->d_reclen;
 			curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
-			dbp = nextdp(dbp);
+			dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
 		}
 	}
 done:
@@ -402,7 +451,6 @@
 	return -error;
 }
 
-
 STATIC int
 xfs_file_mmap(
 	struct file	*filp,
@@ -457,11 +505,10 @@
 	unsigned int	cmd,
 	unsigned long	arg)
 {
-	int		error;
 	struct inode	*inode = filp->f_dentry->d_inode;
 	vnode_t		*vp = vn_from_inode(inode);
+	int		error;
 
-	ASSERT(vp);
 	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 
@@ -537,6 +584,8 @@
 	.aio_read	= xfs_file_aio_read,
 	.aio_write	= xfs_file_aio_write,
 	.sendfile	= xfs_file_sendfile,
+	.splice_read	= xfs_file_splice_read,
+	.splice_write	= xfs_file_splice_write,
 	.unlocked_ioctl	= xfs_file_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_ioctl,
@@ -558,7 +607,9 @@
 	.writev		= xfs_file_writev_invis,
 	.aio_read	= xfs_file_aio_read_invis,
 	.aio_write	= xfs_file_aio_write_invis,
-	.sendfile	= xfs_file_sendfile,
+	.sendfile	= xfs_file_sendfile_invis,
+	.splice_read	= xfs_file_splice_read_invis,
+	.splice_write	= xfs_file_splice_write_invis,
 	.unlocked_ioctl	= xfs_file_ioctl_invis,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= xfs_file_compat_invis_ioctl,
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 1492373..2e2e275 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -673,8 +673,7 @@
 	if (ia_valid & ATTR_ATIME) {
 		vattr.va_mask |= XFS_AT_ATIME;
 		vattr.va_atime = attr->ia_atime;
-		if (ia_valid & ATTR_ATIME_SET)
-			inode->i_atime = attr->ia_atime;
+		inode->i_atime = attr->ia_atime;
 	}
 	if (ia_valid & ATTR_MTIME) {
 		vattr.va_mask |= XFS_AT_MTIME;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 1fe09f2..e9fe43d 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -103,6 +103,7 @@
  */
 #undef  HAVE_REFCACHE	/* reference cache not needed for NFS in 2.6 */
 #define HAVE_SENDFILE	/* sendfile(2) exists in 2.6, but not in 2.4 */
+#define HAVE_SPLICE	/* a splice(2) exists in 2.6, but not in 2.4 */
 #ifdef CONFIG_SMP
 #define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
 #else
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 84ddf18..67efe33 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -301,36 +301,23 @@
 	void			*target,
 	cred_t			*credp)
 {
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
 	ssize_t			ret;
-	xfs_fsize_t		n;
-	xfs_inode_t		*ip;
-	xfs_mount_t		*mp;
-	vnode_t			*vp;
-
-	ip = XFS_BHVTOI(bdp);
-	vp = BHV_TO_VNODE(bdp);
-	mp = ip->i_mount;
 
 	XFS_STATS_INC(xs_read_calls);
-
-	n = XFS_MAXIOFFSET(mp) - *offset;
-	if ((n <= 0) || (count == 0))
-		return 0;
-
-	if (n < count)
-		count = n;
-
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
-	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
 	    (!(ioflags & IO_INVIS))) {
 		vrwlock_t locktype = VRWLOCK_READ;
 		int error;
 
-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+				      *offset, count,
 				      FILP_DELAY_FLAG(filp), &locktype);
 		if (error) {
 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -340,12 +327,98 @@
 	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
 		   (void *)(unsigned long)target, count, *offset, ioflags);
 	ret = generic_file_sendfile(filp, offset, count, actor, target);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-
 	if (ret > 0)
 		XFS_STATS_ADD(xs_read_bytes, ret);
 
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
+}
+
+ssize_t
+xfs_splice_read(
+	bhv_desc_t		*bdp,
+	struct file		*infilp,
+	loff_t			*ppos,
+	struct pipe_inode_info	*pipe,
+	size_t			count,
+	int			flags,
+	int			ioflags,
+	cred_t			*credp)
+{
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_read_calls);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
+	    (!(ioflags & IO_INVIS))) {
+		vrwlock_t locktype = VRWLOCK_READ;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
+					*ppos, count,
+					FILP_DELAY_FLAG(infilp), &locktype);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+			return -error;
+		}
+	}
+	xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore,
+			   pipe, count, *ppos, ioflags);
+	ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
+}
+
+ssize_t
+xfs_splice_write(
+	bhv_desc_t		*bdp,
+	struct pipe_inode_info	*pipe,
+	struct file		*outfilp,
+	loff_t			*ppos,
+	size_t			count,
+	int			flags,
+	int			ioflags,
+	cred_t			*credp)
+{
+	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
+	xfs_mount_t		*mp = ip->i_mount;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_write_calls);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
+	    (!(ioflags & IO_INVIS))) {
+		vrwlock_t locktype = VRWLOCK_WRITE;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
+					*ppos, count,
+					FILP_DELAY_FLAG(outfilp), &locktype);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			return -error;
+		}
+	}
+	xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore,
+			   pipe, count, *ppos, ioflags);
+	ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_write_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 	return ret;
 }
 
@@ -363,7 +436,7 @@
 	xfs_fsize_t	end_size)
 {
 	xfs_fileoff_t	last_fsb;
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		zero_offset;
 	int		zero_len;
@@ -373,8 +446,6 @@
 
 	ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
 
-	mp = io->io_mount;
-
 	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
 	if (zero_offset == 0) {
 		/*
@@ -405,10 +476,9 @@
 	 * don't deadlock when the buffer cache calls back to us.
 	 */
 	XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
+
 	loff = XFS_FSB_TO_B(mp, last_fsb);
-
 	zero_len = mp->m_sb.sb_blocksize - zero_offset;
-
 	error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
 
 	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -441,7 +511,7 @@
 	xfs_fileoff_t	zero_count_fsb;
 	xfs_fileoff_t	last_fsb;
 	xfs_extlen_t	buf_len_fsb;
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		error = 0;
 	xfs_bmbt_irec_t	imap;
@@ -450,8 +520,6 @@
 	ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
 	ASSERT(offset > isize);
 
-	mp = io->io_mount;
-
 	/*
 	 * First handle zeroing the block on which isize resides.
 	 * We only zero a part of that block so it is handled specially.
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 38864a8..8f45399 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -60,6 +60,8 @@
 #define	XFS_IOMAP_ALLOC_ENTER	25
 #define	XFS_IOMAP_ALLOC_MAP	26
 #define	XFS_IOMAP_UNWRITTEN	27
+#define XFS_SPLICE_READ_ENTER	28
+#define XFS_SPLICE_WRITE_ENTER	29
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
 				void *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
@@ -78,6 +80,7 @@
 			struct xfs_iomap *, int *);
 extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
 extern int xfs_bdstrat_cb(struct xfs_buf *);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
 extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
 				xfs_fsize_t, xfs_fsize_t);
@@ -90,7 +93,11 @@
 extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
+				struct pipe_inode_info *, size_t, int, int,
+				struct cred *);
+extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
+				struct file *, loff_t *, size_t, int, int,
+				struct cred *);
 
 #endif	/* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 1884300..68f4793 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -67,7 +67,8 @@
 
 STATIC struct xfs_mount_args *
 xfs_args_allocate(
-	struct super_block	*sb)
+	struct super_block	*sb,
+	int			silent)
 {
 	struct xfs_mount_args	*args;
 
@@ -80,8 +81,8 @@
 		args->flags |= XFSMNT_DIRSYNC;
 	if (sb->s_flags & MS_SYNCHRONOUS)
 		args->flags |= XFSMNT_WSYNC;
-
-	/* Default to 32 bit inodes on Linux all the time */
+	if (silent)
+		args->flags |= XFSMNT_QUIET;
 	args->flags |= XFSMNT_32BITINODES;
 
 	return args;
@@ -719,7 +720,7 @@
 	char			*options)
 {
 	vfs_t			*vfsp = vfs_from_sb(sb);
-	struct xfs_mount_args	*args = xfs_args_allocate(sb);
+	struct xfs_mount_args	*args = xfs_args_allocate(sb, 0);
 	int			error;
 
 	VFS_PARSEARGS(vfsp, options, args, 1, error);
@@ -825,7 +826,7 @@
 {
 	vnode_t			*rootvp;
 	struct vfs		*vfsp = vfs_allocate(sb);
-	struct xfs_mount_args	*args = xfs_args_allocate(sb);
+	struct xfs_mount_args	*args = xfs_args_allocate(sb, silent);
 	struct kstatfs		statvfs;
 	int			error, error2;
 
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 06f5845..2a8e16c 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -173,6 +173,12 @@
 typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
+typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
+				struct pipe_inode_info *, size_t, int, int,
+				struct cred *);
+typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
+				struct file *, loff_t *, size_t, int, int,
+				struct cred *);
 typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
 				int, unsigned int, void __user *);
 typedef int	(*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -231,6 +237,8 @@
 	vop_read_t		vop_read;
 	vop_write_t		vop_write;
 	vop_sendfile_t		vop_sendfile;
+	vop_splice_read_t	vop_splice_read;
+	vop_splice_write_t	vop_splice_write;
 	vop_ioctl_t		vop_ioctl;
 	vop_getattr_t		vop_getattr;
 	vop_setattr_t		vop_setattr;
@@ -276,6 +284,10 @@
 	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
 #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv)		\
 	rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
+#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
+	rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
+#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
+	rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
 #define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
 	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
 #define VOP_OPEN(vp, cr, rv)						\
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 73c1e5e..7fb5eca 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -2624,7 +2624,7 @@
 {
 	int		error;
 	xfs_mount_t	*mp;
-	uint		delblks, blkflags;
+	uint		delblks, blkflags, prjflags = 0;
 	xfs_dquot_t	*unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
 	ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2650,10 +2650,13 @@
 		}
 	}
 	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
-		if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
-		    (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+		if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+			prjflags = XFS_QMOPT_ENOSPC;
+
+		if (prjflags ||
+		    (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+		     ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
 			delblksgdq = gdqp;
 			if (delblks) {
 				ASSERT(ip->i_gdquot);
@@ -2664,7 +2667,7 @@
 
 	if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
 				delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-				flags | blkflags)))
+				flags | blkflags | prjflags)))
 		return (error);
 
 	/*
@@ -2681,7 +2684,7 @@
 		ASSERT(unresudq || unresgdq);
 		if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-				flags | blkflags)))
+				flags | blkflags | prjflags)))
 			return (error);
 		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index d8e131e..9168918 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -595,12 +595,19 @@
 	}
 }
 
+STATIC int
+xfs_quota_error(uint flags)
+{
+	if (flags & XFS_QMOPT_ENOSPC)
+		return ENOSPC;
+	return EDQUOT;
+}
+
 /*
  * This reserves disk blocks and inodes against a dquot.
  * Flags indicate if the dquot is to be locked here and also
  * if the blk reservation is for RT or regular blocks.
  * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
- * Returns EDQUOT if quota is exceeded.
  */
 STATIC int
 xfs_trans_dqresv(
@@ -666,19 +673,15 @@
 			 */
 			if (hardlimit > 0ULL &&
 			     (hardlimit <= nblks + *resbcountp)) {
-				error = EDQUOT;
+				error = xfs_quota_error(flags);
 				goto error_return;
 			}
 
 			if (softlimit > 0ULL &&
 			     (softlimit <= nblks + *resbcountp)) {
-				/*
-				 * If timer or warnings has expired,
-				 * return EDQUOT
-				 */
 				if ((timer != 0 && get_seconds() > timer) ||
 				    (warns != 0 && warns >= warnlimit)) {
-					error = EDQUOT;
+					error = xfs_quota_error(flags);
 					goto error_return;
 				}
 			}
@@ -695,16 +698,12 @@
 			if (!softlimit)
 				softlimit = q->qi_isoftlimit;
 			if (hardlimit > 0ULL && count >= hardlimit) {
-				error = EDQUOT;
+				error = xfs_quota_error(flags);
 				goto error_return;
 			} else if (softlimit > 0ULL && count >= softlimit) {
-				/*
-				 * If timer or warnings has expired,
-				 * return EDQUOT
-				 */
 				if ((timer != 0 && get_seconds() > timer) ||
 				     (warns != 0 && warns >= warnlimit)) {
-					error = EDQUOT;
+					error = xfs_quota_error(flags);
 					goto error_return;
 				}
 			}
@@ -751,13 +750,14 @@
 
 
 /*
- * Given a dquot(s), make disk block and/or inode reservations against them.
+ * Given dquot(s), make disk block and/or inode reservations against them.
  * The fact that this does the reservation against both the usr and
- * grp quotas is important, because this follows a both-or-nothing
+ * grp/prj quotas is important, because this follows a both-or-nothing
  * approach.
  *
  * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
  *	   XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
+ *	   XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT.  Used by pquota.
  *	   XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
  *	   XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
  * dquots are unlocked on return, if they were not locked by caller.
@@ -772,25 +772,27 @@
 	long		ninos,
 	uint		flags)
 {
-	int		resvd;
+	int		resvd = 0, error;
 
-	if (! XFS_IS_QUOTA_ON(mp))
-		return (0);
+	if (!XFS_IS_QUOTA_ON(mp))
+		return 0;
 
 	if (tp && tp->t_dqinfo == NULL)
 		xfs_trans_alloc_dqinfo(tp);
 
 	ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
-	resvd = 0;
 
 	if (udqp) {
-		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
-			return (EDQUOT);
+		error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
+					(flags & ~XFS_QMOPT_ENOSPC));
+		if (error)
+			return error;
 		resvd = 1;
 	}
 
 	if (gdqp) {
-		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
+		error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
+		if (error) {
 			/*
 			 * can't do it, so backout previous reservation
 			 */
@@ -799,14 +801,14 @@
 				xfs_trans_dqresv(tp, mp, udqp,
 						 -nblks, -ninos, flags);
 			}
-			return (EDQUOT);
+			return error;
 		}
 	}
 
 	/*
 	 * Didn't change anything critical, so, no need to log
 	 */
-	return (0);
+	return 0;
 }
 
 
@@ -814,8 +816,6 @@
  * Lock the dquot and change the reservation if we can.
  * This doesn't change the actual usage, just the reservation.
  * The inode sent in is locked.
- *
- * Returns 0 on success, EDQUOT or other errors otherwise
  */
 STATIC int
 xfs_trans_reserve_quota_nblks(
@@ -824,20 +824,24 @@
 	xfs_inode_t	*ip,
 	long		nblks,
 	long		ninos,
-	uint		type)
+	uint		flags)
 {
 	int		error;
 
 	if (!XFS_IS_QUOTA_ON(mp))
-		return (0);
+		return 0;
+	if (XFS_IS_PQUOTA_ON(mp))
+		flags |= XFS_QMOPT_ENOSPC;
 
 	ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
 	ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
 
 	ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
 	ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
-	ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
-	       (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
+	ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+				XFS_TRANS_DQ_RES_RTBLKS ||
+	       (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+				XFS_TRANS_DQ_RES_BLKS);
 
 	/*
 	 * Reserve nblks against these dquots, with trans as the mediator.
@@ -845,8 +849,8 @@
 	error = xfs_trans_reserve_quota_bydquots(tp, mp,
 						 ip->i_udquot, ip->i_gdquot,
 						 nblks, ninos,
-						 type);
-	return (error);
+						 flags);
+	return error;
 }
 
 /*
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index d384e48..26939d3 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4719,18 +4719,17 @@
 				/*
 				 * Make a transaction-less quota reservation for
 				 * delayed allocation blocks. This number gets
-				 * adjusted later.
-				 * We return EDQUOT if we haven't allocated
-				 * blks already inside this loop;
+				 * adjusted later.  We return if we haven't
+				 * allocated blocks already inside this loop.
 				 */
-				if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+				if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
 						mp, NULL, ip, (long)alen, 0,
 						rt ? XFS_QMOPT_RES_RTBLKS :
-						     XFS_QMOPT_RES_REGBLKS)) {
+						     XFS_QMOPT_RES_REGBLKS))) {
 					if (n == 0) {
 						*nmap = 0;
 						ASSERT(cur == NULL);
-						return XFS_ERROR(EDQUOT);
+						return error;
 					}
 					break;
 				}
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f83399c..8e0d73d 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -353,10 +353,11 @@
 	xfs_extnum_t		num);
 
 /*
- * Call xfs_bmap_do_search_extents() to search for the extent
- * record containing block bno. If in multi-level in-core extent
- * allocation mode, find and extract the target extent buffer,
- * otherwise just use the direct extent list.
+ * Search the extent records for the entry containing block bno.
+ * If bno lies in a hole, point to the next entry.  If bno lies
+ * past eof, *eofp will be set, and *prevp will contain the last
+ * entry (null if none).  Else, *lastxp will be set to the index
+ * of the found entry; *gotp will contain the entry.
  */
 xfs_bmbt_rec_t *
 xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 022fff6..5b7eb81 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -68,6 +68,7 @@
 						 * enforcement */
 #define XFSMNT_PQUOTAENF	0x00000040	/* IRIX project quota limit
 						 * enforcement */
+#define XFSMNT_QUIET		0x00000080	/* don't report mount errors */
 #define XFSMNT_NOALIGN		0x00000200	/* don't allocate at
 						 * stripe boundaries*/
 #define XFSMNT_RETERR		0x00000400	/* return error to user */
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 26b8e70..bc43163 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -186,4 +186,7 @@
 #define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
 	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
 
+#define xfs_fs_mount_cmn_err(f, fmt, args...) \
+	((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
+
 #endif	/* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 4eeb856..deddbd0 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -158,9 +158,10 @@
  	 */
 	agi = XFS_BUF_TO_AGI(agbp);
 	newino = be32_to_cpu(agi->agi_newino);
-	if(likely(newino != NULLAGINO)) {
-		args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
-				XFS_IALLOC_BLOCKS(args.mp);
+	args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
+			XFS_IALLOC_BLOCKS(args.mp);
+	if (likely(newino != NULLAGINO &&
+		  (args.agbno < be32_to_cpu(agi->agi_length)))) {
 		args.fsbno = XFS_AGB_TO_FSB(args.mp,
 				be32_to_cpu(agi->agi_seqno), args.agbno);
 		args.type = XFS_ALLOCTYPE_THIS_BNO;
@@ -182,8 +183,8 @@
 		 * Set the alignment for the allocation.
 		 * If stripe alignment is turned on then align at stripe unit
 		 * boundary.
-		 * If the cluster size is smaller than a filesystem block 
-		 * then we're doing I/O for inodes in filesystem block size 
+		 * If the cluster size is smaller than a filesystem block
+		 * then we're doing I/O for inodes in filesystem block size
 		 * pieces, so don't need alignment anyway.
 		 */
 		isaligned = 0;
@@ -192,7 +193,7 @@
 			args.alignment = args.mp->m_dalign;
 			isaligned = 1;
 		} else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
-			   args.mp->m_sb.sb_inoalignmt >= 
+			   args.mp->m_sb.sb_inoalignmt >=
 			   XFS_B_TO_FSBT(args.mp,
 			  	XFS_INODE_CLUSTER_SIZE(args.mp)))
 				args.alignment = args.mp->m_sb.sb_inoalignmt;
@@ -220,7 +221,7 @@
 		if ((error = xfs_alloc_vextent(&args)))
 			return error;
 	}
- 
+
 	/*
 	 * If stripe alignment is turned on, then try again with cluster
 	 * alignment.
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index bb33113..b538543 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -421,7 +421,10 @@
 			ip->i_chash = chlnew;
 			chlnew->chl_ip = ip;
 			chlnew->chl_blkno = ip->i_blkno;
+			if (ch->ch_list)
+				ch->ch_list->chl_prev = chlnew;
 			chlnew->chl_next = ch->ch_list;
+			chlnew->chl_prev = NULL;
 			ch->ch_list = chlnew;
 			chlnew = NULL;
 		}
@@ -723,23 +726,15 @@
 		ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
 		ASSERT(ip->i_chash != NULL);
 		chm=NULL;
-		for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
-			if (chl->chl_blkno == ip->i_blkno) {
-				if (chm == NULL) {
-					/* first item on the list */
-					ch->ch_list = chl->chl_next;
-				} else {
-					chm->chl_next = chl->chl_next;
-				}
-				kmem_zone_free(xfs_chashlist_zone, chl);
-				break;
-			} else {
-				ASSERT(chl->chl_ip != ip);
-				chm = chl;
-			}
-		}
-		ASSERT_ALWAYS(chl != NULL);
-       } else {
+		chl = ip->i_chash;
+		if (chl->chl_prev)
+			chl->chl_prev->chl_next = chl->chl_next;
+		else
+			ch->ch_list = chl->chl_next;
+		if (chl->chl_next)
+			chl->chl_next->chl_prev = chl->chl_prev;
+		kmem_zone_free(xfs_chashlist_zone, chl);
+	} else {
 		/* delete one inode from a non-empty list */
 		iq = ip->i_cnext;
 		iq->i_cprev = ip->i_cprev;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 48146bd..94b60dd0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2732,16 +2732,29 @@
 	ASSERT(atomic_read(&ip->i_pincount) > 0);
 
 	if (atomic_dec_and_test(&ip->i_pincount)) {
-		vnode_t	*vp = XFS_ITOV_NULL(ip);
+		/*
+		 * If the inode is currently being reclaimed, the
+		 * linux inode _and_ the xfs vnode may have been
+		 * freed so we cannot reference either of them safely.
+		 * Hence we should not try to do anything to them
+		 * if the xfs inode is currently in the reclaim
+		 * path.
+		 *
+		 * However, we still need to issue the unpin wakeup
+		 * call as the inode reclaim may be blocked waiting for
+		 * the inode to become unpinned.
+		 */
+		if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
+			vnode_t	*vp = XFS_ITOV_NULL(ip);
 
-		/* make sync come back and flush this inode */
-		if (vp) {
-			struct inode	*inode = vn_to_inode(vp);
+			/* make sync come back and flush this inode */
+			if (vp) {
+				struct inode	*inode = vn_to_inode(vp);
 
-			if (!(inode->i_state & I_NEW))
-				mark_inode_dirty_sync(inode);
+				if (!(inode->i_state & I_NEW))
+					mark_inode_dirty_sync(inode);
+			}
 		}
-
 		wake_up(&ip->i_ipin_wait);
 	}
 }
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 39ef9c3..3b544db 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -189,6 +189,7 @@
  */
 typedef struct xfs_chashlist {
 	struct xfs_chashlist	*chl_next;
+	struct xfs_chashlist	*chl_prev;
 	struct xfs_inode	*chl_ip;
 	xfs_daddr_t		chl_blkno;	/* starting block number of
 						 * the cluster */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 72e7e78..c0b1c29 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -213,7 +213,8 @@
 STATIC int
 xfs_mount_validate_sb(
 	xfs_mount_t	*mp,
-	xfs_sb_t	*sbp)
+	xfs_sb_t	*sbp,
+	int		flags)
 {
 	/*
 	 * If the log device and data device have the
@@ -223,33 +224,29 @@
 	 * a volume filesystem in a non-volume manner.
 	 */
 	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-		cmn_err(CE_WARN, "XFS: bad magic number");
+		xfs_fs_mount_cmn_err(flags, "bad magic number");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (!XFS_SB_GOOD_VERSION(sbp)) {
-		cmn_err(CE_WARN, "XFS: bad version");
+		xfs_fs_mount_cmn_err(flags, "bad version");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
-		cmn_err(CE_WARN,
-	"XFS: filesystem is marked as having an external log; "
-	"specify logdev on the\nmount command line.");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)",
-				     XFS_ERRLEVEL_HIGH, mp, sbp);
-		return XFS_ERROR(EFSCORRUPTED);
+		xfs_fs_mount_cmn_err(flags,
+			"filesystem is marked as having an external log; "
+			"specify logdev on the\nmount command line.");
+		return XFS_ERROR(EINVAL);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
-		cmn_err(CE_WARN,
-	"XFS: filesystem is marked as having an internal log; "
-	"don't specify logdev on\nthe mount command line.");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)",
-				     XFS_ERRLEVEL_HIGH, mp, sbp);
-		return XFS_ERROR(EFSCORRUPTED);
+		xfs_fs_mount_cmn_err(flags,
+			"filesystem is marked as having an internal log; "
+			"do not specify logdev on\nthe mount command line.");
+		return XFS_ERROR(EINVAL);
 	}
 
 	/*
@@ -273,10 +270,8 @@
 	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
-	    (sbp->sb_imax_pct > 100 || sbp->sb_imax_pct < 1))) {
-		cmn_err(CE_WARN, "XFS: SB sanity check 1 failed");
-		XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)",
-				     XFS_ERRLEVEL_LOW, mp, sbp);
+	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
+		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -289,9 +284,7 @@
 	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
 	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
 			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
-		cmn_err(CE_WARN, "XFS: SB sanity check 2 failed");
-		XFS_ERROR_REPORT("xfs_mount_validate_sb(4)",
-				 XFS_ERRLEVEL_LOW, mp);
+		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -307,15 +300,13 @@
 	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
 	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
 #endif
-		cmn_err(CE_WARN,
-	"XFS: File system is too large to be mounted on this system.");
+		xfs_fs_mount_cmn_err(flags,
+			"file system too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
 	}
 
 	if (unlikely(sbp->sb_inprogress)) {
-		cmn_err(CE_WARN, "XFS: file system busy");
-		XFS_ERROR_REPORT("xfs_mount_validate_sb(5)",
-				 XFS_ERRLEVEL_LOW, mp);
+		xfs_fs_mount_cmn_err(flags, "file system busy");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -323,8 +314,8 @@
 	 * Version 1 directory format has never worked on Linux.
 	 */
 	if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
-		cmn_err(CE_WARN,
-	"XFS: Attempted to mount file system using version 1 directory format");
+		xfs_fs_mount_cmn_err(flags,
+			"file system using version 1 directory format");
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -332,11 +323,11 @@
 	 * Until this is fixed only page-sized or smaller data blocks work.
 	 */
 	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
-		cmn_err(CE_WARN,
-		"XFS: Attempted to mount file system with blocksize %d bytes",
+		xfs_fs_mount_cmn_err(flags,
+			"file system with blocksize %d bytes",
 			sbp->sb_blocksize);
-		cmn_err(CE_WARN,
-		"XFS: Only page-sized (%ld) or less blocksizes currently work.",
+		xfs_fs_mount_cmn_err(flags,
+			"only pagesize (%ld) or less will currently work.",
 			PAGE_SIZE);
 		return XFS_ERROR(ENOSYS);
 	}
@@ -484,7 +475,7 @@
  * Does the initial read of the superblock.
  */
 int
-xfs_readsb(xfs_mount_t *mp)
+xfs_readsb(xfs_mount_t *mp, int flags)
 {
 	unsigned int	sector_size;
 	unsigned int	extra_flags;
@@ -506,7 +497,7 @@
 	bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
 				BTOBB(sector_size), extra_flags);
 	if (!bp || XFS_BUF_ISERROR(bp)) {
-		cmn_err(CE_WARN, "XFS: SB read failed");
+		xfs_fs_mount_cmn_err(flags, "SB read failed");
 		error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
 		goto fail;
 	}
@@ -520,9 +511,9 @@
 	sbp = XFS_BUF_TO_SBP(bp);
 	xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
 
-	error = xfs_mount_validate_sb(mp, &(mp->m_sb));
+	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: SB validate failed");
+		xfs_fs_mount_cmn_err(flags, "SB validate failed");
 		goto fail;
 	}
 
@@ -530,8 +521,8 @@
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 */
 	if (sector_size > mp->m_sb.sb_sectsize) {
-		cmn_err(CE_WARN,
-			"XFS: device supports only %u byte sectors (not %u)",
+		xfs_fs_mount_cmn_err(flags,
+			"device supports only %u byte sectors (not %u)",
 			sector_size, mp->m_sb.sb_sectsize);
 		error = ENOSYS;
 		goto fail;
@@ -548,7 +539,7 @@
 		bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
 					BTOBB(sector_size), extra_flags);
 		if (!bp || XFS_BUF_ISERROR(bp)) {
-			cmn_err(CE_WARN, "XFS: SB re-read failed");
+			xfs_fs_mount_cmn_err(flags, "SB re-read failed");
 			error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
 			goto fail;
 		}
@@ -678,7 +669,7 @@
 	int		error = 0;
 
 	if (mp->m_sb_bp == NULL) {
-		if ((error = xfs_readsb(mp))) {
+		if ((error = xfs_readsb(mp, mfsi_flags))) {
 			return error;
 		}
 	}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 66cbee7..668ad23 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -510,9 +510,12 @@
  */
 #define XFS_MFSI_SECOND		0x01	/* Secondary mount -- skip stuff */
 #define XFS_MFSI_CLIENT		0x02	/* Is a client -- skip lots of stuff */
+/*	XFS_MFSI_RRINODES	*/
 #define XFS_MFSI_NOUNLINK	0x08	/* Skip unlinked inode processing in */
 					/* log recovery */
 #define XFS_MFSI_NO_QUOTACHECK	0x10	/* Skip quotacheck processing */
+/*	XFS_MFSI_CONVERT_SUNIT	*/
+#define XFS_MFSI_QUIET		0x40	/* Be silent if mount errors found */
 
 /*
  * Macros for getting from mount to vfs and back.
@@ -581,7 +584,7 @@
 extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
 			uint, int);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
-extern int	xfs_readsb(xfs_mount_t *mp);
+extern int	xfs_readsb(xfs_mount_t *, int);
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 4f6a034..7fbef97 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -196,10 +196,11 @@
 #define XFS_QMOPT_QUOTAOFF	0x0000080 /* quotas are being turned off */
 #define XFS_QMOPT_UMOUNTING	0x0000100 /* filesys is being unmounted */
 #define XFS_QMOPT_DOLOG		0x0000200 /* log buf changes (in quotacheck) */
-#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if necessary */
+#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if needed */
 #define XFS_QMOPT_ILOCKED	0x0000800 /* inode is already locked (excl) */
-#define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot if damaged */
 #define XFS_QMOPT_GQUOTA	0x0002000 /* group dquot requested */
+#define XFS_QMOPT_ENOSPC	0x0004000 /* enospc instead of edquot (prj) */
 
 /*
  * flags to xfs_trans_mod_dquot to indicate which field needs to be
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 504d2a8..f0e09ca 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -442,6 +442,9 @@
 	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
 	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
 
+	if (args->flags & XFSMNT_QUIET)
+		flags |= XFS_MFSI_QUIET;
+
 	/*
 	 * Open real time and log devices - order is important.
 	 */
@@ -492,7 +495,7 @@
 	error = xfs_start_flags(vfsp, args, mp);
 	if (error)
 		goto error1;
-	error = xfs_readsb(mp);
+	error = xfs_readsb(mp, flags);
 	if (error)
 		goto error1;
 	error = xfs_finish_flags(vfsp, args, mp);
@@ -1697,8 +1700,9 @@
 	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
 	int			iosize;
 
-	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
 	args->flags |= XFSMNT_IDELETE;
+	args->flags |= XFSMNT_BARRIER;
+	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
 
 	if (!options)
 		goto done;
@@ -1947,8 +1951,6 @@
 		seq_printf(m, "," MNTOPT_IKEEP);
 	if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
 		seq_printf(m, "," MNTOPT_LARGEIO);
-	if (mp->m_flags & XFS_MOUNT_BARRIER)
-		seq_printf(m, "," MNTOPT_BARRIER);
 
 	if (!(vfsp->vfs_flag & VFS_32BITINODES))
 		seq_printf(m, "," MNTOPT_64BITINODE);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de49601..fa71b30 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4649,6 +4649,10 @@
 #ifdef HAVE_SENDFILE
 	.vop_sendfile		= xfs_sendfile,
 #endif
+#ifdef HAVE_SPLICE
+	.vop_splice_read	= xfs_splice_read,
+	.vop_splice_write	= xfs_splice_write,
+#endif
 	.vop_write		= xfs_write,
 	.vop_ioctl		= xfs_ioctl,
 	.vop_getattr		= xfs_getattr,
diff --git a/include/asm-alpha/numnodes.h b/include/asm-alpha/numnodes.h
deleted file mode 100644
index cd42582..0000000
--- a/include/asm-alpha/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes - Marvel */
-#define NODES_SHIFT	7
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
new file mode 100644
index 0000000..f28636d
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
@@ -0,0 +1,104 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_mci.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * MultiMedia Card Interface (MCI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * 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.
+ */
+
+#ifndef AT91RM9200_MCI_H
+#define AT91RM9200_MCI_H
+
+#define AT91_MCI_CR		0x00		/* Control Register */
+#define		AT91_MCI_MCIEN		(1 <<  0)	/* Multi-Media Interface Enable */
+#define		AT91_MCI_MCIDIS		(1 <<  1)	/* Multi-Media Interface Disable */
+#define		AT91_MCI_PWSEN		(1 <<  2)	/* Power Save Mode Enable */
+#define		AT91_MCI_PWSDIS		(1 <<  3)	/* Power Save Mode Disable */
+#define		AT91_MCI_SWRST		(1 <<  7)	/* Software Reset */
+
+#define AT91_MCI_MR		0x04		/* Mode Register */
+#define		AT91_MCI_CLKDIV		(0xff  <<  0)	/* Clock Divider */
+#define		AT91_MCI_PWSDIV		(3     <<  8)	/* Power Saving Divider */
+#define		AT91_MCI_PDCPADV	(1     << 14)	/* PDC Padding Value */
+#define		AT91_MCI_PDCMODE	(1     << 15)	/* PDC-orientated Mode */
+#define		AT91_MCI_BLKLEN 	(0xfff << 18)	/* Data Block Length */
+
+#define AT91_MCI_DTOR		0x08		/* Data Timeout Register */
+#define		AT91_MCI_DTOCYC		(0xf << 0)	/* Data Timeout Cycle Number */
+#define		AT91_MCI_DTOMUL		(7   << 4)	/* Data Timeout Multiplier */
+#define		AT91_MCI_DTOMUL_1		(0 <<  4)
+#define		AT91_MCI_DTOMUL_16		(1 <<  4)
+#define		AT91_MCI_DTOMUL_128		(2 <<  4)
+#define		AT91_MCI_DTOMUL_256		(3 <<  4)
+#define		AT91_MCI_DTOMUL_1K		(4 <<  4)
+#define		AT91_MCI_DTOMUL_4K		(5 <<  4)
+#define		AT91_MCI_DTOMUL_64K		(6 <<  4)
+#define		AT91_MCI_DTOMUL_1M		(7 <<  4)
+
+#define AT91_MCI_SDCR		0x0c		/* SD Card Register */
+#define		AT91_MCI_SDCSEL		(0xf << 0)	/* SD Card Selector */
+#define		AT91_MCI_SDCBUS		(1   << 7)	/* 1-bit or 4-bit bus */
+
+#define AT91_MCI_ARGR		0x10		/* Argument Register */
+
+#define AT91_MCI_CMDR		0x14		/* Command Register */
+#define		AT91_MCI_CMDNB		(0x3f << 0)	/* Command Number */
+#define		AT91_MCI_RSPTYP		(3    << 6)	/* Response Type */
+#define			AT91_MCI_RSPTYP_NONE	(0 <<  6)
+#define			AT91_MCI_RSPTYP_48	(1 <<  6)
+#define			AT91_MCI_RSPTYP_136	(2 <<  6)
+#define		AT91_MCI_SPCMD		(7    << 8)	/* Special Command */
+#define			AT91_MCI_SPCMD_NONE	(0 <<  8)
+#define			AT91_MCI_SPCMD_INIT	(1 <<  8)
+#define			AT91_MCI_SPCMD_SYNC	(2 <<  8)
+#define			AT91_MCI_SPCMD_ICMD	(4 <<  8)
+#define			AT91_MCI_SPCMD_IRESP	(5 <<  8)
+#define		AT91_MCI_OPDCMD		(1 << 11)	/* Open Drain Command */
+#define		AT91_MCI_MAXLAT		(1 << 12)	/* Max Latency for Command to Response */
+#define		AT91_MCI_TRCMD		(3 << 16)	/* Transfer Command */
+#define			AT91_MCI_TRCMD_NONE	(0 << 16)
+#define			AT91_MCI_TRCMD_START	(1 << 16)
+#define			AT91_MCI_TRCMD_STOP	(2 << 16)
+#define		AT91_MCI_TRDIR		(1 << 18)	/* Transfer Direction */
+#define		AT91_MCI_TRTYP		(3 << 19)	/* Transfer Type */
+#define			AT91_MCI_TRTYP_BLOCK	(0 << 19)
+#define			AT91_MCI_TRTYP_MULTIPLE	(1 << 19)
+#define			AT91_MCI_TRTYP_STREAM	(2 << 19)
+
+#define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
+#define AT91_MCR_RDR		0x30		/* Receive Data Register */
+#define AT91_MCR_TDR		0x34		/* Transmit Data Register */
+
+#define AT91_MCI_SR		0x40		/* Status Register */
+#define		AT91_MCI_CMDRDY		(1 <<  0)	/* Command Ready */
+#define		AT91_MCI_RXRDY		(1 <<  1) 	/* Receiver Ready */
+#define		AT91_MCI_TXRDY		(1 <<  2)	/* Transmit Ready */
+#define		AT91_MCI_BLKE		(1 <<  3)	/* Data Block Ended */
+#define		AT91_MCI_DTIP		(1 <<  4)	/* Data Transfer in Progress */
+#define		AT91_MCI_NOTBUSY	(1 <<  5)	/* Data Not Busy */
+#define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
+#define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
+#define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
+#define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
+#define		AT91_MCI_RINDE		(1 << 16)  	/* Response Index Error */
+#define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
+#define		AT91_MCI_RCRCE		(1 << 18)   	/* Response CRC Error */
+#define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
+#define		AT91_MCI_RTOE		(1 << 20)	/* Reponse Time-out Error */
+#define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
+#define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
+#define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
+#define		AT91_MCI_UNRE		(1 << 31)	/* Underrun */
+
+#define AT91_MCI_IER		0x44		/* Interrupt Enable Register */
+#define AT91_MCI_IDR		0x48		/* Interrupt Disable Register */
+#define AT91_MCI_IMR		0x4c		/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
index 2e7d113..4fdef13 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -38,6 +38,8 @@
 extern int at91_serial_map[AT91_NR_UART];
 extern int at91_console_port;
 
+#include <linux/mtd/partitions.h>
+
  /* USB Device */
 struct at91_udc_data {
 	u8	vbus_pin;		/* high == host powering us */
@@ -77,4 +79,26 @@
 };
 extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
 
+ /* NAND / SmartMedia */
+struct at91_nand_data {
+	u8		enable_pin;	/* chip enable */
+	u8		det_pin;	/* card detect */
+	u8		rdy_pin;	/* ready/busy */
+	u8		ale;		/* address line number connected to ALE */
+	u8		cle;		/* address line number connected to CLE */
+        struct mtd_partition* (*partition_info)(int, int*);
+};
+extern void __init at91_add_device_nand(struct at91_nand_data *data);
+
+ /* I2C*/
+void __init at91_add_device_i2c(void);
+
+ /* RTC */
+void __init at91_add_device_rtc(void);
+
+ /* LEDs */
+extern u8 at91_leds_cpu;
+extern u8 at91_leds_timer;
+extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
+
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
index 2646c01..59e6f44 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -65,6 +65,9 @@
 /* SmartMedia */
 #define AT91_SMARTMEDIA_BASE	0x40000000	/* NCS3: Smartmedia physical base address */
 
+/* Compact Flash */
+#define AT91_CF_BASE		0x50000000	/* NCS4-NCS6: Compact Flash physical base address */
+
 /* Multi-Master Memory controller */
 #define AT91_UHP_BASE		0x00300000	/* USB Host controller */
 
diff --git a/include/asm-arm/arch-cl7500/hardware.h b/include/asm-arm/arch-cl7500/hardware.h
index 2339b76..1adfd18 100644
--- a/include/asm-arm/arch-cl7500/hardware.h
+++ b/include/asm-arm/arch-cl7500/hardware.h
@@ -53,16 +53,12 @@
 #define SCREEN_END		0xdfc00000
 #define SCREEN_BASE		0xdf800000
 
-#define FLUSH_BASE		0xdf000000
-
 #define VIDC_BASE		(void __iomem *)0xe0400000
 #define IOMD_BASE		IOMEM(0xe0200000)
 #define IOC_BASE		IOMEM(0xe0200000)
 #define FLOPPYDMA_BASE		IOMEM(0xe002a000)
 #define PCIO_BASE		IOMEM(0xe0010000)
 
-#define FLUSH_BASE_PHYS		0x00000000	/* ROM */
-
 #define vidc_writel(val)	__raw_writel(val, VIDC_BASE)
 
 /* in/out bias for the ISA slot region */
diff --git a/include/asm-arm/arch-cl7500/memory.h b/include/asm-arm/arch-cl7500/memory.h
index 34f40a6..3178140 100644
--- a/include/asm-arm/arch-cl7500/memory.h
+++ b/include/asm-arm/arch-cl7500/memory.h
@@ -26,4 +26,10 @@
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
 
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS		0x00000000
+#define FLUSH_BASE		0xdf000000
+
 #endif
diff --git a/include/asm-arm/arch-ebsa110/debug-macro.S b/include/asm-arm/arch-ebsa110/debug-macro.S
index f61cada..9213bfe 100644
--- a/include/asm-arm/arch-ebsa110/debug-macro.S
+++ b/include/asm-arm/arch-ebsa110/debug-macro.S
@@ -18,4 +18,4 @@
 
 #define UART_SHIFT	2
 #define FLOW_CONTROL
-#include <asm/hardware/debug-8250.h>
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-ebsa110/hardware.h b/include/asm-arm/arch-ebsa110/hardware.h
index 4e41c23..3ce864d 100644
--- a/include/asm-arm/arch-ebsa110/hardware.h
+++ b/include/asm-arm/arch-ebsa110/hardware.h
@@ -57,9 +57,6 @@
 /*
  * RAM definitions
  */
-#define FLUSH_BASE_PHYS		0x40000000
-#define FLUSH_BASE		0xdf000000
-
 #define UNCACHEABLE_ADDR	0xff000000	/* IRQ_STAT */
 
 #endif
diff --git a/include/asm-arm/arch-ebsa110/memory.h b/include/asm-arm/arch-ebsa110/memory.h
index 02f1445..c7c500e1 100644
--- a/include/asm-arm/arch-ebsa110/memory.h
+++ b/include/asm-arm/arch-ebsa110/memory.h
@@ -28,4 +28,10 @@
 #define __virt_to_bus(x)	(x)
 #define __bus_to_virt(x)	(x)
 
+/*
+ * Cache flushing area - SRAM
+ */
+#define FLUSH_BASE_PHYS		0x40000000
+#define FLUSH_BASE		0xdf000000
+
 #endif
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
index 66b19c7..ae5b775 100644
--- a/include/asm-arm/arch-ebsa110/uncompress.h
+++ b/include/asm-arm/arch-ebsa110/uncompress.h
@@ -10,7 +10,7 @@
 
 #include <linux/serial_reg.h>
 
-#define SERIAL_BASE	((unsigned char *)0xfe000be0)
+#define SERIAL_BASE	((unsigned char *)0xf0000be0)
 
 /*
  * This does not append a newline
diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h
index 2ef2200..ec51fe9 100644
--- a/include/asm-arm/arch-ebsa285/hardware.h
+++ b/include/asm-arm/arch-ebsa285/hardware.h
@@ -48,9 +48,6 @@
 #define PCICFG0_SIZE		0x01000000
 #define PCICFG0_BASE		0xfa000000
 
-#define FLUSH_SIZE		0x00100000
-#define FLUSH_BASE		0xf9000000
-
 #define PCIMEM_SIZE		0x01000000
 #define PCIMEM_BASE		0xf0000000
 
@@ -61,9 +58,6 @@
 #define PCIMEM_SIZE		0x80000000
 #define PCIMEM_BASE		0x80000000
 
-#define FLUSH_SIZE		0x00100000
-#define FLUSH_BASE		0x7e000000
-
 #define WFLUSH_SIZE		0x01000000
 #define WFLUSH_BASE		0x7d000000
 
@@ -94,7 +88,6 @@
 #define XBUS_SWITCH_J17_11	((*XBUS_SWITCH) & (1 << 5))
 #define XBUS_SWITCH_J17_9	((*XBUS_SWITCH) & (1 << 6))
 
-#define FLUSH_BASE_PHYS		0x50000000
 #define UNCACHEABLE_ADDR	(ARMCSR_BASE + 0x108)
 
 
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index 09e335c..99181ff 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -49,12 +49,22 @@
 #define TASK_SIZE		UL(0xbf000000)
 #define PAGE_OFFSET		UL(0xc0000000)
 
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE		0xf9000000
+
 #elif defined(CONFIG_ARCH_CO285)
 
 /* Task size and page offset at 1.5GB */
 #define TASK_SIZE		UL(0x5f000000)
 #define PAGE_OFFSET		UL(0x60000000)
 
+/*
+ * Cache flushing area.
+ */
+#define FLUSH_BASE		0x7e000000
+
 #else
 
 #error "Undefined footbridge architecture"
@@ -72,4 +82,6 @@
  */
 #define TASK_UNMAPPED_BASE ((TASK_SIZE + 0x01000000) / 3)
 
+#define FLUSH_BASE_PHYS		0x50000000
+
 #endif
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
index 412215e..a94f63f 100644
--- a/include/asm-arm/arch-ep93xx/ts72xx.h
+++ b/include/asm-arm/arch-ep93xx/ts72xx.h
@@ -12,6 +12,8 @@
  * febfc000	[67]0000000	4K	NAND data register
  * febfb000	[67]0400000	4K	NAND control register
  * febfa000	[67]0800000	4K	NAND busy register
+ * febf9000	10800000	4K	TS-5620 RTC index register
+ * febf8000	11700000	4K	TS-5620 RTC data register
  */
 
 #define TS72XX_MODEL_PHYS_BASE		0x22000000
@@ -58,6 +60,15 @@
 #define TS72XX_NAND_BUSY_SIZE		0x00001000
 
 
+#define TS72XX_RTC_INDEX_VIRT_BASE	0xfebf9000
+#define TS72XX_RTC_INDEX_PHYS_BASE	0x10800000
+#define TS72XX_RTC_INDEX_SIZE		0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE	0xfebf8000
+#define TS72XX_RTC_DATA_PHYS_BASE	0x11700000
+#define TS72XX_RTC_DATA_SIZE		0x00001000
+
+
 #ifndef __ASSEMBLY__
 #include <asm/io.h>
 
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
index b45fa36..621ff2c 100644
--- a/include/asm-arm/arch-imx/dma.h
+++ b/include/asm-arm/arch-imx/dma.h
@@ -17,27 +17,16 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-/*
- * DMA registration
- */
-
 typedef enum {
 	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 3,
-	DMA_PRIO_LOW = 6
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
 } imx_dma_prio;
 
-int imx_request_dma(char *name, imx_dma_prio prio,
-		    void (*irq_handler) (int, void *, struct pt_regs *),
-		    void (*err_handler) (int, void *, struct pt_regs *),
-		    void *data);
-
-void imx_free_dma(int dma_ch);
-
-
 #define DMA_REQ_UART3_T        2
 #define DMA_REQ_UART3_R        3
 #define DMA_REQ_SSI2_T         4
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
new file mode 100644
index 0000000..f2063c1
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -0,0 +1,90 @@
+/*
+ *  linux/include/asm-arm/imxads/dma.h
+ *
+ *  Copyright (C) 1997,1998 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <asm/dma.h>
+
+#ifndef __ASM_ARCH_IMX_DMA_H
+#define __ASM_ARCH_IMX_DMA_H
+
+#define IMX_DMA_CHANNELS  11
+
+/*
+ * struct imx_dma_channel - i.MX specific DMA extension
+ * @name: name specified by DMA client
+ * @irq_handler: client callback for end of transfer
+ * @err_handler: client callback for error condition
+ * @data: clients context data for callbacks
+ * @dma_mode: direction of the transfer %DMA_MODE_READ or %DMA_MODE_WRITE
+ * @sg: pointer to the actual read/written chunk for scatter-gather emulation
+ * @sgbc: counter of processed bytes in the actual read/written chunk
+ * @resbytes: total residual number of bytes to transfer
+ *            (it can be lower or same as sum of SG mapped chunk sizes)
+ * @sgcount: number of chunks to be read/written
+ *
+ * Structure is used for IMX DMA processing. It would be probably good
+ * @struct dma_struct in the future for external interfacing and use
+ * @struct imx_dma_channel only as extension to it.
+ */
+
+struct imx_dma_channel {
+	const char *name;
+	void (*irq_handler) (int, void *, struct pt_regs *);
+	void (*err_handler) (int, void *, struct pt_regs *);
+	void *data;
+	dmamode_t  dma_mode;
+	struct scatterlist *sg;
+	unsigned int sgbc;
+	unsigned int sgcount;
+	unsigned int resbytes;
+	int dma_num;
+};
+
+extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+
+/* The type to distinguish channel numbers parameter from ordinal int type */
+typedef int imx_dmach_t;
+
+int
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+		unsigned int dma_length, unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+		 struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+		 unsigned int dev_addr, dmamode_t dmamode);
+
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+		void (*irq_handler) (int, void *, struct pt_regs *),
+		void (*err_handler) (int, void *, struct pt_regs *), void *data);
+
+void imx_dma_enable(imx_dmach_t dma_ch);
+
+void imx_dma_disable(imx_dmach_t dma_ch);
+
+int imx_dma_request(imx_dmach_t dma_ch, const char *name);
+
+void imx_dma_free(imx_dmach_t dma_ch);
+
+int imx_dma_request_by_prio(imx_dmach_t *pdma_ch, const char *name, imx_dma_prio prio);
+
+
+#endif	/* _ASM_ARCH_IMX_DMA_H */
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
new file mode 100644
index 0000000..1937151
--- /dev/null
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -0,0 +1,12 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/protocol.h>
+
+struct imxmmc_platform_data {
+	int (*card_present)(void);
+};
+
+extern void imx_set_mmc_info(struct imxmmc_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-ixp23xx/debug-macro.S b/include/asm-arm/arch-ixp23xx/debug-macro.S
index eb99fd6..2b25e64 100644
--- a/include/asm-arm/arch-ixp23xx/debug-macro.S
+++ b/include/asm-arm/arch-ixp23xx/debug-macro.S
@@ -17,6 +17,9 @@
 		tst	\rx, #1				@ mmu enabled?
 		ldreq	\rx, =IXP23XX_PERIPHERAL_PHYS 	@ physical
 		ldrne	\rx, =IXP23XX_PERIPHERAL_VIRT	@ virtual
+#ifdef __ARMEB__
+		orr	\rx, \rx, #0x00000003
+#endif
 		.endm
 
 #define UART_SHIFT	2
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h
index bebcf0a..6e19f46 100644
--- a/include/asm-arm/arch-ixp23xx/memory.h
+++ b/include/asm-arm/arch-ixp23xx/memory.h
@@ -28,6 +28,7 @@
  *		to an address that the kernel can use.
  */
 #ifndef __ASSEMBLY__
+#include <asm/mach-types.h>
 
 #define __virt_to_bus(v)						\
 	({ unsigned int ret;						\
@@ -40,6 +41,22 @@
 	data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR);		\
 	 __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); })
 
+/*
+ * Coherency support.  Only supported on A2 CPUs or on A1
+ * systems that have the cache coherency workaround.
+ */
+static inline int __ixp23xx_arch_is_coherent(void)
+{
+	extern unsigned int processor_id;
+
+	if (((processor_id & 15) >= 2) || machine_is_roadrunner())
+		return 1;
+
+	return 0;
+}
+
+#define arch_is_coherent()	__ixp23xx_arch_is_coherent()
+
 #endif
 
 
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
index f85b468..e4d9906 100644
--- a/include/asm-arm/arch-ixp23xx/platform.h
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -22,6 +22,7 @@
 int ixp23xx_pci_setup(int, struct pci_sys_data *);
 void ixp23xx_pci_preinit(void);
 struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*);
+void ixp23xx_pci_slave_init(void);
 
 extern struct sys_timer ixp23xx_timer;
 
diff --git a/include/asm-arm/arch-l7200/hardware.h b/include/asm-arm/arch-l7200/hardware.h
index b755079..2ab43f3 100644
--- a/include/asm-arm/arch-l7200/hardware.h
+++ b/include/asm-arm/arch-l7200/hardware.h
@@ -52,9 +52,6 @@
 #define ISA_SIZE		0x20000000
 #define ISA_BASE		0xe0000000
 
-#define FLUSH_BASE_PHYS		0x40000000	/* ROM */
-#define FLUSH_BASE		0xdf000000
-
 #define PCIO_BASE		IO_BASE
 
 #endif
diff --git a/include/asm-arm/arch-l7200/memory.h b/include/asm-arm/arch-l7200/memory.h
index 9e50a17..402df63 100644
--- a/include/asm-arm/arch-l7200/memory.h
+++ b/include/asm-arm/arch-l7200/memory.h
@@ -20,4 +20,10 @@
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
 
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS		0x40000000
+#define FLUSH_BASE		0xdf000000
+
 #endif
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h
index c92bcb8..9f1a58c 100644
--- a/include/asm-arm/arch-lh7a40x/memory.h
+++ b/include/asm-arm/arch-lh7a40x/memory.h
@@ -31,8 +31,6 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-#define NODES_SHIFT	4	/* Up to 16 nodes */
-
 /*
  * Given a kernel address, find the home node of the underlying memory.
  */
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h
index 590bac2..6513065 100644
--- a/include/asm-arm/arch-omap/aic23.h
+++ b/include/asm-arm/arch-omap/aic23.h
@@ -57,6 +57,7 @@
 #define LHV_MIN				0x0000
 
 // Analog audio path control register
+#define STA_REG(x)			((x)<<6)
 #define STE_ENABLED			0x0020
 #define DAC_SELECTED			0x0010
 #define BYPASS_ON			0x0008
@@ -109,4 +110,7 @@
 #define TLV320AIC23ID1                  (0x1a)	// cs low
 #define TLV320AIC23ID2                  (0x1b)	// cs high
 
+void tlv320aic23_power_up(void);
+void tlv320aic23_power_down(void);
+
 #endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-omap/board-ams-delta.h b/include/asm-arm/arch-omap/board-ams-delta.h
new file mode 100644
index 0000000..0070f6d
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-ams-delta.h
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-ams-delta.h
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * 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.
+ */
+#ifndef __ASM_ARCH_OMAP_AMS_DELTA_H
+#define __ASM_ARCH_OMAP_AMS_DELTA_H
+
+#if defined (CONFIG_MACH_AMS_DELTA)
+
+#define AMS_DELTA_LATCH1_PHYS		0x01000000
+#define AMS_DELTA_LATCH1_VIRT		0xEA000000
+#define AMS_DELTA_MODEM_PHYS		0x04000000
+#define AMS_DELTA_MODEM_VIRT		0xEB000000
+#define AMS_DELTA_LATCH2_PHYS		0x08000000
+#define AMS_DELTA_LATCH2_VIRT		0xEC000000
+
+#define AMS_DELTA_LATCH1_LED_CAMERA	0x01
+#define AMS_DELTA_LATCH1_LED_ADVERT	0x02
+#define AMS_DELTA_LATCH1_LED_EMAIL	0x04
+#define AMS_DELTA_LATCH1_LED_HANDSFREE	0x08
+#define AMS_DELTA_LATCH1_LED_VOICEMAIL	0x10
+#define AMS_DELTA_LATCH1_LED_VOICE	0x20
+
+#define AMS_DELTA_LATCH2_LCD_VBLEN	0x0001
+#define AMS_DELTA_LATCH2_LCD_NDISP	0x0002
+#define AMS_DELTA_LATCH2_NAND_NCE	0x0004
+#define AMS_DELTA_LATCH2_NAND_NRE	0x0008
+#define AMS_DELTA_LATCH2_NAND_NWP	0x0010
+#define AMS_DELTA_LATCH2_NAND_NWE	0x0020
+#define AMS_DELTA_LATCH2_NAND_ALE	0x0040
+#define AMS_DELTA_LATCH2_NAND_CLE	0x0080
+#define AMS_DELTA_LATCH2_MODEM_NRESET	0x1000
+#define AMS_DELTA_LATCH2_MODEM_CODEC	0x2000
+
+#define AMS_DELTA_GPIO_PIN_NAND_RB	12
+
+#ifndef __ASSEMBLY__
+void ams_delta_latch1_write(u8 mask, u8 value);
+void ams_delta_latch2_write(u16 mask, u16 value);
+#endif
+
+#endif /* CONFIG_MACH_AMS_DELTA */
+
+#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/include/asm-arm/arch-omap/board-apollon.h b/include/asm-arm/arch-omap/board-apollon.h
new file mode 100644
index 0000000..de0c5b7
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-apollon.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/arch-omap/board-apollon.h
+ *
+ * Hardware definitions for Samsung OMAP24XX Apollon board.
+ *
+ * Initial creation by Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS 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.
+ */
+
+#ifndef __ASM_ARCH_OMAP_APOLLON_H
+#define __ASM_ARCH_OMAP_APOLLON_H
+
+/* Placeholder for APOLLON specific defines */
+/* GPMC CS0 */
+#define APOLLON_CS0_BASE		0x00000000
+/* GPMC CS1 */
+#define APOLLON_CS1_BASE		0x08000000
+#define APOLLON_ETHR_START		(APOLLON_CS1_BASE + 0x300)
+#define APOLLON_ETHR_GPIO_IRQ		74
+/* GPMC CS2 - reserved for OneNAND */
+#define APOLLON_CS2_BASE		0x10000000
+/* GPMC CS3 - reserved for NOR or NAND */
+#define APOLLON_CS3_BASE		0x18000000
+
+#endif /*  __ASM_ARCH_OMAP_APOLLON_H */
+
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index 39ca5a3..b2888ef 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -34,9 +34,5 @@
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
 #define OMAP1610_ETHR_START		0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 1b12c1d..761ea0a 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -30,10 +30,6 @@
 /* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
 #define OMAP1710_ETHR_START		0x04000300
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
-
 #define MAXIRQNUM			(IH_BOARD_BASE)
 #define MAXFIQNUM			MAXIRQNUM
 #define MAXSWINUM			MAXIRQNUM
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index 33ea29a..7ef664b 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -33,12 +33,6 @@
 /* GPMC CS1 */
 #define OMAP24XX_ETHR_START             0x08000300
 #define OMAP24XX_ETHR_GPIO_IRQ		92
-
-#define H4_CS0_BASE		     0x04000000
-
-#define H4_CS0_BASE		     0x04000000
-
-#define H4_CS0_BASE		     0x04000000
-
+#define H4_CS0_BASE			0x04000000
 #endif /*  __ASM_ARCH_OMAP_H4_H */
 
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h
deleted file mode 100644
index 77cc0fb..0000000
--- a/include/asm-arm/arch-omap/board-netstar.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Hardware definitions for OMAP5910 based NetStar board.
- *
- * 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_NETSTAR_H
-#define __ASM_ARCH_NETSTAR_H
-
-#include <asm/arch/tc.h>
-
-#define OMAP_NAND_FLASH_START1		OMAP_CS1_PHYS + (1 << 23)
-#define OMAP_NAND_FLASH_START2		OMAP_CS1_PHYS + (2 << 23)
-
-#endif /*  __ASM_ARCH_NETSTAR_H */
diff --git a/include/asm-arm/arch-omap/board-nokia.h b/include/asm-arm/arch-omap/board-nokia.h
new file mode 100644
index 0000000..72deea2
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-nokia.h
@@ -0,0 +1,54 @@
+/*
+ *  linux/include/asm-arm/arch-omap/board-nokia.h
+ *
+ *  Information structures for Nokia-specific board config data
+ *
+ *  Copyright (C) 2005	Nokia Corporation
+ */
+
+#ifndef _OMAP_BOARD_NOKIA_H
+#define _OMAP_BOARD_NOKIA_H
+
+#include <linux/types.h>
+
+#define OMAP_TAG_NOKIA_BT	0x4e01
+#define OMAP_TAG_WLAN_CX3110X	0x4e02
+#define OMAP_TAG_CBUS		0x4e03
+#define OMAP_TAG_EM_ASIC_BB5	0x4e04
+
+
+#define BT_CHIP_CSR		1
+#define BT_CHIP_TI		2
+
+#define BT_SYSCLK_12		1
+#define BT_SYSCLK_38_4		2
+
+struct omap_bluetooth_config {
+	u8    chip_type;
+	u8    bt_wakeup_gpio;
+	u8    host_wakeup_gpio;
+	u8    reset_gpio;
+	u8    bt_uart;
+	u8    bd_addr[6];
+	u8    bt_sysclk;
+};
+
+struct omap_wlan_cx3110x_config {
+	u8  chip_type;
+	s16 power_gpio;
+	s16 irq_gpio;
+	s16 spi_cs_gpio;
+};
+
+struct omap_cbus_config {
+	s16 clk_gpio;
+	s16 dat_gpio;
+	s16 sel_gpio;
+};
+
+struct omap_em_asic_bb5_config {
+	s16 retu_irq_gpio;
+	s16 tahvo_irq_gpio;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 691e52a..eb74420 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -42,8 +42,4 @@
 
 #define NR_IRQS			(MAXIRQNUM + 1)
 
-/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
-#define OMAP_NAND_FLASH_START1	   0x0A000000 /* CS2B */
-#define OMAP_NAND_FLASH_START2	   0x0C000000 /* CS3 */
-
 #endif
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index a0040cd..6d6240a 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -21,9 +21,12 @@
 #define OMAP_TAG_LCD		0x4f05
 #define OMAP_TAG_GPIO_SWITCH	0x4f06
 #define OMAP_TAG_UART		0x4f07
+#define OMAP_TAG_FBMEM		0x4f08
+#define OMAP_TAG_STI_CONSOLE	0x4f09
 
 #define OMAP_TAG_BOOT_REASON    0x4f80
 #define OMAP_TAG_FLASH_PART	0x4f81
+#define OMAP_TAG_VERSION_STR	0x4f82
 
 struct omap_clock_config {
 	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
@@ -54,6 +57,11 @@
 	u32 console_speed;
 };
 
+struct omap_sti_console_config {
+	unsigned enable:1;
+	u8 channel;
+};
+
 struct omap_usb_config {
 	/* Configure drivers according to the connectors on your board:
 	 *  - "A" connector (rectagular)
@@ -87,6 +95,13 @@
 	char ctrl_name[16];
 };
 
+struct omap_fbmem_config {
+	u32 fb_sram_start;
+	u32 fb_sram_size;
+	u32 fb_sdram_start;
+	u32 fb_sdram_size;
+};
+
 /* Cover:
  *      high -> closed
  *      low  -> open
@@ -106,6 +121,12 @@
 	int key_code:24; /* Linux key code */
 };
 
+struct omap_uart_config {
+	/* Bit field of UARTs present; bit 0 --> UART1 */
+	unsigned int enabled_uarts;
+};
+
+
 struct omap_flash_part_config {
 	char part_table[0];
 };
@@ -114,11 +135,14 @@
 	char reason_str[12];
 };
 
-struct omap_uart_config {
-	/* Bit field of UARTs present; bit 0 --> UART1 */
-	unsigned int enabled_uarts;
+struct omap_version_config {
+	char component[12];
+	char version[12];
 };
 
+
+#include <asm-arm/arch-omap/board-nokia.h>
+
 struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 46a0402..3c4eb9f 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -19,6 +19,7 @@
 	struct list_head	node;
 	struct module		*owner;
 	const char		*name;
+	int			id;
 	struct clk		*parent;
 	unsigned long		rate;
 	__u32			flags;
@@ -57,6 +58,7 @@
 extern void followparent_recalc(struct clk * clk);
 extern void clk_allow_idle(struct clk *clk);
 extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
 
 /* Clock flags */
 #define RATE_CKCTL		(1 << 0)	/* Main fixed ratio clocks */
@@ -80,10 +82,11 @@
 #define CM_PLL_SEL1		(1 << 18)
 #define CM_PLL_SEL2		(1 << 19)
 #define CM_SYSCLKOUT_SEL1	(1 << 20)
-#define CLOCK_IN_OMAP730	(1 << 21)
-#define CLOCK_IN_OMAP1510	(1 << 22)
-#define CLOCK_IN_OMAP16XX	(1 << 23)
-#define CLOCK_IN_OMAP242X	(1 << 24)
-#define CLOCK_IN_OMAP243X	(1 << 25)
+#define CLOCK_IN_OMAP310	(1 << 21)
+#define CLOCK_IN_OMAP730	(1 << 22)
+#define CLOCK_IN_OMAP1510	(1 << 23)
+#define CLOCK_IN_OMAP16XX	(1 << 24)
+#define CLOCK_IN_OMAP242X	(1 << 25)
+#define CLOCK_IN_OMAP243X	(1 << 26)
 
 #endif
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index d4e73ef..ca12023 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -404,6 +404,7 @@
 extern void omap_setup_lcd_dma(void);
 extern void omap_enable_lcd_dma(void);
 extern void omap_stop_lcd_dma(void);
+extern int  omap_lcd_dma_ext_running(void);
 extern void omap_set_lcd_dma_ext_controller(int external);
 extern void omap_set_lcd_dma_single_transfer(int single);
 extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
diff --git a/include/asm-arm/arch-omap/dmtimer.h b/include/asm-arm/arch-omap/dmtimer.h
index 11772c7..e6522e6 100644
--- a/include/asm-arm/arch-omap/dmtimer.h
+++ b/include/asm-arm/arch-omap/dmtimer.h
@@ -88,5 +88,6 @@
 void omap_dm_timer_reset_counter(struct omap_dm_timer *timer);
 
 int omap_dm_timers_active(void);
+u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
 
 #endif /* __ASM_ARCH_TIMER_H */
diff --git a/include/asm-arm/arch-omap/dsp.h b/include/asm-arm/arch-omap/dsp.h
index 57bf4f3..06dad83 100644
--- a/include/asm-arm/arch-omap/dsp.h
+++ b/include/asm-arm/arch-omap/dsp.h
@@ -181,10 +181,16 @@
 #define OMAP_DSP_MBCMD_PM_ENABLE	0x01
 
 #define OMAP_DSP_MBCMD_KFUNC_FBCTL	0x00
+#define OMAP_DSP_MBCMD_KFUNC_AUDIO_PWR	0x01
 
+#define OMAP_DSP_MBCMD_FBCTL_UPD	0x0000
 #define OMAP_DSP_MBCMD_FBCTL_ENABLE	0x0002
 #define OMAP_DSP_MBCMD_FBCTL_DISABLE	0x0003
 
+#define OMAP_DSP_MBCMD_AUDIO_PWR_UP	0x0000
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN1	0x0001
+#define OMAP_DSP_MBCMD_AUDIO_PWR_DOWN2	0x0002
+
 #define OMAP_DSP_MBCMD_TDEL_SAFE	0x0000
 #define OMAP_DSP_MBCMD_TDEL_KILL	0x0001
 
diff --git a/include/asm-arm/arch-omap/dsp_common.h b/include/asm-arm/arch-omap/dsp_common.h
index 4fcce69..16a459d 100644
--- a/include/asm-arm/arch-omap/dsp_common.h
+++ b/include/asm-arm/arch-omap/dsp_common.h
@@ -27,11 +27,12 @@
 #ifndef ASM_ARCH_DSP_COMMON_H
 #define ASM_ARCH_DSP_COMMON_H
 
-void omap_dsp_pm_suspend(void);
-void omap_dsp_pm_resume(void);
-void omap_dsp_request_mpui(void);
-void omap_dsp_release_mpui(void);
-int omap_dsp_request_mem(void);
-int omap_dsp_release_mem(void);
+extern void omap_dsp_request_mpui(void);
+extern void omap_dsp_release_mpui(void);
+extern int omap_dsp_request_mem(void);
+extern int omap_dsp_release_mem(void);
+
+extern void (*omap_dsp_audio_pwr_up_request)(int stage);
+extern void (*omap_dsp_audio_pwr_down_request)(int stage);
 
 #endif /* ASM_ARCH_DSP_COMMON_H */
diff --git a/include/asm-arm/arch-omap/gpioexpander.h b/include/asm-arm/arch-omap/gpioexpander.h
new file mode 100644
index 0000000..7a43b0a
--- /dev/null
+++ b/include/asm-arm/arch-omap/gpioexpander.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-omap/gpioexpander.h
+ *
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
+#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
+
+/* Function Prototypes for GPIO Expander functions */
+
+int read_gpio_expa(u8 *, int);
+int write_gpio_expa(u8 , int);
+
+#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 5406b87..7909b72 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -306,6 +306,10 @@
 #include "board-h4.h"
 #endif
 
+#ifdef CONFIG_MACH_OMAP_APOLLON
+#include "board-apollon.h"
+#endif
+
 #ifdef CONFIG_MACH_OMAP_OSK
 #include "board-osk.h"
 #endif
@@ -314,10 +318,6 @@
 #include "board-voiceblue.h"
 #endif
 
-#ifdef CONFIG_MACH_NETSTAR
-#include "board-netstar.h"
-#endif
-
 #endif /* !__ASSEMBLER__ */
 
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/irda.h b/include/asm-arm/arch-omap/irda.h
new file mode 100644
index 0000000..805ae35
--- /dev/null
+++ b/include/asm-arm/arch-omap/irda.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-omap/irda.h
+ *
+ *  Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.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.
+ */
+#ifndef ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_SEL		1	/* Selects IrDA */
+#define IR_SIRMODE	2
+#define IR_FIRMODE	4
+#define IR_MIRMODE	8
+
+struct omap_irda_config {
+	int transceiver_cap;
+	int (*transceiver_mode)(struct device *dev, int mode);
+	int (*select_irda)(struct device *dev, int state);
+	/* Very specific to the needs of some platforms (h3,h4)
+	 * having calls which can sleep in irda_set_speed.
+	 */
+	struct work_struct gpio_expa;
+	int rx_channel;
+	int tx_channel;
+	unsigned long dest_start;
+	unsigned long src_start;
+	int tx_trigger;
+	int rx_trigger;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index 4ffce1d..42098d9 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -242,6 +242,11 @@
 #define INT_24XX_GPIO_BANK2	30
 #define INT_24XX_GPIO_BANK3	31
 #define INT_24XX_GPIO_BANK4	32
+#define INT_24XX_MCBSP1_IRQ_TX	59
+#define INT_24XX_MCBSP1_IRQ_RX	60
+#define INT_24XX_MCBSP2_IRQ_TX	62
+#define INT_24XX_MCBSP2_IRQ_RX	63
+#define INT_24XX_UART3_IRQ	74
 
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
diff --git a/include/asm-arm/arch-omap/keypad.h b/include/asm-arm/arch-omap/keypad.h
new file mode 100644
index 0000000..8a023a9
--- /dev/null
+++ b/include/asm-arm/arch-omap/keypad.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-omap/keypad.h
+ *
+ *  Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.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.
+ */
+#ifndef ASMARM_ARCH_KEYPAD_H
+#define ASMARM_ARCH_KEYPAD_H
+
+struct omap_kp_platform_data {
+	int rows;
+	int cols;
+	int *keymap;
+	unsigned int rep:1;
+	/* specific to OMAP242x*/
+	unsigned int *row_gpios;
+	unsigned int *col_gpios;
+};
+
+/* Group (0..3) -- when multiple keys are pressed, only the
+ * keys pressed in the same group are considered as pressed. This is
+ * in order to workaround certain crappy HW designs that produce ghost
+ * keypresses. */
+#define GROUP_0		(0 << 16)
+#define GROUP_1		(1 << 16)
+#define GROUP_2		(2 << 16)
+#define GROUP_3		(3 << 16)
+#define GROUP_MASK	GROUP_3
+
+#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
+
+#endif
+
diff --git a/include/asm-arm/arch-omap/lcd_lph8923.h b/include/asm-arm/arch-omap/lcd_lph8923.h
new file mode 100644
index 0000000..004e67e
--- /dev/null
+++ b/include/asm-arm/arch-omap/lcd_lph8923.h
@@ -0,0 +1,14 @@
+#ifndef __LCD_LPH8923_H
+#define __LCD_LPH8923_H
+
+enum lcd_lph8923_test_num {
+	LCD_LPH8923_TEST_RGB_LINES,
+};
+
+enum lcd_lph8923_test_result {
+	LCD_LPH8923_TEST_SUCCESS,
+	LCD_LPH8923_TEST_INVALID,
+	LCD_LPH8923_TEST_FAILED,
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
index e79d98a..ed0dde4 100644
--- a/include/asm-arm/arch-omap/mcbsp.h
+++ b/include/asm-arm/arch-omap/mcbsp.h
@@ -37,6 +37,11 @@
 #define OMAP1610_MCBSP2_BASE	0xfffb1000
 #define OMAP1610_MCBSP3_BASE	0xe1017000
 
+#define OMAP24XX_MCBSP1_BASE	0x48074000
+#define OMAP24XX_MCBSP2_BASE	0x48076000
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
+
 #define OMAP_MCBSP_REG_DRR2	0x00
 #define OMAP_MCBSP_REG_DRR1	0x02
 #define OMAP_MCBSP_REG_DXR2	0x04
@@ -71,9 +76,62 @@
 
 #define OMAP_MAX_MCBSP_COUNT 3
 
+#define AUDIO_MCBSP_DATAWRITE	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP		OMAP_MCBSP1
+#define AUDIO_DMA_TX		OMAP_DMA_MCBSP1_TX
+#define AUDIO_DMA_RX		OMAP_DMA_MCBSP1_RX
+
+#elif defined(CONFIG_ARCH_OMAP24XX)
+
+#define OMAP_MCBSP_REG_DRR2	0x00
+#define OMAP_MCBSP_REG_DRR1	0x04
+#define OMAP_MCBSP_REG_DXR2	0x08
+#define OMAP_MCBSP_REG_DXR1	0x0C
+#define OMAP_MCBSP_REG_SPCR2	0x10
+#define OMAP_MCBSP_REG_SPCR1	0x14
+#define OMAP_MCBSP_REG_RCR2	0x18
+#define OMAP_MCBSP_REG_RCR1	0x1C
+#define OMAP_MCBSP_REG_XCR2	0x20
+#define OMAP_MCBSP_REG_XCR1	0x24
+#define OMAP_MCBSP_REG_SRGR2	0x28
+#define OMAP_MCBSP_REG_SRGR1	0x2C
+#define OMAP_MCBSP_REG_MCR2	0x30
+#define OMAP_MCBSP_REG_MCR1	0x34
+#define OMAP_MCBSP_REG_RCERA	0x38
+#define OMAP_MCBSP_REG_RCERB	0x3C
+#define OMAP_MCBSP_REG_XCERA	0x40
+#define OMAP_MCBSP_REG_XCERB	0x44
+#define OMAP_MCBSP_REG_PCR0	0x48
+#define OMAP_MCBSP_REG_RCERC	0x4C
+#define OMAP_MCBSP_REG_RCERD	0x50
+#define OMAP_MCBSP_REG_XCERC	0x54
+#define OMAP_MCBSP_REG_XCERD	0x58
+#define OMAP_MCBSP_REG_RCERE	0x5C
+#define OMAP_MCBSP_REG_RCERF	0x60
+#define OMAP_MCBSP_REG_XCERE	0x64
+#define OMAP_MCBSP_REG_XCERF	0x68
+#define OMAP_MCBSP_REG_RCERG	0x6C
+#define OMAP_MCBSP_REG_RCERH	0x70
+#define OMAP_MCBSP_REG_XCERG	0x74
+#define OMAP_MCBSP_REG_XCERH	0x78
+
+#define OMAP_MAX_MCBSP_COUNT 2
+
+#define AUDIO_MCBSP_DATAWRITE	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
+#define AUDIO_MCBSP_DATAREAD	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
+
+#define AUDIO_MCBSP		OMAP_MCBSP2
+#define AUDIO_DMA_TX		OMAP24XX_DMA_MCBSP2_TX
+#define AUDIO_DMA_RX		OMAP24XX_DMA_MCBSP2_RX
+
+#endif
+
 #define OMAP_MCBSP_READ(base, reg)		__raw_readw((base) + OMAP_MCBSP_REG_##reg)
 #define OMAP_MCBSP_WRITE(base, reg, val)	__raw_writew((val), (base) + OMAP_MCBSP_REG_##reg)
 
+
 /************************** McBSP SPCR1 bit definitions ***********************/
 #define RRST			0x0001
 #define RRDY			0x0002
@@ -195,6 +253,10 @@
 	OMAP_MCBSP3,
 } omap_mcbsp_id;
 
+typedef int __bitwise omap_mcbsp_io_type_t;
+#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
+#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
+
 typedef enum {
 	OMAP_MCBSP_WORD_8 = 0,
 	OMAP_MCBSP_WORD_12,
@@ -246,6 +308,9 @@
 
 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
+
 
 /* SPI specific API */
 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
diff --git a/include/asm-arm/arch-omap/mcspi.h b/include/asm-arm/arch-omap/mcspi.h
new file mode 100644
index 0000000..9e7f40a
--- /dev/null
+++ b/include/asm-arm/arch-omap/mcspi.h
@@ -0,0 +1,16 @@
+#ifndef _OMAP2_MCSPI_H
+#define _OMAP2_MCSPI_H
+
+struct omap2_mcspi_platform_config {
+	unsigned long	base;
+	unsigned short	num_cs;
+};
+
+struct omap2_mcspi_device_config {
+	unsigned turbo_mode:1;
+
+	/* Do we want one channel enabled at the same time? */
+	unsigned single_channel:1;
+};
+
+#endif
diff --git a/include/asm-arm/arch-omap/menelaus.h b/include/asm-arm/arch-omap/menelaus.h
index 46be8b8..88cd4c8 100644
--- a/include/asm-arm/arch-omap/menelaus.h
+++ b/include/asm-arm/arch-omap/menelaus.h
@@ -7,7 +7,7 @@
 #ifndef __ASM_ARCH_MENELAUS_H
 #define __ASM_ARCH_MENELAUS_H
 
-extern void menelaus_mmc_register(void (*callback)(u8 card_mask),
+extern void menelaus_mmc_register(void (*callback)(unsigned long data, u8 card_mask),
 				  unsigned long data);
 extern void menelaus_mmc_remove(void);
 extern void menelaus_mmc_opendrain(int enable);
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 13415a9..0dc24d4 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -112,14 +112,13 @@
  *   as mux config
  */
 #define MUX_CFG_730(desc, mux_reg, mode_offset, mode,	\
-		   pull_reg, pull_bit, pull_status,	\
-		   pu_pd_reg, pu_pd_status, debug_status)\
+		   pull_bit, pull_status, debug_status)\
 {							\
 	.name =	 desc,					\
 	.debug = debug_status,				\
 	MUX_REG_730(mux_reg, mode_offset, mode)		\
 	PULL_REG_730(mux_reg, pull_bit, pull_status)	\
-	PU_PD_REG(pu_pd_reg, pu_pd_status)		\
+	PU_PD_REG(NA, 0)		\
 },
 
 #define MUX_CFG_24XX(desc, reg_offset, mode,			\
@@ -172,6 +171,11 @@
 	E4_730_KBC2,
 	F4_730_KBC3,
 	E3_730_KBC4,
+
+	/* USB */
+	AA17_730_USB_DM,
+	W16_730_USB_PU_EN,
+	W17_730_USB_VBUSI,
 };
 
 enum omap1xxx_index {
@@ -403,9 +407,53 @@
 	/* 24xx Menelaus interrupt */
 	W19_24XX_SYS_NIRQ,
 
+	/* 24xx clock */
+	W14_24XX_SYS_CLKOUT,
+
+	/* 242X McBSP */
+	Y15_24XX_MCBSP2_CLKX,
+	R14_24XX_MCBSP2_FSX,
+	W15_24XX_MCBSP2_DR,
+	V15_24XX_MCBSP2_DX,
+
 	/* 24xx GPIO */
+	M21_242X_GPIO11,
+	AA10_242X_GPIO13,
+	AA6_242X_GPIO14,
+	AA4_242X_GPIO15,
+	Y11_242X_GPIO16,
+	AA12_242X_GPIO17,
+	AA8_242X_GPIO58,
 	Y20_24XX_GPIO60,
+	W4__24XX_GPIO74,
 	M15_24XX_GPIO92,
+	V14_24XX_GPIO117,
+
+	P20_24XX_TSC_IRQ,
+
+	/* UART3 */
+	K15_24XX_UART3_TX,
+	K14_24XX_UART3_RX,
+
+	/* Keypad GPIO*/
+	T19_24XX_KBR0,
+	R19_24XX_KBR1,
+	V18_24XX_KBR2,
+	M21_24XX_KBR3,
+	E5__24XX_KBR4,
+	M18_24XX_KBR5,
+	R20_24XX_KBC0,
+	M14_24XX_KBC1,
+	H19_24XX_KBC2,
+	V17_24XX_KBC3,
+	P21_24XX_KBC4,
+	L14_24XX_KBC5,
+	N19_24XX_KBC6,
+
+	/* 24xx Menelaus Keypad GPIO */
+	B3__24XX_KBR5,
+	AA4_24XX_KBC2,
+	B13_24XX_KBC6,
 };
 
 #ifdef	CONFIG_OMAP_MUX
diff --git a/include/asm-arm/arch-omap/omap-alsa.h b/include/asm-arm/arch-omap/omap-alsa.h
new file mode 100644
index 0000000..df46954
--- /dev/null
+++ b/include/asm-arm/arch-omap/omap-alsa.h
@@ -0,0 +1,124 @@
+/*
+ * linux/include/asm-arm/arch-omap/omap-alsa.h
+ *
+ * Alsa Driver for AIC23 and TSC2101 codecs on OMAP platform boards.
+ *
+ * Copyright (C) 2006 Mika Laitio <lamikr@cc.jyu.fi>
+ *
+ * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus Brazil
+ * Written by Daniel Petrini, David Cohen, Anderson Briglia
+ *            {daniel.petrini, david.cohen, anderson.briglia}@indt.org.br
+ *
+ * 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.
+ *
+ *  History
+ *  -------
+ *
+ *  2005/07/25 INdT-10LE Kernel Team - 	Alsa driver for omap osk,
+ *  					original version based in sa1100 driver
+ *  					and omap oss driver.
+ */
+
+#ifndef __OMAP_ALSA_H
+#define __OMAP_ALSA_H
+
+#include <sound/driver.h>
+#include <asm/arch/dma.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <asm/arch/mcbsp.h>
+#include <linux/platform_device.h>
+
+#define DMA_BUF_SIZE	(1024 * 8)
+
+/*
+ * Buffer management for alsa and dma
+ */
+struct audio_stream {
+	char *id;		/* identification string */
+	int stream_id;		/* numeric identification */
+	int dma_dev;		/* dma number of that device */
+	int *lch;		/* Chain of channels this stream is linked to */
+	char started;		/* to store if the chain was started or not */
+	int dma_q_head;		/* DMA Channel Q Head */
+	int dma_q_tail;		/* DMA Channel Q Tail */
+	char dma_q_count;	/* DMA Channel Q Count */
+	int active:1;		/* we are using this stream for transfer now */
+	int period;		/* current transfer period */
+	int periods;		/* current count of periods registerd in the DMA engine */
+	spinlock_t dma_lock;	/* for locking in DMA operations */
+	snd_pcm_substream_t *stream;	/* the pcm stream */
+	unsigned linked:1;	/* dma channels linked */
+	int offset;		/* store start position of the last period in the alsa buffer */
+	int (*hw_start)(void);  /* interface to start HW interface, e.g. McBSP */
+	int (*hw_stop)(void);   /* interface to stop HW interface, e.g. McBSP */
+};
+
+/*
+ * Alsa card structure for aic23
+ */
+struct snd_card_omap_codec {
+	snd_card_t *card;
+	snd_pcm_t *pcm;
+	long samplerate;
+	struct audio_stream s[2];	/* playback & capture */
+};
+
+/* Codec specific information and function pointers.
+ * Codec (omap-alsa-aic23.c and omap-alsa-tsc2101.c)
+ * are responsible for defining the function pointers.
+ */
+struct omap_alsa_codec_config {
+	char 	*name;
+	struct	omap_mcbsp_reg_cfg *mcbsp_regs_alsa;
+	snd_pcm_hw_constraint_list_t *hw_constraints_rates;
+	snd_pcm_hardware_t *snd_omap_alsa_playback;
+	snd_pcm_hardware_t *snd_omap_alsa_capture;
+	void	(*codec_configure_dev)(void);
+	void	(*codec_set_samplerate)(long);
+	void	(*codec_clock_setup)(void);
+	int	(*codec_clock_on)(void);
+	int 	(*codec_clock_off)(void);
+	int	(*get_default_samplerate)(void);
+};
+
+/*********** Mixer function prototypes *************************/
+int snd_omap_mixer(struct snd_card_omap_codec *);
+void snd_omap_init_mixer(void);
+
+#ifdef CONFIG_PM
+void snd_omap_suspend_mixer(void);
+void snd_omap_resume_mixer(void);
+#endif
+
+int snd_omap_alsa_post_probe(struct platform_device *pdev, struct omap_alsa_codec_config *config);
+int snd_omap_alsa_remove(struct platform_device *pdev);
+#ifdef CONFIG_PM
+int snd_omap_alsa_suspend(struct platform_device *pdev, pm_message_t state);
+int snd_omap_alsa_resume(struct platform_device *pdev);
+#else
+#define snd_omap_alsa_suspend	NULL
+#define snd_omap_alsa_resume	NULL
+#endif
+
+void callback_omap_alsa_sound_dma(void *);
+
+#endif
diff --git a/include/asm-arm/arch-omap/omapfb.h b/include/asm-arm/arch-omap/omapfb.h
index 4ba2622..fccdb3d 100644
--- a/include/asm-arm/arch-omap/omapfb.h
+++ b/include/asm-arm/arch-omap/omapfb.h
@@ -34,9 +34,10 @@
 #define OMAPFB_MIRROR		OMAP_IOW(31, int)
 #define OMAPFB_SYNC_GFX		OMAP_IO(37)
 #define OMAPFB_VSYNC		OMAP_IO(38)
-#define OMAPFB_SET_UPDATE_MODE	OMAP_IOW(40, enum omapfb_update_mode)
+#define OMAPFB_SET_UPDATE_MODE	OMAP_IOW(40, int)
+#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(41, struct omapfb_update_window_old)
 #define OMAPFB_GET_CAPS		OMAP_IOR(42, unsigned long)
-#define OMAPFB_GET_UPDATE_MODE	OMAP_IOW(43, enum omapfb_update_mode)
+#define OMAPFB_GET_UPDATE_MODE	OMAP_IOW(43, int)
 #define OMAPFB_LCD_TEST		OMAP_IOW(45, int)
 #define OMAPFB_CTRL_TEST	OMAP_IOW(46, int)
 #define OMAPFB_UPDATE_WINDOW	OMAP_IOW(47, struct omapfb_update_window)
@@ -66,9 +67,14 @@
 };
 
 struct omapfb_update_window {
-	u32 x, y;
-	u32 width, height;
-	u32 format;
+	__u32 x, y;
+	__u32 width, height;
+	__u32 format;
+};
+
+struct omapfb_update_window_old {
+	__u32 x, y;
+	__u32 width, height;
 };
 
 enum omapfb_plane {
@@ -83,17 +89,17 @@
 };
 
 struct omapfb_setup_plane {
-	u8  plane;
-	u8  channel_out;
-	u32 offset;
-	u32 pos_x, pos_y;
-	u32 width, height;
-	u32 color_mode;
+	__u8  plane;
+	__u8  channel_out;
+	__u32 offset;
+	__u32 pos_x, pos_y;
+	__u32 width, height;
+	__u32 color_mode;
 };
 
 struct omapfb_enable_plane {
-	u8  plane;
-	u8  enable;
+	__u8  plane;
+	__u8  enable;
 };
 
 enum omapfb_color_key_type {
@@ -103,10 +109,10 @@
 };
 
 struct omapfb_color_key {
-	u8  channel_out;
-	u32 background;
-	u32 trans_key;
-	u8  key_type;
+	__u8  channel_out;
+	__u32 background;
+	__u32 trans_key;
+	__u8  key_type;
 };
 
 enum omapfb_update_mode {
@@ -120,6 +126,9 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/fb.h>
+#include <linux/mutex.h>
+
+#include <asm/arch/board.h>
 
 #define OMAP_LCDC_INV_VSYNC             0x0001
 #define OMAP_LCDC_INV_HSYNC             0x0002
@@ -184,19 +193,38 @@
 	int re_cycle_time;
 	int cs_pulse_width;
 	int access_time;
+
+	int clk_div;
+
+	u32 tim[5];		/* set by extif->convert_timings */
+
+	int converted;
 };
 
 struct lcd_ctrl_extif {
 	int  (*init)		(void);
 	void (*cleanup)		(void);
+	void (*get_clk_info)	(u32 *clk_period, u32 *max_clk_div);
+	int  (*convert_timings)	(struct extif_timings *timings);
 	void (*set_timings)	(const struct extif_timings *timings);
-	void (*write_command)	(u32 cmd);
-	u32  (*read_data)	(void);
-	void (*write_data)	(u32 data);
+	void (*set_bits_per_cycle)(int bpc);
+	void (*write_command)	(const void *buf, unsigned int len);
+	void (*read_data)	(void *buf, unsigned int len);
+	void (*write_data)	(const void *buf, unsigned int len);
 	void (*transfer_area)	(int width, int height,
 				 void (callback)(void * data), void *data);
+	unsigned long		max_transmit_size;
 };
 
+struct omapfb_notifier_block {
+	struct notifier_block	nb;
+	void			*data;
+};
+
+typedef int (*omapfb_notifier_callback_t)(struct omapfb_notifier_block *,
+					   unsigned long event,
+					   struct omapfb_device *fbdev);
+
 struct lcd_ctrl {
 	const char	*name;
 	void		*data;
@@ -204,9 +232,11 @@
 	int		(*init)		  (struct omapfb_device *fbdev,
 					   int ext_mode, int req_vram_size);
 	void		(*cleanup)	  (void);
+	void		(*bind_client)	  (struct omapfb_notifier_block *nb);
 	void		(*get_vram_layout)(unsigned long *size,
 					   void **virt_base,
 					   dma_addr_t *phys_base);
+	int		(*mmap)		  (struct vm_area_struct *vma);
 	unsigned long	(*get_caps)	  (void);
 	int		(*set_update_mode)(enum omapfb_update_mode mode);
 	enum omapfb_update_mode (*get_update_mode)(void);
@@ -240,7 +270,7 @@
 	int			state;
 	int                     ext_lcdc;               /* Using external
                                                            LCD controller */
-	struct semaphore	rqueue_sema;
+	struct mutex		rqueue_mutex;
 
 	void			*vram_virt_base;
 	dma_addr_t		vram_phys_base;
@@ -261,12 +291,13 @@
 	struct device		*dev;
 };
 
-extern struct lcd_panel h3_panel;
-extern struct lcd_panel h2_panel;
-extern struct lcd_panel p2_panel;
-extern struct lcd_panel osk_panel;
-extern struct lcd_panel innovator1610_panel;
-extern struct lcd_panel innovator1510_panel;
+struct omapfb_platform_data {
+	struct omap_lcd_config   lcd;
+	struct omap_fbmem_config fbmem;
+};
+
+#define OMAPFB_EVENT_READY	1
+#define OMAPFB_EVENT_DISABLED	2
 
 #ifdef CONFIG_ARCH_OMAP1
 extern struct lcd_ctrl omap1_lcd_ctrl;
@@ -274,7 +305,20 @@
 extern struct lcd_ctrl omap2_disp_ctrl;
 #endif
 
+extern void omapfb_register_panel(struct lcd_panel *panel);
 extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
+extern void omapfb_notify_clients(struct omapfb_device *fbdev,
+				  unsigned long event);
+extern int  omapfb_register_client(struct omapfb_notifier_block *nb,
+				    omapfb_notifier_callback_t callback,
+				    void *callback_data);
+extern int  omapfb_unregister_client(struct omapfb_notifier_block *nb);
+extern int  omapfb_update_window_async(struct omapfb_update_window *win,
+					void (*callback)(void *),
+					void *callback_data);
+
+/* in arch/arm/plat-omap/devices.c */
+extern void omapfb_reserve_mem(void);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h
new file mode 100644
index 0000000..face9ad
--- /dev/null
+++ b/include/asm-arm/arch-omap/param.h
@@ -0,0 +1,8 @@
+/*
+ *  linux/include/asm-arm/arch-omap/param.h
+ *
+ */
+
+#ifdef CONFIG_OMAP_32K_TIMER_HZ
+#define HZ	CONFIG_OMAP_32K_TIMER_HZ
+#endif
diff --git a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h
index 7c79042..05b003f 100644
--- a/include/asm-arm/arch-omap/pm.h
+++ b/include/asm-arm/arch-omap/pm.h
@@ -49,7 +49,7 @@
 
 /*
  * ----------------------------------------------------------------------------
- * Powermanagement bitmasks
+ * Power management bitmasks
  * ----------------------------------------------------------------------------
  */
 #define IDLE_WAIT_CYCLES		0x00000fff
@@ -112,32 +112,59 @@
 #endif
 
 #ifndef __ASSEMBLER__
+
+#include <linux/clk.h>
+
+extern void prevent_idle_sleep(void);
+extern void allow_idle_sleep(void);
+
+/**
+ * clk_deny_idle - Prevents the clock from being idled during MPU idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
+/**
+ * clk_allow_idle - Counters previous clk_deny_idle
+ * @clk: clock signal handle
+ */
+void clk_deny_idle(struct clk *clk);
+
 extern void omap_pm_idle(void);
 extern void omap_pm_suspend(void);
 extern void omap730_cpu_suspend(unsigned short, unsigned short);
 extern void omap1510_cpu_suspend(unsigned short, unsigned short);
 extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision);
 extern void omap730_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
+extern void omap24xx_idle_loop_suspend(void);
+
+extern unsigned int omap730_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap24xx_cpu_suspend_sz;
+extern unsigned int omap730_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+extern unsigned int omap24xx_idle_loop_suspend_sz;
 
 #ifdef CONFIG_OMAP_SERIAL_WAKE
 extern void omap_serial_wake_trigger(int enable);
 #else
+#define omap_serial_wakeup_init()	{}
 #define omap_serial_wake_trigger(x)	{}
 #endif	/* CONFIG_OMAP_SERIAL_WAKE */
 
-extern unsigned int omap730_cpu_suspend_sz;
-extern unsigned int omap730_idle_loop_suspend_sz;
-extern unsigned int omap1510_cpu_suspend_sz;
-extern unsigned int omap1510_idle_loop_suspend_sz;
-extern unsigned int omap1610_cpu_suspend_sz;
-extern unsigned int omap1610_idle_loop_suspend_sz;
-
 #define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
 #define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
 #define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
 
+#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
+#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
+#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
+
 #define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
 #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
 #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
@@ -154,6 +181,10 @@
 #define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
 #define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
 
+#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x
+#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x]
+
 /*
  * List of global OMAP registers to preserve.
  * More ones like CP and general purpose register values are preserved
@@ -176,6 +207,15 @@
 	ARM_SLEEP_SAVE_SIZE
 };
 
+enum dsp_save_state {
+	DSP_SLEEP_SAVE_START = 0,
+	/*
+	 * DSP registers 16 bits
+	 */
+	DSP_SLEEP_SAVE_DSP_IDLECT2,
+	DSP_SLEEP_SAVE_SIZE
+};
+
 enum ulpd_save_state {
 	ULPD_SLEEP_SAVE_START = 0,
 	/*
@@ -254,5 +294,30 @@
 #endif
 };
 
+enum omap24xx_save_state {
+	OMAP24XX_SLEEP_SAVE_START = 0,
+	OMAP24XX_SLEEP_SAVE_INTC_MIR0,
+	OMAP24XX_SLEEP_SAVE_INTC_MIR1,
+	OMAP24XX_SLEEP_SAVE_INTC_MIR2,
+	OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE,
+	OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE,
+	OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE,
+	OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE,
+	OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE,
+	OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1,
+	OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1,
+	OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1,
+	OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1,
+	OMAP24XX_SLEEP_SAVE_GPIO3_OE,
+	OMAP24XX_SLEEP_SAVE_GPIO4_OE,
+	OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT,
+	OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT,
+	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2,
+	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX,
+	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX,
+	OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0,
+	OMAP24XX_SLEEP_SAVE_SIZE
+};
+
 #endif /* ASSEMBLER */
 #endif /* __ASM_ARCH_OMAP_PM_H */
diff --git a/include/asm-arm/arch-omap/prcm.h b/include/asm-arm/arch-omap/prcm.h
index 7b48a5c..7bcaf94 100644
--- a/include/asm-arm/arch-omap/prcm.h
+++ b/include/asm-arm/arch-omap/prcm.h
@@ -1,5 +1,7 @@
 /*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/include/asm-arm/arch-omap/prcm.h
+ *
+ * Access definations for use in OMAP24XX clock and power management
  *
  * Copyright (C) 2005 Texas Instruments, Inc.
  *
@@ -21,405 +23,7 @@
 #ifndef __ASM_ARM_ARCH_DPM_PRCM_H
 #define __ASM_ARM_ARCH_DPM_PRCM_H
 
-/* SET_PERFORMANCE_LEVEL PARAMETERS */
-#define PRCM_HALF_SPEED 1
-#define PRCM_FULL_SPEED 2
-
-#ifndef __ASSEMBLER__
-
-#define PRCM_REG32(offset)	__REG32(OMAP24XX_PRCM_BASE + (offset))
-
-#define PRCM_REVISION		PRCM_REG32(0x000)
-#define PRCM_SYSCONFIG		PRCM_REG32(0x010)
-#define PRCM_IRQSTATUS_MPU	PRCM_REG32(0x018)
-#define PRCM_IRQENABLE_MPU	PRCM_REG32(0x01C)
-#define PRCM_VOLTCTRL		PRCM_REG32(0x050)
-#define PRCM_VOLTST		PRCM_REG32(0x054)
-#define PRCM_CLKSRC_CTRL	PRCM_REG32(0x060)
-#define PRCM_CLKOUT_CTRL	PRCM_REG32(0x070)
-#define PRCM_CLKEMUL_CTRL	PRCM_REG32(0x078)
-#define PRCM_CLKCFG_CTRL	PRCM_REG32(0x080)
-#define PRCM_CLKCFG_STATUS	PRCM_REG32(0x084)
-#define PRCM_VOLTSETUP		PRCM_REG32(0x090)
-#define PRCM_CLKSSETUP		PRCM_REG32(0x094)
-#define PRCM_POLCTRL		PRCM_REG32(0x098)
-
-/* GENERAL PURPOSE */
-#define GENERAL_PURPOSE1	PRCM_REG32(0x0B0)
-#define GENERAL_PURPOSE2	PRCM_REG32(0x0B4)
-#define GENERAL_PURPOSE3	PRCM_REG32(0x0B8)
-#define GENERAL_PURPOSE4	PRCM_REG32(0x0BC)
-#define GENERAL_PURPOSE5	PRCM_REG32(0x0C0)
-#define GENERAL_PURPOSE6	PRCM_REG32(0x0C4)
-#define GENERAL_PURPOSE7	PRCM_REG32(0x0C8)
-#define GENERAL_PURPOSE8	PRCM_REG32(0x0CC)
-#define GENERAL_PURPOSE9	PRCM_REG32(0x0D0)
-#define GENERAL_PURPOSE10	PRCM_REG32(0x0D4)
-#define GENERAL_PURPOSE11	PRCM_REG32(0x0D8)
-#define GENERAL_PURPOSE12	PRCM_REG32(0x0DC)
-#define GENERAL_PURPOSE13	PRCM_REG32(0x0E0)
-#define GENERAL_PURPOSE14	PRCM_REG32(0x0E4)
-#define GENERAL_PURPOSE15	PRCM_REG32(0x0E8)
-#define GENERAL_PURPOSE16	PRCM_REG32(0x0EC)
-#define GENERAL_PURPOSE17	PRCM_REG32(0x0F0)
-#define GENERAL_PURPOSE18	PRCM_REG32(0x0F4)
-#define GENERAL_PURPOSE19	PRCM_REG32(0x0F8)
-#define GENERAL_PURPOSE20	PRCM_REG32(0x0FC)
-
-/* MPU */
-#define CM_CLKSEL_MPU		PRCM_REG32(0x140)
-#define CM_CLKSTCTRL_MPU	PRCM_REG32(0x148)
-#define RM_RSTST_MPU		PRCM_REG32(0x158)
-#define PM_WKDEP_MPU		PRCM_REG32(0x1C8)
-#define PM_EVGENCTRL_MPU	PRCM_REG32(0x1D4)
-#define PM_EVEGENONTIM_MPU	PRCM_REG32(0x1D8)
-#define PM_EVEGENOFFTIM_MPU	PRCM_REG32(0x1DC)
-#define PM_PWSTCTRL_MPU		PRCM_REG32(0x1E0)
-#define PM_PWSTST_MPU		PRCM_REG32(0x1E4)
-
-/* CORE */
-#define CM_FCLKEN1_CORE		PRCM_REG32(0x200)
-#define CM_FCLKEN2_CORE		PRCM_REG32(0x204)
-#define CM_FCLKEN3_CORE		PRCM_REG32(0x208)
-#define CM_ICLKEN1_CORE		PRCM_REG32(0x210)
-#define CM_ICLKEN2_CORE		PRCM_REG32(0x214)
-#define CM_ICLKEN3_CORE		PRCM_REG32(0x218)
-#define CM_ICLKEN4_CORE		PRCM_REG32(0x21C)
-#define CM_IDLEST1_CORE		PRCM_REG32(0x220)
-#define CM_IDLEST2_CORE		PRCM_REG32(0x224)
-#define CM_IDLEST3_CORE		PRCM_REG32(0x228)
-#define CM_IDLEST4_CORE		PRCM_REG32(0x22C)
-#define CM_AUTOIDLE1_CORE	PRCM_REG32(0x230)
-#define CM_AUTOIDLE2_CORE	PRCM_REG32(0x234)
-#define CM_AUTOIDLE3_CORE	PRCM_REG32(0x238)
-#define CM_AUTOIDLE4_CORE	PRCM_REG32(0x23C)
-#define CM_CLKSEL1_CORE		PRCM_REG32(0x240)
-#define CM_CLKSEL2_CORE		PRCM_REG32(0x244)
-#define CM_CLKSTCTRL_CORE	PRCM_REG32(0x248)
-#define PM_WKEN1_CORE		PRCM_REG32(0x2A0)
-#define PM_WKEN2_CORE		PRCM_REG32(0x2A4)
-#define PM_WKST1_CORE		PRCM_REG32(0x2B0)
-#define PM_WKST2_CORE		PRCM_REG32(0x2B4)
-#define PM_WKDEP_CORE		PRCM_REG32(0x2C8)
-#define PM_PWSTCTRL_CORE	PRCM_REG32(0x2E0)
-#define PM_PWSTST_CORE		PRCM_REG32(0x2E4)
-
-/* GFX */
-#define CM_FCLKEN_GFX		PRCM_REG32(0x300)
-#define CM_ICLKEN_GFX		PRCM_REG32(0x310)
-#define CM_IDLEST_GFX		PRCM_REG32(0x320)
-#define CM_CLKSEL_GFX		PRCM_REG32(0x340)
-#define CM_CLKSTCTRL_GFX	PRCM_REG32(0x348)
-#define RM_RSTCTRL_GFX		PRCM_REG32(0x350)
-#define RM_RSTST_GFX		PRCM_REG32(0x358)
-#define PM_WKDEP_GFX		PRCM_REG32(0x3C8)
-#define PM_PWSTCTRL_GFX		PRCM_REG32(0x3E0)
-#define PM_PWSTST_GFX		PRCM_REG32(0x3E4)
-
-/* WAKE-UP */
-#define CM_FCLKEN_WKUP		PRCM_REG32(0x400)
-#define CM_ICLKEN_WKUP		PRCM_REG32(0x410)
-#define CM_IDLEST_WKUP		PRCM_REG32(0x420)
-#define CM_AUTOIDLE_WKUP	PRCM_REG32(0x430)
-#define CM_CLKSEL_WKUP		PRCM_REG32(0x440)
-#define RM_RSTCTRL_WKUP		PRCM_REG32(0x450)
-#define RM_RSTTIME_WKUP		PRCM_REG32(0x454)
-#define RM_RSTST_WKUP		PRCM_REG32(0x458)
-#define PM_WKEN_WKUP		PRCM_REG32(0x4A0)
-#define PM_WKST_WKUP		PRCM_REG32(0x4B0)
-
-/* CLOCKS */
-#define CM_CLKEN_PLL		PRCM_REG32(0x500)
-#define CM_IDLEST_CKGEN		PRCM_REG32(0x520)
-#define CM_AUTOIDLE_PLL		PRCM_REG32(0x530)
-#define CM_CLKSEL1_PLL		PRCM_REG32(0x540)
-#define CM_CLKSEL2_PLL		PRCM_REG32(0x544)
-
-/* DSP */
-#define CM_FCLKEN_DSP		PRCM_REG32(0x800)
-#define CM_ICLKEN_DSP		PRCM_REG32(0x810)
-#define CM_IDLEST_DSP		PRCM_REG32(0x820)
-#define CM_AUTOIDLE_DSP		PRCM_REG32(0x830)
-#define CM_CLKSEL_DSP		PRCM_REG32(0x840)
-#define CM_CLKSTCTRL_DSP	PRCM_REG32(0x848)
-#define RM_RSTCTRL_DSP		PRCM_REG32(0x850)
-#define RM_RSTST_DSP		PRCM_REG32(0x858)
-#define PM_WKEN_DSP		PRCM_REG32(0x8A0)
-#define PM_WKDEP_DSP		PRCM_REG32(0x8C8)
-#define PM_PWSTCTRL_DSP		PRCM_REG32(0x8E0)
-#define PM_PWSTST_DSP		PRCM_REG32(0x8E4)
-#define PRCM_IRQSTATUS_DSP	PRCM_REG32(0x8F0)
-#define PRCM_IRQENABLE_DSP	PRCM_REG32(0x8F4)
-
-/* IVA */
-#define PRCM_IRQSTATUS_IVA	PRCM_REG32(0x8F8)
-#define PRCM_IRQENABLE_IVA	PRCM_REG32(0x8FC)
-
-/* Modem on 2430 */
-#define CM_FCLKEN_MDM		PRCM_REG32(0xC00)
-#define CM_ICLKEN_MDM		PRCM_REG32(0xC10)
-#define CM_IDLEST_MDM		PRCM_REG32(0xC20)
-#define CM_CLKSEL_MDM		PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE		(OMAP24XX_L4_IO_BASE+0x50000)
-#define DISP_REG32(offset)	__REG32(DISP_BASE + (offset))
-
-#define OMAP24XX_GPMC_BASE	(L3_24XX_BASE + 0xa000)
-#define GPMC_BASE		(OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset)	__REG32(GPMC_BASE + (offset))
-
-#define GPT1_BASE		(OMAP24XX_GPT1)
-#define GPT1_REG32(offset)	__REG32(GPT1_BASE + (offset))
-
-/* Misc sysconfig */
-#define DISPC_SYSCONFIG		DISP_REG32(0x410)
-#define SPI_BASE		(OMAP24XX_L4_IO_BASE+0x98000)
-#define MCSPI1_SYSCONFIG	__REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG	__REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG	0x5A000010
-#define CAMERA_MMU_SYSCONFIG	__REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG	0x5D000010
-//#define DSP_DMA_SYSCONFIG	0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG	__REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG	__REG32(DISP_BASE+0x602C)
-#define GPMC_SYSCONFIG		GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG	__REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG		__REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG		0x5C060010
-#define SDRC_SYSCONFIG		__REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG		__REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG		__REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG	0x67FFFE10
-
-/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2		(OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3		(OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4		(OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5		(OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6		(OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7		(OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8		(OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9		(OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10		(OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11		(OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12		(OMAP24XX_L4_IO_BASE+0x8A000)
-
-#define GPTIMER1_SYSCONFIG	GPT1_REG32(0x010)
-#define GPTIMER2_SYSCONFIG	__REG32(OMAP24XX_GPT2 + 0x10)
-#define GPTIMER3_SYSCONFIG	__REG32(OMAP24XX_GPT3 + 0x10)
-#define GPTIMER4_SYSCONFIG	__REG32(OMAP24XX_GPT4 + 0x10)
-#define GPTIMER5_SYSCONFIG	__REG32(OMAP24XX_GPT5 + 0x10)
-#define GPTIMER6_SYSCONFIG	__REG32(OMAP24XX_GPT6 + 0x10)
-#define GPTIMER7_SYSCONFIG	__REG32(OMAP24XX_GPT7 + 0x10)
-#define GPTIMER8_SYSCONFIG	__REG32(OMAP24XX_GPT8 + 0x10)
-#define GPTIMER9_SYSCONFIG	__REG32(OMAP24XX_GPT9 + 0x10)
-#define GPTIMER10_SYSCONFIG	__REG32(OMAP24XX_GPT10 + 0x10)
-#define GPTIMER11_SYSCONFIG	__REG32(OMAP24XX_GPT11 + 0x10)
-#define GPTIMER12_SYSCONFIG	__REG32(OMAP24XX_GPT12 + 0x10)
-
-#define GPIOX_BASE(X)		(OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
-
-#define GPIO1_SYSCONFIG		__REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG		__REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG		__REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG		__REG32((GPIOX_BASE(4)+0x10))
-
-/* GP TIMER 1 */
-#define GPTIMER1_TISTAT		GPT1_REG32(0x014)
-#define GPTIMER1_TISR		GPT1_REG32(0x018)
-#define GPTIMER1_TIER		GPT1_REG32(0x01C)
-#define GPTIMER1_TWER		GPT1_REG32(0x020)
-#define GPTIMER1_TCLR		GPT1_REG32(0x024)
-#define GPTIMER1_TCRR		GPT1_REG32(0x028)
-#define GPTIMER1_TLDR		GPT1_REG32(0x02C)
-#define GPTIMER1_TTGR		GPT1_REG32(0x030)
-#define GPTIMER1_TWPS		GPT1_REG32(0x034)
-#define GPTIMER1_TMAR		GPT1_REG32(0x038)
-#define GPTIMER1_TCAR1		GPT1_REG32(0x03C)
-#define GPTIMER1_TSICR		GPT1_REG32(0x040)
-#define GPTIMER1_TCAR2		GPT1_REG32(0x044)
-
-/* rkw -- base fix up please... */
-#define GPTIMER3_TISR		__REG32(OMAP24XX_L4_IO_BASE+0x78018)
-
-/* SDRC */
-#define SDRC_DLLA_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL		__REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS	__REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER		__REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0		__REG32(OMAP24XX_SDRC_BASE+0x084)
-
-/* GPIO 1 */
-#define GPIO1_BASE		GPIOX_BASE(1)
-#define GPIO1_REG32(offset)	__REG32(GPIO1_BASE + (offset))
-#define GPIO1_IRQENABLE1	GPIO1_REG32(0x01C)
-#define GPIO1_IRQSTATUS1	GPIO1_REG32(0x018)
-#define GPIO1_IRQENABLE2	GPIO1_REG32(0x02C)
-#define GPIO1_IRQSTATUS2	GPIO1_REG32(0x028)
-#define GPIO1_WAKEUPENABLE	GPIO1_REG32(0x020)
-#define GPIO1_RISINGDETECT	GPIO1_REG32(0x048)
-#define GPIO1_DATAIN		GPIO1_REG32(0x038)
-#define GPIO1_OE		GPIO1_REG32(0x034)
-#define GPIO1_DATAOUT		GPIO1_REG32(0x03C)
-
-/* GPIO2 */
-#define GPIO2_BASE		GPIOX_BASE(2)
-#define GPIO2_REG32(offset)	__REG32(GPIO2_BASE + (offset))
-#define GPIO2_IRQENABLE1	GPIO2_REG32(0x01C)
-#define GPIO2_IRQSTATUS1	GPIO2_REG32(0x018)
-#define GPIO2_IRQENABLE2	GPIO2_REG32(0x02C)
-#define GPIO2_IRQSTATUS2	GPIO2_REG32(0x028)
-#define GPIO2_WAKEUPENABLE	GPIO2_REG32(0x020)
-#define GPIO2_RISINGDETECT	GPIO2_REG32(0x048)
-#define GPIO2_DATAIN		GPIO2_REG32(0x038)
-#define GPIO2_OE		GPIO2_REG32(0x034)
-#define GPIO2_DATAOUT		GPIO2_REG32(0x03C)
-
-/* GPIO 3 */
-#define GPIO3_BASE		GPIOX_BASE(3)
-#define GPIO3_REG32(offset)	__REG32(GPIO3_BASE + (offset))
-#define GPIO3_IRQENABLE1	GPIO3_REG32(0x01C)
-#define GPIO3_IRQSTATUS1	GPIO3_REG32(0x018)
-#define GPIO3_IRQENABLE2	GPIO3_REG32(0x02C)
-#define GPIO3_IRQSTATUS2	GPIO3_REG32(0x028)
-#define GPIO3_WAKEUPENABLE	GPIO3_REG32(0x020)
-#define GPIO3_RISINGDETECT	GPIO3_REG32(0x048)
-#define GPIO3_FALLINGDETECT	GPIO3_REG32(0x04C)
-#define GPIO3_DATAIN		GPIO3_REG32(0x038)
-#define GPIO3_OE		GPIO3_REG32(0x034)
-#define GPIO3_DATAOUT		GPIO3_REG32(0x03C)
-#define GPIO3_DEBOUNCENABLE	GPIO3_REG32(0x050)
-#define GPIO3_DEBOUNCINGTIME	GPIO3_REG32(0x054)
-
-/* GPIO 4 */
-#define GPIO4_BASE		GPIOX_BASE(4)
-#define GPIO4_REG32(offset)	__REG32(GPIO4_BASE + (offset))
-#define GPIO4_IRQENABLE1	GPIO4_REG32(0x01C)
-#define GPIO4_IRQSTATUS1	GPIO4_REG32(0x018)
-#define GPIO4_IRQENABLE2	GPIO4_REG32(0x02C)
-#define GPIO4_IRQSTATUS2	GPIO4_REG32(0x028)
-#define GPIO4_WAKEUPENABLE	GPIO4_REG32(0x020)
-#define GPIO4_RISINGDETECT	GPIO4_REG32(0x048)
-#define GPIO4_FALLINGDETECT	GPIO4_REG32(0x04C)
-#define GPIO4_DATAIN		GPIO4_REG32(0x038)
-#define GPIO4_OE		GPIO4_REG32(0x034)
-#define GPIO4_DATAOUT		GPIO4_REG32(0x03C)
-#define GPIO4_DEBOUNCENABLE	GPIO4_REG32(0x050)
-#define GPIO4_DEBOUNCINGTIME	GPIO4_REG32(0x054)
-
-
-/* IO CONFIG */
-#define CONTROL_BASE		(OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset)	__REG32(CONTROL_BASE + (offset))
-
-#define CONTROL_PADCONF_SPI1_NCS2	CONTROL_REG32(0x104)
-#define CONTROL_PADCONF_SYS_XTALOUT	CONTROL_REG32(0x134)
-#define CONTROL_PADCONF_UART1_RX	CONTROL_REG32(0x0C8)
-#define CONTROL_PADCONF_MCBSP1_DX	CONTROL_REG32(0x10C)
-#define CONTROL_PADCONF_GPMC_NCS4	CONTROL_REG32(0x090)
-#define CONTROL_PADCONF_DSS_D5		CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9		CONTROL_REG32(0x0BC)
-#define CONTROL_PADCONF_DSS_D13		CONTROL_REG32(0x0C0)
-#define CONTROL_PADCONF_DSS_VSYNC	CONTROL_REG32(0x0CC)
-
-/* CONTROL */
-#define CONTROL_DEVCONF		CONTROL_REG32(0x274)
-
-/* INTERRUPT CONTROLLER */
-#define INTC_BASE		(OMAP24XX_L4_IO_BASE+0xfe000)
-#define INTC_REG32(offset)	__REG32(INTC_BASE + (offset))
-
-#define INTC1_U_BASE		INTC_REG32(0x000)
-#define INTC_MIR0		INTC_REG32(0x084)
-#define INTC_MIR_SET0		INTC_REG32(0x08C)
-#define INTC_MIR_CLEAR0		INTC_REG32(0x088)
-#define INTC_ISR_CLEAR0		INTC_REG32(0x094)
-#define INTC_MIR1		INTC_REG32(0x0A4)
-#define INTC_MIR_SET1		INTC_REG32(0x0AC)
-#define INTC_MIR_CLEAR1		INTC_REG32(0x0A8)
-#define INTC_ISR_CLEAR1		INTC_REG32(0x0B4)
-#define INTC_MIR2		INTC_REG32(0x0C4)
-#define INTC_MIR_SET2		INTC_REG32(0x0CC)
-#define INTC_MIR_CLEAR2		INTC_REG32(0x0C8)
-#define INTC_ISR_CLEAR2		INTC_REG32(0x0D4)
-#define INTC_SIR_IRQ		INTC_REG32(0x040)
-#define INTC_CONTROL		INTC_REG32(0x048)
-#define INTC_ILR11		INTC_REG32(0x12C)
-#define INTC_ILR32		INTC_REG32(0x180)
-#define INTC_ILR37		INTC_REG32(0x194)
-#define INTC_SYSCONFIG		INTC_REG32(0x010)
-
-/* RAM FIREWALL */
-#define RAMFW_BASE		(0x68005000)
-#define RAMFW_REG32(offset)	__REG32(RAMFW_BASE + (offset))
-
-#define RAMFW_REQINFOPERM0	RAMFW_REG32(0x048)
-#define RAMFW_READPERM0		RAMFW_REG32(0x050)
-#define RAMFW_WRITEPERM0	RAMFW_REG32(0x058)
-
-/* GPMC CS1 FPGA ON USER INTERFACE MODULE */
-//#define DEBUG_BOARD_LED_REGISTER 0x04000014
-
-/* GPMC CS0 */
-#define GPMC_CONFIG1_0		GPMC_REG32(0x060)
-#define GPMC_CONFIG2_0		GPMC_REG32(0x064)
-#define GPMC_CONFIG3_0		GPMC_REG32(0x068)
-#define GPMC_CONFIG4_0		GPMC_REG32(0x06C)
-#define GPMC_CONFIG5_0		GPMC_REG32(0x070)
-#define GPMC_CONFIG6_0		GPMC_REG32(0x074)
-#define GPMC_CONFIG7_0		GPMC_REG32(0x078)
-
-/* GPMC CS1 */
-#define GPMC_CONFIG1_1		GPMC_REG32(0x090)
-#define GPMC_CONFIG2_1		GPMC_REG32(0x094)
-#define GPMC_CONFIG3_1		GPMC_REG32(0x098)
-#define GPMC_CONFIG4_1		GPMC_REG32(0x09C)
-#define GPMC_CONFIG5_1		GPMC_REG32(0x0a0)
-#define GPMC_CONFIG6_1		GPMC_REG32(0x0a4)
-#define GPMC_CONFIG7_1		GPMC_REG32(0x0a8)
-
-/* DSS */
-#define DSS_CONTROL		DISP_REG32(0x040)
-#define DISPC_CONTROL		DISP_REG32(0x440)
-#define DISPC_SYSSTATUS		DISP_REG32(0x414)
-#define DISPC_IRQSTATUS		DISP_REG32(0x418)
-#define DISPC_IRQENABLE		DISP_REG32(0x41C)
-#define DISPC_CONFIG		DISP_REG32(0x444)
-#define DISPC_DEFAULT_COLOR0	DISP_REG32(0x44C)
-#define DISPC_DEFAULT_COLOR1	DISP_REG32(0x450)
-#define DISPC_TRANS_COLOR0	DISP_REG32(0x454)
-#define DISPC_TRANS_COLOR1	DISP_REG32(0x458)
-#define DISPC_LINE_NUMBER	DISP_REG32(0x460)
-#define DISPC_TIMING_H		DISP_REG32(0x464)
-#define DISPC_TIMING_V		DISP_REG32(0x468)
-#define DISPC_POL_FREQ		DISP_REG32(0x46C)
-#define DISPC_DIVISOR		DISP_REG32(0x470)
-#define DISPC_SIZE_DIG		DISP_REG32(0x478)
-#define DISPC_SIZE_LCD		DISP_REG32(0x47C)
-#define DISPC_GFX_BA0		DISP_REG32(0x480)
-#define DISPC_GFX_BA1		DISP_REG32(0x484)
-#define DISPC_GFX_POSITION	DISP_REG32(0x488)
-#define DISPC_GFX_SIZE		DISP_REG32(0x48C)
-#define DISPC_GFX_ATTRIBUTES	DISP_REG32(0x4A0)
-#define DISPC_GFX_FIFO_THRESHOLD	DISP_REG32(0x4A4)
-#define DISPC_GFX_ROW_INC	DISP_REG32(0x4AC)
-#define DISPC_GFX_PIXEL_INC	DISP_REG32(0x4B0)
-#define DISPC_GFX_WINDOW_SKIP	DISP_REG32(0x4B4)
-#define DISPC_GFX_TABLE_BA	DISP_REG32(0x4B8)
-#define DISPC_DATA_CYCLE1	DISP_REG32(0x5D4)
-#define DISPC_DATA_CYCLE2	DISP_REG32(0x5D8)
-#define DISPC_DATA_CYCLE3	DISP_REG32(0x5DC)
-
-/* Wake up define for board */
-#define GPIO97			(1 << 1)
-#define GPIO88			(1 << 24)
-
-#endif /* __ASSEMBLER__ */
+u32 omap_prcm_get_reset_sources(void);
 
 #endif
 
diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h
index e72ccbf..6fc0dd5 100644
--- a/include/asm-arm/arch-omap/sram.h
+++ b/include/asm-arm/arch-omap/sram.h
@@ -20,6 +20,8 @@
 				      u32 mem_type);
 extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
 
+extern unsigned long omap_fb_sram_start;
+extern unsigned long omap_fb_sram_size;
 
 /* Do not use these */
 extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl);
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h
index 6724a81..67970d1 100644
--- a/include/asm-arm/arch-omap/system.h
+++ b/include/asm-arm/arch-omap/system.h
@@ -9,12 +9,13 @@
 
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
-#include <asm/arch/prcm.h>
 
 #ifndef CONFIG_MACH_VOICEBLUE
 #define voiceblue_reset()		do {} while (0)
 #endif
 
+extern void omap_prcm_arch_reset(char mode);
+
 static inline void arch_idle(void)
 {
 	cpu_do_idle();
@@ -38,24 +39,12 @@
 		omap_writew(1, ARM_RSTCT1);
 }
 
-static inline void omap2_arch_reset(char mode)
-{
-	u32 rate;
-	struct clk *vclk, *sclk;
-
-	vclk = clk_get(NULL, "virt_prcm_set");
-	sclk = clk_get(NULL, "sys_ck");
-	rate = clk_get_rate(sclk);
-	clk_set_rate(vclk, rate);	/* go to bypass for OMAP limitation */
-	RM_RSTCTRL_WKUP |= 2;
-}
-
 static inline void arch_reset(char mode)
 {
 	if (!cpu_is_omap24xx())
 		omap1_arch_reset(mode);
 	else
-		omap2_arch_reset(mode);
+		omap_prcm_arch_reset(mode);
 }
 
 #endif
diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h
index 9d7f873..7480f4e 100644
--- a/include/asm-arm/arch-rpc/hardware.h
+++ b/include/asm-arm/arch-rpc/hardware.h
@@ -46,7 +46,6 @@
 #define SCREEN_END		0xdfc00000
 #define SCREEN_BASE		0xdf800000
 
-#define FLUSH_BASE		0xdf000000
 #define UNCACHEABLE_ADDR	0xdf010000
 
 /*
@@ -59,8 +58,6 @@
 #define PCIO_BASE		IOMEM(0xe0010000)
 #define FLOPPYDMA_BASE		IOMEM(0xe002a000)
 
-#define FLUSH_BASE_PHYS		0x00000000	/* ROM */
-
 #define vidc_writel(val)	__raw_writel(val, VIDC_BASE)
 
 #define IO_EC_EASI_BASE		0x81400000
diff --git a/include/asm-arm/arch-rpc/memory.h b/include/asm-arm/arch-rpc/memory.h
index 0592cb3..303c424 100644
--- a/include/asm-arm/arch-rpc/memory.h
+++ b/include/asm-arm/arch-rpc/memory.h
@@ -30,4 +30,10 @@
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
 
+/*
+ * Cache flushing area - ROM
+ */
+#define FLUSH_BASE_PHYS		0x00000000
+#define FLUSH_BASE		0xdf000000
+
 #endif
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index cc06b1b..894c35c 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -6,116 +6,83 @@
  * 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.
+*/
 
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- */
+/* We have a problem that the INTOFFSET register does not always
+ * show one interrupt. Occasionally we get two interrupts through
+ * the prioritiser, and this causes the INTOFFSET register to show
+ * what looks like the logical-or of the two interrupt numbers.
+ *
+ * Thanks to Klaus, Shannon, et al for helping to debug this problem
+*/
+
+#define INTPND		(0x10)
+#define INTOFFSET	(0x14)
+#define EXTINTPEND	(0xa8)
+#define EXTINTMASK	(0xa4)
+
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 
-
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 
-		mov	\tmp, #S3C24XX_VA_IRQ
-		ldr	\irqnr, [ \tmp, #0x14 ]		@ get irq no
-30000:
-		teq	\irqnr, #4
-		teqne	\irqnr, #5
-		beq	1002f				@ external irq reg
+		mov	\base, #S3C24XX_VA_IRQ
 
-		@ debug check to see if interrupt reported is the same
-		@ as the offset....
+		ldr	\irqstat, [ \base, #INTPND]
+		bics	\irqnr, \irqstat, #3<<4		@@ only an GPIO IRQ
+		beq	2000f
 
-		teq	\irqnr, #0
-		beq	20002f
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-		mov	\irqstat, \irqstat, lsr \irqnr
-		tst	\irqstat, #1
-		bne	20002f
+		@@ try the interrupt offset register, since it is there
 
-		/* debug/warning if we get an invalud response from the
-		 * INTOFFSET register */
-#if 1
-		stmfd	r13!, { r0 - r4 , r8-r12, r14 }
-		ldr	r1,	[ \tmp, #0x14 ]		@ INTOFFSET
-		ldr	r2,	[ \tmp, #0x10 ]		@ INTPND
-		ldr	r3,	[ \tmp, #0x00 ]		@ SRCPND
-		adr	r0, 20003f
-		bl	printk
-		b	20004f
+		ldr	\irqnr, [ \base, #INTOFFSET ]
+		mov	\tmp, #1
+		tst	\irqstat, \tmp, lsl \irqnr
+		addne	\irqnr, \irqnr, #IRQ_EINT0
+		bne	1001f
 
-20003:
-		.ascii	"<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
-		.byte	0
-		.align	4
-20004:
-		mov	r1, #1
-		mov	\tmp, #S3C24XX_VA_IRQ
-		ldmfd	r13!, { r0 - r4 , r8-r12, r14 }
-#endif
+		@@ the number specified is not a valid irq, so try
+		@@ and work it out for ourselves
 
-		@ try working out interrupt number for ourselves
-		mov	\irqnr, #0
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-10021:
-		movs	\irqstat, \irqstat, lsr#1
-		bcs	30000b		@ try and re-start the proccess
-		add	\irqnr, \irqnr, #1
-		cmp	\irqnr, #32
-		ble	10021b
+		mov	\irqnr, #IRQ_EINT0		@@ start here
+		b	3000f
 
-		@ found no interrupt, set Z flag and leave
-		movs	\irqnr, #0
-		b	1001f
+2000:
+		@@ load the GPIO interrupt register, and check it
 
-20005:
-20002:		@ exit
-		@ we base the s3c2410x interrupts at 16 and above to allow
-		@ isa peripherals to have their standard interrupts, also
-		@ ensure that Z flag is un-set on exit
+		add	\tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
+		ldr	\irqstat, [ \tmp, # EXTINTPEND ]
+		ldr	\irqnr,   [ \tmp, # EXTINTMASK ]
+		bics	\irqstat, \irqstat, \irqnr
+		beq	1001f
 
-		@ note, we cannot be sure if we get IRQ_EINT0 (0) that
-		@ there is simply no interrupt pending, so in all other
-		@ cases we jump to say we have found something, otherwise
-		@ we check to see if the interrupt really is assrted
-		adds	\irqnr, \irqnr, #IRQ_EINT0
-		teq	\irqnr, #IRQ_EINT0
-		bne	1001f				@ exit
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-		teq	\irqstat, #0
-		moveq	\irqnr, #0
-		b	1001f
+		mov	\irqnr, #(IRQ_EINT4 - 4)
 
-		@ we get here from no main or external interrupts pending
-1002:
-		add	\tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
-		ldr	\irqstat, [ \tmp, # 0xa8 ]	@ EXTINTPEND
-		ldr	\irqnr, [ \tmp, # 0xa4 ]	@ EXTINTMASK
+		@@ work out which irq (if any) we got
+3000:
+		movs	\tmp, \irqstat, lsl#16
+		addeq	\irqnr, \irqnr, #16
+		moveq	\irqstat, \irqstat, lsr#16
+		tst	\irqstat, #0xff
+		addeq	\irqnr, \irqnr, #8
+		moveq	\irqstat, \irqstat, lsr#8
+		tst	\irqstat, #0xf
+		addeq	\irqnr, \irqnr, #4
+		moveq	\irqstat, \irqstat, lsr#4
+		tst	\irqstat, #0x3
+		addeq	\irqnr, \irqnr, #2
+		moveq	\irqstat, \irqstat, lsr#2
+		tst	\irqstat, #0x1
+		addeq	\irqnr, \irqnr, #1
 
-		bic	\irqstat, \irqstat, \irqnr	@ clear masked irqs
+		@@ we have the value
+		movs	\irqnr, \irqnr
 
-		mov	\irqnr, #IRQ_EINT4		@ start extint nos
-		mov	\irqstat, \irqstat, lsr#4	@ ignore bottom 4 bits
-10021:
-		movs	\irqstat, \irqstat, lsr#1
-		bcs	1004f
-		add	\irqnr, \irqnr, #1
-		cmp	\irqnr, #IRQ_EINT23
-		ble	10021b
-
-		@ found no interrupt, set Z flag and leave
-		movs	\irqnr, #0
-
-1004:		@ ensure Z flag clear in case our MOVS shifted out the last bit
-		teq	\irqnr, #0
 1001:
-		@ exit irq routine
-		.endm
+		@@ exit here, Z flag unset if IRQ
 
+	.endm
 
 		/* currently don't need an disable_fiq macro */
 
 		.macro	disable_fiq
 		.endm
-
-
diff --git a/include/asm-arm/arch-s3c2410/leds-gpio.h b/include/asm-arm/arch-s3c2410/leds-gpio.h
new file mode 100644
index 0000000..f07ed04
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/leds-gpio.h
@@ -0,0 +1,28 @@
+/* linux/include/asm-arm/arch-s3c2410/leds-gpio.h
+ *
+ * (c) 2006 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX - LEDs GPIO connector
+ *
+ * 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_LEDSGPIO_H
+#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"
+
+#define S3C24XX_LEDF_ACTLOW	(1<<0)		/* LED is on when GPIO low */
+#define S3C24XX_LEDF_TRISTATE	(1<<1)		/* tristate to turn off */
+
+struct s3c24xx_led_platdata {
+	unsigned int		 gpio;
+	unsigned int		 flags;
+
+	char			*name;
+	char			*def_trigger;
+};
+
+#endif /* __ASM_ARCH_LEDSGPIO_H */
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index 28711aa..ee008a5 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -14,10 +14,6 @@
 
 #include <linux/config.h>
 
-/* Flushing areas */
-#define FLUSH_BASE_PHYS		0xe0000000	/* SA1100 zero bank */
-#define FLUSH_BASE		0xf5000000
-#define FLUSH_BASE_MINICACHE	0xf5800000
 #define UNCACHEABLE_ADDR	0xfa050000
 
 
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index 018a9f0..a29fac1 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -91,4 +91,11 @@
 
 #endif
 
+/*
+ * Cache flushing area - SA1100 zero bank
+ */
+#define FLUSH_BASE_PHYS		0xe0000000
+#define FLUSH_BASE		0xf5000000
+#define FLUSH_BASE_MINICACHE	0xf5100000
+
 #endif
diff --git a/include/asm-arm/arch-shark/hardware.h b/include/asm-arm/arch-shark/hardware.h
index 4d35f8c..ecba452 100644
--- a/include/asm-arm/arch-shark/hardware.h
+++ b/include/asm-arm/arch-shark/hardware.h
@@ -17,11 +17,6 @@
  */
 #define IO_BASE			0xe0000000
 
-/*
- * RAM definitions
- */
-#define FLUSH_BASE_PHYS		0x80000000
-
 #else
 
 #define IO_BASE			0
@@ -33,7 +28,6 @@
 #define ROMCARD_SIZE		0x08000000
 #define ROMCARD_START		0x10000000
 
-#define FLUSH_BASE		0xdf000000
 #define PCIO_BASE		0xe0000000
 
 
diff --git a/include/asm-arm/arch-shark/memory.h b/include/asm-arm/arch-shark/memory.h
index 95a29b4..6968d61 100644
--- a/include/asm-arm/arch-shark/memory.h
+++ b/include/asm-arm/arch-shark/memory.h
@@ -39,4 +39,10 @@
 #define __virt_to_bus(x)	__virt_to_phys(x)
 #define __bus_to_virt(x)	__phys_to_virt(x)
 
+/*
+ * Cache flushing area
+ */
+#define FLUSH_BASE_PHYS		0x80000000
+#define FLUSH_BASE		0xdf000000
+
 #endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index e3e8541..63ca741 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -47,7 +47,7 @@
 
 static inline int dma_is_consistent(dma_addr_t handle)
 {
-	return 0;
+	return !!arch_is_coherent();
 }
 
 /*
@@ -145,7 +145,9 @@
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 	       enum dma_data_direction dir)
 {
-	consistent_sync(cpu_addr, size, dir);
+	if (!arch_is_coherent())
+		consistent_sync(cpu_addr, size, dir);
+
 	return virt_to_dma(dev, (unsigned long)cpu_addr);
 }
 #else
@@ -255,7 +257,9 @@
 
 		sg->dma_address = page_to_dma(dev, sg->page) + sg->offset;
 		virt = page_address(sg->page) + sg->offset;
-		consistent_sync(virt, sg->length, dir);
+
+		if (!arch_is_coherent())
+			consistent_sync(virt, sg->length, dir);
 	}
 
 	return nents;
@@ -310,14 +314,16 @@
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
 			enum dma_data_direction dir)
 {
-	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+	if (!arch_is_coherent())
+		consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
 }
 
 static inline void
 dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
 			   enum dma_data_direction dir)
 {
-	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+	if (!arch_is_coherent())
+		consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
 }
 #else
 extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
@@ -347,7 +353,8 @@
 
 	for (i = 0; i < nents; i++, sg++) {
 		char *virt = page_address(sg->page) + sg->offset;
-		consistent_sync(virt, sg->length, dir);
+		if (!arch_is_coherent())
+			consistent_sync(virt, sg->length, dir);
 	}
 }
 
@@ -359,7 +366,8 @@
 
 	for (i = 0; i < nents; i++, sg++) {
 		char *virt = page_address(sg->page) + sg->offset;
-		consistent_sync(virt, sg->length, dir);
+		if (!arch_is_coherent())
+			consistent_sync(virt, sg->length, dir);
 	}
 }
 #else
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 6246bf8..52bae08 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -26,7 +26,9 @@
 
 struct vfp_hard_struct {
 	__u64 fpregs[16];
+#if __LINUX_ARM_ARCH__ < 6
 	__u32 fpmx_state;
+#endif
 	__u32 fpexc;
 	__u32 fpscr;
 	/*
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index afa5c3e..2092894 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -172,10 +172,10 @@
  *  virt_addr_valid(k)	indicates whether a virtual address is valid
  */
 #ifndef CONFIG_DISCONTIGMEM
-#define ARCH_PFN_OFFSET		(PHYS_PFN_OFFSET)
+#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
 #define pfn_valid(pfn)		((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
 
-#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
 
 #define PHYS_TO_NID(addr)	(0)
@@ -187,8 +187,8 @@
  * around in memory.
  */
 #include <linux/numa.h>
-#define arch_pfn_to_nid(pfn)	(PFN_TO_NID(pfn))
-#define arch_local_page_offset(pfn, nid) (LOCAL_MAP_NR((pfn) << PAGE_OFFSET))
+#define arch_pfn_to_nid(pfn)	PFN_TO_NID(pfn)
+#define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
 
 #define pfn_valid(pfn)						\
 	({							\
@@ -234,6 +234,14 @@
 #define virt_to_dma(dev, addr)		(__arch_virt_to_dma(dev, addr))
 #endif
 
+/*
+ * Optional coherency support.  Currently used only by selected
+ * Intel XSC3-based systems.
+ */
+#ifndef arch_is_coherent
+#define arch_is_coherent()		0
+#endif
+
 #endif
 
 #include <asm-generic/memory_model.h>
diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h
deleted file mode 100644
index 8df3681..0000000
--- a/include/asm-arm/numnodes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  linux/include/asm-arm/numnodes.h
- *
- *  Copyright (C) 2002 Russell King
- *
- * 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 declaration for the size of the NUMA (CONFIG_DISCONTIGMEM)
- * memory node table is the default.
- *
- * A good place to override this value is include/asm/arch/memory.h.
- */
-
-#ifndef __ASM_ARM_NUMNODES_H
-#define __ASM_ARM_NUMNODES_H
-
-#include <asm/memory.h>
-
-#ifndef NODES_SHIFT
-# define NODES_SHIFT	2	/* Normally, Max 4 Nodes */
-#endif
-
-#endif
diff --git a/include/asm-arm/pgtable-hwdef.h b/include/asm-arm/pgtable-hwdef.h
index 1d03349..1bc1f99 100644
--- a/include/asm-arm/pgtable-hwdef.h
+++ b/include/asm-arm/pgtable-hwdef.h
@@ -73,6 +73,7 @@
 #define PTE_EXT_AP_URW_SRW	(PTE_EXT_AP1|PTE_EXT_AP0)
 #define PTE_EXT_TEX(x)		((x) << 6)	/* v5 */
 #define PTE_EXT_APX		(1 << 9)	/* v6 */
+#define PTE_EXT_COHERENT	(1 << 9)	/* XScale3 */
 #define PTE_EXT_SHARED		(1 << 10)	/* v6 */
 #define PTE_EXT_NG		(1 << 11)	/* v6 */
 
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index e595ae2..e85c08d 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -156,6 +156,7 @@
 #define L_PTE_WRITE		(1 << 5)
 #define L_PTE_EXEC		(1 << 6)
 #define L_PTE_DIRTY		(1 << 7)
+#define L_PTE_COHERENT		(1 << 9)	/* I/O coherent (xsc3) */
 #define L_PTE_SHARED		(1 << 10)	/* shared between CPUs (v6) */
 #define L_PTE_ASID		(1 << 11)	/* non-global (use ASID, v6) */
 
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 65ac305..ee8dfea 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -360,6 +360,24 @@
 #define __ARM_NR_usr32			(__ARM_NR_BASE+4)
 #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
 
+/*
+ * The following syscalls are obsolete and no longer available for EABI.
+ */
+#if defined(__ARM_EABI__)
+#undef __NR_time
+#undef __NR_umount
+#undef __NR_stime
+#undef __NR_alarm
+#undef __NR_utime
+#undef __NR_getrlimit
+#undef __NR_select
+#undef __NR_readdir
+#undef __NR_mmap
+#undef __NR_socketcall
+#undef __NR_syscall
+#undef __NR_ipc
+#endif
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
index 15bd6e7..27fe028 100644
--- a/include/asm-arm/vfpmacros.h
+++ b/include/asm-arm/vfpmacros.h
@@ -16,10 +16,18 @@
 
 	@ read all the working registers back into the VFP
 	.macro	VFPFLDMIA, base
+#if __LINUX_ARM_ARCH__ < 6
 	LDC	p11, cr0, [\base],#33*4		    @ FLDMIAX \base!, {d0-d15}
+#else
+	LDC	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d0-d15}
+#endif
 	.endm
 
 	@ write all the working registers out of the VFP
 	.macro	VFPFSTMIA, base
+#if __LINUX_ARM_ARCH__ < 6
 	STC	p11, cr0, [\base],#33*4		    @ FSTMIAX \base!, {d0-d15}
+#else
+	STC	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d0-d15}
+#endif
 	.endm
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index 1d63c2a..b1c593b 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -8,7 +8,6 @@
  */
 
 extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
-#define prepare_to_switch()     do { } while(0)
 #define switch_to(prev,next,last) last = resume(prev,next, \
 					 (int)&((struct task_struct *)0)->thread)
 
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 2627bbd..bb2dfe4 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -288,7 +288,7 @@
 #define __NR_mq_timedreceive	(__NR_mq_open+3)
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 /* #define __NR_sys_setaltroot	285 */
 #define __NR_add_key		286
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index f72ff0c..1734ed9 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -18,8 +18,6 @@
 
 struct thread_struct;
 
-#define prepare_to_switch()    do { } while(0)
-
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 322531c..2662a3e 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -289,7 +289,7 @@
 #define __NR_mq_timedreceive	(__NR_mq_open+3)
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 /* #define __NR_sys_setaltroot	285 */
 #define __NR_add_key		286
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index dfe96c7..8e81cf6 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -4,8 +4,6 @@
 #include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 
-#define prepare_to_switch()	do { } while(0)
-
 /*
  * switch_to(n) should switch tasks to task ptr, first checking that
  * ptr isn't the current task, in which case it does nothing.  This
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 56a4a56..adb0515 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -285,7 +285,7 @@
 #define __NR_mq_timedreceive	(__NR_mq_open+3)
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 /* #define __NR_sys_setaltroot	285 */
 #define __NR_add_key		286
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index ff9ac8d..288233f 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -139,6 +139,8 @@
 
 extern int timer_over_8254;
 
+extern int modern_apic(void);
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 22d80ec..4ddce52 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -183,6 +183,7 @@
 {
 	int __i;
 #ifdef CONFIG_M386
+	unsigned long flags;
 	if(unlikely(boot_cpu_data.x86==3))
 		goto no_xadd;
 #endif
@@ -196,10 +197,10 @@
 
 #ifdef CONFIG_M386
 no_xadd: /* Legacy 386 processor */
-	local_irq_disable();
+	local_irq_save(flags);
 	__i = atomic_read(v);
 	atomic_set(v, i + __i);
-	local_irq_enable();
+	local_irq_restore(flags);
 	return i + __i;
 #endif
 }
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index 5c0b587..b44bfc6 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -71,6 +71,7 @@
 #define X86_FEATURE_P4		(3*32+ 7) /* P4 */
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_UP		(3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index edf65be..ca82acb 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -35,6 +35,10 @@
 };
 
 extern struct e820map e820;
+
+extern int e820_all_mapped(unsigned long start, unsigned long end,
+			   unsigned type);
+
 #endif/*!__ASSEMBLY__*/
 
 #endif/*__E820_HEADER*/
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 16ef9f9..7f1a8a6 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -89,6 +89,7 @@
  * then 32 bit HPET counter wrapsaround in less than 0.5 sec.
  */
 #define HPET_MIN_PERIOD (100000UL)
+#define HPET_TICK_RATE  (HZ * 100000UL)
 
 extern unsigned long hpet_tick;  	/* hpet clks count per tick */
 extern unsigned long hpet_address;	/* hpet memory map physical address */
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index 152d0ba..7b1f011 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -13,6 +13,7 @@
 
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/kernel_stat.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
 #include <asm/user.h>
@@ -38,17 +39,38 @@
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
+/* We need a safe address that is cheap to find and that is already
+   in L1 during context switch. The best choices are unfortunately
+   different for UP and SMP */
+#ifdef CONFIG_SMP
+#define safe_address (__per_cpu_offset[0])
+#else
+#define safe_address (kstat_cpu(0).cpustat.user)
+#endif
+
 /*
  * These must be called with preempt disabled
  */
 static inline void __save_init_fpu( struct task_struct *tsk )
 {
+	/* Use more nops than strictly needed in case the compiler
+	   varies code */
 	alternative_input(
-		"fnsave %1 ; fwait ;" GENERIC_NOP2,
-		"fxsave %1 ; fnclex",
+		"fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
+		"fxsave %[fx]\n"
+		"bt $7,%[fsw] ; jc 1f ; fnclex\n1:",
 		X86_FEATURE_FXSR,
-		"m" (tsk->thread.i387.fxsave)
-		:"memory");
+		[fx] "m" (tsk->thread.i387.fxsave),
+		[fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
+	/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+	   is pending.  Clear the x87 state here by setting it to fixed
+   	   values. __per_cpu_offset[0] is a random variable that should be in L1 */
+	alternative_input(
+		GENERIC_NOP8 GENERIC_NOP2,
+		"emms\n\t"	  	/* clear stack tags */
+		"fildl %[addr]", 	/* set F?P to defined value */
+		X86_FEATURE_FXSAVE_LEAK,
+		[addr] "m" (safe_address));
 	task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index 62113d3..770bf6d 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -18,7 +18,6 @@
 extern void get_smp_config (void);
 extern int nr_ioapics;
 extern int apic_version [MAX_APICS];
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
 extern int mp_irq_entries;
 extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
 extern int mpc_default_type;
diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h
deleted file mode 100644
index a61f38c..0000000
--- a/include/asm-i386/numnodes.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_X86_NUMAQ
-
-/* Max 16 Nodes */
-#define NODES_SHIFT	4
-
-#elif defined(CONFIG_ACPI_SRAT)
-
-/* Max 8 Nodes */
-#define NODES_SHIFT	3
-
-#endif /* CONFIG_X86_NUMAQ */
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index 27bde97..2756d4b 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -18,6 +18,9 @@
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
 
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
+#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+
 #define ptep_get_and_clear(mm,addr,xp)	__pte(xchg(&(xp)->pte_low, 0))
 #define pte_same(a, b)		((a).pte_low == (b).pte_low)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index 36a5aa6..dccb1b3 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -85,6 +85,26 @@
 #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
 			pmd_index(address))
 
+/*
+ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+ * entry, so clear the bottom half first and enforce ordering with a compiler
+ * barrier.
+ */
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	ptep->pte_low = 0;
+	smp_wmb();
+	ptep->pte_high = 0;
+}
+
+static inline void pmd_clear(pmd_t *pmd)
+{
+	u32 *tmp = (u32 *)pmd;
+	*tmp = 0;
+	smp_wmb();
+	*(tmp + 1) = 0;
+}
+
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t res;
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index ee056c4..672c3f7 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -204,12 +204,10 @@
 extern unsigned long pg0[];
 
 #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
 #define pmd_none(x)	(!(unsigned long)pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 
 
@@ -268,7 +266,7 @@
 	pte_t pte;
 	if (full) {
 		pte = *ptep;
-		*ptep = __pte(0);
+		pte_clear(mm, addr, ptep);
 	} else {
 		pte = ptep_get_and_clear(mm, addr, ptep);
 	}
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 2e7f3e2..eb4b152 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -288,7 +288,7 @@
 #define __NR_mq_timedreceive	(__NR_mq_open+3)
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 /* #define __NR_sys_setaltroot	285 */
 #define __NR_add_key		286
@@ -318,10 +318,12 @@
 #define __NR_unshare		310
 #define __NR_set_robust_list	311
 #define __NR_get_robust_list	312
-#define __NR_sys_splice		313
-#define __NR_sys_sync_file_range 314
+#define __NR_splice		313
+#define __NR_sync_file_range	314
+#define __NR_tee		315
+#define __NR_vmsplice		316
 
-#define NR_syscalls 315
+#define NR_syscalls 317
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/acpi-ext.h b/include/asm-ia64/acpi-ext.h
index 56d2ddc..734d137 100644
--- a/include/asm-ia64/acpi-ext.h
+++ b/include/asm-ia64/acpi-ext.h
@@ -1,12 +1,15 @@
 /*
- * ia64/platform/hp/common/hp_acpi.h
+ * (c) Copyright 2003, 2006 Hewlett-Packard Development Company, L.P.
+ *	Alex Williamson <alex.williamson@hp.com>
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
- * Copyright (C) 2003 Hewlett-Packard
- * Copyright (C) Alex Williamson
- * Copyright (C) Bjorn Helgaas
+ * 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.
  *
  * Vendor specific extensions to ACPI.
  */
+
 #ifndef _ASM_IA64_ACPI_EXT_H
 #define _ASM_IA64_ACPI_EXT_H
 
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index d734585..09a5dd0 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -110,9 +110,8 @@
 extern int additional_cpus;
 
 #ifdef CONFIG_ACPI_NUMA
-/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
-#ifdef CONFIG_IA64_NR_NODES
-#define MAX_PXM_DOMAINS CONFIG_IA64_NR_NODES
+#if MAX_NUMNODES > 256
+#define MAX_PXM_DOMAINS MAX_NUMNODES
 #else
 #define MAX_PXM_DOMAINS (256)
 #endif
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 218c458..c195a9a 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -58,6 +58,8 @@
 	DIE_MCA_RENDZVOUS_ENTER,
 	DIE_MCA_RENDZVOUS_PROCESS,
 	DIE_MCA_RENDZVOUS_LEAVE,
+	DIE_MCA_NEW_TIMEOUT,
+	DIE_INIT_ENTER,
 	DIE_INIT_MONARCH_ENTER,
 	DIE_INIT_MONARCH_PROCESS,
 	DIE_INIT_MONARCH_LEAVE,
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index c3e4ed8..a9c995a 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -347,9 +347,11 @@
 #endif
 #ifndef platform_pci_legacy_read
 # define platform_pci_legacy_read	ia64_pci_legacy_read
+extern int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size);
 #endif
 #ifndef platform_pci_legacy_write
 # define platform_pci_legacy_write	ia64_pci_legacy_write
+extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size);
 #endif
 #ifndef platform_inb
 # define platform_inb		__ia64_inb
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index bfbbb8d..9c5389b 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -148,6 +148,11 @@
 extern void ia64_unreg_MCA_extension(void);
 extern u64 ia64_get_rnat(u64 *);
 
+struct ia64_mca_notify_die {
+	struct ia64_sal_os_state *sos;
+	int *monarch_cpu;
+};
+
 #else	/* __ASSEMBLY__ */
 
 #define IA64_MCA_CORRECTED	0x0	/* Error has been corrected by OS_MCA */
diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h
index 5a3224f..bed73a6 100644
--- a/include/asm-ia64/mutex.h
+++ b/include/asm-ia64/mutex.h
@@ -84,7 +84,7 @@
 static inline int
 __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
 {
-	if (likely(cmpxchg_acq(count, 1, 0)) == 1)
+	if (cmpxchg_acq(count, 1, 0) == 1)
 		return 1;
 	return 0;
 }
diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h
deleted file mode 100644
index e9d356f..0000000
--- a/include/asm-ia64/numnodes.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-#ifdef CONFIG_IA64_DIG
-/* Max 8 Nodes */
-#  define NODES_SHIFT	3
-#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB)
-/* Max 32 Nodes */
-#  define NODES_SHIFT	5
-#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC)
-#  if CONFIG_IA64_NR_NODES == 256
-#    define NODES_SHIFT	8
-#  elif CONFIG_IA64_NR_NODES <= 512
-#    define NODES_SHIFT    9
-#  elif CONFIG_IA64_NR_NODES <= 1024
-#    define NODES_SHIFT    10
-#  endif
-#endif
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
index 291ef3d..e61ebac 100644
--- a/include/asm-ia64/sn/sn2/sn_hwperf.h
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h
@@ -45,8 +45,12 @@
 #define SN_HWPERF_IS_NODE(x)		((x) && strstr((x)->name, "SHub"))
 #define SN_HWPERF_IS_NODE_SHUB2(x)	((x) && strstr((x)->name, "SHub 2."))
 #define SN_HWPERF_IS_IONODE(x)		((x) && strstr((x)->name, "TIO"))
-#define SN_HWPERF_IS_ROUTER(x)		((x) && strstr((x)->name, "Router"))
 #define SN_HWPERF_IS_NL3ROUTER(x)	((x) && strstr((x)->name, "NL3Router"))
+#define SN_HWPERF_IS_NL4ROUTER(x)	((x) && strstr((x)->name, "NL4Router"))
+#define SN_HWPERF_IS_OLDROUTER(x)	((x) && strstr((x)->name, "Router"))
+#define SN_HWPERF_IS_ROUTER(x)		(SN_HWPERF_IS_NL3ROUTER(x) || 		\
+					 	SN_HWPERF_IS_NL4ROUTER(x) || 	\
+					 	SN_HWPERF_IS_OLDROUTER(x))
 #define SN_HWPERF_FOREIGN(x)		((x) && !(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
 #define SN_HWPERF_SAME_OBJTYPE(x,y)	((SN_HWPERF_IS_NODE(x) && SN_HWPERF_IS_NODE(y)) ||\
 					(SN_HWPERF_IS_IONODE(x) && SN_HWPERF_IS_IONODE(y)) ||\
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index bf4cc86..51aca02 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -8,7 +8,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.  All rights reserved.
  */
 
 
@@ -85,6 +85,7 @@
 
 #define  SN_SAL_GET_PROM_FEATURE_SET		   0x02000065
 #define  SN_SAL_SET_OS_FEATURE_SET		   0x02000066
+#define  SN_SAL_INJECT_ERROR			   0x02000067
 
 /*
  * Service-specific constants
@@ -705,10 +706,8 @@
 sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
 {
 	struct ia64_sal_retval ret_stuff;
-	int cnodeid;
 	unsigned long irq_flags;
 
-	cnodeid = nasid_to_cnodeid(get_node_number(paddr));
 	local_irq_save(irq_flags);
 	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
 				(u64)nasid_array, perms, 0, 0, 0);
@@ -1140,4 +1139,16 @@
 	return rv.status;
 }
 
+static inline int
+sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
+{
+	struct ia64_sal_retval ret_stuff;
+	unsigned long irq_flags;
+
+	local_irq_save(irq_flags);
+	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
+				(u64)ecc, 0, 0, 0, 0);
+	local_irq_restore(irq_flags);
+	return ret_stuff.status;
+}
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 56394a2..e5392c4 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -67,7 +67,7 @@
 #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
 
 #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct()	((task_t *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct()	((task_t *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
 #define free_task_struct(tsk)	free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
 
 #endif /* !__ASSEMBLY */
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 3ee19df..616b5ed 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -23,6 +23,11 @@
 #define PENALTY_FOR_NODE_WITH_CPUS 255
 
 /*
+ * Distance above which we begin to use zone reclaim
+ */
+#define RECLAIM_DISTANCE 15
+
+/*
  * Returns the number of the node containing CPU 'cpu'
  */
 #define cpu_to_node(cpu) (int)(cpu_to_node_map[cpu])
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 36070c1..7107763 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -286,12 +286,17 @@
 /* 1294, 1295 reserved for pselect/ppoll */
 #define __NR_unshare			1296
 #define __NR_splice			1297
+#define __NR_set_robust_list		1298
+#define __NR_get_robust_list		1299
+#define __NR_sync_file_range		1300
+#define __NR_tee			1301
+#define __NR_vmsplice			1302
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
 
-#define NR_syscalls			274 /* length of syscall table */
+#define NR_syscalls			279 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h
index bc3349f..091177c 100644
--- a/include/asm-ia64/vga.h
+++ b/include/asm-ia64/vga.h
@@ -17,7 +17,7 @@
 extern unsigned long vga_console_iobase;
 extern unsigned long vga_console_membase;
 
-#define VGA_MAP_MEM(x)	((unsigned long) ioremap(vga_console_membase + (x), 0))
+#define VGA_MAP_MEM(x)	((unsigned long) ioremap_nocache(vga_console_membase + (x), 0))
 
 #define vga_readb(x)	(*(x))
 #define vga_writeb(x,y)	(*(y) = (x))
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index b7f4d8a..1a1aa17 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -109,6 +109,9 @@
 	push	r13
 	mvfachi	r13
 	push	r13
+	ldi	r13, #0
+	push	r13		; dummy push acc1h
+	push	r13		; dummy push acc1l
 #else
 #error unknown isa configuration
 #endif
@@ -156,6 +159,8 @@
 	pop	r13
 	mvtaclo	r13, a1
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	pop	r13		; dummy pop acc1h
+	pop	r13		; dummy pop acc1l
 	pop	r13
 	mvtachi	r13
 	pop	r13
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
index 1d3c25d..031369a 100644
--- a/include/asm-m32r/mappi3/mappi3_pld.h
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -53,16 +53,14 @@
 /* Power Control of MMC and CF */
 #define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
 
-
-/*==== ICU ====*/
-#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
-#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
-#define  PLD_IRQ_CFIREQ       (6)  /* INT5 CFC Card Interrupt */
-#define  PLD_IRQ_CFC_INSERT   (7)  /* INT6 CFC Card Insert */
-#define  PLD_IRQ_IDEIREQ      (8)  /* INT7 IDE Interrupt   */
-#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
-#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
-
+/* ICU */
+#define M32R_IRQ_PC104		(5)	/* INT4(PC/104) */
+#define M32R_IRQ_I2C		(28)	/* I2C-BUS */
+#define PLD_IRQ_CFIREQ		(6)	/* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT	(7)	/* INT6 CFC Card Insert & Eject */
+#define PLD_IRQ_IDEIREQ		(8)	/* INT7 IDE Interrupt */
+#define PLD_IRQ_MMCCARD		(43)	/* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ		(44)	/* MMC Transfer Done */
 
 #if 0
 /* LED Control
@@ -97,7 +95,6 @@
 #define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
 #define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
 
-
 #if 0
 /* RTC */
 #define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
@@ -140,4 +137,7 @@
 
 #endif
 
+/* Reset Control */
+#define PLD_REBOOT		__reg16(PLD_BASE + 0x38000)
+
 #endif	/* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h
deleted file mode 100644
index 479a39d4..0000000
--- a/include/asm-m32r/numnodes.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _ASM_NUMNODES_H_
-#define _ASM_NUMNODES_H_
-
-#include <linux/config.h>
-
-#ifdef CONFIG_DISCONTIGMEM
-
-#if defined(CONFIG_CHIP_M32700)
-#define	NODES_SHIFT	1	/* Max 2 Nodes */
-#endif	/* CONFIG_CHIP_M32700 */
-
-#endif	/* CONFIG_DISCONTIGMEM */
-
-#endif	/* _ASM_NUMNODES_H_ */
-
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 0d058b2..53c7924 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -43,6 +43,14 @@
 #define PT_ACC1L	18
 #define PT_ACCH		PT_ACC0H
 #define PT_ACCL		PT_ACC0L
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH		15
+#define PT_ACCL		16
+#define PT_DUMMY_ACC1H	17
+#define PT_DUMMY_ACC1L	18
+#else
+#error unknown isa conifiguration
+#endif
 #define PT_PSW		19
 #define PT_BPC		20
 #define PT_BBPSW	21
@@ -52,21 +60,6 @@
 #define PT_LR		25
 #define PT_SPI		26
 #define PT_ORIGR0	27
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH		15
-#define PT_ACCL		16
-#define PT_PSW		17
-#define PT_BPC		18
-#define PT_BBPSW	19
-#define PT_BBPC		20
-#define PT_SPU		21
-#define PT_FP		22
-#define PT_LR		23
-#define PT_SPI		24
-#define PT_ORIGR0	25
-#else
-#error unknown isa conifiguration
-#endif
 
 /* virtual pt_reg entry for gdb */
 #define PT_PC		30
@@ -121,6 +114,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	unsigned long acch;
 	unsigned long accl;
+	unsigned long dummy_acc1h;
+	unsigned long dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index bf447c5..81750ed 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -9,7 +9,7 @@
  * SMP- and interrupt-safe semaphores..
  *
  * Copyright (C) 1996  Linus Torvalds
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
@@ -77,27 +77,8 @@
  */
 static inline void down(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
-
 	might_sleep();
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# down				\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #-1;		\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count < 0))
+	if (unlikely(atomic_dec_return(&sem->count) < 0))
 		__down(sem);
 }
 
@@ -107,28 +88,10 @@
  */
 static inline int down_interruptible(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
 	int result = 0;
 
 	might_sleep();
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# down_interruptible		\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #-1;		\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count < 0))
+	if (unlikely(atomic_dec_return(&sem->count) < 0))
 		result = __down_interruptible(sem);
 
 	return result;
@@ -174,26 +137,7 @@
  */
 static inline void up(struct semaphore * sem)
 {
-	unsigned long flags;
-	long count;
-
-	local_irq_save(flags);
-	__asm__ __volatile__ (
-		"# up				\n\t"
-		DCACHE_CLEAR("%0", "r4", "%1")
-		M32R_LOCK" %0, @%1;		\n\t"
-		"addi	%0, #1;			\n\t"
-		M32R_UNLOCK" %0, @%1;		\n\t"
-		: "=&r" (count)
-		: "r" (&sem->count)
-		: "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-		, "r4"
-#endif	/* CONFIG_CHIP_M32700_TS1 */
-	);
-	local_irq_restore(flags);
-
-	if (unlikely(count <= 0))
+	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
 
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index c233e2d..942b8a3 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -32,6 +32,8 @@
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
 	unsigned long sc_acch;
 	unsigned long sc_accl;
+	unsigned long sc_dummy_acc1h;
+	unsigned long sc_dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 7885b7d..1184293 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -67,7 +67,8 @@
 #define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 extern cpumask_t cpu_callout_map;
-#define cpu_possible_map cpu_callout_map
+extern cpumask_t cpu_possible_map;
+extern cpumask_t cpu_present_map;
 
 static __inline__ int hard_smp_processor_id(void)
 {
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index d6a2c61..e55013f 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -6,8 +6,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
@@ -19,53 +19,28 @@
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.
  *
- * `next' and `prev' should be struct task_struct, but it isn't always defined
+ * `next' and `prev' should be task_t, but it isn't always defined
  */
 
-#ifndef CONFIG_SMP
-#define prepare_to_switch()  do { } while(0)
-#endif	/* not CONFIG_SMP */
-
 #define switch_to(prev, next, last)  do { \
-	register unsigned long  arg0 __asm__ ("r0") = (unsigned long)prev; \
-	register unsigned long  arg1 __asm__ ("r1") = (unsigned long)next; \
-	register unsigned long  *oldsp __asm__ ("r2") = &(prev->thread.sp); \
-	register unsigned long  *newsp __asm__ ("r3") = &(next->thread.sp); \
-	register unsigned long  *oldlr __asm__ ("r4") = &(prev->thread.lr); \
-	register unsigned long  *newlr __asm__ ("r5") = &(next->thread.lr); \
-	register struct task_struct  *__last __asm__ ("r6"); \
 	__asm__ __volatile__ ( \
-		"st     r8, @-r15                                 \n\t" \
-		"st     r9, @-r15                                 \n\t" \
-		"st    r10, @-r15                                 \n\t" \
-		"st    r11, @-r15                                 \n\t" \
-		"st    r12, @-r15                                 \n\t" \
-		"st    r13, @-r15                                 \n\t" \
-		"st    r14, @-r15                                 \n\t" \
-		"seth  r14, #high(1f)                             \n\t" \
-		"or3   r14, r14, #low(1f)                         \n\t" \
-		"st    r14, @r4    ; store old LR                 \n\t" \
-		"st    r15, @r2    ; store old SP                 \n\t" \
-		"ld    r15, @r3    ; load new SP                  \n\t" \
-		"st     r0, @-r15  ; store 'prev' onto new stack  \n\t" \
-		"ld    r14, @r5    ; load new LR                  \n\t" \
-		"jmp   r14                                        \n\t" \
-		".fillinsn                                        \n  " \
-		"1:                                               \n\t" \
-		"ld     r6, @r15+  ; load 'prev' from new stack   \n\t" \
-		"ld    r14, @r15+                                 \n\t" \
-		"ld    r13, @r15+                                 \n\t" \
-		"ld    r12, @r15+                                 \n\t" \
-		"ld    r11, @r15+                                 \n\t" \
-		"ld    r10, @r15+                                 \n\t" \
-		"ld     r9, @r15+                                 \n\t" \
-		"ld     r8, @r15+                                 \n\t" \
-		: "=&r" (__last) \
-		: "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
-		  "r" (oldlr), "r" (newlr) \
-		: "memory" \
+		"	seth	lr, #high(1f)				\n" \
+		"	or3	lr, lr, #low(1f)			\n" \
+		"	st	lr, @%4  ; store old LR			\n" \
+		"	ld	lr, @%5  ; load new LR			\n" \
+		"	st	sp, @%2  ; store old SP			\n" \
+		"	ld	sp, @%3  ; load new SP			\n" \
+		"	push	%1  ; store `prev' on new stack		\n" \
+		"	jmp	lr					\n" \
+		"	.fillinsn					\n" \
+		"1:							\n" \
+		"	pop	%0  ; restore `__last' from new stack	\n" \
+		: "=r" (last) \
+		: "0" (prev), \
+		  "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+		  "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+		: "memory", "lr" \
 	); \
-	last = __last; \
 } while(0)
 
 /*
@@ -171,8 +146,8 @@
 #define DCACHE_CLEAR(reg0, reg1, addr)
 #endif	/* CONFIG_CHIP_M32700_TS1 */
 
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
-	int size)
+static inline unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
 {
 	unsigned long flags;
 	unsigned long tmp = 0;
@@ -224,7 +199,7 @@
 
 #define __HAVE_ARCH_CMPXCHG	1
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
 {
 	unsigned long flags;
@@ -258,7 +233,7 @@
    if something tries to do an invalid cmpxchg().  */
 extern void __cmpxchg_called_with_bad_pointer(void);
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 {
 	switch (size) {
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index e8ae619..819cc28 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -5,17 +5,9 @@
  *  linux/include/asm-m32r/uaccess.h
  *
  *  M32R version.
- *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ *    Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#undef UACCESS_DEBUG
-
-#ifdef UACCESS_DEBUG
-#define UAPRINTK(args...) printk(args)
-#else
-#define UAPRINTK(args...)
-#endif /* UACCESS_DEBUG */
-
 /*
  * User space memory access functions
  */
@@ -38,27 +30,29 @@
 #define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
 
 #ifdef CONFIG_MMU
+
 #define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
 #define USER_DS		MAKE_MM_SEG(PAGE_OFFSET)
-#else
-#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
-#define USER_DS		MAKE_MM_SEG(0xFFFFFFFF)
-#endif /* CONFIG_MMU */
-
 #define get_ds()	(KERNEL_DS)
-#ifdef CONFIG_MMU
 #define get_fs()	(current_thread_info()->addr_limit)
 #define set_fs(x)	(current_thread_info()->addr_limit = (x))
-#else
+
+#else /* not CONFIG_MMU */
+
+#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS		MAKE_MM_SEG(0xFFFFFFFF)
+#define get_ds()	(KERNEL_DS)
+
 static inline mm_segment_t get_fs(void)
 {
-  return USER_DS;
+	return USER_DS;
 }
 
 static inline void set_fs(mm_segment_t s)
 {
 }
-#endif /* CONFIG_MMU */
+
+#endif /* not CONFIG_MMU */
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
@@ -83,9 +77,9 @@
 		"	subx	%0, %0\n"				\
 		"	cmpu	%4, %1\n"				\
 		"	subx	%0, %5\n"				\
-		: "=&r"(flag), "=r"(sum)				\
-		: "1"(addr), "r"((int)(size)), 				\
-		  "r"(current_thread_info()->addr_limit.seg), "r"(0)	\
+		: "=&r" (flag), "=r" (sum)				\
+		: "1" (addr), "r" ((int)(size)), 			\
+		  "r" (current_thread_info()->addr_limit.seg), "r" (0)	\
 		: "cbit" );						\
 	flag; })
 
@@ -113,10 +107,10 @@
 #else
 static inline int access_ok(int type, const void *addr, unsigned long size)
 {
-  extern unsigned long memory_start, memory_end;
-  unsigned long val = (unsigned long)addr;
+	extern unsigned long memory_start, memory_end;
+	unsigned long val = (unsigned long)addr;
 
-  return ((val >= memory_start) && ((val + size) < memory_end));
+	return ((val >= memory_start) && ((val + size) < memory_end));
 }
 #endif /* CONFIG_MMU */
 
@@ -155,39 +149,6 @@
  * accesses to the same area of user memory).
  */
 
-extern void __get_user_1(void);
-extern void __get_user_2(void);
-extern void __get_user_4(void);
-
-#ifndef MODULE
-#define __get_user_x(size,ret,x,ptr) 					\
-	__asm__ __volatile__(						\
-		"	mv	r0, %0\n"				\
-		"	mv	r1, %1\n" 				\
-		"	bl __get_user_" #size "\n"			\
-		"	mv	%0, r0\n"				\
-		"	mv	%1, r1\n" 				\
-		: "=r"(ret), "=r"(x) 					\
-		: "0"(ptr)						\
-		: "r0", "r1", "r14" )
-#else /* MODULE */
-/*
- * Use "jl" instead of "bl" for MODULE
- */
-#define __get_user_x(size,ret,x,ptr) 					\
-	__asm__ __volatile__(						\
-		"	mv	r0, %0\n"				\
-		"	mv	r1, %1\n" 				\
-		"	seth	lr, #high(__get_user_" #size ")\n"	\
-		"	or3	lr, lr, #low(__get_user_" #size ")\n"	\
-		"	jl 	lr\n"					\
-		"	mv	%0, r0\n"				\
-		"	mv	%1, r1\n" 				\
-		: "=r"(ret), "=r"(x) 					\
-		: "0"(ptr)						\
-		: "r0", "r1", "r14" )
-#endif
-
 /* Careful: we have to cast the result to the type of the pointer for sign
    reasons */
 /**
@@ -208,20 +169,7 @@
  * On error, the variable @x is set to zero.
  */
 #define get_user(x,ptr)							\
-({	int __ret_gu;							\
-	unsigned long __val_gu;						\
-	__chk_user_ptr(ptr);						\
-	switch(sizeof (*(ptr))) {					\
-	case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;		\
-	case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;		\
-	case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;		\
-	default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;		\
-	}								\
-	(x) = (__typeof__(*(ptr)))__val_gu;				\
-	__ret_gu;							\
-})
-
-extern void __put_user_bad(void);
+	__get_user_check((x),(ptr),sizeof(*(ptr)))
 
 /**
  * put_user: - Write a simple value into user space.
@@ -240,8 +188,7 @@
  * Returns zero on success, or -EFAULT on error.
  */
 #define put_user(x,ptr)							\
-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-
+	__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /**
  * __get_user: - Get a simple variable from user space, with less checking.
@@ -264,8 +211,64 @@
  * On error, the variable @x is set to zero.
  */
 #define __get_user(x,ptr) \
-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+	__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
 
+#define __get_user_nocheck(x,ptr,size)					\
+({									\
+	long __gu_err = 0;						\
+	unsigned long __gu_val;						\
+	might_sleep();							\
+	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+#define __get_user_check(x,ptr,size)					\
+({									\
+	long __gu_err = -EFAULT;					\
+	unsigned long __gu_val = 0;					\
+	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
+	might_sleep();							\
+	if (access_ok(VERIFY_READ,__gu_addr,size))			\
+		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval)				\
+do {									\
+	retval = 0;							\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	  case 1: __get_user_asm(x,ptr,retval,"ub"); break;		\
+	  case 2: __get_user_asm(x,ptr,retval,"uh"); break;		\
+	  case 4: __get_user_asm(x,ptr,retval,""); break;		\
+	  default: (x) = __get_user_bad();				\
+	}								\
+} while (0)
+
+#define __get_user_asm(x, addr, err, itype)				\
+	__asm__ __volatile__(						\
+		"	.fillinsn\n"					\
+		"1:	ld"itype" %1,@%2\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	ldi %0,%3\n"					\
+		"	seth r14,#high(2b)\n"				\
+		"	or3 r14,r14,#low(2b)\n"				\
+		"	jmp r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 1b,3b\n"					\
+		".previous"						\
+		: "=&r" (err), "=&r" (x)				\
+		: "r" (addr), "i" (-EFAULT), "0" (err)			\
+		: "r14", "memory")
 
 /**
  * __put_user: - Write a simple value into user space, with less checking.
@@ -287,11 +290,13 @@
  * Returns zero on success, or -EFAULT on error.
  */
 #define __put_user(x,ptr) \
-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+	__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
 
 #define __put_user_nocheck(x,ptr,size)					\
 ({									\
 	long __pu_err;							\
+	might_sleep();							\
 	__put_user_size((x),(ptr),(size),__pu_err);			\
 	__pu_err;							\
 })
@@ -308,28 +313,28 @@
 })
 
 #if defined(__LITTLE_ENDIAN__)
-#define __put_user_u64(x, addr, err)                                    \
-        __asm__ __volatile__(                                           \
-                "       .fillinsn\n"                                    \
-                "1:     st %L1,@%2\n"                                    \
-                "       .fillinsn\n"                                    \
-                "2:     st %H1,@(4,%2)\n"                                \
-                "       .fillinsn\n"                                    \
-                "3:\n"                                                  \
-                ".section .fixup,\"ax\"\n"                              \
-                "       .balign 4\n"                                    \
-                "4:     ldi %0,%3\n"                                    \
-                "       seth r14,#high(3b)\n"                           \
-                "       or3 r14,r14,#low(3b)\n"                         \
-                "       jmp r14\n"                                      \
-                ".previous\n"                                           \
-                ".section __ex_table,\"a\"\n"                           \
-                "       .balign 4\n"                                    \
-                "       .long 1b,4b\n"                                  \
-                "       .long 2b,4b\n"                                  \
-                ".previous"                                             \
-                : "=&r"(err)                                             \
-                : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+#define __put_user_u64(x, addr, err)					\
+        __asm__ __volatile__(						\
+                "       .fillinsn\n"					\
+                "1:     st %L1,@%2\n"					\
+                "       .fillinsn\n"					\
+                "2:     st %H1,@(4,%2)\n"				\
+                "       .fillinsn\n"					\
+                "3:\n"							\
+                ".section .fixup,\"ax\"\n"				\
+                "       .balign 4\n"					\
+                "4:     ldi %0,%3\n"					\
+                "       seth r14,#high(3b)\n"				\
+                "       or3 r14,r14,#low(3b)\n"				\
+                "       jmp r14\n"					\
+                ".previous\n"						\
+                ".section __ex_table,\"a\"\n"				\
+                "       .balign 4\n"					\
+                "       .long 1b,4b\n"					\
+                "       .long 2b,4b\n"					\
+                ".previous"						\
+                : "=&r" (err)						\
+                : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
                 : "r14", "memory")
 
 #elif defined(__BIG_ENDIAN__)
@@ -353,13 +358,15 @@
 		"	.long 1b,4b\n"					\
 		"	.long 2b,4b\n"					\
 		".previous"						\
-		: "=&r"(err)						\
-		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
+		: "=&r" (err)						\
+		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
 		: "r14", "memory")
 #else
 #error no endian defined
 #endif
 
+extern void __put_user_bad(void);
+
 #define __put_user_size(x,ptr,size,retval)				\
 do {									\
 	retval = 0;							\
@@ -398,52 +405,8 @@
 		"	.balign 4\n"					\
 		"	.long 1b,3b\n"					\
 		".previous"						\
-		: "=&r"(err)						\
-		: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)		\
-		: "r14", "memory")
-
-#define __get_user_nocheck(x,ptr,size)					\
-({									\
-	long __gu_err;							\
-	unsigned long __gu_val;						\
-	__get_user_size(__gu_val,(ptr),(size),__gu_err);		\
-	(x) = (__typeof__(*(ptr)))__gu_val;				\
-	__gu_err;							\
-})
-
-extern long __get_user_bad(void);
-
-#define __get_user_size(x,ptr,size,retval)				\
-do {									\
-	retval = 0;							\
-	__chk_user_ptr(ptr);						\
-	switch (size) {							\
-	  case 1: __get_user_asm(x,ptr,retval,"ub"); break;		\
-	  case 2: __get_user_asm(x,ptr,retval,"uh"); break;		\
-	  case 4: __get_user_asm(x,ptr,retval,""); break;		\
-	  default: (x) = __get_user_bad();				\
-	}								\
-} while (0)
-
-#define __get_user_asm(x, addr, err, itype)				\
-	__asm__ __volatile__(						\
-		"	.fillinsn\n"					\
-		"1:	ld"itype" %1,@%2\n"				\
-		"	.fillinsn\n"					\
-		"2:\n"							\
-		".section .fixup,\"ax\"\n"				\
-		"	.balign 4\n"					\
-		"3:	ldi %0,%3\n"					\
-		"	seth r14,#high(2b)\n"				\
-		"	or3 r14,r14,#low(2b)\n"				\
-		"	jmp r14\n"					\
-		".previous\n"						\
-		".section __ex_table,\"a\"\n"				\
-		"	.balign 4\n"					\
-		"	.long 1b,3b\n"					\
-		".previous"						\
-		: "=&r"(err), "=&r"(x)					\
-		: "r"(addr), "i"(-EFAULT), "0"(err)			\
+		: "=&r" (err)						\
+		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)		\
 		: "r14", "memory")
 
 /*
@@ -453,7 +416,6 @@
  * anything, so this is accurate.
  */
 
-
 /*
  * Copy To/From Userspace
  */
@@ -511,8 +473,9 @@
 		"	.long 2b,9b\n"					\
 		"	.long 3b,9b\n"					\
 		".previous\n"						\
-		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
-		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
+		: "=&r" (__dst), "=&r" (__src), "=&r" (size),		\
+		  "=&r" (__c)						\
+		: "0" (to), "1" (from), "2" (size), "3" (size / 4)	\
 		: "r14", "memory");					\
 } while (0)
 
@@ -573,8 +536,9 @@
 		"	.long 2b,7b\n"					\
 		"	.long 3b,7b\n"					\
 		".previous\n"						\
-		: "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)	\
-		: "0"(to), "1"(from), "2"(size), "3"(size / 4)		\
+		: "=&r" (__dst), "=&r" (__src), "=&r" (size),		\
+		  "=&r" (__c)						\
+		: "0" (to), "1" (from), "2" (size), "3" (size / 4)	\
 		: "r14", "memory");					\
 } while (0)
 
@@ -676,7 +640,7 @@
 #define copy_from_user(to,from,n)			\
 ({							\
 	might_sleep();					\
-__generic_copy_from_user((to),(from),(n));	\
+	__generic_copy_from_user((to),(from),(n));	\
 })
 
 long __must_check strncpy_from_user(char *dst, const char __user *src,
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index 39be87c..be0eb01 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -292,7 +292,7 @@
 #define __NR_mq_timedreceive	(__NR_mq_open+3)
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 
 #define NR_syscalls 285
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 30b18ea..f54aa14 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -17,7 +17,26 @@
 #ifdef CONFIG_64BIT
 #include <asm/asmmacro-64.h>
 #endif
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	.macro	local_irq_enable reg=t0
+	mfc0	\reg, CP0_TCSTATUS
+	ori	\reg, \reg, TCSTATUS_IXMT
+	xori	\reg, \reg, TCSTATUS_IXMT
+	mtc0	\reg, CP0_TCSTATUS
+	ehb
+	.endm
+
+	.macro	local_irq_disable reg=t0
+	mfc0	\reg, CP0_TCSTATUS
+	ori	\reg, \reg, TCSTATUS_IXMT
+	mtc0	\reg, CP0_TCSTATUS
+	ehb
+	.endm
+#else
 	.macro	local_irq_enable reg=t0
 	mfc0	\reg, CP0_STATUS
 	ori	\reg, \reg, 1
@@ -32,6 +51,7 @@
 	mtc0	\reg, CP0_STATUS
 	irq_disable_hazard
 	.endm
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #ifdef CONFIG_CPU_SB1
 	.macro	fpu_enable_hazard
@@ -48,4 +68,31 @@
 	.endm
 #endif
 
+/*
+ * Temporary until all gas have MT ASE support
+ */
+	.macro	DMT	reg=0
+	.word	(0x41600bc1 | (\reg << 16))
+	.endm
+
+	.macro	EMT	reg=0
+	.word	(0x41600be1 | (\reg << 16))
+	.endm
+
+	.macro	DVPE	reg=0
+	.word	(0x41600001 | (\reg << 16))
+	.endm
+
+	.macro	EVPE	reg=0
+	.word	(0x41600021 | (\reg << 16))
+	.endm
+
+	.macro	MFTR	rt=0, rd=0, u=0, sel=0
+	 .word	(0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+	.endm
+
+	.macro	MTTR	rt=0, rd=0, u=0, sel=0
+	 .word	(0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index a1728f8..d2f4445 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -467,64 +467,56 @@
 }
 
 /*
+ * fls - find last bit set.
+ * @word: The word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+static inline int fls(int word)
+{
+	__asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
+
+	return 32 - word;
+}
+
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64)
+static inline int fls64(__u64 word)
+{
+	__asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
+
+	return 64 - word;
+}
+#else
+#include <asm-generic/bitops/fls64.h>
+#endif
+
+/*
  * ffs - find first bit set.
  * @word: The word to search
  *
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
  */
-
-static inline unsigned long ffs(unsigned long word)
+static inline int ffs(int word)
 {
 	if (!word)
 		return 0;
 
-	return __ffs(word) + 1;
-}
-
-/*
- * ffz - find first zero in word.
- * @word: The word to search
- *
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
-{
-	return __ffs (~word);
-}
-
-/*
- * fls - find last bit set.
- * @word: The word to search
- *
- * Returns 1..SZLONG
- * Returns 0 if no bit exists
- */
-static inline unsigned long fls(unsigned long word)
-{
-#ifdef CONFIG_CPU_MIPS32
-	__asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
-
-	return 32 - word;
-#endif
-
-#ifdef CONFIG_CPU_MIPS64
-	__asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
-
-	return 64 - word;
-#endif
+	return fls(word & -word);
 }
 
 #else
 
 #include <asm-generic/bitops/__ffs.h>
 #include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
 
 #endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
 
-#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 
 #ifdef __KERNEL__
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index aeae9fa..47bc8f6 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -74,6 +74,7 @@
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
 extern void (*flush_icache_all)(void);
+extern void (*local_flush_data_cache_page)(void * addr);
 extern void (*flush_data_cache_page)(unsigned long addr);
 
 /*
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 3f2b6d9..254e11e 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -40,7 +40,7 @@
 #define cpu_has_sb1_cache	(cpu_data[0].options & MIPS_CPU_SB1_CACHE)
 #endif
 #ifndef cpu_has_fpu
-#define cpu_has_fpu		(cpu_data[0].options & MIPS_CPU_FPU)
+#define cpu_has_fpu		(current_cpu_data.options & MIPS_CPU_FPU)
 #endif
 #ifndef cpu_has_32fpr
 #define cpu_has_32fpr		(cpu_data[0].options & MIPS_CPU_32FPR)
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 140be1c..6572ac7 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -73,6 +73,16 @@
 	struct cache_desc	dcache;	/* Primary D or combined I/D cache */
 	struct cache_desc	scache;	/* Secondary cache */
 	struct cache_desc	tcache;	/* Tertiary/split secondary cache */
+#if defined(CONFIG_MIPS_MT_SMTC)
+	/*
+	 * In the MIPS MT "SMTC" model, each TC is considered
+	 * to be a "CPU" for the purposes of scheduling, but
+	 * exception resources, ASID spaces, etc, are common
+	 * to all TCs within the same VPE.
+	 */
+	int			vpe_id;  /* Virtual Processor number */
+	int			tc_id;   /* Thread Context number */
+#endif /* CONFIG_MIPS_MT */
 	void 			*data;	/* Additional data */
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
diff --git a/include/asm-mips/ds1742.h b/include/asm-mips/ds1742.h
new file mode 100644
index 0000000..c2f2c32
--- /dev/null
+++ b/include/asm-mips/ds1742.h
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef _ASM_DS1742_H
+#define _ASM_DS1742_H
+
+#include <ds1742.h>
+
+#endif /* _ASM_DS1742_H */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 851f013..bdc9de2 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -119,8 +119,49 @@
 #define SHT_MIPS_CONFLICT	0x70000002
 #define SHT_MIPS_GPTAB		0x70000003
 #define SHT_MIPS_UCODE		0x70000004
+#define SHT_MIPS_DEBUG		0x70000005
+#define SHT_MIPS_REGINFO	0x70000006
+#define SHT_MIPS_PACKAGE	0x70000007
+#define SHT_MIPS_PACKSYM	0x70000008
+#define SHT_MIPS_RELD		0x70000009
+#define SHT_MIPS_IFACE		0x7000000b
+#define SHT_MIPS_CONTENT	0x7000000c
+#define SHT_MIPS_OPTIONS	0x7000000d
+#define SHT_MIPS_SHDR		0x70000010
+#define SHT_MIPS_FDESC		0x70000011
+#define SHT_MIPS_EXTSYM		0x70000012
+#define SHT_MIPS_DENSE		0x70000013
+#define SHT_MIPS_PDESC		0x70000014
+#define SHT_MIPS_LOCSYM		0x70000015
+#define SHT_MIPS_AUXSYM		0x70000016
+#define SHT_MIPS_OPTSYM		0x70000017
+#define SHT_MIPS_LOCSTR		0x70000018
+#define SHT_MIPS_LINE		0x70000019
+#define SHT_MIPS_RFDESC		0x7000001a
+#define SHT_MIPS_DELTASYM	0x7000001b
+#define SHT_MIPS_DELTAINST	0x7000001c
+#define SHT_MIPS_DELTACLASS	0x7000001d
+#define SHT_MIPS_DWARF		0x7000001e
+#define SHT_MIPS_DELTADECL	0x7000001f
+#define SHT_MIPS_SYMBOL_LIB	0x70000020
+#define SHT_MIPS_EVENTS		0x70000021
+#define SHT_MIPS_TRANSLATE	0x70000022
+#define SHT_MIPS_PIXIE		0x70000023
+#define SHT_MIPS_XLATE		0x70000024
+#define SHT_MIPS_XLATE_DEBUG	0x70000025
+#define SHT_MIPS_WHIRL		0x70000026
+#define SHT_MIPS_EH_REGION	0x70000027
+#define SHT_MIPS_XLATE_OLD	0x70000028
+#define SHT_MIPS_PDR_EXCEPTION	0x70000029
 
-#define SHF_MIPS_GPREL	0x10000000
+#define SHF_MIPS_GPREL		0x10000000
+#define SHF_MIPS_MERGE		0x20000000
+#define SHF_MIPS_ADDR		0x40000000
+#define SHF_MIPS_STRING		0x80000000
+#define SHF_MIPS_NOSTRIP	0x08000000
+#define SHF_MIPS_LOCAL		0x04000000
+#define SHF_MIPS_NAMES		0x02000000
+#define SHF_MIPS_NODUPES	0x01000000
 
 #ifndef ELF_ARCH
 /* ELF register definitions */
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index 9c828b1..b0f5001 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -21,6 +21,10 @@
 #include <asm/processor.h>
 #include <asm/current.h>
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+#include <asm/mips_mt.h>
+#endif
+
 struct sigcontext;
 struct sigcontext32;
 
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index feb29a7..dadc051 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -284,6 +284,8 @@
 #define instruction_hazard() do { } while (0)
 #endif
 
+extern void mips_ihb(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_HAZARDS_H */
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index 7743487..4bb9c06 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -19,7 +19,12 @@
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+	"	mfc0	$1, $2, 1	# SMTC - clear TCStatus.IXMT	\n"
+	"	ori	$1, 0x400					\n"
+	"	xori	$1, 0x400					\n"
+	"	mtc0	$1, $2, 1					\n"
+#elif defined(CONFIG_CPU_MIPSR2)
 	"	ei							\n"
 #else
 	"	mfc0	$1,$12						\n"
@@ -62,7 +67,12 @@
 	"	.macro	local_irq_disable\n"
 	"	.set	push						\n"
 	"	.set	noat						\n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+	"	mfc0	$1, $2, 1					\n"
+	"	ori	$1, 0x400					\n"
+	"	.set	noreorder					\n"
+	"	mtc0	$1, $2, 1					\n"
+#elif defined(CONFIG_CPU_MIPSR2)
 	"	di							\n"
 #else
 	"	mfc0	$1,$12						\n"
@@ -88,7 +98,11 @@
 	"	.macro	local_save_flags flags				\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
+#ifdef CONFIG_MIPS_MT_SMTC
+	"	mfc0	\\flags, $2, 1					\n"
+#else
 	"	mfc0	\\flags, $12					\n"
+#endif
 	"	.set	pop						\n"
 	"	.endm							\n");
 
@@ -102,7 +116,13 @@
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+	"	mfc0	\\result, $2, 1					\n"
+	"	ori	$1, \\result, 0x400				\n"
+	"	.set	noreorder					\n"
+	"	mtc0	$1, $2, 1					\n"
+	"	andi	\\result, \\result, 0x400			\n"
+#elif defined(CONFIG_CPU_MIPSR2)
 	"	di	\\result					\n"
 	"	andi	\\result, 1					\n"
 #else
@@ -128,7 +148,14 @@
 	"	.set	push						\n"
 	"	.set	noreorder					\n"
 	"	.set	noat						\n"
-#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#ifdef CONFIG_MIPS_MT_SMTC
+	"mfc0	$1, $2, 1						\n"
+	"andi	\\flags, 0x400						\n"
+	"ori	$1, 0x400						\n"
+	"xori	$1, 0x400						\n"
+	"or	\\flags, $1						\n"
+	"mtc0	\\flags, $2, 1						\n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
 	/*
 	 * Slow, but doesn't suffer from a relativly unlikely race
 	 * condition we're having since days 1.
@@ -167,11 +194,29 @@
 		: "memory");						\
 } while(0)
 
-#define irqs_disabled()							\
-({									\
-	unsigned long flags;						\
-	local_save_flags(flags);					\
-	!(flags & 1);							\
-})
+static inline int irqs_disabled(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
+	 */
+	unsigned long __result;
+
+	__asm__ __volatile__(
+	"	.set	noreorder					\n"
+	"	mfc0	%0, $2, 1					\n"
+	"	andi	%0, 0x400					\n"
+	"	slt	%0, $0, %0					\n"
+	"	.set	reorder						\n"
+	: "=r" (__result));
+
+	return __result;
+#else
+	unsigned long flags;
+	local_save_flags(flags);
+
+	return !(flags & 1);
+#endif
+}
 
 #endif /* _ASM_INTERRUPT_H */
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 8a342cc..dde677f 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -11,6 +11,9 @@
 
 #include <linux/config.h>
 #include <linux/linkage.h>
+
+#include <asm/mipsmtregs.h>
+
 #include <irq.h>
 
 #ifdef CONFIG_I8259
@@ -26,6 +29,23 @@
 
 extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
 
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Clear interrupt mask handling "backstop" if irq_hwmask
+ * entry so indicates. This implies that the ack() or end()
+ * functions will take over re-enabling the low-level mask.
+ * Otherwise it will be done on return from exception.
+ */
+#define __DO_IRQ_SMTC_HOOK()						\
+do {									\
+	if (irq_hwmask[irq] & 0x0000ff00)				\
+		write_c0_tccontext(read_c0_tccontext() &		\
+		                   ~(irq_hwmask[irq] & 0x0000ff00));	\
+} while (0)
+#else
+#define __DO_IRQ_SMTC_HOOK() do { } while (0)
+#endif
+
 #ifdef CONFIG_PREEMPT
 
 /*
@@ -39,6 +59,7 @@
 #define do_IRQ(irq, regs)						\
 do {									\
 	irq_enter();							\
+	__DO_IRQ_SMTC_HOOK();						\
 	__do_IRQ((irq), (regs));					\
 	irq_exit();							\
 } while (0)
@@ -46,5 +67,14 @@
 #endif
 
 extern void arch_init_irq(void);
+extern void spurious_interrupt(struct pt_regs *regs);
+
+#ifdef CONFIG_MIPS_MT_SMTC
+struct irqaction;
+
+extern unsigned long irq_hwmask[];
+extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+                          unsigned long hwmask);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/kspd.h b/include/asm-mips/kspd.h
new file mode 100644
index 0000000..4e9e724
--- /dev/null
+++ b/include/asm-mips/kspd.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _ASM_KSPD_H
+#define _ASM_KSPD_H
+
+struct kspd_notifications {
+	void (*kspd_sp_exit)(int sp_id);
+
+	struct list_head list;
+};
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+extern void kspd_notify(struct kspd_notifications *notify);
+#else
+static inline void kspd_notify(struct kspd_notifications *notify)
+{
+}
+#endif
+
+#endif
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index 550979a..e331535 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -104,65 +104,107 @@
 #endif
 
 /* MIPS port and memory-mapped I/O string operations.  */
+static inline void __ide_flush_prologue(void)
+{
+#ifdef CONFIG_SMP
+	if (cpu_has_dc_aliases)
+		preempt_disable();
+#endif
+}
+
+static inline void __ide_flush_epilogue(void)
+{
+#ifdef CONFIG_SMP
+	if (cpu_has_dc_aliases)
+		preempt_enable();
+#endif
+}
 
 static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
 {
 	if (cpu_has_dc_aliases) {
 		unsigned long end = addr + size;
-		for (; addr < end; addr += PAGE_SIZE)
-			flush_dcache_page(virt_to_page(addr));
+
+		while (addr < end) {
+			local_flush_data_cache_page((void *)addr);
+			addr += PAGE_SIZE;
+		}
 	}
 }
 
+/*
+ * insw() and gang might be called with interrupts disabled, so we can't
+ * send IPIs for flushing due to the potencial of deadlocks, see the comment
+ * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
+ * problem by disabling preemption so we know we actually perform the flush
+ * on the processor that actually has the lines to be flushed which hopefully
+ * is even better for performance anyway.
+ */
 static inline void __ide_insw(unsigned long port, void *addr,
 	unsigned int count)
 {
+	__ide_flush_prologue();
 	insw(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
 {
+	__ide_flush_prologue();
 	insl(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_outsw(unsigned long port, const void *addr,
 	unsigned long count)
 {
+	__ide_flush_prologue();
 	outsw(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_outsl(unsigned long port, const void *addr,
 	unsigned long count)
 {
+	__ide_flush_prologue();
 	outsl(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
+	__ide_flush_prologue();
 	readsw(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
+	__ide_flush_prologue();
 	readsl(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
+	__ide_flush_prologue();
 	writesw(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 2);
+	__ide_flush_epilogue();
 }
 
 static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
+	__ide_flush_prologue();
 	writesl(port, addr, count);
 	__ide_flush_dcache_range((unsigned long)addr, count * 4);
+	__ide_flush_epilogue();
 }
 
 /* ide_insw calls insw, not __ide_insw.  Why? */
diff --git a/include/asm-mips/mach-jmr3927/ds1742.h b/include/asm-mips/mach-jmr3927/ds1742.h
index cff6192..8a8fef6 100644
--- a/include/asm-mips/mach-jmr3927/ds1742.h
+++ b/include/asm-mips/mach-jmr3927/ds1742.h
@@ -3,14 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003 by Ralf Baechle
+ * Copyright (C) 2003, 06 by Ralf Baechle
  */
 #ifndef __ASM_MACH_JMR3927_DS1742_H
 #define __ASM_MACH_JMR3927_DS1742_H
 
 #include <asm/jmr3927/jmr3927.h>
 
-#define rtc_read(reg)		(jmr3927_nvram_in(addr))
+#define rtc_read(reg)		(jmr3927_nvram_in(reg))
 #define rtc_write(data, reg)	(jmr3927_nvram_out((data),(reg)))
 
 #endif /* __ASM_MACH_JMR3927_DS1742_H */
diff --git a/include/asm-mips/mach-mips/param.h b/include/asm-mips/mach-mips/param.h
new file mode 100644
index 0000000..805ef6d
--- /dev/null
+++ b/include/asm-mips/mach-mips/param.h
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_PARAM_H
+#define __ASM_MACH_MIPS_PARAM_H
+
+#define HZ		100		/* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_MIPS_PARAM_H */
diff --git a/include/asm-mips/marvell.h b/include/asm-mips/marvell.h
index 9225b33..6bb2125 100644
--- a/include/asm-mips/marvell.h
+++ b/include/asm-mips/marvell.h
@@ -53,4 +53,6 @@
 	unsigned long   config_vreg;
 };
 
+extern void ll_mv64340_irq(struct pt_regs *regs);
+
 #endif	/* __ASM_MIPS_MARVELL_H */
diff --git a/include/asm-mips/mips-boards/atlas.h b/include/asm-mips/mips-boards/atlas.h
index 0998151..a8ae12d 100644
--- a/include/asm-mips/mips-boards/atlas.h
+++ b/include/asm-mips/mips-boards/atlas.h
@@ -33,13 +33,29 @@
 #define ATLAS_RTC_ADR_REG       0x1f000800
 #define ATLAS_RTC_DAT_REG       0x1f000808
 
-
 /*
  * Atlas interrupt controller register base.
  */
 #define ATLAS_ICTRL_REGS_BASE   0x1f000000
 
 /*
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and
+ * only word access are allowed.
+ */
+struct atlas_ictrl_regs {
+	volatile unsigned int intraw;
+	int dummy1;
+	volatile unsigned int intseten;
+	int dummy2;
+	volatile unsigned int intrsten;
+	int dummy3;
+	volatile unsigned int intenable;
+	int dummy4;
+	volatile unsigned int intstatus;
+	int dummy5;
+};
+
+/*
  * Atlas UART register base.
  */
 #define ATLAS_UART_REGS_BASE    0x1f000900
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index bba35c1..fd7ebc5 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -62,23 +62,4 @@
 #define ATLASINT_RES31		(ATLASINT_BASE+31)
 #define ATLASINT_END		(ATLASINT_BASE+31)
 
-/*
- * Atlas registers are memory mapped on 64-bit aligned boundaries and
- * only word access are allowed.
- */
-struct atlas_ictrl_regs {
-        volatile unsigned int intraw;
-        int dummy1;
-        volatile unsigned int intseten;
-        int dummy2;
-        volatile unsigned int intrsten;
-        int dummy3;
-        volatile unsigned int intenable;
-        int dummy4;
-        volatile unsigned int intstatus;
-        int dummy5;
-};
-
-extern void atlasint_init(void);
-
 #endif /* !(_MIPS_ATLASINT_H) */
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index 25b6ffc..fa8b913 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -67,6 +67,7 @@
 #define MIPS_REVISION_CORID_CORE_FPGA2     7
 #define MIPS_REVISION_CORID_CORE_FPGAR2    8
 #define MIPS_REVISION_CORID_CORE_FPGA3     9
+#define MIPS_REVISION_CORID_CORE_24K       10
 
 /**** Artificial corid defines ****/
 /*
diff --git a/include/asm-mips/mips_mt.h b/include/asm-mips/mips_mt.h
new file mode 100644
index 0000000..c31a312
--- /dev/null
+++ b/include/asm-mips/mips_mt.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions and decalrations for MIPS MT support
+ * that are common between SMTC, VSMP, and/or AP/SP
+ * kernel models.
+ */
+#ifndef __ASM_MIPS_MT_H
+#define __ASM_MIPS_MT_H
+
+extern cpumask_t mt_fpu_cpumask;
+extern unsigned long mt_fpemul_threshold;
+
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
+extern void mips_mt_set_cpuoptions(void);
+
+#endif /* __ASM_MIPS_MT_H */
diff --git a/include/asm-mips/mipsmtregs.h b/include/asm-mips/mipsmtregs.h
index a669c07..f637ce7 100644
--- a/include/asm-mips/mipsmtregs.h
+++ b/include/asm-mips/mipsmtregs.h
@@ -165,7 +165,7 @@
 
 #ifndef __ASSEMBLY__
 
-extern void mips_mt_regdump(void);
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
 
 static inline unsigned int dvpe(void)
 {
@@ -234,7 +234,7 @@
 	__asm__ __volatile__(
 	"	.set	noreorder					\n"
 	"	.set	mips32r2					\n"
-	"	emt							\n"
+	"	.word	0x41600be1			# emt		\n"
 	"	ehb							\n"
 	"	.set	mips0						\n"
 	"	.set	reorder");
@@ -282,8 +282,11 @@
 									\
 	__asm__ __volatile__(						\
 	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
 	"	.set	mips32r2				\n"	\
-	"	mftgpr	%0," #rt "				\n"	\
+	"	# mftgpr $1," #rt "				\n"	\
+	"	.word	0x41000820 | (" #rt " << 16)		\n"	\
+	"	move	%0, $1					\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 									\
@@ -295,9 +298,7 @@
 	unsigned long __res;						\
 									\
 	__asm__ __volatile__(						\
-	".set noat\n\t"							\
-	"mftr\t%0, " #rt ", " #u ", " #sel "\n\t"			\
-	".set at\n\t"							\
+	"	mftr	%0, " #rt ", " #u ", " #sel "		\n"	\
 	: "=r" (__res));						\
 									\
 	__res;								\
@@ -364,6 +365,9 @@
 #define read_vpe_c0_ebase()		mftc0(15,1)
 #define write_vpe_c0_ebase(val)		mttc0(15, 1, val)
 #define write_vpe_c0_compare(val)	mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr()		mftc0(8, 0)
+#define read_vpe_c0_epc()		mftc0(14, 0)
+#define write_vpe_c0_epc(val)		mttc0(14, 0, val)
 
 
 /* TC */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 035ba0a..a2ef579 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -836,6 +836,9 @@
 #define read_c0_cache()		__read_32bit_c0_register($7, 0)	/* TX39xx */
 #define write_c0_cache(val)	__write_32bit_c0_register($7, 0, val)
 
+#define read_c0_badvaddr()	__read_ulong_c0_register($8, 0)
+#define write_c0_badvaddr(val)	__write_ulong_c0_register($8, 0, val)
+
 #define read_c0_count()		__read_32bit_c0_register($9, 0)
 #define write_c0_count(val)	__write_32bit_c0_register($9, 0, val)
 
@@ -858,7 +861,19 @@
 #define write_c0_compare3(val)	__write_32bit_c0_register($11, 7, val)
 
 #define read_c0_status()	__read_32bit_c0_register($12, 0)
+#ifdef CONFIG_MIPS_MT_SMTC
+#define write_c0_status(val)						\
+do {									\
+	__write_32bit_c0_register($12, 0, val);				\
+	__ehb();							\
+} while (0)
+#else
+/*
+ * Legacy non-SMTC code, which may be hazardous
+ * but which might not support EHB
+ */
 #define write_c0_status(val)	__write_32bit_c0_register($12, 0, val)
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #define read_c0_cause()		__read_32bit_c0_register($13, 0)
 #define write_c0_cause(val)	__write_32bit_c0_register($13, 0, val)
@@ -1001,6 +1016,9 @@
 #define read_c0_taglo()		__read_32bit_c0_register($28, 0)
 #define write_c0_taglo(val)	__write_32bit_c0_register($28, 0, val)
 
+#define read_c0_dtaglo()	__read_32bit_c0_register($28, 2)
+#define write_c0_dtaglo(val)	__write_32bit_c0_register($28, 2, val)
+
 #define read_c0_taghi()		__read_32bit_c0_register($29, 0)
 #define write_c0_taghi(val)	__write_32bit_c0_register($29, 0, val)
 
@@ -1354,6 +1372,11 @@
 /*
  * Manipulate bits in a c0 register.
  */
+#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Linux requires shutting-down microthread scheduling
+ * during CP0 register read-modify-write sequences.
+ */
 #define __BUILD_SET_C0(name)					\
 static inline unsigned int					\
 set_c0_##name(unsigned int set)					\
@@ -1392,6 +1415,119 @@
 	return res;						\
 }
 
+#else /* SMTC versions that manage MT scheduling */
+
+#include <asm/interrupt.h>
+
+/*
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
+ * header file recursion.
+ */
+static inline unsigned int __dmt(void)
+{
+	int res;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	mips32r2					\n"
+	"	.set	noat						\n"
+	"	.word	0x41610BC1			# dmt $1	\n"
+	"	ehb							\n"
+	"	move	%0, $1						\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+#define __VPECONTROL_TE_SHIFT	15
+#define __VPECONTROL_TE		(1UL << __VPECONTROL_TE_SHIFT)
+
+#define __EMT_ENABLE		__VPECONTROL_TE
+
+static inline void __emt(unsigned int previous)
+{
+	if ((previous & __EMT_ENABLE))
+		__asm__ __volatile__(
+		"	.set	noreorder				\n"
+		"	.set	mips32r2				\n"
+		"	.word	0x41600be1		# emt		\n"
+		"	ehb						\n"
+		"	.set	mips0					\n"
+		"	.set	reorder					\n");
+}
+
+static inline void __ehb(void)
+{
+	__asm__ __volatile__(
+	"	ehb							\n");
+}
+
+/*
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
+ * not Status.IE as in non-SMTC kernel.
+ */
+
+#define __BUILD_SET_C0(name)					\
+static inline unsigned int					\
+set_c0_##name(unsigned int set)					\
+{								\
+	unsigned int res;					\
+	unsigned int omt;					\
+	unsigned int flags;					\
+								\
+	local_irq_save(flags);					\
+	omt = __dmt();						\
+	res = read_c0_##name();					\
+	res |= set;						\
+	write_c0_##name(res);					\
+	__emt(omt);						\
+	local_irq_restore(flags);				\
+								\
+	return res;						\
+}								\
+								\
+static inline unsigned int					\
+clear_c0_##name(unsigned int clear)				\
+{								\
+	unsigned int res;					\
+	unsigned int omt;					\
+	unsigned int flags;					\
+								\
+	local_irq_save(flags);					\
+	omt = __dmt();						\
+	res = read_c0_##name();					\
+	res &= ~clear;						\
+	write_c0_##name(res);					\
+	__emt(omt);						\
+	local_irq_restore(flags);				\
+								\
+	return res;						\
+}								\
+								\
+static inline unsigned int					\
+change_c0_##name(unsigned int change, unsigned int new)		\
+{								\
+	unsigned int res;					\
+	unsigned int omt;					\
+	unsigned int flags;					\
+								\
+	local_irq_save(flags);					\
+								\
+	omt = __dmt();						\
+	res = read_c0_##name();					\
+	res &= ~change;						\
+	res |= (new & change);					\
+	write_c0_##name(res);					\
+	__emt(omt);						\
+	local_irq_restore(flags);				\
+								\
+	return res;						\
+}
+#endif
+
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 61cf225..6e09f4c 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -17,6 +17,10 @@
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#include <asm/smtc.h>
+#endif /* SMTC */
 
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -54,6 +58,14 @@
 #define ASID_INC	0x1
 #define ASID_MASK	0xfff
 
+/* SMTC/34K debug hack - but maybe we'll keep it */
+#elif defined(CONFIG_MIPS_MT_SMTC)
+
+#define ASID_INC	0x1
+extern unsigned long smtc_asid_mask;
+#define ASID_MASK	(smtc_asid_mask)
+#define	HW_ASID_MASK	0xff
+/* End SMTC/34K debug hack */
 #else /* FIXME: not correct for R6000 */
 
 #define ASID_INC	0x1
@@ -76,6 +88,8 @@
 #define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
 #define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
 
+#ifndef CONFIG_MIPS_MT_SMTC
+/* Normal, classic MIPS get_new_mmu_context */
 static inline void
 get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
 {
@@ -91,6 +105,12 @@
 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
+#else /* CONFIG_MIPS_MT_SMTC */
+
+#define get_new_mmu_context(mm,cpu) smtc_get_new_mmu_context((mm),(cpu))
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 /*
  * Initialize the context related info for a new mm_struct
  * instance.
@@ -111,14 +131,46 @@
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned long flags;
-
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long oldasid;
+	unsigned long mtflags;
+	int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
 	local_irq_save(flags);
+	mtflags = dvpe();
+#else /* Not SMTC */
+	local_irq_save(flags);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	/* Check if our ASID is of an older version and thus invalid */
 	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
 		get_new_mmu_context(next, cpu);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+	/*
+	 * If the EntryHi ASID being replaced happens to be
+	 * the value flagged at ASID recycling time as having
+	 * an extended life, clear the bit showing it being
+	 * in use by this "CPU", and if that's the last bit,
+	 * free up the ASID value for use and flush any old
+	 * instances of it from the TLB.
+	 */
+	oldasid = (read_c0_entryhi() & ASID_MASK);
+	if(smtc_live_asid[mytlb][oldasid]) {
+		smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+		if(smtc_live_asid[mytlb][oldasid] == 0)
+			smtc_flush_tlb_asid(oldasid);
+	}
+	/*
+	 * Tread softly on EntryHi, and so long as we support
+	 * having ASID_MASK smaller than the hardware maximum,
+	 * make sure no "soft" bits become "hard"...
+	 */
+	write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+			| (cpu_context(cpu, next) & ASID_MASK));
+	ehb(); /* Make sure it propagates to TCStatus */
+	evpe(mtflags);
+#else
 	write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
 	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
 	/*
@@ -151,12 +203,34 @@
 	unsigned long flags;
 	unsigned int cpu = smp_processor_id();
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long oldasid;
+	unsigned long mtflags;
+	int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 	local_irq_save(flags);
 
 	/* Unconditionally get a new ASID.  */
 	get_new_mmu_context(next, cpu);
 
+#ifdef CONFIG_MIPS_MT_SMTC
+	/* See comments for similar code above */
+	mtflags = dvpe();
+	oldasid = read_c0_entryhi() & ASID_MASK;
+	if(smtc_live_asid[mytlb][oldasid]) {
+		smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+       		if(smtc_live_asid[mytlb][oldasid] == 0)
+               		 smtc_flush_tlb_asid(oldasid);
+	}
+	/* See comments for similar code above */
+	write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+	                 (cpu_context(cpu, next) & ASID_MASK));
+	ehb(); /* Make sure it propagates to TCStatus */
+	evpe(mtflags);
+#else
 	write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
 	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
 	/* mark mmu ownership change */
@@ -174,17 +248,49 @@
 drop_mmu_context(struct mm_struct *mm, unsigned cpu)
 {
 	unsigned long flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long oldasid;
+	/* Can't use spinlock because called from TLB flush within DVPE */
+	unsigned int prevvpe;
+	int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 	local_irq_save(flags);
 
 	if (cpu_isset(cpu, mm->cpu_vm_mask))  {
 		get_new_mmu_context(mm, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+		/* See comments for similar code above */
+		prevvpe = dvpe();
+		oldasid = (read_c0_entryhi() & ASID_MASK);
+		if(smtc_live_asid[mytlb][oldasid]) {
+		  smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+		  if(smtc_live_asid[mytlb][oldasid] == 0)
+			smtc_flush_tlb_asid(oldasid);
+		}
+		/* See comments for similar code above */
+		write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+				| cpu_asid(cpu, mm));
+		ehb(); /* Make sure it propagates to TCStatus */
+		evpe(prevvpe);
+#else /* not CONFIG_MIPS_MT_SMTC */
 		write_c0_entryhi(cpu_asid(cpu, mm));
+#endif /* CONFIG_MIPS_MT_SMTC */
 	} else {
 		/* will get a new context next time */
+#ifndef CONFIG_MIPS_MT_SMTC
 		cpu_context(cpu, mm) = 0;
-	}
+#else /* SMTC */
+		int i;
 
+		/* SMTC shares the TLB (and ASIDs) across VPEs */
+		for (i = 0; i < num_online_cpus(); i++) {
+	    	    if((smtc_status & SMTC_TLB_SHARED)
+	    	    || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+			cpu_context(i, mm) = 0;
+		}
+#endif /* CONFIG_MIPS_MT_SMTC */
+	}
 	local_irq_restore(flags);
 }
 
diff --git a/include/asm-mips/numnodes.h b/include/asm-mips/numnodes.h
deleted file mode 100644
index 4f00c16..0000000
--- a/include/asm-mips/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 128 Nodes */
-#define NODES_SHIFT	6
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 39d2bd5..0fb75f0 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -12,6 +12,7 @@
 #define _ASM_PROCESSOR_H
 
 #include <linux/config.h>
+#include <linux/cpumask.h>
 #include <linux/threads.h>
 
 #include <asm/cachectl.h>
@@ -107,6 +108,10 @@
 
 #define INIT_DSP {{0,},}
 
+#define INIT_CPUMASK { \
+	{0,} \
+}
+
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
@@ -129,6 +134,12 @@
 
 	/* Saved fpu/fpu emulator stuff. */
 	union mips_fpu_union fpu;
+#ifdef CONFIG_MIPS_MT_FPAFF
+	/* Emulated instruction count */
+	unsigned long emulated_fp;
+	/* Saved per-thread scheduler affinity mask */
+	cpumask_t user_cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
 
 	/* Saved state of the DSP ASE, if available. */
 	struct mips_dsp_state dsp;
@@ -142,6 +153,7 @@
 #define MF_LOGADE	2		/* Log address errors to syslog */
 #define MF_32BIT_REGS	4		/* also implies 16/32 fprs */
 #define MF_32BIT_ADDR	8		/* 32-bit address space (o32/n32) */
+#define MF_FPUBOUND	0x10		/* thread bound to FPU-full CPU set */
 	unsigned long mflags;
 	unsigned long irix_trampoline;  /* Wheee... */
 	unsigned long irix_oldctx;
@@ -153,6 +165,12 @@
 #define MF_N32		MF_32BIT_ADDR
 #define MF_N64		0
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+#define FPAFF_INIT 0, INIT_CPUMASK,
+#else
+#define FPAFF_INIT
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
 #define INIT_THREAD  { \
         /* \
          * saved main processor registers \
@@ -168,6 +186,10 @@
 	 */ \
 	INIT_FPU, \
 	/* \
+	 * fpu affinity state (null if not FPAFF) \
+	 */ \
+	FPAFF_INIT \
+	/* \
 	 * saved dsp/dsp emulator stuff \
 	 */ \
 	INIT_DSP, \
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 95c5839..fa9d871 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -45,6 +45,10 @@
 	unsigned long cp0_badvaddr;
 	unsigned long cp0_cause;
 	unsigned long cp0_epc;
+#ifdef CONFIG_MIPS_MT_SMTC
+	unsigned long cp0_tcstatus;
+	unsigned long smtc_pad;
+#endif /* CONFIG_MIPS_MT_SMTC */
 };
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index 90c3747..3c8e3c8 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -15,6 +15,7 @@
 #include <asm/asm.h>
 #include <asm/cacheops.h>
 #include <asm/cpu-features.h>
+#include <asm/mipsmtregs.h>
 
 /*
  * This macro return a properly sign-extended address suitable as base address
@@ -37,16 +38,120 @@
 	"	cache	%0, %1					\n"	\
 	"	.set	pop					\n"	\
 	:								\
-	: "i" (op), "m" (*(unsigned char *)(addr)))
+	: "i" (op), "R" (*(unsigned char *)(addr)))
+
+#ifdef CONFIG_MIPS_MT
+/*
+ * Temporary hacks for SMTC debug. Optionally force single-threaded
+ * execution during I-cache flushes.
+ */
+
+#define PROTECT_CACHE_FLUSHES 1
+
+#ifdef PROTECT_CACHE_FLUSHES
+
+extern int mt_protiflush;
+extern int mt_protdflush;
+extern void mt_cflush_lockdown(void);
+extern void mt_cflush_release(void);
+
+#define BEGIN_MT_IPROT \
+	unsigned long flags = 0;			\
+	unsigned long mtflags = 0;			\
+	if(mt_protiflush) {				\
+		local_irq_save(flags);			\
+		ehb();					\
+		mtflags = dvpe();			\
+		mt_cflush_lockdown();			\
+	}
+
+#define END_MT_IPROT \
+	if(mt_protiflush) {				\
+		mt_cflush_release();			\
+		evpe(mtflags);				\
+		local_irq_restore(flags);		\
+	}
+
+#define BEGIN_MT_DPROT \
+	unsigned long flags = 0;			\
+	unsigned long mtflags = 0;			\
+	if(mt_protdflush) {				\
+		local_irq_save(flags);			\
+		ehb();					\
+		mtflags = dvpe();			\
+		mt_cflush_lockdown();			\
+	}
+
+#define END_MT_DPROT \
+	if(mt_protdflush) {				\
+		mt_cflush_release();			\
+		evpe(mtflags);				\
+		local_irq_restore(flags);		\
+	}
+
+#else
+
+#define BEGIN_MT_IPROT
+#define BEGIN_MT_DPROT
+#define END_MT_IPROT
+#define END_MT_DPROT
+
+#endif /* PROTECT_CACHE_FLUSHES */
+
+#define __iflush_prologue						\
+	unsigned long redundance;					\
+	extern int mt_n_iflushes;					\
+	BEGIN_MT_IPROT							\
+	for (redundance = 0; redundance < mt_n_iflushes; redundance++) {
+
+#define __iflush_epilogue						\
+	END_MT_IPROT							\
+	}
+
+#define __dflush_prologue						\
+	unsigned long redundance;					\
+	extern int mt_n_dflushes;					\
+	BEGIN_MT_DPROT							\
+	for (redundance = 0; redundance < mt_n_dflushes; redundance++) {
+
+#define __dflush_epilogue \
+	END_MT_DPROT	 \
+	}
+
+#define __inv_dflush_prologue __dflush_prologue
+#define __inv_dflush_epilogue __dflush_epilogue
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue __sflush_prologue
+#define __inv_sflush_epilogue __sflush_epilogue
+
+#else /* CONFIG_MIPS_MT */
+
+#define __iflush_prologue {
+#define __iflush_epilogue }
+#define __dflush_prologue {
+#define __dflush_epilogue }
+#define __inv_dflush_prologue {
+#define __inv_dflush_epilogue }
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue {
+#define __inv_sflush_epilogue }
+
+#endif /* CONFIG_MIPS_MT */
 
 static inline void flush_icache_line_indexed(unsigned long addr)
 {
+	__iflush_prologue
 	cache_op(Index_Invalidate_I, addr);
+	__iflush_epilogue
 }
 
 static inline void flush_dcache_line_indexed(unsigned long addr)
 {
+	__dflush_prologue
 	cache_op(Index_Writeback_Inv_D, addr);
+	__dflush_epilogue
 }
 
 static inline void flush_scache_line_indexed(unsigned long addr)
@@ -56,17 +161,23 @@
 
 static inline void flush_icache_line(unsigned long addr)
 {
+	__iflush_prologue
 	cache_op(Hit_Invalidate_I, addr);
+	__iflush_epilogue
 }
 
 static inline void flush_dcache_line(unsigned long addr)
 {
+	__dflush_prologue
 	cache_op(Hit_Writeback_Inv_D, addr);
+	__dflush_epilogue
 }
 
 static inline void invalidate_dcache_line(unsigned long addr)
 {
+	__dflush_prologue
 	cache_op(Hit_Invalidate_D, addr);
+	__dflush_epilogue
 }
 
 static inline void invalidate_scache_line(unsigned long addr)
@@ -239,9 +350,13 @@
 	                       current_cpu_data.desc.waybit;		\
 	unsigned long ws, addr;						\
 									\
+	__##pfx##flush_prologue						\
+									\
 	for (ws = 0; ws < ws_end; ws += ws_inc)				\
 		for (addr = start; addr < end; addr += lsize * 32)	\
 			cache##lsize##_unroll32(addr|ws,indexop);	\
+									\
+	__##pfx##flush_epilogue						\
 }									\
 									\
 static inline void blast_##pfx##cache##lsize##_page(unsigned long page)	\
@@ -249,10 +364,14 @@
 	unsigned long start = page;					\
 	unsigned long end = page + PAGE_SIZE;				\
 									\
+	__##pfx##flush_prologue						\
+									\
 	do {								\
 		cache##lsize##_unroll32(start,hitop);			\
 		start += lsize * 32;					\
 	} while (start < end);						\
+									\
+	__##pfx##flush_epilogue						\
 }									\
 									\
 static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
@@ -265,9 +384,13 @@
 	                       current_cpu_data.desc.waybit;		\
 	unsigned long ws, addr;						\
 									\
+	__##pfx##flush_prologue						\
+									\
 	for (ws = 0; ws < ws_end; ws += ws_inc)				\
 		for (addr = start; addr < end; addr += lsize * 32)	\
 			cache##lsize##_unroll32(addr|ws,indexop);	\
+									\
+	__##pfx##flush_epilogue						\
 }
 
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
@@ -288,12 +411,17 @@
 	unsigned long lsize = cpu_##desc##_line_size();			\
 	unsigned long addr = start & ~(lsize - 1);			\
 	unsigned long aend = (end - 1) & ~(lsize - 1);			\
+									\
+	__##pfx##flush_prologue						\
+									\
 	while (1) {							\
 		prot##cache_op(hitop, addr);				\
 		if (addr == aend)					\
 			break;						\
 		addr += lsize;						\
 	}								\
+									\
+	__##pfx##flush_epilogue						\
 }
 
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
index a2abc45..82ad401 100644
--- a/include/asm-mips/rtc.h
+++ b/include/asm-mips/rtc.h
@@ -32,7 +32,7 @@
 {
 	unsigned long nowtime;
 
-	nowtime = rtc_get_time();
+	nowtime = rtc_mips_get_time();
 	to_tm(nowtime, time);
 	time->tm_year -= 1900;
 
@@ -47,7 +47,7 @@
 	nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
 			time->tm_mday, time->tm_hour, time->tm_min,
 			time->tm_sec);
-	ret = rtc_set_time(nowtime);
+	ret = rtc_mips_set_time(nowtime);
 
 	return ret;
 }
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
index 1298c3f..76cd51c 100644
--- a/include/asm-mips/rtlx.h
+++ b/include/asm-mips/rtlx.h
@@ -3,32 +3,46 @@
  *
  */
 
-#ifndef _RTLX_H
-#define _RTLX_H_
+#ifndef __ASM_RTLX_H
+#define __ASM_RTLX_H_
 
 #define LX_NODE_BASE 10
 
 #define MIPSCPU_INT_BASE       16
 #define MIPS_CPU_RTLX_IRQ 0
 
-#define RTLX_VERSION 1
+#define RTLX_VERSION 2
 #define RTLX_xID 0x12345600
 #define RTLX_ID (RTLX_xID | RTLX_VERSION)
 #define RTLX_CHANNELS 8
 
-#define RTLX_BUFFER_SIZE 1024
+#define RTLX_CHANNEL_STDIO	0
+#define RTLX_CHANNEL_DBG	1
+#define RTLX_CHANNEL_SYSIO	2
 
-/*
- * lx_state bits
- */
-#define RTLX_STATE_OPENED 1UL
+extern int rtlx_open(int index, int can_sleep);
+extern int rtlx_release(int index);
+extern ssize_t rtlx_read(int index, void *buff, size_t count, int user);
+extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user);
+extern unsigned int rtlx_read_poll(int index, int can_sleep);
+extern unsigned int rtlx_write_poll(int index);
+
+enum rtlx_state {
+	RTLX_STATE_UNUSED,
+	RTLX_STATE_INITIALISED,
+	RTLX_STATE_REMOTE_READY,
+	RTLX_STATE_OPENED
+};
+
+#define RTLX_BUFFER_SIZE 1024
 
 /* each channel supports read and write.
    linux (vpe0) reads lx_buffer  and writes rt_buffer
    SP (vpe1) reads rt_buffer and writes lx_buffer
 */
 struct rtlx_channel {
-	unsigned long lx_state;
+	enum rtlx_state rt_state;
+	enum rtlx_state lx_state;
 
 	int buffer_size;
 
@@ -38,15 +52,13 @@
 
 	int lx_write, lx_read;
 	char *lx_buffer;
-
-	void *queues;
-
 };
 
 struct rtlx_info {
 	unsigned long id;
+	enum rtlx_state state;
 
 	struct rtlx_channel channel[RTLX_CHANNELS];
 };
 
-#endif /* _RTLX_H_ */
+#endif /* __ASM_RTLX_H_ */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index 7b23664..7196ceb 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -77,15 +77,15 @@
 #include <asm/it8712.h>
 #define ITE_SERIAL_PORT_DEFNS                                  \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
-      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     { .baud_base = (24000000/(16*13)), .port = (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \
-      .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     /* Smart Card Reader 0 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \
-      .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     /* Smart Card Reader 1 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
-      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
 #else
 #define ITE_SERIAL_PORT_DEFNS
 #endif
@@ -95,10 +95,10 @@
 #include <asm/it8172/it8172_int.h>
 #define IVR_SERIAL_PORT_DEFNS                                  \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
-      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },         \
+      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },         \
     /* Smart Card Reader 1 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
-      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
 #else
 #define IVR_SERIAL_PORT_DEFNS
 #endif
diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
new file mode 100644
index 0000000..e1941d1
--- /dev/null
+++ b/include/asm-mips/smtc.h
@@ -0,0 +1,55 @@
+#ifndef _ASM_SMTC_MT_H
+#define _ASM_SMTC_MT_H
+
+/*
+ * Definitions for SMTC multitasking on MIPS MT cores
+ */
+
+#include <asm/mips_mt.h>
+
+/*
+ * System-wide SMTC status information
+ */
+
+extern unsigned int smtc_status;
+
+#define SMTC_TLB_SHARED	0x00000001
+#define SMTC_MTC_ACTIVE	0x00000002
+
+/*
+ * TLB/ASID Management information
+ */
+
+#define MAX_SMTC_TLBS 2
+#define MAX_SMTC_ASIDS 256
+#if NR_CPUS <= 8
+typedef char asiduse;
+#else
+#if NR_CPUS <= 16
+typedef short asiduse;
+#else
+typedef long asiduse;
+#endif
+#endif
+
+extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
+
+void smtc_flush_tlb_asid(unsigned long asid);
+extern int mipsmt_build_cpu_map(int startslot);
+extern void mipsmt_prepare_cpus(void);
+extern void smtc_smp_finish(void);
+extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+/*
+ * Sharing the TLB between multiple VPEs means that the
+ * "random" index selection function is not allowed to
+ * select the current value of the Index register. To
+ * avoid additional TLB pressure, the Index registers
+ * are "parked" with an non-Valid value.
+ */
+
+#define PARKED_INDEX	((unsigned int)0x80000000)
+
+#endif /*  _ASM_SMTC_MT_H */
diff --git a/include/asm-mips/smtc_ipi.h b/include/asm-mips/smtc_ipi.h
new file mode 100644
index 0000000..f22c3e2
--- /dev/null
+++ b/include/asm-mips/smtc_ipi.h
@@ -0,0 +1,118 @@
+/*
+ * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
+ */
+#ifndef __ASM_SMTC_IPI_H
+#define __ASM_SMTC_IPI_H
+
+//#define SMTC_IPI_DEBUG
+
+#ifdef SMTC_IPI_DEBUG
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#endif /* SMTC_IPI_DEBUG */
+
+/*
+ * An IPI "message"
+ */
+
+struct smtc_ipi {
+	struct smtc_ipi *flink;
+	int type;
+	void *arg;
+	int dest;
+#ifdef	SMTC_IPI_DEBUG
+	int sender;
+	long stamp;
+#endif /* SMTC_IPI_DEBUG */
+};
+
+/*
+ * Defined IPI Types
+ */
+
+#define LINUX_SMP_IPI 1
+#define SMTC_CLOCK_TICK 2
+
+/*
+ * A queue of IPI messages
+ */
+
+struct smtc_ipi_q {
+	struct smtc_ipi *head;
+	spinlock_t lock;
+	struct smtc_ipi *tail;
+	int depth;
+};
+
+extern struct smtc_ipi_q IPIQ[NR_CPUS];
+extern struct smtc_ipi_q freeIPIq;
+
+static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+	long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	if (q->head == NULL)
+		q->head = q->tail = p;
+	else
+		q->tail->flink = p;
+	p->flink = NULL;
+	q->tail = p;
+	q->depth++;
+#ifdef	SMTC_IPI_DEBUG
+	p->sender = read_c0_tcbind();
+	p->stamp = read_c0_count();
+#endif /* SMTC_IPI_DEBUG */
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
+{
+	struct smtc_ipi *p;
+	long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	if (q->head == NULL)
+		p = NULL;
+	else {
+		p = q->head;
+		q->head = q->head->flink;
+		q->depth--;
+		/* Arguably unnecessary, but leaves queue cleaner */
+		if (q->head == NULL)
+			q->tail = NULL;
+	}
+	spin_unlock_irqrestore(&q->lock, flags);
+	return p;
+}
+
+static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+	long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	if (q->head == NULL) {
+		q->head = q->tail = p;
+		p->flink = NULL;
+	} else {
+		p->flink = q->head;
+		q->head = p;
+	}
+	q->depth++;
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
+{
+	long flags;
+	int retval;
+
+	spin_lock_irqsave(&q->lock, flags);
+	retval = q->depth;
+	spin_unlock_irqrestore(&q->lock, flags);
+	return retval;
+}
+
+extern void smtc_send_ipi(int cpu, int type, unsigned int action);
+
+#endif /* __ASM_SMTC_IPI_H */
diff --git a/include/asm-mips/smtc_proc.h b/include/asm-mips/smtc_proc.h
new file mode 100644
index 0000000..25da651
--- /dev/null
+++ b/include/asm-mips/smtc_proc.h
@@ -0,0 +1,23 @@
+/*
+ * Definitions for SMTC /proc entries
+ * Copyright(C) 2005 MIPS Technologies Inc.
+ */
+#ifndef __ASM_SMTC_PROC_H
+#define __ASM_SMTC_PROC_H
+
+/*
+ * per-"CPU" statistics
+ */
+
+struct smtc_cpu_proc {
+	unsigned long timerints;
+	unsigned long selfipis;
+};
+
+extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+/* Count of number of recoveries of "stolen" FPU access rights on 34K */
+
+extern atomic_t smtc_fpu_recoveries;
+
+#endif /* __ASM_SMTC_PROC_H */
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 2acf3e8..c4856a8 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -14,9 +14,14 @@
 #include <linux/threads.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 		.macro	SAVE_AT
 		.set	push
 		.set	noat
@@ -57,13 +62,30 @@
 #ifdef CONFIG_SMP
 		.macro	get_saved_sp	/* SMP variation */
 #ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+		.set	mips32
+		mfc0	k0, CP0_TCBIND;
+		.set	mips0
+		lui	k1, %hi(kernelsp)
+		srl	k0, k0, 19
+		/* No need to shift down and up to clear bits 0-1 */
+#else
 		mfc0	k0, CP0_CONTEXT
 		lui	k1, %hi(kernelsp)
 		srl	k0, k0, 23
+#endif
 		addu	k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
 #endif
 #ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+		.set	mips64
+		mfc0	k0, CP0_TCBIND;
+		.set	mips0
+		lui	k0, %highest(kernelsp)
+		dsrl	k1, 19
+		/* No need to shift down and up to clear bits 0-2 */
+#else
 		MFC0	k1, CP0_CONTEXT
 		lui	k0, %highest(kernelsp)
 		dsrl	k1, 23
@@ -71,20 +93,31 @@
 		dsll	k0, k0, 16
 		daddiu	k0, %hi(kernelsp)
 		dsll	k0, k0, 16
+#endif /* CONFIG_MIPS_MT_SMTC */
 		daddu	k1, k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
-#endif
+#endif /* CONFIG_64BIT */
 		.endm
 
 		.macro	set_saved_sp stackp temp temp2
 #ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+		mfc0	\temp, CP0_TCBIND
+		srl	\temp, 19
+#else
 		mfc0	\temp, CP0_CONTEXT
 		srl	\temp, 23
 #endif
+#endif
 #ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+		mfc0	\temp, CP0_TCBIND
+		dsrl	\temp, 19
+#else
 		MFC0	\temp, CP0_CONTEXT
 		dsrl	\temp, 23
 #endif
+#endif
 		LONG_S	\stackp, kernelsp(\temp)
 		.endm
 #else
@@ -122,10 +155,25 @@
 		PTR_SUBU sp, k1, PT_SIZE
 		LONG_S	k0, PT_R29(sp)
 		LONG_S	$3, PT_R3(sp)
+		/*
+		 * You might think that you don't need to save $0,
+		 * but the FPU emulator and gdb remote debug stub
+		 * need it to operate correctly
+		 */
 		LONG_S	$0, PT_R0(sp)
 		mfc0	v1, CP0_STATUS
 		LONG_S	$2, PT_R2(sp)
 		LONG_S	v1, PT_STATUS(sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * Ideally, these instructions would be shuffled in
+		 * to cover the pipeline delay.
+		 */
+		.set	mips32
+		mfc0	v1, CP0_TCSTATUS
+		.set	mips0
+		LONG_S	v1, PT_TCSTATUS(sp)
+#endif /* CONFIG_MIPS_MT_SMTC */
 		LONG_S	$4, PT_R4(sp)
 		mfc0	v1, CP0_CAUSE
 		LONG_S	$5, PT_R5(sp)
@@ -234,14 +282,36 @@
 		.endm
 
 #else
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#else
+#define STATMASK 0x1f
+#endif
 		.macro	RESTORE_SOME
 		.set	push
 		.set	reorder
 		.set	noat
+#ifdef CONFIG_MIPS_MT_SMTC
+		.set	mips32r2
+		/*
+		 * This may not really be necessary if ints are already
+		 * inhibited here.
+		 */
+		mfc0	v0, CP0_TCSTATUS
+		ori	v0, TCSTATUS_IXMT
+		mtc0	v0, CP0_TCSTATUS
+		ehb
+		DMT	5				# dmt a1
+		jal	mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
 		mfc0	a0, CP0_STATUS
-		ori	a0, 0x1f
-		xori	a0, 0x1f
+		ori	a0, STATMASK
+		xori	a0, STATMASK
 		mtc0	a0, CP0_STATUS
 		li	v1, 0xff00
 		and	a0, v1
@@ -250,6 +320,26 @@
 		and	v0, v1
 		or	v0, a0
 		mtc0	v0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Only after EXL/ERL have been restored to status can we
+ * restore TCStatus.IXMT.
+ */
+		LONG_L	v1, PT_TCSTATUS(sp)
+		ehb
+		mfc0	v0, CP0_TCSTATUS
+		andi	v1, TCSTATUS_IXMT
+		/* We know that TCStatua.IXMT should be set from above */
+		xori	v0, v0, TCSTATUS_IXMT
+		or	v0, v0, v1
+		mtc0	v0, CP0_TCSTATUS
+		ehb
+		andi	a1, a1, VPECONTROL_TE
+		beqz	a1, 1f
+		emt
+1:
+		.set	mips0
+#endif /* CONFIG_MIPS_MT_SMTC */
 		LONG_L	v1, PT_EPC(sp)
 		MTC0	v1, CP0_EPC
 		LONG_L	$31, PT_R31(sp)
@@ -302,11 +392,33 @@
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
 		.macro	CLI
+#if !defined(CONFIG_MIPS_MT_SMTC)
 		mfc0	t0, CP0_STATUS
 		li	t1, ST0_CU0 | 0x1f
 		or	t0, t1
 		xori	t0, 0x1f
 		mtc0	t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+		/*
+		 * For SMTC, we need to set privilege
+		 * and disable interrupts only for the
+		 * current TC, using the TCStatus register.
+		 */
+		mfc0	t0,CP0_TCSTATUS
+		/* Fortunately CU 0 is in the same place in both registers */
+		/* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+		li	t1, ST0_CU0 | 0x08001c00
+		or	t0,t1
+		/* Clear TKSU, leave IXMT */
+		xori	t0, 0x00001800
+		mtc0	t0, CP0_TCSTATUS
+		ehb
+		/* We need to leave the global IE bit set, but clear EXL...*/
+		mfc0	t0, CP0_STATUS
+		ori	t0, ST0_EXL | ST0_ERL
+		xori	t0, ST0_EXL | ST0_ERL
+		mtc0	t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
 		irq_disable_hazard
 		.endm
 
@@ -315,11 +427,35 @@
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
 		.macro	STI
+#if !defined(CONFIG_MIPS_MT_SMTC)
 		mfc0	t0, CP0_STATUS
 		li	t1, ST0_CU0 | 0x1f
 		or	t0, t1
 		xori	t0, 0x1e
 		mtc0	t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+		/*
+		 * For SMTC, we need to set privilege
+		 * and enable interrupts only for the
+		 * current TC, using the TCStatus register.
+		 */
+		ehb
+		mfc0	t0,CP0_TCSTATUS
+		/* Fortunately CU 0 is in the same place in both registers */
+		/* Set TCU0, TKSU (for later inversion) and IXMT */
+		li	t1, ST0_CU0 | 0x08001c00
+		or	t0,t1
+		/* Clear TKSU *and* IXMT */
+		xori	t0, 0x00001c00
+		mtc0	t0, CP0_TCSTATUS
+		ehb
+		/* We need to leave the global IE bit set, but clear EXL...*/
+		mfc0	t0, CP0_STATUS
+		ori	t0, ST0_EXL
+		xori	t0, ST0_EXL
+		mtc0	t0, CP0_STATUS
+		/* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
+#endif /* CONFIG_MIPS_MT_SMTC */
 		irq_enable_hazard
 		.endm
 
@@ -328,11 +464,56 @@
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
 		.macro	KMODE
+#ifdef CONFIG_MIPS_MT_SMTC
+		/*
+		 * This gets baroque in SMTC.  We want to
+		 * protect the non-atomic clearing of EXL
+		 * with DMT/EMT, but we don't want to take
+		 * an interrupt while DMT is still in effect.
+		 */
+
+		/* KMODE gets invoked from both reorder and noreorder code */
+		.set	push
+		.set	mips32r2
+		.set	noreorder
+		mfc0	v0, CP0_TCSTATUS
+		andi	v1, v0, TCSTATUS_IXMT
+		ori	v0, TCSTATUS_IXMT
+		mtc0	v0, CP0_TCSTATUS
+		ehb
+		DMT	2				# dmt	v0
+		/*
+		 * We don't know a priori if ra is "live"
+		 */
+		move	t0, ra
+		jal	mips_ihb
+		nop	/* delay slot */
+		move	ra, t0
+#endif /* CONFIG_MIPS_MT_SMTC */
 		mfc0	t0, CP0_STATUS
 		li	t1, ST0_CU0 | 0x1e
 		or	t0, t1
 		xori	t0, 0x1e
 		mtc0	t0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+		ehb
+		andi	v0, v0, VPECONTROL_TE
+		beqz	v0, 2f
+		nop	/* delay slot */
+		emt
+2:
+		mfc0	v0, CP0_TCSTATUS
+		/* Clear IXMT, then OR in previous value */
+		ori	v0, TCSTATUS_IXMT
+		xori	v0, TCSTATUS_IXMT
+		or	v0, v1, v0
+		mtc0	v0, CP0_TCSTATUS
+		/*
+		 * irq_disable_hazard below should expand to EHB
+		 * on 24K/34K CPUS
+		 */
+		.set pop
+#endif /* CONFIG_MIPS_MT_SMTC */
 		irq_disable_hazard
 		.endm
 
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 4097fac..261f71d 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -155,6 +155,37 @@
 
 struct task_struct;
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management.  We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define switch_to(prev,next,last)					\
+do {									\
+	if (cpu_has_fpu &&						\
+	    (prev->thread.mflags & MF_FPUBOUND) &&			\
+	     (!(KSTK_STATUS(prev) & ST0_CU1))) {			\
+		prev->thread.mflags &= ~MF_FPUBOUND;			\
+		prev->cpus_allowed = prev->thread.user_cpus_allowed;	\
+	}								\
+	if (cpu_has_dsp)						\
+		__save_dsp(prev);					\
+	next->thread.emulated_fp = 0;					\
+	(last) = resume(prev, next, next->thread_info);			\
+	if (cpu_has_dsp)						\
+		__restore_dsp(current);					\
+} while(0)
+
+#else
 #define switch_to(prev,next,last)					\
 do {									\
 	if (cpu_has_dsp)						\
@@ -163,6 +194,7 @@
 	if (cpu_has_dsp)						\
 		__restore_dsp(current);					\
 } while(0)
+#endif
 
 /*
  * On SMP systems, when the scheduler does migration-cost autodetection,
@@ -440,8 +472,8 @@
 extern void set_handler (unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
 extern void *set_vi_handler (int n, void *addr);
-extern void *set_vi_srs_handler (int n, void *addr, int regset);
 extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
 extern void per_cpu_trap_init(void);
 
 extern NORET_TYPE void die(const char *, struct pt_regs *);
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index b5c78a4..1068fe9 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -324,16 +324,18 @@
 #define __NR_pselect6			(__NR_Linux + 301)
 #define __NR_ppoll			(__NR_Linux + 302)
 #define __NR_unshare			(__NR_Linux + 303)
+#define __NR_splice			(__NR_Linux + 304)
+#define __NR_sync_file_range		(__NR_Linux + 305)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		303
+#define __NR_Linux_syscalls		305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		303
+#define __NR_O32_Linux_syscalls		305
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -604,16 +606,18 @@
 #define __NR_pselect6			(__NR_Linux + 260)
 #define __NR_ppoll			(__NR_Linux + 261)
 #define __NR_unshare			(__NR_Linux + 262)
+#define __NR_splice			(__NR_Linux + 263)
+#define __NR_sync_file_range		(__NR_Linux + 264)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		262
+#define __NR_Linux_syscalls		264
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		262
+#define __NR_64_Linux_syscalls		264
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -888,16 +892,18 @@
 #define __NR_pselect6			(__NR_Linux + 264)
 #define __NR_ppoll			(__NR_Linux + 265)
 #define __NR_unshare			(__NR_Linux + 266)
+#define __NR_splice			(__NR_Linux + 267)
+#define __NR_sync_file_range		(__NR_Linux + 268)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		266
+#define __NR_Linux_syscalls		268
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		266
+#define __NR_N32_Linux_syscalls		268
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-mips/vpe.h b/include/asm-mips/vpe.h
new file mode 100644
index 0000000..c6e1b96
--- /dev/null
+++ b/include/asm-mips/vpe.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _ASM_VPE_H
+#define _ASM_VPE_H
+
+struct vpe_notifications {
+	void (*start)(int vpe);
+	void (*stop)(int vpe);
+
+	struct list_head list;
+};
+
+
+extern int vpe_notify(int index, struct vpe_notifications *notify);
+
+extern void *vpe_get_shared(int index);
+extern int vpe_getuid(int index);
+extern int vpe_getgid(int index);
+extern char *vpe_getcwd(int index);
+
+#endif /* _ASM_VPE_H */
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index 29da311..244f6b8 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -126,24 +126,17 @@
 
 extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
+/* Most machines react poorly to I/O-space being cacheable... Instead let's
+ * define ioremap() in terms of ioremap_nocache().
+ */
 extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 {
-	return __ioremap(offset, size, 0);
+	return __ioremap(offset, size, _PAGE_NO_CACHE);
 }
-
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
- */
-extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
-{
-        return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
-}
+#define ioremap_nocache(off, sz)	ioremap((off), (sz))
 
 extern void iounmap(void __iomem *addr);
 
-
 static inline unsigned char __raw_readb(const volatile void __iomem *addr)
 {
 	return (*(volatile unsigned char __force *) (addr));
diff --git a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h
deleted file mode 100644
index 6c67651..0000000
--- a/include/asm-parisc/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 8 Nodes */
-#define NODES_SHIFT	3
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 45e02aa..c0dd461 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -1,13 +1,30 @@
 #ifndef _PARISC_PAGE_H
 #define _PARISC_PAGE_H
 
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT	12
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#define PAGE_MASK	(~(PAGE_SIZE-1))
+#if !defined(__KERNEL__)
+/* this is for userspace applications (4k page size) */
+# define PAGE_SHIFT	12	/* 4k */
+# define PAGE_SIZE	(1UL << PAGE_SHIFT)
+# define PAGE_MASK	(~(PAGE_SIZE-1))
+#endif
+
 
 #ifdef __KERNEL__
 #include <linux/config.h>
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define PAGE_SHIFT	12	/* 4k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define PAGE_SHIFT	14	/* 16k */
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define PAGE_SHIFT	16	/* 64k */
+#else
+# error "unknown default kernel page size"
+#endif
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+
 #ifndef __ASSEMBLY__
 
 #include <asm/types.h>
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index 4e34c6b..aec089e 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -59,16 +59,15 @@
 #define  ISTACK_SIZE  32768 /* Interrupt Stack Size */
 #define  ISTACK_ORDER 3
 
-/* This is the size of the initially mapped kernel memory (i.e. currently
- * 0 to 1<<23 == 8MB */
+/* This is the size of the initially mapped kernel memory */
 #ifdef CONFIG_64BIT
-#define KERNEL_INITIAL_ORDER	24
+#define KERNEL_INITIAL_ORDER	24	/* 0 to 1<<24 = 16MB */
 #else
-#define KERNEL_INITIAL_ORDER	23
+#define KERNEL_INITIAL_ORDER	23	/* 0 to 1<<23 = 8MB */
 #endif
 #define KERNEL_INITIAL_SIZE	(1 << KERNEL_INITIAL_ORDER)
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 #define PT_NLEVELS	3
 #define PGD_ORDER	1 /* Number of pages per pgd */
 #define PMD_ORDER	1 /* Number of pages per pmd */
@@ -111,11 +110,15 @@
 #define MAX_ADDRBITS	(PGDIR_SHIFT + BITS_PER_PGD)
 #define MAX_ADDRESS	(1UL << MAX_ADDRBITS)
 
-#define SPACEID_SHIFT (MAX_ADDRBITS - 32)
+#define SPACEID_SHIFT	(MAX_ADDRBITS - 32)
 
 /* This calculates the number of initial pages we need for the initial
  * page tables */
-#define PT_INITIAL	(1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#if (KERNEL_INITIAL_ORDER) >= (PMD_SHIFT)
+# define PT_INITIAL	(1 << (KERNEL_INITIAL_ORDER - PMD_SHIFT))
+#else
+# define PT_INITIAL	(1)  /* all initial PTEs fit into one page */
+#endif
 
 /*
  * pgd entries used up by user/kernel:
@@ -160,6 +163,10 @@
  * to zero */
 #define PTE_SHIFT	   	xlate_pabit(_PAGE_USER_BIT)
 
+/* PFN_PTE_SHIFT defines the shift of a PTE value to access the PFN field */
+#define PFN_PTE_SHIFT		12
+
+
 /* this is how many bits may be used by the file functions */
 #define PTE_FILE_MAX_BITS	(BITS_PER_LONG - PTE_SHIFT)
 
@@ -188,7 +195,8 @@
 /* The pgd/pmd contains a ptr (in phys addr space); since all pgds/pmds
  * are page-aligned, we don't care about the PAGE_OFFSET bits, except
  * for a few meta-information bits, so we shift the address to be
- * able to effectively address 40-bits of physical address space. */
+ * able to effectively address 40/42/44-bits of physical address space
+ * depending on 4k/16k/64k PAGE_SIZE */
 #define _PxD_PRESENT_BIT   31
 #define _PxD_ATTACHED_BIT  30
 #define _PxD_VALID_BIT     29
@@ -198,7 +206,7 @@
 #define PxD_FLAG_VALID    (1 << xlate_pabit(_PxD_VALID_BIT))
 #define PxD_FLAG_MASK     (0xf)
 #define PxD_FLAG_SHIFT    (4)
-#define PxD_VALUE_SHIFT   (8)
+#define PxD_VALUE_SHIFT   (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
 
 #ifndef __ASSEMBLY__
 
@@ -246,6 +254,7 @@
 #define __S110  PAGE_RWX
 #define __S111  PAGE_RWX
 
+
 extern pgd_t swapper_pg_dir[]; /* declared in init_task.c */
 
 /* initial page tables for 0-8MB for kernel */
@@ -272,7 +281,7 @@
 #define pgd_flag(x)	(pgd_val(x) & PxD_FLAG_MASK)
 #define pgd_address(x)	((unsigned long)(pgd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
 
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 /* The first entry of the permanent pmd is not there if it contains
  * the gateway marker */
 #define pmd_none(x)	(!pmd_val(x) || pmd_flag(x) == PxD_FLAG_ATTACHED)
@@ -282,7 +291,7 @@
 #define pmd_bad(x)	(!(pmd_flag(x) & PxD_FLAG_VALID))
 #define pmd_present(x)	(pmd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pmd_clear(pmd_t *pmd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 	if (pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
 		/* This is the entry pointing to the permanent pmd
 		 * attached to the pgd; cannot clear it */
@@ -303,7 +312,7 @@
 #define pgd_bad(x)      (!(pgd_flag(x) & PxD_FLAG_VALID))
 #define pgd_present(x)  (pgd_flag(x) & PxD_FLAG_PRESENT)
 static inline void pgd_clear(pgd_t *pgd) {
-#ifdef CONFIG_64BIT
+#if PT_NLEVELS == 3
 	if(pgd_flag(*pgd) & PxD_FLAG_ATTACHED)
 		/* This is the permanent pmd attached to the pgd; cannot
 		 * free it */
@@ -351,7 +360,7 @@
 ({									\
 	pte_t __pte;							\
 									\
-	pte_val(__pte) = ((addr)+pgprot_val(pgprot));			\
+	pte_val(__pte) = ((((addr)>>PAGE_SHIFT)<<PFN_PTE_SHIFT) + pgprot_val(pgprot));	\
 									\
 	__pte;								\
 })
@@ -361,20 +370,16 @@
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
 {
 	pte_t pte;
-	pte_val(pte) = (pfn << PAGE_SHIFT) | pgprot_val(pgprot);
+	pte_val(pte) = (pfn << PFN_PTE_SHIFT) | pgprot_val(pgprot);
 	return pte;
 }
 
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
 
 /* Permanent address of a page.  On parisc we don't have highmem. */
 
-#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
+#define pte_pfn(x)		(pte_val(x) >> PFN_PTE_SHIFT)
 
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
 
@@ -499,6 +504,26 @@
 
 #endif /* !__ASSEMBLY__ */
 
+
+/* TLB page size encoding - see table 3-1 in parisc20.pdf */
+#define _PAGE_SIZE_ENCODING_4K		0
+#define _PAGE_SIZE_ENCODING_16K	1
+#define _PAGE_SIZE_ENCODING_64K	2
+#define _PAGE_SIZE_ENCODING_256K	3
+#define _PAGE_SIZE_ENCODING_1M		4
+#define _PAGE_SIZE_ENCODING_4M		5
+#define _PAGE_SIZE_ENCODING_16M	6
+#define _PAGE_SIZE_ENCODING_64M	7
+
+#if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_16KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16K
+#elif defined(CONFIG_PARISC_PAGE_SIZE_64KB)
+# define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_64K
+#endif
+
+
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
 		remap_pfn_range(vma, vaddr, pfn, size, prot)
 
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index c56fccb..0e1a30b 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -780,8 +780,14 @@
 #define __NR_readlinkat		(__NR_Linux + 285)
 #define __NR_fchmodat		(__NR_Linux + 286)
 #define __NR_faccessat		(__NR_Linux + 287)
+#define __NR_unshare		(__NR_Linux + 288)
+#define __NR_set_robust_list	(__NR_Linux + 289)
+#define __NR_get_robust_list	(__NR_Linux + 290)
+#define __NR_splice		(__NR_Linux + 291)
+#define __NR_sync_file_range	(__NR_Linux + 292)
+#define __NR_tee		(__NR_Linux + 293)
 
-#define __NR_Linux_syscalls     288
+#define __NR_Linux_syscalls     294
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index 5207758..868c713 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -60,24 +60,10 @@
  * device (including config space i/o).  Call eeh_add_device_late
  * to finish the eeh setup for this device.
  */
-void eeh_add_device_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *dev);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
 
 /**
- * eeh_remove_device - undo EEH setup for the indicated pci device
- * @dev: pci device to be removed
- *
- * This routine should be called when a device is removed from
- * a running system (e.g. by hotplug or dlpar).  It unregisters
- * the PCI device from the EEH subsystem.  I/O errors affecting
- * this device will no longer be detected after this call; thus,
- * i/o errors affecting this slot may leave this device unusable.
- */
-void eeh_remove_device(struct pci_dev *);
-
-/**
  * eeh_remove_device_recursive - undo EEH for device & children.
  * @dev: pci device to be removed
  *
@@ -116,12 +102,6 @@
 
 static inline void pci_addr_cache_build(void) { }
 
-static inline void eeh_add_device_early(struct device_node *dn) { }
-
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
-static inline void eeh_remove_device(struct pci_dev *dev) { }
-
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index b72c04f..6cc7e1f 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -4,47 +4,88 @@
 
 #define HVSC			.long 0x44000022
 
-#define H_Success	0
-#define H_Busy		1	/* Hardware busy -- retry later */
-#define H_Closed	2	/* Resource closed */
-#define H_Constrained	4	/* Resource request constrained to max allowed */
-#define H_InProgress   14	/* Kind of like busy */
-#define H_Pending      17	/* returned from H_POLL_PENDING */
-#define H_Continue     18	/* Returned from H_Join on success */
-#define H_LongBusyStartRange   9900  /* Start of long busy range */
-#define H_LongBusyOrder1msec   9900  /* Long busy, hint that 1msec is a good time to retry */
-#define H_LongBusyOrder10msec  9901  /* Long busy, hint that 10msec is a good time to retry */
-#define H_LongBusyOrder100msec 9902  /* Long busy, hint that 100msec is a good time to retry */
-#define H_LongBusyOrder1sec    9903  /* Long busy, hint that 1sec is a good time to retry */
-#define H_LongBusyOrder10sec   9904  /* Long busy, hint that 10sec is a good time to retry */
-#define H_LongBusyOrder100sec  9905  /* Long busy, hint that 100sec is a good time to retry */
-#define H_LongBusyEndRange     9905  /* End of long busy range */
-#define H_Hardware	-1	/* Hardware error */
-#define H_Function	-2	/* Function not supported */
-#define H_Privilege	-3	/* Caller not privileged */
-#define H_Parameter	-4	/* Parameter invalid, out-of-range or conflicting */
-#define H_Bad_Mode	-5	/* Illegal msr value */
-#define H_PTEG_Full	-6	/* PTEG is full */
-#define H_Not_Found	-7	/* PTE was not found" */
-#define H_Reserved_DABR	-8	/* DABR address is reserved by the hypervisor on this processor" */
-#define H_NoMem                 -9
-#define H_Authority            -10
-#define H_Permission           -11
-#define H_Dropped              -12
-#define H_SourceParm           -13
-#define H_DestParm             -14
-#define H_RemoteParm           -15
-#define H_Resource             -16
+#define H_SUCCESS	0
+#define H_BUSY		1	/* Hardware busy -- retry later */
+#define H_CLOSED	2	/* Resource closed */
+#define H_NOT_AVAILABLE 3
+#define H_CONSTRAINED	4	/* Resource request constrained to max allowed */
+#define H_PARTIAL       5
+#define H_IN_PROGRESS	14	/* Kind of like busy */
+#define H_PAGE_REGISTERED 15
+#define H_PARTIAL_STORE   16
+#define H_PENDING	17	/* returned from H_POLL_PENDING */
+#define H_CONTINUE	18	/* Returned from H_Join on success */
+#define H_LONG_BUSY_START_RANGE		9900  /* Start of long busy range */
+#define H_LONG_BUSY_ORDER_1_MSEC	9900  /* Long busy, hint that 1msec \
+						 is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_MSEC	9901  /* Long busy, hint that 10msec \
+						 is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_MSEC 	9902  /* Long busy, hint that 100msec \
+						 is a good time to retry */
+#define H_LONG_BUSY_ORDER_1_SEC		9903  /* Long busy, hint that 1sec \
+						 is a good time to retry */
+#define H_LONG_BUSY_ORDER_10_SEC	9904  /* Long busy, hint that 10sec \
+						 is a good time to retry */
+#define H_LONG_BUSY_ORDER_100_SEC	9905  /* Long busy, hint that 100sec \
+						 is a good time to retry */
+#define H_LONG_BUSY_END_RANGE		9905  /* End of long busy range */
+#define H_HARDWARE	-1	/* Hardware error */
+#define H_FUNCTION	-2	/* Function not supported */
+#define H_PRIVILEGE	-3	/* Caller not privileged */
+#define H_PARAMETER	-4	/* Parameter invalid, out-of-range or conflicting */
+#define H_BAD_MODE	-5	/* Illegal msr value */
+#define H_PTEG_FULL	-6	/* PTEG is full */
+#define H_NOT_FOUND	-7	/* PTE was not found" */
+#define H_RESERVED_DABR	-8	/* DABR address is reserved by the hypervisor on this processor" */
+#define H_NO_MEM	-9
+#define H_AUTHORITY	-10
+#define H_PERMISSION	-11
+#define H_DROPPED	-12
+#define H_SOURCE_PARM	-13
+#define H_DEST_PARM	-14
+#define H_REMOTE_PARM	-15
+#define H_RESOURCE	-16
+#define H_ADAPTER_PARM  -17
+#define H_RH_PARM       -18
+#define H_RCQ_PARM      -19
+#define H_SCQ_PARM      -20
+#define H_EQ_PARM       -21
+#define H_RT_PARM       -22
+#define H_ST_PARM       -23
+#define H_SIGT_PARM     -24
+#define H_TOKEN_PARM    -25
+#define H_MLENGTH_PARM  -27
+#define H_MEM_PARM      -28
+#define H_MEM_ACCESS_PARM -29
+#define H_ATTR_PARM     -30
+#define H_PORT_PARM     -31
+#define H_MCG_PARM      -32
+#define H_VL_PARM       -33
+#define H_TSIZE_PARM    -34
+#define H_TRACE_PARM    -35
+
+#define H_MASK_PARM     -37
+#define H_MCG_FULL      -38
+#define H_ALIAS_EXIST   -39
+#define H_P_COUNTER     -40
+#define H_TABLE_FULL    -41
+#define H_ALT_TABLE     -42
+#define H_MR_CONDITION  -43
+#define H_NOT_ENOUGH_RESOURCES -44
+#define H_R_STATE       -45
+#define H_RESCINDEND    -46
+
 
 /* Long Busy is a condition that can be returned by the firmware
  * when a call cannot be completed now, but the identical call
  * should be retried later.  This prevents calls blocking in the
- * firmware for long periods of time. Annoyingly the firmware can return
+ * firmware for long periods of time.  Annoyingly the firmware can return
  * a range of return codes, hinting at how long we should wait before
  * retrying.  If you don't care for the hint, the macro below is a good
  * way to check for the long_busy return codes
  */
-#define H_isLongBusy(x)  ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange))
+#define H_IS_LONG_BUSY(x)  ((x >= H_LONG_BUSY_START_RANGE) \
+			     && (x <= H_LONG_BUSY_END_RANGE))
 
 /* Flags */
 #define H_LARGE_PAGE		(1UL<<(63-16))
@@ -66,6 +107,9 @@
 #define H_DABRX_KERNEL		(1UL<<(63-62))
 #define H_DABRX_USER		(1UL<<(63-63))
 
+/* Each control block has to be on a 4K bondary */
+#define H_CB_ALIGNMENT          4096
+
 /* pSeries hypervisor opcodes */
 #define H_REMOVE		0x04
 #define H_ENTER			0x08
@@ -99,25 +143,52 @@
 #define H_PERFMON		0x7c
 #define H_MIGRATE_DMA		0x78
 #define H_REGISTER_VPA		0xDC
-#define H_CEDE		        0xE0
+#define H_CEDE			0xE0
 #define H_CONFER		0xE4
-#define H_PROD		        0xE8
+#define H_PROD			0xE8
 #define H_GET_PPP		0xEC
 #define H_SET_PPP		0xF0
 #define H_PURR			0xF4
-#define H_PIC		        0xF8
+#define H_PIC			0xF8
 #define H_REG_CRQ		0xFC
 #define H_FREE_CRQ		0x100
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
-#define H_COPY_RDMA             0x110
+#define H_COPY_RDMA		0x110
 #define H_SET_XDABR		0x134
 #define H_STUFF_TCE		0x138
 #define H_PUT_TCE_INDIRECT	0x13C
 #define H_VTERM_PARTNER_INFO	0x150
 #define H_REGISTER_VTERM	0x154
 #define H_FREE_VTERM		0x158
-#define H_POLL_PENDING	        0x1D8
+#define H_RESET_EVENTS          0x15C
+#define H_ALLOC_RESOURCE        0x160
+#define H_FREE_RESOURCE         0x164
+#define H_MODIFY_QP             0x168
+#define H_QUERY_QP              0x16C
+#define H_REREGISTER_PMR        0x170
+#define H_REGISTER_SMR          0x174
+#define H_QUERY_MR              0x178
+#define H_QUERY_MW              0x17C
+#define H_QUERY_HCA             0x180
+#define H_QUERY_PORT            0x184
+#define H_MODIFY_PORT           0x188
+#define H_DEFINE_AQP1           0x18C
+#define H_GET_TRACE_BUFFER      0x190
+#define H_DEFINE_AQP0           0x194
+#define H_RESIZE_MR             0x198
+#define H_ATTACH_MCQP           0x19C
+#define H_DETACH_MCQP           0x1A0
+#define H_CREATE_RPT            0x1A4
+#define H_REMOVE_RPT            0x1A8
+#define H_REGISTER_RPAGES       0x1AC
+#define H_DISABLE_AND_GETC      0x1B0
+#define H_ERROR_DATA            0x1B4
+#define H_GET_HCA_INFO          0x1B8
+#define H_GET_PERF_COUNT        0x1BC
+#define H_MANAGE_TRACE          0x1C0
+#define H_QUERY_INT_STATE       0x1E4
+#define H_POLL_PENDING		0x1D8
 #define H_JOIN			0x298
 #define H_ENABLE_CRQ		0x2B0
 
@@ -152,7 +223,7 @@
  */
 long plpar_hcall_8arg_2ret(unsigned long opcode,
 			   unsigned long arg1,
-		  	   unsigned long arg2,
+			   unsigned long arg2,
 			   unsigned long arg3,
 			   unsigned long arg4,
 			   unsigned long arg5,
@@ -176,6 +247,42 @@
 		      unsigned long *out3,
 		      unsigned long *out4);
 
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+			   unsigned long arg1,
+			   unsigned long arg2,
+			   unsigned long arg3,
+			   unsigned long arg4,
+			   unsigned long arg5,
+			   unsigned long arg6,
+			   unsigned long arg7,
+			   unsigned long *out1,
+			   unsigned long *out2,
+			   unsigned long *out3,
+			   unsigned long *out4,
+			   unsigned long *out5,
+			   unsigned long *out6,
+			   unsigned long *out7);
+
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+			   unsigned long arg1,
+			   unsigned long arg2,
+			   unsigned long arg3,
+			   unsigned long arg4,
+			   unsigned long arg5,
+			   unsigned long arg6,
+			   unsigned long arg7,
+			   unsigned long arg8,
+			   unsigned long arg9,
+			   unsigned long *out1,
+			   unsigned long *out2,
+			   unsigned long *out3,
+			   unsigned long *out4,
+			   unsigned long *out5,
+			   unsigned long *out6,
+			   unsigned long *out7,
+			   unsigned long *out8,
+			   unsigned long *out9);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index d5677cb..18ca29e 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -70,17 +70,18 @@
 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
 
 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
-		struct scatterlist *sglist, int nelems,
+		struct scatterlist *sglist, int nelems, unsigned long mask,
 		enum dma_data_direction direction);
 extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction);
 
 extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, gfp_t flag);
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
 extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
 		void *vaddr, dma_addr_t dma_handle);
 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
-		size_t size, enum dma_data_direction direction);
+		size_t size, unsigned long mask,
+		enum dma_data_direction direction);
 extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction);
 
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 51f87d9..7bc6d73 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -54,6 +54,13 @@
  */
 extern unsigned int virt_irq_to_real_map[NR_IRQS];
 
+/* The maximum virtual IRQ number that we support.  This
+ * can be set by the platform and will be reduced by the
+ * value of __irq_offset_value.  It defaults to and is
+ * capped by (NR_IRQS - 1).
+ */
+extern unsigned int virt_irq_max;
+
 /* Create a mapping for a real_irq if it doesn't already exist.
  * Return the virtual irq as a convenience.
  */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 5ed8476..0f9254c 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -253,7 +253,11 @@
 
 #define __machine_desc __attribute__ ((__section__ (".machine.desc")))
 
-#define define_machine(name) struct machdep_calls mach_##name __machine_desc =
+#define define_machine(name)					\
+	extern struct machdep_calls mach_##name;		\
+	EXPORT_SYMBOL(mach_##name);				\
+	struct machdep_calls mach_##name __machine_desc =
+
 #define machine_is(name) \
 	({ \
 		extern struct machdep_calls mach_##name \
diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h
deleted file mode 100644
index e138eda..0000000
--- a/include/asm-powerpc/numnodes.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_POWERPC_MAX_NUMNODES_H
-#define _ASM_POWERPC_MAX_NUMNODES_H
-#ifdef __KERNEL__
-
-/* Max 16 Nodes */
-#define NODES_SHIFT	4
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_MAX_NUMNODES_H */
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index ffc7462..88b553c 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,6 +37,8 @@
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
 	struct restart_block restart_block;
+	unsigned long	local_flags;		/* private flags for thread */
+
 	/* low level flags - has atomic operations done on it */
 	unsigned long	flags ____cacheline_aligned_in_smp;
 };
@@ -143,6 +145,12 @@
 				 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
 #define _TIF_PERSYSCALL_MASK	(_TIF_RESTOREALL|_TIF_NOERROR)
 
+/* Bits in local_flags */
+/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
+#define TLF_NAPPING		0	/* idle thread enabled NAP mode */
+
+#define _TLF_NAPPING		(1 << TLF_NAPPING)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_POWERPC_THREAD_INFO_H */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 536ba08..34325e2 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -302,8 +302,10 @@
 #define __NR_ppoll		281
 #define __NR_unshare		282
 #define __NR_splice		283
+#define __NR_tee		284
+#define __NR_vmsplice		285
 
-#define __NR_syscalls		284
+#define __NR_syscalls		286
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index de1d992..399bf02 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -1,6 +1,8 @@
 #ifndef __ARCH_S390_ATOMIC__
 #define __ARCH_S390_ATOMIC__
 
+#include <linux/compiler.h>
+
 /*
  *  include/asm-s390/atomic.h
  *
diff --git a/include/asm-s390/cache.h b/include/asm-s390/cache.h
index e20cdd9..cdf431b 100644
--- a/include/asm-s390/cache.h
+++ b/include/asm-s390/cache.h
@@ -16,4 +16,6 @@
 
 #define ARCH_KMALLOC_MINALIGN	8
 
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
 #endif
diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h
index 4cbc336..15fd2ed 100644
--- a/include/asm-s390/ebcdic.h
+++ b/include/asm-s390/ebcdic.h
@@ -14,12 +14,12 @@
 #include <types.h>
 #endif
 
-extern __u8 _ascebc_500[];   /* ASCII -> EBCDIC 500 conversion table */
-extern __u8 _ebcasc_500[];   /* EBCDIC 500 -> ASCII conversion table */
-extern __u8 _ascebc[];   /* ASCII -> EBCDIC conversion table */
-extern __u8 _ebcasc[];   /* EBCDIC -> ASCII conversion table */
-extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
-extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */
+extern __u8 _ascebc_500[256];   /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[256];   /* EBCDIC 500 -> ASCII conversion table */
+extern __u8 _ascebc[256];   /* ASCII -> EBCDIC conversion table */
+extern __u8 _ebcasc[256];   /* EBCDIC -> ASCII conversion table */
+extern __u8 _ebc_tolower[256]; /* EBCDIC -> lowercase */
+extern __u8 _ebc_toupper[256]; /* EBCDIC -> uppercase */
 
 static inline void
 codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 6a332a9..40c25e16 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -1,6 +1,121 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_S390_FUTEX_H
+#define _ASM_S390_FUTEX_H
 
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
 
-#endif
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+#ifndef __s390x__
+#define __futex_atomic_fixup \
+		     ".section __ex_table,\"a\"\n"			\
+		     "   .align 4\n"					\
+		     "   .long  0b,2b,1b,2b\n"				\
+		     ".previous"
+#else /* __s390x__ */
+#define __futex_atomic_fixup \
+		     ".section __ex_table,\"a\"\n"			\
+		     "   .align 8\n"					\
+		     "   .quad  0b,2b,1b,2b\n"				\
+		     ".previous"
+#endif /* __s390x__ */
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)	\
+	asm volatile("   l   %1,0(%6)\n"				\
+		     "0: " insn						\
+		     "   cs  %1,%2,0(%6)\n"				\
+		     "1: jl  0b\n"					\
+		     "   lhi %0,0\n"					\
+		     "2:\n"						\
+		     __futex_atomic_fixup				\
+		     : "=d" (ret), "=&d" (oldval), "=&d" (newval),	\
+		       "=m" (*uaddr)					\
+		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
+		       "m" (*uaddr) : "cc" );
+
+static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, newval, ret;
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	inc_preempt_count();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("lr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("lr %2,%1\nar %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("lr %2,%1\nor %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+				  ret, oldval, newval, uaddr, oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	dec_preempt_count();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+		default: ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+	int ret;
+
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+	asm volatile("   cs   %1,%4,0(%5)\n"
+		     "0: lr   %0,%1\n"
+		     "1:\n"
+#ifndef __s390x__
+		     ".section __ex_table,\"a\"\n"
+		     "   .align 4\n"
+		     "   .long  0b,1b\n"
+		     ".previous"
+#else /* __s390x__ */
+		     ".section __ex_table,\"a\"\n"
+		     "   .align 8\n"
+		     "   .quad  0b,1b\n"
+		     ".previous"
+#endif /* __s390x__ */
+		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+		     : "cc", "memory" );
+	return oldval;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_S390_FUTEX_H */
diff --git a/include/asm-sh/numnodes.h b/include/asm-sh/numnodes.h
deleted file mode 100644
index f73e85b..0000000
--- a/include/asm-sh/numnodes.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_MAX_NUMNODES_H
-#define _ASM_MAX_NUMNODES_H
-
-/* Max 2 Nodes */
-#define NODES_SHIFT	1
-
-#endif /* _ASM_MAX_NUMNODES_H */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index f2c8e14..05520ce 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -290,7 +290,7 @@
 #define __NR_mq_timedreceive    (__NR_mq_open+3)
 #define __NR_mq_notify          (__NR_mq_open+4)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
-#define __NR_sys_kexec_load	283
+#define __NR_kexec_load		283
 #define __NR_waitid		284
 #define __NR_add_key		285
 #define __NR_request_key	286
diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
index 2a1cfa4..1f8f394 100644
--- a/include/asm-sh64/unistd.h
+++ b/include/asm-sh64/unistd.h
@@ -333,7 +333,7 @@
 #define __NR_mq_timedreceive    (__NR_mq_open+3)
 #define __NR_mq_notify          (__NR_mq_open+4)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
-#define __NR_sys_kexec_load	311
+#define __NR_kexec_load		311
 #define __NR_waitid		312
 #define __NR_add_key		313
 #define __NR_request_key	314
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 64ec640..32a48f6 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -180,7 +180,7 @@
 #define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
 #define __NR_getdomainname      162 /* SunOS Specific                              */
 #define __NR_setdomainname      163 /* Common                                      */
-/* #define __NR_ni_syscall	164    ENOSYS under SunOS			   */
+/* #define __NR_utrap_install   164    Linux sparc64 specific			   */
 #define __NR_quotactl           165 /* Common                                      */
 #define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
 #define __NR_mount              167 /* Common                                      */
@@ -248,7 +248,7 @@
 #define __NR_setfsgid           229 /* Linux Specific                              */
 #define __NR__newselect         230 /* Linux Specific                              */
 #define __NR_time               231 /* Linux Specific                              */
-/* #define __NR_oldstat         232    Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
@@ -271,7 +271,7 @@
 #define __NR_getsid             252
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
-#define __NR_aplib              255
+#define __NR_sync_file_range	255
 #define __NR_clock_settime	256
 #define __NR_clock_gettime	257
 #define __NR_clock_getres	258
@@ -296,7 +296,7 @@
 #define __NR_mq_notify		277
 #define __NR_mq_getsetattr	278
 #define __NR_waitid		279
-#define __NR_sys_setaltroot	280
+#define __NR_tee		280
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_keyctl		283
diff --git a/include/asm-sparc/vga.h b/include/asm-sparc/vga.h
new file mode 100644
index 0000000..c69d5b2
--- /dev/null
+++ b/include/asm-sparc/vga.h
@@ -0,0 +1,33 @@
+/*
+ *	Access to VGA videoram
+ *
+ *	(c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _LINUX_ASM_VGA_H_
+#define _LINUX_ASM_VGA_H_
+
+#include <asm/types.h>
+
+#define VT_BUF_HAVE_RW
+
+#undef scr_writew
+#undef scr_readw
+
+static inline void scr_writew(u16 val, u16 *addr)
+{
+	BUG_ON((long) addr >= 0);
+
+	*addr = val;
+}
+
+static inline u16 scr_readw(const u16 *addr)
+{
+	BUG_ON((long) addr >= 0);
+
+	return *addr;
+}
+
+#define VGA_MAP_MEM(x,s) (x)
+
+#endif
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index 82032e1..baef13b 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -26,7 +26,7 @@
 #define percpu_modcopy(pcpudst, src, size)			\
 do {								\
 	unsigned int __i;					\
-	for_each_cpu(__i)					\
+	for_each_possible_cpu(__i)				\
 		memcpy((pcpudst)+__per_cpu_offset(__i),		\
 		       (src), (size));				\
 } while (0)
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index a284986..ca80e8a 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -250,7 +250,7 @@
 #ifdef __KERNEL__
 #define __NR_time		231 /* Linux sparc32                               */
 #endif
-/* #define __NR_oldstat         232    Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
@@ -273,7 +273,7 @@
 #define __NR_getsid             252
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
-#define __NR_aplib              255
+#define __NR_sync_file_range	255
 #define __NR_clock_settime	256
 #define __NR_clock_gettime	257
 #define __NR_clock_getres	258
@@ -298,7 +298,7 @@
 #define __NR_mq_notify		277
 #define __NR_mq_getsetattr	278
 #define __NR_waitid		279
-/*#define __NR_sys_setaltroot	280 available (was setaltroot) */
+#define __NR_tee		280
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_keyctl		283
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 30656c9..6e2528b 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -56,6 +56,9 @@
 extern int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to);
 extern int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to);
 
+extern void arch_switch_to_tt(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to_skas(struct task_struct *from, struct task_struct *to);
+
 static inline int do_get_thread_area(struct user_desc *info)
 {
 	return CHOOSE_MODE_PROC(do_get_thread_area_tt, do_get_thread_area_skas, info);
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 107decb..7091af4 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -18,8 +18,6 @@
 #include <asm/ptrace.h>
 
 
-#define prepare_to_switch()	do { } while (0)
-
 /*
  * switch_to(n) should switch tasks to task ptr, first checking that
  * ptr isn't the current task, in which case it does nothing.
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index c8043a1..f8dff1c 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -20,8 +20,8 @@
        __attribute__((__section__(".data.page_aligned")))
 #endif
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
 #endif
 
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
 #endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 76bb619..662964b 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -64,6 +64,7 @@
 #define X86_FEATURE_REP_GOOD	(3*32+ 4) /* rep microcode works well on this CPU */
 #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 8dcc326..93b51df 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -47,7 +47,8 @@
 extern unsigned long e820_end_of_ram(void);
 extern void e820_reserve_resources(void);
 extern void e820_print_map(char *who);
-extern int e820_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_any_mapped(unsigned long start, unsigned long end, unsigned type);
+extern int e820_all_mapped(unsigned long start, unsigned long end, unsigned type);
 
 extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
 extern void e820_setup_gap(void);
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index 08b75c1..18ff7ee 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -51,6 +51,8 @@
 
 #define HPET_TN_ROUTE_SHIFT	9
 
+#define HPET_TICK_RATE (HZ * 100000UL)
+
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
 extern int oem_force_hpet_timer(void);
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index 876eb9a..cba8a3b 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -72,6 +72,23 @@
 #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
 #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
 
+#define X87_FSW_ES (1 << 7)	/* Exception Summary */
+
+/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+   is pending. Clear the x87 state here by setting it to fixed
+   values. The kernel data segment can be sometimes 0 and sometimes
+   new user value. Both should be ok.
+   Use the PDA as safe address because it should be already in L1. */
+static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+{
+	if (unlikely(fx->swd & X87_FSW_ES))
+		 asm volatile("fnclex");
+	alternative_input(ASM_NOP8 ASM_NOP2,
+	     	     "    emms\n"		/* clear stack tags */
+	     	     "    fildl %%gs:0",	/* load to clear state */
+		     X86_FEATURE_FXSAVE_LEAK);
+}
+
 static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) 
 { 
 	int err;
@@ -119,6 +136,7 @@
 #endif
 	if (unlikely(err))
 		__clear_user(fx, sizeof(struct i387_fxsave_struct));
+	/* No need to clear here because the caller clears USED_MATH */
 	return err;
 } 
 
@@ -149,7 +167,7 @@
 				"i" (offsetof(__typeof__(*tsk),
 					      thread.i387.fxsave)));
 #endif
-	__asm__ __volatile__("fnclex");
+	clear_fpu_state(&tsk->thread.i387.fxsave);
 }
 
 static inline void kernel_fpu_begin(void)
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index eeb2bcd..b4f4b17 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -317,6 +317,4 @@
 #define __NR_ia32_ppoll			309
 #define __NR_ia32_unshare		310
 
-#define IA32_NR_syscalls 315	/* must be > than biggest syscall! */
-
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index cafdfb3..a05da8a 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -177,7 +177,7 @@
 {
 	return *(__force volatile __u16 *)addr;
 }
-static inline __u32 __readl(const volatile void __iomem *addr)
+static __always_inline __u32 __readl(const volatile void __iomem *addr)
 {
 	return *(__force volatile __u32 *)addr;
 }
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h
index 5d298b7..7229785 100644
--- a/include/asm-x86_64/mce.h
+++ b/include/asm-x86_64/mce.h
@@ -70,6 +70,9 @@
 #define MCE_THRESHOLD_BASE      MCE_EXTENDED_BANK + 1 /* MCE_AMD */
 #define MCE_THRESHOLD_DRAM_ECC  MCE_THRESHOLD_BASE + 4
 
+#ifdef __KERNEL__
+#include <asm/atomic.h>
+
 void mce_log(struct mce *m);
 #ifdef CONFIG_X86_MCE_INTEL
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
@@ -87,4 +90,8 @@
 }
 #endif
 
+extern atomic_t mce_entry;
+
+#endif
+
 #endif
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 6b18cd8..6944e71 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -12,7 +12,8 @@
 
 #include <asm/smp.h>
 
-#define NODEMAPSIZE 0xfff
+/* Should really switch to dynamic allocation at some point */
+#define NODEMAPSIZE 0x4fff
 
 /* Simple perfect hash to map physical addresses to node numbers */
 struct memnode {
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index f6cbb4c..1cc92fe 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -2,7 +2,6 @@
 #define _ASM_X8664_NUMA_H 1
 
 #include <linux/nodemask.h>
-#include <asm/numnodes.h>
 
 struct bootnode {
 	u64 start,end; 
@@ -18,6 +17,8 @@
 extern int numa_off;
 
 extern void numa_set_node(int cpu, int node);
+extern void srat_reserve_add_area(int nodeid);
+extern int hotadd_percent;
 
 extern unsigned char apicid_to_node[256];
 #ifdef CONFIG_NUMA
diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h
deleted file mode 100644
index 32be16b..0000000
--- a/include/asm-x86_64/numnodes.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_X8664_NUMNODES_H
-#define _ASM_X8664_NUMNODES_H 1
-
-#include <linux/config.h>
-
-#ifdef CONFIG_NUMA
-#define NODES_SHIFT	6
-#else
-#define NODES_SHIFT	0
-#endif
-
-#endif
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 4405b4a..7f33aaf 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -26,7 +26,7 @@
 #define percpu_modcopy(pcpudst, src, size)			\
 do {								\
 	unsigned int __i;					\
-	for_each_cpu(__i)					\
+	for_each_possible_cpu(__i)				\
 		memcpy((pcpudst)+__per_cpu_offset(__i),		\
 		       (src), (size));				\
 } while (0)
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index f18443f..b9e5320 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -33,7 +33,7 @@
 	unsigned eax;
 	/* Don't do an additional sync on CPUs where we know
 	   RDTSC is already synchronous. */
-	alternative_io(ASM_NOP2, "cpuid", X86_FEATURE_SYNC_RDTSC,
+	alternative_io("cpuid", ASM_NOP2, X86_FEATURE_SYNC_RDTSC,
 			  "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
 	rdtscll(ret);
 	return ret;
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index f21ff2c..feb77cb 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -611,8 +611,14 @@
 __SYSCALL(__NR_get_robust_list, sys_get_robust_list)
 #define __NR_splice		275
 __SYSCALL(__NR_splice, sys_splice)
+#define __NR_tee		276
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_sync_file_range	277
+__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
+#define __NR_vmsplice		278
+__SYSCALL(__NR_vmsplice, sys_vmsplice)
 
-#define __NR_syscall_max __NR_splice
+#define __NR_syscall_max __NR_vmsplice
 
 #ifndef __NO_STUBS
 
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
index 10c4434..3b89a77 100644
--- a/include/asm-xtensa/ioctls.h
+++ b/include/asm-xtensa/ioctls.h
@@ -107,6 +107,6 @@
 #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
 
 #define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 
 #endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
index 5d6fc9c..a99c9ae 100644
--- a/include/asm-xtensa/signal.h
+++ b/include/asm-xtensa/signal.h
@@ -118,9 +118,9 @@
  * SA_INTERRUPT is also used by the irq handling routines.
  * SA_SHIRQ is for shared interrupt support on PCI and EISA.
  */
-#define SA_PROBE		SA_ONESHOT
 #define SA_SAMPLE_RANDOM	SA_RESTART
 #define SA_SHIRQ		0x04000000
+#define SA_PROBEIRQ		0x08000000
 #endif
 
 #define SIG_BLOCK          0	/* for blocking signals */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index 9284867..b29f7ae 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -111,8 +111,6 @@
 
 #endif	/* __ASSEMBLY__ */
 
-#define prepare_to_switch()	do { } while(0)
-
 #define switch_to(prev,next,last)		\
 do {						\
 	clear_cpenable();			\
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d0cac8b..59e1259 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -17,6 +17,8 @@
 
 #include <asm/scatterlist.h>
 
+struct scsi_ioctl_command;
+
 struct request_queue;
 typedef struct request_queue request_queue_t;
 struct elevator_queue;
@@ -611,6 +613,8 @@
 extern int blk_remove_plug(request_queue_t *);
 extern void blk_recount_segments(request_queue_t *, struct bio *);
 extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
+extern int sg_scsi_ioctl(struct file *, struct request_queue *,
+		struct gendisk *, struct scsi_ioctl_command __user *);
 extern void blk_start_queue(request_queue_t *q);
 extern void blk_stop_queue(request_queue_t *q);
 extern void blk_sync_queue(struct request_queue *q);
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index de3eb8d..da2d107 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -45,6 +45,7 @@
 extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
 extern void __init free_bootmem (unsigned long addr, unsigned long size);
 extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+extern void * __init __alloc_bootmem_nopanic (unsigned long size, unsigned long align, unsigned long goal);
 extern void * __init __alloc_bootmem_low(unsigned long size,
 					 unsigned long align,
 					 unsigned long goal);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 176e2d3..047567d 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -58,9 +58,8 @@
  */
 
 static inline struct dentry *debugfs_create_file(const char *name, mode_t mode,
-						 struct dentry *parent,
-						 void *data,
-						 struct file_operations *fops)
+					struct dentry *parent, void *data,
+					const struct file_operations *fops)
 {
 	return ERR_PTR(-ENODEV);
 }
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9b4751a..ff61817 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -21,7 +21,7 @@
 #define DMA_30BIT_MASK	0x000000003fffffffULL
 #define DMA_29BIT_MASK	0x000000001fffffffULL
 #define DMA_28BIT_MASK	0x000000000fffffffULL
-#define DMA_24BIT_MASK 0x0000000000ffffffULL
+#define DMA_24BIT_MASK	0x0000000000ffffffULL
 
 #include <asm/dma-mapping.h>
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4ed7e60..3de2bfb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -762,7 +762,7 @@
 #define SYNC_FILE_RANGE_WRITE		2
 #define SYNC_FILE_RANGE_WAIT_AFTER	4
 extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte,
-			int flags);
+			unsigned int flags);
 
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
@@ -864,7 +864,7 @@
 	 */
 	struct mutex s_vfs_rename_mutex;	/* Kludge */
 
-	/* Granuality of c/m/atime in ns.
+	/* Granularity of c/m/atime in ns.
 	   Cannot be worse than a second */
 	u32		   s_time_gran;
 };
@@ -1039,8 +1039,8 @@
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
 	int (*flock) (struct file *, int, struct file_lock *);
-	ssize_t (*splice_write)(struct inode *, struct file *, size_t, unsigned int);
-	ssize_t (*splice_read)(struct file *, struct inode *, size_t, unsigned int);
+	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
+	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
 };
 
 struct inode_operations {
@@ -1611,8 +1611,17 @@
 extern void do_generic_mapping_read(struct address_space *mapping,
 				    struct file_ra_state *, struct file *,
 				    loff_t *, read_descriptor_t *, read_actor_t);
-extern ssize_t generic_file_splice_read(struct file *, struct inode *, size_t, unsigned int);
-extern ssize_t generic_file_splice_write(struct inode *, struct file *, size_t, unsigned int);
+
+/* fs/splice.c */
+extern ssize_t generic_file_splice_read(struct file *, loff_t *,
+		struct pipe_inode_info *, size_t, unsigned int);
+extern ssize_t generic_file_splice_write(struct pipe_inode_info *,
+		struct file *, loff_t *, size_t, unsigned int);
+extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
+		struct file *out, loff_t *, size_t len, unsigned int flags);
+extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+		size_t len, unsigned int flags);
+
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
 extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 10a27f2..2ef845b 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -105,6 +105,7 @@
                                          * disks that can't be partitioned. */
 	char disk_name[32];		/* name of major driver */
 	struct hd_struct **part;	/* [indexed by minor] */
+	int part_uevent_suppress;
 	struct block_device_operations *fops;
 	struct request_queue *queue;
 	void *private_data;
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 7851e6b..3ac4529 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -57,6 +57,8 @@
 			__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
 			__GFP_NOMEMALLOC|__GFP_HARDWALL)
 
+/* This equals 0, but use constants in case they ever change */
+#define GFP_NOWAIT	(GFP_ATOMIC & ~__GFP_HIGH)
 /* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
 #define GFP_ATOMIC	(__GFP_HIGH)
 #define GFP_NOIO	(__GFP_WAIT)
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index b209392..306acf1 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -80,7 +80,7 @@
  * @first:		pointer to the timer node which expires first
  * @resolution:		the resolution of the clock, in nanoseconds
  * @get_time:		function to retrieve the current time of the clock
- * @get_sofirq_time:	function to retrieve the current time from the softirq
+ * @get_softirq_time:	function to retrieve the current time from the softirq
  * @curr_timer:		the timer which is executing a callback right now
  * @softirq_time:	the time when running the hrtimer queue in the softirq
  */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 8d2db41..a8bef1d 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1220,7 +1220,6 @@
 enum {
 	/* Uses ISA control ports not PCI ones. */
 	IDEPCI_FLAG_ISA_PORTS		= (1 << 0),
-	IDEPCI_FLAG_FORCE_PDC		= (1 << 1),
 };
 
 typedef struct ide_pci_device_s {
diff --git a/include/linux/init.h b/include/linux/init.h
index ed0ac7c..93dcbe1 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -245,7 +245,8 @@
 #define __cpuexitdata	__exitdata
 #endif
 
-#ifdef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+	|| defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 #define __meminit
 #define __meminitdata
 #define __memexit
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 99905e1..0433769 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -36,6 +36,8 @@
 /* LATCH is used in the interval timer and ftape setup. */
 #define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */
 
+#define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ)
+
 /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can
  * improve accuracy by shifting LSH bits, hence calculating:
  *     (NOM << LSH) / DEN
@@ -51,9 +53,13 @@
 /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
 #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))
 
+#define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8))
+
 /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */
 #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))
 
+#define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8))
+
 /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
 #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a3720f9..e1bd084 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -176,7 +176,7 @@
 
 extern void bust_spinlocks(int yes);
 extern int oops_in_progress;		/* If set, an oops, panic(), BUG() or die() is in progress */
-extern __deprecated_for_modules int panic_timeout;
+extern int panic_timeout;
 extern int panic_on_oops;
 extern int tainted;
 extern const char *print_tainted(void);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 4cb1214..c187c53 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -24,6 +24,7 @@
 #include <linux/rwsem.h>
 #include <linux/kref.h>
 #include <linux/kernel.h>
+#include <linux/wait.h>
 #include <asm/atomic.h>
 
 #define KOBJ_NAME_LEN			20
@@ -56,6 +57,7 @@
 	struct kset		* kset;
 	struct kobj_type	* ktype;
 	struct dentry		* dentry;
+	wait_queue_head_t	poll;
 };
 
 extern int kobject_set_name(struct kobject *, const char *, ...)
@@ -255,9 +257,8 @@
 };
 
 extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
-extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
 
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
 void kobject_uevent(struct kobject *kobj, enum kobject_action action);
 
 int add_uevent_var(char **envp, int num_envp, int *cur_index,
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 4617e75..dc23c7c 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -19,39 +19,38 @@
  */
 
 enum led_brightness {
-	LED_OFF = 0,
-	LED_HALF = 127,
-	LED_FULL = 255,
+	LED_OFF		= 0,
+	LED_HALF	= 127,
+	LED_FULL	= 255,
 };
 
 struct led_classdev {
-	const char *name;
-	int brightness;
-	int flags;
-#define LED_SUSPENDED       (1 << 0)
+	const char		*name;
+	int			 brightness;
+	int			 flags;
 
-	/* A function to set the brightness of the led */
-	void (*brightness_set)(struct led_classdev *led_cdev,
-				enum led_brightness brightness);
+#define LED_SUSPENDED		(1 << 0)
 
-	struct class_device *class_dev;
-	/* LED Device linked list */
-	struct list_head node;
+	/* Set LED brightness level */
+	void		(*brightness_set)(struct led_classdev *led_cdev,
+					  enum led_brightness brightness);
 
-	/* Trigger data */
-	char *default_trigger;
+	struct class_device	*class_dev;
+	struct list_head	 node;			/* LED Device list */
+	char			*default_trigger;	/* Trigger to use */
+
 #ifdef CONFIG_LEDS_TRIGGERS
-	rwlock_t trigger_lock;
 	/* Protects the trigger data below */
+	rwlock_t		 trigger_lock;
 
-	struct led_trigger *trigger;
-	struct list_head trig_list;
-	void *trigger_data;
+	struct led_trigger	*trigger;
+	struct list_head	 trig_list;
+	void			*trigger_data;
 #endif
 };
 
 extern int led_classdev_register(struct device *parent,
-				struct led_classdev *led_cdev);
+				 struct led_classdev *led_cdev);
 extern void led_classdev_unregister(struct led_classdev *led_cdev);
 extern void led_classdev_suspend(struct led_classdev *led_cdev);
 extern void led_classdev_resume(struct led_classdev *led_cdev);
@@ -65,16 +64,16 @@
 
 struct led_trigger {
 	/* Trigger Properties */
-	const char *name;
-	void (*activate)(struct led_classdev *led_cdev);
-	void (*deactivate)(struct led_classdev *led_cdev);
+	const char	 *name;
+	void		(*activate)(struct led_classdev *led_cdev);
+	void		(*deactivate)(struct led_classdev *led_cdev);
 
 	/* LEDs under control by this trigger (for simple triggers) */
-	rwlock_t leddev_list_lock;
-	struct list_head led_cdevs;
+	rwlock_t	  leddev_list_lock;
+	struct list_head  led_cdevs;
 
 	/* Link to next registered trigger */
-	struct list_head next_trig;
+	struct list_head  next_trig;
 };
 
 /* Registration functions for complex triggers */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0d61357..b80d2e7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -523,7 +523,6 @@
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
-extern int ata_scsi_error(struct Scsi_Host *host);
 extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 extern int ata_scsi_release(struct Scsi_Host *host);
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 968b1aa..9112063 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -58,8 +58,6 @@
 /* need some defines for these for archs that don't support it */
 extern void online_page(struct page *page);
 /* VM interface that may be used by firmware interface */
-extern int add_memory(u64 start, u64 size);
-extern int remove_memory(u64 start, u64 size);
 extern int online_pages(unsigned long, unsigned long);
 
 /* reasonably generic interface to expand the physical pages in a zone  */
@@ -92,11 +90,6 @@
 	return -ENOSYS;
 }
 
-static inline int __add_pages(struct zone *zone, unsigned long start_pfn,
-	unsigned long nr_pages)
-{
-	return mhp_notimplemented(__FUNCTION__);
-}
 #endif /* ! CONFIG_MEMORY_HOTPLUG */
 static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
 	unsigned long nr_pages)
@@ -105,4 +98,8 @@
 	dump_stack();
 	return -ENOSYS;
 }
+
+extern int add_memory(u64 start, u64 size);
+extern int remove_memory(u64 start, u64 size);
+
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6aa016f..1154684 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -229,10 +229,9 @@
 		unsigned long private;		/* Mapping-private opaque data:
 					 	 * usually used for buffer_heads
 						 * if PagePrivate set; used for
-						 * swp_entry_t if PageSwapCache.
-						 * When page is free, this
+						 * swp_entry_t if PageSwapCache;
 						 * indicates order in the buddy
-						 * system.
+						 * system if PG_buddy is set.
 						 */
 		struct address_space *mapping;	/* If low bit clear, points to
 						 * inode address_space, or NULL.
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index 955d306..edfa012 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_MV643XX_H
 #define __ASM_MV643XX_H
 
-#ifdef __MIPS__
+#ifdef __mips__
 #include <asm/addrspace.h>
 #include <asm/marvell.h>
 #endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 40ccf8c..01db7b8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -829,19 +829,21 @@
 		__netif_rx_schedule(dev);
 }
 
-/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().
- * Do not inline this?
- */
+
+static inline void  __netif_rx_reschedule(struct net_device *dev, int undo)
+{
+	dev->quota += undo;
+	list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
+	__raise_softirq_irqoff(NET_RX_SOFTIRQ);
+}
+
+/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */
 static inline int netif_rx_reschedule(struct net_device *dev, int undo)
 {
 	if (netif_rx_schedule_prep(dev)) {
 		unsigned long flags;
-
-		dev->quota += undo;
-
 		local_irq_save(flags);
-		list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
-		__raise_softirq_irqoff(NET_RX_SOFTIRQ);
+		__netif_rx_reschedule(dev, undo);
 		local_irq_restore(flags);
 		return 1;
 	}
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 412e52c..b31a9bc 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -110,6 +110,8 @@
 /* Function to register/unregister hook points. */
 int nf_register_hook(struct nf_hook_ops *reg);
 void nf_unregister_hook(struct nf_hook_ops *reg);
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
 
 /* Functions to register get/setsockopt ranges (non-inclusive).  You
    need to check permissions yourself! */
@@ -281,16 +283,42 @@
    Returns true or false. */
 extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
 
-struct nf_queue_rerouter {
-	void (*save)(const struct sk_buff *skb, struct nf_info *info);
-	int (*reroute)(struct sk_buff **skb, const struct nf_info *info);
-	int rer_size;
+struct nf_afinfo {
+	unsigned short	family;
+	unsigned int	(*checksum)(struct sk_buff *skb, unsigned int hook,
+				    unsigned int dataoff, u_int8_t protocol);
+	void		(*saveroute)(const struct sk_buff *skb,
+				     struct nf_info *info);
+	int		(*reroute)(struct sk_buff **skb,
+				   const struct nf_info *info);
+	int		route_key_size;
 };
 
-#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
+extern struct nf_afinfo *nf_afinfo[];
+static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
+{
+	return rcu_dereference(nf_afinfo[family]);
+}
 
-extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
-extern int nf_unregister_queue_rerouter(int pf);
+static inline unsigned int
+nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff,
+	    u_int8_t protocol, unsigned short family)
+{
+	struct nf_afinfo *afinfo;
+	unsigned int csum = 0;
+
+	rcu_read_lock();
+	afinfo = nf_get_afinfo(family);
+	if (afinfo)
+		csum = afinfo->checksum(skb, hook, dataoff, protocol);
+	rcu_read_unlock();
+	return csum;
+}
+
+extern int nf_register_afinfo(struct nf_afinfo *afinfo);
+extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
+
+#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
 
 #include <net/flow.h>
 extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 1350e47..3870145 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -142,6 +142,12 @@
 #define ASSERT_WRITE_LOCK(x)
 #include <linux/netfilter_ipv4/listhelp.h>
 
+#ifdef CONFIG_COMPAT
+#define COMPAT_TO_USER		1
+#define COMPAT_FROM_USER	-1
+#define COMPAT_CALC_SIZE	0
+#endif
+
 struct xt_match
 {
 	struct list_head list;
@@ -175,6 +181,9 @@
 	void (*destroy)(const struct xt_match *match, void *matchinfo,
 			unsigned int matchinfosize);
 
+	/* Called when userspace align differs from kernel space one */
+	int (*compat)(void *match, void **dstptr, int *size, int convert);
+
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
 	struct module *me;
 
@@ -220,6 +229,9 @@
 	void (*destroy)(const struct xt_target *target, void *targinfo,
 			unsigned int targinfosize);
 
+	/* Called when userspace align differs from kernel space one */
+	int (*compat)(void *target, void **dstptr, int *size, int convert);
+
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
 	struct module *me;
 
@@ -314,6 +326,65 @@
 extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
 extern void xt_free_table_info(struct xt_table_info *info);
 
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_xt_entry_match
+{
+	union {
+		struct {
+			u_int16_t match_size;
+			char name[XT_FUNCTION_MAXNAMELEN - 1];
+			u_int8_t revision;
+		} user;
+		u_int16_t match_size;
+	} u;
+	unsigned char data[0];
+};
+
+struct compat_xt_entry_target
+{
+	union {
+		struct {
+			u_int16_t target_size;
+			char name[XT_FUNCTION_MAXNAMELEN - 1];
+			u_int8_t revision;
+		} user;
+		u_int16_t target_size;
+	} u;
+	unsigned char data[0];
+};
+
+/* FIXME: this works only on 32 bit tasks
+ * need to change whole approach in order to calculate align as function of
+ * current task alignment */
+
+struct compat_xt_counters
+{
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+	u_int32_t cnt[4];
+#else
+	u_int64_t cnt[2];
+#endif
+};
+
+struct compat_xt_counters_info
+{
+	char name[XT_TABLE_MAXNAMELEN];
+	compat_uint_t num_counters;
+	struct compat_xt_counters counters[0];
+};
+
+#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \
+		& ~(__alignof__(struct compat_xt_counters)-1))
+
+extern void xt_compat_lock(int af);
+extern void xt_compat_unlock(int af);
+extern int xt_compat_match(void *match, void **dstptr, int *size, int convert);
+extern int xt_compat_target(void *target, void **dstptr, int *size,
+		int convert);
+
+#endif /* CONFIG_COMPAT */
 #endif /* __KERNEL__ */
 
 #endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_esp.h b/include/linux/netfilter/xt_esp.h
new file mode 100644
index 0000000..9380fb1
--- /dev/null
+++ b/include/linux/netfilter/xt_esp.h
@@ -0,0 +1,14 @@
+#ifndef _XT_ESP_H
+#define _XT_ESP_H
+
+struct xt_esp
+{
+	u_int32_t spis[2];	/* Security Parameter Index */
+	u_int8_t  invflags;	/* Inverse flags */
+};
+
+/* Values for "invflags" field in struct xt_esp. */
+#define XT_ESP_INV_SPI	0x01	/* Invert the sense of spi. */
+#define XT_ESP_INV_MASK	0x01	/* All possible flags. */
+
+#endif /*_XT_ESP_H*/
diff --git a/include/linux/netfilter/xt_multiport.h b/include/linux/netfilter/xt_multiport.h
new file mode 100644
index 0000000..d49ee41
--- /dev/null
+++ b/include/linux/netfilter/xt_multiport.h
@@ -0,0 +1,30 @@
+#ifndef _XT_MULTIPORT_H
+#define _XT_MULTIPORT_H
+
+enum xt_multiport_flags
+{
+	XT_MULTIPORT_SOURCE,
+	XT_MULTIPORT_DESTINATION,
+	XT_MULTIPORT_EITHER
+};
+
+#define XT_MULTI_PORTS	15
+
+/* Must fit inside union xt_matchinfo: 16 bytes */
+struct xt_multiport
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[XT_MULTI_PORTS];	/* Ports */
+};
+
+struct xt_multiport_v1
+{
+	u_int8_t flags;				/* Type of comparison */
+	u_int8_t count;				/* Number of ports */
+	u_int16_t ports[XT_MULTI_PORTS];	/* Ports */
+	u_int8_t pflags[XT_MULTI_PORTS];	/* Port flags */
+	u_int8_t invert;			/* Invert flag */
+};
+
+#endif /*_XT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 43c09d7..85301c5 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -80,6 +80,8 @@
 #ifdef __KERNEL__
 extern int ip_route_me_harder(struct sk_buff **pskb);
 extern int ip_xfrm_me_harder(struct sk_buff **pskb);
+extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+				   unsigned int dataoff, u_int8_t protocol);
 #endif /*__KERNEL__*/
 
 #endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index 0987cea..eace86b 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -3,6 +3,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
+
 #define RAS_PORT 1719
 #define Q931_PORT 1720
 #define H323_RTP_CHANNEL_MAX 4	/* Audio, video, FAX and other */
@@ -25,6 +27,56 @@
 	};
 };
 
+struct ip_conntrack_expect;
+
+extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
+			 u_int32_t * ip, u_int16_t * port);
+extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
+				     struct ip_conntrack_expect *this);
+extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
+				     struct ip_conntrack_expect *this);
+extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
+				  unsigned char **data, int dataoff,
+				  H245_TransportAddress * addr,
+				  u_int32_t ip, u_int16_t port);
+extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
+				  unsigned char **data, int dataoff,
+				  TransportAddress * addr,
+				  u_int32_t ip, u_int16_t port);
+extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
+				 struct ip_conntrack * ct,
+				 enum ip_conntrack_info ctinfo,
+				 unsigned char **data,
+				 TransportAddress * addr, int count);
+extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
+				 struct ip_conntrack * ct,
+				 enum ip_conntrack_info ctinfo,
+				 unsigned char **data,
+				 TransportAddress * addr, int count);
+extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
+				 struct ip_conntrack * ct,
+				 enum ip_conntrack_info ctinfo,
+				 unsigned char **data, int dataoff,
+				 H245_TransportAddress * addr,
+				 u_int16_t port, u_int16_t rtp_port,
+				 struct ip_conntrack_expect * rtp_exp,
+				 struct ip_conntrack_expect * rtcp_exp);
+extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+			     enum ip_conntrack_info ctinfo,
+			     unsigned char **data, int dataoff,
+			     H245_TransportAddress * addr, u_int16_t port,
+			     struct ip_conntrack_expect * exp);
+extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+			     enum ip_conntrack_info ctinfo,
+			     unsigned char **data, int dataoff,
+			     TransportAddress * addr, u_int16_t port,
+			     struct ip_conntrack_expect * exp);
+extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
+			     enum ip_conntrack_info ctinfo,
+			     unsigned char **data, TransportAddress * addr,
+			     int idx, u_int16_t port,
+			     struct ip_conntrack_expect * exp);
+
 #endif
 
 #endif
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
similarity index 100%
rename from net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h
rename to include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
similarity index 100%
rename from net/ipv4/netfilter/ip_conntrack_helper_h323_types.h
rename to include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index d5b8c0d..c0dac16 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -316,5 +316,23 @@
 				 void *userdata);
 
 #define IPT_ALIGN(s) XT_ALIGN(s)
+
+#ifdef CONFIG_COMPAT
+#include <net/compat.h>
+
+struct compat_ipt_entry
+{
+	struct ipt_ip ip;
+	compat_uint_t nfcache;
+	u_int16_t target_offset;
+	u_int16_t next_offset;
+	compat_uint_t comefrom;
+	struct compat_xt_counters counters;
+	unsigned char elems[0];
+};
+
+#define COMPAT_IPT_ALIGN(s) 	COMPAT_XT_ALIGN(s)
+
+#endif /* CONFIG_COMPAT */
 #endif /*__KERNEL__*/
 #endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ipt_esp.h b/include/linux/netfilter_ipv4/ipt_esp.h
index c782a83..78296e7 100644
--- a/include/linux/netfilter_ipv4/ipt_esp.h
+++ b/include/linux/netfilter_ipv4/ipt_esp.h
@@ -1,16 +1,10 @@
 #ifndef _IPT_ESP_H
 #define _IPT_ESP_H
 
-struct ipt_esp
-{
-	u_int32_t spis[2];			/* Security Parameter Index */
-	u_int8_t  invflags;			/* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
 
-
-
-/* Values for "invflags" field in struct ipt_esp. */
-#define IPT_ESP_INV_SPI		0x01	/* Invert the sense of spi. */
-#define IPT_ESP_INV_MASK	0x01	/* All possible flags. */
+#define ipt_esp xt_esp
+#define IPT_ESP_INV_SPI		XT_ESP_INV_SPI
+#define IPT_ESP_INV_MASK	XT_ESP_INV_MASK
 
 #endif /*_IPT_ESP_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_multiport.h b/include/linux/netfilter_ipv4/ipt_multiport.h
index e6b6fff..55fe85e 100644
--- a/include/linux/netfilter_ipv4/ipt_multiport.h
+++ b/include/linux/netfilter_ipv4/ipt_multiport.h
@@ -1,30 +1,15 @@
 #ifndef _IPT_MULTIPORT_H
 #define _IPT_MULTIPORT_H
-#include <linux/netfilter_ipv4/ip_tables.h>
 
-enum ipt_multiport_flags
-{
-	IPT_MULTIPORT_SOURCE,
-	IPT_MULTIPORT_DESTINATION,
-	IPT_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
 
-#define IPT_MULTI_PORTS	15
+#define IPT_MULTIPORT_SOURCE		XT_MULTIPORT_SOURCE
+#define IPT_MULTIPORT_DESTINATION	XT_MULTIPORT_DESTINATION
+#define IPT_MULTIPORT_EITHER		XT_MULTIPORT_EITHER
 
-/* Must fit inside union ipt_matchinfo: 16 bytes */
-struct ipt_multiport
-{
-	u_int8_t flags;				/* Type of comparison */
-	u_int8_t count;				/* Number of ports */
-	u_int16_t ports[IPT_MULTI_PORTS];	/* Ports */
-};
+#define IPT_MULTI_PORTS			XT_MULTI_PORTS
 
-struct ipt_multiport_v1
-{
-	u_int8_t flags;				/* Type of comparison */
-	u_int8_t count;				/* Number of ports */
-	u_int16_t ports[IPT_MULTI_PORTS];	/* Ports */
-	u_int8_t pflags[IPT_MULTI_PORTS];	/* Port flags */
-	u_int8_t invert;			/* Invert flag */
-};
+#define ipt_multiport			xt_multiport
+#define ipt_multiport_v1		xt_multiport_v1
+
 #endif /*_IPT_MULTIPORT_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 14f2bd0..52a7b9e 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -73,6 +73,9 @@
 };
 
 #ifdef CONFIG_NETFILTER
+extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+				    unsigned int dataoff, u_int8_t protocol);
+
 extern int ipv6_netfilter_init(void);
 extern void ipv6_netfilter_fini(void);
 #else /* CONFIG_NETFILTER */
diff --git a/include/linux/netfilter_ipv6/ip6t_esp.h b/include/linux/netfilter_ipv6/ip6t_esp.h
index a91b6ab..f62eaf5 100644
--- a/include/linux/netfilter_ipv6/ip6t_esp.h
+++ b/include/linux/netfilter_ipv6/ip6t_esp.h
@@ -1,14 +1,10 @@
 #ifndef _IP6T_ESP_H
 #define _IP6T_ESP_H
 
-struct ip6t_esp
-{
-	u_int32_t spis[2];			/* Security Parameter Index */
-	u_int8_t  invflags;			/* Inverse flags */
-};
+#include <linux/netfilter/xt_esp.h>
 
-/* Values for "invflags" field in struct ip6t_esp. */
-#define IP6T_ESP_INV_SPI		0x01	/* Invert the sense of spi. */
-#define IP6T_ESP_INV_MASK	0x01	/* All possible flags. */
+#define ip6t_esp xt_esp
+#define IP6T_ESP_INV_SPI	XT_ESP_INV_SPI
+#define IP6T_ESP_INV_MASK	XT_ESP_INV_MASK
 
 #endif /*_IP6T_ESP_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_multiport.h b/include/linux/netfilter_ipv6/ip6t_multiport.h
index efe4954..042c926 100644
--- a/include/linux/netfilter_ipv6/ip6t_multiport.h
+++ b/include/linux/netfilter_ipv6/ip6t_multiport.h
@@ -1,21 +1,14 @@
 #ifndef _IP6T_MULTIPORT_H
 #define _IP6T_MULTIPORT_H
-#include <linux/netfilter_ipv6/ip6_tables.h>
 
-enum ip6t_multiport_flags
-{
-	IP6T_MULTIPORT_SOURCE,
-	IP6T_MULTIPORT_DESTINATION,
-	IP6T_MULTIPORT_EITHER
-};
+#include <linux/netfilter/xt_multiport.h>
 
-#define IP6T_MULTI_PORTS	15
+#define IP6T_MULTIPORT_SOURCE		XT_MULTIPORT_SOURCE
+#define IP6T_MULTIPORT_DESTINATION	XT_MULTIPORT_DESTINATION
+#define IP6T_MULTIPORT_EITHER		XT_MULTIPORT_EITHER
 
-/* Must fit inside union ip6t_matchinfo: 16 bytes */
-struct ip6t_multiport
-{
-	u_int8_t flags;				/* Type of comparison */
-	u_int8_t count;				/* Number of ports */
-	u_int16_t ports[IP6T_MULTI_PORTS];	/* Ports */
-};
-#endif /*_IPT_MULTIPORT_H*/
+#define IP6T_MULTI_PORTS		XT_MULTI_PORTS
+
+#define ip6t_multiport			xt_multiport
+
+#endif /*_IP6T_MULTIPORT_H*/
diff --git a/include/linux/numa.h b/include/linux/numa.h
index f0c539b..e481feb 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -3,11 +3,9 @@
 
 #include <linux/config.h>
 
-#ifndef CONFIG_FLATMEM
-#include <asm/numnodes.h>
-#endif
-
-#ifndef NODES_SHIFT
+#ifdef CONFIG_NODES_SHIFT
+#define NODES_SHIFT     CONFIG_NODES_SHIFT
+#else
 #define NODES_SHIFT     0
 #endif
 
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 9ea629c..d276a4e 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -48,8 +48,20 @@
 
 /*
  * Don't use the *_dontuse flags.  Use the macros.  Otherwise you'll break
- * locked- and dirty-page accounting.  The top eight bits of page->flags are
- * used for page->zone, so putting flag bits there doesn't work.
+ * locked- and dirty-page accounting.
+ *
+ * The page flags field is split into two parts, the main flags area
+ * which extends from the low bits upwards, and the fields area which
+ * extends from the high bits downwards.
+ *
+ *  | FIELD | ... | FLAGS |
+ *  N-1     ^             0
+ *          (N-FLAGS_RESERVED)
+ *
+ * The fields area is reserved for fields mapping zone, node and SPARSEMEM
+ * section.  The boundry between these two areas is defined by
+ * FLAGS_RESERVED which defines the width of the fields section
+ * (see linux/mmzone.h).  New flags must _not_ overlap with this area.
  */
 #define PG_locked	 	 0	/* Page is locked. Don't touch. */
 #define PG_error		 1
@@ -74,7 +86,9 @@
 #define PG_mappedtodisk		16	/* Has blocks allocated on-disk */
 #define PG_reclaim		17	/* To be reclaimed asap */
 #define PG_nosave_free		18	/* Free, should not be written */
-#define PG_uncached		19	/* Page has been mapped as uncached */
+#define PG_buddy		19	/* Page is free, on buddy lists */
+
+#define PG_uncached		20	/* Page has been mapped as uncached */
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
@@ -317,6 +331,10 @@
 #define SetPageNosaveFree(page)	set_bit(PG_nosave_free, &(page)->flags)
 #define ClearPageNosaveFree(page)		clear_bit(PG_nosave_free, &(page)->flags)
 
+#define PageBuddy(page)		test_bit(PG_buddy, &(page)->flags)
+#define __SetPageBuddy(page)	__set_bit(PG_buddy, &(page)->flags)
+#define __ClearPageBuddy(page)	__clear_bit(PG_buddy, &(page)->flags)
+
 #define PageMappedToDisk(page)	test_bit(PG_mappedtodisk, &(page)->flags)
 #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
 #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9539efd..7a1af57 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -78,6 +78,8 @@
 				unsigned long index, gfp_t gfp_mask);
 unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
 			unsigned int nr_pages, struct page **pages);
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
+			       unsigned int nr_pages, struct page **pages);
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
 			int tag, unsigned int nr_pages, struct page **pages);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0aad5a3..3a6a4e3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -97,7 +97,13 @@
 
 typedef unsigned short __bitwise pci_bus_flags_t;
 enum pci_bus_flags {
-	PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1,
+	PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+};
+
+struct pci_cap_saved_state {
+	struct hlist_node next;
+	char cap_nr;
+	u32 data[0];
 };
 
 /*
@@ -159,6 +165,7 @@
 	unsigned int	block_ucfg_access:1;	/* userspace config space access is blocked */
 
 	u32		saved_config_space[16]; /* config space saved at suspend time */
+	struct hlist_head saved_cap_space;
 	struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
 	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
@@ -169,6 +176,30 @@
 #define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
 #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
 
+static inline struct pci_cap_saved_state *pci_find_saved_cap(
+	struct pci_dev *pci_dev,char cap)
+{
+	struct pci_cap_saved_state *tmp;
+	struct hlist_node *pos;
+
+	hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) {
+		if (tmp->cap_nr == cap)
+			return tmp;
+	}
+	return NULL;
+}
+
+static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
+	struct pci_cap_saved_state *new_cap)
+{
+	hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space);
+}
+
+static inline void pci_remove_saved_cap(struct pci_cap_saved_state *cap)
+{
+	hlist_del(&cap->next);
+}
+
 /*
  *  For PCI devices, the region numbers are assigned this way:
  *
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 870fe38..d6fe048 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -356,6 +356,10 @@
 #define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
 #define PCI_DEVICE_ID_ATI_IXP400_IDE	0x4376
 #define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2	0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA	0x4380
+#define PCI_DEVICE_ID_ATI_IXP600_SRAID	0x4381
+#define PCI_DEVICE_ID_ATI_IXP600_IDE	0x438c
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
@@ -497,7 +501,8 @@
 #define PCI_DEVICE_ID_AMD_8111_SMBUS	0x746b
 #define PCI_DEVICE_ID_AMD_8111_AUDIO	0x746d
 #define PCI_DEVICE_ID_AMD_8151_0	0x7454
-#define PCI_DEVICE_ID_AMD_8131_APIC     0x7450
+#define PCI_DEVICE_ID_AMD_8131_BRIDGE	0x7450
+#define PCI_DEVICE_ID_AMD_8131_APIC	0x7451
 #define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
 #define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
 #define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 75c7f55..0008d4b 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,11 +5,14 @@
 
 #define PIPE_BUFFERS (16)
 
+#define PIPE_BUF_FLAG_STOLEN	0x01
+#define PIPE_BUF_FLAG_LRU	0x02
+
 struct pipe_buffer {
 	struct page *page;
 	unsigned int offset, len;
 	struct pipe_buf_operations *ops;
-	unsigned int stolen;
+	unsigned int flags;
 };
 
 struct pipe_buf_operations {
@@ -18,6 +21,7 @@
 	void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *);
 	void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
 	int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+	void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
 };
 
 struct pipe_inode_info {
@@ -33,32 +37,45 @@
 	unsigned int w_counter;
 	struct fasync_struct *fasync_readers;
 	struct fasync_struct *fasync_writers;
+	struct inode *inode;
 };
 
 /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
    memory allocation, whereas PIPE_BUF makes atomicity guarantees.  */
 #define PIPE_SIZE		PAGE_SIZE
 
-#define PIPE_MUTEX(inode)	(&(inode).i_mutex)
-#define PIPE_WAIT(inode)	(&(inode).i_pipe->wait)
-#define PIPE_READERS(inode)	((inode).i_pipe->readers)
-#define PIPE_WRITERS(inode)	((inode).i_pipe->writers)
-#define PIPE_WAITING_WRITERS(inode)	((inode).i_pipe->waiting_writers)
-#define PIPE_RCOUNTER(inode)	((inode).i_pipe->r_counter)
-#define PIPE_WCOUNTER(inode)	((inode).i_pipe->w_counter)
-#define PIPE_FASYNC_READERS(inode)     (&((inode).i_pipe->fasync_readers))
-#define PIPE_FASYNC_WRITERS(inode)     (&((inode).i_pipe->fasync_writers))
-
 /* Drop the inode semaphore and wait for a pipe event, atomically */
-void pipe_wait(struct inode * inode);
+void pipe_wait(struct pipe_inode_info *pipe);
 
-struct inode* pipe_new(struct inode* inode);
-void free_pipe_info(struct inode* inode);
+struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
+void free_pipe_info(struct inode * inode);
+void __free_pipe_info(struct pipe_inode_info *);
 
 /*
  * splice is tied to pipes as a transport (at least for now), so we'll just
  * add the splice flags here.
  */
 #define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+				 /* we may still block on the fd we splice */
+				 /* from/to, of course */
+#define SPLICE_F_MORE	(0x04)	/* expect more data */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+	unsigned int len, total_len;	/* current and remaining length */
+	unsigned int flags;		/* splice flags */
+	struct file *file;		/* file to read/write */
+	loff_t pos;			/* file position */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+			   struct splice_desc *);
+
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+				loff_t *, size_t, unsigned int,
+				splice_actor *);
 
 #endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 6df2585..66be589 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -199,6 +199,12 @@
 
 extern int dpm_runtime_suspend(struct device *, pm_message_t);
 extern void dpm_runtime_resume(struct device *);
+extern void __suspend_report_result(const char *function, void *fn, int ret);
+
+#define suspend_report_result(fn, ret)					\
+	do {								\
+		__suspend_report_result(__FUNCTION__, fn, ret);		\
+	} while (0)
 
 #else /* !CONFIG_PM */
 
@@ -219,6 +225,8 @@
 {
 }
 
+#define suspend_report_result(fn, ret) do { } while (0)
+
 #endif
 
 /* changes to device_may_wakeup take effect on the next pm state change.
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
index 1252b45..008932d 100644
--- a/include/linux/pm_legacy.h
+++ b/include/linux/pm_legacy.h
@@ -16,11 +16,6 @@
 pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
 
 /*
- * Unregister a device with power management
- */
-void __deprecated pm_unregister(struct pm_dev *dev);
-
-/*
  * Unregister all devices with matching callback
  */
 void __deprecated pm_unregister_all(pm_callback callback);
@@ -41,8 +36,6 @@
 	return NULL;
 }
 
-static inline void pm_unregister(struct pm_dev *dev) {}
-
 static inline void pm_unregister_all(pm_callback callback) {}
 
 static inline int pm_send_all(pm_request_t rqst, void *data)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 135871d..4b47a02 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -79,7 +79,7 @@
 struct vmcore {
 	struct list_head list;
 	unsigned long long paddr;
-	unsigned long size;
+	unsigned long long size;
 	loff_t offset;
 };
 
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 774e1ac..f1fbae7 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -227,8 +227,8 @@
 				 */
 
 	/* These are only valid with feature bit '4' */
-	__u64	reshape_position;	/* next address in array-space for reshape */
 	__u32	new_level;	/* new level we are reshaping to		*/
+	__u64	reshape_position;	/* next address in array-space for reshape */
 	__u32	delta_disks;	/* change in number of raid_disks		*/
 	__u32	new_layout;	/* new layout					*/
 	__u32	new_chunk;	/* new chunk size (bytes)			*/
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 541f482..29b7d4f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -684,6 +684,7 @@
 
 struct audit_context;		/* See audit.c */
 struct mempolicy;
+struct pipe_inode_info;
 
 enum sleep_type {
 	SLEEP_NORMAL,
@@ -882,6 +883,11 @@
 
 	atomic_t fs_excl;	/* holding fs exclusive resources */
 	struct rcu_head rcu;
+
+	/*
+	 * cache last used pipe for splice
+	 */
+	struct pipe_inode_info *splice_pipe;
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
@@ -905,7 +911,6 @@
 extern void free_task(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 
-extern void __put_task_struct_cb(struct rcu_head *rhp);
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
@@ -1187,8 +1192,7 @@
 #define remove_parent(p)	list_del_init(&(p)->sibling)
 #define add_parent(p)		list_add_tail(&(p)->sibling,&(p)->parent->children)
 
-#define next_task(p)	list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p)	list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p)	list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
 
 #define for_each_process(p) \
 	for (p = &init_task ; (p = next_task(p)) != &init_task ; )
@@ -1203,9 +1207,10 @@
 #define while_each_thread(g, t) \
 	while ((t = next_thread(t)) != g)
 
-#define thread_group_leader(p)	(p->pid == p->tgid)
+/* de_thread depends on thread_group_leader not being a pid based check */
+#define thread_group_leader(p)	(p == p->group_leader)
 
-static inline task_t *next_thread(task_t *p)
+static inline task_t *next_thread(const task_t *p)
 {
 	return list_entry(rcu_dereference(p->thread_group.next),
 				task_t, thread_group);
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 6336987..2925e66 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -41,7 +41,8 @@
 	u16 vesapm_off;		/* 0x30 */
 	u16 pages;		/* 0x32 */
 	u16 vesa_attributes;	/* 0x34 */
-				/* 0x36 -- 0x3f reserved for future expansion */
+	u32 capabilities;       /* 0x36 */
+				/* 0x3a -- 0x3f reserved for future expansion */
 };
 
 extern struct screen_info screen_info;
diff --git a/include/linux/sdla_asy.h b/include/linux/sdla_asy.h
deleted file mode 100644
index f622425..0000000
--- a/include/linux/sdla_asy.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*****************************************************************************
-* sdla_asy.h	Header file for the Sangoma S508/S514 asynchronous code API	
-*
-* Author: 	Gideon Hack 	
-*
-* Copyright:	(c) 2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-*
-* Jan 28, 2000	Gideon Hack 	Initial Version
-*
-*****************************************************************************/
-
-
-#ifndef _WANPIPE_ASYNC_H
-#define _WANPIPE_ASYNC_H
-
-/* ----------------------------------------------------------------------------
- *                        Interface commands
- * --------------------------------------------------------------------------*/
-
-#define SET_ASY_CONFIGURATION		0xE2	/* set the asychronous operational configuration */
-#define READ_ASY_CONFIGURATION		0xE3	/* read the current asychronous operational configuration */
-#define ENABLE_ASY_COMMUNICATIONS	0xE4	/* enable asychronous communications */
-#define DISABLE_ASY_COMMUNICATIONS	0xE5	/* disable asychronous communications */
-#define READ_ASY_OPERATIONAL_STATS	0xE7	/* retrieve the asychronous operational statistics */
-#define FLUSH_ASY_OPERATIONAL_STATS	0xE8	/* flush the asychronous operational statistics */
-#define TRANSMIT_ASY_BREAK_SIGNAL	0xEC	/* transmit an asychronous break signal */
-
-
-
-/* ----------------------------------------------------------------------------
- *                     Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_INVALID_FOR_PORT	0x50	/* the command is invalid for the selected port */
-#define DISABLE_ASY_COMMS_BEFORE_CFG 	0xE1	/* communications must be disabled before setting the configuration */
-#define ASY_COMMS_ENABLED		0xE1	/* communications are currently enabled */
-#define ASY_COMMS_DISABLED		0xE1	/* communications are currently disabled */
-#define ASY_CFG_BEFORE_COMMS_ENABLED	0xE2	/* perform a SET_ASY_CONFIGURATION before enabling comms */
-#define LGTH_ASY_CFG_DATA_INVALID  	0xE2	/* the length of the passed configuration data is invalid */
-#define INVALID_ASY_CFG_DATA		0xE3	/* the passed configuration data is invalid */
-#define ASY_BREAK_SIGNAL_BUSY		0xEC	/* a break signal is being transmitted */
-
-
-
-/* ----------------------------------------------------------------------------
- *   Constants for the SET_ASY_CONFIGURATION/READ_ASY_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous configuration structure */
-typedef struct {
-	unsigned long baud_rate			PACKED;							/* the baud rate */	
-	unsigned short line_config_options	PACKED;	/* line configuration options */
-	unsigned short modem_config_options	PACKED;	/* modem configuration options */
-	unsigned short asy_API_options		PACKED;	/* asynchronous API options */
-	unsigned short asy_protocol_options	PACKED; /* asynchronous protocol options */
-	unsigned short Tx_bits_per_char		PACKED;	/* number of bits per tx character */
-	unsigned short Rx_bits_per_char		PACKED;	/* number of bits per received character */
-	unsigned short stop_bits		PACKED;	/* number of stop bits per character */
-	unsigned short parity			PACKED;	/* parity definition */
-	unsigned short break_timer		PACKED;	/* the break signal timer */
-	unsigned short asy_Rx_inter_char_timer	PACKED;	/* the receive inter-character timer */
-	unsigned short asy_Rx_complete_length	PACKED;	/* the receive 'buffer complete' length */
-	unsigned short XON_char			PACKED;	/* the XON character */
-	unsigned short XOFF_char		PACKED;	/* the XOFF character */
-	unsigned short asy_statistics_options	PACKED;	/* async operational stat options */
-	unsigned long ptr_shared_mem_info_struct    PACKED;/* ptr to the shared memory area information structure */
-	unsigned long ptr_asy_Tx_stat_el_cfg_struct PACKED;/* ptr to the transmit status element configuration structure */
-	unsigned long ptr_asy_Rx_stat_el_cfg_struct PACKED;/* ptr to the receive status element configuration structure */
-} ASY_CONFIGURATION_STRUCT;
-
-/* permitted minimum and maximum values for setting the asynchronous configuration */
-#define MIN_ASY_BAUD_RATE		50	/* maximum baud rate */
-#define MAX_ASY_BAUD_RATE		250000	/* minimum baud rate */
-#define MIN_ASY_BITS_PER_CHAR		5	/* minimum number of bits per character */
-#define MAX_ASY_BITS_PER_CHAR		8	/* maximum number of bits per character */
-#define MIN_BREAK_TMR_VAL		0	/* minimum break signal timer */
-#define MAX_BREAK_TMR_VAL		5000	/* maximum break signal timer */
-#define MIN_ASY_RX_INTER_CHAR_TMR	0	/* minimum receive inter-character timer */
-#define MAX_ASY_RX_INTER_CHAR_TMR	30000	/* maximum receive inter-character timer */
-#define MIN_ASY_RX_CPLT_LENGTH		0	/* minimum receive 'length complete' value */
-#define MAX_ASY_RX_CPLT_LENGTH		2000	/* maximum receive 'length complete' value */
-
-/* bit settings for the 'asy_API_options' */
-#define ASY_RX_DATA_TRANSPARENT		0x0001	/* do not strip parity and unused bits from received characters */
-
-/* bit settings for the 'asy_protocol_options' */
-#define ASY_RTS_HS_FOR_RX		0x0001	/* RTS handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_RX		0x0002	/* XON/XOFF handshaking is used for reception control */
-#define ASY_XON_XOFF_HS_FOR_TX		0x0004	/* XON/XOFF handshaking is used for transmission control */
-#define ASY_DCD_HS_FOR_TX		0x0008	/* DCD handshaking is used for transmission control */
-#define ASY_CTS_HS_FOR_TX		0x0020	/* CTS handshaking is used for transmission control */
-
-/* bit settings for the 'stop_bits' definition */
-#define ONE_STOP_BIT			1			/* representation for 1 stop bit */
-#define TWO_STOP_BITS			2			/* representation for 2 stop bits */
-#define ONE_AND_A_HALF_STOP_BITS	3			/* representation for 1.5 stop bits */
-
-/* bit settings for the 'parity' definition */
-#define NO_PARITY			0			/* representation for no parity */
-#define ODD_PARITY			1			/* representation for odd parity */
-#define EVEN_PARITY			2			/* representation for even parity */
-
-
-
-/* ----------------------------------------------------------------------------
- *    Constants for the READ_COMMS_ERROR_STATS command (asynchronous mode)
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
-	unsigned short Rx_overrun_err_count   	PACKED;	/* receiver overrun error count */
-	unsigned short Rx_parity_err_count	PACKED;	/* parity errors received count */
-	unsigned short Rx_framing_err_count	PACKED;	/* framing errors received count */
-	unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later use */
-	unsigned short comms_err_stat_reserved_2 PACKED;/* reserved for later use */
-	unsigned short comms_err_stat_reserved_3 PACKED;/* reserved for later use */
-	unsigned short comms_err_stat_reserved_4 PACKED;/* reserved for later use */
-	unsigned short comms_err_stat_reserved_5 PACKED;/* reserved for later use */
-	unsigned short DCD_state_change_count 	PACKED;	/* DCD state change count */
-	unsigned short CTS_state_change_count	PACKED;	/* CTS state change count */
-} ASY_COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *         Constants for the READ_ASY_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the asynchronous operational statistics structure */
-typedef struct {
-
-	/* Data transmission statistics */
-	unsigned long Data_blocks_Tx_count PACKED;/* number of blocks transmitted */
-	unsigned long Data_bytes_Tx_count  PACKED;/* number of bytes transmitted */
-	unsigned long Data_Tx_throughput   PACKED;/* transmit throughput */
-	unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;/* millisecond time used for the Tx throughput computation */
-	unsigned long Tx_Data_discard_lgth_err_count PACKED;/* number of Data blocks discarded (length error) */
-	unsigned long reserved_Data_frm_Tx_stat1 PACKED;/* reserved for later use */
-	unsigned long reserved_Data_frm_Tx_stat2 PACKED;/* reserved for later use */
-	unsigned long reserved_Data_frm_Tx_stat3 PACKED;/* reserved for later use */
-
-	/* Data reception statistics */
-	unsigned long Data_blocks_Rx_count PACKED;/* number of blocks received */
-	unsigned long Data_bytes_Rx_count  PACKED;/* number of bytes received */
-	unsigned long Data_Rx_throughput   PACKED;/* receive throughput */
-	unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;/* millisecond time used for the Rx throughput computation */
-	unsigned long Rx_Data_bytes_discard_count    PACKED;/* received Data bytes discarded */
-	unsigned long reserved_Data_frm_Rx_stat1     PACKED;/* reserved for later use */
-
-	/* handshaking protocol statistics */
-	unsigned short XON_chars_Tx_count	PACKED;	/* number of XON characters transmitted */
-	unsigned short XOFF_chars_Tx_count	PACKED;	/* number of XOFF characters transmitted */
-	unsigned short XON_chars_Rx_count	PACKED;	/* number of XON characters received */
-	unsigned short XOFF_chars_Rx_count	PACKED;	/* number of XOFF characters received */
-	unsigned short Tx_halt_modem_low_count	PACKED; /* number of times Tx halted (modem line low) */
-	unsigned short Rx_halt_RTS_low_count	PACKED;	/* number of times Rx halted by setting RTS low */
-	unsigned long reserved_handshaking_stat1 PACKED;/* reserved for later use */
-
-	/* break statistics */
-	unsigned short break_Tx_count	PACKED;	/* number of break sequences transmitted */
-	unsigned short break_Rx_count	PACKED;	/* number of break sequences received */
-	unsigned long reserved_break_stat1 PACKED;/* reserved for later use */
-
-	/* miscellaneous statistics */
-	unsigned long reserved_misc_stat1	PACKED;	/* reserved for later use */
-	unsigned long reserved_misc_stat2	PACKED;	/* reserved for later use */
-
-} ASY_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *                      Constants for Data transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data block transmit status element configuration structure */
-typedef struct {
-	unsigned short number_Tx_status_elements PACKED;		/* number of transmit status elements */
-	unsigned long base_addr_Tx_status_elements PACKED;	/* base address of the transmit element list */
-	unsigned long next_Tx_status_element_to_use PACKED;	/* pointer to the next transmit element to be used */
-} ASY_TX_STATUS_EL_CFG_STRUCT;
-
-
-/* the Data block transmit status element structure */
-typedef struct {
-	unsigned char opp_flag PACKED;								/* opp flag */
-	unsigned short data_length PACKED;						/* length of the block to be transmitted */
-	unsigned char reserved_1 PACKED;							/* reserved for internal use */
-	unsigned long reserved_2 PACKED;							/* reserved for internal use */
-	unsigned long reserved_3 PACKED;							/* reserved for internal use */
-	unsigned long ptr_data_bfr PACKED;						/* pointer to the data area */
-} ASY_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *                      Constants for Data reception
- * --------------------------------------------------------------------------*/
-
-/* the Data block receive status element configuration structure */
-typedef struct {
-	unsigned short number_Rx_status_elements    PACKED;/* number of receive status elements */
-	unsigned long base_addr_Rx_status_elements  PACKED;/* base address of the receive element list */
-	unsigned long next_Rx_status_element_to_use PACKED;/* pointer to the next receive element to be used */
-	unsigned long base_addr_Rx_buffer	PACKED;/* base address of the receive data buffer */
-	unsigned long end_addr_Rx_buffer 	PACKED;/* end address of the receive data buffer */
-} ASY_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data block receive status element structure */
-typedef struct {
-	unsigned char opp_flag 		PACKED;	/* opp flag */
-	unsigned short data_length 	PACKED;	/* length of the received data block */
-	unsigned char reserved_1 	PACKED;	/* reserved for internal use */
-	unsigned short time_stamp 	PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
-	unsigned short data_buffered 	PACKED;	/* the number of data bytes still buffered */
-	unsigned long reserved_2 	PACKED;	/* reserved for internal use */
-	unsigned long ptr_data_bfr 	PACKED;	/* pointer to the data area */
-} ASY_DATA_RX_STATUS_EL_STRUCT;
-
-#endif
diff --git a/include/linux/sdla_chdlc.h b/include/linux/sdla_chdlc.h
deleted file mode 100644
index d2e35a2..0000000
--- a/include/linux/sdla_chdlc.h
+++ /dev/null
@@ -1,813 +0,0 @@
-/*************************************************************************
- sdla_chdlc.h	Sangoma Cisco HDLC firmware API definitions
-
- Author:      	Gideon Hack
-		Nenad Corbic <ncorbic@sangoma.com>	
-
- Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-
-		This program is free software; you can redistribute it and/or
-		modify it under the term 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.
-
-===========================================================================
-  Oct 04, 1999  Nenad Corbic    Updated API support
-  Jun 02, 1999  Gideon Hack     Changes for S514 usage.
-  Oct 28, 1998	Jaspreet Singh	Made changes for Dual Port CHDLC.
-  Jun 11, 1998	David Fong	Initial version.
-===========================================================================
-
- Organization
-	- Compatibility notes
-	- Constants defining the shared memory control block (mailbox)
-	- Interface commands
-	- Return code from interface commands
-	- Constants for the commands (structures for casting data)
-	- UDP Management constants and structures
-
-*************************************************************************/
-
-#ifndef _SDLA_CHDLC_H
-#  define _SDLC_CHDLC_H
-
-/*------------------------------------------------------------------------
-   Notes:
-
-	All structres defined in this file are byte-aligned.  
-
-	Compiler	Platform
-	------------------------
-	GNU C		Linux
-
-------------------------------------------------------------------------*/
-
-#ifndef	PACKED
-#define	PACKED __attribute__((packed))
-#endif	/* PACKED */
-
-
-/* ----------------------------------------------------------------------------
- *        Constants defining the shared memory control block (mailbox)
- * --------------------------------------------------------------------------*/
-
-#define PRI_BASE_ADDR_MB_STRUCT 	0xE000 	/* the base address of the mailbox structure on the adapter */
-#define SEC_BASE_ADDR_MB_STRUCT 	0xE800 	/* the base address of the mailbox structure on the adapter */
-#define SIZEOF_MB_DATA_BFR		2032	/* the size of the actual mailbox data area */
-#define NUMBER_MB_RESERVED_BYTES	0x0B	/* the number of reserved bytes in the mailbox header area */
-
-
-#define MIN_LGTH_CHDLC_DATA_CFG  	300 	/* min length of the CHDLC data field (for configuration purposes) */
-#define PRI_MAX_NO_DATA_BYTES_IN_FRAME  15354 /* PRIMARY - max length of the CHDLC data field */
-
-typedef struct {
-	unsigned char opp_flag PACKED;			/* the opp flag */
-	unsigned char command PACKED;			/* the user command */
-	unsigned short buffer_length PACKED;		/* the data length */
-  	unsigned char return_code PACKED;		/* the return code */
-	unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;	/* reserved for later */
-	unsigned char data[SIZEOF_MB_DATA_BFR] PACKED;	/* the data area */
-} CHDLC_MAILBOX_STRUCT;
-
-typedef struct {
-        pid_t                   pid_num PACKED;
-        CHDLC_MAILBOX_STRUCT     cmdarea PACKED;
-
-} CMDBLOCK_STRUCT;
-
-
-
-
-/* ----------------------------------------------------------------------------
- *                        Interface commands
- * --------------------------------------------------------------------------*/
-
-/* global interface commands */
-#define READ_GLOBAL_EXCEPTION_CONDITION	0x01
-#define SET_GLOBAL_CONFIGURATION	0x02
-#define READ_GLOBAL_CONFIGURATION	0x03
-#define READ_GLOBAL_STATISTICS		0x04
-#define FLUSH_GLOBAL_STATISTICS		0x05
-#define SET_MODEM_STATUS		0x06	/* set status of DTR or RTS */
-#define READ_MODEM_STATUS		0x07	/* read status of CTS and DCD */
-#define READ_COMMS_ERROR_STATS		0x08	
-#define FLUSH_COMMS_ERROR_STATS		0x09
-#define SET_TRACE_CONFIGURATION		0x0A	/* set the line trace config */
-#define READ_TRACE_CONFIGURATION	0x0B	/* read the line trace config */
-#define READ_TRACE_STATISTICS		0x0C	/* read the trace statistics */
-#define FLUSH_TRACE_STATISTICS		0x0D	/* flush the trace statistics */
-#define FT1_MONITOR_STATUS_CTRL		0x1C	/* set the status of the S508/FT1 monitoring */
-#define SET_FT1_CONFIGURATION		0x18	/* set the FT1 configuration */
-#define READ_FT1_CONFIGURATION		0x19	/* read the FT1 configuration */
-#define TRANSMIT_ASYNC_DATA_TO_FT1	0x1A	/* output asynchronous data to the FT1 */
-#define RECEIVE_ASYNC_DATA_FROM_FT1	0x1B	/* receive asynchronous data from the FT1 */
-#define FT1_MONITOR_STATUS_CTRL		0x1C	/* set the status of the FT1 monitoring */
-
-#define READ_FT1_OPERATIONAL_STATS	0x1D	/* read the S508/FT1 operational statistics */
-#define SET_FT1_MODE			0x1E	/* set the operational mode of the S508/FT1 module */
-
-/* CHDLC-level interface commands */
-#define READ_CHDLC_CODE_VERSION		0x20	
-#define READ_CHDLC_EXCEPTION_CONDITION	0x21	/* read exception condition from the adapter */
-#define SET_CHDLC_CONFIGURATION		0x22
-#define READ_CHDLC_CONFIGURATION	0x23
-#define ENABLE_CHDLC_COMMUNICATIONS	0x24
-#define DISABLE_CHDLC_COMMUNICATIONS	0x25
-#define READ_CHDLC_LINK_STATUS		0x26
-#define READ_CHDLC_OPERATIONAL_STATS	0x27
-#define FLUSH_CHDLC_OPERATIONAL_STATS	0x28
-#define SET_CHDLC_INTERRUPT_TRIGGERS	0x30	/* set application interrupt triggers */
-#define READ_CHDLC_INTERRUPT_TRIGGERS	0x31	/* read application interrupt trigger configuration */
-
-/* Special UDP drivers management commands */
-#define CPIPE_ENABLE_TRACING				0x50
-#define CPIPE_DISABLE_TRACING				0x51
-#define CPIPE_GET_TRACE_INFO				0x52
-#define CPIPE_GET_IBA_DATA				0x53
-#define CPIPE_FT1_READ_STATUS				0x54
-#define CPIPE_DRIVER_STAT_IFSEND			0x55
-#define CPIPE_DRIVER_STAT_INTR				0x56
-#define CPIPE_DRIVER_STAT_GEN				0x57
-#define CPIPE_FLUSH_DRIVER_STATS			0x58
-#define CPIPE_ROUTER_UP_TIME				0x59
-
-/* Driver specific commands for API */
-#define	CHDLC_READ_TRACE_DATA		0xE4	/* read trace data */
-#define TRACE_ALL                       0x00
-#define TRACE_PROT			0x01
-#define TRACE_DATA			0x02
-
-#define DISCARD_RX_ERROR_FRAMES	0x0001
-
-/* ----------------------------------------------------------------------------
- *                     Return codes from interface commands
- * --------------------------------------------------------------------------*/
-
-#define COMMAND_OK				0x00
-
-/* return codes from global interface commands */
-#define NO_GLOBAL_EXCEP_COND_TO_REPORT		0x01	/* there is no CHDLC exception condition to report */
-#define LGTH_GLOBAL_CFG_DATA_INVALID		0x01	/* the length of the passed global configuration data is invalid */
-#define LGTH_TRACE_CFG_DATA_INVALID		0x01	/* the length of the passed trace configuration data is invalid */
-#define IRQ_TIMEOUT_VALUE_INVALID		0x02	/* an invalid application IRQ timeout value was selected */
-#define TRACE_CONFIG_INVALID			0x02	/* the passed line trace configuration is invalid */
-#define ADAPTER_OPERATING_FREQ_INVALID		0x03	/* an invalid adapter operating frequency was selected */
-#define TRC_DEAC_TMR_INVALID			0x03	/* the trace deactivation timer is invalid */
-#define S508_FT1_ADPTR_NOT_PRESENT		0x0C	/* the S508/FT1 adapter is not present */
-#define INVALID_FT1_STATUS_SELECTION            0x0D    /* the S508/FT1 status selection is invalid */
-#define FT1_OP_STATS_NOT_ENABLED		0x0D    /* the FT1 operational statistics have not been enabled */
-#define FT1_OP_STATS_NOT_AVAILABLE		0x0E    /* the FT1 operational statistics are not currently available */
-#define S508_FT1_MODE_SELECTION_BUSY		0x0E	/* the S508/FT1 adapter is busy selecting the operational mode */
-
-/* return codes from command READ_GLOBAL_EXCEPTION_CONDITION */
-#define EXCEP_MODEM_STATUS_CHANGE		0x10		/* a modem status change occurred */
-#define EXCEP_TRC_DISABLED			0x11		/* the trace has been disabled */
-#define EXCEP_IRQ_TIMEOUT			0x12		/* IRQ timeout */
-
-/* return codes from CHDLC-level interface commands */
-#define NO_CHDLC_EXCEP_COND_TO_REPORT		0x21	/* there is no CHDLC exception condition to report */
-#define CHDLC_COMMS_DISABLED			0x21	/* communications are not currently enabled */
-#define CHDLC_COMMS_ENABLED			0x21	/* communications are currently enabled */
-#define DISABLE_CHDLC_COMMS_BEFORE_CFG		0x21	/* CHDLC communications must be disabled before setting the configuration */
-#define ENABLE_CHDLC_COMMS_BEFORE_CONN		0x21	/* communications must be enabled before using the CHDLC_CONNECT conmmand */
-#define CHDLC_CFG_BEFORE_COMMS_ENABLED		0x22	/* perform a SET_CHDLC_CONFIGURATION before enabling comms */
-#define LGTH_CHDLC_CFG_DATA_INVALID 		0x22	/* the length of the passed CHDLC configuration data is invalid */
-#define LGTH_INT_TRIGGERS_DATA_INVALID		0x22	/* the length of the passed interrupt trigger data is invalid */
-#define INVALID_IRQ_SELECTED			0x23	/* in invalid IRQ was selected in the SET_CHDLC_INTERRUPT_TRIGGERS */
-#define INVALID_CHDLC_CFG_DATA			0x23	/* the passed CHDLC configuration data is invalid */
-#define IRQ_TMR_VALUE_INVALID			0x24	/* an invalid application IRQ timer value was selected */
-#define LARGER_PERCENT_TX_BFR_REQUIRED		0x24	/* a larger Tx buffer percentage is required */
-#define LARGER_PERCENT_RX_BFR_REQUIRED		0x25	/* a larger Rx buffer percentage is required */
-#define S514_BOTH_PORTS_SAME_CLK_MODE		0x26	/* S514 - both ports must have same clock mode */
-#define INVALID_CMND_HDLC_STREAM_MODE           0x4E    /* the CHDLC interface command is invalid for HDLC streaming mode */
-#define INVALID_CHDLC_COMMAND			0x4F	/* the defined CHDLC interface command is invalid */
-
-/* return codes from command READ_CHDLC_EXCEPTION_CONDITION */
-#define EXCEP_LINK_ACTIVE			0x30	/* the CHDLC link has become active */
-#define EXCEP_LINK_INACTIVE_MODEM		0x31	/* the CHDLC link has become inactive (modem status) */
-#define EXCEP_LINK_INACTIVE_KPALV		0x32	/* the CHDLC link has become inactive (keepalive status) */
-#define EXCEP_IP_ADDRESS_DISCOVERED		0x33	/* the IP address has been discovered */
-#define EXCEP_LOOPBACK_CONDITION		0x34	/* a loopback condition has occurred */
-
-
-/* return code from command CHDLC_SEND_WAIT and CHDLC_SEND_NO_WAIT */
-#define LINK_DISCONNECTED			0x21
-#define NO_TX_BFRS_AVAIL			0x24
-
-
-/* ----------------------------------------------------------------------------
- * Constants for the SET_GLOBAL_CONFIGURATION/READ_GLOBAL_CONFIGURATION commands
- * --------------------------------------------------------------------------*/
-
-/* the global configuration structure */
-typedef struct {
-	unsigned short adapter_config_options PACKED;	/* adapter config options */
-	unsigned short app_IRQ_timeout PACKED;		/* application IRQ timeout */
-	unsigned long adapter_operating_frequency PACKED;	/* adapter operating frequency */
-} GLOBAL_CONFIGURATION_STRUCT;
-
-/* settings for the 'app_IRQ_timeout' */
-#define MAX_APP_IRQ_TIMEOUT_VALUE	5000	/* the maximum permitted IRQ timeout */
-
-
-
-/* ----------------------------------------------------------------------------
- *             Constants for the READ_GLOBAL_STATISTICS command
- * --------------------------------------------------------------------------*/
-
-/* the global statistics structure */
-typedef struct {
-	unsigned short app_IRQ_timeout_count PACKED;
-} GLOBAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *             Constants for the READ_COMMS_ERROR_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the communications error statistics structure */
-typedef struct {
-	unsigned short Rx_overrun_err_count PACKED;
-	unsigned short CRC_err_count PACKED;	/* receiver CRC error count */
-	unsigned short Rx_abort_count PACKED; 	/* abort frames recvd count */
-	unsigned short Rx_dis_pri_bfrs_full_count PACKED;/* receiver disabled */
-	unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later */
-	unsigned short sec_Tx_abort_msd_Tx_int_count PACKED; /* secondary - abort frames transmitted count (missed Tx interrupt) */
-	unsigned short missed_Tx_und_int_count PACKED;	/* missed tx underrun interrupt count */
-        unsigned short sec_Tx_abort_count PACKED;   /*secondary-abort frames tx count */
-	unsigned short DCD_state_change_count PACKED; /* DCD state change */
-	unsigned short CTS_state_change_count PACKED; /* CTS state change */
-} COMMS_ERROR_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *                  Constants used for line tracing
- * --------------------------------------------------------------------------*/
-
-/* the trace configuration structure (SET_TRACE_CONFIGURATION/READ_TRACE_CONFIGURATION commands) */
-typedef struct {
-	unsigned char trace_config PACKED;		/* trace configuration */
-	unsigned short trace_deactivation_timer PACKED;	/* trace deactivation timer */
-	unsigned long ptr_trace_stat_el_cfg_struct PACKED;	/* a pointer to the line trace element configuration structure */
-} LINE_TRACE_CONFIG_STRUCT;
-
-/* 'trace_config' bit settings */
-#define TRACE_INACTIVE		0x00	/* trace is inactive */
-#define TRACE_ACTIVE		0x01	/* trace is active */
-#define TRACE_DELAY_MODE	0x04	/* operate the trace in delay mode */
-#define TRACE_DATA_FRAMES	0x08	/* trace Data frames */
-#define TRACE_SLARP_FRAMES	0x10	/* trace SLARP frames */
-#define TRACE_CDP_FRAMES	0x20	/* trace CDP frames */
-
-/* the line trace status element configuration structure */
-typedef struct {
-	unsigned short number_trace_status_elements PACKED;	/* number of line trace elements */
-	unsigned long base_addr_trace_status_elements PACKED;	/* base address of the trace element list */
-	unsigned long next_trace_element_to_use PACKED;	/* pointer to the next trace element to be used */
-	unsigned long base_addr_trace_buffer PACKED;		/* base address of the trace data buffer */
-	unsigned long end_addr_trace_buffer PACKED;		/* end address of the trace data buffer */
-} TRACE_STATUS_EL_CFG_STRUCT;
-
-/* the line trace status element structure */
-typedef struct {
-	unsigned char opp_flag PACKED;			/* opp flag */
-	unsigned short trace_length PACKED;		/* trace length */
-	unsigned char trace_type PACKED;		/* trace type */
-	unsigned short trace_time_stamp PACKED;	/* time stamp */
-	unsigned short trace_reserved_1 PACKED;	/* reserved for later use */
-	unsigned long trace_reserved_2 PACKED;		/* reserved for later use */
-	unsigned long ptr_data_bfr PACKED;		/* ptr to the trace data buffer */
-} TRACE_STATUS_ELEMENT_STRUCT;
-
-/* "trace_type" bit settings */
-#define TRACE_INCOMING 			0x00
-#define TRACE_OUTGOINGING 		0x01
-#define TRACE_INCOMING_ABORTED 		0x10
-#define TRACE_INCOMING_CRC_ERROR 	0x20
-#define TRACE_INCOMING_OVERRUN_ERROR 	0x40
-
-
-
-/* the line trace statistics structure */
-typedef struct {
-	unsigned long frames_traced_count PACKED;	/* number of frames traced */
-	unsigned long trc_frms_not_recorded_count PACKED;	/* number of trace frames discarded */
-} LINE_TRACE_STATS_STRUCT;
-
-
-/* ----------------------------------------------------------------------------
- *               Constants for the FT1_MONITOR_STATUS_CTRL command
- * --------------------------------------------------------------------------*/
-
-#define DISABLE_FT1_STATUS_STATISTICS	0x00    /* disable the FT1 status and statistics monitoring */
-#define ENABLE_READ_FT1_STATUS		0x01    /* read the FT1 operational status */
-#define ENABLE_READ_FT1_OP_STATS	0x02    /* read the FT1 operational statistics */
-#define FLUSH_FT1_OP_STATS		0x04 	/* flush the FT1 operational statistics */
-
-
-
-
-/* ----------------------------------------------------------------------------
- *               Constants for the SET_CHDLC_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC configuration structure */
-typedef struct {
-	unsigned long baud_rate PACKED;		/* the baud rate */	
-	unsigned short line_config_options PACKED;	/* line configuration options */
-	unsigned short modem_config_options PACKED;	/* modem configration options */
-	unsigned short modem_status_timer PACKED;	/* timer for monitoring modem status changes */
-	unsigned short CHDLC_API_options PACKED;	/* CHDLC API options */
-	unsigned short CHDLC_protocol_options PACKED;	/* CHDLC protocol options */
-	unsigned short percent_data_buffer_for_Tx PACKED;	/* percentage data buffering used for Tx */
-	unsigned short CHDLC_statistics_options PACKED;	/* CHDLC operational statistics options */
-	unsigned short max_CHDLC_data_field_length PACKED;	/* the maximum length of the CHDLC Data field */
-	unsigned short transmit_keepalive_timer PACKED;		/* the transmit keepalive timer */
-	unsigned short receive_keepalive_timer PACKED;		/* the receive keepalive timer */
-	unsigned short keepalive_error_tolerance PACKED;	/* the receive keepalive error tolerance */
-	unsigned short SLARP_request_timer PACKED;		/* the SLARP request timer */
-	unsigned long IP_address PACKED;			/* the IP address */
-	unsigned long IP_netmask PACKED;			/* the IP netmask */
-	unsigned long ptr_shared_mem_info_struct PACKED;	/* a pointer to the shared memory area information structure */
-	unsigned long ptr_CHDLC_Tx_stat_el_cfg_struct PACKED;	/* a pointer to the transmit status element configuration structure */
-	unsigned long ptr_CHDLC_Rx_stat_el_cfg_struct PACKED;	/* a pointer to the receive status element configuration structure */
-} CHDLC_CONFIGURATION_STRUCT;
-
-/* settings for the 'line_config_options' */
-#define INTERFACE_LEVEL_V35					0x0000 /* V.35 interface level */
-#define INTERFACE_LEVEL_RS232					0x0001 /* RS-232 interface level */
-
-/* settings for the 'modem_config_options' */
-
-#define DONT_RAISE_DTR_RTS_ON_EN_COMMS		0x0001
-/* don't automatically raise DTR and RTS when performing an
-   ENABLE_CHDLC_COMMUNICATIONS command */
-
-#define DONT_REPORT_CHG_IN_MODEM_STAT 		0x0002
-/* don't report changes in modem status to the application */
-
-
-/* bit settings for the 'CHDLC_protocol_options' byte */
-
-#define IGNORE_DCD_FOR_LINK_STAT		0x0001
-/* ignore DCD in determining the CHDLC link status */
-
-#define IGNORE_CTS_FOR_LINK_STAT		0x0002
-/* ignore CTS in determining the CHDLC link status */
-
-#define IGNORE_KPALV_FOR_LINK_STAT		0x0004
-/* ignore keepalive frames in determining the CHDLC link status */ 
-
-#define SINGLE_TX_BUFFER			0x4000 
-/* configure a single transmit buffer */
-
-#define HDLC_STREAMING_MODE			0x8000
-
-/*   settings for the 'CHDLC_statistics_options' */
-
-#define CHDLC_TX_DATA_BYTE_COUNT_STAT		0x0001
-/* record the number of Data bytes transmitted */
-
-#define CHDLC_RX_DATA_BYTE_COUNT_STAT		0x0002
-/* record the number of Data bytes received */
-
-#define CHDLC_TX_THROUGHPUT_STAT		0x0004
-/* compute the Data frame transmit throughput */
-
-#define CHDLC_RX_THROUGHPUT_STAT		0x0008
-/* compute the Data frame receive throughput */
-
-
-/* permitted minimum and maximum values for setting the CHDLC configuration */
-#define PRI_MAX_BAUD_RATE_S508	2666666 /* PRIMARY   - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S508	258064 	/* SECONDARY - maximum baud rate (S508) */
-#define PRI_MAX_BAUD_RATE_S514  2750000 /* PRIMARY   - maximum baud rate (S508) */
-#define SEC_MAX_BAUD_RATE_S514  515625  /* SECONDARY - maximum baud rate (S508) */
- 
-#define MIN_MODEM_TIMER	0			/* minimum modem status timer */
-#define MAX_MODEM_TIMER	5000			/* maximum modem status timer */
-
-#define SEC_MAX_NO_DATA_BYTES_IN_FRAME  2048 /* SECONDARY - max length of the CHDLC data field */
-
-#define MIN_Tx_KPALV_TIMER	0	  /* minimum transmit keepalive timer */
-#define MAX_Tx_KPALV_TIMER	60000	  /* maximum transmit keepalive timer */
-#define DEFAULT_Tx_KPALV_TIMER	10000	  /* default transmit keepalive timer */
-
-#define MIN_Rx_KPALV_TIMER	10	  /* minimum receive keepalive timer */
-#define MAX_Rx_KPALV_TIMER	60000	  /* maximum receive keepalive timer */
-#define DEFAULT_Rx_KPALV_TIMER	10000	  /* default receive keepalive timer */
-
-#define MIN_KPALV_ERR_TOL	1	  /* min kpalv error tolerance count */
-#define MAX_KPALV_ERR_TOL	20	  /* max kpalv error tolerance count */
-#define DEFAULT_KPALV_ERR_TOL	3	  /* default value */
-
-#define MIN_SLARP_REQ_TIMER	0	  /* min transmit SLARP Request timer */
-#define MAX_SLARP_REQ_TIMER	60000	  /* max transmit SLARP Request timer */
-#define DEFAULT_SLARP_REQ_TIMER	0	  /* default value -- no SLARP */
-
-
-
-/* ----------------------------------------------------------------------------
- *             Constants for the READ_CHDLC_LINK_STATUS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC status structure */
-typedef struct {
-	unsigned char CHDLC_link_status PACKED;	/* CHDLC link status */
-	unsigned char no_Data_frms_for_app PACKED;	/* number of Data frames available for the application */
-	unsigned char receiver_status PACKED;	/* enabled/disabled */
-	unsigned char SLARP_state PACKED;	/* internal SLARP state */
-} CHDLC_LINK_STATUS_STRUCT;
-
-/* settings for the 'CHDLC_link_status' variable */
-#define CHDLC_LINK_INACTIVE		0x00	/* the CHDLC link is inactive */
-#define CHDLC_LINK_ACTIVE		0x01	/* the CHDLC link is active */
-
-
-
-/* ----------------------------------------------------------------------------
- *           Constants for the READ_CHDLC_OPERATIONAL_STATS command
- * --------------------------------------------------------------------------*/
-
-/* the CHDLC operational statistics structure */
-typedef struct {
-
-	/* Data frame transmission statistics */
-	unsigned long Data_frames_Tx_count PACKED;	/* # of frames transmitted */
-	unsigned long Data_bytes_Tx_count PACKED; 	/* # of bytes transmitted */
-	unsigned long Data_Tx_throughput PACKED;	/* transmit throughput */
-	unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;	/* millisecond time used for the Tx throughput computation */
-	unsigned long Tx_Data_discard_lgth_err_count PACKED;	/* number of Data frames discarded (length error) */
-	unsigned long reserved_Data_frm_Tx_stat1 PACKED;	/* reserved for later */
-	unsigned long reserved_Data_frm_Tx_stat2 PACKED;	/* reserved for later */
-	unsigned long reserved_Data_frm_Tx_stat3 PACKED;	/* reserved for later */
-
-	/* Data frame reception statistics */
-	unsigned long Data_frames_Rx_count PACKED;	/* number of frames received */
-	unsigned long Data_bytes_Rx_count PACKED;	/* number of bytes received */
-	unsigned long Data_Rx_throughput PACKED;	/* receive throughput */
-	unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;	/* millisecond time used for the Rx throughput computation */
-	unsigned long Rx_Data_discard_short_count PACKED;	/* received Data frames discarded (too short) */
-	unsigned long Rx_Data_discard_long_count PACKED;	/* received Data frames discarded (too long) */
-	unsigned long Rx_Data_discard_inactive_count PACKED;	/* received Data frames discarded (link inactive) */
-	unsigned long reserved_Data_frm_Rx_stat1 PACKED;	/* reserved for later */
-
-	/* SLARP frame transmission/reception statistics */
-	unsigned long CHDLC_SLARP_REQ_Tx_count PACKED;		/* number of SLARP Request frames transmitted */
-	unsigned long CHDLC_SLARP_REQ_Rx_count PACKED;		/* number of SLARP Request frames received */
-	unsigned long CHDLC_SLARP_REPLY_Tx_count PACKED;	/* number of SLARP Reply frames transmitted */
-	unsigned long CHDLC_SLARP_REPLY_Rx_count PACKED;	/* number of SLARP Reply frames received */
-	unsigned long CHDLC_SLARP_KPALV_Tx_count PACKED;	/* number of SLARP keepalive frames transmitted */
-	unsigned long CHDLC_SLARP_KPALV_Rx_count PACKED;	/* number of SLARP keepalive frames received */
-	unsigned long reserved_SLARP_stat1 PACKED;		/* reserved for later */
-	unsigned long reserved_SLARP_stat2 PACKED;		/* reserved for later */
-
-	/* CDP frame transmission/reception statistics */
-	unsigned long CHDLC_CDP_Tx_count PACKED;		/* number of CDP frames transmitted */
-	unsigned long CHDLC_CDP_Rx_count PACKED;		/* number of CDP frames received */
-	unsigned long reserved_CDP_stat1 PACKED;		/* reserved for later */
-	unsigned long reserved_CDP_stat2 PACKED;		/* reserved for later */
-	unsigned long reserved_CDP_stat3 PACKED;		/* reserved for later */
-	unsigned long reserved_CDP_stat4 PACKED;		/* reserved for later */
-	unsigned long reserved_CDP_stat5 PACKED;		/* reserved for later */
-	unsigned long reserved_CDP_stat6 PACKED;		/* reserved for later */
-
-	/* Incoming frames with a format error statistics */
-	unsigned short Rx_frm_incomp_CHDLC_hdr_count PACKED;	/* frames received of with incomplete Cisco HDLC header */
-	unsigned short Rx_frms_too_long_count PACKED;		/* frames received of excessive length count */
-	unsigned short Rx_invalid_CHDLC_addr_count PACKED;	/* frames received with an invalid CHDLC address count */
-	unsigned short Rx_invalid_CHDLC_ctrl_count PACKED;	/* frames received with an invalid CHDLC control field count */
-	unsigned short Rx_invalid_CHDLC_type_count PACKED;	/* frames received of an invalid CHDLC frame type count */
-	unsigned short Rx_SLARP_invalid_code_count PACKED;	/* SLARP frame received with an invalid packet code */
-	unsigned short Rx_SLARP_Reply_bad_IP_addr PACKED;	/* SLARP Reply received - bad IP address */
-	unsigned short Rx_SLARP_Reply_bad_netmask PACKED;	/* SLARP Reply received - bad netmask */
-	unsigned long reserved_frm_format_err1 PACKED;		/* reserved for later */
-	unsigned long reserved_frm_format_err2 PACKED;		/* reserved for later */
-	unsigned long reserved_frm_format_err3 PACKED;		/* reserved for later */
-	unsigned long reserved_frm_format_err4 PACKED;		/* reserved for later */
-
-	/* CHDLC timeout/retry statistics */
-	unsigned short SLARP_Rx_keepalive_TO_count PACKED;	/* timeout count for incoming SLARP frames */
-	unsigned short SLARP_Request_TO_count PACKED;		/* timeout count for SLARP Request frames */
-	unsigned long To_retry_reserved_stat1 PACKED;		/* reserved for later */
-	unsigned long To_retry_reserved_stat2 PACKED;		/* reserved for later */
-	unsigned long To_retry_reserved_stat3 PACKED;		/* reserved for later */
-
-	/* CHDLC link active/inactive and loopback statistics */
-	unsigned short link_active_count PACKED;		/* number of times that the link went active */
-	unsigned short link_inactive_modem_count PACKED;	/* number of times that the link went inactive (modem failure) */
-	unsigned short link_inactive_keepalive_count PACKED;	/* number of times that the link went inactive (keepalive failure) */
-	unsigned short link_looped_count PACKED;		/* link looped count */
-	unsigned long link_status_reserved_stat1 PACKED;	/* reserved for later use */
-	unsigned long link_status_reserved_stat2 PACKED;	/* reserved for later use */
-
-	/* miscellaneous statistics */
-	unsigned long reserved_misc_stat1 PACKED;		/* reserved for later */
-	unsigned long reserved_misc_stat2 PACKED;		/* reserved for later */
-	unsigned long reserved_misc_stat3 PACKED;		/* reserved for later */
-	unsigned long reserved_misc_stat4 PACKED;		/* reserved for later */
-
-} CHDLC_OPERATIONAL_STATS_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *                 Constants for using application interrupts
- * --------------------------------------------------------------------------*/
-
-/* the structure used for the SET_CHDLC_INTERRUPT_TRIGGERS/READ_CHDLC_INTERRUPT_TRIGGERS command */
-typedef struct {
-	unsigned char CHDLC_interrupt_triggers PACKED;	/* CHDLC interrupt trigger configuration */
-	unsigned char IRQ PACKED;			/* IRQ to be used */
-	unsigned short interrupt_timer PACKED;		/* interrupt timer */
-	unsigned short misc_interrupt_bits PACKED;	/* miscellaneous bits */
-} CHDLC_INT_TRIGGERS_STRUCT;
-
-/* 'CHDLC_interrupt_triggers' bit settings */
-#define APP_INT_ON_RX_FRAME		0x01	/* interrupt on Data frame reception */
-#define APP_INT_ON_TX_FRAME		0x02	/* interrupt when an Data frame may be transmitted */
-#define APP_INT_ON_COMMAND_COMPLETE	0x04	/* interrupt when an interface command is complete */
-#define APP_INT_ON_TIMER		0x08	/* interrupt on a defined millisecond timeout */
-#define APP_INT_ON_GLOBAL_EXCEP_COND 	0x10	/* interrupt on a global exception condition */
-#define APP_INT_ON_CHDLC_EXCEP_COND	0x20	/* interrupt on an CHDLC exception condition */
-#define APP_INT_ON_TRACE_DATA_AVAIL	0x80	/* interrupt when trace data is available */
-
-/* interrupt types indicated at 'interrupt_type' byte of the INTERRUPT_INFORMATION_STRUCT */
-#define NO_APP_INTS_PEND		0x00	/* no interrups are pending */
-#define RX_APP_INT_PEND			0x01	/* a receive interrupt is pending */
-#define TX_APP_INT_PEND			0x02	/* a transmit interrupt is pending */
-#define COMMAND_COMPLETE_APP_INT_PEND	0x04	/* a 'command complete' interrupt is pending */
-#define TIMER_APP_INT_PEND		0x08	/* a timer interrupt is pending */
-#define GLOBAL_EXCEP_COND_APP_INT_PEND 	0x10	/* a global exception condition interrupt is pending */
-#define CHDLC_EXCEP_COND_APP_INT_PEND 	0x20	/* an CHDLC exception condition interrupt is pending */
-#define TRACE_DATA_AVAIL_APP_INT_PEND	0x80	/* a trace data available interrupt is pending */
-
-
-/* modem status changes */
-#define DCD_HIGH			0x08
-#define CTS_HIGH			0x20
-
-
-/* ----------------------------------------------------------------------------
- *                   Constants for Data frame transmission
- * --------------------------------------------------------------------------*/
-
-/* the Data frame transmit status element configuration structure */
-typedef struct {
-	unsigned short number_Tx_status_elements PACKED;	/* number of transmit status elements */
-	unsigned long base_addr_Tx_status_elements PACKED;	/* base address of the transmit element list */
-	unsigned long next_Tx_status_element_to_use PACKED;	/* pointer to the next transmit element to be used */
-} CHDLC_TX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame transmit status element structure */
-typedef struct {
-	unsigned char opp_flag PACKED;		/* opp flag */
-	unsigned short frame_length PACKED;	/* length of the frame to be transmitted */
-	unsigned char reserved_1 PACKED;	/* reserved for internal use */
-	unsigned long reserved_2 PACKED;	/* reserved for internal use */
-	unsigned long reserved_3 PACKED;	/* reserved for internal use */
-	unsigned long ptr_data_bfr PACKED;	/* pointer to the data area */
-} CHDLC_DATA_TX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *                   Constants for Data frame reception
- * --------------------------------------------------------------------------*/
-
-/* the Data frame receive status element configuration structure */
-typedef struct {
-	unsigned short number_Rx_status_elements PACKED;	/* number of receive status elements */
-	unsigned long base_addr_Rx_status_elements PACKED;	/* base address of the receive element list */
-	unsigned long next_Rx_status_element_to_use PACKED;	/* pointer to the next receive element to be used */
-	unsigned long base_addr_Rx_buffer PACKED;		/* base address of the receive data buffer */
-	unsigned long end_addr_Rx_buffer PACKED;		/* end address of the receive data buffer */
-} CHDLC_RX_STATUS_EL_CFG_STRUCT;
-
-/* the Data frame receive status element structure */
-typedef struct {
-	unsigned char opp_flag PACKED;		/* opp flag */
-	unsigned short frame_length PACKED;   /* length of the received frame */
-        unsigned char error_flag PACKED; /* frame errors (HDLC_STREAMING_MODE)*/
-        unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */
-        unsigned long reserved_1 PACKED; 	/* reserved for internal use */
-        unsigned short reserved_2 PACKED; 	/* reserved for internal use */
-        unsigned long ptr_data_bfr PACKED;	/* pointer to the data area */
-} CHDLC_DATA_RX_STATUS_EL_STRUCT;
-
-
-
-/* ----------------------------------------------------------------------------
- *         Constants defining the shared memory information area
- * --------------------------------------------------------------------------*/
-
-/* the global information structure */
-typedef struct {
- 	unsigned char global_status PACKED;		/* global status */
- 	unsigned char modem_status PACKED;		/* current modem status */
- 	unsigned char global_excep_conditions PACKED;	/* global exception conditions */
-	unsigned char glob_info_reserved[5] PACKED;	/* reserved */
-	unsigned char codename[4] PACKED;		/* Firmware name */
-	unsigned char codeversion[4] PACKED;		/* Firmware version */
-} GLOBAL_INFORMATION_STRUCT;
-
-/* the CHDLC information structure */
-typedef struct {
-	unsigned char CHDLC_status PACKED;		/* CHDLC status */
- 	unsigned char CHDLC_excep_conditions PACKED;	/* CHDLC exception conditions */
-	unsigned char CHDLC_info_reserved[14] PACKED;	/* reserved */
-} CHDLC_INFORMATION_STRUCT;
-
-/* the interrupt information structure */
-typedef struct {
- 	unsigned char interrupt_type PACKED;		/* type of interrupt triggered */
- 	unsigned char interrupt_permission PACKED;	/* interrupt permission mask */
-	unsigned char int_info_reserved[14] PACKED;	/* reserved */
-} INTERRUPT_INFORMATION_STRUCT;
-
-/* the S508/FT1 information structure */
-typedef struct {
- 	unsigned char parallel_port_A_input PACKED;	/* input - parallel port A */
- 	unsigned char parallel_port_B_input PACKED;	/* input - parallel port B */
-	unsigned char FT1_info_reserved[14] PACKED;	/* reserved */
-} FT1_INFORMATION_STRUCT;
-
-/* the shared memory area information structure */
-typedef struct {
-	GLOBAL_INFORMATION_STRUCT global_info_struct PACKED;		/* the global information structure */
-	CHDLC_INFORMATION_STRUCT CHDLC_info_struct PACKED;		/* the CHDLC information structure */
-	INTERRUPT_INFORMATION_STRUCT interrupt_info_struct PACKED;	/* the interrupt information structure */
-	FT1_INFORMATION_STRUCT FT1_info_struct PACKED;			/* the S508/FT1 information structure */
-} SHARED_MEMORY_INFO_STRUCT;
-
-/* ----------------------------------------------------------------------------
- *        UDP Management constants and structures 
- * --------------------------------------------------------------------------*/
-
-/* The embedded control block for UDP mgmt 
-   This is essentially a mailbox structure, without the large data field */
-
-typedef struct {
-        unsigned char  opp_flag PACKED;                  /* the opp flag */
-        unsigned char  command PACKED;                   /* the user command */
-        unsigned short buffer_length PACKED;             /* the data length */
-        unsigned char  return_code PACKED;               /* the return code */
-	unsigned char  MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;	/* reserved for later */
-} cblock_t;
-
-
-/* UDP management packet layout (data area of ip packet) */
-/*
-typedef struct {
-	unsigned char		signature[8]	PACKED;
-	unsigned char		request_reply	PACKED;
-	unsigned char		id		PACKED;
-	unsigned char		reserved[6]	PACKED;
-	cblock_t		cblock		PACKED;
-	unsigned char		num_frames	PACKED;
-	unsigned char		ismoredata	PACKED;
-	unsigned char 		data[SIZEOF_MB_DATA_BFR] 	PACKED;
-} udp_management_packet_t;
-
-*/
-
-typedef struct {
-	unsigned char		num_frames	PACKED;
-	unsigned char		ismoredata	PACKED;
-} trace_info_t;
-
-typedef struct {
-	ip_pkt_t 		ip_pkt		PACKED;
-	udp_pkt_t		udp_pkt		PACKED;
-	wp_mgmt_t		wp_mgmt		PACKED;
-	cblock_t                cblock          PACKED;
-	trace_info_t       	trace_info      PACKED;
-	unsigned char           data[SIZEOF_MB_DATA_BFR]      PACKED;
-} chdlc_udp_pkt_t;
-
-typedef struct ft1_exec_cmd{
-	unsigned char  command PACKED;                   /* the user command */
-        unsigned short buffer_length PACKED;             /* the data length */
-        unsigned char  return_code PACKED;               /* the return code */
-	unsigned char  MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED;
-} ft1_exec_cmd_t;
-
-typedef struct {
-	unsigned char  opp_flag 			PACKED;
-	ft1_exec_cmd_t cmd				PACKED;
-	unsigned char  data[SIZEOF_MB_DATA_BFR]      	PACKED;
-} ft1_exec_t;
-
-#define UDPMGMT_SIGNATURE	"CTPIPEAB"
-
-
-/* UDP/IP packet (for UDP management) layout */
-/*
-typedef struct {
-	unsigned char	reserved[2]	PACKED;
-	unsigned short	ip_length	PACKED;
-	unsigned char	reserved2[4]	PACKED;
-	unsigned char	ip_ttl		PACKED;
-	unsigned char	ip_protocol	PACKED;
-	unsigned short	ip_checksum	PACKED;
-	unsigned long	ip_src_address	PACKED;
-	unsigned long	ip_dst_address	PACKED;
-	unsigned short	udp_src_port	PACKED;
-	unsigned short	udp_dst_port	PACKED;
-	unsigned short	udp_length	PACKED;
-	unsigned short	udp_checksum	PACKED;
-	udp_management_packet_t um_packet PACKED;
-} ip_packet_t;
-*/
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-
-
-typedef struct {
-	unsigned char	status		PACKED;
-	unsigned char	data_avail	PACKED;
-	unsigned short	real_length	PACKED;
-	unsigned short	time_stamp	PACKED;
-	unsigned char	data[1]		PACKED;
-} trace_pkt_t;
-
-typedef struct {
-	unsigned char	error_flag	PACKED;
-	unsigned short	time_stamp	PACKED;
-	unsigned char	reserved[13]	PACKED;
-} api_rx_hdr_t;
-
-typedef struct {
-        api_rx_hdr_t	api_rx_hdr      PACKED;
-        void *   	data    	PACKED;
-} api_rx_element_t;
-
-typedef struct {
-	unsigned char 	attr		PACKED;
-	unsigned char  	reserved[15]	PACKED;
-} api_tx_hdr_t;
-
-typedef struct {
-	api_tx_hdr_t 	api_tx_hdr	PACKED;
-	void *		data		PACKED;
-} api_tx_element_t;
-
-/* ----------------------------------------------------------------------------
- *   Constants for the SET_FT1_CONFIGURATION/READ_FT1_CONFIGURATION command
- * --------------------------------------------------------------------------*/
-
-/* the FT1 configuration structure */
-typedef struct {
-	unsigned short framing_mode;
-	unsigned short encoding_mode;
-	unsigned short line_build_out;
-	unsigned short channel_base;
-	unsigned short baud_rate_kbps;					/* the baud rate (in kbps) */	
-	unsigned short clock_mode;
-} ft1_config_t;
-
-/* settings for the 'framing_mode' */
-#define ESF_FRAMING 	0x00	/* ESF framing */
-#define D4_FRAMING  	0x01	/* D4 framing */
-
-/* settings for the 'encoding_mode' */
-#define B8ZS_ENCODING 	0x00	/* B8ZS encoding */
-#define AMI_ENCODING	0x01	/* AMI encoding */
-
-/* settings for the 'line_build_out' */
-#define LN_BLD_CSU_0dB_DSX1_0_to_133	0x00	/* set build out to CSU (0db) or DSX-1 (0-133ft) */
-#define LN_BLD_DSX1_133_to_266		0x01	/* set build out DSX-1 (133-266ft) */
-#define LN_BLD_DSX1_266_to_399		0x02	/* set build out DSX-1 (266-399ft) */
-#define LN_BLD_DSX1_399_to_533		0x03	/* set build out DSX-1 (399-533ft) */
-#define LN_BLD_DSX1_533_to_655		0x04	/* set build out DSX-1 (533-655ft) */
-#define LN_BLD_CSU_NEG_7dB		0x05	/* set build out to CSU (-7.5db) */
-#define LN_BLD_CSU_NEG_15dB		0x06	/* set build out to CSU (-15db) */
-#define LN_BLD_CSU_NEG_22dB		0x07	/* set build out to CSU (-22.5db) */
-
-/* settings for the 'channel_base' */
-#define MIN_CHANNEL_BASE_VALUE		1		/* the minimum permitted channel base value */
-#define MAX_CHANNEL_BASE_VALUE		24		/* the maximum permitted channel base value */
-
-/* settings for the 'baud_rate_kbps' */
-#define MIN_BAUD_RATE_KBPS		0		/* the minimum permitted baud rate (kbps) */
-#define MAX_BAUD_RATE_KBPS 		1536	/* the maximum permitted baud rate (kbps) */
-#define BAUD_RATE_FT1_AUTO_CONFIG	0xFFFF /* the baud rate used to trigger an automatic FT1 configuration */
-
-/* settings for the 'clock_mode' */
-#define CLOCK_MODE_NORMAL		0x00	/* clock mode set to normal (slave) */
-#define CLOCK_MODE_MASTER		0x01	/* clock mode set to master */
-
-
-#define BAUD_RATE_FT1_AUTO_CONFIG   	0xFFFF
-#define AUTO_FT1_CONFIG_NOT_COMPLETE	0x08
-#define AUTO_FT1_CFG_FAIL_OP_MODE	0x0C
-#define AUTO_FT1_CFG_FAIL_INVALID_LINE 	0x0D
-
- 
-#ifdef		_MSC_
-#  pragma	pack()
-#endif
-#endif	/* _SDLA_CHDLC_H */
diff --git a/include/linux/sdla_ppp.h b/include/linux/sdla_ppp.h
deleted file mode 100644
index 6f39231..0000000
--- a/include/linux/sdla_ppp.h
+++ /dev/null
@@ -1,575 +0,0 @@
-/*****************************************************************************
-* sdla_ppp.h	Sangoma PPP firmware API definitions.
-*
-* Author:	Nenad Corbic	<ncorbic@sangoma.com>
-*
-* Copyright:	(c) 1995-1997 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Feb 24, 2000  Nenad Corbic    v2.1.2
-* Jan 06, 1997	Gene Kozin	v2.0
-* Apr 11, 1996	Gene Kozin	Initial version.
-*****************************************************************************/
-#ifndef	_SDLA_PPP_H
-#define	_SDLA_PPP_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.  
- *
- *	Compiler	Platform
- *	--------	--------
- *	GNU C		Linux		
- */
-
-#ifndef	PACKED
-#    define	PACKED	__attribute__((packed))
-#endif	/* PACKED */
-
-/* Adapter memory layout and important constants */
-#define	PPP508_MB_VECT	0xE000	/* mailbox window vector */
-#define	PPP508_MB_OFFS	0		/* mailbox offset */
-#define	PPP508_FLG_OFFS	0x1000	/* status flags offset */
-#define	PPP508_BUF_OFFS	0x1100	/* buffer info block offset */
-#define PPP514_MB_OFFS  0xE000  /* mailbox offset */
-#define PPP514_FLG_OFFS 0xF000  /* status flags offset */
-#define PPP514_BUF_OFFS 0xF100  /* buffer info block offset */
-
-#define PPP_MAX_DATA	1008	/* command block data buffer length */
-
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * PPP Command Block.
- */
-typedef struct ppp_cmd{
-	unsigned char  command	PACKED;	/* command code */
-	unsigned short length	PACKED;	/* length of data buffer */
-	unsigned char  result	PACKED;	/* return code */
-	unsigned char  rsrv[11]	PACKED;	/* reserved for future use */
-} ppp_cmd_t;
-
-typedef struct cblock{
-	unsigned char  opp_flag	PACKED;
-	unsigned char  command	PACKED;	/* command code */
-	unsigned short length	PACKED;	/* length of data buffer */
-	unsigned char  result	PACKED;	/* return code */
-	unsigned char  rsrv[11]	PACKED;	/* reserved for future use */
-} cblock_t;
-
-typedef struct ppp_udp_pkt{
-	ip_pkt_t 	ip_pkt	PACKED;
-	udp_pkt_t	udp_pkt	PACKED;
-	wp_mgmt_t	wp_mgmt PACKED;
-	cblock_t	cblock  PACKED;
-	unsigned char   data[MAX_LGTH_UDP_MGNT_PKT] PACKED;
-} ppp_udp_pkt_t;	
-
-typedef struct {
-	unsigned char	status		PACKED;
-	unsigned char	data_avail	PACKED;
-	unsigned short	real_length	PACKED;
-	unsigned short	time_stamp	PACKED;
-	unsigned char	data[1]		PACKED;
-} trace_pkt_t;
-
-
-typedef struct {
-	unsigned char 	opp_flag	PACKED;
-	unsigned char	trace_type	PACKED;
-	unsigned short 	trace_length	PACKED;
-	unsigned short 	trace_data_ptr	PACKED;
-	unsigned short  trace_time_stamp PACKED;
-} trace_element_t;
-
-/* 'command' field defines */
-#define PPP_READ_CODE_VERSION	0x10	/* configuration commands */
-#define PPP_SET_CONFIG		0x05
-#define PPP_READ_CONFIG		0x06
-#define	PPP_SET_INTR_FLAGS	0x20
-#define	PPP_READ_INTR_FLAGS	0x21
-#define	PPP_SET_INBOUND_AUTH	0x30
-#define	PPP_SET_OUTBOUND_AUTH	0x31
-#define	PPP_GET_CONNECTION_INFO	0x32
-
-#define PPP_COMM_ENABLE		0x03	/* operational commands */
-#define PPP_COMM_DISABLE	0x04
-#define	PPP_SEND_SIGN_FRAME	0x23
-#define	PPP_READ_SIGN_RESPONSE	0x24
-#define	PPP_DATALINE_MONITOR	0x33
-
-#define PPP_READ_STATISTICS	0x07	/* statistics commands */
-#define PPP_FLUSH_STATISTICS	0x08
-#define PPP_READ_ERROR_STATS	0x09
-#define PPP_FLUSH_ERROR_STATS	0x0A
-#define PPP_READ_PACKET_STATS	0x12
-#define PPP_FLUSH_PACKET_STATS	0x13
-#define PPP_READ_LCP_STATS	0x14
-#define PPP_FLUSH_LCP_STATS	0x15
-#define PPP_READ_LPBK_STATS	0x16
-#define PPP_FLUSH_LPBK_STATS	0x17
-#define PPP_READ_IPCP_STATS	0x18
-#define PPP_FLUSH_IPCP_STATS	0x19
-#define PPP_READ_IPXCP_STATS	0x1A
-#define PPP_FLUSH_IPXCP_STATS	0x1B
-#define PPP_READ_PAP_STATS	0x1C
-#define PPP_FLUSH_PAP_STATS	0x1D
-#define PPP_READ_CHAP_STATS	0x1E
-#define PPP_FLUSH_CHAP_STATS	0x1F
-
-/* 'result' field defines */
-#define PPPRES_OK		0x00	/* command executed successfully */
-#define	PPPRES_INVALID_STATE	0x09	/* invalid command in this context */
-
-/*----------------------------------------------------------------------------
- * PPP Mailbox.
- *	This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT
- */
-typedef struct ppp_mbox
-{
-	unsigned char flag	PACKED;	/* 00h: command execution flag */
-	ppp_cmd_t     cmd	PACKED; /* 01h: command block */
-	unsigned char data[1]	PACKED;	/* 10h: variable length data buffer */
-} ppp_mbox_t;
-
-/*----------------------------------------------------------------------------
- * PPP Status Flags.
- *	This structure is located at offset PPP???_FLG_OFFS into
- *	PPP???_MB_VECT.
- */
-typedef struct	ppp_flags
-{
-	unsigned char iflag		PACKED;	/* 00: interrupt flag */
-	unsigned char imask		PACKED;	/* 01: interrupt mask */
-	unsigned char resrv		PACKED;
-	unsigned char mstatus		PACKED;	/* 03: modem status */
-	unsigned char lcp_state		PACKED; /* 04: LCP state */
-	unsigned char ppp_phase		PACKED;	/* 05: PPP phase */
-	unsigned char ip_state		PACKED; /* 06: IPCP state */
-	unsigned char ipx_state		PACKED; /* 07: IPXCP state */
-	unsigned char pap_state		PACKED; /* 08: PAP state */
-	unsigned char chap_state	PACKED; /* 09: CHAP state */
-	unsigned short disc_cause	PACKED;	/* 0A: disconnection cause */
-} ppp_flags_t;
-
-/* 'iflag' defines */
-#define	PPP_INTR_RXRDY		0x01	/* Rx ready */
-#define	PPP_INTR_TXRDY		0x02	/* Tx ready */
-#define	PPP_INTR_MODEM		0x04	/* modem status change (DCD, CTS) */
-#define	PPP_INTR_CMD		0x08	/* interface command completed */
-#define	PPP_INTR_DISC		0x10	/* data link disconnected */
-#define	PPP_INTR_OPEN		0x20	/* data link open */
-#define	PPP_INTR_DROP_DTR	0x40	/* DTR drop timeout expired */
-#define PPP_INTR_TIMER          0x80    /* timer interrupt */
-
-
-/* 'mstatus' defines */
-#define	PPP_MDM_DCD		0x08	/* mdm_status: DCD */
-#define	PPP_MDM_CTS		0x20	/* mdm_status: CTS */
-
-/* 'disc_cause' defines */
-#define PPP_LOCAL_TERMINATION   0x0001	/* Local Request by PPP termination phase */
-#define PPP_DCD_CTS_DROP        0x0002  /* DCD and/or CTS dropped. Link down */
-#define PPP_REMOTE_TERMINATION	0x0800	/* Remote Request by PPP termination phase */
-
-/* 'misc_config_bits' defines */
-#define DONT_RE_TX_ABORTED_I_FRAMES 	0x01
-#define TX_FRM_BYTE_COUNT_STATS         0x02
-#define RX_FRM_BYTE_COUNT_STATS         0x04
-#define TIME_STAMP_IN_RX_FRAMES         0x08
-#define NON_STD_ADPTR_FREQ              0x10
-#define INTERFACE_LEVEL_RS232           0x20
-#define AUTO_LINK_RECOVERY              0x100
-#define DONT_TERMINATE_LNK_MAX_CONFIG   0x200                    
-
-/* 'authentication options' defines */
-#define NO_AUTHENTICATION	0x00
-#define INBOUND_AUTH		0x80
-#define PAP_AUTH		0x01
-#define CHAP_AUTH		0x02		
-
-/* 'ip options' defines */
-#define L_AND_R_IP_NO_ASSIG	0x00
-#define L_IP_LOCAL_ASSIG    	0x01
-#define L_IP_REMOTE_ASSIG   	0x02
-#define R_IP_LOCAL_ASSIG        0x04
-#define R_IP_REMOTE_ASSIG       0x08
-#define ENABLE_IP		0x80
-
-/* 'ipx options' defines */
-#define ROUTING_PROT_DEFAULT    0x20
-#define ENABLE_IPX		0x80
-#define DISABLE_IPX		0x00
-
-/*----------------------------------------------------------------------------
- * PPP Buffer Info.
- *	This structure is located at offset PPP508_BUF_OFFS into
- *	PPP508_MB_VECT.
- */
-typedef struct	ppp508_buf_info
-{
-	unsigned short txb_num	PACKED;	/* 00: number of transmit buffers */
-	unsigned long  txb_ptr	PACKED;	/* 02: pointer to the buffer ctl. */
-	unsigned long  txb_nxt  PACKED;
-	unsigned char  rsrv1[22] PACKED;
-	unsigned short rxb_num	PACKED;	/* 20: number of receive buffers */
-	unsigned long  rxb_ptr	PACKED;	/* 22: pointer to the buffer ctl. */
-	unsigned long  rxb1_ptr	PACKED;	/* 26: pointer to the first buf.ctl. */
-	unsigned long  rxb_base	PACKED;	/* 2A: pointer to the buffer base */
-	unsigned char  rsrv2[2]	PACKED;
-	unsigned long  rxb_end	PACKED;	/* 30: pointer to the buffer end */
-} ppp508_buf_info_t;
-
-/*----------------------------------------------------------------------------
- * Transmit/Receive Buffer Control Block.
- */
-typedef struct	ppp_buf_ctl
-{
-	unsigned char  flag		PACKED;	/* 00: 'buffer ready' flag */
-	unsigned short length		PACKED;	/* 01: length of data */
-	unsigned char  reserved1[1]	PACKED;	/* 03: */
-	unsigned char  proto		PACKED;	/* 04: protocol */
-	unsigned short timestamp	PACKED;	/* 05: time stamp (Rx only) */
-	unsigned char  reserved2[5]	PACKED;	/* 07: */
-	union
-	{
-		unsigned short o_p[2];	/* 1C: buffer offset & page (S502) */
-		unsigned long  ptr;	/* 1C: buffer pointer (S508) */
-	} buf				PACKED;
-} ppp_buf_ctl_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command).
- */
-typedef struct	ppp508_conf
-{
-	unsigned long  line_speed	PACKED;	/* 00: baud rate, bps */
-	unsigned short txbuf_percent	PACKED;	/* 04: % of Tx buffer */
-	unsigned short conf_flags	PACKED;	/* 06: configuration bits */
-	unsigned short mtu_local	PACKED;	/* 08: local MTU */
-	unsigned short mtu_remote	PACKED;	/* 0A: remote MTU */
-	unsigned short restart_tmr	PACKED;	/* 0C: restart timer */
-	unsigned short auth_rsrt_tmr	PACKED;	/* 0E: authentication timer */
-	unsigned short auth_wait_tmr	PACKED;	/* 10: authentication timer */
-	unsigned short mdm_fail_tmr	PACKED;	/* 12: modem failure timer */
-	unsigned short dtr_drop_tmr	PACKED;	/* 14: DTR drop timer */
-	unsigned short connect_tmout	PACKED;	/* 16: connection timeout */
-	unsigned short conf_retry	PACKED;	/* 18: max. retry */
-	unsigned short term_retry	PACKED;	/* 1A: max. retry */
-	unsigned short fail_retry	PACKED;	/* 1C: max. retry */
-	unsigned short auth_retry	PACKED;	/* 1E: max. retry */
-	unsigned char  auth_options	PACKED;	/* 20: authentication opt. */
-	unsigned char  ip_options	PACKED;	/* 21: IP options */
-	unsigned long  ip_local		PACKED;	/* 22: local IP address */
-	unsigned long  ip_remote	PACKED;	/* 26: remote IP address */
-	unsigned char  ipx_options	PACKED;	/* 2A: IPX options */
-	unsigned char  ipx_netno[4]	PACKED;	/* 2B: IPX net number */
-	unsigned char  ipx_local[6]	PACKED;	/* 2F: local IPX node number*/
-	unsigned char  ipx_remote[6]	PACKED;	/* 35: remote IPX node num.*/
-	unsigned char  ipx_router[48]	PACKED;	/* 3B: IPX router name*/
-	unsigned long  alt_cpu_clock	PACKED;	/* 6B:  */
-} ppp508_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Read Connection Information Block 
- *    Returned by the PPP_GET_CONNECTION_INFO command
- */
-typedef struct	ppp508_connect_info
-{
-	unsigned short 	mru		PACKED;	/* 00-01 Remote Max Rec' Unit */
-	unsigned char  	ip_options 	PACKED; /* 02: Negotiated ip options  */
-	unsigned long  	ip_local	PACKED;	/* 03-06: local IP address    */
-	unsigned long  	ip_remote	PACKED;	/* 07-0A: remote IP address   */
-	unsigned char	ipx_options	PACKED; /* 0B: Negotiated ipx options */
-	unsigned char  	ipx_netno[4]	PACKED;	/* 0C-0F: IPX net number      */
-	unsigned char  	ipx_local[6]	PACKED;	/* 10-1F: local IPX node #    */
-	unsigned char  	ipx_remote[6]	PACKED;	/* 16-1B: remote IPX node #   */
-	unsigned char  	ipx_router[48]	PACKED;	/* 1C-4B: IPX router name     */
-	unsigned char	auth_status	PACKED; /* 4C: Authentication Status  */
-	unsigned char 	inbd_auth_peerID[1] PACKED; /* 4D: variable length inbound authenticated peer ID */
-} ppp508_connect_info_t;
-
-/* 'line_speed' field */
-#define	PPP_BITRATE_1200	0x01
-#define	PPP_BITRATE_2400	0x02
-#define	PPP_BITRATE_4800	0x03
-#define	PPP_BITRATE_9600	0x04
-#define	PPP_BITRATE_19200	0x05
-#define	PPP_BITRATE_38400	0x06
-#define	PPP_BITRATE_45000	0x07
-#define	PPP_BITRATE_56000	0x08
-#define	PPP_BITRATE_64000	0x09
-#define	PPP_BITRATE_74000	0x0A
-#define	PPP_BITRATE_112000	0x0B
-#define	PPP_BITRATE_128000	0x0C
-#define	PPP_BITRATE_156000	0x0D
-
-/* Defines for the 'conf_flags' field */
-#define	PPP_IGNORE_TX_ABORT	0x01	/* don't re-transmit aborted frames */
-#define	PPP_ENABLE_TX_STATS	0x02	/* enable Tx statistics */
-#define	PPP_ENABLE_RX_STATS	0x04	/* enable Rx statistics */
-#define	PPP_ENABLE_TIMESTAMP	0x08	/* enable timestamp */
-
-/* 'ip_options' defines */
-#define	PPP_LOCAL_IP_LOCAL	0x01
-#define	PPP_LOCAL_IP_REMOTE	0x02
-#define	PPP_REMOTE_IP_LOCAL	0x04
-#define	PPP_REMOTE_IP_REMOTE	0x08
-
-/* 'ipx_options' defines */
-#define	PPP_REMOTE_IPX_NETNO	0x01
-#define	PPP_REMOTE_IPX_LOCAL	0x02
-#define	PPP_REMOTE_IPX_REMOTE	0x04
-#define	PPP_IPX_ROUTE_RIP_SAP	0x08
-#define	PPP_IPX_ROUTE_NLSP	0x10
-#define	PPP_IPX_ROUTE_DEFAULT	0x20
-#define	PPP_IPX_CONF_COMPLETE	0x40
-#define	PPP_IPX_ENABLE		0x80
-
-/*----------------------------------------------------------------------------
- * S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command).
- */
-typedef struct	ppp508_get_conf
-{
-	unsigned long  bps	PACKED;	/* 00: baud rate, bps */
-	ppp508_conf_t  conf	PACKED;	/* 04: requested config. */
-	unsigned short txb_num	PACKED;	/* 6F: number of Tx buffers */
-	unsigned short rxb_num	PACKED;	/* 71: number of Rx buffers */
-} ppp508_get_conf_t;
-
-/*----------------------------------------------------------------------------
- * S508 Operational Statistics (returned by the PPP_READ_STATISTIC command).
- */
-typedef struct ppp508_stats
-{
-	unsigned short reserved1	PACKED;	/* 00: */
-	unsigned short rx_bad_len	PACKED;	/* 02: */
-	unsigned short reserved2	PACKED;	/* 04: */
-	unsigned long  tx_frames	PACKED;	/* 06: */
-	unsigned long  tx_bytes	PACKED;	/* 0A: */
-	unsigned long  rx_frames	PACKED;	/* 0E: */
-	unsigned long  rx_bytes	PACKED;	/* 12: */
-} ppp508_stats_t;
-
-/*----------------------------------------------------------------------------
- * Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command).
- */
-typedef struct	ppp_err_stats
-{
-	unsigned char	 rx_overrun	PACKED;	/* 00: Rx overrun errors */
-	unsigned char	 rx_bad_crc	PACKED;	/* 01: Rx CRC errors */
-	unsigned char	 rx_abort	PACKED;	/* 02: Rx aborted frames */
-	unsigned char	 rx_lost	PACKED;	/* 03: Rx frames lost */
-	unsigned char	 tx_abort	PACKED;	/* 04: Tx aborted frames */
-	unsigned char	 tx_underrun	PACKED;	/* 05: Tx underrun errors */
-	unsigned char	 tx_missed_intr	PACKED;	/* 06: Tx underruns missed */
-	unsigned char	 reserved	PACKED;	/* 07: Tx underruns missed */
-	unsigned char	 dcd_trans	PACKED;	/* 08: DCD transitions */
-	unsigned char	 cts_trans	PACKED;	/* 09: CTS transitions */
-} ppp_err_stats_t;
-
-/*----------------------------------------------------------------------------
- * Packet Statistics (returned by the PPP_READ_PACKET_STATS command).
- */
-typedef struct	ppp_pkt_stats
-{
-	unsigned short rx_bad_header	PACKED;	/* 00: */
-	unsigned short rx_prot_unknwn	PACKED;	/* 02: */
-	unsigned short rx_too_large	PACKED;	/* 04: */
-	unsigned short rx_lcp		PACKED;	/* 06: */
-	unsigned short tx_lcp		PACKED;	/* 08: */
-	unsigned short rx_ipcp		PACKED;	/* 0A: */
-	unsigned short tx_ipcp		PACKED;	/* 0C: */
-	unsigned short rx_ipxcp		PACKED;	/* 0E: */
-	unsigned short tx_ipxcp		PACKED;	/* 10: */
-	unsigned short rx_pap		PACKED;	/* 12: */
-	unsigned short tx_pap		PACKED;	/* 14: */
-	unsigned short rx_chap		PACKED;	/* 16: */
-	unsigned short tx_chap		PACKED;	/* 18: */
-	unsigned short rx_lqr		PACKED;	/* 1A: */
-	unsigned short tx_lqr		PACKED;	/* 1C: */
-	unsigned short rx_ip		PACKED;	/* 1E: */
-	unsigned short tx_ip		PACKED;	/* 20: */
-	unsigned short rx_ipx		PACKED;	/* 22: */
-	unsigned short tx_ipx		PACKED;	/* 24: */
-} ppp_pkt_stats_t;
-
-/*----------------------------------------------------------------------------
- * LCP Statistics (returned by the PPP_READ_LCP_STATS command).
- */
-typedef struct	ppp_lcp_stats
-{
-	unsigned short rx_unknown	PACKED;	/* 00: unknown LCP type */
-	unsigned short rx_conf_rqst	PACKED;	/* 02: Configure-Request */
-	unsigned short rx_conf_ack	PACKED;	/* 04: Configure-Ack */
-	unsigned short rx_conf_nak	PACKED;	/* 06: Configure-Nak */
-	unsigned short rx_conf_rej	PACKED;	/* 08: Configure-Reject */
-	unsigned short rx_term_rqst	PACKED;	/* 0A: Terminate-Request */
-	unsigned short rx_term_ack	PACKED;	/* 0C: Terminate-Ack */
-	unsigned short rx_code_rej	PACKED;	/* 0E: Code-Reject */
-	unsigned short rx_proto_rej	PACKED;	/* 10: Protocol-Reject */
-	unsigned short rx_echo_rqst	PACKED;	/* 12: Echo-Request */
-	unsigned short rx_echo_reply	PACKED;	/* 14: Echo-Reply */
-	unsigned short rx_disc_rqst	PACKED;	/* 16: Discard-Request */
-	unsigned short tx_conf_rqst	PACKED;	/* 18: Configure-Request */
-	unsigned short tx_conf_ack	PACKED;	/* 1A: Configure-Ack */
-	unsigned short tx_conf_nak	PACKED;	/* 1C: Configure-Nak */
-	unsigned short tx_conf_rej	PACKED;	/* 1E: Configure-Reject */
-	unsigned short tx_term_rqst	PACKED;	/* 20: Terminate-Request */
-	unsigned short tx_term_ack	PACKED;	/* 22: Terminate-Ack */
-	unsigned short tx_code_rej	PACKED;	/* 24: Code-Reject */
-	unsigned short tx_proto_rej	PACKED;	/* 26: Protocol-Reject */
-	unsigned short tx_echo_rqst	PACKED;	/* 28: Echo-Request */
-	unsigned short tx_echo_reply	PACKED;	/* 2A: Echo-Reply */
-	unsigned short tx_disc_rqst	PACKED;	/* 2E: Discard-Request */
-	unsigned short rx_too_large	PACKED;	/* 30: packets too large */
-	unsigned short rx_ack_inval	PACKED;	/* 32: invalid Conf-Ack */
-	unsigned short rx_rej_inval	PACKED;	/* 34: invalid Conf-Reject */
-	unsigned short rx_rej_badid	PACKED;	/* 36: Conf-Reject w/bad ID */
-} ppp_lcp_stats_t;
-
-/*----------------------------------------------------------------------------
- * Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command).
- */
-typedef struct	ppp_lpbk_stats
-{
-	unsigned short conf_magic	PACKED;	/* 00:  */
-	unsigned short loc_echo_rqst	PACKED;	/* 02:  */
-	unsigned short rem_echo_rqst	PACKED;	/* 04:  */
-	unsigned short loc_echo_reply	PACKED;	/* 06:  */
-	unsigned short rem_echo_reply	PACKED;	/* 08:  */
-	unsigned short loc_disc_rqst	PACKED;	/* 0A:  */
-	unsigned short rem_disc_rqst	PACKED;	/* 0C:  */
-	unsigned short echo_tx_collsn	PACKED;	/* 0E:  */
-	unsigned short echo_rx_collsn	PACKED;	/* 10:  */
-} ppp_lpbk_stats_t;
-
-/*----------------------------------------------------------------------------
- * Protocol Statistics (returned by the PPP_READ_IPCP_STATS and
- * PPP_READ_IPXCP_STATS commands).
- */
-typedef struct	ppp_prot_stats
-{
-	unsigned short rx_unknown	PACKED;	/* 00: unknown type */
-	unsigned short rx_conf_rqst	PACKED;	/* 02: Configure-Request */
-	unsigned short rx_conf_ack	PACKED;	/* 04: Configure-Ack */
-	unsigned short rx_conf_nak	PACKED;	/* 06: Configure-Nak */
-	unsigned short rx_conf_rej	PACKED;	/* 08: Configure-Reject */
-	unsigned short rx_term_rqst	PACKED;	/* 0A: Terminate-Request */
-	unsigned short rx_term_ack	PACKED;	/* 0C: Terminate-Ack */
-	unsigned short rx_code_rej	PACKED;	/* 0E: Code-Reject */
-	unsigned short reserved		PACKED;	/* 10: */
-	unsigned short tx_conf_rqst	PACKED;	/* 12: Configure-Request */
-	unsigned short tx_conf_ack	PACKED;	/* 14: Configure-Ack */
-	unsigned short tx_conf_nak	PACKED;	/* 16: Configure-Nak */
-	unsigned short tx_conf_rej	PACKED;	/* 18: Configure-Reject */
-	unsigned short tx_term_rqst	PACKED;	/* 1A: Terminate-Request */
-	unsigned short tx_term_ack	PACKED;	/* 1C: Terminate-Ack */
-	unsigned short tx_code_rej	PACKED;	/* 1E: Code-Reject */
-	unsigned short rx_too_large	PACKED;	/* 20: packets too large */
-	unsigned short rx_ack_inval	PACKED;	/* 22: invalid Conf-Ack */
-	unsigned short rx_rej_inval	PACKED;	/* 24: invalid Conf-Reject */
-	unsigned short rx_rej_badid	PACKED;	/* 26: Conf-Reject w/bad ID */
-} ppp_prot_stats_t;
-
-/*----------------------------------------------------------------------------
- * PAP Statistics (returned by the PPP_READ_PAP_STATS command).
- */
-typedef struct	ppp_pap_stats
-{
-	unsigned short rx_unknown	PACKED;	/* 00: unknown type */
-	unsigned short rx_auth_rqst	PACKED;	/* 02: Authenticate-Request */
-	unsigned short rx_auth_ack	PACKED;	/* 04: Authenticate-Ack */
-	unsigned short rx_auth_nak	PACKED;	/* 06: Authenticate-Nak */
-	unsigned short reserved		PACKED;	/* 08: */
-	unsigned short tx_auth_rqst	PACKED;	/* 0A: Authenticate-Request */
-	unsigned short tx_auth_ack	PACKED;	/* 0C: Authenticate-Ack */
-	unsigned short tx_auth_nak	PACKED;	/* 0E: Authenticate-Nak */
-	unsigned short rx_too_large	PACKED;	/* 10: packets too large */
-	unsigned short rx_bad_peerid	PACKED;	/* 12: invalid peer ID */
-	unsigned short rx_bad_passwd	PACKED;	/* 14: invalid password */
-} ppp_pap_stats_t;
-
-/*----------------------------------------------------------------------------
- * CHAP Statistics (returned by the PPP_READ_CHAP_STATS command).
- */
-typedef struct	ppp_chap_stats
-{
-	unsigned short rx_unknown	PACKED;	/* 00: unknown type */
-	unsigned short rx_challenge	PACKED;	/* 02: Authenticate-Request */
-	unsigned short rx_response	PACKED;	/* 04: Authenticate-Ack */
-	unsigned short rx_success	PACKED;	/* 06: Authenticate-Nak */
-	unsigned short rx_failure	PACKED;	/* 08: Authenticate-Nak */
-	unsigned short reserved		PACKED;	/* 0A: */
-	unsigned short tx_challenge	PACKED;	/* 0C: Authenticate-Request */
-	unsigned short tx_response	PACKED;	/* 0E: Authenticate-Ack */
-	unsigned short tx_success	PACKED;	/* 10: Authenticate-Nak */
-	unsigned short tx_failure	PACKED;	/* 12: Authenticate-Nak */
-	unsigned short rx_too_large	PACKED;	/* 14: packets too large */
-	unsigned short rx_bad_peerid	PACKED;	/* 16: invalid peer ID */
-	unsigned short rx_bad_passwd	PACKED;	/* 18: invalid password */
-	unsigned short rx_bad_md5	PACKED;	/* 1A: invalid MD5 format */
-	unsigned short rx_bad_resp	PACKED;	/* 1C: invalid response */
-} ppp_chap_stats_t;
-
-/*----------------------------------------------------------------------------
- * Connection Information (returned by the PPP_GET_CONNECTION_INFO command).
- */
-typedef struct	ppp_conn_info
-{
-	unsigned short remote_mru	PACKED;	/* 00:  */
-	unsigned char  ip_options	PACKED;	/* 02:  */
-	unsigned char  ip_local[4]	PACKED;	/* 03:  */
-	unsigned char  ip_remote[4]	PACKED;	/* 07:  */
-	unsigned char  ipx_options	PACKED;	/* 0B:  */
-	unsigned char  ipx_network[4]	PACKED;	/* 0C:  */
-	unsigned char  ipx_local[6]	PACKED;	/* 10:  */
-	unsigned char  ipx_remote[6]	PACKED;	/* 16:  */
-	unsigned char  ipx_router[48]	PACKED;	/* 1C:  */
-	unsigned char  auth_status	PACKED;	/* 4C:  */
-	unsigned char  peer_id[0]	PACKED;	/* 4D:  */
-} ppp_conn_info_t;
-
-/* Data structure for SET_TRIGGER_INTR command
- */
-
-typedef struct ppp_intr_info{
-	unsigned char  i_enable		PACKED; /* 0 Interrupt enable bits */
-	unsigned char  irq              PACKED; /* 1 Irq number */
-	unsigned short timer_len        PACKED; /* 2 Timer delay */
-} ppp_intr_info_t;
-
-
-#define FT1_MONITOR_STATUS_CTRL                         0x80
-#define SET_FT1_MODE                                    0x81
-
-
-
-/* Special UDP drivers management commands */
-#define PPIPE_ENABLE_TRACING                            0x20
-#define PPIPE_DISABLE_TRACING                           0x21
-#define PPIPE_GET_TRACE_INFO                            0x22
-#define PPIPE_GET_IBA_DATA                              0x23
-#define PPIPE_KILL_BOARD     				0x24
-#define PPIPE_FT1_READ_STATUS                           0x25
-#define PPIPE_DRIVER_STAT_IFSEND                        0x26
-#define PPIPE_DRIVER_STAT_INTR                          0x27
-#define PPIPE_DRIVER_STAT_GEN                           0x28
-#define PPIPE_FLUSH_DRIVER_STATS                        0x29
-#define PPIPE_ROUTER_UP_TIME                            0x30
-
-#define DISABLE_TRACING 				0x00
-#define TRACE_SIGNALLING_FRAMES				0x01
-#define TRACE_DATA_FRAMES				0x02
-
-
-
-#ifdef		_MSC_
-#  pragma	pack()
-#endif
-#endif	/* _SDLA_PPP_H */
diff --git a/include/linux/sdla_x25.h b/include/linux/sdla_x25.h
deleted file mode 100644
index 57db980..0000000
--- a/include/linux/sdla_x25.h
+++ /dev/null
@@ -1,772 +0,0 @@
-/*****************************************************************************
-* sdla_x25.h	Sangoma X.25 firmware API definitions.
-*
-* Author:	Nenad Corbic	<ncorbic@sangoma.com>
-*
-* Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Feb 28, 2000  Nenad Corbic    Updated for socket based x25api
-* Dec 13, 1996	Gene Kozin	Initial version
-*****************************************************************************/
-#ifndef	_SDLA_X25_H
-#define	_SDLA_X25_H
-
-/*----------------------------------------------------------------------------
- * Notes:
- * ------
- * 1. All structures defined in this file are byte-alined.  
- *	Compiler	Platform	
- *	--------	--------
- *	GNU C		Linux
- *
- */
-
-#ifndef	PACKED
-#	define	PACKED	__attribute__((packed))
-#endif	/* PACKED */
-
-/******	CONSTANTS DEFINITIONS ***********************************************/
-
-#define	X25_MAX_CHAN	255	/* max number of open X.25 circuits */
-#define	X25_MAX_DATA	1024	/* max length of X.25 data buffer */
-/*
- * X.25 shared memory layout.
- */
-#define	X25_MBOX_OFFS	0x16B0	/* general mailbox block */
-#define	X25_RXMBOX_OFFS	0x1AD0	/* receive mailbox */
-#define	X25_STATUS_OFFS	0x1EF0	/* X.25 status structure */
-#define X25_MB_VECTOR	0xE000	/* S514 mailbox window vecotr */
-#define X25_MISC_HDLC_BITS 0x1F00 /*X.25 miscallaneous HDLC bits */
-
-/* code levels */
-#define HDLC_LEVEL 0x01
-#define X25_LEVEL  0x02
-#define X25_AND_HDLC_LEVEL 0x03
-#define DO_HDLC_LEVEL_ERROR_CHECKING 0x04
-
-/****** DATA STRUCTURES *****************************************************/
-
-/*----------------------------------------------------------------------------
- * X.25 Command Block.
- */
-typedef struct X25Cmd
-{
-	unsigned char command	PACKED;	/* command code */
-	unsigned short length	PACKED;	/* transfer data length */
-	unsigned char result	PACKED;	/* return code */
-	unsigned char pf	PACKED;	/* P/F bit */
-	unsigned short lcn	PACKED;	/* logical channel */
-	unsigned char qdm	PACKED;	/* Q/D/M bits */
-	unsigned char cause	PACKED;	/* cause field */
-	unsigned char diagn	PACKED;	/* diagnostics */
-	unsigned char pktType	PACKED;	/* packet type */
-	unsigned char resrv[4]	PACKED;	/* reserved */
-} TX25Cmd;
-
-/*
- * Defines for the 'command' field.
- */
-/*----- General commands --------------*/
-#define X25_SET_GLOBAL_VARS	0x0B   	/* set global variables */ 
-#define X25_READ_MODEM_STATUS	0x0C 	/* read modem status */
-#define X25_READ_CODE_VERSION	0x15	/* read firmware version number */
-#define X25_TRACE_CONFIGURE	0x14	/* configure trace facility */
-#define X25_READ_TRACE_DATA	0x16	/* read trace data */
-#define	X25_SET_INTERRUPT_MODE	0x17	/* set interrupt generation mode */
-#define	X25_READ_INTERRUPT_MODE	0x18	/* read interrupt generation mode */
-/*----- HDLC-level commands -----------*/
-#define X25_HDLC_LINK_CONFIGURE	0x01	/* configure HDLC link level */   
-#define X25_HDLC_LINK_OPEN	0x02	/* open HDLC link */         	
-#define X25_HDLC_LINK_CLOSE	0x03	/* close HDLC link */
-#define X25_HDLC_LINK_SETUP	0x04	/* set up HDLC link */ 
-#define X25_HDLC_LINK_DISC	0x05	/* disconnect DHLC link */
-#define X25_HDLC_LINK_STATUS	0x06	/* read DHLC link status */
-#define X25_HDLC_READ_STATS	0x07	/* read operational statistics */
-#define X25_HDLC_FLUSH_STATS	0x08 	/* flush operational statistics */
-#define X25_HDLC_READ_COMM_ERR	0x09 	/* read error statistics */
-#define X25_HDLC_FLUSH_COMM_ERR	0x0A	/* flush error statistics */
-#define X25_HDLC_FLUSH_BUFFERS	0x0D	/* flush HDLC-level data buffers */
-#define X25_HDLC_SPRVS_CNT_STAT 0x0F	/* read surervisory count status */
-#define X25_HDLC_SEND_UI_FRAME	0x10	/* send unnumbered information frame */
-#define X25_HDLC_WRITE		0x11	/* send HDLC information frame */
-#define X25_HDLC_READ		0x21	/* read HDLC information frame */
-#define X25_HDLC_READ_CONFIG	0x12	/* read HDLC configuration */
-#define X25_HDLC_SET_CONFIG	0x13	/* set HDLC configuration */
-#define SET_PROTOCOL_LEVEL	0x1F	/* set protocol level */
-/*----- X.25-level commands -----------*/
-#define X25_READ		0x22	/* read X.25 packet */
-#define X25_WRITE		0x23	/* send X.25 packet */
-#define X25_PLACE_CALL		0x30	/* place a call on SVC */
-#define X25_ACCEPT_CALL		0x31	/* accept incomming call */
-#define X25_CLEAR_CALL		0x32	/* clear call */
-#define X25_CLEAR_CONFRM	0x33	/* send clear confirmation packet */
-#define X25_RESET		0x34	/* send reset request packet */
-#define X25_RESET_CONFRM	0x35	/* send reset confirmation packet */
-#define X25_RESTART		0x36	/* send restart request packet */
-#define X25_RESTART_CONFRM	0x37	/* send restart confirmation packet */
-#define X25_INTERRUPT		0x38	/* send interrupt request packet */
-#define X25_INTERRUPT_CONFRM	0x39	/* send interrupt confirmation pkt */
-#define X25_REGISTRATION_RQST	0x3A	/* send registration request packet */
-#define X25_REGISTRATION_CONFRM	0x3B	/* send registration confirmation */
-#define X25_IS_DATA_AVAILABLE	0x40	/* querry receive queue */
-#define X25_INCOMMING_CALL_CTL	0x41	/* select incomming call options */
-#define X25_CONFIGURE_PVC	0x42	/* configure PVC */
-#define X25_GET_ACTIVE_CHANNELS	0x43	/* get a list of active circuits */
-#define X25_READ_CHANNEL_CONFIG	0x44	/* read virt. circuit configuration */
-#define X25_FLUSH_DATA_BUFFERS	0x45	/* flush X.25-level data buffers */
-#define X25_READ_HISTORY_TABLE	0x46	/* read asynchronous event log */
-#define X25_HISTORY_TABLE_CTL	0x47	/* control asynchronous event log */
-#define	X25_GET_TX_D_BIT_STATUS	0x48	/* is packet with D-bit acknowleged */
-#define	X25_READ_STATISTICS	0x49	/* read X.25-level statistics */
-#define	X25_FLUSH_STATISTICS	0x4A	/* flush X.25-level statistics */
-#define	X25_READ_CONFIGURATION	0x50	/* read HDLC & X.25 configuration */
-#define	X25_SET_CONFIGURATION	0x51	/* set HDLC & X.25 configuration */
-
-/*
- * Defines for the 'result' field.
- */
-/*----- General results ---------------*/
-#define X25RES_OK		0x00
-#define X25RES_ERROR		0x01
-#define X25RES_LINK_NOT_IN_ABM	0x02	/* link is not in ABM mode */
-#define X25RES_LINK_CLOSED	0x03
-#define X25RES_INVAL_LENGTH	0x04
-#define X25RES_INVAL_CMD	0x05
-#define X25RES_UNNUMBERED_FRAME	0x06	/* unnunbered frame received */
-#define X25RES_FRM_REJECT_MODE	0x07	/* link is in Frame Reject mode */
-#define X25RES_MODEM_FAILURE	0x08	/* DCD and/or CTS dropped */
-#define X25RES_N2_RETRY_LIMIT	0x09	/* N2 retry limit has been exceeded */
-#define X25RES_INVAL_LCN	0x30	/* invalid logical channel number */
-#define X25RES_INVAL_STATE	0x31	/* channel is not in data xfer mode */
-#define X25RES_INVAL_DATA_LEN	0x32	/* invalid data length */
-#define X25RES_NOT_READY	0x33	/* no data available / buffers full */
-#define X25RES_NETWORK_DOWN	0x34
-#define X25RES_CHANNEL_IN_USE	0x35	/* there is data queued on this LCN */
-#define X25RES_REGST_NOT_SUPPRT	0x36	/* registration not supported */
-#define X25RES_INVAL_FORMAT	0x37	/* invalid packet format */
-#define X25RES_D_BIT_NOT_SUPPRT	0x38	/* D-bit pragmatics not supported */
-#define X25RES_FACIL_NOT_SUPPRT	0x39	/* Call facility not supported */
-#define X25RES_INVAL_CALL_ARG	0x3A	/* errorneous call arguments */
-#define X25RES_INVAL_CALL_DATA	0x3B	/* errorneous call user data */
-#define X25RES_ASYNC_PACKET	0x40	/* asynchronous packet received */
-#define X25RES_PROTO_VIOLATION	0x41	/* protocol violation occurred */
-#define X25RES_PKT_TIMEOUT	0x42	/* X.25 packet time out */
-#define X25RES_PKT_RETRY_LIMIT	0x43	/* X.25 packet retry limit exceeded */
-/*----- Command-dependent results -----*/
-#define X25RES_LINK_DISC	0x00	/* HDLC_LINK_STATUS */
-#define X25RES_LINK_IN_ABM	0x01	/* HDLC_LINK_STATUS */
-#define X25RES_NO_DATA		0x01	/* HDLC_READ/READ_TRACE_DATA*/
-#define X25RES_TRACE_INACTIVE	0x02	/* READ_TRACE_DATA */
-#define X25RES_LINK_IS_OPEN	0x01	/* HDLC_LINK_OPEN */
-#define X25RES_LINK_IS_DISC	0x02	/* HDLC_LINK_DISC */
-#define X25RES_LINK_IS_CLOSED	0x03	/* HDLC_LINK_CLOSE */
-#define X25RES_INVAL_PARAM	0x31	/* INCOMMING_CALL_CTL */
-#define X25RES_INVAL_CONFIG	0x35	/* REGISTR_RQST/CONFRM */
-
-/*
- * Defines for the 'qdm_bits' field.
- */
-#define X25CMD_Q_BIT_MASK	0x04
-#define X25CMD_D_BIT_MASK	0x02
-#define X25CMD_M_BIT_MASK	0x01
-
-/*
- * Defines for the 'pkt_type' field.
- */
-/*----- Asynchronous events ------*/
-#define ASE_CLEAR_RQST		0x02
-#define ASE_RESET_RQST		0x04
-#define ASE_RESTART_RQST	0x08
-#define ASE_INTERRUPT		0x10
-#define ASE_DTE_REGISTR_RQST	0x20
-#define ASE_CALL_RQST		0x30
-#define ASE_CALL_ACCEPTED	0x31
-#define ASE_CLEAR_CONFRM	0x32
-#define ASE_RESET_CONFRM	0x33
-#define ASE_RESTART_CONFRM	0x34
-#define ASE_INTERRUPT_CONFRM	0x35
-#define ASE_DCE_REGISTR_CONFRM	0x36
-#define ASE_DIAGNOSTIC		0x37
-#define ASE_CALL_AUTO_CLEAR	0x38
-#define AUTO_RESPONSE_FLAG	0x80
-/*----- Time-Out events ----------*/
-#define TOE_RESTART_RQST	0x03
-#define TOE_CALL_RQST		0x05
-#define TOE_CLEAR_RQST		0x08
-#define TOE_RESET_RQST		0x0A
-/*----- Protocol Violation events */
-#define PVE_CLEAR_RQST		0x32
-#define PVE_RESET_RQST		0x33
-#define PVE_RESTART_RQST	0x34
-#define PVE_DIAGNOSTIC		0x37
-
-#define INTR_ON_RX_FRAME            0x01
-#define INTR_ON_TX_FRAME            0x02
-#define INTR_ON_MODEM_STATUS_CHANGE 0x04
-#define INTR_ON_COMMAND_COMPLETE    0x08
-#define INTR_ON_X25_ASY_TRANSACTION 0x10
-#define INTR_ON_TIMER		    0x40
-#define DIRECT_RX_INTR_USAGE        0x80
-
-#define NO_INTR_PENDING  	        0x00
-#define RX_INTR_PENDING			0x01	
-#define TX_INTR_PENDING			0x02
-#define MODEM_INTR_PENDING		0x04
-#define COMMAND_COMPLETE_INTR_PENDING 	0x08
-#define X25_ASY_TRANS_INTR_PENDING	0x10
-#define TIMER_INTR_PENDING		0x40
-
-/*----------------------------------------------------------------------------
- * X.25 Mailbox.
- *	This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS
- *	into shared memory window.
- */
-typedef struct X25Mbox
-{
-	unsigned char opflag	PACKED;	/* 00h: execution flag */
-	TX25Cmd cmd		PACKED;	/* 01h: command block */
-	unsigned char data[1]	PACKED;	/* 10h: data buffer */
-} TX25Mbox;
-
-/*----------------------------------------------------------------------------
- * X.25 Time Stamp Structure.
- */
-typedef struct X25TimeStamp
-{
-	unsigned char month	PACKED;
-	unsigned char date	PACKED;
-	unsigned char sec	PACKED;
-	unsigned char min	PACKED;
-	unsigned char hour	PACKED;
-} TX25TimeStamp;
-
-/*----------------------------------------------------------------------------
- * X.25 Status Block.
- *	This structure is located at offset X25_STATUS_OFF into shared memory
- *	window.
- */
-typedef struct X25Status
-{
-	unsigned short pvc_map	PACKED;	/* 00h: PVC map */
-	unsigned short icc_map	PACKED;	/* 02h: Incomming Chan. map */
-	unsigned short twc_map	PACKED;	/* 04h: Two-way Cnan. map */
-	unsigned short ogc_map	PACKED;	/* 06h: Outgoing Chan. map */
-	TX25TimeStamp tstamp	PACKED;	/* 08h: timestamp (BCD) */
-	unsigned char iflags	PACKED;	/* 0Dh: interrupt flags */
-	unsigned char imask     PACKED; /* 0Eh: interrupt mask  */
-	unsigned char resrv	PACKED;	/* 0Eh: */
-	unsigned char gflags	PACKED;	/* 10h: misc. HDLC/X25 flags */
-	unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */
-} TX25Status;
-
-/*
- * Bitmasks for the 'iflags' field.
- */
-#define X25_RX_INTR	0x01	/* receive interrupt */
-#define X25_TX_INTR	0x02	/* transmit interrupt */
-#define X25_MODEM_INTR	0x04	/* modem status interrupt (CTS/DCD) */
-#define X25_EVENT_INTR	0x10	/* asyncronous event encountered */
-#define X25_CMD_INTR	0x08	/* interface command complete */
-
-/*
- * Bitmasks for the 'gflags' field.
- */
-#define X25_HDLC_ABM	0x01	/* HDLC is in ABM mode */
-#define X25_RX_READY	0x02	/* X.25 data available */
-#define X25_TRACE_READY	0x08	/* trace data available */
-#define X25_EVENT_IND	0x20	/* asynchronous event indicator */
-#define X25_TX_READY	0x40	/* space is available in Tx buf.*/
-
-/*
- * Bitmasks for the 'cflags' field.
- */
-#define X25_XFER_MODE	0x80	/* channel is in data transfer mode */
-#define X25_TXWIN_OPEN	0x40	/* transmit window open */
-#define X25_RXBUF_MASK	0x3F	/* number of data buffers available */
-
-/*****************************************************************************
- * Following definitions structurize contents of the TX25Mbox.data field for
- * different X.25 interface commands.
- ****************************************************************************/
-
-/* ---------------------------------------------------------------------------
- * X25_SET_GLOBAL_VARS Command.
- */
-typedef struct X25GlobalVars
-{
-	unsigned char resrv	PACKED;	/* 00h: reserved */
-	unsigned char dtrCtl	PACKED;	/* 01h: DTR control code */
-	unsigned char resErr	PACKED;	/* 01h: '1' - reset modem error */
-} TX25GlobalVars;
-
-/*
- * Defines for the 'dtrCtl' field.
- */
-#define X25_RAISE_DTR	0x01
-#define X25_DROP_DTR	0x02
-
-/* ---------------------------------------------------------------------------
- * X25_READ_MODEM_STATUS Command.
- */
-typedef struct X25ModemStatus
-{
-	unsigned char	status	PACKED;		/* 00h: modem status */
-} TX25ModemStatus;
-
-/*
- * Defines for the 'status' field.
- */
-#define X25_CTS_MASK	0x20
-#define X25_DCD_MASK	0x08
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_LINK_STATUS Command.
- */
-typedef struct X25LinkStatus
-{
-	unsigned char txQueued	PACKED;	/* 00h: queued Tx I-frames*/
-	unsigned char rxQueued	PACKED;	/* 01h: queued Rx I-frames*/
-	unsigned char station	PACKED;	/* 02h: DTE/DCE config. */
-	unsigned char reserved	PACKED;	/* 03h: reserved */
-	unsigned char sfTally	PACKED;	/* 04h: supervisory frame tally */
-} TX25LinkStatus;
-
-/*
- * Defines for the 'station' field.
- */
-#define	X25_STATION_DTE	0x01	/* station configured as DTE */
-#define X25_STATION_DCE	0x02	/* station configured as DCE */
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_STATS Command.
- */
-typedef struct HdlcStats
-{						/*	a number of ... */
-	unsigned short rxIFrames	PACKED;	/* 00h: ready Rx I-frames */
-	unsigned short rxNoseq		PACKED;	/* 02h: frms out-of-sequence */
-	unsigned short rxNodata		PACKED;	/* 04h: I-frms without data */
-	unsigned short rxDiscarded	PACKED;	/* 06h: discarded frames */
-	unsigned short rxTooLong	PACKED;	/* 08h: frames too long */
-	unsigned short rxBadAddr	PACKED;	/* 0Ah: frms with inval.addr*/
-	unsigned short txAcked		PACKED;	/* 0Ch: acknowledged I-frms */
-	unsigned short txRetransm	PACKED;	/* 0Eh: re-transmit. I-frms */
-	unsigned short t1Timeout	PACKED;	/* 10h: T1 timeouts */
-	unsigned short rxSABM		PACKED;	/* 12h: received SABM frames */
-	unsigned short rxDISC		PACKED;	/* 14h: received DISC frames */
-	unsigned short rxDM		PACKED;	/* 16h: received DM frames */
-	unsigned short rxFRMR		PACKED;	/* 18h: FRMR frames received */
-	unsigned short txSABM		PACKED;	/* 1Ah: transm. SABM frames*/
-	unsigned short txDISC		PACKED;	/* 1Ch: transm. DISC frames*/
-	unsigned short txDM		PACKED;	/* 1Eh: transm. DM frames */
-	unsigned short txFRMR		PACKED;	/* 20h: transm. FRMR frames*/
-} THdlcStats;
-
-/* ---------------------------------------------------------------------------
- * X25_HDLC_READ_COMM_ERR Command.
- */
-typedef struct HdlcCommErr
-{						/*	a number of ... */
-	unsigned char rxOverrun		PACKED;	/* 00h: Rx overrun errors */
-	unsigned char rxBadCrc		PACKED;	/* 01h: Rx CRC errors */
-	unsigned char rxAborted		PACKED;	/* 02h: Rx aborted frames */
-	unsigned char rxDropped		PACKED;	/* 03h: frames lost */
-	unsigned char txAborted		PACKED;	/* 04h: Tx aborted frames */
-	unsigned char txUnderrun	PACKED;	/* 05h: Tx underrun errors */
-	unsigned char txMissIntr	PACKED;	/* 06h: missed underrun ints */
-	unsigned char reserved		PACKED;	/* 07h: reserved */
-	unsigned char droppedDCD	PACKED;	/* 08h: times DCD dropped */
-	unsigned char droppedCTS	PACKED;	/* 09h: times CTS dropped */
-} THdlcCommErr;
-
-/* ---------------------------------------------------------------------------
- * X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands.
- */
-typedef struct X25Config
-{
-unsigned char baudRate		PACKED;	/* 00h:  */
-	unsigned char t1		PACKED;	/* 01h:  */
-	unsigned char t2		PACKED;	/* 02h:  */
-	unsigned char n2		PACKED;	/* 03h:  */
-	unsigned short hdlcMTU		PACKED;	/* 04h:  */
-	unsigned char hdlcWindow	PACKED;	/* 06h:  */
-	unsigned char t4		PACKED;	/* 07h:  */
-	unsigned char autoModem		PACKED;	/* 08h:  */
-	unsigned char autoHdlc		PACKED;	/* 09h:  */
-	unsigned char hdlcOptions	PACKED;	/* 0Ah:  */
-	unsigned char station		PACKED;	/* 0Bh:  */
-	unsigned char pktWindow		PACKED;	/* 0Ch:  */
-	unsigned short defPktSize	PACKED;	/* 0Dh:  */
-	unsigned short pktMTU		PACKED;	/* 0Fh:  */
-	unsigned short loPVC		PACKED;	/* 11h:  */
-	unsigned short hiPVC		PACKED;	/* 13h:  */
-	unsigned short loIncommingSVC	PACKED;	/* 15h:  */
-	unsigned short hiIncommingSVC	PACKED;	/* 17h:  */
-	unsigned short loTwoWaySVC	PACKED;	/* 19h:  */
-	unsigned short hiTwoWaySVC	PACKED;	/* 1Bh:  */
-	unsigned short loOutgoingSVC	PACKED;	/* 1Dh:  */
-	unsigned short hiOutgoingSVC	PACKED;	/* 1Fh:  */
-	unsigned short options		PACKED;	/* 21h:  */
-	unsigned char responseOpt	PACKED;	/* 23h:  */
-	unsigned short facil1		PACKED;	/* 24h:  */
-	unsigned short facil2		PACKED;	/* 26h:  */
-	unsigned short ccittFacil	PACKED;	/* 28h:  */
-	unsigned short otherFacil	PACKED;	/* 2Ah:  */
-	unsigned short ccittCompat	PACKED;	/* 2Ch:  */
-	unsigned char t10t20		PACKED;	/* 2Eh:  */
-	unsigned char t11t21		PACKED;	/* 2Fh:  */
-	unsigned char t12t22		PACKED;	/* 30h:  */
-	unsigned char t13t23		PACKED;	/* 31h:  */
-	unsigned char t16t26		PACKED;	/* 32H:  */
-	unsigned char t28		PACKED;	/* 33h:  */
-	unsigned char r10r20		PACKED;	/* 34h:  */
-	unsigned char r12r22		PACKED;	/* 35h:  */
-	unsigned char r13r23		PACKED;	/* 36h:  */
-} TX25Config;
-
-/* ---------------------------------------------------------------------------
- * X25_READ_CHANNEL_CONFIG Command.
- */
-typedef struct X25ChanAlloc			/*----- Channel allocation -*/
-{
-	unsigned short loPVC		PACKED;	/* 00h: lowest PVC number */
-	unsigned short hiPVC		PACKED;	/* 02h: highest PVC number */
-	unsigned short loIncommingSVC	PACKED;	/* 04h: lowest incoming SVC */
-	unsigned short hiIncommingSVC	PACKED;	/* 06h: highest incoming SVC */
-	unsigned short loTwoWaySVC	PACKED;	/* 08h: lowest two-way SVC */
-	unsigned short hiTwoWaySVC	PACKED;	/* 0Ah: highest two-way SVC */
-	unsigned short loOutgoingSVC	PACKED;	/* 0Ch: lowest outgoing SVC */
-	unsigned short hiOutgoingSVC	PACKED;	/* 0Eh: highest outgoing SVC */
-} TX25ChanAlloc;
-
-typedef struct X25ChanCfg		/*------ Channel configuration -----*/
-{
-	unsigned char type	PACKED;	/* 00h: channel type */
-	unsigned char txConf	PACKED;	/* 01h: Tx packet and window sizes */
-	unsigned char rxConf	PACKED;	/* 01h: Rx packet and window sizes */
-} TX25ChanCfg;
-
-/*
- * Defines for the 'type' field.
- */
-#define	X25_PVC  	0x01	/* PVC */
-#define	X25_SVC_IN	0x03	/* Incoming SVC */
-#define	X25_SVC_TWOWAY	0x07	/* Two-way SVC */
-#define	X25_SVC_OUT	0x0B	/* Outgoing SVC */
-
-/*----------------------------------------------------------------------------
- * X25_READ_STATISTICS Command.
- */
-typedef struct X25Stats
-{						/* number of packets Tx/Rx'ed */
-	unsigned short txRestartRqst	PACKED;	/* 00h: Restart Request */
-	unsigned short rxRestartRqst	PACKED;	/* 02h: Restart Request */
-	unsigned short txRestartConf	PACKED;	/* 04h: Restart Confirmation */
-	unsigned short rxRestartConf	PACKED;	/* 06h: Restart Confirmation */
-	unsigned short txResetRqst	PACKED;	/* 08h: Reset Request */
-	unsigned short rxResetRqst	PACKED;	/* 0Ah: Reset Request */
-	unsigned short txResetConf	PACKED;	/* 0Ch: Reset Confirmation */
-	unsigned short rxResetConf	PACKED;	/* 0Eh: Reset Confirmation */
-	unsigned short txCallRequest	PACKED;	/* 10h: Call Request */
-	unsigned short rxCallRequest	PACKED;	/* 12h: Call Request */
-	unsigned short txCallAccept	PACKED;	/* 14h: Call Accept */
-	unsigned short rxCallAccept	PACKED;	/* 16h: Call Accept */
-	unsigned short txClearRqst	PACKED;	/* 18h: Clear Request */
-	unsigned short rxClearRqst	PACKED;	/* 1Ah: Clear Request */
-	unsigned short txClearConf	PACKED;	/* 1Ch: Clear Confirmation */
-	unsigned short rxClearConf	PACKED;	/* 1Eh: Clear Confirmation */
-	unsigned short txDiagnostic	PACKED;	/* 20h: Diagnostic */
-	unsigned short rxDiagnostic	PACKED;	/* 22h: Diagnostic */
-	unsigned short txRegRqst	PACKED;	/* 24h: Registration Request */
-	unsigned short rxRegRqst	PACKED;	/* 26h: Registration Request */
-	unsigned short txRegConf	PACKED;	/* 28h: Registration Confirm.*/
-	unsigned short rxRegConf	PACKED;	/* 2Ah: Registration Confirm.*/
-	unsigned short txInterrupt	PACKED;	/* 2Ch: Interrupt */
-	unsigned short rxInterrupt	PACKED;	/* 2Eh: Interrupt */
-	unsigned short txIntrConf	PACKED;	/* 30h: Interrupt Confirm. */
-	unsigned short rxIntrConf	PACKED;	/* 32h: Interrupt Confirm. */
-	unsigned short txData		PACKED;	/* 34h: Data */
-	unsigned short rxData		PACKED;	/* 36h: Data */
-	unsigned short txRR		PACKED;	/* 38h: RR */
-	unsigned short rxRR		PACKED;	/* 3Ah: RR */
-	unsigned short txRNR		PACKED;	/* 3Ch: RNR */
-	unsigned short rxRNR		PACKED;	/* 3Eh: RNR */
-} TX25Stats;
-
-/*----------------------------------------------------------------------------
- * X25_READ_HISTORY_TABLE Command.
- */
-typedef struct X25EventLog
-{
-	unsigned char	type	PACKED;	/* 00h: transaction type */
-	unsigned short	lcn	PACKED;	/* 01h: logical channel num */
-	unsigned char	packet	PACKED;	/* 03h: async packet type */
-	unsigned char	cause	PACKED;	/* 04h: X.25 cause field */
-	unsigned char	diag	PACKED;	/* 05h: X.25 diag field */
-	TX25TimeStamp	ts	PACKED;	/* 06h: time stamp */
-} TX25EventLog;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25LOG_INCOMMING	0x00
-#define X25LOG_APPLICATION 	0x01
-#define X25LOG_AUTOMATIC	0x02
-#define X25LOG_ERROR		0x04
-#define X25LOG_TIMEOUT		0x08
-#define X25LOG_RECOVERY		0x10
-
-/*
- * Defines for the 'packet' field.
- */
-#define X25LOG_CALL_RQST	0x0B
-#define X25LOG_CALL_ACCEPTED	0x0F
-#define X25LOG_CLEAR_RQST	0x13
-#define X25LOG_CLEAR_CONFRM	0x17
-#define X25LOG_RESET_RQST	0x1B
-#define X25LOG_RESET_CONFRM	0x1F
-#define X25LOG_RESTART_RQST	0xFB
-#define X25LOG_RESTART_COMFRM	0xFF
-#define X25LOG_DIAGNOSTIC	0xF1
-#define X25LOG_DTE_REG_RQST	0xF3
-#define X25LOG_DTE_REG_COMFRM	0xF7
-
-/* ---------------------------------------------------------------------------
- * X25_TRACE_CONFIGURE Command.
- */
-typedef struct X25TraceCfg
-{
-	unsigned char flags	PACKED;	/* 00h: trace configuration flags */
-	unsigned char timeout	PACKED;	/* 01h: timeout for trace delay mode*/
-} TX25TraceCfg;
-
-/*
- * Defines for the 'flags' field.
- */
-#define X25_TRC_ENABLE		0x01	/* bit0: '1' - trace enabled */
-#define X25_TRC_TIMESTAMP	0x02	/* bit1: '1' - time stamping enabled*/
-#define X25_TRC_DELAY		0x04	/* bit2: '1' - trace delay enabled */
-#define X25_TRC_DATA		0x08	/* bit3: '1' - trace data packets */
-#define X25_TRC_SUPERVISORY	0x10    /* bit4: '1' - trace suprvisory pkts*/
-#define X25_TRC_ASYNCHRONOUS	0x20	/* bit5: '1' - trace asynch. packets*/
-#define X25_TRC_HDLC		0x40	/* bit6: '1' - trace all packets */
-#define X25_TRC_READ		0x80	/* bit7: '1' - get current config. */
-
-/* ---------------------------------------------------------------------------
- * X25_READ_TRACE_DATA Command.
- */
-typedef struct X25Trace			/*----- Trace data structure -------*/
-{
-	unsigned short length	PACKED;	/* 00h: trace data length */
-	unsigned char type	PACKED;	/* 02h: trace type */
-	unsigned char lost_cnt	PACKED;	/* 03h: N of traces lost */
-	TX25TimeStamp tstamp	PACKED;	/* 04h: mon/date/sec/min/hour */
-	unsigned short millisec	PACKED;	/* 09h: ms time stamp */
-	unsigned char data[0]	PACKED;	/* 0Bh: traced frame */
-} TX25Trace;
-
-/*
- * Defines for the 'type' field.
- */
-#define X25_TRC_TYPE_MASK	0x0F	/* bits 0..3: trace type */
-#define X25_TRC_TYPE_RX_FRAME	0x00	/* received frame trace */
-#define X25_TRC_TYPE_TX_FRAME	0x01	/* transmitted frame */
-#define X25_TRC_TYPE_ERR_FRAME	0x02	/* error frame */
-
-#define X25_TRC_ERROR_MASK	0xF0	/* bits 4..7: error code */
-#define X25_TRCERR_RX_ABORT	0x10	/* receive abort error */
-#define X25_TRCERR_RX_BADCRC	0x20	/* receive CRC error */
-#define X25_TRCERR_RX_OVERRUN	0x30	/* receiver overrun error */
-#define X25_TRCERR_RX_TOO_LONG	0x40	/* excessive frame length error */
-#define X25_TRCERR_TX_ABORT	0x70	/* aborted frame transmittion error */
-#define X25_TRCERR_TX_UNDERRUN	0x80	/* transmit underrun error */
-
-/*****************************************************************************
- * Following definitions describe HDLC frame and X.25 packet formats.
- ****************************************************************************/
-
-typedef struct HDLCFrame		/*----- DHLC Frame Format ----------*/
-{
-	unsigned char addr	PACKED;	/* address field */
-	unsigned char cntl	PACKED;	/* control field */
-	unsigned char data[0]	PACKED;
-} THDLCFrame;
-
-typedef struct X25Pkt			/*----- X.25 Paket Format ----------*/
-{
-	unsigned char lcn_hi	PACKED;	/* 4 MSB of Logical Channel Number */
-	unsigned char lcn_lo	PACKED;	/* 8 LSB of Logical Channel Number */
-	unsigned char type	PACKED;
-	unsigned char data[0]	PACKED;
-} TX25Pkt;
-
-/*
- * Defines for the 'lcn_hi' field.
- */
-#define	X25_Q_BIT_MASK		0x80	/* Data Qualifier Bit mask */
-#define	X25_D_BIT_MASK		0x40	/* Delivery Confirmation Bit mask */
-#define	X25_M_BITS_MASK		0x30	/* Modulo Bits mask */
-#define	X25_LCN_MSB_MASK	0x0F	/* LCN most significant bits mask */
-
-/*
- * Defines for the 'type' field.
- */
-#define	X25PKT_DATA		0x01	/* Data packet mask */
-#define	X25PKT_SUPERVISORY	0x02	/* Supervisory packet mask */
-#define	X25PKT_CALL_RQST	0x0B	/* Call Request/Incoming */
-#define	X25PKT_CALL_ACCEPTED	0x0F	/* Call Accepted/Connected */
-#define	X25PKT_CLEAR_RQST	0x13	/* Clear Request/Indication */
-#define	X25PKT_CLEAR_CONFRM	0x17	/* Clear Confirmation */
-#define	X25PKT_RESET_RQST	0x1B	/* Reset Request/Indication */
-#define	X25PKT_RESET_CONFRM	0x1F	/* Reset Confirmation */
-#define	X25PKT_RESTART_RQST	0xFB	/* Restart Request/Indication */
-#define	X25PKT_RESTART_CONFRM	0xFF	/* Restart Confirmation */
-#define	X25PKT_INTERRUPT	0x23	/* Interrupt */
-#define	X25PKT_INTERRUPT_CONFRM	0x27	/* Interrupt Confirmation */
-#define	X25PKT_DIAGNOSTIC	0xF1	/* Diagnostic */
-#define	X25PKT_REGISTR_RQST	0xF3	/* Registration Request */
-#define	X25PKT_REGISTR_CONFRM	0xF7	/* Registration Confirmation */
-#define	X25PKT_RR_MASKED	0x01	/* Receive Ready packet after masking */
-#define	X25PKT_RNR_MASKED	0x05	/* Receive Not Ready after masking  */
-
-
-typedef struct {
-	TX25Cmd cmd		PACKED;
-	char data[X25_MAX_DATA]	PACKED;
-} mbox_cmd_t;
-
-
-typedef struct {
-	unsigned char  qdm	PACKED;	/* Q/D/M bits */
-	unsigned char  cause	PACKED;	/* cause field */
-	unsigned char  diagn	PACKED;	/* diagnostics */
-	unsigned char  pktType  PACKED;
-	unsigned short length   PACKED;
-	unsigned char  result	PACKED;
-	unsigned short lcn	PACKED;
-	char reserved[7]	PACKED;
-}x25api_hdr_t;
-
-
-typedef struct {
-	x25api_hdr_t hdr	PACKED;
-	char data[X25_MAX_DATA]	PACKED;
-}x25api_t;
-
-
-/* 
- * XPIPEMON Definitions
- */
-
-/* valid ip_protocol for UDP management */
-#define UDPMGMT_UDP_PROTOCOL 0x11
-#define UDPMGMT_XPIPE_SIGNATURE         "XLINK8ND"
-#define UDPMGMT_DRVRSTATS_SIGNATURE     "DRVSTATS"
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST	0x01
-#define UDPMGMT_REPLY	0x02
-#define UDP_OFFSET	12
-
-
-typedef struct {
-	unsigned char opp_flag  PACKED; /* the opp flag */
-	unsigned char command	PACKED;	/* command code */
-	unsigned short length	PACKED;	/* transfer data length */
-	unsigned char result	PACKED;	/* return code */
-	unsigned char pf	PACKED;	/* P/F bit */
-	unsigned short lcn	PACKED;	/* logical channel */
-	unsigned char qdm	PACKED;	/* Q/D/M bits */
-	unsigned char cause	PACKED;	/* cause field */
-	unsigned char diagn	PACKED;	/* diagnostics */
-	unsigned char pktType	PACKED;	/* packet type */
-	unsigned char resrv[4]	PACKED;	/* reserved */
-} cblock_t;
-
-typedef struct {
-	ip_pkt_t 		ip_pkt		PACKED;
-	udp_pkt_t		udp_pkt		PACKED;
-	wp_mgmt_t 		wp_mgmt       	PACKED;
-        cblock_t                cblock          PACKED;
-        unsigned char           data[4080]      PACKED;
-} x25_udp_pkt_t;
-
-
-typedef struct read_hdlc_stat {
-	unsigned short inf_frames_rx_ok PACKED;
-        unsigned short inf_frames_rx_out_of_seq PACKED;
-	unsigned short inf_frames_rx_no_data PACKED;
-	unsigned short inf_frames_rx_dropped PACKED;
-	unsigned short inf_frames_rx_data_too_long PACKED;
-	unsigned short inf_frames_rx_invalid_addr PACKED;
-	unsigned short inf_frames_tx_ok PACKED;
-        unsigned short inf_frames_tx_retransmit PACKED;
-       	unsigned short T1_timeouts PACKED;
-	unsigned short SABM_frames_rx PACKED;
-	unsigned short DISC_frames_rx PACKED;
-	unsigned short DM_frames_rx PACKED;
-	unsigned short FRMR_frames_rx PACKED;
-	unsigned short SABM_frames_tx PACKED;
-	unsigned short DISC_frames_tx PACKED;
-	unsigned short DM_frames_tx PACKED;
-	unsigned short FRMR_frames_tx PACKED;
-} read_hdlc_stat_t;
-
-typedef struct read_comms_err_stats{
-	unsigned char overrun_err_rx PACKED;
-	unsigned char CRC_err PACKED;
-	unsigned char abort_frames_rx PACKED;
-	unsigned char frames_dropped_buf_full PACKED;
-	unsigned char abort_frames_tx PACKED;
-	unsigned char transmit_underruns PACKED;
-	unsigned char missed_tx_underruns_intr PACKED;
-	unsigned char reserved PACKED;
-	unsigned char DCD_drop PACKED;
-	unsigned char CTS_drop PACKED;
-} read_comms_err_stats_t;
-
-typedef struct trace_data {
-	unsigned short length PACKED;
-	unsigned char  type PACKED;
-	unsigned char  trace_dropped PACKED;
-	unsigned char  reserved[5] PACKED;
-	unsigned short timestamp PACKED;
-        unsigned char  data PACKED;
-} trace_data_t;
-
-enum {UDP_XPIPE_TYPE};
-
-#define XPIPE_ENABLE_TRACING                    0x14
-#define XPIPE_DISABLE_TRACING                   0x14
-#define XPIPE_GET_TRACE_INFO                    0x16
-#define XPIPE_FT1_READ_STATUS                   0x74
-#define XPIPE_DRIVER_STAT_IFSEND                0x75
-#define XPIPE_DRIVER_STAT_INTR                  0x76
-#define XPIPE_DRIVER_STAT_GEN                   0x77
-#define XPIPE_FLUSH_DRIVER_STATS                0x78
-#define XPIPE_ROUTER_UP_TIME                    0x79        
-#define XPIPE_SET_FT1_MODE			0x81
-#define XPIPE_FT1_STATUS_CTRL			0x80
-
-
-/* error messages */
-#define NO_BUFFS_OR_CLOSED_WIN  0x33
-#define DATA_LENGTH_TOO_BIG     0x32
-#define NO_DATA_AVAILABLE       0x33
-#define Z80_TIMEOUT_ERROR       0x0a   
-#define	NO_BUFFS		0x08
-
-
-/* Trace options */
-#define TRACE_DEFAULT		0x03
-#define TRACE_SUPERVISOR_FRMS	0x10
-#define TRACE_ASYNC_FRMS	0x20
-#define TRACE_ALL_HDLC_FRMS	0x40
-#define TRACE_DATA_FRMS		0x08
-
-
-#endif	/* _SDLA_X25_H */
diff --git a/include/linux/sdladrv.h b/include/linux/sdladrv.h
deleted file mode 100644
index c85e103..0000000
--- a/include/linux/sdladrv.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*****************************************************************************
-* sdladrv.h	SDLA Support Module.  Kernel API Definitions.
-*
-* Author: 	Gideon Hack	
-*
-* Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Jun 02, 1999 	Gideon Hack	Added support for the S514 PCI adapter.
-* Dec 11, 1996	Gene Kozin	Complete overhaul.
-* Oct 17, 1996	Gene Kozin	Minor bug fixes.
-* Jun 12, 1996	Gene Kozin 	Added support for S503 card.
-* Dec 06, 1995	Gene Kozin	Initial version.
-*****************************************************************************/
-#ifndef	_SDLADRV_H
-#define	_SDLADRV_H
-
-
-#define	SDLA_MAXIORANGE	4	/* maximum I/O port range */
-#define	SDLA_WINDOWSIZE	0x2000	/* default dual-port memory window size */
-/****** Data Structures *****************************************************/
-
-/*----------------------------------------------------------------------------
- * Adapter hardware configuration. Pointer to this structure is passed to all
- * APIs.
- */
-typedef struct sdlahw
-{
-	unsigned type;			/* adapter type */
-	unsigned fwid;			/* firmware ID */
-	unsigned port;			/* adapter I/O port base */
-	int irq;			/* interrupt request level */
-	char S514_cpu_no[1];		/* PCI CPU Number */
-	unsigned char S514_slot_no;	/* PCI Slot Number */
-	char auto_pci_cfg;		/* Autodetect PCI Slot */
-	struct pci_dev *pci_dev;	/* PCI device */
-	void * dpmbase;			/* dual-port memory base */
-	unsigned dpmsize;		/* dual-port memory size */
-	unsigned pclk;			/* CPU clock rate, kHz */
-	unsigned long memory;		/* memory size */
-	unsigned long vector;		/* local offset of the DPM window */
-	unsigned io_range;		/* I/O port range */
-	unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */
-	unsigned reserved[5];
-} sdlahw_t;
-
-/****** Function Prototypes *************************************************/
-
-extern int sdla_setup	(sdlahw_t* hw, void* sfm, unsigned len);
-extern int sdla_down	(sdlahw_t* hw);
-extern void S514_intack  (sdlahw_t* hw, u32 int_status);
-extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status);
-extern int sdla_mapmem	(sdlahw_t* hw, unsigned long addr);
-extern int sdla_peek	(sdlahw_t* hw, unsigned long addr, void* buf,
-			 unsigned len);
-extern int sdla_poke	(sdlahw_t* hw, unsigned long addr, void* buf,
-			 unsigned len);
-extern int sdla_exec	(void* opflag);
-
-extern unsigned wanpipe_hw_probe(void);
-
-#endif	/* _SDLADRV_H */
diff --git a/include/linux/sdlapci.h b/include/linux/sdlapci.h
deleted file mode 100644
index 6f7c904..0000000
--- a/include/linux/sdlapci.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*****************************************************************************
-* sdlapci.h	WANPIPE(tm) Multiprotocol WAN Link Driver.
-*		Definitions for the SDLA PCI adapter.
-*
-* Author:	Gideon Hack	<ghack@sangoma.com>
-*
-* Copyright:	(c) 1999-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Jun 02, 1999	Gideon Hack	Initial version.
-*****************************************************************************/
-#ifndef	_SDLAPCI_H
-#define	_SDLAPCI_H
-
-/****** Defines *************************************************************/
-
-/* Definitions for identifying and finding S514 PCI adapters */
-#define V3_VENDOR_ID		0x11B0		/* V3 vendor ID number */
-#define V3_DEVICE_ID  		0x0002		/* V3 device ID number */
-#define SANGOMA_SUBSYS_VENDOR 	0x4753		/* ID for Sangoma */
-#define PCI_DEV_SLOT_MASK	0x1F		/* mask for slot numbering */
-#define PCI_IRQ_NOT_ALLOCATED	0xFF		/* interrupt line for no IRQ */
-
-/* Local PCI register offsets */ 
-#define PCI_VENDOR_ID_WORD	0x00		/* vendor ID */
-#define PCI_IO_BASE_DWORD	0x10		/* IO base */	
-#define PCI_MEM_BASE0_DWORD	0x14		/* memory base - apperture 0 */
-#define PCI_MEM_BASE1_DWORD     0x18		/* memory base - apperture 1 */
-#define PCI_SUBSYS_VENDOR_WORD 	0x2C		/* subsystem vendor ID */
-#define PCI_INT_LINE_BYTE	0x3C		/* interrupt line */
-#define PCI_INT_PIN_BYTE	0x3D		/* interrupt pin */
-#define PCI_MAP0_DWORD		0x40		/* PCI to local bus address 0 */
-#define PCI_MAP1_DWORD          0x44		/* PCI to local bus address 1 */
-#define PCI_INT_STATUS          0x48		/* interrupt status */
-#define PCI_INT_CONFIG		0x4C		/* interrupt configuration */
-  
-/* Local PCI register usage */
-#define PCI_MEMORY_ENABLE	0x00000003	/* enable PCI memory */
-#define PCI_CPU_A_MEM_DISABLE	0x00000002	/* disable CPU A memory */
-#define PCI_CPU_B_MEM_DISABLE  	0x00100002	/* disable CPU B memory */
-#define PCI_ENABLE_IRQ_CPU_A	0x005A0004	/* enable IRQ for CPU A */
-#define PCI_ENABLE_IRQ_CPU_B    0x005A0008	/* enable IRQ for CPU B */
-#define PCI_DISABLE_IRQ_CPU_A   0x00000004	/* disable IRQ for CPU A */
-#define PCI_DISABLE_IRQ_CPU_B   0x00000008	/* disable IRQ for CPU B */
- 
-/* Setting for the Interrupt Status register */  
-#define IRQ_CPU_A               0x04            /* IRQ for CPU A */
-#define IRQ_CPU_B               0x08		/* IRQ for CPU B */
-
-/* The maximum size of the S514 memory */
-#define MAX_SIZEOF_S514_MEMORY	(256 * 1024)
-
-/* S514 control register offsets within the memory address space */
-#define S514_CTRL_REG_BYTE	0x80000
- 
-/* S514 adapter control bytes */
-#define S514_CPU_HALT 		0x00
-#define S514_CPU_START		0x01
-
-/* The maximum number of S514 adapters supported */
-#define MAX_S514_CARDS		20	
-
-#define PCI_CARD_TYPE		0x2E
-#define S514_DUAL_CPU		0x12
-#define S514_SINGLE_CPU		0x11
-
-#endif	/* _SDLAPCI_H */
-
diff --git a/include/linux/sdlasfm.h b/include/linux/sdlasfm.h
deleted file mode 100644
index 94aaa8a..0000000
--- a/include/linux/sdlasfm.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*****************************************************************************
-* sdlasfm.h	WANPIPE(tm) Multiprotocol WAN Link Driver.
-*		Definitions for the SDLA Firmware Module (SFM).
-*
-* Author: 	Gideon Hack 	
-*
-* Copyright:	(c) 1995-1999 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Jun 02, 1999  Gideon Hack	Added support for the S514 adapter.
-* Dec 11, 1996	Gene Kozin	Cosmetic changes
-* Apr 16, 1996	Gene Kozin	Changed adapter & firmware IDs. Version 2
-* Dec 15, 1995	Gene Kozin	Structures chaned
-* Nov 09, 1995	Gene Kozin	Initial version.
-*****************************************************************************/
-#ifndef	_SDLASFM_H
-#define	_SDLASFM_H
-
-/****** Defines *************************************************************/
-
-#define	SFM_VERSION	2
-#define	SFM_SIGNATURE	"SFM - Sangoma SDLA Firmware Module"
-
-/* min/max */
-#define	SFM_IMAGE_SIZE	0x8000	/* max size of SDLA code image file */
-#define	SFM_DESCR_LEN	256	/* max length of description string */
-#define	SFM_MAX_SDLA	16	/* max number of compatible adapters */
-
-/* Adapter types */
-#define SDLA_S502A	5020
-#define SDLA_S502E	5021
-#define SDLA_S503	5030
-#define SDLA_S508	5080
-#define SDLA_S507	5070
-#define SDLA_S509	5090
-#define SDLA_S514	5140
-
-/* S514 PCI adapter CPU numbers */
-#define S514_CPU_A	'A'
-#define S514_CPU_B	'B'
-
-
-/* Firmware identification numbers:
- *    0  ..  999	Test & Diagnostics
- *  1000 .. 1999	Streaming HDLC
- *  2000 .. 2999	Bisync
- *  3000 .. 3999	SDLC
- *  4000 .. 4999	HDLC
- *  5000 .. 5999	X.25
- *  6000 .. 6999	Frame Relay
- *  7000 .. 7999	PPP
- *  8000 .. 8999        Cisco HDLC
- */
-#define	SFID_CALIB502	 200
-#define	SFID_STRM502	1200
-#define	SFID_STRM508	1800
-#define	SFID_BSC502	2200
-#define	SFID_SDLC502	3200
-#define	SFID_HDLC502	4200
-#define	SFID_HDLC508	4800
-#define	SFID_X25_502	5200
-#define	SFID_X25_508	5800
-#define	SFID_FR502	6200
-#define	SFID_FR508	6800
-#define	SFID_PPP502	7200
-#define	SFID_PPP508	7800
-#define SFID_PPP514	7140
-#define	SFID_CHDLC508	8800
-#define SFID_CHDLC514	8140
-
-/****** Data Types **********************************************************/
-
-typedef struct	sfm_info		/* firmware module information */
-{
-	unsigned short	codeid;		/* firmware ID */
-	unsigned short	version;	/* firmaware version number */
-	unsigned short	adapter[SFM_MAX_SDLA]; /* compatible adapter types */
-	unsigned long	memsize;	/* minimum memory size */
-	unsigned short	reserved[2];	/* reserved */
-	unsigned short	startoffs;	/* entry point offset */
-	unsigned short	winoffs;	/* dual-port memory window offset */
-	unsigned short	codeoffs;	/* code load offset */
-	unsigned short	codesize;	/* code size */
-	unsigned short	dataoffs;	/* configuration data load offset */
-	unsigned short	datasize;	/* configuration data size */
-} sfm_info_t;
-
-typedef struct sfm			/* SDLA firmware file structire */
-{
-	char		signature[80];	/* SFM file signature */
-	unsigned short	version;	/* file format version */
-	unsigned short	checksum;	/* info + image */
-	unsigned short	reserved[6];	/* reserved */
-	char		descr[SFM_DESCR_LEN]; /* description string */
-	sfm_info_t	info;		/* firmware module info */
-	unsigned char	image[1];	/* code image (variable size) */
-} sfm_t;
-
-#endif	/* _SDLASFM_H */
-
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index fca9b0f..5a09557 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -73,7 +73,7 @@
 }
 
 /* Start of read calculation -- fetch last complete writer token */
-static inline unsigned read_seqbegin(const seqlock_t *sl)
+static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
 {
 	unsigned ret = sl->sequence;
 	smp_rmb();
@@ -88,7 +88,7 @@
  *    
  * Using xor saves one conditional branch.
  */
-static inline int read_seqretry(const seqlock_t *sl, unsigned iv)
+static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv)
 {
 	smp_rmb();
 	return (iv & 1) | (sl->sequence ^ iv);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 162a8fd..70739f5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -14,10 +14,12 @@
  *
  * SA_INTERRUPT is also used by the irq handling routines.
  * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ * SA_PROBEIRQ is set by callers when they expect sharing mismatches to occur
  */
-#define SA_PROBE		SA_ONESHOT
 #define SA_SAMPLE_RANDOM	SA_RESTART
 #define SA_SHIRQ		0x04000000
+#define SA_PROBEIRQ		0x08000000
+
 /*
  * As above, these correspond to the IORESOURCE_IRQ_* defines in
  * linux/ioport.h to select the interrupt line behaviour.  When
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c4619a4..f8f2347 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -344,6 +344,13 @@
 				     void *here);
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
+extern void	      skb_truesize_bug(struct sk_buff *skb);
+
+static inline void skb_truesize_check(struct sk_buff *skb)
+{
+	if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+		skb_truesize_bug(skb);
+}
 
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			int getfrag(void *from, char *to, int offset,
diff --git a/include/linux/string.h b/include/linux/string.h
index dee2214..c61306d 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -13,11 +13,6 @@
 extern "C" {
 #endif
 
-extern char * strpbrk(const char *,const char *);
-extern char * strsep(char **,const char *);
-extern __kernel_size_t strspn(const char *,const char *);
-extern __kernel_size_t strcspn(const char *,const char *);
-
 extern char *strndup_user(const char __user *, long);
 
 /*
@@ -70,6 +65,18 @@
 #ifndef __HAVE_ARCH_STRNLEN
 extern __kernel_size_t strnlen(const char *,__kernel_size_t);
 #endif
+#ifndef __HAVE_ARCH_STRPBRK
+extern char * strpbrk(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSEP
+extern char * strsep(char **,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRSPN
+extern __kernel_size_t strspn(const char *,const char *);
+#endif
+#ifndef __HAVE_ARCH_STRCSPN
+extern __kernel_size_t strcspn(const char *,const char *);
+#endif
 
 #ifndef __HAVE_ARCH_MEMSET
 extern void * memset(void *,int,__kernel_size_t);
diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h
index 8f96e9d..77f78e5 100644
--- a/include/linux/sunrpc/metrics.h
+++ b/include/linux/sunrpc/metrics.h
@@ -69,9 +69,21 @@
 /*
  * EXPORTed functions for managing rpc_iostats structures
  */
+
+#ifdef CONFIG_PROC_FS
+
 struct rpc_iostats *	rpc_alloc_iostats(struct rpc_clnt *);
 void			rpc_count_iostats(struct rpc_task *);
 void			rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 void			rpc_free_iostats(struct rpc_iostats *);
 
+#else  /*  CONFIG_PROC_FS  */
+
+static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
+static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
+
+#endif  /*  CONFIG_PROC_FS  */
+
 #endif /* _LINUX_SUNRPC_METRICS_H */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 50cab2a..5035643 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -197,15 +197,16 @@
 	return rqstp->rq_respages[rqstp->rq_resused++];
 }
 
-static inline int svc_take_page(struct svc_rqst *rqstp)
+static inline void svc_take_page(struct svc_rqst *rqstp)
 {
-	if (rqstp->rq_arghi <= rqstp->rq_argused)
-		return -ENOMEM;
+	if (rqstp->rq_arghi <= rqstp->rq_argused) {
+		WARN_ON(1);
+		return;
+	}
 	rqstp->rq_arghi--;
 	rqstp->rq_respages[rqstp->rq_resused] =
 		rqstp->rq_argpages[rqstp->rq_arghi];
 	rqstp->rq_resused++;
-	return 0;
 }
 
 static inline void svc_pushback_allpages(struct svc_rqst *rqstp)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 7eebbab..e8bbe81 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -53,6 +53,7 @@
 
 struct rpc_task;
 struct rpc_xprt;
+struct seq_file;
 
 /*
  * This describes a complete RPC request
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 54eac8a..5b1fdf1 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -155,6 +155,7 @@
 /* linux/mm/page_alloc.c */
 extern unsigned long totalram_pages;
 extern unsigned long totalhigh_pages;
+extern unsigned long totalreserve_pages;
 extern long nr_swap_pages;
 extern unsigned int nr_free_pages(void);
 extern unsigned int nr_free_pages_pgdat(pg_data_t *pgdat);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5717147..3996960 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -569,9 +569,17 @@
 asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
 				   int flags, int mode);
 asmlinkage long sys_unshare(unsigned long unshare_flags);
-asmlinkage long sys_splice(int fdin, int fdout, size_t len,
-				unsigned int flags);
+
+asmlinkage long sys_splice(int fd_in, loff_t __user *off_in,
+			   int fd_out, loff_t __user *off_out,
+			   size_t len, unsigned int flags);
+
+asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags);
+
+asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags);
+
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
-					int flags);
+					unsigned int flags);
 
 #endif
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 392da5a..1ea5d3c 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -74,6 +74,7 @@
 	umode_t			s_mode;
 	struct dentry		* s_dentry;
 	struct iattr		* s_iattr;
+	atomic_t		s_event;
 };
 
 #define SYSFS_ROOT		0x0001
@@ -117,6 +118,7 @@
 
 int sysfs_create_group(struct kobject *, const struct attribute_group *);
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
+void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
 #else /* CONFIG_SYSFS */
 
@@ -185,6 +187,10 @@
 	;
 }
 
+static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
+{
+}
+
 #endif /* CONFIG_SYSFS */
 
 #endif /* _SYSFS_H_ */
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 0976a16..3154830 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -6,9 +6,10 @@
 extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size);
 extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
 extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
+void tty_schedule_flip(struct tty_struct *tty);
 
 static inline int tty_insert_flip_char(struct tty_struct *tty,
-				       unsigned char ch, char flag)
+					unsigned char ch, char flag)
 {
 	struct tty_buffer *tb = tty->buf.tail;
 	if (tb && tb->active && tb->used < tb->size) {
@@ -19,26 +20,4 @@
 	return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
 }
 
-static inline void tty_schedule_flip(struct tty_struct *tty)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&tty->buf.lock, flags);
-	if (tty->buf.tail != NULL) {
-		tty->buf.tail->active = 0;
-		tty->buf.tail->commit = tty->buf.tail->used;
-	}
-	spin_unlock_irqrestore(&tty->buf.lock, flags);
-	schedule_delayed_work(&tty->buf.work, 1);
-}
-
-#undef _INLINE_
-
-
 #endif /* _LINUX_TTY_FLIP_H */
-
-
-
-
-
-
-
diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
new file mode 100644
index 0000000..c602f88
--- /dev/null
+++ b/include/linux/usb/net2280.h
@@ -0,0 +1,444 @@
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+#ifndef __LINUX_USB_NET2280_H
+#define __LINUX_USB_NET2280_H
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* NET2280 MEMORY MAPPED REGISTERS
+ *
+ * The register layout came from the chip documentation, and the bit
+ * number definitions were extracted from chip specification.
+ *
+ * Use the shift operator ('<<') to build bit masks, with readl/writel
+ * to access the registers through PCI.
+ */
+
+/* main registers, BAR0 + 0x0000 */
+struct net2280_regs {
+	// offset 0x0000
+	u32		devinit;
+#define     LOCAL_CLOCK_FREQUENCY                               8
+#define     FORCE_PCI_RESET                                     7
+#define     PCI_ID                                              6
+#define     PCI_ENABLE                                          5
+#define     FIFO_SOFT_RESET                                     4
+#define     CFG_SOFT_RESET                                      3
+#define     PCI_SOFT_RESET                                      2
+#define     USB_SOFT_RESET                                      1
+#define     M8051_RESET                                         0
+	u32		eectl;
+#define     EEPROM_ADDRESS_WIDTH                                23
+#define     EEPROM_CHIP_SELECT_ACTIVE                           22
+#define     EEPROM_PRESENT                                      21
+#define     EEPROM_VALID                                        20
+#define     EEPROM_BUSY                                         19
+#define     EEPROM_CHIP_SELECT_ENABLE                           18
+#define     EEPROM_BYTE_READ_START                              17
+#define     EEPROM_BYTE_WRITE_START                             16
+#define     EEPROM_READ_DATA                                    8
+#define     EEPROM_WRITE_DATA                                   0
+	u32		eeclkfreq;
+	u32		_unused0;
+	// offset 0x0010
+
+	u32		pciirqenb0;		/* interrupt PCI master ... */
+#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
+#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
+#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
+#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
+#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
+#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
+#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
+#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
+	u32		pciirqenb1;
+#define     PCI_INTERRUPT_ENABLE                                31
+#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+#define     PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE          18
+#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+#define     GPIO_INTERRUPT_ENABLE                               13
+#define     DMA_D_INTERRUPT_ENABLE                              12
+#define     DMA_C_INTERRUPT_ENABLE                              11
+#define     DMA_B_INTERRUPT_ENABLE                              10
+#define     DMA_A_INTERRUPT_ENABLE                              9
+#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+#define     VBUS_INTERRUPT_ENABLE                               7
+#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+#define     RESUME_INTERRUPT_ENABLE                             1
+#define     SOF_INTERRUPT_ENABLE                                0
+	u32		cpu_irqenb0;		/* ... or onboard 8051 */
+#define     SETUP_PACKET_INTERRUPT_ENABLE                       7
+#define     ENDPOINT_F_INTERRUPT_ENABLE                         6
+#define     ENDPOINT_E_INTERRUPT_ENABLE                         5
+#define     ENDPOINT_D_INTERRUPT_ENABLE                         4
+#define     ENDPOINT_C_INTERRUPT_ENABLE                         3
+#define     ENDPOINT_B_INTERRUPT_ENABLE                         2
+#define     ENDPOINT_A_INTERRUPT_ENABLE                         1
+#define     ENDPOINT_0_INTERRUPT_ENABLE                         0
+	u32		cpu_irqenb1;
+#define     CPU_INTERRUPT_ENABLE                                31
+#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+#define     PCI_INTA_INTERRUPT_ENABLE                           24
+#define     PCI_PME_INTERRUPT_ENABLE                            23
+#define     PCI_SERR_INTERRUPT_ENABLE                           22
+#define     PCI_PERR_INTERRUPT_ENABLE                           21
+#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+#define     GPIO_INTERRUPT_ENABLE                               13
+#define     DMA_D_INTERRUPT_ENABLE                              12
+#define     DMA_C_INTERRUPT_ENABLE                              11
+#define     DMA_B_INTERRUPT_ENABLE                              10
+#define     DMA_A_INTERRUPT_ENABLE                              9
+#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+#define     VBUS_INTERRUPT_ENABLE                               7
+#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+#define     RESUME_INTERRUPT_ENABLE                             1
+#define     SOF_INTERRUPT_ENABLE                                0
+
+	// offset 0x0020
+	u32		_unused1;
+	u32		usbirqenb1;
+#define     USB_INTERRUPT_ENABLE                                31
+#define     POWER_STATE_CHANGE_INTERRUPT_ENABLE                 27
+#define     PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE                26
+#define     PCI_PARITY_ERROR_INTERRUPT_ENABLE                   25
+#define     PCI_INTA_INTERRUPT_ENABLE                           24
+#define     PCI_PME_INTERRUPT_ENABLE                            23
+#define     PCI_SERR_INTERRUPT_ENABLE                           22
+#define     PCI_PERR_INTERRUPT_ENABLE                           21
+#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE          20
+#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE          19
+#define     PCI_RETRY_ABORT_INTERRUPT_ENABLE                    17
+#define     PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE              16
+#define     GPIO_INTERRUPT_ENABLE                               13
+#define     DMA_D_INTERRUPT_ENABLE                              12
+#define     DMA_C_INTERRUPT_ENABLE                              11
+#define     DMA_B_INTERRUPT_ENABLE                              10
+#define     DMA_A_INTERRUPT_ENABLE                              9
+#define     EEPROM_DONE_INTERRUPT_ENABLE                        8
+#define     VBUS_INTERRUPT_ENABLE                               7
+#define     CONTROL_STATUS_INTERRUPT_ENABLE                     6
+#define     ROOT_PORT_RESET_INTERRUPT_ENABLE                    4
+#define     SUSPEND_REQUEST_INTERRUPT_ENABLE                    3
+#define     SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE             2
+#define     RESUME_INTERRUPT_ENABLE                             1
+#define     SOF_INTERRUPT_ENABLE                                0
+	u32		irqstat0;
+#define     INTA_ASSERTED                                       12
+#define     SETUP_PACKET_INTERRUPT                              7
+#define     ENDPOINT_F_INTERRUPT                                6
+#define     ENDPOINT_E_INTERRUPT                                5
+#define     ENDPOINT_D_INTERRUPT                                4
+#define     ENDPOINT_C_INTERRUPT                                3
+#define     ENDPOINT_B_INTERRUPT                                2
+#define     ENDPOINT_A_INTERRUPT                                1
+#define     ENDPOINT_0_INTERRUPT                                0
+	u32		irqstat1;
+#define     POWER_STATE_CHANGE_INTERRUPT                        27
+#define     PCI_ARBITER_TIMEOUT_INTERRUPT                       26
+#define     PCI_PARITY_ERROR_INTERRUPT                          25
+#define     PCI_INTA_INTERRUPT                                  24
+#define     PCI_PME_INTERRUPT                                   23
+#define     PCI_SERR_INTERRUPT                                  22
+#define     PCI_PERR_INTERRUPT                                  21
+#define     PCI_MASTER_ABORT_RECEIVED_INTERRUPT                 20
+#define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
+#define     PCI_RETRY_ABORT_INTERRUPT                           17
+#define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
+#define     SOF_DOWN_INTERRUPT                                  14
+#define     GPIO_INTERRUPT                                      13
+#define     DMA_D_INTERRUPT                                     12
+#define     DMA_C_INTERRUPT                                     11
+#define     DMA_B_INTERRUPT                                     10
+#define     DMA_A_INTERRUPT                                     9
+#define     EEPROM_DONE_INTERRUPT                               8
+#define     VBUS_INTERRUPT                                      7
+#define     CONTROL_STATUS_INTERRUPT                            6
+#define     ROOT_PORT_RESET_INTERRUPT                           4
+#define     SUSPEND_REQUEST_INTERRUPT                           3
+#define     SUSPEND_REQUEST_CHANGE_INTERRUPT                    2
+#define     RESUME_INTERRUPT                                    1
+#define     SOF_INTERRUPT                                       0
+	// offset 0x0030
+	u32		idxaddr;
+	u32		idxdata;
+	u32		fifoctl;
+#define     PCI_BASE2_RANGE                                     16
+#define     IGNORE_FIFO_AVAILABILITY                            3
+#define     PCI_BASE2_SELECT                                    2
+#define     FIFO_CONFIGURATION_SELECT                           0
+	u32		_unused2;
+	// offset 0x0040
+	u32		memaddr;
+#define     START                                               28
+#define     DIRECTION                                           27
+#define     FIFO_DIAGNOSTIC_SELECT                              24
+#define     MEMORY_ADDRESS                                      0
+	u32		memdata0;
+	u32		memdata1;
+	u32		_unused3;
+	// offset 0x0050
+	u32		gpioctl;
+#define     GPIO3_LED_SELECT                                    12
+#define     GPIO3_INTERRUPT_ENABLE                              11
+#define     GPIO2_INTERRUPT_ENABLE                              10
+#define     GPIO1_INTERRUPT_ENABLE                              9
+#define     GPIO0_INTERRUPT_ENABLE                              8
+#define     GPIO3_OUTPUT_ENABLE                                 7
+#define     GPIO2_OUTPUT_ENABLE                                 6
+#define     GPIO1_OUTPUT_ENABLE                                 5
+#define     GPIO0_OUTPUT_ENABLE                                 4
+#define     GPIO3_DATA                                          3
+#define     GPIO2_DATA                                          2
+#define     GPIO1_DATA                                          1
+#define     GPIO0_DATA                                          0
+	u32		gpiostat;
+#define     GPIO3_INTERRUPT                                     3
+#define     GPIO2_INTERRUPT                                     2
+#define     GPIO1_INTERRUPT                                     1
+#define     GPIO0_INTERRUPT                                     0
+} __attribute__ ((packed));
+
+/* usb control, BAR0 + 0x0080 */
+struct net2280_usb_regs {
+	// offset 0x0080
+	u32		stdrsp;
+#define     STALL_UNSUPPORTED_REQUESTS                          31
+#define     SET_TEST_MODE                                       16
+#define     GET_OTHER_SPEED_CONFIGURATION                       15
+#define     GET_DEVICE_QUALIFIER                                14
+#define     SET_ADDRESS                                         13
+#define     ENDPOINT_SET_CLEAR_HALT                             12
+#define     DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP               11
+#define     GET_STRING_DESCRIPTOR_2                             10
+#define     GET_STRING_DESCRIPTOR_1                             9
+#define     GET_STRING_DESCRIPTOR_0                             8
+#define     GET_SET_INTERFACE                                   6
+#define     GET_SET_CONFIGURATION                               5
+#define     GET_CONFIGURATION_DESCRIPTOR                        4
+#define     GET_DEVICE_DESCRIPTOR                               3
+#define     GET_ENDPOINT_STATUS                                 2
+#define     GET_INTERFACE_STATUS                                1
+#define     GET_DEVICE_STATUS                                   0
+	u32		prodvendid;
+#define     PRODUCT_ID                                          16
+#define     VENDOR_ID                                           0
+	u32		relnum;
+	u32		usbctl;
+#define     SERIAL_NUMBER_INDEX                                 16
+#define     PRODUCT_ID_STRING_ENABLE                            13
+#define     VENDOR_ID_STRING_ENABLE                             12
+#define     USB_ROOT_PORT_WAKEUP_ENABLE                         11
+#define     VBUS_PIN                                            10
+#define     TIMED_DISCONNECT                                    9
+#define     SUSPEND_IMMEDIATELY                                 7
+#define     SELF_POWERED_USB_DEVICE                             6
+#define     REMOTE_WAKEUP_SUPPORT                               5
+#define     PME_POLARITY                                        4
+#define     USB_DETECT_ENABLE                                   3
+#define     PME_WAKEUP_ENABLE                                   2
+#define     DEVICE_REMOTE_WAKEUP_ENABLE                         1
+#define     SELF_POWERED_STATUS                                 0
+	// offset 0x0090
+	u32		usbstat;
+#define     HIGH_SPEED                                          7
+#define     FULL_SPEED                                          6
+#define     GENERATE_RESUME                                     5
+#define     GENERATE_DEVICE_REMOTE_WAKEUP                       4
+	u32		xcvrdiag;
+#define     FORCE_HIGH_SPEED_MODE                               31
+#define     FORCE_FULL_SPEED_MODE                               30
+#define     USB_TEST_MODE                                       24
+#define     LINE_STATE                                          16
+#define     TRANSCEIVER_OPERATION_MODE                          2
+#define     TRANSCEIVER_SELECT                                  1
+#define     TERMINATION_SELECT                                  0
+	u32		setup0123;
+	u32		setup4567;
+	// offset 0x0090
+	u32		_unused0;
+	u32		ouraddr;
+#define     FORCE_IMMEDIATE                                     7
+#define     OUR_USB_ADDRESS                                     0
+	u32		ourconfig;
+} __attribute__ ((packed));
+
+/* pci control, BAR0 + 0x0100 */
+struct net2280_pci_regs {
+	// offset 0x0100
+	u32		 pcimstctl;
+#define     PCI_ARBITER_PARK_SELECT                             13
+#define     PCI_MULTI LEVEL_ARBITER                             12
+#define     PCI_RETRY_ABORT_ENABLE                              11
+#define     DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE              10
+#define     DMA_READ_MULTIPLE_ENABLE                            9
+#define     DMA_READ_LINE_ENABLE                                8
+#define     PCI_MASTER_COMMAND_SELECT                           6
+#define         MEM_READ_OR_WRITE                                   0
+#define         IO_READ_OR_WRITE                                    1
+#define         CFG_READ_OR_WRITE                                   2
+#define     PCI_MASTER_START                                    5
+#define     PCI_MASTER_READ_WRITE                               4
+#define         PCI_MASTER_WRITE                                    0
+#define         PCI_MASTER_READ                                     1
+#define     PCI_MASTER_BYTE_WRITE_ENABLES                       0
+	u32		 pcimstaddr;
+	u32		 pcimstdata;
+	u32		 pcimststat;
+#define     PCI_ARBITER_CLEAR                                   2
+#define     PCI_EXTERNAL_ARBITER                                1
+#define     PCI_HOST_MODE                                       0
+} __attribute__ ((packed));
+
+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+ * for channels 0..3.  see also struct net2280_dma:  descriptor
+ * that can be loaded into some of these registers.
+ */
+struct net2280_dma_regs {	/* [11.7] */
+	// offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+	u32		dmactl;
+#define     DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE            25
+#define     DMA_CLEAR_COUNT_ENABLE                              21
+#define     DESCRIPTOR_POLLING_RATE                             19
+#define         POLL_CONTINUOUS                                     0
+#define         POLL_1_USEC                                         1
+#define         POLL_100_USEC                                       2
+#define         POLL_1_MSEC                                         3
+#define     DMA_VALID_BIT_POLLING_ENABLE                        18
+#define     DMA_VALID_BIT_ENABLE                                17
+#define     DMA_SCATTER_GATHER_ENABLE                           16
+#define     DMA_OUT_AUTO_START_ENABLE                           4
+#define     DMA_PREEMPT_ENABLE                                  3
+#define     DMA_FIFO_VALIDATE                                   2
+#define     DMA_ENABLE                                          1
+#define     DMA_ADDRESS_HOLD                                    0
+	u32		dmastat;
+#define     DMA_ABORT_DONE_INTERRUPT                            27
+#define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
+#define     DMA_TRANSACTION_DONE_INTERRUPT                      24
+#define     DMA_ABORT                                           1
+#define     DMA_START                                           0
+	u32		_unused0 [2];
+	// offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+	u32		dmacount;
+#define     VALID_BIT                                           31
+#define     DMA_DIRECTION                                       30
+#define     DMA_DONE_INTERRUPT_ENABLE                           29
+#define     END_OF_CHAIN                                        28
+#define         DMA_BYTE_COUNT_MASK                                 ((1<<24)-1)
+#define     DMA_BYTE_COUNT                                      0
+	u32		dmaaddr;
+	u32		dmadesc;
+	u32		_unused1;
+} __attribute__ ((packed));
+
+/* dedicated endpoint registers, BAR0 + 0x0200 */
+
+struct net2280_dep_regs {	/* [11.8] */
+	// offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+	u32		dep_cfg;
+	// offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+	u32		dep_rsp;
+	u32		_unused [2];
+} __attribute__ ((packed));
+
+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+ * like this, for ep0 then the configurable endpoints A..F
+ * ep0 reserved for control; E and F have only 64 bytes of fifo
+ */
+struct net2280_ep_regs {	/* [11.9] */
+	// offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+	u32		ep_cfg;
+#define     ENDPOINT_BYTE_COUNT                                 16
+#define     ENDPOINT_ENABLE                                     10
+#define     ENDPOINT_TYPE                                       8
+#define     ENDPOINT_DIRECTION                                  7
+#define     ENDPOINT_NUMBER                                     0
+	u32		ep_rsp;
+#define     SET_NAK_OUT_PACKETS                                 15
+#define     SET_EP_HIDE_STATUS_PHASE                            14
+#define     SET_EP_FORCE_CRC_ERROR                              13
+#define     SET_INTERRUPT_MODE                                  12
+#define     SET_CONTROL_STATUS_PHASE_HANDSHAKE                  11
+#define     SET_NAK_OUT_PACKETS_MODE                            10
+#define     SET_ENDPOINT_TOGGLE                                 9
+#define     SET_ENDPOINT_HALT                                   8
+#define     CLEAR_NAK_OUT_PACKETS                               7
+#define     CLEAR_EP_HIDE_STATUS_PHASE                          6
+#define     CLEAR_EP_FORCE_CRC_ERROR                            5
+#define     CLEAR_INTERRUPT_MODE                                4
+#define     CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE                3
+#define     CLEAR_NAK_OUT_PACKETS_MODE                          2
+#define     CLEAR_ENDPOINT_TOGGLE                               1
+#define     CLEAR_ENDPOINT_HALT                                 0
+	u32		ep_irqenb;
+#define     SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE              6
+#define     SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE           5
+#define     DATA_PACKET_RECEIVED_INTERRUPT_ENABLE               3
+#define     DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE            2
+#define     DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE                1
+#define     DATA_IN_TOKEN_INTERRUPT_ENABLE                      0
+	u32		ep_stat;
+#define     FIFO_VALID_COUNT                                    24
+#define     HIGH_BANDWIDTH_OUT_TRANSACTION_PID                  22
+#define     TIMEOUT                                             21
+#define     USB_STALL_SENT                                      20
+#define     USB_IN_NAK_SENT                                     19
+#define     USB_IN_ACK_RCVD                                     18
+#define     USB_OUT_PING_NAK_SENT                               17
+#define     USB_OUT_ACK_SENT                                    16
+#define     FIFO_OVERFLOW                                       13
+#define     FIFO_UNDERFLOW                                      12
+#define     FIFO_FULL                                           11
+#define     FIFO_EMPTY                                          10
+#define     FIFO_FLUSH                                          9
+#define     SHORT_PACKET_OUT_DONE_INTERRUPT                     6
+#define     SHORT_PACKET_TRANSFERRED_INTERRUPT                  5
+#define     NAK_OUT_PACKETS                                     4
+#define     DATA_PACKET_RECEIVED_INTERRUPT                      3
+#define     DATA_PACKET_TRANSMITTED_INTERRUPT                   2
+#define     DATA_OUT_PING_TOKEN_INTERRUPT                       1
+#define     DATA_IN_TOKEN_INTERRUPT                             0
+	// offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+	u32		ep_avail;
+	u32		ep_data;
+	u32		_unused0 [2];
+} __attribute__ ((packed));
+
+#endif /* __LINUX_USB_NET2280_H */
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index fadc535..dc7c621 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -12,6 +12,11 @@
 #else
 #define MODULE_VERMAGIC_PREEMPT ""
 #endif
+#ifdef CONFIG_MODULE_UNLOAD
+#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
+#else
+#define MODULE_VERMAGIC_MODULE_UNLOAD ""
+#endif
 #ifndef MODULE_ARCH_VERMAGIC
 #define MODULE_ARCH_VERMAGIC ""
 #endif
@@ -19,5 +24,5 @@
 #define VERMAGIC_STRING 						\
 	UTS_RELEASE " "							\
 	MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT 			\
-	MODULE_ARCH_VERMAGIC 						\
+	MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC 		\
 	"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index af2d615..d7670ec 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -966,66 +966,17 @@
 
 /* Teletext World System Teletext
    (WST), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_PAL_B      (0x000001)
-#define V4L2_SLICED_TELETEXT_PAL_C      (0x000002)
-#define V4L2_SLICED_TELETEXT_NTSC_B     (0x000010)
-#define V4L2_SLICED_TELETEXT_SECAM      (0x000020)
-
-/* Teletext North American Broadcast Teletext Specification
-   (NABTS), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_NTSC_C     (0x000040)
-#define V4L2_SLICED_TELETEXT_NTSC_D     (0x000080)
-
+#define V4L2_SLICED_TELETEXT_B          (0x0001)
 /* Video Program System, defined on ETS 300 231*/
-#define V4L2_SLICED_VPS                 (0x000400)
-
+#define V4L2_SLICED_VPS                 (0x0400)
 /* Closed Caption, defined on EIA-608 */
-#define V4L2_SLICED_CAPTION_525         (0x001000)
-#define V4L2_SLICED_CAPTION_625         (0x002000)
-
+#define V4L2_SLICED_CAPTION_525         (0x1000)
 /* Wide Screen System, defined on ITU-R BT1119.1 */
-#define V4L2_SLICED_WSS_625             (0x004000)
+#define V4L2_SLICED_WSS_625             (0x4000)
 
-/* Wide Screen System, defined on IEC 61880 */
-#define V4L2_SLICED_WSS_525             (0x008000)
+#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)
 
-/* Vertical Interval Timecode (VITC), defined on SMPTE 12M */
-#define V4l2_SLICED_VITC_625		(0x010000)
-#define V4l2_SLICED_VITC_525		(0x020000)
-
-#define V4L2_SLICED_TELETEXT_B		(V4L2_SLICED_TELETEXT_PAL_B  |\
-					 V4L2_SLICED_TELETEXT_NTSC_B)
-
-#define V4L2_SLICED_TELETEXT		(V4L2_SLICED_TELETEXT_PAL_B  |\
-					 V4L2_SLICED_TELETEXT_PAL_C  |\
-					 V4L2_SLICED_TELETEXT_SECAM  |\
-					 V4L2_SLICED_TELETEXT_NTSC_B |\
-					 V4L2_SLICED_TELETEXT_NTSC_C |\
-					 V4L2_SLICED_TELETEXT_NTSC_D)
-
-#define V4L2_SLICED_CAPTION		(V4L2_SLICED_CAPTION_525     |\
-					 V4L2_SLICED_CAPTION_625)
-
-#define V4L2_SLICED_WSS			(V4L2_SLICED_WSS_525         |\
-					 V4L2_SLICED_WSS_625)
-
-#define V4L2_SLICED_VITC		(V4L2_SLICED_VITC_525        |\
-					 V4L2_SLICED_VITC_625)
-
-#define V4L2_SLICED_VBI_525             (V4L2_SLICED_TELETEXT_NTSC_B |\
-					 V4L2_SLICED_TELETEXT_NTSC_C |\
-					 V4L2_SLICED_TELETEXT_NTSC_D |\
-					 V4L2_SLICED_CAPTION_525     |\
-					 V4L2_SLICED_WSS_525         |\
-					 V4l2_SLICED_VITC_525)
-
-#define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_PAL_B  |\
-					 V4L2_SLICED_TELETEXT_PAL_C  |\
-					 V4L2_SLICED_TELETEXT_SECAM  |\
-					 V4L2_SLICED_VPS             |\
-					 V4L2_SLICED_CAPTION_625     |\
-					 V4L2_SLICED_WSS_625         |\
-					 V4l2_SLICED_VITC_625)
 
 struct v4l2_sliced_vbi_cap
 {
diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h
deleted file mode 100644
index dae9860..0000000
--- a/include/linux/wanpipe.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/*****************************************************************************
-* wanpipe.h	WANPIPE(tm) Multiprotocol WAN Link Driver.
-*		User-level API definitions.
-*
-* Author: 	Nenad Corbic <ncorbic@sangoma.com>
-*		Gideon Hack  	
-*
-* Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
-*
-*		This program is free software; you can redistribute it and/or
-*		modify it under the terms of the GNU General Public License
-*		as published by the Free Software Foundation; either version
-*		2 of the License, or (at your option) any later version.
-* ============================================================================
-* Nov 3,  2000  Nenad Corbic    Added config_id to sdla_t structure.
-*                               Used to determine the protocol running.
-* Jul 13, 2000  Nenad Corbic	Added SyncPPP Support
-* Feb 24, 2000  Nenad Corbic    Added support for x25api driver
-* Oct 04, 1999  Nenad Corbic    New CHDLC and FRAME RELAY code, SMP support
-* Jun 02, 1999  Gideon Hack	Added 'update_call_count' for Cisco HDLC 
-*				support
-* Jun 26, 1998	David Fong	Added 'ip_mode' in sdla_t.u.p for dynamic IP
-*				routing mode configuration
-* Jun 12, 1998	David Fong	Added Cisco HDLC union member in sdla_t
-* Dec 08, 1997	Jaspreet Singh  Added 'authenticator' in union of 'sdla_t' 
-* Nov 26, 1997	Jaspreet Singh	Added 'load_sharing' structure.  Also added 
-*				'devs_struct','dev_to_devtint_next' to 'sdla_t'	
-* Nov 24, 1997	Jaspreet Singh	Added 'irq_dis_if_send_count', 
-*				'irq_dis_poll_count' to 'sdla_t'.
-* Nov 06, 1997	Jaspreet Singh	Added a define called 'INTR_TEST_MODE'
-* Oct 20, 1997	Jaspreet Singh	Added 'buff_intr_mode_unbusy' and 
-*				'dlci_intr_mode_unbusy' to 'sdla_t'
-* Oct 18, 1997	Jaspreet Singh	Added structure to maintain global driver
-*				statistics.
-* Jan 15, 1997	Gene Kozin	Version 3.1.0
-*				 o added UDP management stuff
-* Jan 02, 1997	Gene Kozin	Version 3.0.0
-*****************************************************************************/
-#ifndef	_WANPIPE_H
-#define	_WANPIPE_H
-
-#include <linux/wanrouter.h>
-
-/* Defines */
-
-#ifndef	PACKED
-#define	PACKED	__attribute__((packed))
-#endif
-
-#define	WANPIPE_MAGIC	0x414C4453L	/* signature: 'SDLA' reversed */
-
-/* IOCTL numbers (up to 16) */
-#define	WANPIPE_DUMP	(ROUTER_USER+0)	/* dump adapter's memory */
-#define	WANPIPE_EXEC	(ROUTER_USER+1)	/* execute firmware command */
-
-#define TRACE_ALL                       0x00
-#define TRACE_PROT			0x01
-#define TRACE_DATA			0x02
-
-/* values for request/reply byte */
-#define UDPMGMT_REQUEST	0x01
-#define UDPMGMT_REPLY	0x02
-#define UDP_OFFSET	12
-
-#define MAX_CMD_BUFF 	10
-#define MAX_X25_LCN 	255	/* Maximum number of x25 channels */
-#define MAX_LCN_NUM	4095	/* Maximum lcn number */
-#define MAX_FT1_RETRY 	100
-
-#ifndef AF_WANPIPE
-	#define AF_WANPIPE 25
-	#ifndef PF_WANPIPE
-		#define PF_WANPIPE AF_WANPIPE
-	#endif
-#endif
-
-
-#define TX_TIMEOUT 5*HZ
-
-/* General Critical Flags */
-#define SEND_CRIT	0x00
-#define PERI_CRIT	0x01
-
-/* Chdlc and PPP polling critical flag */
-#define POLL_CRIT	0x03
-
-/* Frame Relay Tx IRQ send critical flag */
-#define SEND_TXIRQ_CRIT 0x02
-
-/* Frame Relay ARP critical flag */
-#define ARP_CRIT	0x03
-
-/* Bit maps for dynamic interface configuration
- * DYN_OPT_ON : turns this option on/off 
- * DEV_DOWN   : device was shutdown by the driver not
- *              by user 
- */
-#define DYN_OPT_ON	0x00
-#define DEV_DOWN	0x01
-
-/*
- * Data structures for IOCTL calls.
- */
-
-typedef struct sdla_dump	/* WANPIPE_DUMP */
-{
-	unsigned long magic;	/* for verification */
-	unsigned long offset;	/* absolute adapter memory address */
-	unsigned long length;	/* block length */
-	void* ptr;		/* -> buffer */
-} sdla_dump_t;
-
-typedef struct sdla_exec	/* WANPIPE_EXEC */
-{
-	unsigned long magic;	/* for verification */
-	void* cmd;		/* -> command structure */
-	void* data;		/* -> data buffer */
-} sdla_exec_t;
-
-/* UDP management stuff */
-
-typedef struct wum_header
-{
-	unsigned char signature[8];	/* 00h: signature */
-	unsigned char type;		/* 08h: request/reply */
-	unsigned char command;		/* 09h: commnand */
-	unsigned char reserved[6];	/* 0Ah: reserved */
-} wum_header_t;
-
-/*************************************************************************
- Data Structure for global statistics
-*************************************************************************/
-
-typedef struct global_stats
-{
-	unsigned long isr_entry;
-	unsigned long isr_already_critical;		
-	unsigned long isr_rx;
-	unsigned long isr_tx;
-	unsigned long isr_intr_test;
-	unsigned long isr_spurious;
-	unsigned long isr_enable_tx_int;
-	unsigned long rx_intr_corrupt_rx_bfr;
-	unsigned long rx_intr_on_orphaned_DLCI;
-	unsigned long rx_intr_dev_not_started;
-	unsigned long tx_intr_dev_not_started;
-	unsigned long poll_entry;
-	unsigned long poll_already_critical;
-	unsigned long poll_processed;
-	unsigned long poll_tbusy_bad_status;
-	unsigned long poll_host_disable_irq;
-	unsigned long poll_host_enable_irq;
-
-} global_stats_t;
-
-
-typedef struct{
-	unsigned short	udp_src_port		PACKED;
-	unsigned short	udp_dst_port		PACKED;
-	unsigned short	udp_length		PACKED;
-	unsigned short	udp_checksum		PACKED;
-} udp_pkt_t;
-
-
-typedef struct {
-	unsigned char	ver_inet_hdr_length	PACKED;
-	unsigned char	service_type		PACKED;
-	unsigned short	total_length		PACKED;
-	unsigned short	identifier		PACKED;
-	unsigned short	flags_frag_offset	PACKED;
-	unsigned char	ttl			PACKED;
-	unsigned char	protocol		PACKED;
-	unsigned short	hdr_checksum		PACKED;
-	unsigned long	ip_src_address		PACKED;
-	unsigned long	ip_dst_address		PACKED;
-} ip_pkt_t;
-
-
-typedef struct {
-        unsigned char           signature[8]    PACKED;
-        unsigned char           request_reply   PACKED;
-        unsigned char           id              PACKED;
-        unsigned char           reserved[6]     PACKED;
-} wp_mgmt_t;
-
-/*************************************************************************
- Data Structure for if_send  statistics
-*************************************************************************/  
-typedef struct if_send_stat{
-	unsigned long if_send_entry;
-	unsigned long if_send_skb_null;
-	unsigned long if_send_broadcast;
-	unsigned long if_send_multicast;
-	unsigned long if_send_critical_ISR;
-	unsigned long if_send_critical_non_ISR;
-	unsigned long if_send_tbusy;
-	unsigned long if_send_tbusy_timeout;
-	unsigned long if_send_PIPE_request;
-	unsigned long if_send_wan_disconnected;
-	unsigned long if_send_dlci_disconnected;
-	unsigned long if_send_no_bfrs;
-	unsigned long if_send_adptr_bfrs_full;
-	unsigned long if_send_bfr_passed_to_adptr;
-	unsigned long if_send_protocol_error;
-       	unsigned long if_send_bfr_not_passed_to_adptr;
-       	unsigned long if_send_tx_int_enabled;
-        unsigned long if_send_consec_send_fail; 
-} if_send_stat_t;
-
-typedef struct rx_intr_stat{
-	unsigned long rx_intr_no_socket;
-	unsigned long rx_intr_dev_not_started;
-	unsigned long rx_intr_PIPE_request;
-	unsigned long rx_intr_bfr_not_passed_to_stack;
-	unsigned long rx_intr_bfr_passed_to_stack;
-} rx_intr_stat_t;	
-
-typedef struct pipe_mgmt_stat{
-	unsigned long UDP_PIPE_mgmt_kmalloc_err;
-	unsigned long UDP_PIPE_mgmt_direction_err;
-	unsigned long UDP_PIPE_mgmt_adptr_type_err;
-	unsigned long UDP_PIPE_mgmt_adptr_cmnd_OK;
-	unsigned long UDP_PIPE_mgmt_adptr_cmnd_timeout;
-	unsigned long UDP_PIPE_mgmt_adptr_send_passed;
-	unsigned long UDP_PIPE_mgmt_adptr_send_failed;
-	unsigned long UDP_PIPE_mgmt_not_passed_to_stack;
-	unsigned long UDP_PIPE_mgmt_passed_to_stack;
-	unsigned long UDP_PIPE_mgmt_no_socket;
-        unsigned long UDP_PIPE_mgmt_passed_to_adptr;
-} pipe_mgmt_stat_t;
-
-
-typedef struct {
-	struct sk_buff *skb;
-} bh_data_t, cmd_data_t;
-
-#define MAX_LGTH_UDP_MGNT_PKT 2000
- 
-
-/* This is used for interrupt testing */
-#define INTR_TEST_MODE	0x02
-
-#define	WUM_SIGNATURE_L	0x50495046
-#define	WUM_SIGNATURE_H	0x444E3845
-
-#define	WUM_KILL	0x50
-#define	WUM_EXEC	0x51
-
-#define WANPIPE		0x00
-#define API		0x01
-#define BRIDGE		0x02
-#define BRIDGE_NODE	0x03
-
-#ifdef	__KERNEL__
-/****** Kernel Interface ****************************************************/
-
-#include <linux/sdladrv.h>	/* SDLA support module API definitions */
-#include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
-#include <linux/workqueue.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-
-/****** Data Structures *****************************************************/
-
-/* Adapter Data Space.
- * This structure is needed because we handle multiple cards, otherwise
- * static data would do it.
- */
-typedef struct sdla
-{
-	char devname[WAN_DRVNAME_SZ+1];	/* card name */
-	sdlahw_t hw;			/* hardware configuration */
-	struct wan_device wandev;	/* WAN device data space */
-	
-	unsigned open_cnt;		/* number of open interfaces */
-	unsigned long state_tick;	/* link state timestamp */
-	unsigned intr_mode;		/* Type of Interrupt Mode */
-	char in_isr;			/* interrupt-in-service flag */
-	char buff_int_mode_unbusy;	/* flag for carrying out dev_tint */  
-	char dlci_int_mode_unbusy;	/* flag for carrying out dev_tint */
-	long configured;		/* flag for previous configurations */
-	
-	unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/
-	unsigned short irq_dis_poll_count;   /* Disabling irqs in poll routine*/
-	unsigned short force_enable_irq;
-	char TracingEnabled;		/* flag for enabling trace */
-	global_stats_t statistics;	/* global statistics */
-	void* mbox;			/* -> mailbox */
-	void* rxmb;			/* -> receive mailbox */
-	void* flags;			/* -> adapter status flags */
-	void (*isr)(struct sdla* card);	/* interrupt service routine */
-	void (*poll)(struct sdla* card); /* polling routine */
-	int (*exec)(struct sdla* card, void* u_cmd, void* u_data);
-					/* Used by the listen() system call */		
-	/* Wanpipe Socket Interface */
-	int   (*func) (struct sk_buff *, struct sock *);
-	struct sock *sk;
-
-	/* Shutdown function */
-	void (*disable_comm) (struct sdla *card);
-
-	/* Secondary Port Device: Piggibacking */
-	struct sdla *next;
-
-	/* TTY driver variables */
-	unsigned char tty_opt;
-	struct tty_struct *tty;
-	unsigned int tty_minor;
-	unsigned int tty_open;
-	unsigned char *tty_buf;
-	unsigned char *tty_rx;
-	struct work_struct tty_work;
-	
-	union
-	{
-		struct
-		{			/****** X.25 specific data **********/
-			u32 lo_pvc;
-			u32 hi_pvc;
-			u32 lo_svc;
-			u32 hi_svc;
-			struct net_device *svc_to_dev_map[MAX_X25_LCN];
-			struct net_device *pvc_to_dev_map[MAX_X25_LCN];
-			struct net_device *tx_dev;
-			struct net_device *cmd_dev;
-			u32 no_dev;
-			volatile u8 *hdlc_buf_status;
-			u32 tx_interrupts_pending;
-                        u16 timer_int_enabled;
-			struct net_device *poll_device;
-			atomic_t command_busy;
-
-			u16 udp_pkt_lgth;
-                        u32 udp_type;
-                        u8  udp_pkt_src;
-			u32 udp_lcn;
-                        struct net_device *udp_dev;
-                        s8 udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-
-		 	u8 LAPB_hdlc;		/* Option to turn off X25 and run only LAPB */
-			u8 logging;		/* Option to log call messages */
-			u8 oob_on_modem;	/* Option to send modem status to the api */
-			u16 num_of_ch;		/* Number of channels configured by the user */
-
-			struct work_struct x25_poll_work;
-			struct timer_list x25_timer;
-		} x;
-		struct
-		{			/****** frame relay specific data ***/
-			void* rxmb_base;	/* -> first Rx buffer */
-			void* rxmb_last;	/* -> last Rx buffer */
-			unsigned rx_base;	/* S508 receive buffer base */
-			unsigned rx_top;	/* S508 receive buffer end */
-			unsigned short node_dlci[100];
-			unsigned short dlci_num;
-                        struct net_device *dlci_to_dev_map[991 + 1];
-                        unsigned tx_interrupts_pending;
-                        unsigned short timer_int_enabled;
-                        unsigned short udp_pkt_lgth;
-                        int udp_type;
-                        char udp_pkt_src;
-                        unsigned udp_dlci;
-                        char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
-                        void* trc_el_base;      		/* first trace element */
-                        void* trc_el_last;      		/* last trace element */
-                        void *curr_trc_el;      		/* current trace element */
-                        unsigned short trc_bfr_space; 		/* trace buffer space */
-			unsigned char  update_comms_stats;
-			struct net_device *arp_dev;
-			spinlock_t if_send_lock;
-		} f;
-		struct			/****** PPP-specific data ***********/
-		{
-			char if_name[WAN_IFNAME_SZ+1];	/* interface name */
-			void* txbuf;		/* -> current Tx buffer */
-			void* txbuf_base;	/* -> first Tx buffer */
-			void* txbuf_last;	/* -> last Tx buffer */
-			void* rxbuf_base;	/* -> first Rx buffer */
-			void* rxbuf_last;	/* -> last Rx buffer */
-			unsigned rx_base;	/* S508 receive buffer base */
-			unsigned rx_top;	/* S508 receive buffer end */
-			char ip_mode;		/* STATIC/HOST/PEER IP Mode */
-			char authenticator;	/* Authenticator for PAP/CHAP */
-			unsigned char comm_enabled; /* Is comm enabled or not */
-			unsigned char peer_route;   /* Process Peer Route */	
-			unsigned long *txbuf_next;  /* Next Tx buffer to use */ 
-			unsigned long *rxbuf_next;  /* Next Rx buffer to use */
-		} p;
-		struct			/* Cisco HDLC-specific data */
-		{
-			char if_name[WAN_IFNAME_SZ+1];	/* interface name */
-			unsigned char comm_port;/* Communication Port O or 1 */
-			unsigned char usedby;  /* Used by WANPIPE or API */
-			void* rxmb;		/* Receive mail box */
-			void* flags;		/* flags */
-			void* tx_status;	/* Tx status element */
-			void* rx_status;	/* Rx status element */
-			void* txbuf;		/* -> current Tx buffer */
-			void* txbuf_base;	/* -> first Tx buffer */
-			void* txbuf_last;	/* -> last Tx buffer */
-			void* rxbuf_base;	/* -> first Rx buffer */
-			void* rxbuf_last;	/* -> last Rx buffer */
-			unsigned rx_base;	/* S508 receive buffer base */
-			unsigned rx_top;	/* S508 receive buffer end */
-			unsigned char receive_only; /* high speed receivers */
-			unsigned short protocol_options;
-			unsigned short kpalv_tx;	/* Tx kpalv timer */
-			unsigned short kpalv_rx;	/* Rx kpalv timer */
-			unsigned short kpalv_err;	/* Error tolerance */
-			unsigned short slarp_timer;	/* SLARP req timer */
-			unsigned state;			/* state of the link */
-			unsigned char api_status;
-			unsigned char update_call_count;
-			unsigned short api_options;	/* for async config */
-			unsigned char  async_mode;
-		        unsigned short tx_bits_per_char;
-		        unsigned short rx_bits_per_char;
-		        unsigned short stop_bits;
-		        unsigned short parity;
-			unsigned short break_timer;
-		        unsigned short inter_char_timer;
-		        unsigned short rx_complete_length;
-		        unsigned short xon_char;
-		        unsigned short xoff_char;
-			unsigned char comm_enabled; /* Is comm enabled or not */
-			unsigned char backup;
-		} c;
-		struct
-		{
-			void* tx_status;	/* Tx status element */
-			void* rx_status;	/* Rx status element */
-			void* trace_status;	/* Trace status element */
-			void* txbuf;		/* -> current Tx buffer */
-			void* txbuf_base;	/* -> first Tx buffer */
-			void* txbuf_last;	/* -> last Tx buffer */
-			void* rxbuf_base;	/* -> first Rx buffer */
-			void* rxbuf_last;	/* -> last Rx buffer */
-			void* tracebuf;		/* -> current Trace buffer */
-			void* tracebuf_base;	/* -> current Trace buffer */
-			void* tracebuf_last;	/* -> current Trace buffer */
-			unsigned rx_base;	/* receive buffer base */
-			unsigned rx_end;	/* receive buffer end */
-			unsigned trace_base;	/* trace buffer base */
-			unsigned trace_end;	/* trace buffer end */
-
-		} h;
-	} u;
-} sdla_t;
-
-/****** Public Functions ****************************************************/
-
-void wanpipe_open      (sdla_t* card);			/* wpmain.c */
-void wanpipe_close     (sdla_t* card);			/* wpmain.c */
-void wanpipe_set_state (sdla_t* card, int state);	/* wpmain.c */
-
-int wpx_init (sdla_t* card, wandev_conf_t* conf);	/* wpx.c */
-int wpf_init (sdla_t* card, wandev_conf_t* conf);	/* wpf.c */
-int wpp_init (sdla_t* card, wandev_conf_t* conf);	/* wpp.c */
-int wpc_init (sdla_t* card, wandev_conf_t* conf); /* Cisco HDLC */
-int bsc_init (sdla_t* card, wandev_conf_t* conf);	/* BSC streaming */
-int hdlc_init(sdla_t* card, wandev_conf_t* conf);	/* HDLC support */
-int wpft1_init (sdla_t* card, wandev_conf_t* conf);     /* FT1 Config support */
-int wsppp_init (sdla_t* card, wandev_conf_t* conf);	/* Sync PPP on top of RAW CHDLC */
-
-extern sdla_t * wanpipe_find_card(char *);
-extern sdla_t * wanpipe_find_card_num (int);
-
-extern void wanpipe_queue_work (struct work_struct *);
-extern void wanpipe_mark_bh (void);
-extern void wakeup_sk_bh(struct net_device *dev);
-extern int change_dev_flags(struct net_device *dev, unsigned flags);
-extern unsigned long get_ip_address(struct net_device *dev, int option);
-extern void add_gateway(sdla_t *card, struct net_device *dev);
-
-
-#endif	/* __KERNEL__ */
-#endif	/* _WANPIPE_H */
-
diff --git a/include/media/cx25840.h b/include/media/cx25840.h
new file mode 100644
index 0000000..8e7e52d6
--- /dev/null
+++ b/include/media/cx25840.h
@@ -0,0 +1,64 @@
+/*
+    cx25840.h - definition for cx25840/1/2/3 inputs
+
+    Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _CX25840_H_
+#define _CX25840_H_
+
+enum cx25840_video_input {
+	/* Composite video inputs In1-In8 */
+	CX25840_COMPOSITE1 = 1,
+	CX25840_COMPOSITE2,
+	CX25840_COMPOSITE3,
+	CX25840_COMPOSITE4,
+	CX25840_COMPOSITE5,
+	CX25840_COMPOSITE6,
+	CX25840_COMPOSITE7,
+	CX25840_COMPOSITE8,
+
+	/* S-Video inputs consist of one luma input (In1-In4) ORed with one
+	   chroma input (In5-In8) */
+	CX25840_SVIDEO_LUMA1 = 0x10,
+	CX25840_SVIDEO_LUMA2 = 0x20,
+	CX25840_SVIDEO_LUMA3 = 0x30,
+	CX25840_SVIDEO_LUMA4 = 0x40,
+	CX25840_SVIDEO_CHROMA4 = 0x400,
+	CX25840_SVIDEO_CHROMA5 = 0x500,
+	CX25840_SVIDEO_CHROMA6 = 0x600,
+	CX25840_SVIDEO_CHROMA7 = 0x700,
+	CX25840_SVIDEO_CHROMA8 = 0x800,
+
+	/* S-Video aliases for common luma/chroma combinations */
+	CX25840_SVIDEO1 = 0x510,
+	CX25840_SVIDEO2 = 0x620,
+	CX25840_SVIDEO3 = 0x730,
+	CX25840_SVIDEO4 = 0x840,
+};
+
+enum cx25840_audio_input {
+	/* Audio inputs: serial or In4-In8 */
+	CX25840_AUDIO_SERIAL,
+	CX25840_AUDIO4 = 4,
+	CX25840_AUDIO5,
+	CX25840_AUDIO6,
+	CX25840_AUDIO7,
+	CX25840_AUDIO8,
+};
+
+#endif
diff --git a/include/media/msp3400.h b/include/media/msp3400.h
index 0be61a0..6ab8549 100644
--- a/include/media/msp3400.h
+++ b/include/media/msp3400.h
@@ -80,16 +80,16 @@
  */
 
 /* SCART input to DSP selection */
-#define MSP_IN_SCART_1  	0  /* Pin SC1_IN */
-#define MSP_IN_SCART_2  	1  /* Pin SC2_IN */
-#define MSP_IN_SCART_3  	2  /* Pin SC3_IN */
-#define MSP_IN_SCART_4  	3  /* Pin SC4_IN */
+#define MSP_IN_SCART1  		0  /* Pin SC1_IN */
+#define MSP_IN_SCART2  		1  /* Pin SC2_IN */
+#define MSP_IN_SCART3  		2  /* Pin SC3_IN */
+#define MSP_IN_SCART4  		3  /* Pin SC4_IN */
 #define MSP_IN_MONO     	6  /* Pin MONO_IN */
 #define MSP_IN_MUTE     	7  /* Mute DSP input */
 #define MSP_SCART_TO_DSP(in) 	(in)
 /* Tuner input to demodulator and DSP selection */
-#define MSP_IN_TUNER_1 		0  /* Analog Sound IF input pin ANA_IN1 */
-#define MSP_IN_TUNER_2  	1  /* Analog Sound IF input pin ANA_IN2 */
+#define MSP_IN_TUNER1 		0  /* Analog Sound IF input pin ANA_IN1 */
+#define MSP_IN_TUNER2 		1  /* Analog Sound IF input pin ANA_IN2 */
 #define MSP_TUNER_TO_DSP(in) 	((in) << 3)
 
 /* The msp has up to 5 DSP outputs, each output can independently select
@@ -109,14 +109,14 @@
    DSP. This is currently not implemented. Also not implemented is the
    multi-channel capable I2S3 input of the 44x0G. If someone can demonstrate
    a need for one of those features then additional support can be added. */
-#define MSP_DSP_OUT_TUNER 	0  /* Tuner output */
-#define MSP_DSP_OUT_SCART 	2  /* SCART output */
-#define MSP_DSP_OUT_I2S1 	5  /* I2S1 output */
-#define MSP_DSP_OUT_I2S2 	6  /* I2S2 output */
-#define MSP_DSP_OUT_I2S3    	7  /* I2S3 output */
-#define MSP_DSP_OUT_MAIN_AVC 	11 /* MAIN AVC processed output */
-#define MSP_DSP_OUT_MAIN 	12 /* MAIN output */
-#define MSP_DSP_OUT_AUX 	13 /* AUX output */
+#define MSP_DSP_IN_TUNER 	0  /* Tuner DSP input */
+#define MSP_DSP_IN_SCART 	2  /* SCART DSP input */
+#define MSP_DSP_IN_I2S1 	5  /* I2S1 DSP input */
+#define MSP_DSP_IN_I2S2 	6  /* I2S2 DSP input */
+#define MSP_DSP_IN_I2S3    	7  /* I2S3 DSP input */
+#define MSP_DSP_IN_MAIN_AVC 	11 /* MAIN AVC processed DSP input */
+#define MSP_DSP_IN_MAIN 	12 /* MAIN DSP input */
+#define MSP_DSP_IN_AUX 		13 /* AUX DSP input */
 #define MSP_DSP_TO_MAIN(in)   	((in) << 4)
 #define MSP_DSP_TO_AUX(in)    	((in) << 8)
 #define MSP_DSP_TO_SCART1(in) 	((in) << 12)
@@ -125,16 +125,16 @@
 
 /* Output SCART select: the SCART outputs can select which input
    to use. */
-#define MSP_OUT_SCART1 		0  /* SCART1 input, bypassing the DSP */
-#define MSP_OUT_SCART2 		1  /* SCART2 input, bypassing the DSP */
-#define MSP_OUT_SCART3 		2  /* SCART3 input, bypassing the DSP */
-#define MSP_OUT_SCART4 		3  /* SCART4 input, bypassing the DSP */
-#define MSP_OUT_SCART1_DA 	4  /* DSP SCART1 output */
-#define MSP_OUT_SCART2_DA 	5  /* DSP SCART2 output */
-#define MSP_OUT_MONO 		6  /* MONO input, bypassing the DSP */
-#define MSP_OUT_MUTE 		7  /* MUTE output */
-#define MSP_OUT_TO_SCART1(in)   	(in)
-#define MSP_OUT_TO_SCART2(in)   	((in) << 4)
+#define MSP_SC_IN_SCART1 	0  /* SCART1 input, bypassing the DSP */
+#define MSP_SC_IN_SCART2 	1  /* SCART2 input, bypassing the DSP */
+#define MSP_SC_IN_SCART3 	2  /* SCART3 input, bypassing the DSP */
+#define MSP_SC_IN_SCART4 	3  /* SCART4 input, bypassing the DSP */
+#define MSP_SC_IN_DSP_SCART1 	4  /* DSP SCART1 input */
+#define MSP_SC_IN_DSP_SCART2 	5  /* DSP SCART2 input */
+#define MSP_SC_IN_MONO 		6  /* MONO input, bypassing the DSP */
+#define MSP_SC_IN_MUTE 		7  /* MUTE output */
+#define MSP_SC_TO_SCART1(in)	(in)
+#define MSP_SC_TO_SCART2(in)	((in) << 4)
 
 /* Shortcut macros */
 #define MSP_INPUT(sc, t, main_aux_src, sc_i2s_src) \
@@ -145,14 +145,14 @@
 	 MSP_DSP_TO_SCART1(sc_i2s_src) | \
 	 MSP_DSP_TO_SCART2(sc_i2s_src) | \
 	 MSP_DSP_TO_I2S(sc_i2s_src))
-#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, \
-				    MSP_DSP_OUT_TUNER, MSP_DSP_OUT_TUNER)
+#define MSP_INPUT_DEFAULT MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+				    MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
 #define MSP_OUTPUT(sc) \
-	(MSP_OUT_TO_SCART1(sc) | \
-	 MSP_OUT_TO_SCART2(sc))
+	(MSP_SC_TO_SCART1(sc) | \
+	 MSP_SC_TO_SCART2(sc))
 /* This equals the RESET position of the msp3400 ACB register */
-#define MSP_OUTPUT_DEFAULT (MSP_OUT_TO_SCART1(MSP_OUT_SCART3) | \
-			    MSP_OUT_TO_SCART2(MSP_OUT_SCART1_DA))
+#define MSP_OUTPUT_DEFAULT (MSP_SC_TO_SCART1(MSP_SC_IN_SCART3) | \
+			    MSP_SC_TO_SCART2(MSP_SC_IN_DSP_SCART1))
 
 /* Tuner inputs vs. msp version */
 /* Chip      TUNER_1   TUNER_2
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
new file mode 100644
index 0000000..6b4836f
--- /dev/null
+++ b/include/media/saa7115.h
@@ -0,0 +1,37 @@
+/*
+    saa7115.h - definition for saa7113/4/5 inputs
+
+    Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _SAA7115_H_
+#define _SAA7115_H_
+
+/* SAA7113/4/5 HW inputs */
+#define SAA7115_COMPOSITE0 0
+#define SAA7115_COMPOSITE1 1
+#define SAA7115_COMPOSITE2 2
+#define SAA7115_COMPOSITE3 3
+#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */
+#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */
+#define SAA7115_SVIDEO0    6
+#define SAA7115_SVIDEO1    7
+#define SAA7115_SVIDEO2    8
+#define SAA7115_SVIDEO3    9
+
+#endif
+
diff --git a/include/media/saa7127.h b/include/media/saa7127.h
new file mode 100644
index 0000000..bbcf862
--- /dev/null
+++ b/include/media/saa7127.h
@@ -0,0 +1,41 @@
+/*
+    saa7127.h - definition for saa7126/7/8/9 inputs/outputs
+
+    Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _SAA7127_H_
+#define _SAA7127_H_
+
+/* Enumeration for the supported input types */
+enum saa7127_input_type {
+	SAA7127_INPUT_TYPE_NORMAL,
+	SAA7127_INPUT_TYPE_TEST_IMAGE
+};
+
+/* Enumeration for the supported output signal types */
+enum saa7127_output_type {
+	SAA7127_OUTPUT_TYPE_BOTH,
+	SAA7127_OUTPUT_TYPE_COMPOSITE,
+	SAA7127_OUTPUT_TYPE_SVIDEO,
+	SAA7127_OUTPUT_TYPE_RGB,
+	SAA7127_OUTPUT_TYPE_YUV_C,
+	SAA7127_OUTPUT_TYPE_YUV_V
+};
+
+#endif
+
diff --git a/include/media/upd64031a.h b/include/media/upd64031a.h
new file mode 100644
index 0000000..3ad6a32
--- /dev/null
+++ b/include/media/upd64031a.h
@@ -0,0 +1,40 @@
+/*
+ * upd64031a - NEC Electronics Ghost Reduction input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _UPD64031A_H_
+#define _UPD64031A_H_
+
+/* Ghost reduction modes */
+#define UPD64031A_GR_ON 	0
+#define UPD64031A_GR_OFF 	1
+#define UPD64031A_GR_THROUGH 	3
+
+/* Direct 3D/YCS Connection */
+#define UPD64031A_3DYCS_DISABLE   (0 << 2)
+#define UPD64031A_3DYCS_COMPOSITE (2 << 2)
+#define UPD64031A_3DYCS_SVIDEO    (3 << 2)
+
+/* Composite sync digital separation circuit */
+#define UPD64031A_COMPOSITE_EXTERNAL (1 << 4)
+
+/* Vertical sync digital separation circuit */
+#define UPD64031A_VERTICAL_EXTERNAL (1 << 5)
+
+#endif
diff --git a/include/media/upd64083.h b/include/media/upd64083.h
new file mode 100644
index 0000000..59b6f32
--- /dev/null
+++ b/include/media/upd64083.h
@@ -0,0 +1,58 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation input defines
+ *
+ * 2006 by Hans Verkuil (hverkuil@xs4all.nl)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _UPD64083_H_
+#define _UPD64083_H_
+
+/* There are two bits of information that the driver needs in order
+   to select the correct routing: the operating mode and the selection
+   of the Y input (external or internal).
+
+   The first two operating modes expect a composite signal on the Y input,
+   the second two operating modes use both the Y and C inputs.
+
+   Normally YCS_MODE is used for tuner and composite inputs, and the
+   YCNR mode is used for S-Video inputs.
+
+   The external Y-ADC is selected when the composite input comes from a
+   upd64031a ghost reduction device. If this device is not present, or
+   the input is a S-Video signal, then the internal Y-ADC input should
+   be used. */
+
+/* Operating modes: */
+
+/* YCS mode: Y/C separation (burst locked clocking) */
+#define UPD64083_YCS_MODE      0
+/* YCS+ mode: 2D Y/C separation and YCNR (burst locked clocking) */
+#define UPD64083_YCS_PLUS_MODE 1
+
+/* Note: the following two modes cannot be used in combination with the
+   external Y-ADC. */
+/* MNNR mode: frame comb type YNR+C delay (line locked clocking) */
+#define UPD64083_MNNR_MODE     2
+/* YCNR mode: frame recursive YCNR (burst locked clocking) */
+#define UPD64083_YCNR_MODE     3
+
+/* Select external Y-ADC: this should be set if this device is used in
+   combination with the upd64031a ghost reduction device.
+   Otherwise leave at 0 (use internal Y-ADC). */
+#define UPD64083_EXT_Y_ADC     (1 << 2)
+
+#endif
diff --git a/include/net/arp.h b/include/net/arp.h
index a13e30c..643bded 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -10,8 +10,6 @@
 extern struct neigh_table arp_tbl;
 
 extern void	arp_init(void);
-extern int	arp_rcv(struct sk_buff *skb, struct net_device *dev,
-			struct packet_type *pt, struct net_device *orig_dev);
 extern int	arp_find(unsigned char *haddr, struct sk_buff *skb);
 extern int	arp_ioctl(unsigned int cmd, void __user *arg);
 extern void     arp_send(int type, int ptype, u32 dest_ip, 
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index b971d8c..b1ebfba 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -96,10 +96,13 @@
 	 *
 	 * bssvalid is true if we found a matching network
 	 * and saved it's BSSID into the bssid above.
+	 *
+	 * bssfixed is used for SIOCSIWAP.
 	 */
 	u8 static_essid:1,
 	   associating:1,
-	   bssvalid:1;
+	   bssvalid:1,
+	   bssfixed:1;
 
 	/* Scan retries remaining */
 	int scan_retry;
@@ -267,8 +270,9 @@
 #define IEEE80211SOFTMAC_EVENT_AUTH_FAILED		5
 #define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT		6
 #define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND	7
+#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED		8
 /* keep this updated! */
-#define IEEE80211SOFTMAC_EVENT_LAST			7
+#define IEEE80211SOFTMAC_EVENT_LAST			8
 /*
  * If you want to be notified of certain events, you can call
  * ieee80211softmac_notify[_atomic] with
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 25f708f..59f0c83 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -48,31 +48,7 @@
 	return inet6_ehashfn(laddr, lport, faddr, fport);
 }
 
-static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
-				struct sock *sk)
-{
-	struct hlist_head *list;
-	rwlock_t *lock;
-
-	BUG_TRAP(sk_unhashed(sk));
-
-	if (sk->sk_state == TCP_LISTEN) {
-		list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
-		lock = &hashinfo->lhash_lock;
-		inet_listen_wlock(hashinfo);
-	} else {
-		unsigned int hash;
-		sk->sk_hash = hash = inet6_sk_ehashfn(sk);
-		hash &= (hashinfo->ehash_size - 1);
-		list = &hashinfo->ehash[hash].chain;
-		lock = &hashinfo->ehash[hash].lock;
-		write_lock(lock);
-	}
-
-	__sk_add_node(sk, list);
-	sock_prot_inc_use(sk->sk_prot);
-	write_unlock(lock);
-}
+extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
 
 /*
  * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
@@ -80,52 +56,12 @@
  *
  * The sockhash lock must be held as a reader here.
  */
-static inline struct sock *
-		__inet6_lookup_established(struct inet_hashinfo *hashinfo,
+extern struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
 					   const struct in6_addr *saddr,
 					   const u16 sport,
 					   const struct in6_addr *daddr,
 					   const u16 hnum,
-					   const int dif)
-{
-	struct sock *sk;
-	const struct hlist_node *node;
-	const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
-	/* Optimize here for direct hit, only listening connections can
-	 * have wildcards anyways.
-	 */
-	unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
-	struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
-
-	prefetch(head->chain.first);
-	read_lock(&head->lock);
-	sk_for_each(sk, node, &head->chain) {
-		/* For IPV6 do the cheaper port and family tests first. */
-		if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
-			goto hit; /* You sunk my battleship! */
-	}
-	/* Must check for a TIME_WAIT'er before going to listener hash. */
-	sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
-		const struct inet_timewait_sock *tw = inet_twsk(sk);
-
-		if(*((__u32 *)&(tw->tw_dport))	== ports	&&
-		   sk->sk_family		== PF_INET6) {
-			const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
-
-			if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr)	&&
-			    ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr)	&&
-			    (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
-				goto hit;
-		}
-	}
-	read_unlock(&head->lock);
-	return NULL;
-
-hit:
-	sock_hold(sk);
-	read_unlock(&head->lock);
-	return sk;
-}
+					   const int dif);
 
 extern struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
 					  const struct in6_addr *daddr,
diff --git a/include/net/ip.h b/include/net/ip.h
index 8fe6156..3d2e5ca 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@
 extern int		ip_mr_input(struct sk_buff *skb);
 extern int		ip_output(struct sk_buff *skb);
 extern int		ip_mc_output(struct sk_buff *skb);
+extern int		ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 extern int		ip_do_nat(struct sk_buff *skb);
 extern void		ip_send_check(struct iphdr *ip);
 extern int		ip_queue_xmit(struct sk_buff *skb, int ipfragok);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 6d6f063..4abedb8 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -230,7 +230,7 @@
 					       void (*destructor)(struct sock *));
 
 
-extern int			ipv6_parse_hopopts(struct sk_buff *skb, int);
+extern int			ipv6_parse_hopopts(struct sk_buff *skb);
 
 extern struct ipv6_txoptions *  ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
 extern struct ipv6_txoptions *	ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
diff --git a/include/net/sock.h b/include/net/sock.h
index af2b054..ff8b0da 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -454,6 +454,7 @@
 
 static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
 {
+	skb_truesize_check(skb);
 	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 	sk->sk_wmem_queued   -= skb->truesize;
 	sk->sk_forward_alloc += skb->truesize;
diff --git a/include/net/x25device.h b/include/net/x25device.h
index 1a31837..1d10c87 100644
--- a/include/net/x25device.h
+++ b/include/net/x25device.h
@@ -8,6 +8,7 @@
 static inline __be16 x25_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	skb->mac.raw = skb->data;
+	skb->dev = dev;
 	skb->pkt_type = PACKET_HOST;
 	
 	return htons(ETH_P_X25);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e100291..afa508d 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -143,6 +143,11 @@
 	/* Replay detection state at the time we sent the last notification */
 	struct xfrm_replay_state preplay;
 
+	/* internal flag that only holds state for delayed aevent at the
+	 * moment
+	*/
+	u32			xflags;
+
 	/* Replay detection notification settings */
 	u32			replay_maxage;
 	u32			replay_maxdiff;
@@ -168,6 +173,9 @@
 	void			*data;
 };
 
+/* xflags - make enum if more show up */
+#define XFRM_TIME_DEFER	1
+
 enum {
 	XFRM_STATE_VOID,
 	XFRM_STATE_ACQ,
@@ -242,7 +250,6 @@
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
-struct xfrm_decap_state;
 struct xfrm_type
 {
 	char			*description;
@@ -251,7 +258,7 @@
 
 	int			(*init_state)(struct xfrm_state *x);
 	void			(*destructor)(struct xfrm_state *);
-	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
+	int			(*input)(struct xfrm_state *, struct sk_buff *skb);
 	int			(*output)(struct xfrm_state *, struct sk_buff *pskb);
 	/* Estimate maximal size of result of transformation of a dgram */
 	u32			(*get_max_size)(struct xfrm_state *, int size);
@@ -606,25 +613,11 @@
 
 extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
-/* Decapsulation state, used by the input to store data during
- * decapsulation procedure, to be used later (during the policy
- * check
- */
-struct xfrm_decap_state {
-	char	decap_data[20];
-	__u16	decap_type;
-};   
-
-struct sec_decap_state {
-	struct xfrm_state	*xvec;
-	struct xfrm_decap_state decap;
-};
-
 struct sec_path
 {
 	atomic_t		refcnt;
 	int			len;
-	struct sec_decap_state	x[XFRM_MAX_DEPTH];
+	struct xfrm_state	*xvec[XFRM_MAX_DEPTH];
 };
 
 static inline struct sec_path *
diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h
index b53b78d..6bc7472 100644
--- a/include/pcmcia/bulkmem.h
+++ b/include/pcmcia/bulkmem.h
@@ -35,7 +35,7 @@
 #define REGION_BAR_MASK		0xe000
 #define REGION_BAR_SHIFT	13
 
-int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn);
-int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn);
+int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn);
+int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn);
 
 #endif /* _LINUX_BULKMEM_H */
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index da19c29..c1da855 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -1,5 +1,5 @@
 /*
- * ciscode.h -- Definitions for bulk memory services
+ * ciscode.h
  *
  * 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
@@ -122,4 +122,7 @@
 
 #define MANFID_XIRCOM			0x0105
 
+#define MANFID_POSSIO			0x030c
+#define PRODID_POSSIO_GCC		0x0003
+
 #endif /* _LINUX_CISCODE_H */
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index c6a0695..d3bbb19 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -586,12 +586,7 @@
     cisdata_t	Data[CISTPL_MAX_CIS_SIZE];
 } cisdump_t;
 
-int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
-int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple);
-int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse);
 
-int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info);
 int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
 
 /* don't use outside of PCMCIA core yet */
@@ -602,4 +597,20 @@
 
 int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info);
 
+/* ... but use these wrappers instead */
+#define pcmcia_get_first_tuple(p_dev, tuple) \
+		pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_next_tuple(p_dev, tuple) \
+		pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
+
+#define pcmcia_get_tuple_data(p_dev, tuple) \
+		pccard_get_tuple_data(p_dev->socket, tuple)
+
+#define pcmcia_parse_tuple(p_dev, tuple, parse) \
+		pccard_parse_tuple(tuple, parse)
+
+#define pcmcia_validate_cis(p_dev, info) \
+		pccard_validate_cis(p_dev->socket, p_dev->func, info)
+
 #endif /* LINUX_CISTPL_H */
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 52660f3..d5838c3 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -109,17 +109,6 @@
 
 #define CLIENT_THIS_SOCKET	0x01
 
-/* For RegisterClient */
-typedef struct client_reg_t {
-    dev_info_t	*dev_info;
-    u_int	Attributes;  /* UNUSED */
-    u_int	EventMask;
-    int		(*event_handler)(event_t event, int priority,
-				 event_callback_args_t *);
-    event_callback_args_t event_callback_args;
-    u_int	Version;
-} client_reg_t;
-
 /* ModifyConfiguration */
 typedef struct modconf_t {
     u_int	Attributes;
@@ -127,15 +116,16 @@
 } modconf_t;
 
 /* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID	0x100
-#define CONF_VCC_CHANGE_VALID	0x200
-#define CONF_VPP1_CHANGE_VALID	0x400
-#define CONF_VPP2_CHANGE_VALID	0x800
+#define CONF_IRQ_CHANGE_VALID	0x0100
+#define CONF_VCC_CHANGE_VALID	0x0200
+#define CONF_VPP1_CHANGE_VALID	0x0400
+#define CONF_VPP2_CHANGE_VALID	0x0800
+#define CONF_IO_CHANGE_WIDTH	0x1000
 
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int	Attributes;
-    u_int	Vcc, Vpp1, Vpp2;
+    u_int	Vpp; /* both Vpp1 and Vpp2 */
     u_int	IntType;
     u_int	ConfigBase;
     u_char	Status, Pin, Copy, ExtStatus;
@@ -389,23 +379,27 @@
 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
-int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
 int pcmcia_release_window(window_handle_t win);
 int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
 int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
 int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
-int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req);
 int pcmcia_suspend_card(struct pcmcia_socket *skt);
 int pcmcia_resume_card(struct pcmcia_socket *skt);
 int pcmcia_eject_card(struct pcmcia_socket *skt);
 int pcmcia_insert_card(struct pcmcia_socket *skt);
+int pccard_reset_card(struct pcmcia_socket *skt);
+
+struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *p_dev);
+void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
 void pcmcia_put_socket(struct pcmcia_socket *skt);
 
+/* compatibility functions */
+#define pcmcia_reset_card(p_dev, req) \
+		pccard_reset_card(p_dev->socket)
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 8e2a963..8c339f5 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -39,7 +39,7 @@
 typedef struct bind_info_t {
     dev_info_t		dev_info;
     u_char		function;
-    struct dev_link_t	*instance;
+    struct pcmcia_device *instance;
     char		name[DEV_NAME_LEN];
     u_short		major, minor;
     void		*next;
@@ -96,6 +96,7 @@
 
 #ifdef __KERNEL__
 #include <linux/device.h>
+#include <pcmcia/ss.h>
 
 typedef struct dev_node_t {
     char		dev_name[DEV_NAME_LEN];
@@ -103,34 +104,9 @@
     struct dev_node_t	*next;
 } dev_node_t;
 
-typedef struct dev_link_t {
-    dev_node_t		*dev;
-    u_int		state, open;
-    wait_queue_head_t	pending;
-    client_handle_t	handle;
-    io_req_t		io;
-    irq_req_t		irq;
-    config_req_t	conf;
-    window_handle_t	win;
-    void		*priv;
-    struct dev_link_t	*next;
-} dev_link_t;
-
-/* Flags for device state */
-#define DEV_PRESENT		0x01
-#define DEV_CONFIG		0x02
-#define DEV_STALE_CONFIG	0x04	/* release on close */
-#define DEV_STALE_LINK		0x08	/* detach on release */
-#define DEV_CONFIG_PENDING	0x10
-#define DEV_RELEASE_PENDING	0x20
-#define DEV_SUSPEND		0x40
-#define DEV_BUSY		0x80
-
-#define DEV_OK(l) \
-    ((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
-
 
 struct pcmcia_socket;
+struct config_t;
 
 struct pcmcia_driver {
 	int (*probe)		(struct pcmcia_device *dev);
@@ -148,6 +124,7 @@
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
+
 struct pcmcia_device {
 	/* the socket and the device_no [for multifunction devices]
 	   uniquely define a pcmcia_device */
@@ -160,21 +137,40 @@
 	/* the hardware "function" device; certain subdevices can
 	 * share one hardware "function" device. */
 	u8			func;
+	struct config_t*	function_config;
 
 	struct list_head	socket_device_list;
 
-	/* deprecated, a cleaned up version will be moved into this
-	   struct soon */
-	dev_link_t		*instance;
-	u_int			state;
+	/* deprecated, will be cleaned up soon */
+	dev_node_t		*dev_node;
+	u_int			open;
+	io_req_t		io;
+	irq_req_t		irq;
+	config_req_t		conf;
+	window_handle_t		win;
+
+	/* Is the device suspended, or in the process of
+	 * being removed? */
+	u16			suspended:1;
+	u16			_removed:1;
+
+	/* Flags whether io, irq, win configurations were
+	 * requested, and whether the configuration is "locked" */
+	u16			_irq:1;
+	u16			_io:1;
+	u16			_win:4;
+	u16			_locked:1;
+
+	/* Flag whether a "fuzzy" func_id based match is
+	 * allowed. */
+	u16			allow_func_id_match:1;
 
 	/* information about this device */
-	u8			has_manf_id:1;
-	u8			has_card_id:1;
-	u8			has_func_id:1;
+	u16			has_manf_id:1;
+	u16			has_card_id:1;
+	u16			has_func_id:1;
 
-	u8			allow_func_id_match:1;
-	u8			reserved:4;
+	u16			reserved:3;
 
 	u8			func_id;
 	u16			manf_id;
@@ -182,22 +178,24 @@
 
 	char *			prod_id[4];
 
+	struct device		dev;
+
+#ifdef CONFIG_PCMCIA_IOCTL
 	/* device driver wanted by cardmgr */
 	struct pcmcia_driver *	cardmgr;
+#endif
 
-	struct device		dev;
+	/* data private to drivers */
+	void			*priv;
 };
 
 #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
 #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
 
-#define handle_to_pdev(handle) (handle)
 #define handle_to_dev(handle) (handle->dev)
 
-#define dev_to_instance(dev) (dev->instance)
-
 /* error reporting */
-void cs_error(client_handle_t handle, int func, int ret);
+void cs_error(struct pcmcia_device *handle, int func, int ret);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_DS_H */
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 2889a69..5e0a01a 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -18,6 +18,7 @@
 #include <linux/config.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* task_struct, completion */
+#include <linux/mutex.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -146,14 +147,15 @@
 /* !SS_CAP_STATIC_MAP */
 extern struct pccard_resource_ops pccard_nonstatic_ops;
 
+/* static mem, dynamic IO sockets */
+extern struct pccard_resource_ops pccard_iodyn_ops;
+
 /*
  *  Calls to set up low-level "Socket Services" drivers
  */
 struct pcmcia_socket;
 
 typedef struct io_window_t {
-	u_int			Attributes;
-	kio_addr_t		BasePort, NumPorts;
 	kio_addr_t		InUse, Config;
 	struct resource		*res;
 } io_window_t;
@@ -162,7 +164,7 @@
 typedef struct window_t {
 	u_short			magic;
 	u_short			index;
-	client_handle_t		handle;
+	struct pcmcia_device	*handle;
 	struct pcmcia_socket 	*sock;
 	pccard_mem_map		ctl;
 } window_t;
@@ -186,7 +188,6 @@
 	u_short				lock_count;
 	pccard_mem_map			cis_mem;
 	void __iomem 			*cis_virt;
-	struct config_t			*config;
 	struct {
 		u_int			AssignedIRQ;
 		u_int			Config;
@@ -241,7 +242,7 @@
 #endif
 
 	/* state thread */
-	struct semaphore		skt_sem;	/* protects socket h/w state */
+	struct mutex			skt_mutex;	/* protects socket h/w state */
 
 	struct task_struct		*thread;
 	struct completion		thread_done;
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index f404fe2..ad63c21 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -91,34 +91,6 @@
 	IB_SA_BEST = 3
 };
 
-enum ib_sa_rate {
-	IB_SA_RATE_2_5_GBPS = 2,
-	IB_SA_RATE_5_GBPS   = 5,
-	IB_SA_RATE_10_GBPS  = 3,
-	IB_SA_RATE_20_GBPS  = 6,
-	IB_SA_RATE_30_GBPS  = 4,
-	IB_SA_RATE_40_GBPS  = 7,
-	IB_SA_RATE_60_GBPS  = 8,
-	IB_SA_RATE_80_GBPS  = 9,
-	IB_SA_RATE_120_GBPS = 10
-};
-
-static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
-{
-	switch (rate) {
-	case IB_SA_RATE_2_5_GBPS: return  1;
-	case IB_SA_RATE_5_GBPS:   return  2;
-	case IB_SA_RATE_10_GBPS:  return  4;
-	case IB_SA_RATE_20_GBPS:  return  8;
-	case IB_SA_RATE_30_GBPS:  return 12;
-	case IB_SA_RATE_40_GBPS:  return 16;
-	case IB_SA_RATE_60_GBPS:  return 24;
-	case IB_SA_RATE_80_GBPS:  return 32;
-	case IB_SA_RATE_120_GBPS: return 48;
-	default: 	          return -1;
-	}
-}
-
 /*
  * Structures for SA records are named "struct ib_sa_xxx_rec."  No
  * attempt is made to pack structures to match the physical layout of
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c1ad627..6bbf1b3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -314,6 +314,34 @@
 	IB_AH_GRH	= 1
 };
 
+enum ib_rate {
+	IB_RATE_PORT_CURRENT = 0,
+	IB_RATE_2_5_GBPS = 2,
+	IB_RATE_5_GBPS   = 5,
+	IB_RATE_10_GBPS  = 3,
+	IB_RATE_20_GBPS  = 6,
+	IB_RATE_30_GBPS  = 4,
+	IB_RATE_40_GBPS  = 7,
+	IB_RATE_60_GBPS  = 8,
+	IB_RATE_80_GBPS  = 9,
+	IB_RATE_120_GBPS = 10
+};
+
+/**
+ * ib_rate_to_mult - Convert the IB rate enum to a multiple of the
+ * base rate of 2.5 Gbit/sec.  For example, IB_RATE_5_GBPS will be
+ * converted to 2, since 5 Gbit/sec is 2 * 2.5 Gbit/sec.
+ * @rate: rate to convert.
+ */
+int ib_rate_to_mult(enum ib_rate rate) __attribute_const__;
+
+/**
+ * mult_to_ib_rate - Convert a multiple of 2.5 Gbit/sec to an IB rate
+ * enum.
+ * @mult: multiple to convert.
+ */
+enum ib_rate mult_to_ib_rate(int mult) __attribute_const__;
+
 struct ib_ah_attr {
 	struct ib_global_route	grh;
 	u16			dlid;
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index 174101b..d31b16d 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -28,4 +28,5 @@
 #define BLIST_NO_ULD_ATTACH	0x100000 /* device is actually for RAID config */
 #define BLIST_SELECT_NO_ATN	0x200000 /* select without ATN */
 #define BLIST_RETRY_HWERROR	0x400000 /* retry HARDWARE_ERROR */
+#define BLIST_MAX_512		0x800000 /* maximum 512 sector cdb length */
 #endif
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index dc6862d..de6ce54 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -140,7 +140,6 @@
 	 *
 	 * Status: REQUIRED	(at least one of them)
 	 */
-	int (* eh_strategy_handler)(struct Scsi_Host *);
 	int (* eh_abort_handler)(struct scsi_cmnd *);
 	int (* eh_device_reset_handler)(struct scsi_cmnd *);
 	int (* eh_bus_reset_handler)(struct scsi_cmnd *);
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
index d4be4d9..edb9525 100644
--- a/include/scsi/scsi_ioctl.h
+++ b/include/scsi/scsi_ioctl.h
@@ -41,8 +41,6 @@
 } Scsi_FCTargAddress;
 
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int scsi_ioctl_send_command(struct scsi_device *,
-				   struct scsi_ioctl_command __user *);
 extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
 				   void __user *arg, struct file *filp);
 
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index b3657f1..cca1d49 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -50,6 +50,11 @@
 	unsigned int create_work_queue : 1;
 
 	/*
+	 * Allows a transport to override the default error handler.
+	 */
+	void (* eh_strategy_handler)(struct Scsi_Host *);
+
+	/*
 	 * This is an optional routine that allows the transport to become
 	 * involved when a scsi io timer fires. The return value tells the
 	 * timer routine how to finish the io timeout handling:
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index cf3fec8..5626225 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -202,12 +202,19 @@
 	/* internal data */
 	unsigned int channel;
 	u32 number;
+	u8 flags;
 	struct list_head peers;
 	struct device dev;
  	struct work_struct dev_loss_work;
  	struct work_struct scan_work;
+ 	struct work_struct stgt_delete_work;
+	struct work_struct rport_delete_work;
 } __attribute__((aligned(sizeof(unsigned long))));
 
+/* bit field values for struct fc_rport "flags" field: */
+#define FC_RPORT_DEVLOSS_PENDING	0x01
+#define FC_RPORT_SCAN_PENDING		0x02
+
 #define	dev_to_rport(d)				\
 	container_of(d, struct fc_rport, dev)
 #define transport_class_to_rport(classdev)	\
@@ -327,13 +334,16 @@
 	struct list_head rport_bindings;
 	u32 next_rport_number;
 	u32 next_target_id;
-	u8 flags;
- 	struct work_struct rport_del_work;
+
+	/* work queues for rport state manipulation */
+	char work_q_name[KOBJ_NAME_LEN];
+	struct workqueue_struct *work_q;
+	char devloss_work_q_name[KOBJ_NAME_LEN];
+	struct workqueue_struct *devloss_work_q;
 };
 
-/* values for struct fc_host_attrs "flags" field: */
-#define FC_SHOST_RPORT_DEL_SCHEDULED	0x01
-
+#define shost_to_fc_host(x) \
+	((struct fc_host_attrs *)(x)->shost_data)
 
 #define fc_host_node_name(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->node_name)
@@ -375,10 +385,14 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
 #define fc_host_next_target_id(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
-#define fc_host_flags(x) \
-	(((struct fc_host_attrs *)(x)->shost_data)->flags)
-#define fc_host_rport_del_work(x) \
-	(((struct fc_host_attrs *)(x)->shost_data)->rport_del_work)
+#define fc_host_work_q_name(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->work_q_name)
+#define fc_host_work_q(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->work_q)
+#define fc_host_devloss_work_q_name(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
+#define fc_host_devloss_work_q(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
 
 
 /* The functions by which the transport class and the driver communicate */
@@ -461,10 +475,15 @@
 
 	switch (rport->port_state) {
 	case FC_PORTSTATE_ONLINE:
-		result = 0;
+		if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+			result = 0;
+		else if (rport->flags & FC_RPORT_DEVLOSS_PENDING)
+			result = DID_IMM_RETRY << 16;
+		else
+			result = DID_NO_CONNECT << 16;
 		break;
 	case FC_PORTSTATE_BLOCKED:
-		result = DID_BUS_BUSY << 16;
+		result = DID_IMM_RETRY << 16;
 		break;
 	default:
 		result = DID_NO_CONNECT << 16;
diff --git a/include/sound/core.h b/include/sound/core.h
index 7f32c12..5135147 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -170,13 +170,13 @@
 }
 
 /* init.c */
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file);
+int snd_power_wait(struct snd_card *card, unsigned int power_state);
 
 #else /* ! CONFIG_PM */
 
 #define snd_power_lock(card)		do { (void)(card); } while (0)
 #define snd_power_unlock(card)		do { (void)(card); } while (0)
-static inline int snd_power_wait(struct snd_card *card, unsigned int state, struct file *file) { return 0; }
+static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
 #define snd_power_get_state(card)	SNDRV_CTL_POWER_D0
 #define snd_power_change_state(card, state)	do { (void)(card); } while (0)
 
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 15b8856..df70e75 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -367,8 +367,9 @@
 	struct snd_pcm_group self_group;	/* fake group for non linked substream (with substream lock inside) */
 	struct snd_pcm_group *group;		/* pointer to current group */
 	/* -- assigned files -- */
-	struct snd_pcm_file *file;
+	void *file;
 	struct file *ffile;
+	void (*pcm_release)(struct snd_pcm_substream *);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
 	struct snd_pcm_oss_substream oss;
@@ -381,13 +382,10 @@
 	struct snd_info_entry *proc_prealloc_entry;
 	/* misc flags */
 	unsigned int no_mmap_ctrl: 1;
+	unsigned int hw_opened: 1;
 };
 
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL || ((substream)->oss.file != NULL))
-#else
 #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
-#endif
 
 
 struct snd_pcm_str {
@@ -460,7 +458,6 @@
 		      struct snd_pcm_info __user *info);
 int snd_pcm_status(struct snd_pcm_substream *substream,
 		   struct snd_pcm_status *status);
-int snd_pcm_prepare(struct snd_pcm_substream *substream);
 int snd_pcm_start(struct snd_pcm_substream *substream);
 int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
@@ -468,11 +465,13 @@
 int snd_pcm_suspend(struct snd_pcm_substream *substream);
 int snd_pcm_suspend_all(struct snd_pcm *pcm);
 #endif
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
 int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file,
+			   struct snd_pcm_substream **rsubstream);
 void snd_pcm_release_substream(struct snd_pcm_substream *substream);
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
+			     struct snd_pcm_substream **rsubstream);
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
 void snd_pcm_vma_notify_data(void *client, void *data);
 int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
 
@@ -899,7 +898,6 @@
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
-const char *snd_pcm_format_name(snd_pcm_format_t format);
 
 void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops);
 void snd_pcm_set_sync(struct snd_pcm_substream *substream);
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index bff0778e..39df2ba 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -69,8 +69,7 @@
 
 struct snd_pcm_oss_substream {
 	unsigned oss: 1;			/* oss mode */
-	struct snd_pcm_oss_setup *setup;		/* active setup */
-	struct snd_pcm_oss_file *file;
+	struct snd_pcm_oss_setup setup;		/* active setup */
 };
 
 struct snd_pcm_oss_stream {
diff --git a/ipc/shm.c b/ipc/shm.c
index f806a2e..1c2faf6 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -91,8 +91,8 @@
 static inline void shm_inc (int id) {
 	struct shmid_kernel *shp;
 
-	if(!(shp = shm_lock(id)))
-		BUG();
+	shp = shm_lock(id);
+	BUG_ON(!shp);
 	shp->shm_atim = get_seconds();
 	shp->shm_lprid = current->tgid;
 	shp->shm_nattch++;
@@ -142,8 +142,8 @@
 
 	mutex_lock(&shm_ids.mutex);
 	/* remove from the list of attaches of the shm segment */
-	if(!(shp = shm_lock(id)))
-		BUG();
+	shp = shm_lock(id);
+	BUG_ON(!shp);
 	shp->shm_lprid = current->tgid;
 	shp->shm_dtim = get_seconds();
 	shp->shm_nattch--;
@@ -162,6 +162,8 @@
 	ret = shmem_mmap(file, vma);
 	if (ret == 0) {
 		vma->vm_ops = &shm_vm_ops;
+		if (!(vma->vm_flags & VM_WRITE))
+			vma->vm_flags &= ~VM_MAYWRITE;
 		shm_inc(file->f_dentry->d_inode->i_ino);
 	}
 
@@ -283,8 +285,7 @@
 		err = -EEXIST;
 	} else {
 		shp = shm_lock(id);
-		if(shp==NULL)
-			BUG();
+		BUG_ON(shp==NULL);
 		if (shp->shm_segsz < size)
 			err = -EINVAL;
 		else if (ipcperms(&shp->shm_perm, shmflg))
@@ -774,8 +775,8 @@
 	up_write(&current->mm->mmap_sem);
 
 	mutex_lock(&shm_ids.mutex);
-	if(!(shp = shm_lock(shmid)))
-		BUG();
+	shp = shm_lock(shmid);
+	BUG_ON(!shp);
 	shp->shm_nattch--;
 	if(shp->shm_nattch == 0 &&
 	   shp->shm_perm.mode & SHM_DEST)
diff --git a/ipc/util.c b/ipc/util.c
index 23151ef..b3dcfad 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -183,8 +183,7 @@
 	if(new == NULL)
 		return size;
 	new->size = newsize;
-	memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
-					sizeof(struct ipc_id_ary));
+	memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
 	for(i=size;i<newsize;i++) {
 		new->p[i] = NULL;
 	}
@@ -266,8 +265,7 @@
 {
 	struct kern_ipc_perm* p;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid >= ids->entries->size)
-		BUG();
+	BUG_ON(lid >= ids->entries->size);
 
 	/* 
 	 * do not need a rcu_dereference()() here to force ordering
@@ -275,8 +273,7 @@
 	 */	
 	p = ids->entries->p[lid];
 	ids->entries->p[lid] = NULL;
-	if(p==NULL)
-		BUG();
+	BUG_ON(p==NULL);
 	ids->in_use--;
 
 	if (lid == ids->max_id) {
diff --git a/kernel/exit.c b/kernel/exit.c
index 6c2eeb8..f86434d 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -34,6 +34,7 @@
 #include <linux/mutex.h>
 #include <linux/futex.h>
 #include <linux/compat.h>
+#include <linux/pipe_fs_i.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -55,7 +56,7 @@
 		detach_pid(p, PIDTYPE_PGID);
 		detach_pid(p, PIDTYPE_SID);
 
-		list_del_init(&p->tasks);
+		list_del_rcu(&p->tasks);
 		__get_cpu_var(process_counts)--;
 	}
 	list_del_rcu(&p->thread_group);
@@ -941,6 +942,9 @@
 	if (tsk->io_context)
 		exit_io_context();
 
+	if (tsk->splice_pipe)
+		__free_pipe_info(tsk->splice_pipe);
+
 	/* PF_DEAD causes final put_task_struct after we schedule. */
 	preempt_disable();
 	BUG_ON(tsk->flags & PF_DEAD);
diff --git a/kernel/fork.c b/kernel/fork.c
index 3384eb8..d2fa57d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -124,12 +124,6 @@
 		free_task(tsk);
 }
 
-void __put_task_struct_cb(struct rcu_head *rhp)
-{
-	struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
-	__put_task_struct(tsk);
-}
-
 void __init fork_init(unsigned long mempages)
 {
 #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
@@ -186,6 +180,7 @@
 	atomic_set(&tsk->usage,2);
 	atomic_set(&tsk->fs_excl, 0);
 	tsk->btrace_seq = 0;
+	tsk->splice_pipe = NULL;
 	return tsk;
 }
 
@@ -1210,7 +1205,7 @@
 			attach_pid(p, PIDTYPE_PGID, process_group(p));
 			attach_pid(p, PIDTYPE_SID, p->signal->session);
 
-			list_add_tail(&p->tasks, &init_task.tasks);
+			list_add_tail_rcu(&p->tasks, &init_task.tasks);
 			__get_cpu_var(process_counts)++;
 		}
 		attach_pid(p, PIDTYPE_PID, p->pid);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f181ff4..b7f0388 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -501,6 +501,7 @@
 
 		if (ret >= 0)
 			return ret;
+		cpu_relax();
 	}
 }
 
@@ -835,7 +836,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+static int hrtimer_cpu_notify(struct notifier_block *self,
 					unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -859,7 +860,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata hrtimers_nb = {
+static struct notifier_block hrtimers_nb = {
 	.notifier_call = hrtimer_cpu_notify,
 };
 
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 2b33f85..9f77f50 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -1,4 +1,5 @@
 
-obj-y := handle.o manage.o spurious.o migration.o
+obj-y := handle.o manage.o spurious.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ac766ad..1279e34 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -246,8 +246,10 @@
 
 mismatch:
 	spin_unlock_irqrestore(&desc->lock, flags);
-	printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
-	dump_stack();
+	if (!(new->flags & SA_PROBEIRQ)) {
+		printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+		dump_stack();
+	}
 	return -EBUSY;
 }
 
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 52a8655..134f9f2 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -1,6 +1,5 @@
-#include <linux/irq.h>
 
-#if defined(CONFIG_GENERIC_PENDING_IRQ)
+#include <linux/irq.h>
 
 void set_pending_irq(unsigned int irq, cpumask_t mask)
 {
@@ -61,5 +60,3 @@
 	}
 	cpus_clear(pending_irq_cpumask[irq]);
 }
-
-#endif
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1156eb0..1fbf466 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -585,6 +585,9 @@
 	int i;
 
 	rp->kp.pre_handler = pre_handler_kretprobe;
+	rp->kp.post_handler = NULL;
+	rp->kp.fault_handler = NULL;
+	rp->kp.break_handler = NULL;
 
 	/* Pre-allocate memory for max kretprobe instances */
 	if (rp->maxactive <= 0) {
diff --git a/kernel/panic.c b/kernel/panic.c
index f895c7c..cc2a4c9 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -27,7 +27,6 @@
 static DEFINE_SPINLOCK(pause_on_oops_lock);
 
 int panic_timeout;
-EXPORT_SYMBOL(panic_timeout);
 
 ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 9fd8d4f..ce0dfb8 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -41,7 +41,7 @@
 	depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
 	---help---
 	  Enable the possibility of suspending the machine.
-	  It doesn't need APM.
+	  It doesn't need ACPI or APM.
 	  You may suspend your machine by 'swsusp' or 'shutdown -z <time>' 
 	  (patch for sysvinit needed). 
 
diff --git a/kernel/power/main.c b/kernel/power/main.c
index ee371f5..a6d9ef4 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -272,7 +272,7 @@
 		if (*s && !strncmp(buf, *s, len))
 			break;
 	}
-	if (*s)
+	if (state < PM_SUSPEND_MAX && *s)
 		error = enter_state(state);
 	else
 		error = -EINVAL;
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 0f6908c..84063ac 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -75,25 +75,6 @@
 	return dev;
 }
 
-/**
- *	pm_unregister -  unregister a device with power management
- *	@dev: device to unregister
- *
- *	Remove a device from the power management notification lists. The
- *	dev passed must be a handle previously returned by pm_register.
- */
- 
-void pm_unregister(struct pm_dev *dev)
-{
-	if (dev) {
-		mutex_lock(&pm_devs_lock);
-		list_del(&dev->entry);
-		mutex_unlock(&pm_devs_lock);
-
-		kfree(dev);
-	}
-}
-
 static void __pm_unregister(struct pm_dev *dev)
 {
 	if (dev) {
@@ -258,7 +239,6 @@
 }
 
 EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
 EXPORT_SYMBOL(pm_unregister_all);
 EXPORT_SYMBOL(pm_send_all);
 EXPORT_SYMBOL(pm_active);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c5863d0..3eeedbb 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -240,14 +240,15 @@
  *	free_pagedir - free pages allocated with alloc_pagedir()
  */
 
-static void free_pagedir(struct pbe *pblist)
+static void free_pagedir(struct pbe *pblist, int clear_nosave_free)
 {
 	struct pbe *pbe;
 
 	while (pblist) {
 		pbe = (pblist + PB_PAGE_SKIP)->next;
 		ClearPageNosave(virt_to_page(pblist));
-		ClearPageNosaveFree(virt_to_page(pblist));
+		if (clear_nosave_free)
+			ClearPageNosaveFree(virt_to_page(pblist));
 		free_page((unsigned long)pblist);
 		pblist = pbe;
 	}
@@ -389,7 +390,7 @@
 		pbe->next = alloc_image_page(gfp_mask, safe_needed);
 	}
 	if (!pbe) { /* get_zeroed_page() failed */
-		free_pagedir(pblist);
+		free_pagedir(pblist, 1);
 		pblist = NULL;
         } else
 		create_pbe_list(pblist, nr_pages);
@@ -736,7 +737,7 @@
 		pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
 		if (pblist)
 			copy_page_backup_list(pblist, p);
-		free_pagedir(p);
+		free_pagedir(p, 0);
 		if (!pblist)
 			error = -ENOMEM;
 	}
diff --git a/kernel/printk.c b/kernel/printk.c
index 8cc1943..c056f33 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -360,8 +360,7 @@
 	unsigned long cur_index, start_print;
 	static int msg_level = -1;
 
-	if (((long)(start - end)) > 0)
-		BUG();
+	BUG_ON(((long)(start - end)) > 0);
 
 	cur_index = start;
 	start_print = start;
@@ -708,8 +707,7 @@
  */
 void acquire_console_sem(void)
 {
-	if (in_interrupt())
-		BUG();
+	BUG_ON(in_interrupt());
 	down(&console_sem);
 	console_locked = 1;
 	console_may_schedule = 1;
diff --git a/kernel/profile.c b/kernel/profile.c
index 5a730fd..68afe12 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -299,7 +299,7 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int __devinit profile_cpu_callback(struct notifier_block *info,
+static int profile_cpu_callback(struct notifier_block *info,
 					unsigned long action, void *__cpu)
 {
 	int node, cpu = (unsigned long)__cpu;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 86a7f6c..4e0f0ec 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -30,8 +30,7 @@
  */
 void __ptrace_link(task_t *child, task_t *new_parent)
 {
-	if (!list_empty(&child->ptrace_list))
-		BUG();
+	BUG_ON(!list_empty(&child->ptrace_list));
 	if (child->parent == new_parent)
 		return;
 	list_add(&child->ptrace_list, &child->parent->ptrace_children);
@@ -57,10 +56,6 @@
 			signal_wake_up(child, 1);
 		}
 	}
-	if (child->signal->flags & SIGNAL_GROUP_EXIT) {
-		sigaddset(&child->pending.signal, SIGKILL);
-		signal_wake_up(child, 1);
-	}
 	spin_unlock(&child->sighand->siglock);
 }
 
@@ -82,7 +77,8 @@
 		add_parent(child);
 	}
 
-	ptrace_untrace(child);
+	if (child->state == TASK_TRACED)
+		ptrace_untrace(child);
 }
 
 /*
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 13458bb..6d32ff2 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -520,7 +520,7 @@
 	tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
 }
 
-static int __devinit rcu_cpu_notify(struct notifier_block *self, 
+static int rcu_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -537,7 +537,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata rcu_nb = {
+static struct notifier_block rcu_nb = {
 	.notifier_call	= rcu_cpu_notify,
 };
 
diff --git a/kernel/sched.c b/kernel/sched.c
index dd153d6..4c64f85 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -665,13 +665,55 @@
 }
 
 /*
+ * We place interactive tasks back into the active array, if possible.
+ *
+ * To guarantee that this does not starve expired tasks we ignore the
+ * interactivity of a task if the first expired task had to wait more
+ * than a 'reasonable' amount of time. This deadline timeout is
+ * load-dependent, as the frequency of array switched decreases with
+ * increasing number of running tasks. We also ignore the interactivity
+ * if a better static_prio task has expired, and switch periodically
+ * regardless, to ensure that highly interactive tasks do not starve
+ * the less fortunate for unreasonably long periods.
+ */
+static inline int expired_starving(runqueue_t *rq)
+{
+	int limit;
+
+	/*
+	 * Arrays were recently switched, all is well
+	 */
+	if (!rq->expired_timestamp)
+		return 0;
+
+	limit = STARVATION_LIMIT * rq->nr_running;
+
+	/*
+	 * It's time to switch arrays
+	 */
+	if (jiffies - rq->expired_timestamp >= limit)
+		return 1;
+
+	/*
+	 * There's a better selection in the expired array
+	 */
+	if (rq->curr->static_prio > rq->best_expired_prio)
+		return 1;
+
+	/*
+	 * All is well
+	 */
+	return 0;
+}
+
+/*
  * __activate_task - move a task to the runqueue.
  */
 static void __activate_task(task_t *p, runqueue_t *rq)
 {
 	prio_array_t *target = rq->active;
 
-	if (batch_task(p))
+	if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p))))
 		target = rq->expired;
 	enqueue_task(p, target);
 	rq->nr_running++;
@@ -2490,22 +2532,6 @@
 }
 
 /*
- * We place interactive tasks back into the active array, if possible.
- *
- * To guarantee that this does not starve expired tasks we ignore the
- * interactivity of a task if the first expired task had to wait more
- * than a 'reasonable' amount of time. This deadline timeout is
- * load-dependent, as the frequency of array switched decreases with
- * increasing number of running tasks. We also ignore the interactivity
- * if a better static_prio task has expired:
- */
-#define EXPIRED_STARVING(rq) \
-	((STARVATION_LIMIT && ((rq)->expired_timestamp && \
-		(jiffies - (rq)->expired_timestamp >= \
-			STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \
-			((rq)->curr->static_prio > (rq)->best_expired_prio))
-
-/*
  * Account user cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
@@ -2640,7 +2666,7 @@
 
 		if (!rq->expired_timestamp)
 			rq->expired_timestamp = jiffies;
-		if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {
+		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
 			enqueue_task(p, rq->expired);
 			if (p->static_prio < rq->best_expired_prio)
 				rq->best_expired_prio = p->static_prio;
@@ -4788,7 +4814,7 @@
 /* Register at highest priority so that task migration (migrate_all_tasks)
  * happens before everything else.
  */
-static struct notifier_block __devinitdata migration_notifier = {
+static struct notifier_block migration_notifier = {
 	.notifier_call = migration_call,
 	.priority = 10
 };
diff --git a/kernel/signal.c b/kernel/signal.c
index 92025b1..e5f8aea 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -769,8 +769,7 @@
 {
 	int ret = 0;
 
-	if (!irqs_disabled())
-		BUG();
+	BUG_ON(!irqs_disabled());
 	assert_spin_locked(&t->sighand->siglock);
 
 	/* Short-circuit ignored signals.  */
@@ -869,7 +868,6 @@
 		if (t == NULL)
 			/* restart balancing at this thread */
 			t = p->signal->curr_target = p;
-		BUG_ON(t->tgid != p->tgid);
 
 		while (!wants_signal(sig, t)) {
 			t = next_thread(t);
@@ -1384,8 +1382,7 @@
 		 * the overrun count.  Other uses should not try to
 		 * send the signal multiple times.
 		 */
-		if (q->info.si_code != SI_TIMER)
-			BUG();
+		BUG_ON(q->info.si_code != SI_TIMER);
 		q->info.si_overrun++;
 		goto out;
 	} 
@@ -1757,9 +1754,9 @@
 			/* Let the debugger run.  */
 			ptrace_stop(signr, signr, info);
 
-			/* We're back.  Did the debugger cancel the sig or group_exit? */
+			/* We're back.  Did the debugger cancel the sig?  */
 			signr = current->exit_code;
-			if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT)
+			if (signr == 0)
 				continue;
 
 			current->exit_code = 0;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index ec8fed4..336f92d 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -446,7 +446,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
@@ -484,7 +484,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index ced91e1..14c7faf 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -104,7 +104,7 @@
 /*
  * Create/destroy watchdog threads as CPUs come and go:
  */
-static int __devinit
+static int
 cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
@@ -140,7 +140,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index d82864c..5433195 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -120,3 +120,15 @@
 cond_syscall(ppc_rtas);
 cond_syscall(sys_spu_run);
 cond_syscall(sys_spu_create);
+
+/* mmu depending weak syscall entries */
+cond_syscall(sys_mprotect);
+cond_syscall(sys_msync);
+cond_syscall(sys_mlock);
+cond_syscall(sys_munlock);
+cond_syscall(sys_mlockall);
+cond_syscall(sys_munlockall);
+cond_syscall(sys_mincore);
+cond_syscall(sys_madvise);
+cond_syscall(sys_mremap);
+cond_syscall(sys_remap_file_pages);
diff --git a/kernel/time.c b/kernel/time.c
index ff8e701..b00ddc7 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -410,7 +410,7 @@
  * current_fs_time - Return FS time
  * @sb: Superblock.
  *
- * Return the current time truncated to the time granuality supported by
+ * Return the current time truncated to the time granularity supported by
  * the fs.
  */
 struct timespec current_fs_time(struct super_block *sb)
@@ -421,11 +421,11 @@
 EXPORT_SYMBOL(current_fs_time);
 
 /**
- * timespec_trunc - Truncate timespec to a granuality
+ * timespec_trunc - Truncate timespec to a granularity
  * @t: Timespec
- * @gran: Granuality in ns.
+ * @gran: Granularity in ns.
  *
- * Truncate a timespec to a granuality. gran must be smaller than a second.
+ * Truncate a timespec to a granularity. gran must be smaller than a second.
  * Always rounds down.
  *
  * This function should be only used for timestamps returned by
diff --git a/kernel/timer.c b/kernel/timer.c
index 6b812c0..67eaf0f 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -81,9 +81,10 @@
 } ____cacheline_aligned_in_smp;
 
 typedef struct tvec_t_base_s tvec_base_t;
-static DEFINE_PER_CPU(tvec_base_t *, tvec_bases);
+
 tvec_base_t boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
+static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };
 
 static inline void set_running_timer(tvec_base_t *base,
 					struct timer_list *timer)
@@ -1224,28 +1225,36 @@
 {
 	int j;
 	tvec_base_t *base;
+	static char __devinitdata tvec_base_done[NR_CPUS];
 
-	base = per_cpu(tvec_bases, cpu);
-	if (!base) {
+	if (!tvec_base_done[cpu]) {
 		static char boot_done;
 
-		/*
-		 * Cannot do allocation in init_timers as that runs before the
-		 * allocator initializes (and would waste memory if there are
-		 * more possible CPUs than will ever be installed/brought up).
-		 */
 		if (boot_done) {
+			/*
+			 * The APs use this path later in boot
+			 */
 			base = kmalloc_node(sizeof(*base), GFP_KERNEL,
 						cpu_to_node(cpu));
 			if (!base)
 				return -ENOMEM;
 			memset(base, 0, sizeof(*base));
+			per_cpu(tvec_bases, cpu) = base;
 		} else {
-			base = &boot_tvec_bases;
+			/*
+			 * This is for the boot CPU - we use compile-time
+			 * static initialisation because per-cpu memory isn't
+			 * ready yet and because the memory allocators are not
+			 * initialised either.
+			 */
 			boot_done = 1;
+			base = &boot_tvec_bases;
 		}
-		per_cpu(tvec_bases, cpu) = base;
+		tvec_base_done[cpu] = 1;
+	} else {
+		base = per_cpu(tvec_bases, cpu);
 	}
+
 	spin_lock_init(&base->lock);
 	for (j = 0; j < TVN_SIZE; j++) {
 		INIT_LIST_HEAD(base->tv5.vec + j);
@@ -1305,7 +1314,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit timer_cpu_notify(struct notifier_block *self, 
+static int timer_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -1325,7 +1334,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata timers_nb = {
+static struct notifier_block timers_nb = {
 	.notifier_call	= timer_cpu_notify,
 };
 
@@ -1455,7 +1464,7 @@
 	 */
 	if (jiffies % INTERPOLATOR_ADJUST == 0)
 	{
-		if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC)
+		if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
 			time_interpolator->nsec_per_cyc--;
 		if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
 			time_interpolator->nsec_per_cyc++;
@@ -1479,8 +1488,7 @@
 	unsigned long flags;
 
 	/* Sanity check */
-	if (ti->frequency == 0 || ti->mask == 0)
-		BUG();
+	BUG_ON(ti->frequency == 0 || ti->mask == 0);
 
 	ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
 	spin_lock(&time_interpolator_lock);
diff --git a/kernel/uid16.c b/kernel/uid16.c
index aa25605..187e2a4 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -20,43 +20,67 @@
 
 asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-	return sys_chown(filename, low2highuid(user), low2highgid(group));
+	long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-	return sys_lchown(filename, low2highuid(user), low2highgid(group));
+	long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
 {
-	return sys_fchown(fd, low2highuid(user), low2highgid(group));
+	long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
 {
-	return sys_setregid(low2highgid(rgid), low2highgid(egid));
+	long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setgid16(old_gid_t gid)
 {
-	return sys_setgid(low2highgid(gid));
+	long ret = sys_setgid(low2highgid(gid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
 {
-	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+	long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setuid16(old_uid_t uid)
 {
-	return sys_setuid(low2highuid(uid));
+	long ret = sys_setuid(low2highuid(uid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
 {
-	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
-		low2highuid(suid));
+	long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+				 low2highuid(suid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
@@ -72,8 +96,11 @@
 
 asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
 {
-	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
-		low2highgid(sgid));
+	long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+				 low2highgid(sgid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
@@ -89,12 +116,18 @@
 
 asmlinkage long sys_setfsuid16(old_uid_t uid)
 {
-	return sys_setfsuid(low2highuid(uid));
+	long ret = sys_setfsuid(low2highuid(uid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 asmlinkage long sys_setfsgid16(old_gid_t gid)
 {
-	return sys_setfsgid(low2highgid(gid));
+	long ret = sys_setfsgid(low2highgid(gid));
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
 }
 
 static int groups16_to_user(old_gid_t __user *grouplist,
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index e9e464a..880fb41 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -547,7 +547,7 @@
 }
 
 /* We're holding the cpucontrol mutex here */
-static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
+static int workqueue_cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index d57fd91..6ecc180 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -101,7 +101,7 @@
 
 config DEBUG_MUTEXES
 	bool "Mutex debugging, deadlock detection"
-	default y
+	default n
 	depends on DEBUG_KERNEL
 	help
 	 This allows mutex semantics violations and mutex related deadlocks
diff --git a/lib/kobject.c b/lib/kobject.c
index 25204a4..b46350c 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -128,6 +128,7 @@
 {
 	kref_init(&kobj->kref);
 	INIT_LIST_HEAD(&kobj->entry);
+	init_waitqueue_head(&kobj->poll);
 	kobj->kset = kset_get(kobj->kset);
 }
 
@@ -421,7 +422,6 @@
 
 	return k;
 }
-EXPORT_SYMBOL_GPL(kobject_add_dir);
 
 /**
  *	kset_init - initialize a kset for use
@@ -568,7 +568,7 @@
  *	@s:	subsystem.
  *	@a:	attribute desciptor.
  */
-
+#if 0
 void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
 {
 	if (subsys_get(s)) {
@@ -576,6 +576,7 @@
 		subsys_put(s);
 	}
 }
+#endif  /*  0  */
 
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
@@ -587,10 +588,7 @@
 
 EXPORT_SYMBOL(kset_register);
 EXPORT_SYMBOL(kset_unregister);
-EXPORT_SYMBOL(kset_find_obj);
 
-EXPORT_SYMBOL(subsystem_init);
 EXPORT_SYMBOL(subsystem_register);
 EXPORT_SYMBOL(subsystem_unregister);
 EXPORT_SYMBOL(subsys_create_file);
-EXPORT_SYMBOL(subsys_remove_file);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 982226d..7f20e7b 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -25,11 +25,13 @@
 #define BUFFER_SIZE	2048	/* buffer for the variables */
 #define NUM_ENVP	32	/* number of env pointers */
 
-#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+#if defined(CONFIG_HOTPLUG)
 u64 uevent_seqnum;
 char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
 static DEFINE_SPINLOCK(sequence_lock);
+#if defined(CONFIG_NET)
 static struct sock *uevent_sock;
+#endif
 
 static char *action_to_string(enum kobject_action action)
 {
@@ -155,6 +157,7 @@
 	spin_unlock(&sequence_lock);
 	sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
 
+#if defined(CONFIG_NET)
 	/* send netlink message */
 	if (uevent_sock) {
 		struct sk_buff *skb;
@@ -179,6 +182,7 @@
 			netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
 		}
 	}
+#endif
 
 	/* call uevent_helper, usually only enabled during early boot */
 	if (uevent_helper[0]) {
@@ -249,6 +253,7 @@
 }
 EXPORT_SYMBOL_GPL(add_uevent_var);
 
+#if defined(CONFIG_NET)
 static int __init kobject_uevent_init(void)
 {
 	uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
@@ -264,5 +269,6 @@
 }
 
 postcore_initcall(kobject_uevent_init);
+#endif
 
 #endif /* CONFIG_HOTPLUG */
diff --git a/lib/string.c b/lib/string.c
index b3c28a3..064f631 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -362,6 +362,7 @@
 EXPORT_SYMBOL(strspn);
 #endif
 
+#ifndef __HAVE_ARCH_STRCSPN
 /**
  * strcspn - Calculate the length of the initial substring of @s which does
  * 	not contain letters in @reject
@@ -384,6 +385,7 @@
 	return count;
 }
 EXPORT_SYMBOL(strcspn);
+#endif
 
 #ifndef __HAVE_ARCH_STRPBRK
 /**
@@ -403,6 +405,7 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL(strpbrk);
 #endif
 
 #ifndef __HAVE_ARCH_STRSEP
@@ -467,7 +470,7 @@
 void *memcpy(void *dest, const void *src, size_t count)
 {
 	char *tmp = dest;
-	char *s = src;
+	const char *s = src;
 
 	while (count--)
 		*tmp++ = *s++;
diff --git a/mm/bootmem.c b/mm/bootmem.c
index d3e3bd2..d213fed 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -401,7 +401,7 @@
 	return(free_all_bootmem_core(NODE_DATA(0)));
 }
 
-void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal)
 {
 	bootmem_data_t *bdata;
 	void *ptr;
@@ -409,7 +409,14 @@
 	list_for_each_entry(bdata, &bdata_list, list)
 		if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0)))
 			return(ptr);
+	return NULL;
+}
 
+void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
+{
+	void *mem = __alloc_bootmem_nopanic(size,align,goal);
+	if (mem)
+		return mem;
 	/*
 	 * Whoops, we cannot satisfy the allocation request.
 	 */
diff --git a/mm/filemap.c b/mm/filemap.c
index 3ef2073..fd57442 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -697,6 +697,38 @@
 	return ret;
 }
 
+/**
+ * find_get_pages_contig - gang contiguous pagecache lookup
+ * @mapping:	The address_space to search
+ * @index:	The starting page index
+ * @nr_pages:	The maximum number of pages
+ * @pages:	Where the resulting pages are placed
+ *
+ * find_get_pages_contig() works exactly like find_get_pages(), except
+ * that the returned number of pages are guaranteed to be contiguous.
+ *
+ * find_get_pages_contig() returns the number of pages which were found.
+ */
+unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
+			       unsigned int nr_pages, struct page **pages)
+{
+	unsigned int i;
+	unsigned int ret;
+
+	read_lock_irq(&mapping->tree_lock);
+	ret = radix_tree_gang_lookup(&mapping->page_tree,
+				(void **)pages, index, nr_pages);
+	for (i = 0; i < ret; i++) {
+		if (pages[i]->mapping == NULL || pages[i]->index != index)
+			break;
+
+		page_cache_get(pages[i]);
+		index++;
+	}
+	read_unlock_irq(&mapping->tree_lock);
+	return i;
+}
+
 /*
  * Like find_get_pages, except we only return pages which are tagged with
  * `tag'.   We update *index to index the next page for the traversal.
diff --git a/mm/highmem.c b/mm/highmem.c
index 55885f6..9b274fdf 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -74,8 +74,7 @@
 		pkmap_count[i] = 0;
 
 		/* sanity check */
-		if (pte_none(pkmap_page_table[i]))
-			BUG();
+		BUG_ON(pte_none(pkmap_page_table[i]));
 
 		/*
 		 * Don't need an atomic fetch-and-clear op here;
@@ -158,8 +157,7 @@
 	if (!vaddr)
 		vaddr = map_new_virtual(page);
 	pkmap_count[PKMAP_NR(vaddr)]++;
-	if (pkmap_count[PKMAP_NR(vaddr)] < 2)
-		BUG();
+	BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2);
 	spin_unlock(&kmap_lock);
 	return (void*) vaddr;
 }
@@ -174,8 +172,7 @@
 
 	spin_lock(&kmap_lock);
 	vaddr = (unsigned long)page_address(page);
-	if (!vaddr)
-		BUG();
+	BUG_ON(!vaddr);
 	nr = PKMAP_NR(vaddr);
 
 	/*
@@ -220,8 +217,7 @@
 		return 0;
 
 	page_pool = mempool_create_page_pool(POOL_SIZE, 0);
-	if (!page_pool)
-		BUG();
+	BUG_ON(!page_pool);
 	printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
 
 	return 0;
@@ -264,8 +260,7 @@
 
 	isa_page_pool = mempool_create(ISA_POOL_SIZE, mempool_alloc_pages_isa,
 				       mempool_free_pages, (void *) 0);
-	if (!isa_page_pool)
-		BUG();
+	BUG_ON(!isa_page_pool);
 
 	printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
 	return 0;
diff --git a/mm/madvise.c b/mm/madvise.c
index af3d573..4e19615 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -168,6 +168,9 @@
 			return -EINVAL;
 	}
 
+	if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
+		return -EACCES;
+
 	mapping = vma->vm_file->f_mapping;
 
 	offset = (loff_t)(start - vma->vm_start)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index dec8249..8778f58 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1761,7 +1761,6 @@
 		md->mapcount_max = count;
 
 	md->node[page_to_nid(page)]++;
-	cond_resched();
 }
 
 #ifdef CONFIG_HUGETLB_PAGE
diff --git a/mm/migrate.c b/mm/migrate.c
index 09f6e4a..d444229 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -16,8 +16,7 @@
 #include <linux/module.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
-#include <linux/buffer_head.h>	/* for try_to_release_page(),
-					buffer_heads_over_limit */
+#include <linux/buffer_head.h>
 #include <linux/mm_inline.h>
 #include <linux/pagevec.h>
 #include <linux/rmap.h>
@@ -28,8 +27,6 @@
 
 #include "internal.h"
 
-#include "internal.h"
-
 /* The maximum number of pages to take off the LRU for migration */
 #define MIGRATE_CHUNK_SIZE 256
 
@@ -176,7 +173,6 @@
 retry:
 	return -EAGAIN;
 }
-EXPORT_SYMBOL(swap_page);
 
 /*
  * Remove references for a page and establish the new page with the correct
@@ -234,7 +230,7 @@
 	if (!page_mapping(page) || page_count(page) != nr_refs ||
 			*radix_pointer != page) {
 		write_unlock_irq(&mapping->tree_lock);
-		return 1;
+		return -EAGAIN;
 	}
 
 	/*
diff --git a/mm/mmap.c b/mm/mmap.c
index 4f5b570..e6ee123 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -121,14 +121,26 @@
 		 * only call if we're about to fail.
 		 */
 		n = nr_free_pages();
+
+		/*
+		 * Leave reserved pages. The pages are not for anonymous pages.
+		 */
+		if (n <= totalreserve_pages)
+			goto error;
+		else
+			n -= totalreserve_pages;
+
+		/*
+		 * Leave the last 3% for root
+		 */
 		if (!cap_sys_admin)
 			n -= n / 32;
 		free += n;
 
 		if (free > pages)
 			return 0;
-		vm_unacct_memory(pages);
-		return -ENOMEM;
+
+		goto error;
 	}
 
 	allowed = (totalram_pages - hugetlb_total_pages())
@@ -150,7 +162,7 @@
 	 */
 	if (atomic_read(&vm_committed_space) < (long)allowed)
 		return 0;
-
+error:
 	vm_unacct_memory(pages);
 
 	return -ENOMEM;
@@ -220,6 +232,17 @@
 
 	if (brk < mm->end_code)
 		goto out;
+
+	/*
+	 * Check against rlimit here. If this check is done later after the test
+	 * of oldbrk with newbrk then it can escape the test and let the data
+	 * segment grow beyond its set limit the in case where the limit is
+	 * not page aligned -Ram Gupta
+	 */
+	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+		goto out;
+
 	newbrk = PAGE_ALIGN(brk);
 	oldbrk = PAGE_ALIGN(mm->brk);
 	if (oldbrk == newbrk)
@@ -232,11 +255,6 @@
 		goto out;
 	}
 
-	/* Check against rlimit.. */
-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
-	if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
-		goto out;
-
 	/* Check against existing mmap mappings. */
 	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
 		goto out;
@@ -294,8 +312,7 @@
 	i = browse_rb(&mm->mm_rb);
 	if (i != mm->map_count)
 		printk("map_count %d rb %d\n", mm->map_count, i), bug = 1;
-	if (bug)
-		BUG();
+	BUG_ON(bug);
 }
 #else
 #define validate_mm(mm) do { } while (0)
@@ -432,8 +449,7 @@
 	struct rb_node ** rb_link, * rb_parent;
 
 	__vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent);
-	if (__vma && __vma->vm_start < vma->vm_end)
-		BUG();
+	BUG_ON(__vma && __vma->vm_start < vma->vm_end);
 	__vma_link(mm, vma, prev, rb_link, rb_parent);
 	mm->map_count++;
 }
@@ -813,8 +829,7 @@
 	 * (e.g. stash info in next's anon_vma_node when assigning
 	 * an anon_vma, or when trying vma_merge).  Another time.
 	 */
-	if (find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma)
-		BUG();
+	BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma);
 	if (!near)
 		goto none;
 
diff --git a/mm/nommu.c b/mm/nommu.c
index db45efa..029fada 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1147,14 +1147,26 @@
 		 * only call if we're about to fail.
 		 */
 		n = nr_free_pages();
+
+		/*
+		 * Leave reserved pages. The pages are not for anonymous pages.
+		 */
+		if (n <= totalreserve_pages)
+			goto error;
+		else
+			n -= totalreserve_pages;
+
+		/*
+		 * Leave the last 3% for root
+		 */
 		if (!cap_sys_admin)
 			n -= n / 32;
 		free += n;
 
 		if (free > pages)
 			return 0;
-		vm_unacct_memory(pages);
-		return -ENOMEM;
+
+		goto error;
 	}
 
 	allowed = totalram_pages * sysctl_overcommit_ratio / 100;
@@ -1175,7 +1187,7 @@
 	 */
 	if (atomic_read(&vm_committed_space) < (long)allowed)
 		return 0;
-
+error:
 	vm_unacct_memory(pages);
 
 	return -ENOMEM;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 78747af..042e643 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -46,15 +46,25 @@
 unsigned long badness(struct task_struct *p, unsigned long uptime)
 {
 	unsigned long points, cpu_time, run_time, s;
-	struct list_head *tsk;
+	struct mm_struct *mm;
+	struct task_struct *child;
 
-	if (!p->mm)
+	task_lock(p);
+	mm = p->mm;
+	if (!mm) {
+		task_unlock(p);
 		return 0;
+	}
 
 	/*
 	 * The memory size of the process is the basis for the badness.
 	 */
-	points = p->mm->total_vm;
+	points = mm->total_vm;
+
+	/*
+	 * After this unlock we can no longer dereference local variable `mm'
+	 */
+	task_unlock(p);
 
 	/*
 	 * Processes which fork a lot of child processes are likely
@@ -64,11 +74,11 @@
 	 * child is eating the vast majority of memory, adding only half
 	 * to the parents will make the child our kill candidate of choice.
 	 */
-	list_for_each(tsk, &p->children) {
-		struct task_struct *chld;
-		chld = list_entry(tsk, struct task_struct, sibling);
-		if (chld->mm != p->mm && chld->mm)
-			points += chld->mm->total_vm/2 + 1;
+	list_for_each_entry(child, &p->children, sibling) {
+		task_lock(child);
+		if (child->mm != mm && child->mm)
+			points += child->mm->total_vm/2 + 1;
+		task_unlock(child);
 	}
 
 	/*
@@ -244,17 +254,24 @@
 	force_sig(SIGKILL, p);
 }
 
-static struct mm_struct *oom_kill_task(task_t *p, const char *message)
+static int oom_kill_task(task_t *p, const char *message)
 {
-	struct mm_struct *mm = get_task_mm(p);
+	struct mm_struct *mm;
 	task_t * g, * q;
 
-	if (!mm)
-		return NULL;
-	if (mm == &init_mm) {
-		mmput(mm);
-		return NULL;
-	}
+	mm = p->mm;
+
+	/* WARNING: mm may not be dereferenced since we did not obtain its
+	 * value from get_task_mm(p).  This is OK since all we need to do is
+	 * compare mm to q->mm below.
+	 *
+	 * Furthermore, even if mm contains a non-NULL value, p->mm may
+	 * change to NULL at any time since we do not hold task_lock(p).
+	 * However, this is of no concern to us.
+	 */
+
+	if (mm == NULL || mm == &init_mm)
+		return 1;
 
 	__oom_kill_task(p, message);
 	/*
@@ -266,13 +283,12 @@
 			__oom_kill_task(q, message);
 	while_each_thread(g, q);
 
-	return mm;
+	return 0;
 }
 
-static struct mm_struct *oom_kill_process(struct task_struct *p,
-				unsigned long points, const char *message)
+static int oom_kill_process(struct task_struct *p, unsigned long points,
+		const char *message)
 {
- 	struct mm_struct *mm;
 	struct task_struct *c;
 	struct list_head *tsk;
 
@@ -283,9 +299,8 @@
 		c = list_entry(tsk, struct task_struct, sibling);
 		if (c->mm == p->mm)
 			continue;
-		mm = oom_kill_task(c, message);
-		if (mm)
-			return mm;
+		if (!oom_kill_task(c, message))
+			return 0;
 	}
 	return oom_kill_task(p, message);
 }
@@ -300,7 +315,6 @@
  */
 void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
 {
-	struct mm_struct *mm = NULL;
 	task_t *p;
 	unsigned long points = 0;
 
@@ -320,12 +334,12 @@
 	 */
 	switch (constrained_alloc(zonelist, gfp_mask)) {
 	case CONSTRAINT_MEMORY_POLICY:
-		mm = oom_kill_process(current, points,
+		oom_kill_process(current, points,
 				"No available memory (MPOL_BIND)");
 		break;
 
 	case CONSTRAINT_CPUSET:
-		mm = oom_kill_process(current, points,
+		oom_kill_process(current, points,
 				"No available memory in cpuset");
 		break;
 
@@ -347,8 +361,7 @@
 			panic("Out of memory and no killable processes...\n");
 		}
 
-		mm = oom_kill_process(p, points, "Out of memory");
-		if (!mm)
+		if (oom_kill_process(p, points, "Out of memory"))
 			goto retry;
 
 		break;
@@ -357,8 +370,6 @@
 out:
 	read_unlock(&tasklist_lock);
 	cpuset_unlock();
-	if (mm)
-		mmput(mm);
 
 	/*
 	 * Give "p" a good chance of killing itself before we
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 893d767..75d7f48 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -72,13 +72,12 @@
 int vm_dirty_ratio = 40;
 
 /*
- * The interval between `kupdate'-style writebacks, in centiseconds
- * (hundredths of a second)
+ * The interval between `kupdate'-style writebacks, in jiffies
  */
 int dirty_writeback_interval = 5 * HZ;
 
 /*
- * The longest number of centiseconds for which data is allowed to remain dirty
+ * The longest number of jiffies for which data is allowed to remain dirty
  */
 int dirty_expire_interval = 30 * HZ;
 
@@ -258,7 +257,7 @@
 /**
  * balance_dirty_pages_ratelimited_nr - balance dirty memory state
  * @mapping: address_space which was dirtied
- * @nr_pages: number of pages which the caller has just dirtied
+ * @nr_pages_dirtied: number of pages which the caller has just dirtied
  *
  * Processes which are dirtying memory should call in here once for each page
  * which was newly dirtied.  The function will periodically check the system's
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dc523a1..ea77c99 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -51,6 +51,7 @@
 EXPORT_SYMBOL(node_possible_map);
 unsigned long totalram_pages __read_mostly;
 unsigned long totalhigh_pages __read_mostly;
+unsigned long totalreserve_pages __read_mostly;
 long nr_swap_pages;
 int percpu_pagelist_fraction;
 
@@ -151,7 +152,8 @@
 			1 << PG_reclaim |
 			1 << PG_slab    |
 			1 << PG_swapcache |
-			1 << PG_writeback );
+			1 << PG_writeback |
+			1 << PG_buddy );
 	set_page_count(page, 0);
 	reset_page_mapcount(page);
 	page->mapping = NULL;
@@ -230,18 +232,20 @@
  * zone->lock is already acquired when we use these.
  * So, we don't need atomic page->flags operations here.
  */
-static inline unsigned long page_order(struct page *page) {
+static inline unsigned long page_order(struct page *page)
+{
 	return page_private(page);
 }
 
-static inline void set_page_order(struct page *page, int order) {
+static inline void set_page_order(struct page *page, int order)
+{
 	set_page_private(page, order);
-	__SetPagePrivate(page);
+	__SetPageBuddy(page);
 }
 
 static inline void rmv_page_order(struct page *page)
 {
-	__ClearPagePrivate(page);
+	__ClearPageBuddy(page);
 	set_page_private(page, 0);
 }
 
@@ -280,11 +284,13 @@
  * This function checks whether a page is free && is the buddy
  * we can do coalesce a page and its buddy if
  * (a) the buddy is not in a hole &&
- * (b) the buddy is free &&
- * (c) the buddy is on the buddy system &&
- * (d) a page and its buddy have the same order.
- * for recording page's order, we use page_private(page) and PG_private.
+ * (b) the buddy is in the buddy system &&
+ * (c) a page and its buddy have the same order.
  *
+ * For recording whether a page is in the buddy system, we use PG_buddy.
+ * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
+ *
+ * For recording page's order, we use page_private(page).
  */
 static inline int page_is_buddy(struct page *page, int order)
 {
@@ -293,11 +299,11 @@
 		return 0;
 #endif
 
-       if (PagePrivate(page)           &&
-           (page_order(page) == order) &&
-            page_count(page) == 0)
-               return 1;
-       return 0;
+	if (PageBuddy(page) && page_order(page) == order) {
+		BUG_ON(page_count(page) != 0);
+		return 1;
+	}
+	return 0;
 }
 
 /*
@@ -313,7 +319,7 @@
  * as necessary, plus some accounting needed to play nicely with other
  * parts of the VM system.
  * At each level, we keep a list of pages, which are heads of continuous
- * free pages of length of (1 << order) and marked with PG_Private.Page's
+ * free pages of length of (1 << order) and marked with PG_buddy. Page's
  * order is recorded in page_private(page) field.
  * So when we are allocating or freeing one, we can derive the state of the
  * other.  That is, if we allocate a small block, and both were   
@@ -376,7 +382,8 @@
 			1 << PG_slab	|
 			1 << PG_swapcache |
 			1 << PG_writeback |
-			1 << PG_reserved ))))
+			1 << PG_reserved |
+			1 << PG_buddy ))))
 		bad_page(page);
 	if (PageDirty(page))
 		__ClearPageDirty(page);
@@ -524,7 +531,8 @@
 			1 << PG_slab    |
 			1 << PG_swapcache |
 			1 << PG_writeback |
-			1 << PG_reserved ))))
+			1 << PG_reserved |
+			1 << PG_buddy ))))
 		bad_page(page);
 
 	/*
@@ -1954,7 +1962,7 @@
 	}
 }
 
-static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
+static int pageset_cpuup_callback(struct notifier_block *nfb,
 		unsigned long action,
 		void *hcpu)
 {
@@ -2472,6 +2480,38 @@
 }
 
 /*
+ * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio
+ *	or min_free_kbytes changes.
+ */
+static void calculate_totalreserve_pages(void)
+{
+	struct pglist_data *pgdat;
+	unsigned long reserve_pages = 0;
+	int i, j;
+
+	for_each_online_pgdat(pgdat) {
+		for (i = 0; i < MAX_NR_ZONES; i++) {
+			struct zone *zone = pgdat->node_zones + i;
+			unsigned long max = 0;
+
+			/* Find valid and maximum lowmem_reserve in the zone */
+			for (j = i; j < MAX_NR_ZONES; j++) {
+				if (zone->lowmem_reserve[j] > max)
+					max = zone->lowmem_reserve[j];
+			}
+
+			/* we treat pages_high as reserved pages. */
+			max += zone->pages_high;
+
+			if (max > zone->present_pages)
+				max = zone->present_pages;
+			reserve_pages += max;
+		}
+	}
+	totalreserve_pages = reserve_pages;
+}
+
+/*
  * setup_per_zone_lowmem_reserve - called whenever
  *	sysctl_lower_zone_reserve_ratio changes.  Ensures that each zone
  *	has a correct pages reserved value, so an adequate number of
@@ -2502,6 +2542,9 @@
 			}
 		}
 	}
+
+	/* update totalreserve_pages */
+	calculate_totalreserve_pages();
 }
 
 /*
@@ -2556,6 +2599,9 @@
 		zone->pages_high  = zone->pages_min + tmp / 2;
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
+
+	/* update totalreserve_pages */
+	calculate_totalreserve_pages();
 }
 
 /*
diff --git a/mm/shmem.c b/mm/shmem.c
index 37eaf42e..4c5e68e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -46,6 +46,8 @@
 #include <linux/mempolicy.h>
 #include <linux/namei.h>
 #include <linux/ctype.h>
+#include <linux/migrate.h>
+
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <asm/pgtable.h>
@@ -2173,6 +2175,7 @@
 	.prepare_write	= shmem_prepare_write,
 	.commit_write	= simple_commit_write,
 #endif
+	.migratepage	= migrate_page,
 };
 
 static struct file_operations shmem_file_operations = {
diff --git a/mm/slab.c b/mm/slab.c
index 4cbf8bb..c32af7e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -420,6 +420,7 @@
 	unsigned long max_freeable;
 	unsigned long node_allocs;
 	unsigned long node_frees;
+	unsigned long node_overflow;
 	atomic_t allochit;
 	atomic_t allocmiss;
 	atomic_t freehit;
@@ -465,6 +466,7 @@
 #define	STATS_INC_ERR(x)	((x)->errors++)
 #define	STATS_INC_NODEALLOCS(x)	((x)->node_allocs++)
 #define	STATS_INC_NODEFREES(x)	((x)->node_frees++)
+#define STATS_INC_ACOVERFLOW(x)   ((x)->node_overflow++)
 #define	STATS_SET_FREEABLE(x, i)					\
 	do {								\
 		if ((x)->max_freeable < i)				\
@@ -484,6 +486,7 @@
 #define	STATS_INC_ERR(x)	do { } while (0)
 #define	STATS_INC_NODEALLOCS(x)	do { } while (0)
 #define	STATS_INC_NODEFREES(x)	do { } while (0)
+#define STATS_INC_ACOVERFLOW(x)   do { } while (0)
 #define	STATS_SET_FREEABLE(x, i) do { } while (0)
 #define STATS_INC_ALLOCHIT(x)	do { } while (0)
 #define STATS_INC_ALLOCMISS(x)	do { } while (0)
@@ -976,7 +979,8 @@
 		 * That way we could avoid the overhead of putting the objects
 		 * into the free lists and getting them back later.
 		 */
-		transfer_objects(rl3->shared, ac, ac->limit);
+		if (rl3->shared)
+			transfer_objects(rl3->shared, ac, ac->limit);
 
 		free_block(cachep, ac->entry, ac->avail, node);
 		ac->avail = 0;
@@ -1033,7 +1037,7 @@
 
 #endif
 
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int cpuup_callback(struct notifier_block *nfb,
 				    unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -1297,8 +1301,7 @@
 		if (cache_cache.num)
 			break;
 	}
-	if (!cache_cache.num)
-		BUG();
+	BUG_ON(!cache_cache.num);
 	cache_cache.gfporder = order;
 	cache_cache.colour = left_over / cache_cache.colour_off;
 	cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
@@ -1454,7 +1457,14 @@
 	int i;
 
 	flags |= cachep->gfpflags;
+#ifndef CONFIG_MMU
+	/* nommu uses slab's for process anonymous memory allocations, so
+	 * requires __GFP_COMP to properly refcount higher order allocations"
+	 */
+	page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder);
+#else
 	page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+#endif
 	if (!page)
 		return NULL;
 	addr = page_address(page);
@@ -1974,8 +1984,7 @@
 	 * Always checks flags, a caller might be expecting debug support which
 	 * isn't available.
 	 */
-	if (flags & ~CREATE_MASK)
-		BUG();
+	BUG_ON(flags & ~CREATE_MASK);
 
 	/*
 	 * Check that size is in terms of words.  This is needed to avoid
@@ -2206,8 +2215,7 @@
 
 		slabp = list_entry(l3->slabs_free.prev, struct slab, list);
 #if DEBUG
-		if (slabp->inuse)
-			BUG();
+		BUG_ON(slabp->inuse);
 #endif
 		list_del(&slabp->list);
 
@@ -2248,8 +2256,7 @@
  */
 int kmem_cache_shrink(struct kmem_cache *cachep)
 {
-	if (!cachep || in_interrupt())
-		BUG();
+	BUG_ON(!cachep || in_interrupt());
 
 	return __cache_shrink(cachep);
 }
@@ -2277,8 +2284,7 @@
 	int i;
 	struct kmem_list3 *l3;
 
-	if (!cachep || in_interrupt())
-		BUG();
+	BUG_ON(!cachep || in_interrupt());
 
 	/* Don't let CPUs to come and go */
 	lock_cpu_hotplug();
@@ -2323,13 +2329,15 @@
 
 /* Get the memory for a slab management obj. */
 static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,
-				   int colour_off, gfp_t local_flags)
+				   int colour_off, gfp_t local_flags,
+				   int nodeid)
 {
 	struct slab *slabp;
 
 	if (OFF_SLAB(cachep)) {
 		/* Slab management obj is off-slab. */
-		slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
+		slabp = kmem_cache_alloc_node(cachep->slabp_cache,
+					      local_flags, nodeid);
 		if (!slabp)
 			return NULL;
 	} else {
@@ -2339,6 +2347,7 @@
 	slabp->inuse = 0;
 	slabp->colouroff = colour_off;
 	slabp->s_mem = objp + colour_off;
+	slabp->nodeid = nodeid;
 	return slabp;
 }
 
@@ -2477,8 +2486,7 @@
 	 * Be lazy and only check for valid flags here,  keeping it out of the
 	 * critical path in kmem_cache_alloc().
 	 */
-	if (flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW))
-		BUG();
+	BUG_ON(flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW));
 	if (flags & SLAB_NO_GROW)
 		return 0;
 
@@ -2525,7 +2533,7 @@
 		goto failed;
 
 	/* Get slab management. */
-	slabp = alloc_slabmgmt(cachep, objp, offset, local_flags);
+	slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid);
 	if (!slabp)
 		goto opps1;
 
@@ -3086,9 +3094,11 @@
 			if (l3->alien && l3->alien[nodeid]) {
 				alien = l3->alien[nodeid];
 				spin_lock(&alien->lock);
-				if (unlikely(alien->avail == alien->limit))
+				if (unlikely(alien->avail == alien->limit)) {
+					STATS_INC_ACOVERFLOW(cachep);
 					__drain_alien_cache(cachep,
 							    alien, nodeid);
+				}
 				alien->entry[alien->avail++] = objp;
 				spin_unlock(&alien->lock);
 			} else {
@@ -3766,7 +3776,7 @@
 	seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
 #if STATS
 	seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
-		 "<error> <maxfreeable> <nodeallocs> <remotefrees>");
+		 "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
 	seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
 #endif
 	seq_putc(m, '\n');
@@ -3880,11 +3890,12 @@
 		unsigned long max_freeable = cachep->max_freeable;
 		unsigned long node_allocs = cachep->node_allocs;
 		unsigned long node_frees = cachep->node_frees;
+		unsigned long overflows = cachep->node_overflow;
 
 		seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
-				%4lu %4lu %4lu %4lu", allocs, high, grown,
+				%4lu %4lu %4lu %4lu %4lu", allocs, high, grown,
 				reaped, errors, max_freeable, node_allocs,
-				node_frees);
+				node_frees, overflows);
 	}
 	/* cpu stats */
 	{
diff --git a/mm/slob.c b/mm/slob.c
index 9bcc7e2..a68255b 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -354,9 +354,7 @@
 	if (!pdata)
 		return NULL;
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_possible_cpu(i) {
 		pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
 		if (!pdata->ptrs[i])
 			goto unwind_oom;
@@ -383,11 +381,9 @@
 	int i;
 	struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_possible_cpu(i)
 		kfree(p->ptrs[i]);
-	}
+
 	kfree(p);
 }
 EXPORT_SYMBOL(free_percpu);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index d7af296..e0e1583 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -148,8 +148,7 @@
 	swp_entry_t entry;
 	int err;
 
-	if (!PageLocked(page))
-		BUG();
+	BUG_ON(!PageLocked(page));
 
 	for (;;) {
 		entry = get_swap_page();
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 729eb3e..c0504f1 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -321,8 +321,7 @@
 		int i;
 
 		for (i = 0; i < area->nr_pages; i++) {
-			if (unlikely(!area->pages[i]))
-				BUG();
+			BUG_ON(!area->pages[i]);
 			__free_page(area->pages[i]);
 		}
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index acdf001..4649a63 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1328,7 +1328,7 @@
    not required for correctness.  So if the last cpu in a node goes
    away, we get changed to run anywhere: as the first one comes back,
    restore their cpu bindings. */
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int cpu_callback(struct notifier_block *nfb,
 				  unsigned long action, void *hcpu)
 {
 	pg_data_t *pgdat;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 3ab4e79..1a786bf 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -2,7 +2,6 @@
 
 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
-
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -54,24 +53,24 @@
 static struct atm_vcc *atmarpd;
 static struct neigh_table clip_tbl;
 static struct timer_list idle_timer;
-static int start_timer = 1;
 
-
-static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
+static int to_atmarpd(enum atmarp_ctrl_type type, int itf, unsigned long ip)
 {
 	struct sock *sk;
 	struct atmarp_ctrl *ctrl;
 	struct sk_buff *skb;
 
-	DPRINTK("to_atmarpd(%d)\n",type);
-	if (!atmarpd) return -EUNATCH;
+	DPRINTK("to_atmarpd(%d)\n", type);
+	if (!atmarpd)
+		return -EUNATCH;
 	skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
-	if (!skb) return -ENOMEM;
+	if (!skb)
+		return -ENOMEM;
 	ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
 	ctrl->type = type;
 	ctrl->itf_num = itf;
 	ctrl->ip = ip;
-	atm_force_charge(atmarpd,skb->truesize);
+	atm_force_charge(atmarpd, skb->truesize);
 
 	sk = sk_atm(atmarpd);
 	skb_queue_tail(&sk->sk_receive_queue, skb);
@@ -79,26 +78,24 @@
 	return 0;
 }
 
-
-static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry)
+static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
 {
-	DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry,
-	    entry->neigh);
+	DPRINTK("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
+		entry->neigh);
 	clip_vcc->entry = entry;
-	clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */
+	clip_vcc->xoff = 0;	/* @@@ may overrun buffer by one packet */
 	clip_vcc->next = entry->vccs;
 	entry->vccs = clip_vcc;
 	entry->neigh->used = jiffies;
 }
 
-
 static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
 {
 	struct atmarp_entry *entry = clip_vcc->entry;
 	struct clip_vcc **walk;
 
 	if (!entry) {
-		printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
+		printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
 		return;
 	}
 	spin_lock_bh(&entry->neigh->dev->xmit_lock);	/* block clip_start_xmit() */
@@ -107,24 +104,24 @@
 		if (*walk == clip_vcc) {
 			int error;
 
-			*walk = clip_vcc->next; /* atomic */
+			*walk = clip_vcc->next;	/* atomic */
 			clip_vcc->entry = NULL;
 			if (clip_vcc->xoff)
 				netif_wake_queue(entry->neigh->dev);
 			if (entry->vccs)
 				goto out;
-			entry->expires = jiffies-1;
-				/* force resolution or expiration */
+			entry->expires = jiffies - 1;
+			/* force resolution or expiration */
 			error = neigh_update(entry->neigh, NULL, NUD_NONE,
 					     NEIGH_UPDATE_F_ADMIN);
 			if (error)
 				printk(KERN_CRIT "unlink_clip_vcc: "
-				    "neigh_update failed with %d\n",error);
+				       "neigh_update failed with %d\n", error);
 			goto out;
 		}
 	printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
-	  "0x%p)\n",entry,clip_vcc);
-out:
+	       "0x%p)\n", entry, clip_vcc);
+      out:
 	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
 }
 
@@ -153,13 +150,13 @@
 		DPRINTK("destruction postponed with ref %d\n",
 			atomic_read(&n->refcnt));
 
-		while ((skb = skb_dequeue(&n->arp_queue)) != NULL) 
+		while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
 			dev_kfree_skb(skb);
 
 		return 0;
 	}
 
-	DPRINTK("expired neigh %p\n",n);
+	DPRINTK("expired neigh %p\n", n);
 	return 1;
 }
 
@@ -167,7 +164,7 @@
 {
 	write_lock(&clip_tbl.lock);
 	__neigh_for_each_release(&clip_tbl, neigh_check_cb);
-	mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+	mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
 	write_unlock(&clip_tbl.lock);
 }
 
@@ -177,13 +174,13 @@
 
 	DPRINTK("clip_arp_rcv\n");
 	vcc = ATM_SKB(skb)->vcc;
-	if (!vcc || !atm_charge(vcc,skb->truesize)) {
+	if (!vcc || !atm_charge(vcc, skb->truesize)) {
 		dev_kfree_skb_any(skb);
 		return 0;
 	}
-	DPRINTK("pushing to %p\n",vcc);
-	DPRINTK("using %p\n",CLIP_VCC(vcc)->old_push);
-	CLIP_VCC(vcc)->old_push(vcc,skb);
+	DPRINTK("pushing to %p\n", vcc);
+	DPRINTK("using %p\n", CLIP_VCC(vcc)->old_push);
+	CLIP_VCC(vcc)->old_push(vcc, skb);
 	return 0;
 }
 
@@ -193,34 +190,38 @@
 	0x03,	/* Ctrl: Unnumbered Information Command PDU */
 	0x00,	/* OUI: EtherType */
 	0x00,
-	0x00 };
+	0x00
+};
 
-static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
 
 	DPRINTK("clip push\n");
 	if (!skb) {
-		DPRINTK("removing VCC %p\n",clip_vcc);
-		if (clip_vcc->entry) unlink_clip_vcc(clip_vcc);
-		clip_vcc->old_push(vcc,NULL); /* pass on the bad news */
+		DPRINTK("removing VCC %p\n", clip_vcc);
+		if (clip_vcc->entry)
+			unlink_clip_vcc(clip_vcc);
+		clip_vcc->old_push(vcc, NULL);	/* pass on the bad news */
 		kfree(clip_vcc);
 		return;
 	}
-	atm_return(vcc,skb->truesize);
+	atm_return(vcc, skb->truesize);
 	skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
-		/* clip_vcc->entry == NULL if we don't have an IP address yet */
+	/* clip_vcc->entry == NULL if we don't have an IP address yet */
 	if (!skb->dev) {
 		dev_kfree_skb_any(skb);
 		return;
 	}
 	ATM_SKB(skb)->vcc = vcc;
 	skb->mac.raw = skb->data;
-	if (!clip_vcc->encap || skb->len < RFC1483LLC_LEN || memcmp(skb->data,
-	    llc_oui,sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP);
+	if (!clip_vcc->encap
+	    || skb->len < RFC1483LLC_LEN
+	    || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
+		skb->protocol = htons(ETH_P_IP);
 	else {
 		skb->protocol = ((u16 *) skb->data)[3];
-		skb_pull(skb,RFC1483LLC_LEN);
+		skb_pull(skb, RFC1483LLC_LEN);
 		if (skb->protocol == htons(ETH_P_ARP)) {
 			PRIV(skb->dev)->stats.rx_packets++;
 			PRIV(skb->dev)->stats.rx_bytes += skb->len;
@@ -235,58 +236,54 @@
 	netif_rx(skb);
 }
 
-
 /*
  * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
  * clip_pop is atomic with respect to the critical section in clip_start_xmit.
  */
 
-
-static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
 	struct net_device *dev = skb->dev;
 	int old;
 	unsigned long flags;
 
-	DPRINTK("clip_pop(vcc %p)\n",vcc);
-	clip_vcc->old_pop(vcc,skb);
+	DPRINTK("clip_pop(vcc %p)\n", vcc);
+	clip_vcc->old_pop(vcc, skb);
 	/* skb->dev == NULL in outbound ARP packets */
-	if (!dev) return;
-	spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
-	if (atm_may_send(vcc,0)) {
-		old = xchg(&clip_vcc->xoff,0);
-		if (old) netif_wake_queue(dev);
+	if (!dev)
+		return;
+	spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
+	if (atm_may_send(vcc, 0)) {
+		old = xchg(&clip_vcc->xoff, 0);
+		if (old)
+			netif_wake_queue(dev);
 	}
-	spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
+	spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
 }
 
-
 static void clip_neigh_destroy(struct neighbour *neigh)
 {
-	DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh);
+	DPRINTK("clip_neigh_destroy (neigh %p)\n", neigh);
 	if (NEIGH2ENTRY(neigh)->vccs)
 		printk(KERN_CRIT "clip_neigh_destroy: vccs != NULL !!!\n");
 	NEIGH2ENTRY(neigh)->vccs = (void *) 0xdeadbeef;
 }
 
-
-static void clip_neigh_solicit(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n",neigh,skb);
-	to_atmarpd(act_need,PRIV(neigh->dev)->number,NEIGH2ENTRY(neigh)->ip);
+	DPRINTK("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
+	to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
 }
 
-
-static void clip_neigh_error(struct neighbour *neigh,struct sk_buff *skb)
+static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
 {
 #ifndef CONFIG_ATM_CLIP_NO_ICMP
-	icmp_send(skb,ICMP_DEST_UNREACH,ICMP_HOST_UNREACH,0);
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
 #endif
 	kfree_skb(skb);
 }
 
-
 static struct neigh_ops clip_neigh_ops = {
 	.family =		AF_INET,
 	.solicit =		clip_neigh_solicit,
@@ -297,7 +294,6 @@
 	.queue_xmit =		dev_queue_xmit,
 };
 
-
 static int clip_constructor(struct neighbour *neigh)
 {
 	struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
@@ -305,9 +301,10 @@
 	struct in_device *in_dev;
 	struct neigh_parms *parms;
 
-	DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
+	DPRINTK("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
 	neigh->type = inet_addr_type(entry->ip);
-	if (neigh->type != RTN_UNICAST) return -EINVAL;
+	if (neigh->type != RTN_UNICAST)
+		return -EINVAL;
 
 	rcu_read_lock();
 	in_dev = __in_dev_get_rcu(dev);
@@ -326,13 +323,13 @@
 	    neigh->ops->connected_output : neigh->ops->output;
 	entry->neigh = neigh;
 	entry->vccs = NULL;
-	entry->expires = jiffies-1;
+	entry->expires = jiffies - 1;
 	return 0;
 }
 
 static u32 clip_hash(const void *pkey, const struct net_device *dev)
 {
-	return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
+	return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
 }
 
 static struct neigh_table clip_tbl = {
@@ -366,7 +363,6 @@
 	.gc_thresh3 	= 1024,
 };
 
-
 /* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
 
 /*
@@ -376,15 +372,13 @@
  * clip_setentry.
  */
 
-
-static int clip_encap(struct atm_vcc *vcc,int mode)
+static int clip_encap(struct atm_vcc *vcc, int mode)
 {
 	CLIP_VCC(vcc)->encap = mode;
 	return 0;
 }
 
-
-static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
+static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct clip_priv *clip_priv = PRIV(dev);
 	struct atmarp_entry *entry;
@@ -392,7 +386,7 @@
 	int old;
 	unsigned long flags;
 
-	DPRINTK("clip_start_xmit (skb %p)\n",skb);
+	DPRINTK("clip_start_xmit (skb %p)\n", skb);
 	if (!skb->dst) {
 		printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
 		dev_kfree_skb(skb);
@@ -401,9 +395,9 @@
 	}
 	if (!skb->dst->neighbour) {
 #if 0
-		skb->dst->neighbour = clip_find_neighbour(skb->dst,1);
+		skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
 		if (!skb->dst->neighbour) {
-			dev_kfree_skb(skb); /* lost that one */
+			dev_kfree_skb(skb);	/* lost that one */
 			clip_priv->stats.tx_dropped++;
 			return 0;
 		}
@@ -417,73 +411,73 @@
 	if (!entry->vccs) {
 		if (time_after(jiffies, entry->expires)) {
 			/* should be resolved */
-			entry->expires = jiffies+ATMARP_RETRY_DELAY*HZ;
-			to_atmarpd(act_need,PRIV(dev)->number,entry->ip);
+			entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
+			to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
 		}
 		if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
-			skb_queue_tail(&entry->neigh->arp_queue,skb);
+			skb_queue_tail(&entry->neigh->arp_queue, skb);
 		else {
 			dev_kfree_skb(skb);
 			clip_priv->stats.tx_dropped++;
 		}
 		return 0;
 	}
-	DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs);
+	DPRINTK("neigh %p, vccs %p\n", entry, entry->vccs);
 	ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
-	DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc);
+	DPRINTK("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
 	if (entry->vccs->encap) {
 		void *here;
 
-		here = skb_push(skb,RFC1483LLC_LEN);
-		memcpy(here,llc_oui,sizeof(llc_oui));
+		here = skb_push(skb, RFC1483LLC_LEN);
+		memcpy(here, llc_oui, sizeof(llc_oui));
 		((u16 *) here)[3] = skb->protocol;
 	}
 	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
-	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
-	old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */
+	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
+	old = xchg(&entry->vccs->xoff, 1);	/* assume XOFF ... */
 	if (old) {
 		printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
 		return 0;
 	}
 	clip_priv->stats.tx_packets++;
 	clip_priv->stats.tx_bytes += skb->len;
-	(void) vcc->send(vcc,skb);
-	if (atm_may_send(vcc,0)) {
+	vcc->send(vcc, skb);
+	if (atm_may_send(vcc, 0)) {
 		entry->vccs->xoff = 0;
 		return 0;
 	}
-	spin_lock_irqsave(&clip_priv->xoff_lock,flags);
-	netif_stop_queue(dev); /* XOFF -> throttle immediately */
+	spin_lock_irqsave(&clip_priv->xoff_lock, flags);
+	netif_stop_queue(dev);	/* XOFF -> throttle immediately */
 	barrier();
 	if (!entry->vccs->xoff)
 		netif_start_queue(dev);
-		/* Oh, we just raced with clip_pop. netif_start_queue should be
-		   good enough, because nothing should really be asleep because
-		   of the brief netif_stop_queue. If this isn't true or if it
-		   changes, use netif_wake_queue instead. */
-	spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
+	/* Oh, we just raced with clip_pop. netif_start_queue should be
+	   good enough, because nothing should really be asleep because
+	   of the brief netif_stop_queue. If this isn't true or if it
+	   changes, use netif_wake_queue instead. */
+	spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
 	return 0;
 }
 
-
 static struct net_device_stats *clip_get_stats(struct net_device *dev)
 {
 	return &PRIV(dev)->stats;
 }
 
-
-static int clip_mkip(struct atm_vcc *vcc,int timeout)
+static int clip_mkip(struct atm_vcc *vcc, int timeout)
 {
 	struct clip_vcc *clip_vcc;
 	struct sk_buff_head copy;
 	struct sk_buff *skb;
 
-	if (!vcc->push) return -EBADFD;
-	clip_vcc = kmalloc(sizeof(struct clip_vcc),GFP_KERNEL);
-	if (!clip_vcc) return -ENOMEM;
-	DPRINTK("mkip clip_vcc %p vcc %p\n",clip_vcc,vcc);
+	if (!vcc->push)
+		return -EBADFD;
+	clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
+	if (!clip_vcc)
+		return -ENOMEM;
+	DPRINTK("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
 	clip_vcc->vcc = vcc;
 	vcc->user_back = clip_vcc;
 	set_bit(ATM_VF_IS_CLIP, &vcc->flags);
@@ -491,7 +485,7 @@
 	clip_vcc->xoff = 0;
 	clip_vcc->encap = 1;
 	clip_vcc->last_use = jiffies;
-	clip_vcc->idle_timeout = timeout*HZ;
+	clip_vcc->idle_timeout = timeout * HZ;
 	clip_vcc->old_push = vcc->push;
 	clip_vcc->old_pop = vcc->pop;
 	vcc->push = clip_push;
@@ -501,27 +495,25 @@
 	/* re-process everything received between connection setup and MKIP */
 	while ((skb = skb_dequeue(&copy)) != NULL)
 		if (!clip_devs) {
-			atm_return(vcc,skb->truesize);
+			atm_return(vcc, skb->truesize);
 			kfree_skb(skb);
-		}
-		else {
+		} else {
 			unsigned int len = skb->len;
 
-			clip_push(vcc,skb);
+			clip_push(vcc, skb);
 			PRIV(skb->dev)->stats.rx_packets--;
 			PRIV(skb->dev)->stats.rx_bytes -= len;
 		}
 	return 0;
 }
 
-
-static int clip_setentry(struct atm_vcc *vcc,u32 ip)
+static int clip_setentry(struct atm_vcc *vcc, u32 ip)
 {
 	struct neighbour *neigh;
 	struct atmarp_entry *entry;
 	int error;
 	struct clip_vcc *clip_vcc;
-	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
+	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
 	struct rtable *rt;
 
 	if (vcc->push != clip_push) {
@@ -538,28 +530,29 @@
 		unlink_clip_vcc(clip_vcc);
 		return 0;
 	}
-	error = ip_route_output_key(&rt,&fl);
-	if (error) return error;
-	neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
+	error = ip_route_output_key(&rt, &fl);
+	if (error)
+		return error;
+	neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
 	ip_rt_put(rt);
 	if (!neigh)
 		return -ENOMEM;
 	entry = NEIGH2ENTRY(neigh);
 	if (entry != clip_vcc->entry) {
-		if (!clip_vcc->entry) DPRINTK("setentry: add\n");
+		if (!clip_vcc->entry)
+			DPRINTK("setentry: add\n");
 		else {
 			DPRINTK("setentry: update\n");
 			unlink_clip_vcc(clip_vcc);
 		}
-		link_vcc(clip_vcc,entry);
+		link_vcc(clip_vcc, entry);
 	}
-	error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 
-			     NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
+	error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
+			     NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
 	neigh_release(neigh);
 	return error;
 }
 
-
 static void clip_setup(struct net_device *dev)
 {
 	dev->hard_start_xmit = clip_start_xmit;
@@ -568,15 +561,14 @@
 	dev->type = ARPHRD_ATM;
 	dev->hard_header_len = RFC1483LLC_LEN;
 	dev->mtu = RFC1626_MTU;
-	dev->tx_queue_len = 100; /* "normal" queue (packets) */
-	    /* When using a "real" qdisc, the qdisc determines the queue */
-	    /* length. tx_queue_len is only used for the default case, */
-	    /* without any more elaborate queuing. 100 is a reasonable */
-	    /* compromise between decent burst-tolerance and protection */
-	    /* against memory hogs. */
+	dev->tx_queue_len = 100;	/* "normal" queue (packets) */
+	/* When using a "real" qdisc, the qdisc determines the queue */
+	/* length. tx_queue_len is only used for the default case, */
+	/* without any more elaborate queuing. 100 is a reasonable */
+	/* compromise between decent burst-tolerance and protection */
+	/* against memory hogs. */
 }
 
-
 static int clip_create(int number)
 {
 	struct net_device *dev;
@@ -585,19 +577,19 @@
 
 	if (number != -1) {
 		for (dev = clip_devs; dev; dev = PRIV(dev)->next)
-			if (PRIV(dev)->number == number) return -EEXIST;
-	}
-	else {
+			if (PRIV(dev)->number == number)
+				return -EEXIST;
+	} else {
 		number = 0;
 		for (dev = clip_devs; dev; dev = PRIV(dev)->next)
 			if (PRIV(dev)->number >= number)
-				number = PRIV(dev)->number+1;
+				number = PRIV(dev)->number + 1;
 	}
 	dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
 	if (!dev)
 		return -ENOMEM;
 	clip_priv = PRIV(dev);
-	sprintf(dev->name,"atm%d",number);
+	sprintf(dev->name, "atm%d", number);
 	spin_lock_init(&clip_priv->xoff_lock);
 	clip_priv->number = number;
 	error = register_netdev(dev);
@@ -607,53 +599,48 @@
 	}
 	clip_priv->next = clip_devs;
 	clip_devs = dev;
-	DPRINTK("registered (net:%s)\n",dev->name);
+	DPRINTK("registered (net:%s)\n", dev->name);
 	return number;
 }
 
-
-static int clip_device_event(struct notifier_block *this,unsigned long event,
-    void *dev)
+static int clip_device_event(struct notifier_block *this, unsigned long event,
+			     void *arg)
 {
-	/* ignore non-CLIP devices */
-	if (((struct net_device *) dev)->type != ARPHRD_ATM ||
-	    ((struct net_device *) dev)->hard_start_xmit != clip_start_xmit)
+	struct net_device *dev = arg;
+
+	if (event == NETDEV_UNREGISTER) {
+		neigh_ifdown(&clip_tbl, dev);
 		return NOTIFY_DONE;
+	}
+
+	/* ignore non-CLIP devices */
+	if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
+		return NOTIFY_DONE;
+
 	switch (event) {
-		case NETDEV_UP:
-			DPRINTK("clip_device_event NETDEV_UP\n");
-			(void) to_atmarpd(act_up,PRIV(dev)->number,0);
-			break;
-		case NETDEV_GOING_DOWN:
-			DPRINTK("clip_device_event NETDEV_DOWN\n");
-			(void) to_atmarpd(act_down,PRIV(dev)->number,0);
-			break;
-		case NETDEV_CHANGE:
-		case NETDEV_CHANGEMTU:
-			DPRINTK("clip_device_event NETDEV_CHANGE*\n");
-			(void) to_atmarpd(act_change,PRIV(dev)->number,0);
-			break;
-		case NETDEV_REBOOT:
-		case NETDEV_REGISTER:
-		case NETDEV_DOWN:
-			DPRINTK("clip_device_event %ld\n",event);
-			/* ignore */
-			break;
-		default:
-			printk(KERN_WARNING "clip_device_event: unknown event "
-			    "%ld\n",event);
-			break;
+	case NETDEV_UP:
+		DPRINTK("clip_device_event NETDEV_UP\n");
+		to_atmarpd(act_up, PRIV(dev)->number, 0);
+		break;
+	case NETDEV_GOING_DOWN:
+		DPRINTK("clip_device_event NETDEV_DOWN\n");
+		to_atmarpd(act_down, PRIV(dev)->number, 0);
+		break;
+	case NETDEV_CHANGE:
+	case NETDEV_CHANGEMTU:
+		DPRINTK("clip_device_event NETDEV_CHANGE*\n");
+		to_atmarpd(act_change, PRIV(dev)->number, 0);
+		break;
 	}
 	return NOTIFY_DONE;
 }
 
-
-static int clip_inet_event(struct notifier_block *this,unsigned long event,
-    void *ifa)
+static int clip_inet_event(struct notifier_block *this, unsigned long event,
+			   void *ifa)
 {
 	struct in_device *in_dev;
 
-	in_dev = ((struct in_ifaddr *) ifa)->ifa_dev;
+	in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
 	if (!in_dev || !in_dev->dev) {
 		printk(KERN_WARNING "clip_inet_event: no device\n");
 		return NOTIFY_DONE;
@@ -662,23 +649,20 @@
 	 * Transitions are of the down-change-up type, so it's sufficient to
 	 * handle the change on up.
 	 */
-	if (event != NETDEV_UP) return NOTIFY_DONE;
-	return clip_device_event(this,NETDEV_CHANGE,in_dev->dev);
+	if (event != NETDEV_UP)
+		return NOTIFY_DONE;
+	return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
 }
 
 
 static struct notifier_block clip_dev_notifier = {
-	clip_device_event,
-	NULL,
-	0
+	.notifier_call = clip_device_event,
 };
 
 
 
 static struct notifier_block clip_inet_notifier = {
-	clip_inet_event,
-	NULL,
-	0
+	.notifier_call = clip_inet_event,
 };
 
 
@@ -686,14 +670,12 @@
 static void atmarpd_close(struct atm_vcc *vcc)
 {
 	DPRINTK("atmarpd_close\n");
-	atmarpd = NULL; /* assumed to be atomic */
-	barrier();
-	unregister_inetaddr_notifier(&clip_inet_notifier);
-	unregister_netdevice_notifier(&clip_dev_notifier);
-	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
-		printk(KERN_ERR "atmarpd_close: closing with requests "
-		    "pending\n");
+
+	rtnl_lock();
+	atmarpd = NULL;
 	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
+	rtnl_unlock();
+
 	DPRINTK("(done)\n");
 	module_put(THIS_MODULE);
 }
@@ -714,14 +696,14 @@
 
 static int atm_init_atmarp(struct atm_vcc *vcc)
 {
-	if (atmarpd) return -EADDRINUSE;
-	if (start_timer) {
-		start_timer = 0;
-		init_timer(&idle_timer);
-		idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ;
-		idle_timer.function = idle_timer_check;
-		add_timer(&idle_timer);
+	rtnl_lock();
+	if (atmarpd) {
+		rtnl_unlock();
+		return -EADDRINUSE;
 	}
+
+	mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
+
 	atmarpd = vcc;
 	set_bit(ATM_VF_META,&vcc->flags);
 	set_bit(ATM_VF_READY,&vcc->flags);
@@ -731,10 +713,7 @@
 	vcc->push = NULL;
 	vcc->pop = NULL; /* crash */
 	vcc->push_oam = NULL; /* crash */
-	if (register_netdevice_notifier(&clip_dev_notifier))
-		printk(KERN_ERR "register_netdevice_notifier failed\n");
-	if (register_inetaddr_notifier(&clip_inet_notifier))
-		printk(KERN_ERR "register_inetaddr_notifier failed\n");
+	rtnl_unlock();
 	return 0;
 }
 
@@ -744,53 +723,53 @@
 	int err = 0;
 
 	switch (cmd) {
-		case SIOCMKCLIP:
-		case ATMARPD_CTRL:
-		case ATMARP_MKIP:
-		case ATMARP_SETENTRY:
-		case ATMARP_ENCAP:
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			break;
-		default:
-			return -ENOIOCTLCMD;
+	case SIOCMKCLIP:
+	case ATMARPD_CTRL:
+	case ATMARP_MKIP:
+	case ATMARP_SETENTRY:
+	case ATMARP_ENCAP:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		break;
+	default:
+		return -ENOIOCTLCMD;
 	}
 
 	switch (cmd) {
-		case SIOCMKCLIP:
-			err = clip_create(arg);
-			break;
-		case ATMARPD_CTRL:
-			err = atm_init_atmarp(vcc);
-			if (!err) {
-				sock->state = SS_CONNECTED;
-				__module_get(THIS_MODULE);
-			}
-			break;
-		case ATMARP_MKIP:
-			err = clip_mkip(vcc ,arg);
-			break;
-		case ATMARP_SETENTRY:
-			err = clip_setentry(vcc, arg);
-			break;
-		case ATMARP_ENCAP:
-			err = clip_encap(vcc, arg);
-			break;
+	case SIOCMKCLIP:
+		err = clip_create(arg);
+		break;
+	case ATMARPD_CTRL:
+		err = atm_init_atmarp(vcc);
+		if (!err) {
+			sock->state = SS_CONNECTED;
+			__module_get(THIS_MODULE);
+		}
+		break;
+	case ATMARP_MKIP:
+		err = clip_mkip(vcc, arg);
+		break;
+	case ATMARP_SETENTRY:
+		err = clip_setentry(vcc, arg);
+		break;
+	case ATMARP_ENCAP:
+		err = clip_encap(vcc, arg);
+		break;
 	}
 	return err;
 }
 
 static struct atm_ioctl clip_ioctl_ops = {
-	.owner 	= THIS_MODULE,
-	.ioctl	= clip_ioctl,
+	.owner = THIS_MODULE,
+	.ioctl = clip_ioctl,
 };
 
 #ifdef CONFIG_PROC_FS
 
 static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
 {
-	static int code[] = { 1,2,10,6,1,0 };
-	static int e164[] = { 1,8,4,6,1,0 };
+	static int code[] = { 1, 2, 10, 6, 1, 0 };
+	static int e164[] = { 1, 8, 4, 6, 1, 0 };
 
 	if (*addr->sas_addr.pub) {
 		seq_printf(seq, "%s", addr->sas_addr.pub);
@@ -809,7 +788,7 @@
 		for (i = 0; fields[i]; i++) {
 			for (j = fields[i]; j; j--)
 				seq_printf(seq, "%02X", *prv++);
-			if (fields[i+1])
+			if (fields[i + 1])
 				seq_putc(seq, '.');
 		}
 	}
@@ -828,8 +807,7 @@
 	svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
 	       (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
 
-	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
-	       clip_vcc->encap);
+	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
 
 	if (clip_vcc == SEQ_NO_VCC_TOKEN)
 		exp = entry->neigh->used;
@@ -839,10 +817,7 @@
 	exp = (jiffies - exp) / HZ;
 
 	seq_printf(seq, "%-6s%-4s%-4s%5ld ",
-		   dev->name,
-		   svc ? "SVC" : "PVC",
-		   llc ? "LLC" : "NULL",
-		   exp);
+		   dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
 
 	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
 			NIPQUAD(entry->ip));
@@ -860,8 +835,7 @@
 	} else if (!svc) {
 		seq_printf(seq, "%d.%d.%d\n",
 			   clip_vcc->vcc->dev->number,
-			   clip_vcc->vcc->vpi,
-			   clip_vcc->vcc->vci);
+			   clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
 	} else {
 		svc_addr(seq, &clip_vcc->vcc->remote);
 		seq_putc(seq, '\n');
@@ -894,7 +868,7 @@
 }
 
 static void *clip_seq_vcc_walk(struct clip_seq_state *state,
-			       struct atmarp_entry *e, loff_t *pos)
+			       struct atmarp_entry *e, loff_t * pos)
 {
 	struct clip_vcc *vcc = state->vcc;
 
@@ -911,24 +885,24 @@
 
 	return vcc;
 }
-  
+
 static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
-			       struct neighbour *n, loff_t *pos)
+			       struct neighbour *n, loff_t * pos)
 {
-	struct clip_seq_state *state = (struct clip_seq_state *) _state;
+	struct clip_seq_state *state = (struct clip_seq_state *)_state;
 
 	return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
 }
 
-static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
+static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
 {
 	return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
 }
 
 static int clip_seq_show(struct seq_file *seq, void *v)
 {
-	static char atm_arp_banner[] = 
-		"IPitf TypeEncp Idle IP address      ATM address\n";
+	static char atm_arp_banner[] =
+	    "IPitf TypeEncp Idle IP address      ATM address\n";
 
 	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, atm_arp_banner);
@@ -939,7 +913,7 @@
 
 		atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
 	}
-  	return 0;
+	return 0;
 }
 
 static struct seq_operations arp_seq_ops = {
@@ -988,20 +962,19 @@
 
 static int __init atm_clip_init(void)
 {
+	struct proc_dir_entry *p;
 	neigh_table_init(&clip_tbl);
 
 	clip_tbl_hook = &clip_tbl;
 	register_atm_ioctl(&clip_ioctl_ops);
+	register_netdevice_notifier(&clip_dev_notifier);
+	register_inetaddr_notifier(&clip_inet_notifier);
 
-#ifdef CONFIG_PROC_FS
-{
-	struct proc_dir_entry *p;
+	setup_timer(&idle_timer, idle_timer_check, 0);
 
 	p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
 	if (p)
 		p->proc_fops = &arp_seq_fops;
-}
-#endif
 
 	return 0;
 }
@@ -1012,13 +985,15 @@
 
 	remove_proc_entry("arp", atm_proc_root);
 
+	unregister_inetaddr_notifier(&clip_inet_notifier);
+	unregister_netdevice_notifier(&clip_dev_notifier);
+
 	deregister_atm_ioctl(&clip_ioctl_ops);
 
 	/* First, stop the idle timer, so it stops banging
 	 * on the table.
 	 */
-	if (start_timer == 0)
-		del_timer(&idle_timer);
+	del_timer_sync(&idle_timer);
 
 	/* Next, purge the table, so that the device
 	 * unregister loop below does not hang due to
@@ -1042,5 +1017,6 @@
 
 module_init(atm_clip_init);
 module_exit(atm_clip_exit);
-
+MODULE_AUTHOR("Werner Almesberger");
+MODULE_DESCRIPTION("Classical/IP over ATM interface");
 MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6b61323..0c2d13a 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -255,7 +255,7 @@
 	}
 
 	if ((err = hci_send_sco(conn->hcon, skb)) < 0)
-		goto fail;
+		return err;
 
 	return count;
 
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 2d24fb4..56f3aa4 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <linux/if_vlan.h>
 #include <linux/netfilter_bridge.h>
 #include "br_private.h"
 
@@ -29,10 +30,15 @@
 	return 1;
 }
 
+static inline unsigned packet_length(const struct sk_buff *skb)
+{
+	return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0);
+}
+
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
 	/* drop mtu oversized packets except tso */
-	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
+	if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
 		kfree_skb(skb);
 	else {
 #ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b776656..b0b7f55 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -125,9 +125,6 @@
 	struct sk_buff *skb = *pskb;
 	const unsigned char *dest = eth_hdr(skb)->h_dest;
 
-	if (p->state == BR_STATE_DISABLED)
-		goto err;
-
 	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
 		goto err;
 
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b..3da9264 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@
 	return NF_STOLEN;
 }
 
+static int br_nf_dev_queue_xmit(struct sk_buff *skb)
+{
+	if (skb->protocol == htons(ETH_P_IP) &&
+	    skb->len > skb->dev->mtu &&
+	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+		return ip_fragment(skb, br_dev_queue_push_xmit);
+	else
+		return br_dev_queue_push_xmit(skb);
+}
 
 /* PF_BRIDGE/POST_ROUTING ********************************************/
 static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@
 		realoutdev = nf_bridge->netoutdev;
 #endif
 	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
-		br_dev_queue_push_xmit);
+		br_nf_dev_queue_xmit);
 
 	return NF_STOLEN;
 
@@ -869,7 +878,7 @@
 
 	if ((out->hard_start_xmit == br_dev_xmit &&
 	     okfn != br_nf_forward_finish &&
-	     okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
+	     okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 	    || ((out->priv_flags & IFF_802_1Q_VLAN) &&
 		VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 01eae97..3a13ed6 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -824,14 +824,14 @@
 	if (udc_cnt) {
 		/* this will get free'd in do_replace()/ebt_register_table()
 		   if an error occurs */
-		newinfo->chainstack = (struct ebt_chainstack **)
-		   vmalloc((highest_possible_processor_id()+1) 
-				   		* sizeof(struct ebt_chainstack));
+		newinfo->chainstack =
+			vmalloc((highest_possible_processor_id()+1)
+				   	* sizeof(*(newinfo->chainstack)));
 		if (!newinfo->chainstack)
 			return -ENOMEM;
-		for_each_cpu(i) {
+		for_each_possible_cpu(i) {
 			newinfo->chainstack[i] =
-			   vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
+			  vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
 			if (!newinfo->chainstack[i]) {
 				while (i)
 					vfree(newinfo->chainstack[--i]);
@@ -841,8 +841,7 @@
 			}
 		}
 
-		cl_s = (struct ebt_cl_stack *)
-		   vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
+		cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
 		if (!cl_s)
 			return -ENOMEM;
 		i = 0; /* the i'th udc */
@@ -901,7 +900,7 @@
 	       sizeof(struct ebt_counter) * nentries);
 
 	/* add other counters to those of cpu 0 */
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (cpu == 0)
 			continue;
 		counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
@@ -944,8 +943,7 @@
 
 	countersize = COUNTER_OFFSET(tmp.nentries) * 
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
 		return -ENOMEM;
 
@@ -967,8 +965,7 @@
 	/* the user wants counters back
 	   the check on the size is done later, when we have the lock */
 	if (tmp.num_counters) {
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp));
 		if (!counterstmp) {
 			ret = -ENOMEM;
 			goto free_entries;
@@ -1036,7 +1033,7 @@
 
 	vfree(table->entries);
 	if (table->chainstack) {
-		for_each_cpu(i)
+		for_each_possible_cpu(i)
 			vfree(table->chainstack[i]);
 		vfree(table->chainstack);
 	}
@@ -1054,7 +1051,7 @@
 	vfree(counterstmp);
 	/* can be initialized in translate_table() */
 	if (newinfo->chainstack) {
-		for_each_cpu(i)
+		for_each_possible_cpu(i)
 			vfree(newinfo->chainstack[i]);
 		vfree(newinfo->chainstack);
 	}
@@ -1148,8 +1145,7 @@
 
 	countersize = COUNTER_OFFSET(table->table->nentries) *
 					(highest_possible_processor_id()+1);
-	newinfo = (struct ebt_table_info *)
-	   vmalloc(sizeof(struct ebt_table_info) + countersize);
+	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	ret = -ENOMEM;
 	if (!newinfo)
 		return -ENOMEM;
@@ -1201,7 +1197,7 @@
 	mutex_unlock(&ebt_mutex);
 free_chainstack:
 	if (newinfo->chainstack) {
-		for_each_cpu(i)
+		for_each_possible_cpu(i)
 			vfree(newinfo->chainstack[i]);
 		vfree(newinfo->chainstack);
 	}
@@ -1224,7 +1220,7 @@
 	mutex_unlock(&ebt_mutex);
 	vfree(table->private->entries);
 	if (table->private->chainstack) {
-		for_each_cpu(i)
+		for_each_possible_cpu(i)
 			vfree(table->private->chainstack[i]);
 		vfree(table->private->chainstack);
 	}
@@ -1247,8 +1243,7 @@
 	if (hlp.num_counters == 0)
 		return -EINVAL;
 
-	if ( !(tmp = (struct ebt_counter *)
-	   vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
+	if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) {
 		MEMPRINT("Update_counters && nomemory\n");
 		return -ENOMEM;
 	}
@@ -1377,8 +1372,7 @@
 			BUGPRINT("Num_counters wrong\n");
 			return -EINVAL;
 		}
-		counterstmp = (struct ebt_counter *)
-		   vmalloc(nentries * sizeof(struct ebt_counter));
+		counterstmp = vmalloc(nentries * sizeof(*counterstmp));
 		if (!counterstmp) {
 			MEMPRINT("Couldn't copy counters, out of memory\n");
 			return -ENOMEM;
diff --git a/net/compat.c b/net/compat.c
index 8fd37cd..d5d69fa 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -476,8 +476,7 @@
 	int err;
 	struct socket *sock;
 
-	/* SO_SET_REPLACE seems to be the same in all levels */
-	if (optname == IPT_SO_SET_REPLACE)
+	if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE)
 		return do_netfilter_replace(fd, level, optname,
 					    optval, optlen);
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 434220d..3bad1af 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2698,7 +2698,8 @@
 				/* If command is `set a parameter', or
 				 * `get the encoding parameters', check if
 				 * the user has the right to do it */
-				if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) {
+				if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE
+				    || cmd == SIOCGIWENCODEEXT) {
 					if (!capable(CAP_NET_ADMIN))
 						return -EPERM;
 				}
@@ -3042,11 +3043,11 @@
 
 		switch(dev->reg_state) {
 		case NETREG_REGISTERING:
+			dev->reg_state = NETREG_REGISTERED;
 			err = netdev_register_sysfs(dev);
 			if (err)
 				printk(KERN_ERR "%s: failed sysfs registration (%d)\n",
 				       dev->name, err);
-			dev->reg_state = NETREG_REGISTERED;
 			break;
 
 		case NETREG_UNREGISTERING:
@@ -3100,12 +3101,11 @@
 	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
 	alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
 
-	p = kmalloc(alloc_size, GFP_KERNEL);
+	p = kzalloc(alloc_size, GFP_KERNEL);
 	if (!p) {
 		printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
 		return NULL;
 	}
-	memset(p, 0, alloc_size);
 
 	dev = (struct net_device *)
 		(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
@@ -3347,7 +3347,7 @@
 	 *	Initialise the packet receive queues.
 	 */
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		struct softnet_data *queue;
 
 		queue = &per_cpu(softnet_data, i);
diff --git a/net/core/dv.c b/net/core/dv.c
index cf58140..29ee77f 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -55,15 +55,12 @@
 
 	dev->divert = NULL;
 	if (dev->type == ARPHRD_ETHER) {
-		dev->divert = (struct divert_blk *)
-			kmalloc(alloc_size, GFP_KERNEL);
+		dev->divert = kzalloc(alloc_size, GFP_KERNEL);
 		if (dev->divert == NULL) {
 			printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n",
 			       dev->name);
 			return -ENOMEM;
 		}
-
-		memset(dev->divert, 0, sizeof(struct divert_blk));
 		dev_hold(dev);
 	}
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 93fbd01..5b4486a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -34,6 +34,7 @@
 #include <linux/timer.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/unaligned.h>
 #include <linux/filter.h>
 
 /* No hurry in this branch */
@@ -177,7 +178,7 @@
 load_w:
 			ptr = load_pointer(skb, k, 4, &tmp);
 			if (ptr != NULL) {
-				A = ntohl(*(u32 *)ptr);
+				A = ntohl(get_unaligned((u32 *)ptr));
 				continue;
 			}
 			break;
@@ -186,7 +187,7 @@
 load_h:
 			ptr = load_pointer(skb, k, 2, &tmp);
 			if (ptr != NULL) {
-				A = ntohs(*(u16 *)ptr);
+				A = ntohs(get_unaligned((u16 *)ptr));
 				continue;
 			}
 			break;
diff --git a/net/core/flow.c b/net/core/flow.c
index 55789f8..2191af5 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -79,7 +79,7 @@
 {
 	int i;
 
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		flow_hash_rnd_recalc(i) = 1;
 
 	flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
@@ -318,12 +318,10 @@
 		/* NOTHING */;
 
 	flow_table(cpu) = (struct flow_cache_entry **)
-		__get_free_pages(GFP_KERNEL, order);
+		__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
 	if (!flow_table(cpu))
 		panic("NET: failed to allocate flow cache order %lu\n", order);
 
-	memset(flow_table(cpu), 0, PAGE_SIZE << order);
-
 	flow_hash_rnd_recalc(cpu) = 1;
 	flow_count(cpu) = 0;
 
@@ -363,7 +361,7 @@
 	flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD;
 	add_timer(&flow_hash_rnd_timer);
 
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		flow_cache_cpu_prepare(i);
 
 	hotcpu_notifier(flow_cache_cpu, 0);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index b07c029..3cad026 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -159,11 +159,10 @@
 	if (parm->interval < -2 || parm->interval > 3)
 		return -EINVAL;
 
-	est = kmalloc(sizeof(*est), GFP_KERNEL);
+	est = kzalloc(sizeof(*est), GFP_KERNEL);
 	if (est == NULL)
 		return -ENOBUFS;
 
-	memset(est, 0, sizeof(*est));
 	est->interval = parm->interval + 2;
 	est->bstats = bstats;
 	est->rate_est = rate_est;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c86668..4cf878e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -284,14 +284,11 @@
 	struct neighbour **ret;
 
 	if (size <= PAGE_SIZE) {
-		ret = kmalloc(size, GFP_ATOMIC);
+		ret = kzalloc(size, GFP_ATOMIC);
 	} else {
 		ret = (struct neighbour **)
-			__get_free_pages(GFP_ATOMIC, get_order(size));
+		      __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
 	}
-	if (ret)
-		memset(ret, 0, size);
-
 	return ret;
 }
 
@@ -1089,8 +1086,7 @@
 		if (hh->hh_type == protocol)
 			break;
 
-	if (!hh && (hh = kmalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
-		memset(hh, 0, sizeof(struct hh_cache));
+	if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
 		rwlock_init(&hh->hh_lock);
 		hh->hh_type = protocol;
 		atomic_set(&hh->hh_refcnt, 0);
@@ -1366,13 +1362,11 @@
 	tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
 
 	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
-	tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+	tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
 
 	if (!tbl->hash_buckets || !tbl->phash_buckets)
 		panic("cannot allocate neighbour cache hashes");
 
-	memset(tbl->phash_buckets, 0, phsize);
-
 	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
 
 	rwlock_init(&tbl->lock);
@@ -1633,7 +1627,7 @@
 
 		memset(&ndst, 0, sizeof(ndst));
 
-		for_each_cpu(cpu) {
+		for_each_possible_cpu(cpu) {
 			struct neigh_statistics	*st;
 
 			st = per_cpu_ptr(tbl->stats, cpu);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 21b6846..c12990c 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -165,7 +165,7 @@
 		operstate = IF_OPER_DOWN;
 	read_unlock(&dev_base_lock);
 
-	if (operstate >= sizeof(operstates))
+	if (operstate >= ARRAY_SIZE(operstates))
 		return -EINVAL; /* should not happen */
 
 	return sprintf(buf, "%s\n", operstates[operstate]);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 1e44eda..79ebd75 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -38,13 +38,11 @@
 {
 	const int lopt_size = sizeof(struct listen_sock) +
 			      nr_table_entries * sizeof(struct request_sock *);
-	struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
+	struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL);
 
 	if (lopt == NULL)
 		return -ENOMEM;
 
-	memset(lopt, 0, lopt_size);
-
 	for (lopt->max_qlen_log = 6;
 	     (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
 	     lopt->max_qlen_log++);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 09464fa..fb3770f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -112,6 +112,14 @@
 	BUG();
 }
 
+void skb_truesize_bug(struct sk_buff *skb)
+{
+	printk(KERN_ERR "SKB BUG: Invalid truesize (%u) "
+	       "len=%u, sizeof(sk_buff)=%Zd\n",
+	       skb->truesize, skb->len, sizeof(struct sk_buff));
+}
+EXPORT_SYMBOL(skb_truesize_bug);
+
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
diff --git a/net/core/stream.c b/net/core/stream.c
index 35e2525..e948969 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -176,6 +176,7 @@
 {
 	struct sock *sk = skb->sk;
 
+	skb_truesize_check(skb);
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 	sk->sk_forward_alloc += skb->truesize;
 }
diff --git a/net/core/utils.c b/net/core/utils.c
index fdc4f38..4f96f38 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -121,7 +121,7 @@
 {
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
 		__net_srandom(state, i+jiffies);
 	}
@@ -133,7 +133,7 @@
 	unsigned long seed[NR_CPUS];
 
 	get_random_bytes(seed, sizeof(seed));
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
 		__net_srandom(state, seed[i]);
 	}
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 81d6995..d2bc72d 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -1726,6 +1726,14 @@
 	if(!IW_IS_GET(request->cmd))
 		return -EOPNOTSUPP;
 
+	/* If command is `get the encoding parameters', check if
+	 * the user has the right to do it */
+	if (request->cmd == SIOCGIWENCODE ||
+	    request->cmd == SIOCGIWENCODEEXT) {
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	}
+
 	/* Special cases */
 	if(request->cmd == SIOCGIWSTATS)
 		/* Get Wireless Stats */
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 2904799..f2c011f 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -498,7 +498,7 @@
 		goto drop;
 
 	if (dccp_parse_options(sk, skb))
-		goto drop;
+		goto drop_and_free;
 
 	dccp_openreq_init(req, &dp, skb);
 
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index 6cd9f34..f2a27cc 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -1,6 +1,7 @@
 config IEEE80211_SOFTMAC
 	tristate "Software MAC add-on to the IEEE 802.11 networking stack"
 	depends on IEEE80211 && EXPERIMENTAL
+	select WIRELESS_EXT
 	---help---
 	This option enables the hardware independent software MAC addon
 	for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index be61de78..fb79ce7 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -101,6 +101,7 @@
 	/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
 	mac->associated = 0;
 	mac->associnfo.associating = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -143,6 +144,12 @@
 	if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
 		return 0;
 
+	/* assume that users know what they're doing ...
+	 * (note we don't let them select a net we're incompatible with) */
+	if (mac->associnfo.bssfixed) {
+		return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+	}
+
 	/* if 'ANY' network requested, take any that doesn't have privacy enabled */
 	if (mac->associnfo.req_essid.len == 0 
 	    && !(net->capability & WLAN_CAPABILITY_PRIVACY))
@@ -175,7 +182,7 @@
 		ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
 
 	/* try to find the requested network in our list, if we found one already */
-	if (mac->associnfo.bssvalid)
+	if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
 		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);	
 	
 	/* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -240,19 +247,25 @@
 			if (ieee80211softmac_start_scan(mac))
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
 			return;
-		}
-		else {
+		} else {
 			spin_lock_irqsave(&mac->lock, flags);
 			mac->associnfo.associating = 0;
 			mac->associated = 0;
 			spin_unlock_irqrestore(&mac->lock, flags);
 
 			dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
+			/* reset the retry counter for the next user request since we
+			 * break out and don't reschedule ourselves after this point. */
+			mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
 			return;
 		}
 	}
-	
+
+	/* reset the retry counter for the next user request since we
+	 * now found a net and will try to associate to it, but not
+	 * schedule this function again. */
+	mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
 	mac->associnfo.bssvalid = 1;
 	memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
 	/* copy the ESSID for displaying it */
@@ -373,6 +386,7 @@
 	spin_lock_irqsave(&mac->lock, flags);
 	mac->associnfo.bssvalid = 0;
 	mac->associated = 0;
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	schedule_work(&mac->associnfo.work);
 	spin_unlock_irqrestore(&mac->lock, flags);
 	
@@ -391,6 +405,7 @@
 		dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
 		return 0;
 	}
-	ieee80211softmac_assoc(mac, network);
+	schedule_work(&mac->associnfo.work);
+
 	return 0;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 0a52bbd..8cc8f3f 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -67,6 +67,7 @@
 	"authenticating failed",
 	"authenticating timed out",
 	"associating failed because no suitable network was found",
+	"disassociated",
 };
 
 
@@ -128,13 +129,42 @@
 ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
 {
 	struct ieee80211softmac_event *eventptr, *tmp;
-	union iwreq_data wrqu;
-	char *msg;
+	struct ieee80211softmac_network *network;
 	
 	if (event >= 0) {
-		msg = event_descriptions[event];
-		wrqu.data.length = strlen(msg);
-		wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg);
+		union iwreq_data wrqu;
+		int we_event;
+		char *msg = NULL;
+
+		switch(event) {
+		case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
+			network = (struct ieee80211softmac_network *)event_ctx;
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memset(&wrqu, '\0', sizeof (union iwreq_data));
+			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+			we_event = SIOCGIWAP;
+			break;
+		case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
+			wrqu.data.length = 0;
+			wrqu.data.flags = 0;
+			memset(&wrqu, '\0', sizeof (union iwreq_data));
+			we_event = SIOCGIWSCAN;
+			break;
+		default:
+			msg = event_descriptions[event];
+			wrqu.data.length = strlen(msg);
+			we_event = IWEVCUSTOM;
+			break;
+		}
+		wireless_send_event(mac->dev, we_event, &wrqu, msg);
 	}
 
 	if (!list_empty(&mac->events))
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index febc51d..cc6cd56 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -180,9 +180,21 @@
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
 
 	/* Fill in capability Info */
-	(*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ?
-		cpu_to_le16(WLAN_CAPABILITY_ESS) :
-		cpu_to_le16(WLAN_CAPABILITY_IBSS);
+	switch (mac->ieee->iw_mode) {
+	case IW_MODE_INFRA:
+		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+		break;
+	case IW_MODE_ADHOC:
+		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+		break;
+	case IW_MODE_AUTO:
+		(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+		break;
+	default:
+		/* bleh. we don't ever go to these modes */
+		printk(KERN_ERR PFX "invalid iw_mode!\n");
+		break;
+	}
 	/* Need to add this
 	(*pkt)->capability |= mac->ieee->short_slot ? 
 			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 60f06a31..be83bdc 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -45,6 +45,8 @@
 	softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
 	softmac->scaninfo = NULL;
 
+	softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+
 	/* TODO: initialise all the other callbacks in the ieee struct
 	 *	 (once they're written)
 	 */
diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c
index bb9ab8b..2b9e7ed 100644
--- a/net/ieee80211/softmac/ieee80211softmac_scan.c
+++ b/net/ieee80211/softmac/ieee80211softmac_scan.c
@@ -47,6 +47,7 @@
 	sm->scanning = 1;
 	spin_unlock_irqrestore(&sm->lock, flags);
 
+	netif_tx_disable(sm->ieee->dev);
 	ret = sm->start_scan(sm->dev);
 	if (ret) {
 		spin_lock_irqsave(&sm->lock, flags);
@@ -239,6 +240,7 @@
 		if (net)
 			sm->set_channel(sm->dev, net->channel);
 	}
+	netif_wake_queue(sm->ieee->dev);
 	ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index b559aa9..27edb2b 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -27,7 +27,8 @@
 #include "ieee80211softmac_priv.h"
 
 #include <net/iw_handler.h>
-
+/* for is_broadcast_ether_addr and is_zero_ether_addr */
+#include <linux/etherdevice.h>
 
 int
 ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
@@ -41,13 +42,23 @@
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
 
 
+/* if we're still scanning, return -EAGAIN so that userspace tools
+ * can get the complete scan results, otherwise return 0. */
 int
 ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
 				     struct iw_request_info *info,
 				     union iwreq_data *data,
 				     char *extra)
 {
+	unsigned long flags;
 	struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
+
+	spin_lock_irqsave(&sm->lock, flags);
+	if (sm->scanning) {
+		spin_unlock_irqrestore(&sm->lock, flags);
+		return -EAGAIN;
+	}
+	spin_unlock_irqrestore(&sm->lock, flags);
 	return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
@@ -73,7 +84,6 @@
 			sm->associnfo.static_essid = 1;
 		}
 	}
-	sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
 
 	/* set our requested ESSID length.
 	 * If applicable, we have already copied the data in */
@@ -300,8 +310,6 @@
 			    char *extra)
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-	static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 	unsigned long flags;
 
 	/* sanity check */
@@ -310,10 +318,17 @@
 	}
 
 	spin_lock_irqsave(&mac->lock, flags);
-	if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
-	    !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
-		schedule_work(&mac->associnfo.work);
-		goto out;
+	if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
+		/* the bssid we have is not to be fixed any longer,
+		 * and we should reassociate to the best AP. */
+		mac->associnfo.bssfixed = 0;
+		/* force reassociation */
+		mac->associnfo.bssvalid = 0;
+		if (mac->associated)
+			schedule_work(&mac->associnfo.work);
+	} else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
+		/* the bssid we have is no longer fixed */
+		mac->associnfo.bssfixed = 0;
         } else {
 		if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
 			if (mac->associnfo.associating || mac->associated) {
@@ -323,12 +338,14 @@
 		} else {
 			/* copy new value in data->ap_addr.sa_data to bssid */
 			memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
-		}	
+		}
+		/* tell the other code that this bssid should be used no matter what */
+		mac->associnfo.bssfixed = 1;
 		/* queue associate if new bssid or (old one again and not associated) */
 		schedule_work(&mac->associnfo.work);
         }
 
-out:
+ out:
 	spin_unlock_irqrestore(&mac->lock, flags);
 	return 0;
 }
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e16d8b4..e2e4771 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -116,7 +116,7 @@
 	return err;
 }
 
-static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int ah_hlen;
 	struct iphdr *iph;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 041dadd..4749d50 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -928,7 +928,8 @@
  *	Receive an arp request from the device layer.
  */
 
-int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
+		   struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct arphdr *arp;
 
@@ -1417,7 +1418,6 @@
 
 EXPORT_SYMBOL(arp_broken_ops);
 EXPORT_SYMBOL(arp_find);
-EXPORT_SYMBOL(arp_rcv);
 EXPORT_SYMBOL(arp_create);
 EXPORT_SYMBOL(arp_xmit);
 EXPORT_SYMBOL(arp_send);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 81c2f78..54419b2 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1556,7 +1556,6 @@
 #endif
 }
 
-EXPORT_SYMBOL(devinet_ioctl);
 EXPORT_SYMBOL(in_dev_finish_destroy);
 EXPORT_SYMBOL(inet_select_addr);
 EXPORT_SYMBOL(inetdev_by_index);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index bf88c62..9d1881c 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -133,7 +133,7 @@
  * expensive, so we only support truncated data, which is the recommended
  * and common case.
  */
-static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct iphdr *iph;
 	struct ip_esp_hdr *esph;
@@ -208,9 +208,6 @@
 		struct xfrm_encap_tmpl *encap = x->encap;
 		struct udphdr *uh;
 
-		if (encap->encap_type != decap->decap_type)
-			goto out;
-
 		uh = (struct udphdr *)(iph + 1);
 		encap_len = (void*)esph - (void*)uh;
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 4e3d381..cdde963 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -666,4 +666,3 @@
 }
 
 EXPORT_SYMBOL(inet_addr_type);
-EXPORT_SYMBOL(ip_rt_ioctl);
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ccd3efc..95a639f 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -50,7 +50,7 @@
  *		Patrick McHardy <kaber@trash.net>
  */
 
-#define VERSION "0.406"
+#define VERSION "0.407"
 
 #include <linux/config.h>
 #include <asm/uaccess.h>
@@ -314,11 +314,6 @@
 	kfree(container_of(head, struct leaf, rcu));
 }
 
-static inline void free_leaf(struct leaf *leaf)
-{
-	call_rcu(&leaf->rcu, __leaf_free_rcu);
-}
-
 static void __leaf_info_free_rcu(struct rcu_head *head)
 {
 	kfree(container_of(head, struct leaf_info, rcu));
@@ -357,7 +352,12 @@
 
 static inline void tnode_free(struct tnode *tn)
 {
-	call_rcu(&tn->rcu, __tnode_free_rcu);
+	if(IS_LEAF(tn)) {
+		struct leaf *l = (struct leaf *) tn;
+		call_rcu_bh(&l->rcu, __leaf_free_rcu);
+	}
+        else
+		call_rcu(&tn->rcu, __tnode_free_rcu);
 }
 
 static struct leaf *leaf_new(void)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 9831fd2..2a04559 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1107,7 +1107,7 @@
 	struct inet_sock *inet;
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		int err;
 
 		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ef7366f..ee9b551 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -43,8 +43,6 @@
 	return tb;
 }
 
-EXPORT_SYMBOL(inet_bind_bucket_create);
-
 /*
  * Caller must hold hashbucket lock for this tb with local BH disabled
  */
@@ -64,8 +62,6 @@
 	inet_csk(sk)->icsk_bind_hash = tb;
 }
 
-EXPORT_SYMBOL(inet_bind_hash);
-
 /*
  * Get rid of any references to a local port held by the given sock.
  */
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2a8adda..da734c4 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -304,13 +304,17 @@
 
 /* Creation primitives. */
 
-static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
+static struct ipq *ip_frag_intern(struct ipq *qp_in)
 {
 	struct ipq *qp;
 #ifdef CONFIG_SMP
 	struct hlist_node *n;
 #endif
+	unsigned int hash;
+
 	write_lock(&ipfrag_lock);
+	hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
+			 qp_in->protocol);
 #ifdef CONFIG_SMP
 	/* With SMP race we have to recheck hash table, because
 	 * such entry could be created on other cpu, while we
@@ -345,7 +349,7 @@
 }
 
 /* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
+static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
 {
 	struct ipq *qp;
 
@@ -371,7 +375,7 @@
 	spin_lock_init(&qp->lock);
 	atomic_set(&qp->refcnt, 1);
 
-	return ip_frag_intern(hash, qp);
+	return ip_frag_intern(qp);
 
 out_nomem:
 	LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
@@ -387,11 +391,12 @@
 	__u32 saddr = iph->saddr;
 	__u32 daddr = iph->daddr;
 	__u8 protocol = iph->protocol;
-	unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+	unsigned int hash;
 	struct ipq *qp;
 	struct hlist_node *n;
 
 	read_lock(&ipfrag_lock);
+	hash = ipqhashfn(id, saddr, daddr, protocol);
 	hlist_for_each_entry(qp, n, &ipq_hash[hash], list) {
 		if(qp->id == id		&&
 		   qp->saddr == saddr	&&
@@ -405,7 +410,7 @@
 	}
 	read_unlock(&ipfrag_lock);
 
-	return ip_frag_create(hash, iph, user);
+	return ip_frag_create(iph, user);
 }
 
 /* Is the fragment too far ahead to be part of ipq? */
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 9981dcd..ab99beb 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -656,7 +656,7 @@
 		read_unlock(&ipgre_lock);
 		return(0);
 	}
-	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
 drop:
 	read_unlock(&ipgre_lock);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d..cff9c3a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
 
 int sysctl_ip_default_ttl = IPDEFTTL;
 
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
-
 /* Generate a checksum for an outgoing IP datagram. */
 __inline__ void ip_send_check(struct iphdr *iph)
 {
@@ -421,7 +419,7 @@
  *	single device frame, and queue such a frame for sending.
  */
 
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
 {
 	struct iphdr *iph;
 	int raw = 0;
@@ -673,6 +671,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(ip_fragment);
+
 int
 ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
 {
@@ -904,7 +904,7 @@
 			 * because we have no idea what fragment will be
 			 * the last.
 			 */
-			if (datalen == length)
+			if (datalen == length + fraggap)
 				alloclen += rt->u.dst.trailer_len;
 
 			if (transhdrlen) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index c95020f..cd810f41 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -81,8 +81,7 @@
 	return err;
 }
 
-static int ipcomp_input(struct xfrm_state *x,
-                        struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	u8 nexthdr;
 	int err = 0;
@@ -291,11 +290,8 @@
 	if (!scratches)
 		return;
 
-	for_each_cpu(i) {
-		void *scratch = *per_cpu_ptr(scratches, i);
-		if (scratch)
-			vfree(scratch);
-	}
+	for_each_possible_cpu(i)
+		vfree(*per_cpu_ptr(scratches, i));
 
 	free_percpu(scratches);
 }
@@ -314,7 +310,7 @@
 
 	ipcomp_scratches = scratches;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
 		if (!scratch)
 			return NULL;
@@ -345,7 +341,7 @@
 	if (!tfms)
 		return;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
 		crypto_free_tfm(tfm);
 	}
@@ -385,7 +381,7 @@
 	if (!tfms)
 		goto error;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
 		if (!tfm)
 			goto error;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index eef07b0..ea398ee 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -474,9 +474,6 @@
 	struct iphdr *iph;
 	struct ip_tunnel *tunnel;
 
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto out;
-
 	iph = skb->nh.iph;
 
 	read_lock(&ipip_lock);
@@ -508,7 +505,6 @@
 	}
 	read_unlock(&ipip_lock);
 
-out:
 	return -1;
 }
 
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b5ad9ac..6a9e34b 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@
 	u_int8_t tos;
 };
 
-static void queue_save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
 {
 	struct ip_rt_info *rt_info = nf_info_reroute(info);
 
@@ -146,7 +146,7 @@
 	}
 }
 
-static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
 {
 	const struct ip_rt_info *rt_info = nf_info_reroute(info);
 
@@ -161,20 +161,54 @@
 	return 0;
 }
 
-static struct nf_queue_rerouter ip_reroute = {
-	.rer_size	= sizeof(struct ip_rt_info),
-	.save		= queue_save,
-	.reroute	= queue_reroute,
+unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+			    unsigned int dataoff, u_int8_t protocol)
+{
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int csum = 0;
+
+	switch (skb->ip_summed) {
+	case CHECKSUM_HW:
+		if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
+			break;
+		if ((protocol == 0 && !(u16)csum_fold(skb->csum)) ||
+		    !csum_tcpudp_magic(iph->saddr, iph->daddr,
+			    	       skb->len - dataoff, protocol,
+				       skb->csum)) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			break;
+		}
+		/* fall through */
+	case CHECKSUM_NONE:
+		if (protocol == 0)
+			skb->csum = 0;
+		else
+			skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+						       skb->len - dataoff,
+						       protocol, 0);
+		csum = __skb_checksum_complete(skb);
+	}
+	return csum;
+}
+
+EXPORT_SYMBOL(nf_ip_checksum);
+
+static struct nf_afinfo nf_ip_afinfo = {
+	.family		= AF_INET,
+	.checksum	= nf_ip_checksum,
+	.saveroute	= nf_ip_saveroute,
+	.reroute	= nf_ip_reroute,
+	.route_key_size	= sizeof(struct ip_rt_info),
 };
 
 static int ipv4_netfilter_init(void)
 {
-	return nf_register_queue_rerouter(PF_INET, &ip_reroute);
+	return nf_register_afinfo(&nf_ip_afinfo);
 }
 
 static void ipv4_netfilter_fini(void)
 {
-	nf_unregister_queue_rerouter(PF_INET);
+	nf_unregister_afinfo(&nf_ip_afinfo);
 }
 
 module_init(ipv4_netfilter_init);
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 882b842..3d560de 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -69,6 +69,7 @@
 	tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
 	depends on EXPERIMENTAL && IP_NF_CONNTRACK && NETFILTER_NETLINK
 	depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+	depends on IP_NF_NAT=n || IP_NF_NAT
 	help
 	  This option enables support for a netlink-based userspace interface
 
@@ -221,16 +222,6 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_MATCH_MULTIPORT
-	tristate "Multiple port match support"
-	depends on IP_NF_IPTABLES
-	help
-	  Multiport matching allows you to match TCP or UDP packets based on
-	  a series of source or destination ports: normally a rule can only
-	  match a single range of ports.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 config IP_NF_MATCH_TOS
 	tristate "TOS match support"
 	depends on IP_NF_IPTABLES
@@ -272,12 +263,12 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_MATCH_AH_ESP
-	tristate "AH/ESP match support"
+config IP_NF_MATCH_AH
+	tristate "AH match support"
 	depends on IP_NF_IPTABLES
 	help
-	  These two match extensions (`ah' and `esp') allow you to match a
-	  range of SPIs inside AH or ESP headers of IPSec packets.
+	  This match extension allows you to match a range of SPIs
+	  inside AH header of IPSec packets.
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
@@ -354,7 +345,7 @@
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 config IP_NF_TARGET_ULOG
-	tristate "ULOG target support (OBSOLETE)"
+	tristate "ULOG target support"
 	depends on IP_NF_IPTABLES
 	---help---
 
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index f2cd9a6..461cb1e 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -53,13 +53,12 @@
 # matches
 obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
 obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
-obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
+obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index a44a5d7..c2d92f9 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -646,7 +646,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		if (newinfo->entries[i] && newinfo->entries[i] != entry0)
 			memcpy(newinfo->entries[i], entry0, newinfo->size);
 	}
@@ -696,7 +696,7 @@
 			   counters,
 			   &i);
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (cpu == curcpu)
 			continue;
 		i = 0;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index d0d379c..d7c472f 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -181,33 +181,26 @@
 
 static int __init arptable_filter_init(void)
 {
-	int ret, i;
+	int ret;
 
 	/* Register table */
 	ret = arpt_register_table(&packet_filter, &initial_table.repl);
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
-		if ((ret = nf_register_hook(&arpt_ops[i])) < 0)
-			goto cleanup_hooks;
+	ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
+	if (ret < 0)
+		goto cleanup_table;
 	return ret;
 
-cleanup_hooks:
-	while (--i >= 0)
-		nf_unregister_hook(&arpt_ops[i]);
-
+cleanup_table:
 	arpt_unregister_table(&packet_filter);
 	return ret;
 }
 
 static void __exit arptable_filter_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(arpt_ops); i++)
-		nf_unregister_hook(&arpt_ops[i]);
-
+	nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops));
 	arpt_unregister_table(&packet_filter);
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index ceaabc1..979a2ea 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -133,7 +133,7 @@
 	struct ip_conntrack_ecache *ecache;
 	int cpu;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		ecache = &per_cpu(ip_conntrack_ecache, cpu);
 		if (ecache->ct)
 			ip_conntrack_put(ecache->ct);
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index daeb139..2c2fb70 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -9,37 +9,6 @@
  * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  *
  * For more information, please see http://nath323.sourceforge.net/
- *
- * Changes:
- * 	2006-02-01 - initial version 0.1
- *
- *	2006-02-20 - version 0.2
- *	  1. Changed source format to follow kernel conventions
- *	  2. Deleted some unnecessary structures
- *	  3. Minor fixes
- *
- * 	2006-03-10 - version 0.3
- * 	  1. Added support for multiple TPKTs in one packet (suggested by
- * 	     Patrick McHardy)
- * 	  2. Avoid excessive stack usage (based on Patrick McHardy's patch)
- * 	  3. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 	  4. Fixed missing H.245 module owner (Patrick McHardy)
- * 	  5. Avoid long RAS expectation chains (Patrick McHardy)
- * 	  6. Fixed incorrect __exit attribute (Patrick McHardy)
- * 	  7. Eliminated unnecessary return code
- * 	  8. Fixed incorrect use of NAT data from conntrack code (suggested by
- * 	     Patrick McHardy)
- * 	  9. Fixed TTL calculation error in RCF
- * 	  10. Added TTL support in RRQ
- * 	  11. Better support for separate TPKT header and data
- *
- * 	2006-03-15 - version 0.4
- * 	  1. Added support for T.120 channels
- * 	  2. Added parameter gkrouted_only (suggested by Patrick McHardy)
- * 	  3. Splitted ASN.1 code and data (suggested by Patrick McHardy)
- * 	  4. Sort ASN.1 data to avoid forwarding declarations (suggested by
- * 	     Patrick McHardy)
- * 	  5. Reset next TPKT data length in get_tpkt_data()
  */
 
 #include <linux/config.h>
@@ -54,8 +23,6 @@
 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
 #include <linux/moduleparam.h>
 
-#include "ip_conntrack_helper_h323_asn1.h"
-
 #if 0
 #define DEBUGP printk
 #else
@@ -63,6 +30,10 @@
 #endif
 
 /* Parameters */
+static unsigned int default_rrq_ttl = 300;
+module_param(default_rrq_ttl, uint, 0600);
+MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");
+
 static int gkrouted_only = 1;
 module_param(gkrouted_only, int, 0600);
 MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
@@ -222,8 +193,8 @@
 }
 
 /****************************************************************************/
-int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
-		  u_int32_t * ip, u_int16_t * port)
+static int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
+			 u_int32_t * ip, u_int16_t * port)
 {
 	unsigned char *p;
 
@@ -1302,7 +1273,7 @@
 		DEBUGP("ip_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
 		info->timeout = rrq->timeToLive;
 	} else
-		info->timeout = 0;
+		info->timeout = default_rrq_ttl;
 
 	return 0;
 }
@@ -1713,18 +1684,17 @@
 module_init(init);
 module_exit(fini);
 
-EXPORT_SYMBOL(get_h245_addr);
-EXPORT_SYMBOL(get_h225_addr);
-EXPORT_SYMBOL(ip_conntrack_h245_expect);
-EXPORT_SYMBOL(ip_conntrack_q931_expect);
-EXPORT_SYMBOL(set_h245_addr_hook);
-EXPORT_SYMBOL(set_h225_addr_hook);
-EXPORT_SYMBOL(set_sig_addr_hook);
-EXPORT_SYMBOL(set_ras_addr_hook);
-EXPORT_SYMBOL(nat_rtp_rtcp_hook);
-EXPORT_SYMBOL(nat_t120_hook);
-EXPORT_SYMBOL(nat_h245_hook);
-EXPORT_SYMBOL(nat_q931_hook);
+EXPORT_SYMBOL_GPL(get_h225_addr);
+EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);
+EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);
+EXPORT_SYMBOL_GPL(set_h245_addr_hook);
+EXPORT_SYMBOL_GPL(set_h225_addr_hook);
+EXPORT_SYMBOL_GPL(set_sig_addr_hook);
+EXPORT_SYMBOL_GPL(set_ras_addr_hook);
+EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
+EXPORT_SYMBOL_GPL(nat_t120_hook);
+EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_q931_hook);
 
 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
 MODULE_DESCRIPTION("H.323 connection tracking helper");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index afa5251..4807800 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -15,7 +15,7 @@
 #else
 #include <stdio.h>
 #endif
-#include "ip_conntrack_helper_h323_asn1.h"
+#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
 
 /* Trace Flag */
 #ifndef H323_TRACE
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 9b6e19b..01bd7ca 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1658,7 +1658,7 @@
 	printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
-	ip_conntrack_unregister_notifier(&ctnl_notifier_exp);
+	ip_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
 	ip_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 3021af0..d8b14a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,25 +224,14 @@
 	}
 
 	/* See ip_conntrack_proto_tcp.c */
-	if (hooknum != NF_IP_PRE_ROUTING)
-		goto checksum_skipped;
-
-	switch (skb->ip_summed) {
-	case CHECKSUM_HW:
-		if (!(u16)csum_fold(skb->csum)) 
-			break;
-		/* fall through */
-	case CHECKSUM_NONE:
-		skb->csum = 0;
-		if (__skb_checksum_complete(skb)) {
-			if (LOG_INVALID(IPPROTO_ICMP))
-				nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
-					      "ip_ct_icmp: bad ICMP checksum ");
-			return -NF_ACCEPT;
-		}
+	if (hooknum == NF_IP_PRE_ROUTING &&
+	    nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
+				      "ip_ct_icmp: bad ICMP checksum ");
+		return -NF_ACCEPT;
 	}
 
-checksum_skipped:
 	/*
 	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
 	 *
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e0dc370..062b252 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,11 +870,8 @@
 	 * and moreover root might send raw packets.
 	 */
 	/* FIXME: Source route IP option packets --RR */
-	if (hooknum == NF_IP_PRE_ROUTING
-	    && skb->ip_summed != CHECKSUM_UNNECESSARY
-	    && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
-			         skb->ip_summed == CHECKSUM_HW ? skb->csum
-			      	 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
+	if (hooknum == NF_IP_PRE_ROUTING &&
+	    nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 				  "ip_ct_tcp: bad TCP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 55b7d32..7089986 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,11 +120,8 @@
 	 * because the semantic of CHECKSUM_HW is different there 
 	 * and moreover root might send raw packets.
 	 * FIXME: Source route IP option packets --RR */
-	if (hooknum == NF_IP_PRE_ROUTING
-	    && skb->ip_summed != CHECKSUM_UNNECESSARY
-	    && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
-			         skb->ip_summed == CHECKSUM_HW ? skb->csum
-			      	 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
+	if (hooknum == NF_IP_PRE_ROUTING &&
+	    nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
 		if (LOG_INVALID(IPPROTO_UDP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 				  "ip_ct_udp: bad UDP checksum ");
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 5207602..929d61f 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -469,70 +469,63 @@
 
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
-static struct nf_hook_ops ip_conntrack_defrag_ops = {
-	.hook		= ip_conntrack_defrag,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_PRE_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_in_ops = {
-	.hook		= ip_conntrack_in,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_PRE_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
-	.hook		= ip_conntrack_defrag,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_OUT,
-	.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ip_conntrack_local_out_ops = {
-	.hook		= ip_conntrack_local,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_OUT,
-	.priority	= NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ip_conntrack_helper_out_ops = {
-	.hook		= ip_conntrack_help,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ip_conntrack_helper_in_ops = {
-	.hook		= ip_conntrack_help,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ip_conntrack_out_ops = {
-	.hook		= ip_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ip_conntrack_local_in_ops = {
-	.hook		= ip_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ip_conntrack_ops[] = {
+	{
+		.hook		= ip_conntrack_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ip_conntrack_in,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK,
+	},
+	{
+		.hook		= ip_conntrack_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ip_conntrack_local,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_CONNTRACK,
+	},
+	{
+		.hook		= ip_conntrack_help,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
+		.hook		= ip_conntrack_help,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
+		.hook		= ip_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+	},
+	{
+		.hook		= ip_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+	},
 };
 
 /* Sysctl support */
@@ -783,122 +776,6 @@
 EXPORT_SYMBOL(ip_ct_log_invalid);
 #endif /* CONFIG_SYSCTL */
 
-static int init_or_cleanup(int init)
-{
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
-#endif
-	int ret = 0;
-
-	if (!init) goto cleanup;
-
-	ret = ip_conntrack_init();
-	if (ret < 0)
-		goto cleanup_nothing;
-
-#ifdef CONFIG_PROC_FS
-	ret = -ENOMEM;
-	proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
-	if (!proc) goto cleanup_init;
-
-	proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
-					&exp_file_ops);
-	if (!proc_exp) goto cleanup_proc;
-
-	proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
-	if (!proc_stat)
-		goto cleanup_proc_exp;
-
-	proc_stat->proc_fops = &ct_cpu_seq_fops;
-	proc_stat->owner = THIS_MODULE;
-#endif
-
-	ret = nf_register_hook(&ip_conntrack_defrag_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register pre-routing defrag hook.\n");
-		goto cleanup_proc_stat;
-	}
-	ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register local_out defrag hook.\n");
-		goto cleanup_defragops;
-	}
-	ret = nf_register_hook(&ip_conntrack_in_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register pre-routing hook.\n");
-		goto cleanup_defraglocalops;
-	}
-	ret = nf_register_hook(&ip_conntrack_local_out_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register local out hook.\n");
-		goto cleanup_inops;
-	}
-	ret = nf_register_hook(&ip_conntrack_helper_in_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register local in helper hook.\n");
-		goto cleanup_inandlocalops;
-	}
-	ret = nf_register_hook(&ip_conntrack_helper_out_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register postrouting helper hook.\n");
-		goto cleanup_helperinops;
-	}
-	ret = nf_register_hook(&ip_conntrack_out_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register post-routing hook.\n");
-		goto cleanup_helperoutops;
-	}
-	ret = nf_register_hook(&ip_conntrack_local_in_ops);
-	if (ret < 0) {
-		printk("ip_conntrack: can't register local in hook.\n");
-		goto cleanup_inoutandlocalops;
-	}
-#ifdef CONFIG_SYSCTL
-	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
-	if (ip_ct_sysctl_header == NULL) {
-		printk("ip_conntrack: can't register to sysctl.\n");
-		ret = -ENOMEM;
-		goto cleanup_localinops;
-	}
-#endif
-
-	return ret;
-
- cleanup:
-	synchronize_net();
-#ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(ip_ct_sysctl_header);
- cleanup_localinops:
-#endif
-	nf_unregister_hook(&ip_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
-	nf_unregister_hook(&ip_conntrack_out_ops);
- cleanup_helperoutops:
-	nf_unregister_hook(&ip_conntrack_helper_out_ops);
- cleanup_helperinops:
-	nf_unregister_hook(&ip_conntrack_helper_in_ops);
- cleanup_inandlocalops:
-	nf_unregister_hook(&ip_conntrack_local_out_ops);
- cleanup_inops:
-	nf_unregister_hook(&ip_conntrack_in_ops);
- cleanup_defraglocalops:
-	nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
- cleanup_defragops:
-	nf_unregister_hook(&ip_conntrack_defrag_ops);
- cleanup_proc_stat:
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("ip_conntrack", proc_net_stat);
- cleanup_proc_exp:
-	proc_net_remove("ip_conntrack_expect");
- cleanup_proc:
-	proc_net_remove("ip_conntrack");
- cleanup_init:
-#endif /* CONFIG_PROC_FS */
-	ip_conntrack_cleanup();
- cleanup_nothing:
-	return ret;
-}
-
 /* FIXME: Allow NULL functions and sub in pointers to generic for
    them. --RR */
 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
@@ -921,7 +798,7 @@
 	write_lock_bh(&ip_conntrack_lock);
 	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
 	write_unlock_bh(&ip_conntrack_lock);
-	
+
 	/* Somebody could be still looking at the proto in bh. */
 	synchronize_net();
 
@@ -931,12 +808,77 @@
 
 static int __init ip_conntrack_standalone_init(void)
 {
-	return init_or_cleanup(1);
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
+	int ret = 0;
+
+	ret = ip_conntrack_init();
+	if (ret < 0)
+		return ret;
+
+#ifdef CONFIG_PROC_FS
+	ret = -ENOMEM;
+	proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
+	if (!proc) goto cleanup_init;
+
+	proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+					&exp_file_ops);
+	if (!proc_exp) goto cleanup_proc;
+
+	proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+	if (!proc_stat)
+		goto cleanup_proc_exp;
+
+	proc_stat->proc_fops = &ct_cpu_seq_fops;
+	proc_stat->owner = THIS_MODULE;
+#endif
+
+	ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+	if (ret < 0) {
+		printk("ip_conntrack: can't register hooks.\n");
+		goto cleanup_proc_stat;
+	}
+#ifdef CONFIG_SYSCTL
+	ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
+	if (ip_ct_sysctl_header == NULL) {
+		printk("ip_conntrack: can't register to sysctl.\n");
+		ret = -ENOMEM;
+		goto cleanup_hooks;
+	}
+#endif
+	return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup_hooks:
+	nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+#endif
+ cleanup_proc_stat:
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("ip_conntrack", proc_net_stat);
+ cleanup_proc_exp:
+	proc_net_remove("ip_conntrack_expect");
+ cleanup_proc:
+	proc_net_remove("ip_conntrack");
+ cleanup_init:
+#endif /* CONFIG_PROC_FS */
+	ip_conntrack_cleanup();
+	return ret;
 }
 
 static void __exit ip_conntrack_standalone_fini(void)
 {
-	init_or_cleanup(0);
+	synchronize_net();
+#ifdef CONFIG_SYSCTL
+	unregister_sysctl_table(ip_ct_sysctl_header);
+#endif
+	nf_unregister_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("ip_conntrack", proc_net_stat);
+	proc_net_remove("ip_conntrack_expect");
+	proc_net_remove("ip_conntrack");
+#endif /* CONFIG_PROC_FS */
+	ip_conntrack_cleanup();
 }
 
 module_init(ip_conntrack_standalone_init);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index a0bc883..d45663d 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -7,24 +7,6 @@
  *
  * Based on the 'brute force' H.323 NAT module by
  * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * Changes:
- *	2006-02-01 - initial version 0.1
- *
- *	2006-02-20 - version 0.2
- *	  1. Changed source format to follow kernel conventions
- *	  2. Deleted some unnecessary structures
- *	  3. Minor fixes
- *
- * 	2006-03-10 - version 0.3
- * 	  1. Added support for multiple TPKTs in one packet (suggested by
- * 	     Patrick McHardy)
- * 	  2. Added support for non-linear skb (based on Patrick McHardy's patch)
- * 	  3. Eliminated unnecessary return code
- *
- * 	2006-03-15 - version 0.4
- * 	  1. Added support for T.120 channels
- * 	  2. Added parameter gkrouted_only (suggested by Patrick McHardy)
  */
 
 #include <linux/module.h>
@@ -41,65 +23,12 @@
 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 
-#include "ip_conntrack_helper_h323_asn1.h"
-
 #if 0
 #define DEBUGP printk
 #else
 #define DEBUGP(format, args...)
 #endif
 
-extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr,
-			 u_int32_t * ip, u_int16_t * port);
-extern int get_h225_addr(unsigned char *data, TransportAddress * addr,
-			 u_int32_t * ip, u_int16_t * port);
-extern void ip_conntrack_h245_expect(struct ip_conntrack *new,
-				     struct ip_conntrack_expect *this);
-extern void ip_conntrack_q931_expect(struct ip_conntrack *new,
-				     struct ip_conntrack_expect *this);
-extern int (*set_h245_addr_hook) (struct sk_buff ** pskb,
-				  unsigned char **data, int dataoff,
-				  H245_TransportAddress * addr,
-				  u_int32_t ip, u_int16_t port);
-extern int (*set_h225_addr_hook) (struct sk_buff ** pskb,
-				  unsigned char **data, int dataoff,
-				  TransportAddress * addr,
-				  u_int32_t ip, u_int16_t port);
-extern int (*set_sig_addr_hook) (struct sk_buff ** pskb,
-				 struct ip_conntrack * ct,
-				 enum ip_conntrack_info ctinfo,
-				 unsigned char **data,
-				 TransportAddress * addr, int count);
-extern int (*set_ras_addr_hook) (struct sk_buff ** pskb,
-				 struct ip_conntrack * ct,
-				 enum ip_conntrack_info ctinfo,
-				 unsigned char **data,
-				 TransportAddress * addr, int count);
-extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb,
-				 struct ip_conntrack * ct,
-				 enum ip_conntrack_info ctinfo,
-				 unsigned char **data, int dataoff,
-				 H245_TransportAddress * addr,
-				 u_int16_t port, u_int16_t rtp_port,
-				 struct ip_conntrack_expect * rtp_exp,
-				 struct ip_conntrack_expect * rtcp_exp);
-extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
-			     enum ip_conntrack_info ctinfo,
-			     unsigned char **data, int dataoff,
-			     H245_TransportAddress * addr, u_int16_t port,
-			     struct ip_conntrack_expect * exp);
-extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
-			     enum ip_conntrack_info ctinfo,
-			     unsigned char **data, int dataoff,
-			     TransportAddress * addr, u_int16_t port,
-			     struct ip_conntrack_expect * exp);
-extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
-			     enum ip_conntrack_info ctinfo,
-			     unsigned char **data, TransportAddress * addr,
-			     int idx, u_int16_t port,
-			     struct ip_conntrack_expect * exp);
-
-
 /****************************************************************************/
 static int set_addr(struct sk_buff **pskb,
 		    unsigned char **data, int dataoff,
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index efba8c4..1aba926 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -279,7 +279,7 @@
 	.target		= ipt_dnat_target,
 	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
 	.table		= "nat",
-	.hooks		= 1 << NF_IP_PRE_ROUTING,
+	.hooks		= (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
 	.checkentry	= ipt_dnat_checkentry,
 };
 
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 3505b0d..8f760b2 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -299,69 +299,63 @@
 
 /* We must be after connection tracking and before packet filtering. */
 
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_in_ops = {
-	.hook		= ip_nat_in,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_PRE_ROUTING,
-	.priority	= NF_IP_PRI_NAT_DST,
+static struct nf_hook_ops ip_nat_ops[] = {
+	/* Before packet filtering, change destination */
+	{
+		.hook		= ip_nat_in,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING,
+		.priority	= NF_IP_PRI_NAT_DST,
+	},
+	/* After packet filtering, change source */
+	{
+		.hook		= ip_nat_out,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_NAT_SRC,
+	},
+	/* After conntrack, adjust sequence number */
+	{
+		.hook		= ip_nat_adjust,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+	},
+	/* Before packet filtering, change destination */
+	{
+		.hook		= ip_nat_local_fn,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_NAT_DST,
+	},
+	/* After packet filtering, change source */
+	{
+		.hook		= ip_nat_fn,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_NAT_SRC,
+	},
+	/* After conntrack, adjust sequence number */
+	{
+		.hook		= ip_nat_adjust,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
+	},
 };
 
-/* After packet filtering, change source */
-static struct nf_hook_ops ip_nat_out_ops = {
-	.hook		= ip_nat_out,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_out_ops = {
-	.hook		= ip_nat_adjust,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-/* Before packet filtering, change destination */
-static struct nf_hook_ops ip_nat_local_out_ops = {
-	.hook		= ip_nat_local_fn,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_OUT,
-	.priority	= NF_IP_PRI_NAT_DST,
-};
-
-/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
-static struct nf_hook_ops ip_nat_local_in_ops = {
-	.hook		= ip_nat_fn,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_NAT_SRC,
-};
-
-/* After conntrack, adjust sequence number */
-static struct nf_hook_ops ip_nat_adjust_in_ops = {
-	.hook		= ip_nat_adjust,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_NAT_SEQ_ADJUST,
-};
-
-
-static int init_or_cleanup(int init)
+static int __init ip_nat_standalone_init(void)
 {
 	int ret = 0;
 
 	need_conntrack();
 
-	if (!init) goto cleanup;
-
 #ifdef CONFIG_XFRM
 	BUG_ON(ip_nat_decode_session != NULL);
 	ip_nat_decode_session = nat_decode_session;
@@ -371,50 +365,13 @@
 		printk("ip_nat_init: can't setup rules.\n");
 		goto cleanup_decode_session;
 	}
-	ret = nf_register_hook(&ip_nat_in_ops);
+	ret = nf_register_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
 	if (ret < 0) {
-		printk("ip_nat_init: can't register in hook.\n");
+		printk("ip_nat_init: can't register hooks.\n");
 		goto cleanup_rule_init;
 	}
-	ret = nf_register_hook(&ip_nat_out_ops);
-	if (ret < 0) {
-		printk("ip_nat_init: can't register out hook.\n");
-		goto cleanup_inops;
-	}
-	ret = nf_register_hook(&ip_nat_adjust_in_ops);
-	if (ret < 0) {
-		printk("ip_nat_init: can't register adjust in hook.\n");
-		goto cleanup_outops;
-	}
-	ret = nf_register_hook(&ip_nat_adjust_out_ops);
-	if (ret < 0) {
-		printk("ip_nat_init: can't register adjust out hook.\n");
-		goto cleanup_adjustin_ops;
-	}
-	ret = nf_register_hook(&ip_nat_local_out_ops);
-	if (ret < 0) {
-		printk("ip_nat_init: can't register local out hook.\n");
-		goto cleanup_adjustout_ops;
-	}
-	ret = nf_register_hook(&ip_nat_local_in_ops);
-	if (ret < 0) {
-		printk("ip_nat_init: can't register local in hook.\n");
-		goto cleanup_localoutops;
-	}
 	return ret;
 
- cleanup:
-	nf_unregister_hook(&ip_nat_local_in_ops);
- cleanup_localoutops:
-	nf_unregister_hook(&ip_nat_local_out_ops);
- cleanup_adjustout_ops:
-	nf_unregister_hook(&ip_nat_adjust_out_ops);
- cleanup_adjustin_ops:
-	nf_unregister_hook(&ip_nat_adjust_in_ops);
- cleanup_outops:
-	nf_unregister_hook(&ip_nat_out_ops);
- cleanup_inops:
-	nf_unregister_hook(&ip_nat_in_ops);
  cleanup_rule_init:
 	ip_nat_rule_cleanup();
  cleanup_decode_session:
@@ -425,14 +382,14 @@
 	return ret;
 }
 
-static int __init ip_nat_standalone_init(void)
-{
-	return init_or_cleanup(1);
-}
-
 static void __exit ip_nat_standalone_fini(void)
 {
-	init_or_cleanup(0);
+	nf_unregister_hooks(ip_nat_ops, ARRAY_SIZE(ip_nat_ops));
+	ip_nat_rule_cleanup();
+#ifdef CONFIG_XFRM
+	ip_nat_decode_session = NULL;
+	synchronize_net();
+#endif
 }
 
 module_init(ip_nat_standalone_init);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 896a244..b93f049 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -662,15 +662,11 @@
 	.outfn	= &ipq_enqueue_packet,
 };
 
-static int
-init_or_cleanup(int init)
+static int __init ip_queue_init(void)
 {
 	int status = -ENOMEM;
 	struct proc_dir_entry *proc;
 	
-	if (!init)
-		goto cleanup;
-
 	netlink_register_notifier(&ipq_nl_notifier);
 	ipqnl = netlink_kernel_create(NETLINK_FIREWALL, 0, ipq_rcv_sk,
 				      THIS_MODULE);
@@ -697,11 +693,6 @@
 	}
 	return status;
 
-cleanup:
-	nf_unregister_queue_handlers(&nfqh);
-	synchronize_net();
-	ipq_flush(NF_DROP);
-	
 cleanup_sysctl:
 	unregister_sysctl_table(ipq_sysctl_header);
 	unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -717,15 +708,21 @@
 	return status;
 }
 
-static int __init ip_queue_init(void)
-{
-	
-	return init_or_cleanup(1);
-}
-
 static void __exit ip_queue_fini(void)
 {
-	init_or_cleanup(0);
+	nf_unregister_queue_handlers(&nfqh);
+	synchronize_net();
+	ipq_flush(NF_DROP);
+
+	unregister_sysctl_table(ipq_sysctl_header);
+	unregister_netdevice_notifier(&ipq_dev_notifier);
+	proc_net_remove(IPQ_PROC_FS_NAME);
+
+	sock_release(ipqnl->sk_socket);
+	mutex_lock(&ipqnl_mutex);
+	mutex_unlock(&ipqnl_mutex);
+
+	netlink_unregister_notifier(&ipq_nl_notifier);
 }
 
 MODULE_DESCRIPTION("IPv4 packet queue handler");
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 460fd90..d25ac8b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/icmp.h>
 #include <net/ip.h>
+#include <net/compat.h>
 #include <asm/uaccess.h>
 #include <linux/mutex.h>
 #include <linux/proc_fs.h>
@@ -734,7 +735,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		if (newinfo->entries[i] && newinfo->entries[i] != entry0)
 			memcpy(newinfo->entries[i], entry0, newinfo->size);
 	}
@@ -787,7 +788,7 @@
 			  counters,
 			  &i);
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (cpu == curcpu)
 			continue;
 		i = 0;
@@ -799,17 +800,11 @@
 	}
 }
 
-static int
-copy_entries_to_user(unsigned int total_size,
-		     struct ipt_table *table,
-		     void __user *userptr)
+static inline struct xt_counters * alloc_counters(struct ipt_table *table)
 {
-	unsigned int off, num, countersize;
-	struct ipt_entry *e;
+	unsigned int countersize;
 	struct xt_counters *counters;
 	struct xt_table_info *private = table->private;
-	int ret = 0;
-	void *loc_cpu_entry;
 
 	/* We need atomic snapshot of counters: rest doesn't change
 	   (other than comefrom, which userspace doesn't care
@@ -818,13 +813,32 @@
 	counters = vmalloc_node(countersize, numa_node_id());
 
 	if (counters == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	/* First, sum counters... */
 	write_lock_bh(&table->lock);
 	get_counters(private, counters);
 	write_unlock_bh(&table->lock);
 
+	return counters;
+}
+
+static int
+copy_entries_to_user(unsigned int total_size,
+		     struct ipt_table *table,
+		     void __user *userptr)
+{
+	unsigned int off, num;
+	struct ipt_entry *e;
+	struct xt_counters *counters;
+	struct xt_table_info *private = table->private;
+	int ret = 0;
+	void *loc_cpu_entry;
+
+	counters = alloc_counters(table);
+	if (IS_ERR(counters))
+		return PTR_ERR(counters);
+
 	/* choose the copy that is on our node/cpu, ...
 	 * This choice is lazy (because current thread is
 	 * allowed to migrate to another cpu)
@@ -884,25 +898,278 @@
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_delta {
+	struct compat_delta *next;
+	u_int16_t offset;
+	short delta;
+};
+
+static struct compat_delta *compat_offsets = NULL;
+
+static int compat_add_offset(u_int16_t offset, short delta)
+{
+	struct compat_delta *tmp;
+
+	tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+	tmp->offset = offset;
+	tmp->delta = delta;
+	if (compat_offsets) {
+		tmp->next = compat_offsets->next;
+		compat_offsets->next = tmp;
+	} else {
+		compat_offsets = tmp;
+		tmp->next = NULL;
+	}
+	return 0;
+}
+
+static void compat_flush_offsets(void)
+{
+	struct compat_delta *tmp, *next;
+
+	if (compat_offsets) {
+		for(tmp = compat_offsets; tmp; tmp = next) {
+			next = tmp->next;
+			kfree(tmp);
+		}
+		compat_offsets = NULL;
+	}
+}
+
+static short compat_calc_jump(u_int16_t offset)
+{
+	struct compat_delta *tmp;
+	short delta;
+
+	for(tmp = compat_offsets, delta = 0; tmp; tmp = tmp->next)
+		if (tmp->offset < offset)
+			delta += tmp->delta;
+	return delta;
+}
+
+struct compat_ipt_standard_target
+{
+	struct compat_xt_entry_target target;
+	compat_int_t verdict;
+};
+
+#define IPT_ST_OFFSET	(sizeof(struct ipt_standard_target) - \
+				sizeof(struct compat_ipt_standard_target))
+
+struct compat_ipt_standard
+{
+	struct compat_ipt_entry entry;
+	struct compat_ipt_standard_target target;
+};
+
+static int compat_ipt_standard_fn(void *target,
+		void **dstptr, int *size, int convert)
+{
+	struct compat_ipt_standard_target compat_st, *pcompat_st;
+	struct ipt_standard_target st, *pst;
+	int ret;
+
+	ret = 0;
+	switch (convert) {
+		case COMPAT_TO_USER:
+			pst = (struct ipt_standard_target *)target;
+			memcpy(&compat_st.target, &pst->target,
+					sizeof(struct ipt_entry_target));
+			compat_st.verdict = pst->verdict;
+			if (compat_st.verdict > 0)
+				compat_st.verdict -=
+					compat_calc_jump(compat_st.verdict);
+			compat_st.target.u.user.target_size =
+			sizeof(struct compat_ipt_standard_target);
+			if (__copy_to_user(*dstptr, &compat_st,
+				sizeof(struct compat_ipt_standard_target)))
+				ret = -EFAULT;
+			*size -= IPT_ST_OFFSET;
+			*dstptr += sizeof(struct compat_ipt_standard_target);
+			break;
+		case COMPAT_FROM_USER:
+			pcompat_st =
+				(struct compat_ipt_standard_target *)target;
+			memcpy(&st.target, &pcompat_st->target,
+					sizeof(struct ipt_entry_target));
+			st.verdict = pcompat_st->verdict;
+			if (st.verdict > 0)
+				st.verdict += compat_calc_jump(st.verdict);
+			st.target.u.user.target_size =
+			sizeof(struct ipt_standard_target);
+			memcpy(*dstptr, &st,
+					sizeof(struct ipt_standard_target));
+			*size += IPT_ST_OFFSET;
+			*dstptr += sizeof(struct ipt_standard_target);
+			break;
+		case COMPAT_CALC_SIZE:
+			*size += IPT_ST_OFFSET;
+			break;
+		default:
+			ret = -ENOPROTOOPT;
+			break;
+	}
+	return ret;
+}
+
+static inline int
+compat_calc_match(struct ipt_entry_match *m, int * size)
+{
+	if (m->u.kernel.match->compat)
+		m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+	else
+		xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+	return 0;
+}
+
+static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info,
+		void *base, struct xt_table_info *newinfo)
+{
+	struct ipt_entry_target *t;
+	u_int16_t entry_offset;
+	int off, i, ret;
+
+	off = 0;
+	entry_offset = (void *)e - base;
+	IPT_MATCH_ITERATE(e, compat_calc_match, &off);
+	t = ipt_get_target(e);
+	if (t->u.kernel.target->compat)
+		t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+	else
+		xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+	newinfo->size -= off;
+	ret = compat_add_offset(entry_offset, off);
+	if (ret)
+		return ret;
+
+	for (i = 0; i< NF_IP_NUMHOOKS; i++) {
+		if (info->hook_entry[i] && (e < (struct ipt_entry *)
+				(base + info->hook_entry[i])))
+			newinfo->hook_entry[i] -= off;
+		if (info->underflow[i] && (e < (struct ipt_entry *)
+				(base + info->underflow[i])))
+			newinfo->underflow[i] -= off;
+	}
+	return 0;
+}
+
+static int compat_table_info(struct xt_table_info *info,
+		struct xt_table_info *newinfo)
+{
+	void *loc_cpu_entry;
+	int i;
+
+	if (!newinfo || !info)
+		return -EINVAL;
+
+	memset(newinfo, 0, sizeof(struct xt_table_info));
+	newinfo->size = info->size;
+	newinfo->number = info->number;
+	for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+		newinfo->hook_entry[i] = info->hook_entry[i];
+		newinfo->underflow[i] = info->underflow[i];
+	}
+	loc_cpu_entry = info->entries[raw_smp_processor_id()];
+	return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,
+			compat_calc_entry, info, loc_cpu_entry, newinfo);
+}
+#endif
+
+static int get_info(void __user *user, int *len, int compat)
+{
+	char name[IPT_TABLE_MAXNAMELEN];
+	struct ipt_table *t;
+	int ret;
+
+	if (*len != sizeof(struct ipt_getinfo)) {
+		duprintf("length %u != %u\n", *len,
+			(unsigned int)sizeof(struct ipt_getinfo));
+		return -EINVAL;
+	}
+
+	if (copy_from_user(name, user, sizeof(name)) != 0)
+		return -EFAULT;
+
+	name[IPT_TABLE_MAXNAMELEN-1] = '\0';
+#ifdef CONFIG_COMPAT
+	if (compat)
+		xt_compat_lock(AF_INET);
+#endif
+	t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+			"iptable_%s", name);
+	if (t && !IS_ERR(t)) {
+		struct ipt_getinfo info;
+		struct xt_table_info *private = t->private;
+
+#ifdef CONFIG_COMPAT
+		if (compat) {
+			struct xt_table_info tmp;
+			ret = compat_table_info(private, &tmp);
+			compat_flush_offsets();
+			private =  &tmp;
+		}
+#endif
+		info.valid_hooks = t->valid_hooks;
+		memcpy(info.hook_entry, private->hook_entry,
+				sizeof(info.hook_entry));
+		memcpy(info.underflow, private->underflow,
+				sizeof(info.underflow));
+		info.num_entries = private->number;
+		info.size = private->size;
+		strcpy(info.name, name);
+
+		if (copy_to_user(user, &info, *len) != 0)
+			ret = -EFAULT;
+		else
+			ret = 0;
+
+		xt_table_unlock(t);
+		module_put(t->me);
+	} else
+		ret = t ? PTR_ERR(t) : -ENOENT;
+#ifdef CONFIG_COMPAT
+	if (compat)
+		xt_compat_unlock(AF_INET);
+#endif
+	return ret;
+}
+
 static int
-get_entries(const struct ipt_get_entries *entries,
-	    struct ipt_get_entries __user *uptr)
+get_entries(struct ipt_get_entries __user *uptr, int *len)
 {
 	int ret;
+	struct ipt_get_entries get;
 	struct ipt_table *t;
 
-	t = xt_find_table_lock(AF_INET, entries->name);
+	if (*len < sizeof(get)) {
+		duprintf("get_entries: %u < %d\n", *len,
+				(unsigned int)sizeof(get));
+		return -EINVAL;
+	}
+	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+		return -EFAULT;
+	if (*len != sizeof(struct ipt_get_entries) + get.size) {
+		duprintf("get_entries: %u != %u\n", *len,
+				(unsigned int)(sizeof(struct ipt_get_entries) +
+				get.size));
+		return -EINVAL;
+	}
+
+	t = xt_find_table_lock(AF_INET, get.name);
 	if (t && !IS_ERR(t)) {
 		struct xt_table_info *private = t->private;
 		duprintf("t->private->number = %u\n",
 			 private->number);
-		if (entries->size == private->size)
+		if (get.size == private->size)
 			ret = copy_entries_to_user(private->size,
 						   t, uptr->entrytable);
 		else {
 			duprintf("get_entries: I've got %u not %u!\n",
 				 private->size,
-				 entries->size);
+				 get.size);
 			ret = -EINVAL;
 		}
 		module_put(t->me);
@@ -914,14 +1181,81 @@
 }
 
 static int
+__do_replace(const char *name, unsigned int valid_hooks,
+		struct xt_table_info *newinfo, unsigned int num_counters,
+		void __user *counters_ptr)
+{
+	int ret;
+	struct ipt_table *t;
+	struct xt_table_info *oldinfo;
+	struct xt_counters *counters;
+	void *loc_cpu_old_entry;
+
+	ret = 0;
+	counters = vmalloc(num_counters * sizeof(struct xt_counters));
+	if (!counters) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	t = try_then_request_module(xt_find_table_lock(AF_INET, name),
+				    "iptable_%s", name);
+	if (!t || IS_ERR(t)) {
+		ret = t ? PTR_ERR(t) : -ENOENT;
+		goto free_newinfo_counters_untrans;
+	}
+
+	/* You lied! */
+	if (valid_hooks != t->valid_hooks) {
+		duprintf("Valid hook crap: %08X vs %08X\n",
+			 valid_hooks, t->valid_hooks);
+		ret = -EINVAL;
+		goto put_module;
+	}
+
+	oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
+	if (!oldinfo)
+		goto put_module;
+
+	/* Update module usage count based on number of rules */
+	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
+		oldinfo->number, oldinfo->initial_entries, newinfo->number);
+	if ((oldinfo->number > oldinfo->initial_entries) ||
+	    (newinfo->number <= oldinfo->initial_entries))
+		module_put(t->me);
+	if ((oldinfo->number > oldinfo->initial_entries) &&
+	    (newinfo->number <= oldinfo->initial_entries))
+		module_put(t->me);
+
+	/* Get the old counters. */
+	get_counters(oldinfo, counters);
+	/* Decrease module usage counts and free resource */
+	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+	IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
+	xt_free_table_info(oldinfo);
+	if (copy_to_user(counters_ptr, counters,
+			 sizeof(struct xt_counters) * num_counters) != 0)
+		ret = -EFAULT;
+	vfree(counters);
+	xt_table_unlock(t);
+	return ret;
+
+ put_module:
+	module_put(t->me);
+	xt_table_unlock(t);
+ free_newinfo_counters_untrans:
+	vfree(counters);
+ out:
+	return ret;
+}
+
+static int
 do_replace(void __user *user, unsigned int len)
 {
 	int ret;
 	struct ipt_replace tmp;
-	struct ipt_table *t;
-	struct xt_table_info *newinfo, *oldinfo;
-	struct xt_counters *counters;
-	void *loc_cpu_entry, *loc_cpu_old_entry;
+	struct xt_table_info *newinfo;
+	void *loc_cpu_entry;
 
 	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
 		return -EFAULT;
@@ -949,69 +1283,23 @@
 		goto free_newinfo;
 	}
 
-	counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
-	if (!counters) {
-		ret = -ENOMEM;
-		goto free_newinfo;
-	}
-
 	ret = translate_table(tmp.name, tmp.valid_hooks,
 			      newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
 			      tmp.hook_entry, tmp.underflow);
 	if (ret != 0)
-		goto free_newinfo_counters;
+		goto free_newinfo;
 
 	duprintf("ip_tables: Translated table\n");
 
-	t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
-				    "iptable_%s", tmp.name);
-	if (!t || IS_ERR(t)) {
-		ret = t ? PTR_ERR(t) : -ENOENT;
-		goto free_newinfo_counters_untrans;
-	}
+	ret = __do_replace(tmp.name, tmp.valid_hooks,
+			      newinfo, tmp.num_counters,
+			      tmp.counters);
+	if (ret)
+		goto free_newinfo_untrans;
+	return 0;
 
-	/* You lied! */
-	if (tmp.valid_hooks != t->valid_hooks) {
-		duprintf("Valid hook crap: %08X vs %08X\n",
-			 tmp.valid_hooks, t->valid_hooks);
-		ret = -EINVAL;
-		goto put_module;
-	}
-
-	oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
-	if (!oldinfo)
-		goto put_module;
-
-	/* Update module usage count based on number of rules */
-	duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n",
-		oldinfo->number, oldinfo->initial_entries, newinfo->number);
-	if ((oldinfo->number > oldinfo->initial_entries) || 
-	    (newinfo->number <= oldinfo->initial_entries)) 
-		module_put(t->me);
-	if ((oldinfo->number > oldinfo->initial_entries) &&
-	    (newinfo->number <= oldinfo->initial_entries))
-		module_put(t->me);
-
-	/* Get the old counters. */
-	get_counters(oldinfo, counters);
-	/* Decrease module usage counts and free resource */
-	loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
-	IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
-	xt_free_table_info(oldinfo);
-	if (copy_to_user(tmp.counters, counters,
-			 sizeof(struct xt_counters) * tmp.num_counters) != 0)
-		ret = -EFAULT;
-	vfree(counters);
-	xt_table_unlock(t);
-	return ret;
-
- put_module:
-	module_put(t->me);
-	xt_table_unlock(t);
- free_newinfo_counters_untrans:
+ free_newinfo_untrans:
 	IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
- free_newinfo_counters:
-	vfree(counters);
  free_newinfo:
 	xt_free_table_info(newinfo);
 	return ret;
@@ -1040,31 +1328,59 @@
 }
 
 static int
-do_add_counters(void __user *user, unsigned int len)
+do_add_counters(void __user *user, unsigned int len, int compat)
 {
 	unsigned int i;
-	struct xt_counters_info tmp, *paddc;
+	struct xt_counters_info tmp;
+	struct xt_counters *paddc;
+	unsigned int num_counters;
+	char *name;
+	int size;
+	void *ptmp;
 	struct ipt_table *t;
 	struct xt_table_info *private;
 	int ret = 0;
 	void *loc_cpu_entry;
+#ifdef CONFIG_COMPAT
+	struct compat_xt_counters_info compat_tmp;
 
-	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+	if (compat) {
+		ptmp = &compat_tmp;
+		size = sizeof(struct compat_xt_counters_info);
+	} else
+#endif
+	{
+		ptmp = &tmp;
+		size = sizeof(struct xt_counters_info);
+	}
+
+	if (copy_from_user(ptmp, user, size) != 0)
 		return -EFAULT;
 
-	if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
+#ifdef CONFIG_COMPAT
+	if (compat) {
+		num_counters = compat_tmp.num_counters;
+		name = compat_tmp.name;
+	} else
+#endif
+	{
+		num_counters = tmp.num_counters;
+		name = tmp.name;
+	}
+
+	if (len != size + num_counters * sizeof(struct xt_counters))
 		return -EINVAL;
 
-	paddc = vmalloc_node(len, numa_node_id());
+	paddc = vmalloc_node(len - size, numa_node_id());
 	if (!paddc)
 		return -ENOMEM;
 
-	if (copy_from_user(paddc, user, len) != 0) {
+	if (copy_from_user(paddc, user + size, len - size) != 0) {
 		ret = -EFAULT;
 		goto free;
 	}
 
-	t = xt_find_table_lock(AF_INET, tmp.name);
+	t = xt_find_table_lock(AF_INET, name);
 	if (!t || IS_ERR(t)) {
 		ret = t ? PTR_ERR(t) : -ENOENT;
 		goto free;
@@ -1072,7 +1388,7 @@
 
 	write_lock_bh(&t->lock);
 	private = t->private;
-	if (private->number != paddc->num_counters) {
+	if (private->number != num_counters) {
 		ret = -EINVAL;
 		goto unlock_up_free;
 	}
@@ -1083,7 +1399,7 @@
 	IPT_ENTRY_ITERATE(loc_cpu_entry,
 			  private->size,
 			  add_counter_to_entry,
-			  paddc->counters,
+			  paddc,
 			  &i);
  unlock_up_free:
 	write_unlock_bh(&t->lock);
@@ -1095,6 +1411,609 @@
 	return ret;
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_ipt_replace {
+	char			name[IPT_TABLE_MAXNAMELEN];
+	u32			valid_hooks;
+	u32			num_entries;
+	u32			size;
+	u32			hook_entry[NF_IP_NUMHOOKS];
+	u32			underflow[NF_IP_NUMHOOKS];
+	u32			num_counters;
+	compat_uptr_t		counters;	/* struct ipt_counters * */
+	struct compat_ipt_entry	entries[0];
+};
+
+static inline int compat_copy_match_to_user(struct ipt_entry_match *m,
+		void __user **dstptr, compat_uint_t *size)
+{
+	if (m->u.kernel.match->compat)
+		return m->u.kernel.match->compat(m, dstptr, size,
+				COMPAT_TO_USER);
+	else
+		return xt_compat_match(m, dstptr, size, COMPAT_TO_USER);
+}
+
+static int compat_copy_entry_to_user(struct ipt_entry *e,
+		void __user **dstptr, compat_uint_t *size)
+{
+	struct ipt_entry_target __user *t;
+	struct compat_ipt_entry __user *ce;
+	u_int16_t target_offset, next_offset;
+	compat_uint_t origsize;
+	int ret;
+
+	ret = -EFAULT;
+	origsize = *size;
+	ce = (struct compat_ipt_entry __user *)*dstptr;
+	if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
+		goto out;
+
+	*dstptr += sizeof(struct compat_ipt_entry);
+	ret = IPT_MATCH_ITERATE(e, compat_copy_match_to_user, dstptr, size);
+	target_offset = e->target_offset - (origsize - *size);
+	if (ret)
+		goto out;
+	t = ipt_get_target(e);
+	if (t->u.kernel.target->compat)
+		ret = t->u.kernel.target->compat(t, dstptr, size,
+				COMPAT_TO_USER);
+	else
+		ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER);
+	if (ret)
+		goto out;
+	ret = -EFAULT;
+	next_offset = e->next_offset - (origsize - *size);
+	if (__put_user(target_offset, &ce->target_offset))
+		goto out;
+	if (__put_user(next_offset, &ce->next_offset))
+		goto out;
+	return 0;
+out:
+	return ret;
+}
+
+static inline int
+compat_check_calc_match(struct ipt_entry_match *m,
+	    const char *name,
+	    const struct ipt_ip *ip,
+	    unsigned int hookmask,
+	    int *size, int *i)
+{
+	struct ipt_match *match;
+
+	match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
+						   m->u.user.revision),
+					"ipt_%s", m->u.user.name);
+	if (IS_ERR(match) || !match) {
+		duprintf("compat_check_calc_match: `%s' not found\n",
+				m->u.user.name);
+		return match ? PTR_ERR(match) : -ENOENT;
+	}
+	m->u.kernel.match = match;
+
+	if (m->u.kernel.match->compat)
+		m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE);
+	else
+		xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE);
+
+	(*i)++;
+	return 0;
+}
+
+static inline int
+check_compat_entry_size_and_hooks(struct ipt_entry *e,
+			   struct xt_table_info *newinfo,
+			   unsigned int *size,
+			   unsigned char *base,
+			   unsigned char *limit,
+			   unsigned int *hook_entries,
+			   unsigned int *underflows,
+			   unsigned int *i,
+			   const char *name)
+{
+	struct ipt_entry_target *t;
+	struct ipt_target *target;
+	u_int16_t entry_offset;
+	int ret, off, h, j;
+
+	duprintf("check_compat_entry_size_and_hooks %p\n", e);
+	if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0
+	    || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) {
+		duprintf("Bad offset %p, limit = %p\n", e, limit);
+		return -EINVAL;
+	}
+
+	if (e->next_offset < sizeof(struct compat_ipt_entry) +
+			sizeof(struct compat_xt_entry_target)) {
+		duprintf("checking: element %p size %u\n",
+			 e, e->next_offset);
+		return -EINVAL;
+	}
+
+	if (!ip_checkentry(&e->ip)) {
+		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+		return -EINVAL;
+	}
+
+	off = 0;
+	entry_offset = (void *)e - (void *)base;
+	j = 0;
+	ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+			e->comefrom, &off, &j);
+	if (ret != 0)
+		goto out;
+
+	t = ipt_get_target(e);
+	target = try_then_request_module(xt_find_target(AF_INET,
+						     t->u.user.name,
+						     t->u.user.revision),
+					 "ipt_%s", t->u.user.name);
+	if (IS_ERR(target) || !target) {
+		duprintf("check_entry: `%s' not found\n", t->u.user.name);
+		ret = target ? PTR_ERR(target) : -ENOENT;
+		goto out;
+	}
+	t->u.kernel.target = target;
+
+	if (t->u.kernel.target->compat)
+		t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE);
+	else
+		xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE);
+	*size += off;
+	ret = compat_add_offset(entry_offset, off);
+	if (ret)
+		goto out;
+
+	/* Check hooks & underflows */
+	for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+		if ((unsigned char *)e - base == hook_entries[h])
+			newinfo->hook_entry[h] = hook_entries[h];
+		if ((unsigned char *)e - base == underflows[h])
+			newinfo->underflow[h] = underflows[h];
+	}
+
+	/* Clear counters and comefrom */
+	e->counters = ((struct ipt_counters) { 0, 0 });
+	e->comefrom = 0;
+
+	(*i)++;
+	return 0;
+out:
+	IPT_MATCH_ITERATE(e, cleanup_match, &j);
+	return ret;
+}
+
+static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
+	void **dstptr, compat_uint_t *size, const char *name,
+	const struct ipt_ip *ip, unsigned int hookmask)
+{
+	struct ipt_entry_match *dm;
+	struct ipt_match *match;
+	int ret;
+
+	dm = (struct ipt_entry_match *)*dstptr;
+	match = m->u.kernel.match;
+	if (match->compat)
+		match->compat(m, dstptr, size, COMPAT_FROM_USER);
+	else
+		xt_compat_match(m, dstptr, size, COMPAT_FROM_USER);
+
+	ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
+			     name, hookmask, ip->proto,
+			     ip->invflags & IPT_INV_PROTO);
+	if (ret)
+		return ret;
+
+	if (m->u.kernel.match->checkentry
+	    && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
+					      dm->u.match_size - sizeof(*dm),
+					      hookmask)) {
+		duprintf("ip_tables: check failed for `%s'.\n",
+			 m->u.kernel.match->name);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
+	unsigned int *size, const char *name,
+	struct xt_table_info *newinfo, unsigned char *base)
+{
+	struct ipt_entry_target *t;
+	struct ipt_target *target;
+	struct ipt_entry *de;
+	unsigned int origsize;
+	int ret, h;
+
+	ret = 0;
+	origsize = *size;
+	de = (struct ipt_entry *)*dstptr;
+	memcpy(de, e, sizeof(struct ipt_entry));
+
+	*dstptr += sizeof(struct compat_ipt_entry);
+	ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
+			name, &de->ip, de->comefrom);
+	if (ret)
+		goto out;
+	de->target_offset = e->target_offset - (origsize - *size);
+	t = ipt_get_target(e);
+	target = t->u.kernel.target;
+	if (target->compat)
+		target->compat(t, dstptr, size, COMPAT_FROM_USER);
+	else
+		xt_compat_target(t, dstptr, size, COMPAT_FROM_USER);
+
+	de->next_offset = e->next_offset - (origsize - *size);
+	for (h = 0; h < NF_IP_NUMHOOKS; h++) {
+		if ((unsigned char *)de - base < newinfo->hook_entry[h])
+			newinfo->hook_entry[h] -= origsize - *size;
+		if ((unsigned char *)de - base < newinfo->underflow[h])
+			newinfo->underflow[h] -= origsize - *size;
+	}
+
+	t = ipt_get_target(de);
+	target = t->u.kernel.target;
+	ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+			      name, e->comefrom, e->ip.proto,
+			      e->ip.invflags & IPT_INV_PROTO);
+	if (ret)
+		goto out;
+
+	ret = -EINVAL;
+	if (t->u.kernel.target == &ipt_standard_target) {
+		if (!standard_check(t, *size))
+			goto out;
+	} else if (t->u.kernel.target->checkentry
+		   && !t->u.kernel.target->checkentry(name, de, target,
+				t->data, t->u.target_size - sizeof(*t),
+				de->comefrom)) {
+		duprintf("ip_tables: compat: check failed for `%s'.\n",
+			 t->u.kernel.target->name);
+		goto out;
+	}
+	ret = 0;
+out:
+	return ret;
+}
+
+static int
+translate_compat_table(const char *name,
+		unsigned int valid_hooks,
+		struct xt_table_info **pinfo,
+		void **pentry0,
+		unsigned int total_size,
+		unsigned int number,
+		unsigned int *hook_entries,
+		unsigned int *underflows)
+{
+	unsigned int i;
+	struct xt_table_info *newinfo, *info;
+	void *pos, *entry0, *entry1;
+	unsigned int size;
+	int ret;
+
+	info = *pinfo;
+	entry0 = *pentry0;
+	size = total_size;
+	info->number = number;
+
+	/* Init all hooks to impossible value. */
+	for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+		info->hook_entry[i] = 0xFFFFFFFF;
+		info->underflow[i] = 0xFFFFFFFF;
+	}
+
+	duprintf("translate_compat_table: size %u\n", info->size);
+	i = 0;
+	xt_compat_lock(AF_INET);
+	/* Walk through entries, checking offsets. */
+	ret = IPT_ENTRY_ITERATE(entry0, total_size,
+				check_compat_entry_size_and_hooks,
+				info, &size, entry0,
+				entry0 + total_size,
+				hook_entries, underflows, &i, name);
+	if (ret != 0)
+		goto out_unlock;
+
+	ret = -EINVAL;
+	if (i != number) {
+		duprintf("translate_compat_table: %u not %u entries\n",
+			 i, number);
+		goto out_unlock;
+	}
+
+	/* Check hooks all assigned */
+	for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+		/* Only hooks which are valid */
+		if (!(valid_hooks & (1 << i)))
+			continue;
+		if (info->hook_entry[i] == 0xFFFFFFFF) {
+			duprintf("Invalid hook entry %u %u\n",
+				 i, hook_entries[i]);
+			goto out_unlock;
+		}
+		if (info->underflow[i] == 0xFFFFFFFF) {
+			duprintf("Invalid underflow %u %u\n",
+				 i, underflows[i]);
+			goto out_unlock;
+		}
+	}
+
+	ret = -ENOMEM;
+	newinfo = xt_alloc_table_info(size);
+	if (!newinfo)
+		goto out_unlock;
+
+	newinfo->number = number;
+	for (i = 0; i < NF_IP_NUMHOOKS; i++) {
+		newinfo->hook_entry[i] = info->hook_entry[i];
+		newinfo->underflow[i] = info->underflow[i];
+	}
+	entry1 = newinfo->entries[raw_smp_processor_id()];
+	pos = entry1;
+	size =  total_size;
+	ret = IPT_ENTRY_ITERATE(entry0, total_size,
+			compat_copy_entry_from_user, &pos, &size,
+			name, newinfo, entry1);
+	compat_flush_offsets();
+	xt_compat_unlock(AF_INET);
+	if (ret)
+		goto free_newinfo;
+
+	ret = -ELOOP;
+	if (!mark_source_chains(newinfo, valid_hooks, entry1))
+		goto free_newinfo;
+
+	/* And one copy for every other CPU */
+	for_each_cpu(i)
+		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
+			memcpy(newinfo->entries[i], entry1, newinfo->size);
+
+	*pinfo = newinfo;
+	*pentry0 = entry1;
+	xt_free_table_info(info);
+	return 0;
+
+free_newinfo:
+	xt_free_table_info(newinfo);
+out:
+	return ret;
+out_unlock:
+	xt_compat_unlock(AF_INET);
+	goto out;
+}
+
+static int
+compat_do_replace(void __user *user, unsigned int len)
+{
+	int ret;
+	struct compat_ipt_replace tmp;
+	struct xt_table_info *newinfo;
+	void *loc_cpu_entry;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+		return -EFAULT;
+
+	/* Hack: Causes ipchains to give correct error msg --RR */
+	if (len != sizeof(tmp) + tmp.size)
+		return -ENOPROTOOPT;
+
+	/* overflow check */
+	if (tmp.size >= (INT_MAX - sizeof(struct xt_table_info)) / NR_CPUS -
+			SMP_CACHE_BYTES)
+		return -ENOMEM;
+	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
+		return -ENOMEM;
+
+	newinfo = xt_alloc_table_info(tmp.size);
+	if (!newinfo)
+		return -ENOMEM;
+
+	/* choose the copy that is our node/cpu */
+	loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+	if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
+			   tmp.size) != 0) {
+		ret = -EFAULT;
+		goto free_newinfo;
+	}
+
+	ret = translate_compat_table(tmp.name, tmp.valid_hooks,
+			      &newinfo, &loc_cpu_entry, tmp.size,
+			      tmp.num_entries, tmp.hook_entry, tmp.underflow);
+	if (ret != 0)
+		goto free_newinfo;
+
+	duprintf("compat_do_replace: Translated table\n");
+
+	ret = __do_replace(tmp.name, tmp.valid_hooks,
+			      newinfo, tmp.num_counters,
+			      compat_ptr(tmp.counters));
+	if (ret)
+		goto free_newinfo_untrans;
+	return 0;
+
+ free_newinfo_untrans:
+	IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
+ free_newinfo:
+	xt_free_table_info(newinfo);
+	return ret;
+}
+
+static int
+compat_do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user,
+		unsigned int len)
+{
+	int ret;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case IPT_SO_SET_REPLACE:
+		ret = compat_do_replace(user, len);
+		break;
+
+	case IPT_SO_SET_ADD_COUNTERS:
+		ret = do_add_counters(user, len, 1);
+		break;
+
+	default:
+		duprintf("do_ipt_set_ctl:  unknown request %i\n", cmd);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+struct compat_ipt_get_entries
+{
+	char name[IPT_TABLE_MAXNAMELEN];
+	compat_uint_t size;
+	struct compat_ipt_entry entrytable[0];
+};
+
+static int compat_copy_entries_to_user(unsigned int total_size,
+		     struct ipt_table *table, void __user *userptr)
+{
+	unsigned int off, num;
+	struct compat_ipt_entry e;
+	struct xt_counters *counters;
+	struct xt_table_info *private = table->private;
+	void __user *pos;
+	unsigned int size;
+	int ret = 0;
+	void *loc_cpu_entry;
+
+	counters = alloc_counters(table);
+	if (IS_ERR(counters))
+		return PTR_ERR(counters);
+
+	/* choose the copy that is on our node/cpu, ...
+	 * This choice is lazy (because current thread is
+	 * allowed to migrate to another cpu)
+	 */
+	loc_cpu_entry = private->entries[raw_smp_processor_id()];
+	pos = userptr;
+	size = total_size;
+	ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,
+			compat_copy_entry_to_user, &pos, &size);
+	if (ret)
+		goto free_counters;
+
+	/* ... then go back and fix counters and names */
+	for (off = 0, num = 0; off < size; off += e.next_offset, num++) {
+		unsigned int i;
+		struct ipt_entry_match m;
+		struct ipt_entry_target t;
+
+		ret = -EFAULT;
+		if (copy_from_user(&e, userptr + off,
+					sizeof(struct compat_ipt_entry)))
+			goto free_counters;
+		if (copy_to_user(userptr + off +
+			offsetof(struct compat_ipt_entry, counters),
+			 &counters[num], sizeof(counters[num])))
+			goto free_counters;
+
+		for (i = sizeof(struct compat_ipt_entry);
+				i < e.target_offset; i += m.u.match_size) {
+			if (copy_from_user(&m, userptr + off + i,
+					sizeof(struct ipt_entry_match)))
+				goto free_counters;
+			if (copy_to_user(userptr + off + i +
+				offsetof(struct ipt_entry_match, u.user.name),
+				m.u.kernel.match->name,
+				strlen(m.u.kernel.match->name) + 1))
+				goto free_counters;
+		}
+
+		if (copy_from_user(&t, userptr + off + e.target_offset,
+					sizeof(struct ipt_entry_target)))
+			goto free_counters;
+		if (copy_to_user(userptr + off + e.target_offset +
+			offsetof(struct ipt_entry_target, u.user.name),
+			t.u.kernel.target->name,
+			strlen(t.u.kernel.target->name) + 1))
+			goto free_counters;
+	}
+	ret = 0;
+free_counters:
+	vfree(counters);
+	return ret;
+}
+
+static int
+compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
+{
+	int ret;
+	struct compat_ipt_get_entries get;
+	struct ipt_table *t;
+
+
+	if (*len < sizeof(get)) {
+		duprintf("compat_get_entries: %u < %u\n",
+				*len, (unsigned int)sizeof(get));
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
+		return -EFAULT;
+
+	if (*len != sizeof(struct compat_ipt_get_entries) + get.size) {
+		duprintf("compat_get_entries: %u != %u\n", *len,
+			(unsigned int)(sizeof(struct compat_ipt_get_entries) +
+			get.size));
+		return -EINVAL;
+	}
+
+	xt_compat_lock(AF_INET);
+	t = xt_find_table_lock(AF_INET, get.name);
+	if (t && !IS_ERR(t)) {
+		struct xt_table_info *private = t->private;
+		struct xt_table_info info;
+		duprintf("t->private->number = %u\n",
+			 private->number);
+		ret = compat_table_info(private, &info);
+		if (!ret && get.size == info.size) {
+			ret = compat_copy_entries_to_user(private->size,
+						   t, uptr->entrytable);
+		} else if (!ret) {
+			duprintf("compat_get_entries: I've got %u not %u!\n",
+				 private->size,
+				 get.size);
+			ret = -EINVAL;
+		}
+		compat_flush_offsets();
+		module_put(t->me);
+		xt_table_unlock(t);
+	} else
+		ret = t ? PTR_ERR(t) : -ENOENT;
+
+	xt_compat_unlock(AF_INET);
+	return ret;
+}
+
+static int
+compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
+{
+	int ret;
+
+	switch (cmd) {
+	case IPT_SO_GET_INFO:
+		ret = get_info(user, len, 1);
+		break;
+	case IPT_SO_GET_ENTRIES:
+		ret = compat_get_entries(user, len);
+		break;
+	default:
+		duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+#endif
+
 static int
 do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user, unsigned int len)
 {
@@ -1109,7 +2028,7 @@
 		break;
 
 	case IPT_SO_SET_ADD_COUNTERS:
-		ret = do_add_counters(user, len);
+		ret = do_add_counters(user, len, 0);
 		break;
 
 	default:
@@ -1129,65 +2048,13 @@
 		return -EPERM;
 
 	switch (cmd) {
-	case IPT_SO_GET_INFO: {
-		char name[IPT_TABLE_MAXNAMELEN];
-		struct ipt_table *t;
-
-		if (*len != sizeof(struct ipt_getinfo)) {
-			duprintf("length %u != %u\n", *len,
-				 sizeof(struct ipt_getinfo));
-			ret = -EINVAL;
-			break;
-		}
-
-		if (copy_from_user(name, user, sizeof(name)) != 0) {
-			ret = -EFAULT;
-			break;
-		}
-		name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-
-		t = try_then_request_module(xt_find_table_lock(AF_INET, name),
-					    "iptable_%s", name);
-		if (t && !IS_ERR(t)) {
-			struct ipt_getinfo info;
-			struct xt_table_info *private = t->private;
-
-			info.valid_hooks = t->valid_hooks;
-			memcpy(info.hook_entry, private->hook_entry,
-			       sizeof(info.hook_entry));
-			memcpy(info.underflow, private->underflow,
-			       sizeof(info.underflow));
-			info.num_entries = private->number;
-			info.size = private->size;
-			memcpy(info.name, name, sizeof(info.name));
-
-			if (copy_to_user(user, &info, *len) != 0)
-				ret = -EFAULT;
-			else
-				ret = 0;
-			xt_table_unlock(t);
-			module_put(t->me);
-		} else
-			ret = t ? PTR_ERR(t) : -ENOENT;
-	}
-	break;
-
-	case IPT_SO_GET_ENTRIES: {
-		struct ipt_get_entries get;
-
-		if (*len < sizeof(get)) {
-			duprintf("get_entries: %u < %u\n", *len, sizeof(get));
-			ret = -EINVAL;
-		} else if (copy_from_user(&get, user, sizeof(get)) != 0) {
-			ret = -EFAULT;
-		} else if (*len != sizeof(struct ipt_get_entries) + get.size) {
-			duprintf("get_entries: %u != %u\n", *len,
-				 sizeof(struct ipt_get_entries) + get.size);
-			ret = -EINVAL;
-		} else
-			ret = get_entries(&get, user);
+	case IPT_SO_GET_INFO:
+		ret = get_info(user, len, 0);
 		break;
-	}
+
+	case IPT_SO_GET_ENTRIES:
+		ret = get_entries(user, len);
+		break;
 
 	case IPT_SO_GET_REVISION_MATCH:
 	case IPT_SO_GET_REVISION_TARGET: {
@@ -1336,6 +2203,9 @@
 	.name		= IPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET,
+#ifdef CONFIG_COMPAT
+	.compat		= &compat_ipt_standard_fn,
+#endif
 };
 
 static struct ipt_target ipt_error_target = {
@@ -1350,9 +2220,15 @@
 	.set_optmin	= IPT_BASE_CTL,
 	.set_optmax	= IPT_SO_SET_MAX+1,
 	.set		= do_ipt_set_ctl,
+#ifdef CONFIG_COMPAT
+	.compat_set	= compat_do_ipt_set_ctl,
+#endif
 	.get_optmin	= IPT_BASE_CTL,
 	.get_optmax	= IPT_SO_GET_MAX+1,
 	.get		= do_ipt_get_ctl,
+#ifdef CONFIG_COMPAT
+	.compat_get	= compat_do_ipt_get_ctl,
+#endif
 };
 
 static struct ipt_match icmp_matchstruct = {
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index e4768a3..aad9d28 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -725,22 +725,17 @@
 
 #endif /* CONFIG_PROC_FS */
 
-static int init_or_cleanup(int fini)
+static int __init ipt_clusterip_init(void)
 {
 	int ret;
 
-	if (fini)
-		goto cleanup;
+	ret = ipt_register_target(&clusterip_tgt);
+	if (ret < 0)
+		return ret;
 
-	if (ipt_register_target(&clusterip_tgt)) {
-		ret = -EINVAL;
-		goto cleanup_none;
-	}
-
-	if (nf_register_hook(&cip_arp_ops) < 0) {
-		ret = -EINVAL;
+	ret = nf_register_hook(&cip_arp_ops);
+	if (ret < 0)
 		goto cleanup_target;
-	}
 
 #ifdef CONFIG_PROC_FS
 	clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", proc_net);
@@ -753,31 +748,24 @@
 
 	printk(KERN_NOTICE "ClusterIP Version %s loaded successfully\n",
 		CLUSTERIP_VERSION);
-
 	return 0;
 
-cleanup:
+cleanup_hook:
+	nf_unregister_hook(&cip_arp_ops);
+cleanup_target:
+	ipt_unregister_target(&clusterip_tgt);
+	return ret;
+}
+
+static void __exit ipt_clusterip_fini(void)
+{
 	printk(KERN_NOTICE "ClusterIP Version %s unloading\n",
 		CLUSTERIP_VERSION);
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
 #endif
-cleanup_hook:
 	nf_unregister_hook(&cip_arp_ops);
-cleanup_target:
 	ipt_unregister_target(&clusterip_tgt);
-cleanup_none:
-	return -EINVAL;
-}
-
-static int __init ipt_clusterip_init(void)
-{
-	return init_or_cleanup(0);
-}
-
-static void __exit ipt_clusterip_fini(void)
-{
-	init_or_cleanup(1);
 }
 
 module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 4269a54..0bba3c2 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -106,7 +106,6 @@
 	struct rtable *rt;
 	u_int16_t tmp_port;
 	u_int32_t tmp_addr;
-	unsigned int tcplen;
 	int needs_ack;
 	int hh_len;
 
@@ -124,13 +123,7 @@
 		return;
 
 	/* Check checksum */
-	tcplen = oldskb->len - iph->ihl * 4;
-	if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
-	     (hook == NF_IP_LOCAL_IN &&
-	      oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
-	    csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
-	                      oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
-	                      skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+	if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
 		return;
 
 	if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
deleted file mode 100644
index 3840b41..0000000
--- a/net/ipv4/netfilter/ipt_esp.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Kernel module to match ESP parameters. */
-
-/* (C) 1999-2000 Yon Uriarte <yon@astaro.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-
-#include <linux/netfilter_ipv4/ipt_esp.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
-MODULE_DESCRIPTION("iptables ESP SPI match module");
-
-#ifdef DEBUG_CONNTRACK
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
-{
-	int r=0;
-        duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-        	min,spi,max);
-	r=(spi >= min && spi <= max) ^ invert;
-	duprintf(" result %s\n",r? "PASS" : "FAILED");
-	return r;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-	struct ip_esp_hdr _esp, *eh;
-	const struct ipt_esp *espinfo = matchinfo;
-
-	/* Must not be a fragment. */
-	if (offset)
-		return 0;
-
-	eh = skb_header_pointer(skb, protoff,
-				sizeof(_esp), &_esp);
-	if (eh == NULL) {
-		/* We've been asked to examine this packet, and we
-		 * can't.  Hence, no choice but to drop.
-		 */
-		duprintf("Dropping evil ESP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
-	}
-
-	return spi_match(espinfo->spis[0], espinfo->spis[1],
-			 ntohl(eh->spi),
-			 !!(espinfo->invflags & IPT_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-	   const void *ip_void,
-	   const struct xt_match *match,
-	   void *matchinfo,
-	   unsigned int matchinfosize,
-	   unsigned int hook_mask)
-{
-	const struct ipt_esp *espinfo = matchinfo;
-
-	/* Must specify no unknown invflags */
-	if (espinfo->invflags & ~IPT_ESP_INV_MASK) {
-		duprintf("ipt_esp: unknown flags %X\n", espinfo->invflags);
-		return 0;
-	}
-	return 1;
-}
-
-static struct ipt_match esp_match = {
-	.name		= "esp",
-	.match		= match,
-	.matchsize	= sizeof(struct ipt_esp),
-	.proto		= IPPROTO_ESP,
-	.checkentry	= checkentry,
-	.me		= THIS_MODULE,
-};
-
-static int __init ipt_esp_init(void)
-{
-	return ipt_register_match(&esp_match);
-}
-
-static void __exit ipt_esp_fini(void)
-{
-	ipt_unregister_match(&esp_match);
-}
-
-module_init(ipt_esp_init);
-module_exit(ipt_esp_fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
deleted file mode 100644
index ac95d83..0000000
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
-   the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-
-#include <linux/netfilter_ipv4/ipt_multiport.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("iptables multiple port match module");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
-	    u_int8_t count, u_int16_t src, u_int16_t dst)
-{
-	unsigned int i;
-	for (i=0; i<count; i++) {
-		if (flags != IPT_MULTIPORT_DESTINATION
-		    && portlist[i] == src)
-			return 1;
-
-		if (flags != IPT_MULTIPORT_SOURCE
-		    && portlist[i] == dst)
-			return 1;
-	}
-
-	return 0;
-}
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match_v1(const struct ipt_multiport_v1 *minfo,
-	       u_int16_t src, u_int16_t dst)
-{
-	unsigned int i;
-	u_int16_t s, e;
-
-	for (i=0; i < minfo->count; i++) {
-		s = minfo->ports[i];
-
-		if (minfo->pflags[i]) {
-			/* range port matching */
-			e = minfo->ports[++i];
-			duprintf("src or dst matches with %d-%d?\n", s, e);
-
-			if (minfo->flags == IPT_MULTIPORT_SOURCE
-			    && src >= s && src <= e)
-				return 1 ^ minfo->invert;
-			if (minfo->flags == IPT_MULTIPORT_DESTINATION
-			    && dst >= s && dst <= e)
-				return 1 ^ minfo->invert;
-			if (minfo->flags == IPT_MULTIPORT_EITHER
-			    && ((dst >= s && dst <= e)
-				|| (src >= s && src <= e)))
-				return 1 ^ minfo->invert;
-		} else {
-			/* exact port matching */
-			duprintf("src or dst matches with %d?\n", s);
-
-			if (minfo->flags == IPT_MULTIPORT_SOURCE
-			    && src == s)
-				return 1 ^ minfo->invert;
-			if (minfo->flags == IPT_MULTIPORT_DESTINATION
-			    && dst == s)
-				return 1 ^ minfo->invert;
-			if (minfo->flags == IPT_MULTIPORT_EITHER
-			    && (src == s || dst == s))
-				return 1 ^ minfo->invert;
-		}
-	}
- 
- 	return minfo->invert;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-	u16 _ports[2], *pptr;
-	const struct ipt_multiport *multiinfo = matchinfo;
-
-	if (offset)
-		return 0;
-
-	pptr = skb_header_pointer(skb, protoff,
-				  sizeof(_ports), _ports);
-	if (pptr == NULL) {
-		/* We've been asked to examine this packet, and we
-		 * can't.  Hence, no choice but to drop.
-		 */
-		duprintf("ipt_multiport:"
-			 " Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
-	}
-
-	return ports_match(multiinfo->ports,
-			   multiinfo->flags, multiinfo->count,
-			   ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static int
-match_v1(const struct sk_buff *skb,
-	 const struct net_device *in,
-	 const struct net_device *out,
-	 const struct xt_match *match,
-	 const void *matchinfo,
-	 int offset,
-	 unsigned int protoff,
-	 int *hotdrop)
-{
-	u16 _ports[2], *pptr;
-	const struct ipt_multiport_v1 *multiinfo = matchinfo;
-
-	if (offset)
-		return 0;
-
-	pptr = skb_header_pointer(skb, protoff,
-				  sizeof(_ports), _ports);
-	if (pptr == NULL) {
-		/* We've been asked to examine this packet, and we
-		 * can't.  Hence, no choice but to drop.
-		 */
-		duprintf("ipt_multiport:"
-			 " Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
-	}
-
-	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-static struct ipt_match multiport_match = {
-	.name		= "multiport",
-	.revision	= 0,
-	.match		= match,
-	.matchsize	= sizeof(struct ipt_multiport),
-	.me		= THIS_MODULE,
-};
-
-static struct ipt_match multiport_match_v1 = {
-	.name		= "multiport",
-	.revision	= 1,
-	.match		= match_v1,
-	.matchsize	= sizeof(struct ipt_multiport_v1),
-	.me		= THIS_MODULE,
-};
-
-static int __init ipt_multiport_init(void)
-{
-	int err;
-
-	err = ipt_register_match(&multiport_match);
-	if (!err) {
-		err = ipt_register_match(&multiport_match_v1);
-		if (err)
-			ipt_unregister_match(&multiport_match);
-	}
-
-	return err;
-}
-
-static void __exit ipt_multiport_fini(void)
-{
-	ipt_unregister_match(&multiport_match);
-	ipt_unregister_match(&multiport_match_v1);
-}
-
-module_init(ipt_multiport_init);
-module_exit(ipt_multiport_fini);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 3d80aef..7f41748 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -157,37 +157,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ipt_ops[0]);
+	ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ipt_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
-	ret = nf_register_hook(&ipt_ops[2]);
-	if (ret < 0)
-		goto cleanup_hook1;
-
 	return ret;
 
- cleanup_hook1:
-	nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
-	nf_unregister_hook(&ipt_ops[0]);
  cleanup_table:
 	ipt_unregister_table(&packet_filter);
-
 	return ret;
 }
 
 static void __exit iptable_filter_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ipt_ops[i]);
-
+	nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	ipt_unregister_table(&packet_filter);
 }
 
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 412fc96..397b95c 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -211,49 +211,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ipt_ops[0]);
+	ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ipt_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
-	ret = nf_register_hook(&ipt_ops[2]);
-	if (ret < 0)
-		goto cleanup_hook1;
-
-	ret = nf_register_hook(&ipt_ops[3]);
-	if (ret < 0)
-		goto cleanup_hook2;
-
-	ret = nf_register_hook(&ipt_ops[4]);
-	if (ret < 0)
-		goto cleanup_hook3;
-
 	return ret;
 
- cleanup_hook3:
-        nf_unregister_hook(&ipt_ops[3]);
- cleanup_hook2:
-        nf_unregister_hook(&ipt_ops[2]);
- cleanup_hook1:
-	nf_unregister_hook(&ipt_ops[1]);
- cleanup_hook0:
-	nf_unregister_hook(&ipt_ops[0]);
  cleanup_table:
 	ipt_unregister_table(&packet_mangler);
-
 	return ret;
 }
 
 static void __exit iptable_mangle_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ipt_ops[i]);
-
+	nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	ipt_unregister_table(&packet_mangler);
 }
 
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 03cc79a..7912cce 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -101,18 +101,18 @@
 /* 'raw' is the very first table. */
 static struct nf_hook_ops ipt_ops[] = {
 	{
-	  .hook = ipt_hook, 
-	  .pf = PF_INET, 
-	  .hooknum = NF_IP_PRE_ROUTING, 
-	  .priority = NF_IP_PRI_RAW,
-	  .owner = THIS_MODULE,
+		.hook = ipt_hook,
+		.pf = PF_INET,
+		.hooknum = NF_IP_PRE_ROUTING,
+		.priority = NF_IP_PRI_RAW,
+		.owner = THIS_MODULE,
 	},
 	{
-	  .hook = ipt_hook, 
-	  .pf = PF_INET, 
-	  .hooknum = NF_IP_LOCAL_OUT, 
-	  .priority = NF_IP_PRI_RAW,
-	  .owner = THIS_MODULE,
+		.hook = ipt_hook,
+		.pf = PF_INET,
+		.hooknum = NF_IP_LOCAL_OUT,
+		.priority = NF_IP_PRI_RAW,
+		.owner = THIS_MODULE,
 	},
 };
 
@@ -126,31 +126,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ipt_ops[0]);
+	ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ipt_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
 	return ret;
 
- cleanup_hook0:
-	nf_unregister_hook(&ipt_ops[0]);
  cleanup_table:
 	ipt_unregister_table(&packet_raw);
-
 	return ret;
 }
 
 static void __exit iptable_raw_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ipt_ops[i]);
-
+	nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
 	ipt_unregister_table(&packet_raw);
 }
 
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 4afbc69..5bc9f64 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -210,71 +210,63 @@
 
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
-static struct nf_hook_ops ipv4_conntrack_defrag_ops = {
-	.hook		= ipv4_conntrack_defrag,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_PRE_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_in_ops = {
-	.hook		= ipv4_conntrack_in,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_PRE_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = {
-	.hook           = ipv4_conntrack_defrag,
-	.owner          = THIS_MODULE,
-	.pf             = PF_INET,
-	.hooknum        = NF_IP_LOCAL_OUT,
-	.priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_out_ops = {
-	.hook		= ipv4_conntrack_local,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_OUT,
-	.priority	= NF_IP_PRI_CONNTRACK,
-};
-
-/* helpers */
-static struct nf_hook_ops ipv4_conntrack_helper_out_ops = {
-	.hook		= ipv4_conntrack_help,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
-	.hook		= ipv4_conntrack_help,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_CONNTRACK_HELPER,
-};
-
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv4_conntrack_out_ops = {
-	.hook		= ipv4_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_POST_ROUTING,
-	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
-};
-
-static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
-	.hook		= ipv4_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET,
-	.hooknum	= NF_IP_LOCAL_IN,
-	.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+static struct nf_hook_ops ipv4_conntrack_ops[] = {
+	{
+		.hook		= ipv4_conntrack_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv4_conntrack_in,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_PRE_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK,
+	},
+	{
+		.hook           = ipv4_conntrack_defrag,
+		.owner          = THIS_MODULE,
+		.pf             = PF_INET,
+		.hooknum        = NF_IP_LOCAL_OUT,
+		.priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv4_conntrack_local,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_OUT,
+		.priority	= NF_IP_PRI_CONNTRACK,
+	},
+	{
+		.hook		= ipv4_conntrack_help,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
+		.hook		= ipv4_conntrack_help,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_CONNTRACK_HELPER,
+	},
+	{
+		.hook		= ipv4_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_POST_ROUTING,
+		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+	},
+	{
+		.hook		= ipv4_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET,
+		.hooknum	= NF_IP_LOCAL_IN,
+		.priority	= NF_IP_PRI_CONNTRACK_CONFIRM,
+	},
 };
 
 #ifdef CONFIG_SYSCTL
@@ -440,16 +432,20 @@
 extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
 extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
 extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
+MODULE_LICENSE("GPL");
+
+static int __init nf_conntrack_l3proto_ipv4_init(void)
 {
 	int ret = 0;
 
-	if (!init) goto cleanup;
+	need_conntrack();
 
 	ret = nf_register_sockopt(&so_getorigdst);
 	if (ret < 0) {
 		printk(KERN_ERR "Unable to register netfilter socket option\n");
-		goto cleanup_nothing;
+		return ret;
 	}
 
 	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4);
@@ -476,84 +472,26 @@
 		goto cleanup_icmp;
 	}
 
-	ret = nf_register_hook(&ipv4_conntrack_defrag_ops);
+	ret = nf_register_hooks(ipv4_conntrack_ops,
+				ARRAY_SIZE(ipv4_conntrack_ops));
 	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n");
+		printk("nf_conntrack_ipv4: can't register hooks.\n");
 		goto cleanup_ipv4;
 	}
-	ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n");
-		goto cleanup_defragops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_in_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register pre-routing hook.\n");
-		goto cleanup_defraglocalops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_local_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register local out hook.\n");
-		goto cleanup_inops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_helper_in_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register local helper hook.\n");
-		goto cleanup_inandlocalops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_helper_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n");
-		goto cleanup_helperinops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register post-routing hook.\n");
-		goto cleanup_helperoutops;
-	}
-
-	ret = nf_register_hook(&ipv4_conntrack_local_in_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv4: can't register local in hook.\n");
-		goto cleanup_inoutandlocalops;
-	}
-
 #ifdef CONFIG_SYSCTL
 	nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
 	if (nf_ct_ipv4_sysctl_header == NULL) {
 		printk("nf_conntrack: can't register to sysctl.\n");
 		ret = -ENOMEM;
-		goto cleanup_localinops;
+		goto cleanup_hooks;
 	}
 #endif
 	return ret;
 
- cleanup:
-	synchronize_net();
 #ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
 #endif
-	nf_unregister_hook(&ipv4_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
-	nf_unregister_hook(&ipv4_conntrack_out_ops);
- cleanup_helperoutops:
-	nf_unregister_hook(&ipv4_conntrack_helper_out_ops);
- cleanup_helperinops:
-	nf_unregister_hook(&ipv4_conntrack_helper_in_ops);
- cleanup_inandlocalops:
-	nf_unregister_hook(&ipv4_conntrack_local_out_ops);
- cleanup_inops:
-	nf_unregister_hook(&ipv4_conntrack_in_ops);
- cleanup_defraglocalops:
-	nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops);
- cleanup_defragops:
-	nf_unregister_hook(&ipv4_conntrack_defrag_ops);
  cleanup_ipv4:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
  cleanup_icmp:
@@ -564,22 +502,21 @@
 	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
  cleanup_sockopt:
 	nf_unregister_sockopt(&so_getorigdst);
- cleanup_nothing:
 	return ret;
 }
 
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
-MODULE_LICENSE("GPL");
-
-static int __init nf_conntrack_l3proto_ipv4_init(void)
-{
-	need_conntrack();
-	return init_or_cleanup(1);
-}
-
 static void __exit nf_conntrack_l3proto_ipv4_fini(void)
 {
-	init_or_cleanup(0);
+	synchronize_net();
+#ifdef CONFIG_SYSCTL
+ 	unregister_sysctl_table(nf_ct_ipv4_sysctl_header);
+#endif
+	nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
+	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4);
+	nf_unregister_sockopt(&so_getorigdst);
 }
 
 module_init(nf_conntrack_l3proto_ipv4_init);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 52dc175..4b0d361 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,30 +235,14 @@
 	}
 
 	/* See ip_conntrack_proto_tcp.c */
-	if (hooknum != NF_IP_PRE_ROUTING)
-		goto checksum_skipped;
-
-	switch (skb->ip_summed) {
-	case CHECKSUM_HW:
-		if (!(u16)csum_fold(skb->csum))
-			break;
+	if (hooknum == NF_IP_PRE_ROUTING &&
+	    nf_ip_checksum(skb, hooknum, dataoff, 0)) {
 		if (LOG_INVALID(IPPROTO_ICMP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 				      "nf_ct_icmp: bad HW ICMP checksum ");
 		return -NF_ACCEPT;
-	case CHECKSUM_NONE:
-		if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
-			if (LOG_INVALID(IPPROTO_ICMP))
-				nf_log_packet(PF_INET, 0, skb, NULL, NULL,
-					      NULL,
-					      "nf_ct_icmp: bad ICMP checksum ");
-			return -NF_ACCEPT;
-		}
-	default:
-		break;
 	}
 
-checksum_skipped:
 	/*
 	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
 	 *
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 1b167c4b..d61e2a9 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -49,7 +49,7 @@
 	int res = 0;
 	int cpu;
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		res += proto->stats[cpu].inuse;
 
 	return res;
@@ -91,7 +91,7 @@
 	unsigned long res = 0;
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
 	}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94fcbc5..cc9423d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2741,7 +2741,10 @@
 	/* Reserve room for dummy headers, this skb can pass
 	   through good chunk of routing engine.
 	 */
-	skb->mac.raw = skb->data;
+	skb->mac.raw = skb->nh.raw = skb->data;
+
+	/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
+	skb->nh.iph->protocol = IPPROTO_ICMP;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
 	if (rta[RTA_SRC - 1])
@@ -3083,7 +3086,7 @@
 		memcpy(dst, src, length);
 
 		/* Add the other cpus in, one int at a time */
-		for_each_cpu(i) {
+		for_each_possible_cpu(i) {
 			unsigned int j;
 
 			src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 195d835..9f0cca4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4559,7 +4559,6 @@
 
 EXPORT_SYMBOL(sysctl_tcp_ecn);
 EXPORT_SYMBOL(sysctl_tcp_reordering);
-EXPORT_SYMBOL(sysctl_tcp_abc);
 EXPORT_SYMBOL(tcp_parse_options);
 EXPORT_SYMBOL(tcp_rcv_established);
 EXPORT_SYMBOL(tcp_rcv_state_process);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 9e85c04..672950e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1859,5 +1859,4 @@
 #endif
 EXPORT_SYMBOL(sysctl_local_port_range);
 EXPORT_SYMBOL(sysctl_tcp_low_latency);
-EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
 
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 9d79546..a28ae59 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,9 +59,6 @@
 int sysctl_tcp_mtu_probing = 0;
 int sysctl_tcp_base_mss = 512;
 
-EXPORT_SYMBOL(sysctl_tcp_mtu_probing);
-EXPORT_SYMBOL(sysctl_tcp_base_mss);
-
 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
 			     struct sk_buff *skb)
 {
@@ -536,6 +533,7 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *buff;
 	int nsize, old_factor;
+	int nlen;
 	u16 flags;
 
 	BUG_ON(len > skb->len);
@@ -554,7 +552,11 @@
 	buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
 	if (buff == NULL)
 		return -ENOMEM; /* We'll just try again later. */
+
 	sk_charge_skb(sk, buff);
+	nlen = skb->len - len - nsize;
+	buff->truesize += nlen;
+	skb->truesize -= nlen;
 
 	/* Correct the sequence numbers. */
 	TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
@@ -1040,7 +1042,8 @@
 	if (unlikely(buff == NULL))
 		return -ENOMEM;
 
-	buff->truesize = nlen;
+	sk_charge_skb(sk, buff);
+	buff->truesize += nlen;
 	skb->truesize -= nlen;
 
 	/* Correct the sequence numbers. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index 0d7d386..8d30c48 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -8,6 +8,8 @@
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <net/icmp.h>
+#include <net/ip.h>
 #include <net/protocol.h>
 #include <net/xfrm.h>
 
@@ -70,10 +72,16 @@
 {
 	struct xfrm_tunnel *handler;
 
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto drop;
+
 	for (handler = tunnel4_handlers; handler; handler = handler->next)
 		if (!handler->handler(skb))
 			return 0;
 
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+drop:
 	kfree_skb(skb);
 	return 0;
 }
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 850d919..3e174c8 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -37,8 +37,6 @@
 {
 	switch (nexthdr) {
 	case IPPROTO_IPIP:
-		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-			return -EINVAL;
 		*spi = skb->nh.iph->saddr;
 		*seq = 0;
 		return 0;
@@ -68,7 +66,7 @@
 {
 	int err;
 	u32 spi, seq;
-	struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
 	int decaps = 0;
@@ -90,14 +88,16 @@
 		if (unlikely(x->km.state != XFRM_STATE_VALID))
 			goto drop_unlock;
 
+		if ((x->encap ? x->encap->encap_type : 0) != encap_type)
+			goto drop_unlock;
+
 		if (x->props.replay_window && xfrm_replay_check(x, seq))
 			goto drop_unlock;
 
 		if (xfrm_state_check_expire(x))
 			goto drop_unlock;
 
-		xfrm_vec[xfrm_nr].decap.decap_type = encap_type;
-		if (x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb))
+		if (x->type->input(x, skb))
 			goto drop_unlock;
 
 		/* only the first xfrm gets the encap type */
@@ -111,7 +111,7 @@
 
 		spin_unlock(&x->lock);
 
-		xfrm_vec[xfrm_nr++].xvec = x;
+		xfrm_vec[xfrm_nr++] = x;
 
 		iph = skb->nh.iph;
 
@@ -153,7 +153,8 @@
 	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
 		goto drop;
 
-	memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+	memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+	       xfrm_nr * sizeof(xfrm_vec[0]));
 	skb->sp->len += xfrm_nr;
 
 	nf_reset(skb);
@@ -184,7 +185,7 @@
 	xfrm_state_put(x);
 drop:
 	while (--xfrm_nr >= 0)
-		xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
 
 	kfree_skb(skb);
 	return 0;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 2d67093..f8ceaa1 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -21,7 +21,7 @@
 	return 0;
 }
 
-static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
 {
 	return 0;
 }
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index cf58251..6778173 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -229,7 +229,7 @@
 	return err;
 }
 
-static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	/*
 	 * Before process AH
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 3dcaac7..22f0460 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -130,7 +130,7 @@
 	return err;
 }
 
-static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct ipv6hdr *iph;
 	struct ipv6_esp_hdr *esph;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2a1e7e4..a18d425 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -485,15 +485,27 @@
 	{ -1, }
 };
 
-int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
+int ipv6_parse_hopopts(struct sk_buff *skb)
 {
 	struct inet6_skb_parm *opt = IP6CB(skb);
 
+	/*
+	 * skb->nh.raw is equal to skb->data, and
+	 * skb->h.raw - skb->nh.raw is always equal to
+	 * sizeof(struct ipv6hdr) by definition of
+	 * hop-by-hop options.
+	 */
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
+	    !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
+		kfree_skb(skb);
+		return -1;
+	}
+
 	opt->hop = sizeof(struct ipv6hdr);
 	if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
 		skb->h.raw += (skb->h.raw[1]+1)<<3;
 		opt->nhoff = sizeof(struct ipv6hdr);
-		return sizeof(struct ipv6hdr);
+		return 1;
 	}
 	return -1;
 }
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 21eb725..1044b6f 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -717,7 +717,7 @@
 	struct sock *sk;
 	int err, i, j;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
 				       &per_cpu(__icmpv6_socket, i));
 		if (err < 0) {
@@ -763,7 +763,7 @@
 {
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		sock_release(per_cpu(__icmpv6_socket, i));
 	}
 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index bb8ffb8..2ae84c9 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -23,6 +23,86 @@
 #include <net/inet6_hashtables.h>
 #include <net/ip.h>
 
+void __inet6_hash(struct inet_hashinfo *hashinfo,
+				struct sock *sk)
+{
+	struct hlist_head *list;
+	rwlock_t *lock;
+
+	BUG_TRAP(sk_unhashed(sk));
+
+	if (sk->sk_state == TCP_LISTEN) {
+		list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+		lock = &hashinfo->lhash_lock;
+		inet_listen_wlock(hashinfo);
+	} else {
+		unsigned int hash;
+		sk->sk_hash = hash = inet6_sk_ehashfn(sk);
+		hash &= (hashinfo->ehash_size - 1);
+		list = &hashinfo->ehash[hash].chain;
+		lock = &hashinfo->ehash[hash].lock;
+		write_lock(lock);
+	}
+
+	__sk_add_node(sk, list);
+	sock_prot_inc_use(sk->sk_prot);
+	write_unlock(lock);
+}
+EXPORT_SYMBOL(__inet6_hash);
+
+/*
+ * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * The sockhash lock must be held as a reader here.
+ */
+struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo,
+					   const struct in6_addr *saddr,
+					   const u16 sport,
+					   const struct in6_addr *daddr,
+					   const u16 hnum,
+					   const int dif)
+{
+	struct sock *sk;
+	const struct hlist_node *node;
+	const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
+	/* Optimize here for direct hit, only listening connections can
+	 * have wildcards anyways.
+	 */
+	unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
+	struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
+
+	prefetch(head->chain.first);
+	read_lock(&head->lock);
+	sk_for_each(sk, node, &head->chain) {
+		/* For IPV6 do the cheaper port and family tests first. */
+		if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
+			goto hit; /* You sunk my battleship! */
+	}
+	/* Must check for a TIME_WAIT'er before going to listener hash. */
+	sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+		const struct inet_timewait_sock *tw = inet_twsk(sk);
+
+		if(*((__u32 *)&(tw->tw_dport))	== ports	&&
+		   sk->sk_family		== PF_INET6) {
+			const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
+
+			if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr)	&&
+			    ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr)	&&
+			    (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
+				goto hit;
+		}
+	}
+	read_unlock(&head->lock);
+	return NULL;
+
+hit:
+	sock_hold(sk);
+	read_unlock(&head->lock);
+	return sk;
+}
+EXPORT_SYMBOL(__inet6_lookup_established);
+
 struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
 				   const struct in6_addr *daddr,
 				   const unsigned short hnum, const int dif)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 29f7359..aceee25 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -114,11 +114,10 @@
 	}
 
 	if (hdr->nexthdr == NEXTHDR_HOP) {
-		if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
+		if (ipv6_parse_hopopts(skb) < 0) {
 			IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
 			return 0;
 		}
-		hdr = skb->nh.ipv6h;
 	}
 
 	return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ff9040c..a995796 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -519,9 +519,6 @@
 	struct ipv6hdr *ipv6h;
 	struct ip6_tnl *t;
 
-	if (!pskb_may_pull(skb, sizeof (*ipv6h)))
-		goto discard;
-
 	ipv6h = skb->nh.ipv6h;
 
 	read_lock(&ip6ip6_lock);
@@ -529,8 +526,7 @@
 	if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) {
 		if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 			read_unlock(&ip6ip6_lock);
-			kfree_skb(skb);
-			return 0;
+			goto discard;
 		}
 
 		if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
@@ -557,9 +553,11 @@
 		return 0;
 	}
 	read_unlock(&ip6ip6_lock);
-	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
-discard:
 	return 1;
+
+discard:
+	kfree_skb(skb);
+	return 0;
 }
 
 static inline struct ipv6_txoptions *create_tel(__u8 encap_limit)
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index d4cfec3..05eb67d 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -63,7 +63,7 @@
 static int ipcomp6_scratch_users;
 static LIST_HEAD(ipcomp6_tfms_list);
 
-static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err = 0;
 	u8 nexthdr = 0;
@@ -290,7 +290,7 @@
 	if (!scratches)
 		return;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		void *scratch = *per_cpu_ptr(scratches, i);
 
 		vfree(scratch);
@@ -313,7 +313,7 @@
 
 	ipcomp6_scratches = scratches;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
 		if (!scratch)
 			return NULL;
@@ -344,7 +344,7 @@
 	if (!tfms)
 		return;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
 		crypto_free_tfm(tfm);
 	}
@@ -384,7 +384,7 @@
 	if (!tfms)
 		goto error;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
 		if (!tfm)
 			goto error;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc..395a417 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -7,6 +7,7 @@
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
 #include <net/xfrm.h>
+#include <net/ip6_checksum.h>
 
 int ip6_route_me_harder(struct sk_buff *skb)
 {
@@ -54,7 +55,7 @@
 	struct in6_addr saddr;
 };
 
-static void save(const struct sk_buff *skb, struct nf_info *info)
+static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
 {
 	struct ip6_rt_info *rt_info = nf_info_reroute(info);
 
@@ -66,7 +67,7 @@
 	}
 }
 
-static int reroute(struct sk_buff **pskb, const struct nf_info *info)
+static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
 {
 	struct ip6_rt_info *rt_info = nf_info_reroute(info);
 
@@ -79,15 +80,50 @@
 	return 0;
 }
 
-static struct nf_queue_rerouter ip6_reroute = {
-	.rer_size	= sizeof(struct ip6_rt_info),
-	.save 		= &save,
-	.reroute	= &reroute,
+unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
+			     unsigned int dataoff, u_int8_t protocol)
+{
+	struct ipv6hdr *ip6h = skb->nh.ipv6h;
+	unsigned int csum = 0;
+
+	switch (skb->ip_summed) {
+	case CHECKSUM_HW:
+		if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN)
+			break;
+		if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+			    	     skb->len - dataoff, protocol,
+				     csum_sub(skb->csum,
+					      skb_checksum(skb, 0,
+							   dataoff, 0)))) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			break;
+		}
+		/* fall through */
+	case CHECKSUM_NONE:
+		skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+					     skb->len - dataoff,
+					     protocol,
+					     csum_sub(0,
+						      skb_checksum(skb, 0,
+							           dataoff, 0)));
+		csum = __skb_checksum_complete(skb);
+	}
+	return csum;
+}
+
+EXPORT_SYMBOL(nf_ip6_checksum);
+
+static struct nf_afinfo nf_ip6_afinfo = {
+	.family		= AF_INET6,
+	.checksum	= nf_ip6_checksum,
+	.saveroute	= nf_ip6_saveroute,
+	.reroute	= nf_ip6_reroute,
+	.route_key_size	= sizeof(struct ip6_rt_info),
 };
 
 int __init ipv6_netfilter_init(void)
 {
-	return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
+	return nf_register_afinfo(&nf_ip6_afinfo);
 }
 
 /* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +131,5 @@
  */
 void ipv6_netfilter_fini(void)
 {
-	nf_unregister_queue_rerouter(PF_INET6);
+	nf_unregister_afinfo(&nf_ip6_afinfo);
 }
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 98f7875..4bc4e5b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -87,16 +87,6 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP6_NF_MATCH_MULTIPORT
-	tristate "Multiple port match support"
-	depends on IP6_NF_IPTABLES
-	help
-	  Multiport matching allows you to match TCP or UDP packets based on
-	  a series of source or destination ports: normally a rule can only
-	  match a single range of ports.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 config IP6_NF_MATCH_OWNER
 	tristate "Owner match support"
 	depends on IP6_NF_IPTABLES
@@ -115,11 +105,11 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP6_NF_MATCH_AHESP
-	tristate "AH/ESP match support"
+config IP6_NF_MATCH_AH
+	tristate "AH match support"
 	depends on IP6_NF_IPTABLES
 	help
-	  This module allows one to match AH and ESP packets.
+	  This module allows one to match AH packets.
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 8436a1a..eeeb57d 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -8,9 +8,8 @@
 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
 obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
-obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
-obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index e81c6a9..b4b7d44 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -658,15 +658,11 @@
 	.outfn	= &ipq_enqueue_packet,
 };
 
-static int
-init_or_cleanup(int init)
+static int __init ip6_queue_init(void)
 {
 	int status = -ENOMEM;
 	struct proc_dir_entry *proc;
 	
-	if (!init)
-		goto cleanup;
-
 	netlink_register_notifier(&ipq_nl_notifier);
 	ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk,
 	                              THIS_MODULE);
@@ -693,11 +689,6 @@
 	}
 	return status;
 
-cleanup:
-	nf_unregister_queue_handlers(&nfqh);
-	synchronize_net();
-	ipq_flush(NF_DROP);
-	
 cleanup_sysctl:
 	unregister_sysctl_table(ipq_sysctl_header);
 	unregister_netdevice_notifier(&ipq_dev_notifier);
@@ -713,15 +704,21 @@
 	return status;
 }
 
-static int __init ip6_queue_init(void)
-{
-	
-	return init_or_cleanup(1);
-}
-
 static void __exit ip6_queue_fini(void)
 {
-	init_or_cleanup(0);
+	nf_unregister_queue_handlers(&nfqh);
+	synchronize_net();
+	ipq_flush(NF_DROP);
+
+	unregister_sysctl_table(ipq_sysctl_header);
+	unregister_netdevice_notifier(&ipq_dev_notifier);
+	proc_net_remove(IPQ_PROC_FS_NAME);
+
+	sock_release(ipqnl->sk_socket);
+	mutex_lock(&ipqnl_mutex);
+	mutex_unlock(&ipqnl_mutex);
+
+	netlink_unregister_notifier(&ipq_nl_notifier);
 }
 
 MODULE_DESCRIPTION("IPv6 packet queue handler");
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 3ecf2db..0a67303 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -288,19 +288,6 @@
 	table_base = (void *)private->entries[smp_processor_id()];
 	e = get_entry(table_base, private->hook_entry[hook]);
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	/* Check noone else using our table */
-	if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
-	    && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
-		printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
-		       smp_processor_id(),
-		       table->name,
-		       &((struct ip6t_entry *)table_base)->comefrom,
-		       ((struct ip6t_entry *)table_base)->comefrom);
-	}
-	((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
-#endif
-
 	/* For return from builtin chain */
 	back = get_entry(table_base, private->underflow[hook]);
 
@@ -788,7 +775,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		if (newinfo->entries[i] && newinfo->entries[i] != entry0)
 			memcpy(newinfo->entries[i], entry0, newinfo->size);
 	}
@@ -841,7 +828,7 @@
 			   counters,
 			   &i);
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (cpu == curcpu)
 			continue;
 		i = 0;
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
deleted file mode 100644
index 36bedad..0000000
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Kernel module to match ESP parameters. */
-/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/types.h>
-#include <net/checksum.h>
-#include <net/ipv6.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_esp.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IPv6 ESP match");
-MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
-{
-	int r=0;
-	DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-	       min,spi,max);
-	r=(spi >= min && spi <= max) ^ invert;
-	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
-	return r;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-	struct ip_esp_hdr _esp, *eh;
-	const struct ip6t_esp *espinfo = matchinfo;
-	unsigned int ptr;
-
-	/* Make sure this isn't an evil packet */
-	/*DEBUGP("ipv6_esp entered \n");*/
-
-	if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
-		return 0;
-
-	eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
-	if (eh == NULL) {
-		*hotdrop = 1;
-		return 0;
-	}
-
-	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
-
-	return (eh != NULL)
-		&& spi_match(espinfo->spis[0], espinfo->spis[1],
-			      ntohl(eh->spi),
-			      !!(espinfo->invflags & IP6T_ESP_INV_SPI));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-	   const void *ip,
-	   const struct xt_match *match,
-	   void *matchinfo,
-	   unsigned int matchinfosize,
-	   unsigned int hook_mask)
-{
-	const struct ip6t_esp *espinfo = matchinfo;
-
-	if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
-		DEBUGP("ip6t_esp: unknown flags %X\n",
-			 espinfo->invflags);
-		return 0;
-	}
-	return 1;
-}
-
-static struct ip6t_match esp_match = {
-	.name		= "esp",
-	.match		= match,
-	.matchsize	= sizeof(struct ip6t_esp),
-	.checkentry	= checkentry,
-	.me		= THIS_MODULE,
-};
-
-static int __init ip6t_esp_init(void)
-{
-	return ip6t_register_match(&esp_match);
-}
-
-static void __exit ip6t_esp_fini(void)
-{
-	ip6t_unregister_match(&esp_match);
-}
-
-module_init(ip6t_esp_init);
-module_exit(ip6t_esp_fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
deleted file mode 100644
index 10c48ba..0000000
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
-   the same place so we can treat them as equal. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/udp.h>
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include <linux/netfilter_ipv6/ip6t_multiport.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("ip6tables match for multiple ports");
-
-#if 0
-#define duprintf(format, args...) printk(format , ## args)
-#else
-#define duprintf(format, args...)
-#endif
-
-/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
-ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
-	    u_int8_t count, u_int16_t src, u_int16_t dst)
-{
-	unsigned int i;
-	for (i=0; i<count; i++) {
-		if (flags != IP6T_MULTIPORT_DESTINATION
-		    && portlist[i] == src)
-			return 1;
-
-		if (flags != IP6T_MULTIPORT_SOURCE
-		    && portlist[i] == dst)
-			return 1;
-	}
-
-	return 0;
-}
-
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-	u16 _ports[2], *pptr;
-	const struct ip6t_multiport *multiinfo = matchinfo;
-
-	/* Must not be a fragment. */
-	if (offset)
-		return 0;
-
-	/* Must be big enough to read ports (both UDP and TCP have
-	   them at the start). */
-	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
-	if (pptr == NULL) {
-		/* We've been asked to examine this packet, and we
-		 * can't.  Hence, no choice but to drop.
-		 */
-		duprintf("ip6t_multiport:"
-			 " Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
-	}
-
-	return ports_match(multiinfo->ports,
-			   multiinfo->flags, multiinfo->count,
-			   ntohs(pptr[0]), ntohs(pptr[1]));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-checkentry(const char *tablename,
-	   const void *info,
-	   const struct xt_match *match,
-	   void *matchinfo,
-	   unsigned int matchsize,
-	   unsigned int hook_mask)
-{
-	const struct ip6t_ip6 *ip = info;
-	const struct ip6t_multiport *multiinfo = matchinfo;
-
-	/* Must specify proto == TCP/UDP, no unknown flags or bad count */
-	return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
-		&& !(ip->invflags & IP6T_INV_PROTO)
-		&& (multiinfo->flags == IP6T_MULTIPORT_SOURCE
-		    || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
-		    || multiinfo->flags == IP6T_MULTIPORT_EITHER)
-		&& multiinfo->count <= IP6T_MULTI_PORTS;
-}
-
-static struct ip6t_match multiport_match = {
-	.name		= "multiport",
-	.match		= match,
-	.matchsize	= sizeof(struct ip6t_multiport),
-	.checkentry	= checkentry,
-	.me		= THIS_MODULE,
-};
-
-static int __init ip6t_multiport_init(void)
-{
-	return ip6t_register_match(&multiport_match);
-}
-
-static void __exit ip6t_multiport_fini(void)
-{
-	ip6t_unregister_match(&multiport_match);
-}
-
-module_init(ip6t_multiport_init);
-module_exit(ip6t_multiport_fini);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index e5e724d..60976c0 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -177,37 +177,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ip6t_ops[0]);
+	ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ip6t_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
-	ret = nf_register_hook(&ip6t_ops[2]);
-	if (ret < 0)
-		goto cleanup_hook1;
-
 	return ret;
 
- cleanup_hook1:
-	nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
-	nf_unregister_hook(&ip6t_ops[0]);
  cleanup_table:
 	ip6t_unregister_table(&packet_filter);
-
 	return ret;
 }
 
 static void __exit ip6table_filter_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ip6t_ops[i]);
-
+	nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	ip6t_unregister_table(&packet_filter);
 }
 
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index e1f0f6a..03a13ea 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -238,49 +238,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ip6t_ops[0]);
+	ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ip6t_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
-	ret = nf_register_hook(&ip6t_ops[2]);
-	if (ret < 0)
-		goto cleanup_hook1;
-
-	ret = nf_register_hook(&ip6t_ops[3]);
-	if (ret < 0)
-		goto cleanup_hook2;
-
-	ret = nf_register_hook(&ip6t_ops[4]);
-	if (ret < 0)
-		goto cleanup_hook3;
-
 	return ret;
 
- cleanup_hook3:
-        nf_unregister_hook(&ip6t_ops[3]);
- cleanup_hook2:
-	nf_unregister_hook(&ip6t_ops[2]);
- cleanup_hook1:
-	nf_unregister_hook(&ip6t_ops[1]);
- cleanup_hook0:
-	nf_unregister_hook(&ip6t_ops[0]);
  cleanup_table:
 	ip6t_unregister_table(&packet_mangler);
-
 	return ret;
 }
 
 static void __exit ip6table_mangle_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ip6t_ops[i]);
-
+	nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	ip6t_unregister_table(&packet_mangler);
 }
 
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 54d1fff..61a7c58 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -152,31 +152,20 @@
 		return ret;
 
 	/* Register hooks */
-	ret = nf_register_hook(&ip6t_ops[0]);
+	ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	if (ret < 0)
 		goto cleanup_table;
 
-	ret = nf_register_hook(&ip6t_ops[1]);
-	if (ret < 0)
-		goto cleanup_hook0;
-
 	return ret;
 
- cleanup_hook0:
-	nf_unregister_hook(&ip6t_ops[0]);
  cleanup_table:
 	ip6t_unregister_table(&packet_raw);
-
 	return ret;
 }
 
 static void __exit ip6table_raw_fini(void)
 {
-	unsigned int i;
-
-	for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
-		nf_unregister_hook(&ip6t_ops[i]);
-
+	nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops));
 	ip6t_unregister_table(&packet_raw);
 }
 
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index c8b5a96..93bae36 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -286,55 +286,49 @@
 	return ipv6_conntrack_in(hooknum, pskb, in, out, okfn);
 }
 
-/* Connection tracking may drop packets, but never alters them, so
-   make it the first hook. */
-static struct nf_hook_ops ipv6_conntrack_defrag_ops = {
-	.hook		= ipv6_defrag,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_PRE_ROUTING,
-	.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-static struct nf_hook_ops ipv6_conntrack_in_ops = {
-	.hook		= ipv6_conntrack_in,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_PRE_ROUTING,
-	.priority	= NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_out_ops = {
-	.hook		= ipv6_conntrack_local,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_LOCAL_OUT,
-	.priority	= NF_IP6_PRI_CONNTRACK,
-};
-
-static struct nf_hook_ops ipv6_conntrack_defrag_local_out_ops = {
-	.hook		= ipv6_defrag,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_LOCAL_OUT,
-	.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
-};
-
-/* Refragmenter; last chance. */
-static struct nf_hook_ops ipv6_conntrack_out_ops = {
-	.hook		= ipv6_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_POST_ROUTING,
-	.priority	= NF_IP6_PRI_LAST,
-};
-
-static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
-	.hook		= ipv6_confirm,
-	.owner		= THIS_MODULE,
-	.pf		= PF_INET6,
-	.hooknum	= NF_IP6_LOCAL_IN,
-	.priority	= NF_IP6_PRI_LAST-1,
+static struct nf_hook_ops ipv6_conntrack_ops[] = {
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv6_conntrack_in,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_PRE_ROUTING,
+		.priority	= NF_IP6_PRI_CONNTRACK,
+	},
+	{
+		.hook		= ipv6_conntrack_local,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_CONNTRACK,
+	},
+	{
+		.hook		= ipv6_defrag,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_OUT,
+		.priority	= NF_IP6_PRI_CONNTRACK_DEFRAG,
+	},
+	{
+		.hook		= ipv6_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_POST_ROUTING,
+		.priority	= NF_IP6_PRI_LAST,
+	},
+	{
+		.hook		= ipv6_confirm,
+		.owner		= THIS_MODULE,
+		.pf		= PF_INET6,
+		.hooknum	= NF_IP6_LOCAL_IN,
+		.priority	= NF_IP6_PRI_LAST-1,
+	},
 };
 
 #ifdef CONFIG_SYSCTL
@@ -470,16 +464,21 @@
 extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6;
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
-static int init_or_cleanup(int init)
+
+MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
+
+static int __init nf_conntrack_l3proto_ipv6_init(void)
 {
 	int ret = 0;
 
-	if (!init) goto cleanup;
+	need_conntrack();
 
 	ret = nf_ct_frag6_init();
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't initialize frag6.\n");
-		goto cleanup_nothing;
+		return ret;
 	}
 	ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6);
 	if (ret < 0) {
@@ -505,71 +504,27 @@
 		goto cleanup_icmpv6;
 	}
 
-	ret = nf_register_hook(&ipv6_conntrack_defrag_ops);
+	ret = nf_register_hooks(ipv6_conntrack_ops,
+				ARRAY_SIZE(ipv6_conntrack_ops));
 	if (ret < 0) {
 		printk("nf_conntrack_ipv6: can't register pre-routing defrag "
 		       "hook.\n");
 		goto cleanup_ipv6;
 	}
-
-	ret = nf_register_hook(&ipv6_conntrack_defrag_local_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv6: can't register local_out defrag "
-		       "hook.\n");
-		goto cleanup_defragops;
-	}
-
-	ret = nf_register_hook(&ipv6_conntrack_in_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv6: can't register pre-routing hook.\n");
-		goto cleanup_defraglocalops;
-	}
-
-	ret = nf_register_hook(&ipv6_conntrack_local_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv6: can't register local out hook.\n");
-		goto cleanup_inops;
-	}
-
-	ret = nf_register_hook(&ipv6_conntrack_out_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv6: can't register post-routing hook.\n");
-		goto cleanup_inandlocalops;
-	}
-
-	ret = nf_register_hook(&ipv6_conntrack_local_in_ops);
-	if (ret < 0) {
-		printk("nf_conntrack_ipv6: can't register local in hook.\n");
-		goto cleanup_inoutandlocalops;
-	}
-
 #ifdef CONFIG_SYSCTL
 	nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
 	if (nf_ct_ipv6_sysctl_header == NULL) {
 		printk("nf_conntrack: can't register to sysctl.\n");
 		ret = -ENOMEM;
-		goto cleanup_localinops;
+		goto cleanup_hooks;
 	}
 #endif
 	return ret;
 
- cleanup:
-	synchronize_net();
 #ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
- cleanup_localinops:
+ cleanup_hooks:
+	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
 #endif
-	nf_unregister_hook(&ipv6_conntrack_local_in_ops);
- cleanup_inoutandlocalops:
-	nf_unregister_hook(&ipv6_conntrack_out_ops);
- cleanup_inandlocalops:
-	nf_unregister_hook(&ipv6_conntrack_local_out_ops);
- cleanup_inops:
-	nf_unregister_hook(&ipv6_conntrack_in_ops);
- cleanup_defraglocalops:
-	nf_unregister_hook(&ipv6_conntrack_defrag_local_out_ops);
- cleanup_defragops:
-	nf_unregister_hook(&ipv6_conntrack_defrag_ops);
  cleanup_ipv6:
 	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
  cleanup_icmpv6:
@@ -580,23 +535,21 @@
 	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
  cleanup_frag6:
 	nf_ct_frag6_cleanup();
- cleanup_nothing:
 	return ret;
 }
 
-MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
-
-static int __init nf_conntrack_l3proto_ipv6_init(void)
-{
-	need_conntrack();
-	return init_or_cleanup(1);
-}
-
 static void __exit nf_conntrack_l3proto_ipv6_fini(void)
 {
-	init_or_cleanup(0);
+	synchronize_net();
+#ifdef CONFIG_SYSCTL
+ 	unregister_sysctl_table(nf_ct_ipv6_sysctl_header);
+#endif
+	nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
+	nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6);
+	nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6);
+	nf_ct_frag6_cleanup();
 }
 
 module_init(nf_conntrack_l3proto_ipv6_init);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 09945c3..86c6703 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,21 +233,13 @@
 		return -NF_ACCEPT;
 	}
 
-	if (hooknum != NF_IP6_PRE_ROUTING)
-		goto skipped;
-
-	/* Ignore it if the checksum's bogus. */
-	if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
-			    skb->len - dataoff, IPPROTO_ICMPV6,
-			    skb_checksum(skb, dataoff,
-					 skb->len - dataoff, 0))) {
+	if (hooknum == NF_IP6_PRE_ROUTING &&
+	    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
 		nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
 			      "nf_ct_icmpv6: ICMPv6 checksum failed\n");
 		return -NF_ACCEPT;
 	}
 
-skipped:
-
 	/* is not error message ? */
 	if (icmp6h->icmp6_type >= 128)
 		return NF_ACCEPT;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 4238b1e..779ddf7 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -38,7 +38,7 @@
 	int res = 0;
 	int cpu;
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		res += proto->stats[cpu].inuse;
 
 	return res;
@@ -140,7 +140,7 @@
         unsigned long res = 0;
         int i;
  
-        for_each_cpu(i) {
+        for_each_possible_cpu(i) {
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
         }
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b67a45f..eef985e 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -121,6 +121,10 @@
 	write_unlock(&ip6_frag_lock);
 }
 
+/*
+ * callers should be careful not to use the hash value outside the ipfrag_lock
+ * as doing so could race with ipfrag_hash_rnd being recalculated.
+ */
 static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
 			       struct in6_addr *daddr)
 {
@@ -324,15 +328,16 @@
 /* Creation primitives. */
 
 
-static struct frag_queue *ip6_frag_intern(unsigned int hash,
-					  struct frag_queue *fq_in)
+static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
 {
 	struct frag_queue *fq;
+	unsigned int hash;
 #ifdef CONFIG_SMP
 	struct hlist_node *n;
 #endif
 
 	write_lock(&ip6_frag_lock);
+	hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
 #ifdef CONFIG_SMP
 	hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
 		if (fq->id == fq_in->id && 
@@ -362,7 +367,7 @@
 
 
 static struct frag_queue *
-ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst)
 {
 	struct frag_queue *fq;
 
@@ -379,7 +384,7 @@
 	spin_lock_init(&fq->lock);
 	atomic_set(&fq->refcnt, 1);
 
-	return ip6_frag_intern(hash, fq);
+	return ip6_frag_intern(fq);
 
 oom:
 	IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
@@ -391,9 +396,10 @@
 {
 	struct frag_queue *fq;
 	struct hlist_node *n;
-	unsigned int hash = ip6qhashfn(id, src, dst);
+	unsigned int hash;
 
 	read_lock(&ip6_frag_lock);
+	hash = ip6qhashfn(id, src, dst);
 	hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) {
 		if (fq->id == id && 
 		    ipv6_addr_equal(src, &fq->saddr) &&
@@ -405,7 +411,7 @@
 	}
 	read_unlock(&ip6_frag_lock);
 
-	return ip6_frag_create(hash, id, src, dst);
+	return ip6_frag_create(id, src, dst);
 }
 
 
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c2d3e17..6578c30 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -397,7 +397,7 @@
 		return 0;
 	}
 
-	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
+	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 	kfree_skb(skb);
 	read_unlock(&ipip6_lock);
 out:
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c
index 5659b52..0ef9a35 100644
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -19,11 +19,13 @@
  * 		YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
  */
 
+#include <linux/icmpv6.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <net/ipv6.h>
 #include <net/protocol.h>
 #include <net/xfrm.h>
 
@@ -87,10 +89,16 @@
 	struct sk_buff *skb = *pskb;
 	struct xfrm6_tunnel *handler;
 
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto drop;
+
 	for (handler = tunnel6_handlers; handler; handler = handler->next)
 		if (!handler->handler(skb))
 			return 0;
 
+	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
+
+drop:
 	kfree_skb(skb);
 	return 0;
 }
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index cccf8b7..00cfdee 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -32,7 +32,7 @@
 {
 	int err;
 	u32 seq;
-	struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
+	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
 	int decaps = 0;
@@ -65,7 +65,7 @@
 		if (xfrm_state_check_expire(x))
 			goto drop_unlock;
 
-		nexthdr = x->type->input(x, &(xfrm_vec[xfrm_nr].decap), skb);
+		nexthdr = x->type->input(x, skb);
 		if (nexthdr <= 0)
 			goto drop_unlock;
 
@@ -79,7 +79,7 @@
 
 		spin_unlock(&x->lock);
 
-		xfrm_vec[xfrm_nr++].xvec = x;
+		xfrm_vec[xfrm_nr++] = x;
 
 		if (x->props.mode) { /* XXX */
 			if (nexthdr != IPPROTO_IPV6)
@@ -118,7 +118,8 @@
 	if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
 		goto drop;
 
-	memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
+	memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
+	       xfrm_nr * sizeof(xfrm_vec[0]));
 	skb->sp->len += xfrm_nr;
 	skb->ip_summed = CHECKSUM_NONE;
 
@@ -149,7 +150,7 @@
 	xfrm_state_put(x);
 drop:
 	while (--xfrm_nr >= 0)
-		xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
+		xfrm_state_put(xfrm_vec[xfrm_nr]);
 	kfree_skb(skb);
 	return -1;
 }
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 91cce8b..88c840f 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -191,16 +191,18 @@
 static inline void
 _decode_session6(struct sk_buff *skb, struct flowi *fl)
 {
-	u16 offset = sizeof(struct ipv6hdr);
+	u16 offset = skb->h.raw - skb->nh.raw;
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
-	struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
+	struct ipv6_opt_hdr *exthdr;
+	u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
 
 	memset(fl, 0, sizeof(struct flowi));
 	ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
 	ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
 
 	while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+		exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+
 		switch (nexthdr) {
 		case NEXTHDR_ROUTING:
 		case NEXTHDR_HOP:
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index a8f6776..d37768e 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -351,7 +351,7 @@
 	return 0;
 }
 
-static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	return 0;
 }
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 8f3addf..d62e0f9 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -118,7 +118,8 @@
 		u16 pdulen = eth_hdr(skb)->h_proto,
 		    data_size = ntohs(pdulen) - llc_len;
 
-		skb_trim(skb, data_size);
+		if (unlikely(pskb_trim_rcsum(skb, data_size)))
+			return 0;
 	}
 	return 1;
 }
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 332acb3..e2893ef 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -231,6 +231,15 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_ESP
+	tristate '"ESP" match support'
+	depends on NETFILTER_XTABLES
+	help
+	  This match extension allows you to match a range of SPIs
+	  inside ESP header of IPSec packets.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_HELPER
 	tristate '"helper" match support'
 	depends on NETFILTER_XTABLES
@@ -289,6 +298,16 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_MULTIPORT
+	tristate "Multiple port match support"
+	depends on NETFILTER_XTABLES
+	help
+	  Multiport matching allows you to match TCP or UDP packets based on
+	  a series of source or destination ports: normally a rule can only
+	  match a single range of ports.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_PHYSDEV
 	tristate '"physdev" match support'
 	depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9558727..95b7e41 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -35,11 +35,13 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1ceb1a6..8455a32 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
 
 #include "nf_internals.h"
 
+static DEFINE_SPINLOCK(afinfo_lock);
+
+struct nf_afinfo *nf_afinfo[NPROTO];
+EXPORT_SYMBOL(nf_afinfo);
+
+int nf_register_afinfo(struct nf_afinfo *afinfo)
+{
+	spin_lock(&afinfo_lock);
+	rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
+	spin_unlock(&afinfo_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nf_register_afinfo);
+
+void nf_unregister_afinfo(struct nf_afinfo *afinfo)
+{
+	spin_lock(&afinfo_lock);
+	rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
+	spin_unlock(&afinfo_lock);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
+
 /* In this code, we can be waiting indefinitely for userspace to
  * service a packet if a hook returns NF_QUEUE.  We could keep a count
  * of skbuffs queued for userspace, and not deregister a hook unless
@@ -63,6 +86,34 @@
 }
 EXPORT_SYMBOL(nf_unregister_hook);
 
+int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+	unsigned int i;
+	int err = 0;
+
+	for (i = 0; i < n; i++) {
+		err = nf_register_hook(&reg[i]);
+		if (err)
+			goto err;
+	}
+	return err;
+
+err:
+	if (i > 0)
+		nf_unregister_hooks(reg, i);
+	return err;
+}
+EXPORT_SYMBOL(nf_register_hooks);
+
+void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; i++)
+		nf_unregister_hook(&reg[i]);
+}
+EXPORT_SYMBOL(nf_unregister_hooks);
+
 unsigned int nf_iterate(struct list_head *head,
 			struct sk_buff **skb,
 			int hook,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 56389c8..f9b83f9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -146,7 +146,7 @@
 	struct nf_conntrack_ecache *ecache;
 	int cpu;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		ecache = &per_cpu(nf_conntrack_ecache, cpu);
 		if (ecache->ct)
 			nf_ct_put(ecache->ct);
@@ -178,9 +178,6 @@
 	/* allocated slab cache + modules which uses this slab cache */
 	int use;
 
-	/* Initialization */
-	int (*init_conntrack)(struct nf_conn *, u_int32_t);
-
 } nf_ct_cache[NF_CT_F_NUM];
 
 /* protect members of nf_ct_cache except of "use" */
@@ -208,10 +205,8 @@
 
 	preempt_disable();
 	p = __nf_ct_proto_find(l3proto, protocol);
-	if (p) {
-		if (!try_module_get(p->me))
-			p = &nf_conntrack_generic_protocol;
-	}
+	if (!try_module_get(p->me))
+		p = &nf_conntrack_generic_protocol;
 	preempt_enable();
 	
 	return p;
@@ -229,10 +224,8 @@
 
 	preempt_disable();
 	p = __nf_ct_l3proto_find(l3proto);
-	if (p) {
-		if (!try_module_get(p->me))
-			p = &nf_conntrack_generic_l3proto;
-	}
+	if (!try_module_get(p->me))
+		p = &nf_conntrack_generic_l3proto;
 	preempt_enable();
 
 	return p;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index 7de4f06..3fc58e4 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -94,5 +94,4 @@
 	.print_conntrack = generic_print_conntrack,
 	.prepare	 = generic_prepare,
 	.get_features	 = generic_get_features,
-	.me		 = THIS_MODULE,
 };
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 0e0e9d7..bd10eb9 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1022,7 +1022,7 @@
 			return err;
 	}
 
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK-1])
 		ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
@@ -1062,7 +1062,7 @@
 			return err;
 	}
 
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK-1])
 		ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
@@ -1687,7 +1687,7 @@
 	printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
-	nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+	nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
 	nf_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6492ed6..69899f2 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -799,8 +799,7 @@
 		     unsigned int dataoff,
 		     enum ip_conntrack_info *ctinfo,
 		     int pf,
-		     unsigned int hooknum,
-		     int(*csum)(const struct sk_buff *,unsigned int))
+		     unsigned int hooknum)
 {
 	struct tcphdr _tcph, *th;
 	unsigned int tcplen = skb->len - dataoff;
@@ -830,9 +829,8 @@
 	 */
 	/* FIXME: Source route IP option packets --RR */
 	if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
-	     (pf == PF_INET6 && hooknum  == NF_IP6_PRE_ROUTING))
-	    && skb->ip_summed != CHECKSUM_UNNECESSARY
-	    && csum(skb, dataoff)) {
+	     (pf == PF_INET6 && hooknum  == NF_IP6_PRE_ROUTING)) &&
+	    nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
 				  "nf_ct_tcp: bad TCP checksum ");
@@ -851,44 +849,6 @@
 	return NF_ACCEPT;
 }
 
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
-	return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
-				 skb->len - dataoff, IPPROTO_TCP,
-			         skb->ip_summed == CHECKSUM_HW ? skb->csum
-			      	 : skb_checksum(skb, dataoff,
-						skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
-	return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
-			       skb->len - dataoff, IPPROTO_TCP,
-			       skb->ip_summed == CHECKSUM_HW
-			       ? csum_sub(skb->csum,
-					  skb_checksum(skb, 0, dataoff, 0))
-			       : skb_checksum(skb, dataoff, skb->len - dataoff,
-					      0));
-}
-
-static int tcp_error4(struct sk_buff *skb,
-		      unsigned int dataoff,
-		      enum ip_conntrack_info *ctinfo,
-		      int pf,
-		      unsigned int hooknum)
-{
-	return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int tcp_error6(struct sk_buff *skb,
-		      unsigned int dataoff,
-		      enum ip_conntrack_info *ctinfo,
-		      int pf,
-		      unsigned int hooknum)
-{
-	return tcp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
 /* Returns verdict for packet, or -1 for invalid. */
 static int tcp_packet(struct nf_conn *conntrack,
 		      const struct sk_buff *skb,
@@ -1218,7 +1178,7 @@
 	.print_conntrack 	= tcp_print_conntrack,
 	.packet 		= tcp_packet,
 	.new 			= tcp_new,
-	.error			= tcp_error4,
+	.error			= tcp_error,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.to_nfattr		= tcp_to_nfattr,
@@ -1239,7 +1199,7 @@
 	.print_conntrack 	= tcp_print_conntrack,
 	.packet 		= tcp_packet,
 	.new 			= tcp_new,
-	.error			= tcp_error6,
+	.error			= tcp_error,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.to_nfattr		= tcp_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 831d206..d93edbf 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -103,8 +103,7 @@
 static int udp_error(struct sk_buff *skb, unsigned int dataoff,
 		     enum ip_conntrack_info *ctinfo,
 		     int pf,
-		     unsigned int hooknum,
-		     int (*csum)(const struct sk_buff *, unsigned int))
+		     unsigned int hooknum)
 {
 	unsigned int udplen = skb->len - dataoff;
 	struct udphdr _hdr, *hdr;
@@ -136,9 +135,8 @@
 	 * and moreover root might send raw packets.
 	 * FIXME: Source route IP option packets --RR */
 	if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
-	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))
-	    && skb->ip_summed != CHECKSUM_UNNECESSARY
-	    && csum(skb, dataoff)) {
+	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
+	    nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 		if (LOG_INVALID(IPPROTO_UDP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
 				"nf_ct_udp: bad UDP checksum ");
@@ -148,44 +146,6 @@
 	return NF_ACCEPT;
 }
 
-static int csum4(const struct sk_buff *skb, unsigned int dataoff)
-{
-	return csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
-				 skb->len - dataoff, IPPROTO_UDP,
-				 skb->ip_summed == CHECKSUM_HW ? skb->csum
-				 : skb_checksum(skb, dataoff,
-						skb->len - dataoff, 0));
-}
-
-static int csum6(const struct sk_buff *skb, unsigned int dataoff)
-{
-	return csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
-			       skb->len - dataoff, IPPROTO_UDP,
-			       skb->ip_summed == CHECKSUM_HW
-			       ? csum_sub(skb->csum,
-					  skb_checksum(skb, 0, dataoff, 0))
-			       : skb_checksum(skb, dataoff, skb->len - dataoff,
-					      0));
-}
-
-static int udp_error4(struct sk_buff *skb,
-		      unsigned int dataoff,
-		      enum ip_conntrack_info *ctinfo,
-		      int pf,
-		      unsigned int hooknum)
-{
-	return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum4);
-}
-
-static int udp_error6(struct sk_buff *skb,
-		      unsigned int dataoff,
-		      enum ip_conntrack_info *ctinfo,
-		      int pf,
-		      unsigned int hooknum)
-{
-	return udp_error(skb, dataoff, ctinfo, pf, hooknum, csum6);
-}
-
 struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
 {
 	.l3proto		= PF_INET,
@@ -197,7 +157,7 @@
 	.print_conntrack	= udp_print_conntrack,
 	.packet			= udp_packet,
 	.new			= udp_new,
-	.error			= udp_error4,
+	.error			= udp_error,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
@@ -216,7 +176,7 @@
 	.print_conntrack	= udp_print_conntrack,
 	.packet			= udp_packet,
 	.new			= udp_new,
-	.error			= udp_error6,
+	.error			= udp_error,
 #if defined(CONFIG_NF_CT_NETLINK) || \
     defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index c72aa3c..408960c 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -649,63 +649,6 @@
 EXPORT_SYMBOL(nf_ct_log_invalid);
 #endif /* CONFIG_SYSCTL */
 
-static int init_or_cleanup(int init)
-{
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
-#endif
-	int ret = 0;
-
-	if (!init) goto cleanup;
-
-	ret = nf_conntrack_init();
-	if (ret < 0)
-		goto cleanup_nothing;
-
-#ifdef CONFIG_PROC_FS
-	proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
-	if (!proc) goto cleanup_init;
-
-	proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
-					&exp_file_ops);
-	if (!proc_exp) goto cleanup_proc;
-
-	proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
-	if (!proc_stat)
-		goto cleanup_proc_exp;
-
-	proc_stat->proc_fops = &ct_cpu_seq_fops;
-	proc_stat->owner = THIS_MODULE;
-#endif
-#ifdef CONFIG_SYSCTL
-	nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
-	if (nf_ct_sysctl_header == NULL) {
-		printk("nf_conntrack: can't register to sysctl.\n");
-		ret = -ENOMEM;
-		goto cleanup_proc_stat;
-	}
-#endif
-
-	return ret;
-
- cleanup:
-#ifdef CONFIG_SYSCTL
- 	unregister_sysctl_table(nf_ct_sysctl_header);
- cleanup_proc_stat:
-#endif
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("nf_conntrack", proc_net_stat);
- cleanup_proc_exp:
-	proc_net_remove("nf_conntrack_expect");
- cleanup_proc:
-	proc_net_remove("nf_conntrack");
- cleanup_init:
-#endif /* CNFIG_PROC_FS */
-	nf_conntrack_cleanup();
- cleanup_nothing:
-	return ret;
-}
-
 int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
 {
 	int ret = 0;
@@ -808,12 +751,66 @@
 
 static int __init nf_conntrack_standalone_init(void)
 {
-	return init_or_cleanup(1);
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
+	int ret = 0;
+
+	ret = nf_conntrack_init();
+	if (ret < 0)
+		return ret;
+
+#ifdef CONFIG_PROC_FS
+	proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
+	if (!proc) goto cleanup_init;
+
+	proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
+					&exp_file_ops);
+	if (!proc_exp) goto cleanup_proc;
+
+	proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
+	if (!proc_stat)
+		goto cleanup_proc_exp;
+
+	proc_stat->proc_fops = &ct_cpu_seq_fops;
+	proc_stat->owner = THIS_MODULE;
+#endif
+#ifdef CONFIG_SYSCTL
+	nf_ct_sysctl_header = register_sysctl_table(nf_ct_net_table, 0);
+	if (nf_ct_sysctl_header == NULL) {
+		printk("nf_conntrack: can't register to sysctl.\n");
+		ret = -ENOMEM;
+		goto cleanup_proc_stat;
+	}
+#endif
+	return ret;
+
+#ifdef CONFIG_SYSCTL
+ cleanup_proc_stat:
+#endif
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("nf_conntrack", proc_net_stat);
+ cleanup_proc_exp:
+	proc_net_remove("nf_conntrack_expect");
+ cleanup_proc:
+	proc_net_remove("nf_conntrack");
+ cleanup_init:
+#endif /* CNFIG_PROC_FS */
+	nf_conntrack_cleanup();
+	return ret;
 }
 
 static void __exit nf_conntrack_standalone_fini(void)
 {
-	init_or_cleanup(0);
+#ifdef CONFIG_SYSCTL
+ 	unregister_sysctl_table(nf_ct_sysctl_header);
+#endif
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("nf_conntrack", proc_net_stat);
+	proc_net_remove("nf_conntrack_expect");
+	proc_net_remove("nf_conntrack");
+#endif /* CNFIG_PROC_FS */
+	nf_conntrack_cleanup();
 }
 
 module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7e..ee8f708 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
  * for queueing and must reinject all packets it receives, no matter what.
  */
 static struct nf_queue_handler *queue_handler[NPROTO];
-static struct nf_queue_rerouter *queue_rerouter[NPROTO];
 
 static DEFINE_RWLOCK(queue_handler_lock);
 
@@ -59,32 +58,6 @@
 }
 EXPORT_SYMBOL(nf_unregister_queue_handler);
 
-int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
-{
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	rcu_assign_pointer(queue_rerouter[pf], rer);
-	write_unlock_bh(&queue_handler_lock);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
-
-int nf_unregister_queue_rerouter(int pf)
-{
-	if (pf >= NPROTO)
-		return -EINVAL;
-
-	write_lock_bh(&queue_handler_lock);
-	rcu_assign_pointer(queue_rerouter[pf], NULL);
-	write_unlock_bh(&queue_handler_lock);
-	synchronize_rcu();
-	return 0;
-}
-EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
-
 void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
 {
 	int pf;
@@ -116,7 +89,7 @@
 	struct net_device *physindev = NULL;
 	struct net_device *physoutdev = NULL;
 #endif
-	struct nf_queue_rerouter *rerouter;
+	struct nf_afinfo *afinfo;
 
 	/* QUEUE == DROP if noone is waiting, to be safe. */
 	read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@
 		return 1;
 	}
 
-	info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC);
+	afinfo = nf_get_afinfo(pf);
+	if (!afinfo) {
+		read_unlock(&queue_handler_lock);
+		kfree_skb(*skb);
+		return 1;
+	}
+
+	info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
 	if (!info) {
 		if (net_ratelimit())
 			printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@
 		if (physoutdev) dev_hold(physoutdev);
 	}
 #endif
-	rerouter = rcu_dereference(queue_rerouter[pf]);
-	if (rerouter)
-		rerouter->save(*skb, info);
-
+	afinfo->saveroute(*skb, info);
 	status = queue_handler[pf]->outfn(*skb, info, queuenum,
 					  queue_handler[pf]->data);
 
@@ -190,7 +167,7 @@
 {
 	struct list_head *elem = &info->elem->list;
 	struct list_head *i;
-	struct nf_queue_rerouter *rerouter;
+	struct nf_afinfo *afinfo;
 
 	rcu_read_lock();
 
@@ -228,8 +205,8 @@
 	}
 
 	if (verdict == NF_ACCEPT) {
-		rerouter = rcu_dereference(queue_rerouter[info->pf]);
-		if (rerouter && rerouter->reroute(&skb, info) < 0)
+		afinfo = nf_get_afinfo(info->pf);
+		if (!afinfo || afinfo->reroute(&skb, info) < 0)
 			verdict = NF_DROP;
 	}
 
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 3e3f544..c60273c 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1033,17 +1033,13 @@
 
 #endif /* PROC_FS */
 
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_log_init(void)
 {
 	int i, status = -ENOMEM;
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_nful;
 #endif
 	
-	if (!init)
-		goto cleanup;
-
 	for (i = 0; i < INSTANCE_BUCKETS; i++)
 		INIT_HLIST_HEAD(&instance_table[i]);
 	
@@ -1066,30 +1062,25 @@
 		goto cleanup_subsys;
 	proc_nful->proc_fops = &nful_file_ops;
 #endif
-
 	return status;
 
-cleanup:
-	nf_log_unregister_logger(&nfulnl_logger);
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry("nfnetlink_log", proc_net_netfilter);
 cleanup_subsys:
-#endif
 	nfnetlink_subsys_unregister(&nfulnl_subsys);
+#endif
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
 	return status;
 }
 
-static int __init nfnetlink_log_init(void)
-{
-	
-	return init_or_cleanup(1);
-}
-
 static void __exit nfnetlink_log_fini(void)
 {
-	init_or_cleanup(0);
+	nf_log_unregister_logger(&nfulnl_logger);
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("nfnetlink_log", proc_net_netfilter);
+#endif
+	nfnetlink_subsys_unregister(&nfulnl_subsys);
+	netlink_unregister_notifier(&nfulnl_rtnl_notifier);
 }
 
 MODULE_DESCRIPTION("netfilter userspace logging");
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index d0e62f6..86a4ac3 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1071,17 +1071,13 @@
 
 #endif /* PROC_FS */
 
-static int
-init_or_cleanup(int init)
+static int __init nfnetlink_queue_init(void)
 {
 	int i, status = -ENOMEM;
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *proc_nfqueue;
 #endif
 	
-	if (!init)
-		goto cleanup;
-
 	for (i = 0; i < INSTANCE_BUCKETS; i++)
 		INIT_HLIST_HEAD(&instance_table[i]);
 
@@ -1101,31 +1097,26 @@
 #endif
 
 	register_netdevice_notifier(&nfqnl_dev_notifier);
-
 	return status;
 
-cleanup:
-	nf_unregister_queue_handlers(&nfqh);
-	unregister_netdevice_notifier(&nfqnl_dev_notifier);
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
 cleanup_subsys:
-#endif	
 	nfnetlink_subsys_unregister(&nfqnl_subsys);
+#endif
 cleanup_netlink_notifier:
 	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
 	return status;
 }
 
-static int __init nfnetlink_queue_init(void)
-{
-	
-	return init_or_cleanup(1);
-}
-
 static void __exit nfnetlink_queue_fini(void)
 {
-	init_or_cleanup(0);
+	nf_unregister_queue_handlers(&nfqh);
+	unregister_netdevice_notifier(&nfqnl_dev_notifier);
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
+#endif
+	nfnetlink_subsys_unregister(&nfqnl_subsys);
+	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
 }
 
 MODULE_DESCRIPTION("netfilter packet queue handler");
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index a657ab5..17abf60 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -38,6 +38,7 @@
 	struct list_head match;
 	struct list_head target;
 	struct list_head tables;
+	struct mutex compat_mutex;
 };
 
 static struct xt_af *xt;
@@ -272,6 +273,54 @@
 }
 EXPORT_SYMBOL_GPL(xt_check_match);
 
+#ifdef CONFIG_COMPAT
+int xt_compat_match(void *match, void **dstptr, int *size, int convert)
+{
+	struct xt_match *m;
+	struct compat_xt_entry_match *pcompat_m;
+	struct xt_entry_match *pm;
+	u_int16_t msize;
+	int off, ret;
+
+	ret = 0;
+	m = ((struct xt_entry_match *)match)->u.kernel.match;
+	off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize);
+	switch (convert) {
+		case COMPAT_TO_USER:
+			pm = (struct xt_entry_match *)match;
+			msize = pm->u.user.match_size;
+			if (__copy_to_user(*dstptr, pm, msize)) {
+				ret = -EFAULT;
+				break;
+			}
+			msize -= off;
+			if (put_user(msize, (u_int16_t *)*dstptr))
+				ret = -EFAULT;
+			*size -= off;
+			*dstptr += msize;
+			break;
+		case COMPAT_FROM_USER:
+			pcompat_m = (struct compat_xt_entry_match *)match;
+			pm = (struct xt_entry_match *)*dstptr;
+			msize = pcompat_m->u.user.match_size;
+			memcpy(pm, pcompat_m, msize);
+			msize += off;
+			pm->u.user.match_size = msize;
+			*size += off;
+			*dstptr += msize;
+			break;
+		case COMPAT_CALC_SIZE:
+			*size += off;
+			break;
+		default:
+			ret = -ENOPROTOOPT;
+			break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_match);
+#endif
+
 int xt_check_target(const struct xt_target *target, unsigned short family,
 		    unsigned int size, const char *table, unsigned int hook_mask,
 		    unsigned short proto, int inv_proto)
@@ -301,6 +350,54 @@
 }
 EXPORT_SYMBOL_GPL(xt_check_target);
 
+#ifdef CONFIG_COMPAT
+int xt_compat_target(void *target, void **dstptr, int *size, int convert)
+{
+	struct xt_target *t;
+	struct compat_xt_entry_target *pcompat;
+	struct xt_entry_target *pt;
+	u_int16_t tsize;
+	int off, ret;
+
+	ret = 0;
+	t = ((struct xt_entry_target *)target)->u.kernel.target;
+	off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize);
+	switch (convert) {
+		case COMPAT_TO_USER:
+			pt = (struct xt_entry_target *)target;
+			tsize = pt->u.user.target_size;
+			if (__copy_to_user(*dstptr, pt, tsize)) {
+				ret = -EFAULT;
+				break;
+			}
+			tsize -= off;
+			if (put_user(tsize, (u_int16_t *)*dstptr))
+				ret = -EFAULT;
+			*size -= off;
+			*dstptr += tsize;
+			break;
+		case COMPAT_FROM_USER:
+			pcompat = (struct compat_xt_entry_target *)target;
+			pt = (struct xt_entry_target *)*dstptr;
+			tsize = pcompat->u.user.target_size;
+			memcpy(pt, pcompat, tsize);
+			tsize += off;
+			pt->u.user.target_size = tsize;
+			*size += off;
+			*dstptr += tsize;
+			break;
+		case COMPAT_CALC_SIZE:
+			*size += off;
+			break;
+		default:
+			ret = -ENOPROTOOPT;
+			break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xt_compat_target);
+#endif
+
 struct xt_table_info *xt_alloc_table_info(unsigned int size)
 {
 	struct xt_table_info *newinfo;
@@ -316,7 +413,7 @@
 
 	newinfo->size = size;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (size <= PAGE_SIZE)
 			newinfo->entries[cpu] = kmalloc_node(size,
 							GFP_KERNEL,
@@ -339,7 +436,7 @@
 {
 	int cpu;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		if (info->size <= PAGE_SIZE)
 			kfree(info->entries[cpu]);
 		else
@@ -371,6 +468,19 @@
 }
 EXPORT_SYMBOL_GPL(xt_table_unlock);
 
+#ifdef CONFIG_COMPAT
+void xt_compat_lock(int af)
+{
+	mutex_lock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_lock);
+
+void xt_compat_unlock(int af)
+{
+	mutex_unlock(&xt[af].compat_mutex);
+}
+EXPORT_SYMBOL_GPL(xt_compat_unlock);
+#endif
 
 struct xt_table_info *
 xt_replace_table(struct xt_table *table,
@@ -419,6 +529,7 @@
 
 	/* Simplifies replace_table code. */
 	table->private = bootstrap;
+	rwlock_init(&table->lock);
 	if (!xt_replace_table(table, 0, newinfo, &ret))
 		goto unlock;
 
@@ -428,7 +539,6 @@
 	/* save number of initial entries */
 	private->initial_entries = private->number;
 
-	rwlock_init(&table->lock);
 	list_prepend(&xt[table->af].tables, table);
 
 	ret = 0;
@@ -671,6 +781,9 @@
 
 	for (i = 0; i < NPROTO; i++) {
 		mutex_init(&xt[i].mutex);
+#ifdef CONFIG_COMPAT
+		mutex_init(&xt[i].compat_mutex);
+#endif
 		INIT_LIST_HEAD(&xt[i].target);
 		INIT_LIST_HEAD(&xt[i].match);
 		INIT_LIST_HEAD(&xt[i].tables);
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
new file mode 100644
index 0000000..9dad628
--- /dev/null
+++ b/net/netfilter/xt_esp.c
@@ -0,0 +1,136 @@
+/* Kernel module to match ESP parameters. */
+
+/* (C) 1999-2000 Yon Uriarte <yon@astaro.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+
+#include <linux/netfilter/xt_esp.h>
+#include <linux/netfilter/x_tables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
+MODULE_DESCRIPTION("x_tables ESP SPI match module");
+MODULE_ALIAS("ipt_esp");
+MODULE_ALIAS("ip6t_esp");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the spi is matched by the range, 0 otherwise */
+static inline int
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+{
+	int r = 0;
+	duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+		 min, spi, max);
+	r = (spi >= min && spi <= max) ^ invert;
+	duprintf(" result %s\n", r ? "PASS" : "FAILED");
+	return r;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      int *hotdrop)
+{
+	struct ip_esp_hdr _esp, *eh;
+	const struct xt_esp *espinfo = matchinfo;
+
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
+	if (eh == NULL) {
+		/* We've been asked to examine this packet, and we
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("Dropping evil ESP tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
+			 !!(espinfo->invflags & XT_ESP_INV_SPI));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+	   const void *ip_void,
+	   const struct xt_match *match,
+	   void *matchinfo,
+	   unsigned int matchinfosize,
+	   unsigned int hook_mask)
+{
+	const struct xt_esp *espinfo = matchinfo;
+
+	if (espinfo->invflags & ~XT_ESP_INV_MASK) {
+		duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct xt_match esp_match = {
+	.name		= "esp",
+	.family		= AF_INET,
+	.proto		= IPPROTO_ESP,
+	.match		= &match,
+	.matchsize	= sizeof(struct xt_esp),
+	.checkentry	= &checkentry,
+	.me		= THIS_MODULE,
+};
+
+static struct xt_match esp6_match = {
+	.name		= "esp",
+	.family		= AF_INET6,
+	.proto		= IPPROTO_ESP,
+	.match		= &match,
+	.matchsize	= sizeof(struct xt_esp),
+	.checkentry	= &checkentry,
+	.me		= THIS_MODULE,
+};
+
+static int __init xt_esp_init(void)
+{
+	int ret;
+	ret = xt_register_match(&esp_match);
+	if (ret)
+		return ret;
+
+	ret = xt_register_match(&esp6_match);
+	if (ret)
+		xt_unregister_match(&esp_match);
+
+	return ret;
+}
+
+static void __exit xt_esp_cleanup(void)
+{
+	xt_unregister_match(&esp_match);
+	xt_unregister_match(&esp6_match);
+}
+
+module_init(xt_esp_init);
+module_exit(xt_esp_cleanup);
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
new file mode 100644
index 0000000..b56cd2b
--- /dev/null
+++ b/net/netfilter/xt_multiport.c
@@ -0,0 +1,314 @@
+/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+   the same place so we can treat them as equal. */
+
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include <linux/netfilter/xt_multiport.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
+MODULE_DESCRIPTION("x_tables multiple port match module");
+MODULE_ALIAS("ipt_multiport");
+MODULE_ALIAS("ip6t_multiport");
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
+	    u_int8_t count, u_int16_t src, u_int16_t dst)
+{
+	unsigned int i;
+	for (i = 0; i < count; i++) {
+		if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
+			return 1;
+
+		if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
+			return 1;
+	}
+
+	return 0;
+}
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match_v1(const struct xt_multiport_v1 *minfo,
+	       u_int16_t src, u_int16_t dst)
+{
+	unsigned int i;
+	u_int16_t s, e;
+
+	for (i = 0; i < minfo->count; i++) {
+		s = minfo->ports[i];
+
+		if (minfo->pflags[i]) {
+			/* range port matching */
+			e = minfo->ports[++i];
+			duprintf("src or dst matches with %d-%d?\n", s, e);
+
+			if (minfo->flags == XT_MULTIPORT_SOURCE
+			    && src >= s && src <= e)
+				return 1 ^ minfo->invert;
+			if (minfo->flags == XT_MULTIPORT_DESTINATION
+			    && dst >= s && dst <= e)
+				return 1 ^ minfo->invert;
+			if (minfo->flags == XT_MULTIPORT_EITHER
+			    && ((dst >= s && dst <= e)
+				|| (src >= s && src <= e)))
+				return 1 ^ minfo->invert;
+		} else {
+			/* exact port matching */
+			duprintf("src or dst matches with %d?\n", s);
+
+			if (minfo->flags == XT_MULTIPORT_SOURCE
+			    && src == s)
+				return 1 ^ minfo->invert;
+			if (minfo->flags == XT_MULTIPORT_DESTINATION
+			    && dst == s)
+				return 1 ^ minfo->invert;
+			if (minfo->flags == XT_MULTIPORT_EITHER
+			    && (src == s || dst == s))
+				return 1 ^ minfo->invert;
+		}
+	}
+
+ 	return minfo->invert;
+}
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      int *hotdrop)
+{
+	u16 _ports[2], *pptr;
+	const struct xt_multiport *multiinfo = matchinfo;
+
+	if (offset)
+		return 0;
+
+	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+	if (pptr == NULL) {
+		/* We've been asked to examine this packet, and we
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	return ports_match(multiinfo->ports,
+			   multiinfo->flags, multiinfo->count,
+			   ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static int
+match_v1(const struct sk_buff *skb,
+	 const struct net_device *in,
+	 const struct net_device *out,
+	 const struct xt_match *match,
+	 const void *matchinfo,
+	 int offset,
+	 unsigned int protoff,
+	 int *hotdrop)
+{
+	u16 _ports[2], *pptr;
+	const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+	if (offset)
+		return 0;
+
+	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
+	if (pptr == NULL) {
+		/* We've been asked to examine this packet, and we
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
+}
+
+static inline int
+check(u_int16_t proto,
+      u_int8_t ip_invflags,
+      u_int8_t match_flags,
+      u_int8_t count)
+{
+	/* Must specify proto == TCP/UDP, no unknown flags or bad count */
+	return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+		&& !(ip_invflags & XT_INV_PROTO)
+		&& (match_flags == XT_MULTIPORT_SOURCE
+		    || match_flags == XT_MULTIPORT_DESTINATION
+		    || match_flags == XT_MULTIPORT_EITHER)
+		&& count <= XT_MULTI_PORTS;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+	   const void *info,
+	   const struct xt_match *match,
+	   void *matchinfo,
+	   unsigned int matchsize,
+	   unsigned int hook_mask)
+{
+	const struct ipt_ip *ip = info;
+	const struct xt_multiport *multiinfo = matchinfo;
+
+	return check(ip->proto, ip->invflags, multiinfo->flags,
+		     multiinfo->count);
+}
+
+static int
+checkentry_v1(const char *tablename,
+	      const void *info,
+	      const struct xt_match *match,
+	      void *matchinfo,
+	      unsigned int matchsize,
+	      unsigned int hook_mask)
+{
+	const struct ipt_ip *ip = info;
+	const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+	return check(ip->proto, ip->invflags, multiinfo->flags,
+		     multiinfo->count);
+}
+
+static int
+checkentry6(const char *tablename,
+	    const void *info,
+	    const struct xt_match *match,
+	    void *matchinfo,
+	    unsigned int matchsize,
+	    unsigned int hook_mask)
+{
+	const struct ip6t_ip6 *ip = info;
+	const struct xt_multiport *multiinfo = matchinfo;
+
+	return check(ip->proto, ip->invflags, multiinfo->flags,
+		     multiinfo->count);
+}
+
+static int
+checkentry6_v1(const char *tablename,
+	       const void *info,
+	       const struct xt_match *match,
+	       void *matchinfo,
+	       unsigned int matchsize,
+	       unsigned int hook_mask)
+{
+	const struct ip6t_ip6 *ip = info;
+	const struct xt_multiport_v1 *multiinfo = matchinfo;
+
+	return check(ip->proto, ip->invflags, multiinfo->flags,
+		     multiinfo->count);
+}
+
+static struct xt_match multiport_match = {
+	.name		= "multiport",
+	.revision	= 0,
+	.matchsize	= sizeof(struct xt_multiport),
+	.match		= &match,
+	.checkentry	= &checkentry,
+	.family		= AF_INET,
+	.me		= THIS_MODULE,
+};
+
+static struct xt_match multiport_match_v1 = {
+	.name		= "multiport",
+	.revision	= 1,
+	.matchsize	= sizeof(struct xt_multiport_v1),
+	.match		= &match_v1,
+	.checkentry	= &checkentry_v1,
+	.family		= AF_INET,
+	.me		= THIS_MODULE,
+};
+
+static struct xt_match multiport6_match = {
+	.name		= "multiport",
+	.revision	= 0,
+	.matchsize	= sizeof(struct xt_multiport),
+	.match		= &match,
+	.checkentry	= &checkentry6,
+	.family		= AF_INET6,
+	.me		= THIS_MODULE,
+};
+
+static struct xt_match multiport6_match_v1 = {
+	.name		= "multiport",
+	.revision	= 1,
+	.matchsize	= sizeof(struct xt_multiport_v1),
+	.match		= &match_v1,
+	.checkentry	= &checkentry6_v1,
+	.family		= AF_INET6,
+	.me		= THIS_MODULE,
+};
+
+static int __init xt_multiport_init(void)
+{
+	int ret;
+
+	ret = xt_register_match(&multiport_match);
+	if (ret)
+		goto out;
+
+	ret = xt_register_match(&multiport_match_v1);
+	if (ret)
+		goto out_unreg_multi_v0;
+
+	ret = xt_register_match(&multiport6_match);
+	if (ret)
+		goto out_unreg_multi_v1;
+
+	ret = xt_register_match(&multiport6_match_v1);
+	if (ret)
+		goto out_unreg_multi6_v0;
+
+	return ret;
+
+out_unreg_multi6_v0:
+	xt_unregister_match(&multiport6_match);
+out_unreg_multi_v1:
+	xt_unregister_match(&multiport_match_v1);
+out_unreg_multi_v0:
+	xt_unregister_match(&multiport_match);
+out:
+	return ret;
+}
+
+static void __exit xt_multiport_fini(void)
+{
+	xt_unregister_match(&multiport_match);
+	xt_unregister_match(&multiport_match_v1);
+	xt_unregister_match(&multiport6_match);
+	xt_unregister_match(&multiport6_match_v1);
+}
+
+module_init(xt_multiport_init);
+module_exit(xt_multiport_fini);
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 1099cb0..a3aa62f 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -71,7 +71,7 @@
 			return 0;
 		e = &info->pol[pos];
 
-		if (match_xfrm_state(sp->x[i].xvec, e, family)) {
+		if (match_xfrm_state(sp->xvec[i], e, family)) {
 			if (!strict)
 				return 1;
 		} else if (strict)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 6056d20..37640c6 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -69,6 +69,11 @@
 	DPRINTK("ipt_init_target: found %s\n", target->name);
 	t->u.kernel.target = target;
 
+	ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
+			      table, hook, 0, 0);
+	if (ret)
+		return ret;
+
 	if (t->u.kernel.target->checkentry
 	    && !t->u.kernel.target->checkentry(table, NULL,
 		    			       t->u.kernel.target, t->data,
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fa877f8..24c348f 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -66,7 +66,7 @@
 }
 
 #ifdef CONFIG_NET_CLS_ACT
-static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb,
+static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
                               int type, struct tc_action *a)
 {
 	struct tcf_police *p;
@@ -113,7 +113,7 @@
 }
 
 static inline int
-tcf_hash_search(struct tc_action *a, u32 index)
+tcf_act_police_hash_search(struct tc_action *a, u32 index)
 {
 	struct tcf_police *p = tcf_police_lookup(index);
 
@@ -387,9 +387,9 @@
 	.act		=	tcf_act_police,
 	.dump		=	tcf_act_police_dump,
 	.cleanup	=	tcf_act_police_cleanup,
-	.lookup		=	tcf_hash_search,
+	.lookup		=	tcf_act_police_hash_search,
 	.init		=	tcf_act_police_locate,
-	.walk		=	tcf_generic_walker
+	.walk		=	tcf_act_police_walker
 };
 
 static int __init
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index d47a52c..5b3b0e0 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -69,7 +69,7 @@
 	unsigned long res = 0;
 	int i;
 
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		res +=
 		    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
 					 sizeof (unsigned long) * nr));
diff --git a/net/socket.c b/net/socket.c
index b13042f..0ce12df 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -119,10 +119,6 @@
 static ssize_t sock_sendpage(struct file *file, struct page *page,
 			     int offset, size_t size, loff_t *ppos, int more);
 
-extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out,
-				size_t len, unsigned int flags);
-
-
 /*
  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
  *	in the operation structures but are done directly via the socketcall() multiplexor.
@@ -494,6 +490,7 @@
 	struct file *file;
 	struct socket *sock;
 
+	*err = -EBADF;
 	file = fget_light(fd, fput_needed);
 	if (file) {
 		sock = sock_from_file(file, err);
@@ -1418,7 +1415,8 @@
 	newfd = sock_alloc_fd(&newfile);
 	if (unlikely(newfd < 0)) {
 		err = newfd;
-		goto out_release;
+		sock_release(newsock);
+		goto out_put;
 	}
 
 	err = sock_attach_fd(newsock, newfile);
@@ -1455,10 +1453,8 @@
 out:
 	return err;
 out_fd:
-	put_filp(newfile);
+	fput(newfile);
 	put_unused_fd(newfd);
-out_release:
-	sock_release(newsock);
 	goto out_put;
 }
 
@@ -2137,7 +2133,7 @@
 	int cpu;
 	int counter = 0;
 
-	for_each_cpu(cpu)
+	for_each_possible_cpu(cpu)
 		counter += per_cpu(sockets_in_use, cpu);
 
 	/* It can be negative, by the way. 8) */
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 900ef31..519ebc1 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -794,7 +794,6 @@
 
 out_err:
 	dprintk("RPC:      gss_create_cred failed with error %d\n", err);
-	if (cred) gss_destroy_cred(&cred->gc_base);
 	return ERR_PTR(err);
 }
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 97c981f..76b969e 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -212,7 +212,6 @@
 	char                            *cksumname;
 	struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
 	struct scatterlist              sg[1];
-	u32                             code = GSS_S_FAILURE;
 
 	switch (cksumtype) {
 		case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@
 		default:
 			dprintk("RPC:      krb5_make_checksum:"
 				" unsupported checksum %d", cksumtype);
-			goto out;
+			return GSS_S_FAILURE;
 	}
 	if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
-		goto out;
+		return GSS_S_FAILURE;
 	cksum->len = crypto_tfm_alg_digestsize(tfm);
-	if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
-		goto out;
 
 	crypto_digest_init(tfm);
 	sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@
 	process_xdr_buf(body, body_offset, body->len - body_offset,
 			checksummer, tfm);
 	crypto_digest_final(tfm, cksum->data);
-	code = 0;
-out:
 	crypto_free_tfm(tfm);
-	return code;
+	return 0;
 }
 
 EXPORT_SYMBOL(make_checksum);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 4d7eb9e..d51e316 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1122,18 +1122,20 @@
 					integ_len))
 			BUG();
 		if (resbuf->page_len == 0
-			&& resbuf->tail[0].iov_len + RPC_MAX_AUTH_SIZE
+			&& resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
 				< PAGE_SIZE) {
 			BUG_ON(resbuf->tail[0].iov_len);
 			/* Use head for everything */
 			resv = &resbuf->head[0];
 		} else if (resbuf->tail[0].iov_base == NULL) {
-			/* copied from nfsd4_encode_read */
-			svc_take_page(rqstp);
-			resbuf->tail[0].iov_base = page_address(rqstp
-					->rq_respages[rqstp->rq_resused-1]);
-			rqstp->rq_restailpage = rqstp->rq_resused-1;
+			if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE
+					> PAGE_SIZE)
+				goto out_err;
+			resbuf->tail[0].iov_base =
+				resbuf->head[0].iov_base
+				+ resbuf->head[0].iov_len;
 			resbuf->tail[0].iov_len = 0;
+			rqstp->rq_restailpage = 0;
 			resv = &resbuf->tail[0];
 		} else {
 			resv = &resbuf->tail[0];
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index dea5296..15c2db2 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -176,7 +176,8 @@
 	op_metrics->om_execute += execute;
 }
 
-void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+static void _print_name(struct seq_file *seq, unsigned int op,
+			struct rpc_procinfo *procs)
 {
 	if (procs[op].p_name)
 		seq_printf(seq, "\t%12s: ", procs[op].p_name);
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 953307a..a3bbc89 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -229,8 +229,7 @@
 				     publ->node, publ->ref, publ->key);
         assert(p == publ);
 	write_unlock_bh(&tipc_nametbl_lock);
-	if (publ)
-		kfree(publ);
+	kfree(publ);
 }
 
 /**
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 8b9bf4a..b126518 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -55,12 +55,10 @@
 #include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/wanpipe.h>
 #include <linux/if_wanpipe.h>
 #include <linux/pkt_sched.h>
 #include <linux/tcp_states.h>
 #include <linux/if_wanpipe_common.h>
-#include <linux/sdla_x25.h>
 
 #ifdef CONFIG_INET
 #include <net/inet_common.h>
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2407a70..b549710 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -18,7 +18,7 @@
 {
 	int i;
 	for (i = 0; i < sp->len; i++)
-		xfrm_state_put(sp->x[i].xvec);
+		xfrm_state_put(sp->xvec[i]);
 	kmem_cache_free(secpath_cachep, sp);
 }
 EXPORT_SYMBOL(__secpath_destroy);
@@ -37,7 +37,7 @@
 
 		memcpy(sp, src, sizeof(*sp));
 		for (i = 0; i < sp->len; i++)
-			xfrm_state_hold(sp->x[i].xvec);
+			xfrm_state_hold(sp->xvec[i]);
 	}
 	atomic_set(&sp->refcnt, 1);
 	return sp;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f5eae9f..c3725fe 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -943,9 +943,9 @@
 	} else
 		start = -1;
 	for (; idx < sp->len; idx++) {
-		if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family))
+		if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
 			return ++idx;
-		if (sp->x[idx].xvec->props.mode)
+		if (sp->xvec[idx]->props.mode)
 			break;
 	}
 	return start;
@@ -968,7 +968,7 @@
 static inline int secpath_has_tunnel(struct sec_path *sp, int k)
 {
 	for (; k < sp->len; k++) {
-		if (sp->x[k].xvec->props.mode)
+		if (sp->xvec[k]->props.mode)
 			return 1;
 	}
 
@@ -994,8 +994,8 @@
 		int i;
 
 		for (i=skb->sp->len-1; i>=0; i--) {
-			struct sec_decap_state *xvec = &(skb->sp->x[i]);
-			if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
+			struct xfrm_state *x = skb->sp->xvec[i];
+			if (!xfrm_selector_match(&x->sel, &fl, family))
 				return 0;
 		}
 	}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a8e14dc..3dc3e1f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -805,16 +805,22 @@
 	case XFRM_REPLAY_UPDATE:
 		if (x->replay_maxdiff &&
 		    (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
-		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))
-			return;
+		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+			if (x->xflags & XFRM_TIME_DEFER)
+				event = XFRM_REPLAY_TIMEOUT;
+			else
+				return;
+		}
 
 		break;
 
 	case XFRM_REPLAY_TIMEOUT:
 		if ((x->replay.seq == x->preplay.seq) &&
 		    (x->replay.bitmap == x->preplay.bitmap) &&
-		    (x->replay.oseq == x->preplay.oseq))
+		    (x->replay.oseq == x->preplay.oseq)) {
+			x->xflags |= XFRM_TIME_DEFER;
 			return;
+		}
 
 		break;
 	}
@@ -825,8 +831,10 @@
 	km_state_notify(x, &c);
 
 	if (x->replay_maxage &&
-	    !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+	    !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) {
 		xfrm_state_hold(x);
+		x->xflags &= ~XFRM_TIME_DEFER;
+	}
 }
 EXPORT_SYMBOL(xfrm_replay_notify);
 
@@ -836,10 +844,15 @@
 
 	spin_lock(&x->lock);
 
-	if (xfrm_aevent_is_on() && x->km.state == XFRM_STATE_VALID)
-		xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+	if (x->km.state == XFRM_STATE_VALID) {
+		if (xfrm_aevent_is_on())
+			xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+		else
+			x->xflags |= XFRM_TIME_DEFER;
+	}
 
 	spin_unlock(&x->lock);
+	xfrm_state_put(x);
 }
 
 int xfrm_replay_check(struct xfrm_state *x, u32 seq)
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 59620b1..b0d067b 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -87,6 +87,11 @@
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
+# Prefix -I with $(srctree) if it is not an absolute path
+addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# Find all -I options and call addtree
+flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+
 # If quiet is set, only print short version of command
 cmd = @$(echo-cmd) $(cmd_$(1))
 
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 550798f..2cb4935 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -99,11 +99,6 @@
 __cpp_flags     = $(_cpp_flags)
 else
 
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
-# Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
-
 # -I$(obj) locates generated .h files
 # $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files
 #   and locates generated .h files
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
old mode 100644
new mode 100755
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
old mode 100644
new mode 100755
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index 6d41116..56b3bed 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -1,22 +1,55 @@
 #!/bin/bash
 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
+# Copyright (c) 2006           Sam Ravnborg <sam@ravnborg.org>
+#
 # Released under the terms of the GNU GPL
 #
-# Generate a newline separated list of entries from the file/directory
-# supplied as an argument.
-#
-# If a file/directory is not supplied then generate a small dummy file.
-#
-# The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c.
-#
+# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
+# the cpio archive, and gzip to pack it.
+# The script may also be used to generate the inputfile used for gen_init_cpio
+# This script assumes that gen_init_cpio is located in usr/ directory
+
+# error out on errors
+set -e
+
+usage() {
+cat << EOF
+Usage:
+$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
+	-o <file>      Create gzipped initramfs file named <file> using
+	               gen_init_cpio and gzip
+	-u <uid>       User ID to map to user ID 0 (root).
+	               <uid> is only meaningful if <cpio_source>
+	               is a directory.
+	-g <gid>       Group ID to map to group ID 0 (root).
+	               <gid> is only meaningful if <cpio_source>
+	               is a directory.
+	<cpio_source>  File list or directory for cpio archive.
+	               If <cpio_source> is a .cpio file it will be used
+		       as direct input to initramfs.
+	-d             Output the default cpio list.
+
+All options except -o and -l may be repeated and are interpreted
+sequentially and immediately.  -u and -g states are preserved across
+<cpio_source> options so an explicit "-u 0 -g 0" is required
+to reset the root/group mapping.
+EOF
+}
+
+list_default_initramfs() {
+	# echo usr/kinit/kinit
+	:
+}
 
 default_initramfs() {
-	cat <<-EOF
+	cat <<-EOF >> ${output}
 		# This is a very simple, default initramfs
 
 		dir /dev 0755 0 0
 		nod /dev/console 0600 0 0 c 5 1
 		dir /root 0700 0 0
+		# file /kinit usr/kinit/kinit 0755 0 0
+		# slink /init kinit 0755 0 0
 	EOF
 }
 
@@ -42,18 +75,28 @@
 	return 0
 }
 
-print_mtime() {
-	local argv1="$1"
-	local my_mtime="0"
-
-	if [ -e "${argv1}" ]; then
-		my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1)
-	fi
-	
-	echo "# Last modified: ${my_mtime}"
-	echo
+list_print_mtime() {
+	:
 }
 
+print_mtime() {
+	local my_mtime="0"
+
+	if [ -e "$1" ]; then
+		my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
+	fi
+
+	echo "# Last modified: ${my_mtime}" >> ${output}
+	echo "" >> ${output}
+}
+
+list_parse() {
+	echo "$1 \\"
+}
+
+# for each file print a line in following format
+# <filetype> <name> <path to file> <octal mode> <uid> <gid>
+# for links, devices etc the format differs. See gen_init_cpio for details
 parse() {
 	local location="$1"
 	local name="${location/${srcdir}//}"
@@ -99,80 +142,112 @@
 			;;
 	esac
 
-	echo "${str}"
+	echo "${str}" >> ${output}
 
 	return 0
 }
 
-usage() {
-	printf    "Usage:\n"
-	printf    "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n"
-	printf    "\n"
-	printf -- "-u <root_uid>  User ID to map to user ID 0 (root).\n"
-	printf    "               <root_uid> is only meaningful if <cpio_source>\n"
-	printf    "               is a directory.\n"
-	printf -- "-g <root_gid>  Group ID to map to group ID 0 (root).\n"
-	printf    "               <root_gid> is only meaningful if <cpio_source>\n"
-	printf    "               is a directory.\n"
-	printf    "<cpio_source>  File list or directory for cpio archive.\n"
-	printf    "               If <cpio_source> is not provided then a\n"
-	printf    "               a default list will be output.\n"
-	printf -- "-d             Output the default cpio list.  If no <cpio_source>\n"
-	printf    "               is given then the default cpio list will be output.\n"
-	printf    "\n"
-	printf    "All options may be repeated and are interpreted sequentially\n"
-	printf    "and immediately.  -u and -g states are preserved across\n"
-	printf    "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n"
-	printf    "to reset the root/group mapping.\n"
+unknown_option() {
+	printf "ERROR: unknown option \"$arg\"\n" >&2
+	printf "If the filename validly begins with '-', " >&2
+	printf "then it must be prefixed\n" >&2
+	printf "by './' so that it won't be interpreted as an option." >&2
+	printf "\n" >&2
+	usage >&2
+	exit 1
 }
 
-build_list() {
-	printf "\n#####################\n# $cpio_source\n"
+list_header() {
+	echo "deps_initramfs := \\"
+}
 
-	if [ -f "$cpio_source" ]; then
-		print_mtime "$cpio_source"
-		cat "$cpio_source"
-	elif [ -d "$cpio_source" ]; then
-		srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g')
-		dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+header() {
+	printf "\n#####################\n# $1\n" >> ${output}
+}
 
-		# If $dirlist is only one line, then the directory is empty
-		if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
-			print_mtime "$cpio_source"
-		
-			echo "${dirlist}" | \
-			while read x; do
-				parse ${x}
-			done
-		else
-			# Failsafe in case directory is empty
-			default_initramfs
+# process one directory (incl sub-directories)
+dir_filelist() {
+	${dep_list}header "$1"
+
+	srcdir=$(echo "$1" | sed -e 's://*:/:g')
+	dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+
+	# If $dirlist is only one line, then the directory is empty
+	if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
+		${dep_list}print_mtime "$1"
+
+		echo "${dirlist}" | \
+		while read x; do
+			${dep_list}parse ${x}
+		done
+	fi
+}
+
+# if only one file is specified and it is .cpio file then use it direct as fs
+# if a directory is specified then add all files in given direcotry to fs
+# if a regular file is specified assume it is in gen_initramfs format
+input_file() {
+	source="$1"
+	if [ -f "$1" ]; then
+		${dep_list}header "$1"
+		is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
+		if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
+			cpio_file=$1
+			[ ! -z ${dep_list} ] && echo "$1"
+			return 0
 		fi
+		if [ -z ${dep_list} ]; then
+			print_mtime "$1" >> ${output}
+			cat "$1"         >> ${output}
+		else
+			grep ^file "$1" | cut -d ' ' -f 3
+		fi
+	elif [ -d "$1" ]; then
+		dir_filelist "$1"
 	else
-		echo "  $0: Cannot open '$cpio_source'" >&2
+		echo "  ${prog}: Cannot open '$1'" >&2
 		exit 1
 	fi
 }
 
-
+prog=$0
 root_uid=0
 root_gid=0
+dep_list=
+cpio_file=
+cpio_list=
+output="/dev/stdout"
+output_file=""
 
+arg="$1"
+case "$arg" in
+	"-l")	# files included in initramfs - used by kbuild
+		dep_list="list_"
+		shift
+		;;
+	"-o")	# generate gzipped cpio image named $1
+		shift
+		output_file="$1"
+		cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
+		output=${cpio_list}
+		shift
+		;;
+esac
 while [ $# -gt 0 ]; do
 	arg="$1"
 	shift
 	case "$arg" in
-		"-u")
+		"-u")	# map $1 to uid=0 (root)
 			root_uid="$1"
 			shift
 			;;
-		"-g")
+		"-g")	# map $1 to gid=0 (root)
 			root_gid="$1"
 			shift
 			;;
-		"-d")
+		"-d")	# display default initramfs list
 			default_list="$arg"
-			default_initramfs
+			${dep_list}default_initramfs
 			;;
 		"-h")
 			usage
@@ -181,23 +256,27 @@
 		*)
 			case "$arg" in
 				"-"*)
-					printf "ERROR: unknown option \"$arg\"\n" >&2
-					printf "If the filename validly begins with '-', then it must be prefixed\n" >&2
-					printf "by './' so that it won't be interpreted as an option." >&2
-					printf "\n" >&2
-					usage >&2
-					exit 1
+					unknown_option
 					;;
-				*)
-					cpio_source="$arg"
-					build_list
+				*)	# input file/dir - process it
+					input_file "$arg" "$#"
 					;;
 			esac
 			;;
 	esac
 done
 
-# spit out the default cpio list if a source hasn't been specified
-[ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs
-
+# If output_file is set we will generate cpio archive and gzip it
+# we are carefull to delete tmp files
+if [ ! -z ${output_file} ]; then
+	if [ -z ${cpio_file} ]; then
+		cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
+		usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
+	else
+		cpio_tfile=${cpio_file}
+	fi
+	rm ${cpio_list}
+	cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
+	[ -z ${cpio_file} ] && rm ${cpio_tfile}
+fi
 exit 0
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 10eeae5..8012d10 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -5,6 +5,7 @@
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
@@ -63,20 +64,6 @@
 	}
 }
 
-static char *fgets_check_stream(char *s, int size, FILE *stream)
-{
-	char *ret = fgets(s, size, stream);
-
-	if (ret == NULL && feof(stream)) {
-		printf(_("aborted!\n\n"));
-		printf(_("Console input is closed. "));
-		printf(_("Run 'make oldconfig' to update configuration.\n\n"));
-		exit(1);
-	}
-
-	return ret;
-}
-
 static void conf_askvalue(struct symbol *sym, const char *def)
 {
 	enum symbol_type type = sym_get_type(sym);
@@ -114,7 +101,7 @@
 		check_stdin();
 	case ask_all:
 		fflush(stdout);
-		fgets_check_stream(line, 128, stdin);
+		fgets(line, 128, stdin);
 		return;
 	case set_default:
 		printf("%s\n", def);
@@ -328,8 +315,7 @@
 		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
 		def_sym = sym_get_choice_value(sym);
 		cnt = def = 0;
-		line[0] = '0';
-		line[1] = 0;
+		line[0] = 0;
 		for (child = menu->list; child; child = child->next) {
 			if (!menu_is_visible(child))
 				continue;
@@ -370,7 +356,7 @@
 			check_stdin();
 		case ask_all:
 			fflush(stdout);
-			fgets_check_stream(line, 128, stdin);
+			fgets(line, 128, stdin);
 			strip(line);
 			if (line[0] == '?') {
 				printf("\n%s\n", menu->sym->help ?
@@ -546,7 +532,7 @@
 			break;
 		case 'h':
 		case '?':
-			printf("%s [-o|-s] config\n", av[0]);
+			fprintf(stderr, "See README for usage info\n");
 			exit(0);
 		}
 	}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1b8882d..1b5df58 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -325,7 +325,7 @@
 				sym->flags |= e->right.sym->flags & SYMBOL_NEW;
 	}
 
-	sym_change_count = conf_warnings && conf_unsaved;
+	sym_change_count = conf_warnings || conf_unsaved;
 
 	return 0;
 }
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index db07ae7..be0200e 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -196,8 +196,8 @@
 
 	print_buttons(dialog, height, width, 0);
 
-	wnoutrefresh(list);
 	wnoutrefresh(dialog);
+	wnoutrefresh(list);
 	doupdate();
 
 	while (key != ESC) {
@@ -225,12 +225,11 @@
 					}
 					scroll--;
 					print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
-					wnoutrefresh(list);
-
 					print_arrows(dialog, choice, item_no,
 						     scroll, box_y, box_x + check_x + 5, list_height);
 
-					wrefresh(dialog);
+					wnoutrefresh(dialog);
+					wrefresh(list);
 
 					continue;	/* wait for another key press */
 				} else
@@ -252,12 +251,12 @@
 					scroll++;
 					print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
 						   status[scroll + max_choice - 1], max_choice - 1, TRUE);
-					wnoutrefresh(list);
 
 					print_arrows(dialog, choice, item_no,
 						     scroll, box_y, box_x + check_x + 5, list_height);
 
-					wrefresh(dialog);
+					wnoutrefresh(dialog);
+					wrefresh(list);
 
 					continue;	/* wait for another key press */
 				} else
@@ -271,8 +270,8 @@
 				choice = i;
 				print_item(list, items[(scroll + choice) * 3 + 1],
 					   status[scroll + choice], choice, TRUE);
-				wnoutrefresh(list);
-				wrefresh(dialog);
+				wnoutrefresh(dialog);
+				wrefresh(list);
 			}
 			continue;	/* wait for another key press */
 		}
@@ -306,8 +305,8 @@
 						print_item(list, items[(scroll + i) * 3 + 1],
 							   status[scroll + i], i, i == choice);
 				}
-				wnoutrefresh(list);
-				wrefresh(dialog);
+				wnoutrefresh(dialog);
+				wrefresh(list);
 
 				for (i = 0; i < item_no; i++)
 					if (status[i])
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 09512b5..bf8052f 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -58,8 +58,7 @@
 
 #include "dialog.h"
 
-#define ITEM_IDENT 1   /* Indent of menu entries. Fixed for all menus */
-static int menu_width;
+static int menu_width, item_x;
 
 /*
  * Print menu item
@@ -70,7 +69,7 @@
 	int j;
 	char *menu_item = malloc(menu_width + 1);
 
-	strncpy(menu_item, item, menu_width - ITEM_IDENT);
+	strncpy(menu_item, item, menu_width - item_x);
 	menu_item[menu_width] = 0;
 	j = first_alpha(menu_item, "YyNnMmHh");
 
@@ -87,13 +86,13 @@
 	wclrtoeol(win);
 #endif
 	wattrset(win, selected ? item_selected_attr : item_attr);
-	mvwaddstr(win, choice, ITEM_IDENT, menu_item);
+	mvwaddstr(win, choice, item_x, menu_item);
 	if (hotkey) {
 		wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
-		mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]);
+		mvwaddch(win, choice, item_x + j, menu_item[j]);
 	}
 	if (selected) {
-		wmove(win, choice, ITEM_IDENT + 1);
+		wmove(win, choice, item_x + 1);
 	}
 	free(menu_item);
 	wrefresh(win);
@@ -227,6 +226,8 @@
 	draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
 		 menubox_border_attr, menubox_attr);
 
+	item_x = (menu_width - 70) / 2;
+
 	/* Set choice to default item */
 	for (i = 0; i < item_no; i++)
 		if (strcmp(current, items[i * 2]) == 0)
@@ -263,10 +264,10 @@
 	wnoutrefresh(menu);
 
 	print_arrows(dialog, item_no, scroll,
-		     box_y, box_x + ITEM_IDENT + 1, menu_height);
+		     box_y, box_x + item_x + 1, menu_height);
 
 	print_buttons(dialog, height, width, 0);
-	wmove(menu, choice, ITEM_IDENT + 1);
+	wmove(menu, choice, item_x + 1);
 	wrefresh(menu);
 
 	while (key != ESC) {
@@ -349,7 +350,7 @@
 			print_item(scroll + choice, choice, TRUE);
 
 			print_arrows(dialog, item_no, scroll,
-				     box_y, box_x + ITEM_IDENT + 1, menu_height);
+				     box_y, box_x + item_x + 1, menu_height);
 
 			wnoutrefresh(dialog);
 			wrefresh(menu);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0b92ddf..cd00e9f 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -492,17 +492,19 @@
  *   These functions may often be marked __init and we do not want to
  *   warn here.
  *   the pattern is identified by:
- *   tosec   = .init.text | .exit.text
+ *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
- *   atsym = *_driver, *_ops, *_probe, *probe_one
+ *   atsym = *_driver, *_template, *_sht, *_ops, *_probe, *probe_one
  **/
 static int secref_whitelist(const char *tosec, const char *fromsec,
-			  const char *atsym)
+			    const char *atsym)
 {
 	int f1 = 1, f2 = 1;
 	const char **s;
 	const char *pat2sym[] = {
 		"_driver",
+		"_template", /* scsi uses *_template a lot */
+		"_sht",      /* scsi also used *_sht to some extent */
 		"_ops",
 		"_probe",
 		"_probe_one",
@@ -522,7 +524,8 @@
 
 	/* Check for pattern 2 */
 	if ((strcmp(tosec, ".init.text") != 0) &&
-	    (strcmp(tosec, ".exit.text") != 0))
+	    (strcmp(tosec, ".exit.text") != 0) &&
+	    (strcmp(tosec, ".init.data") != 0))
 		f2 = 0;
 	if (strcmp(fromsec, ".data") != 0)
 		f2 = 0;
@@ -658,7 +661,7 @@
 		warn("%s - Section mismatch: reference to %s:%s from %s "
 		     "before '%s' (at offset -0x%llx)\n",
 		     modname, secname, refsymname, fromsec,
-		     elf->strtab + before->st_name,
+		     elf->strtab + after->st_name,
 		     (long long)r.r_offset);
 	} else {
 		warn("%s - Section mismatch: reference to %s:%s from %s "
@@ -820,6 +823,7 @@
  * For our future {in}sanity, add a comment that this is the ppc .opd
  * section, not the ia64 .opd section.
  * ia64 .opd should not point to discarded sections.
+ * [.rodata] like for .init.text we ignore .rodata references -same reason
  **/
 static int exit_section_ref_ok(const char *name)
 {
@@ -829,6 +833,7 @@
 		".exit.text",
 		".exit.data",
 		".init.text",
+		".rodata",
 		".opd", /* See comment [OPD] */
 		".toc1",  /* used by ppc64 */
 		".altinstructions",
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
old mode 100644
new mode 100755
diff --git a/scripts/show_delta b/scripts/show_delta
old mode 100644
new mode 100755
diff --git a/scripts/ver_linux b/scripts/ver_linux
index beb43ef7..84999f6 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -39,10 +39,10 @@
 fsck.jfs -V 2>&1 | grep version | sed 's/,//' |  awk \
 'NR==1 {print "jfsutils              ", $3}'
 
-reiserfsck -V 2>&1 | grep reiserfsck | awk \
+reiserfsck -V 2>&1 | grep ^reiserfsck | awk \
 'NR==1{print "reiserfsprogs         ", $2}'
 
-fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \
 'NR==1{print "reiser4progs          ", $2}'
 
 xfs_db -V 2>&1 | grep version | awk \
diff --git a/security/keys/key.c b/security/keys/key.c
index a057e33..b6061fa 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -785,6 +785,10 @@
 
 	key_check(keyring);
 
+	key_ref = ERR_PTR(-ENOTDIR);
+	if (keyring->type != &key_type_keyring)
+		goto error_2;
+
 	down_write(&keyring->sem);
 
 	/* if we're going to allocate a new key, we're going to have
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index d65a180..bffa924 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -437,6 +437,7 @@
 /*
  * search the given keyring only (no recursion)
  * - keyring must be locked by caller
+ * - caller must guarantee that the keyring is a keyring
  */
 key_ref_t __keyring_search_one(key_ref_t keyring_ref,
 			       const struct key_type *ktype,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index f694061..217a0be 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -168,11 +168,12 @@
  */
 int install_process_keyring(struct task_struct *tsk)
 {
-	unsigned long flags;
 	struct key *keyring;
 	char buf[20];
 	int ret;
 
+	might_sleep();
+
 	if (!tsk->signal->process_keyring) {
 		sprintf(buf, "_pid.%u", tsk->tgid);
 
@@ -183,12 +184,12 @@
 		}
 
 		/* attach keyring */
-		spin_lock_irqsave(&tsk->sighand->siglock, flags);
+		spin_lock_irq(&tsk->sighand->siglock);
 		if (!tsk->signal->process_keyring) {
 			tsk->signal->process_keyring = keyring;
 			keyring = NULL;
 		}
-		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+		spin_unlock_irq(&tsk->sighand->siglock);
 
 		key_put(keyring);
 	}
@@ -207,38 +208,37 @@
 static int install_session_keyring(struct task_struct *tsk,
 				   struct key *keyring)
 {
-	unsigned long flags;
 	struct key *old;
 	char buf[20];
-	int ret;
+
+	might_sleep();
 
 	/* create an empty session keyring */
 	if (!keyring) {
 		sprintf(buf, "_ses.%u", tsk->tgid);
 
 		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
-		if (IS_ERR(keyring)) {
-			ret = PTR_ERR(keyring);
-			goto error;
-		}
+		if (IS_ERR(keyring))
+			return PTR_ERR(keyring);
 	}
 	else {
 		atomic_inc(&keyring->usage);
 	}
 
 	/* install the keyring */
-	spin_lock_irqsave(&tsk->sighand->siglock, flags);
-	old = rcu_dereference(tsk->signal->session_keyring);
+	spin_lock_irq(&tsk->sighand->siglock);
+	old = tsk->signal->session_keyring;
 	rcu_assign_pointer(tsk->signal->session_keyring, keyring);
-	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+	spin_unlock_irq(&tsk->sighand->siglock);
 
-	ret = 0;
+	/* we're using RCU on the pointer, but there's no point synchronising
+	 * on it if it didn't previously point to anything */
+	if (old) {
+		synchronize_rcu();
+		key_put(old);
+	}
 
-	/* we're using RCU on the pointer */
-	synchronize_rcu();
-	key_put(old);
-error:
-	return ret;
+	return 0;
 
 } /* end install_session_keyring() */
 
@@ -311,7 +311,6 @@
  */
 int exec_keys(struct task_struct *tsk)
 {
-	unsigned long flags;
 	struct key *old;
 
 	/* newly exec'd tasks don't get a thread keyring */
@@ -323,10 +322,10 @@
 	key_put(old);
 
 	/* discard the process keyring from a newly exec'd task */
-	spin_lock_irqsave(&tsk->sighand->siglock, flags);
+	spin_lock_irq(&tsk->sighand->siglock);
 	old = tsk->signal->process_keyring;
 	tsk->signal->process_keyring = NULL;
-	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+	spin_unlock_irq(&tsk->sighand->siglock);
 
 	key_put(old);
 
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 640d0bf..84047f69 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -264,7 +264,7 @@
 
 	if (!selinux_mls_enabled) {
 		if (def_sid != SECSID_NULL && oldc)
-			*scontext += strlen(*scontext);
+			*scontext += strlen(*scontext)+1;
 		return 0;
 	}
 
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index dfab6c8..abe99d8 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -281,7 +281,7 @@
 		int i;
 
 		for (i = sp->len-1; i >= 0; i--) {
-			struct xfrm_state *x = sp->x[i].xvec;
+			struct xfrm_state *x = sp->xvec[i];
 			if (selinux_authorizable_xfrm(x)) {
 				struct xfrm_sec_ctx *ctx = x->security;
 				return ctx->ctx_sid;
@@ -314,7 +314,7 @@
 		 *  Only need to verify the existence of an authorizable sp.
 		 */
 		for (i = 0; i < sp->len; i++) {
-			struct xfrm_state *x = sp->x[i].xvec;
+			struct xfrm_state *x = sp->xvec[i];
 
 			if (x && selinux_authorizable_xfrm(x))
 				goto accept;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 9dd121b..8efc1b1 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -92,8 +92,9 @@
 
 	  Many programs still use the OSS API, so say Y.
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called snd-seq-oss.
+	  If you choose M in "Sequencer support" (SND_SEQUENCER),
+	  this will be compiled as a module. The module will be called
+	  snd-seq-oss.
 
 config SND_RTCTIMER
 	tristate "RTC Timer support"
diff --git a/sound/core/control.c b/sound/core/control.c
index 5747453..22565c9b 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -664,7 +664,7 @@
 	if (copy_from_user(&info, _info, sizeof(info)))
 		return -EFAULT;
 	snd_power_lock(ctl->card);
-	result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+	result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
 	if (result >= 0)
 		result = snd_ctl_elem_info(ctl, &info);
 	snd_power_unlock(ctl->card);
@@ -718,7 +718,7 @@
 		return -EFAULT;
 	}
 	snd_power_lock(card);
-	result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+	result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 	if (result >= 0)
 		result = snd_ctl_elem_read(card, control);
 	snd_power_unlock(card);
@@ -783,7 +783,7 @@
 	}
 	card = file->card;
 	snd_power_lock(card);
-	result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+	result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 	if (result >= 0)
 		result = snd_ctl_elem_write(card, file, control);
 	snd_power_unlock(card);
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 84fef50..3c0161b 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -109,7 +109,7 @@
 		goto error;
 
 	snd_power_lock(ctl->card);
-	err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL);
+	err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
 	if (err >= 0)
 		err = snd_ctl_elem_info(ctl, data);
 	snd_power_unlock(ctl->card);
@@ -294,7 +294,7 @@
 		goto error;
 
 	snd_power_lock(card);
-	err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+	err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 	if (err >= 0)
 		err = snd_ctl_elem_read(card, data);
 	snd_power_unlock(card);
@@ -320,7 +320,7 @@
 		goto error;
 
 	snd_power_lock(card);
-	err = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL);
+	err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 	if (err >= 0)
 		err = snd_ctl_elem_write(card, file, data);
 	snd_power_unlock(card);
diff --git a/sound/core/init.c b/sound/core/init.c
index 5bb8a8b..39ed2e5 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -722,13 +722,12 @@
  *  snd_power_wait - wait until the power-state is changed.
  *  @card: soundcard structure
  *  @power_state: expected power state
- *  @file: file structure for the O_NONBLOCK check (optional)
  *
  *  Waits until the power-state is changed.
  *
  *  Note: the power lock must be active before call.
  */
-int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file)
+int snd_power_wait(struct snd_card *card, unsigned int power_state)
 {
 	wait_queue_t wait;
 	int result = 0;
@@ -745,12 +744,6 @@
 		}
 		if (snd_power_get_state(card) == power_state)
 			break;
-#if 0 /* block all devices */
-		if (file && (file->f_flags & O_NONBLOCK)) {
-			result = -EAGAIN;
-			break;
-		}
-#endif
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		snd_power_unlock(card);
 		schedule_timeout(30 * HZ);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f8302b7..c5978d6 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -208,9 +208,8 @@
 			oss_buffer_size = runtime->oss.mmap_bytes;
 	}
 
-	if (substream->oss.setup &&
-	    substream->oss.setup->period_size > 16)
-		oss_period_size = substream->oss.setup->period_size;
+	if (substream->oss.setup.period_size > 16)
+		oss_period_size = substream->oss.setup.period_size;
 	else if (runtime->oss.fragshift) {
 		oss_period_size = 1 << runtime->oss.fragshift;
 		if (oss_period_size > oss_buffer_size / 2)
@@ -252,10 +251,8 @@
 
 	oss_periods = oss_buffer_size / oss_period_size;
 
-	if (substream->oss.setup) {
-		if (substream->oss.setup->periods > 1)
-			oss_periods = substream->oss.setup->periods;
-	}
+	if (substream->oss.setup.periods > 1)
+		oss_periods = substream->oss.setup.periods;
 
 	s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL);
 	if (runtime->oss.maxfrags && s > runtime->oss.maxfrags)
@@ -341,12 +338,10 @@
 		goto failure;
 	}
 
-	if (atomic_read(&runtime->mmap_count)) {
+	if (atomic_read(&runtime->mmap_count))
 		direct = 1;
-	} else {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		direct = (setup != NULL && setup->direct);
-	}
+	else
+		direct = substream->oss.setup.direct;
 
 	_snd_pcm_hw_params_any(sparams);
 	_snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
@@ -482,7 +477,7 @@
 		1 : runtime->period_size;
 	sw_params->xfer_align = 1;
 	if (atomic_read(&runtime->mmap_count) ||
-	    (substream->oss.setup && substream->oss.setup->nosilence)) {
+	    substream->oss.setup.nosilence) {
 		sw_params->silence_threshold = 0;
 		sw_params->silence_size = 0;
 	} else {
@@ -843,7 +838,7 @@
 			buf += tmp;
 			bytes -= tmp;
 			xfer += tmp;
-			if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
+			if (substream->oss.setup.partialfrag ||
 			    runtime->oss.buffer_used == runtime->oss.period_bytes) {
 				tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 
 							 runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
@@ -959,12 +954,12 @@
 
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream != NULL) {
-		snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+		snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
 		substream->runtime->oss.prepare = 1;
 	}
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
 	if (substream != NULL) {
-		snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+		snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
 		substream->runtime->oss.prepare = 1;
 	}
 	return 0;
@@ -979,7 +974,7 @@
 	if (substream != NULL) {
 		if ((err = snd_pcm_oss_make_ready(substream)) < 0)
 			return err;
-		snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
+		snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL);
 	}
 	/* note: all errors from the start action are ignored */
 	/* OSS apps do not know, how to handle them */
@@ -1108,7 +1103,7 @@
 	      __direct:
 		saved_f_flags = substream->ffile->f_flags;
 		substream->ffile->f_flags &= ~O_NONBLOCK;
-		err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
+		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 		substream->ffile->f_flags = saved_f_flags;
 		if (err < 0)
 			return err;
@@ -1120,7 +1115,7 @@
 		if ((err = snd_pcm_oss_make_ready(substream)) < 0)
 			return err;
 		runtime = substream->runtime;
-		err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
 		if (err < 0)
 			return err;
 		runtime->oss.buffer_used = 0;
@@ -1214,12 +1209,10 @@
 
 	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
 		return err;
-	if (atomic_read(&substream->runtime->mmap_count)) {
+	if (atomic_read(&substream->runtime->mmap_count))
 		direct = 1;
-	} else {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		direct = (setup != NULL && setup->direct);
-	}
+	else
+		direct = substream->oss.setup.direct;
 	if (!direct)
 		return AFMT_MU_LAW | AFMT_U8 |
 		       AFMT_S16_LE | AFMT_S16_BE |
@@ -1437,7 +1430,7 @@
 			cmd = SNDRV_PCM_IOCTL_DROP;
 			runtime->oss.prepare = 1;
 		}
-		err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL);
+		err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
 		if (err < 0)
 			return err;
 	}
@@ -1458,7 +1451,7 @@
 			cmd = SNDRV_PCM_IOCTL_DROP;
 			runtime->oss.prepare = 1;
 		}
-		err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL);
+		err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
 		if (err < 0)
 			return err;
 	}
@@ -1495,7 +1488,7 @@
 	runtime = substream->runtime;
 	if (runtime->oss.params || runtime->oss.prepare)
 		return 0;
-	err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
 	if (err == -EPIPE)
 		delay = 0;	/* hack for broken OSS applications */
 	else if (err < 0)
@@ -1555,8 +1548,7 @@
 	} else {
 		delay = snd_pcm_oss_bytes(substream, delay);
 		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			struct snd_pcm_oss_setup *setup = substream->oss.setup;
-			if (setup && setup->buggyptr)
+			if (substream->oss.setup.buggyptr)
 				info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
 			else
 				info.blocks = (delay + fixup) / runtime->oss.period_bytes;
@@ -1638,37 +1630,46 @@
 	return -EINVAL;
 }
 
-static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
+static const char *strip_task_path(const char *path)
 {
-	const char *ptr, *ptrl;
+	const char *ptr, *ptrl = NULL;
+	for (ptr = path; *ptr; ptr++) {
+		if (*ptr == '/')
+			ptrl = ptr + 1;
+	}
+	return ptrl;
+}
+
+static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
+				      const char *task_name,
+				      struct snd_pcm_oss_setup *rsetup)
+{
 	struct snd_pcm_oss_setup *setup;
 
 	mutex_lock(&pcm->streams[stream].oss.setup_mutex);
-	for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
-		if (!strcmp(setup->task_name, task_name)) {
-			mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
-			return setup;
+	do {
+		for (setup = pcm->streams[stream].oss.setup_list; setup;
+		     setup = setup->next) {
+			if (!strcmp(setup->task_name, task_name))
+				goto out;
 		}
-	}
-	ptr = ptrl = task_name;
-	while (*ptr) {
-		if (*ptr == '/')
-			ptrl = ptr + 1;
-		ptr++;
-	}
-	if (ptrl == task_name) {
-		goto __not_found;
-		return NULL;
-	}
-	for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
-		if (!strcmp(setup->task_name, ptrl)) {
-			mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
-			return setup;
-		}
-	}
-      __not_found:
+	} while ((task_name = strip_task_path(task_name)) != NULL);
+ out:
+	if (setup)
+		*rsetup = *setup;
 	mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
-	return NULL;
+}
+
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime;
+	runtime = substream->runtime;
+	vfree(runtime->oss.buffer);
+	runtime->oss.buffer = NULL;
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+	snd_pcm_oss_plugin_clear(substream);
+#endif
+	substream->oss.oss = 0;
 }
 
 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
@@ -1678,7 +1679,11 @@
 	struct snd_pcm_runtime *runtime;
 
 	substream->oss.oss = 1;
-	substream->oss.setup = setup;
+	substream->oss.setup = *setup;
+	if (setup->nonblock)
+		substream->ffile->f_flags |= O_NONBLOCK;
+	else if (setup->block)
+		substream->ffile->f_flags &= ~O_NONBLOCK;
 	runtime = substream->runtime;
 	runtime->oss.params = 1;
 	runtime->oss.trigger = 1;
@@ -1697,18 +1702,7 @@
 	runtime->oss.fragshift = 0;
 	runtime->oss.maxfrags = 0;
 	runtime->oss.subdivision = 0;
-}
-
-static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime;
-	runtime = substream->runtime;
-	vfree(runtime->oss.buffer);
-#ifdef CONFIG_SND_PCM_OSS_PLUGINS
-	snd_pcm_oss_plugin_clear(substream);
-#endif
-	substream->oss.file = NULL;
-	substream->oss.oss = 0;
+	substream->pcm_release = snd_pcm_oss_release_substream;
 }
 
 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1717,23 +1711,8 @@
 	snd_assert(pcm_oss_file != NULL, return -ENXIO);
 	for (cidx = 0; cidx < 2; ++cidx) {
 		struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
-		struct snd_pcm_runtime *runtime;
-		if (substream == NULL)
-			continue;
-		runtime = substream->runtime;
-		
-		snd_pcm_stream_lock_irq(substream);
-		if (snd_pcm_running(substream))
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-		snd_pcm_stream_unlock_irq(substream);
-		if (substream->ffile != NULL) {
-			if (substream->ops->hw_free != NULL)
-				substream->ops->hw_free(substream);
-			substream->ops->close(substream);
-			substream->ffile = NULL;
-		}
-		snd_pcm_oss_release_substream(substream);
-		snd_pcm_release_substream(substream);
+		if (substream)
+			snd_pcm_release_substream(substream);
 	}
 	kfree(pcm_oss_file);
 	return 0;
@@ -1743,12 +1722,11 @@
 				 struct snd_pcm *pcm,
 				 struct snd_pcm_oss_file **rpcm_oss_file,
 				 int minor,
-				 struct snd_pcm_oss_setup *psetup,
-				 struct snd_pcm_oss_setup *csetup)
+				 struct snd_pcm_oss_setup *setup)
 {
-	int err = 0;
+	int idx, err;
 	struct snd_pcm_oss_file *pcm_oss_file;
-	struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
+	struct snd_pcm_substream *substream;
 	unsigned int f_mode = file->f_mode;
 
 	snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1761,73 +1739,32 @@
 	if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
 	    (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
 		f_mode = FMODE_WRITE;
-	if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) {
-		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-					       &psubstream)) < 0) {
+
+	for (idx = 0; idx < 2; idx++) {
+		if (setup[idx].disable)
+			continue;
+		if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (! (f_mode & FMODE_WRITE))
+				continue;
+		} else {
+			if (! (f_mode & FMODE_READ))
+				continue;
+		}
+		err = snd_pcm_open_substream(pcm, idx, file, &substream);
+		if (err < 0) {
 			snd_pcm_oss_release_file(pcm_oss_file);
 			return err;
 		}
-		pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream;
-	}
-	if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) {
-		if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 
-					       &csubstream)) < 0) {
-			if (!(f_mode & FMODE_WRITE) || err != -ENODEV) {
-				snd_pcm_oss_release_file(pcm_oss_file);
-				return err;
-			} else {
-				csubstream = NULL;
-			}
-		}
-		pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream;
+
+		pcm_oss_file->streams[idx] = substream;
+		substream->file = pcm_oss_file;
+		snd_pcm_oss_init_substream(substream, &setup[idx], minor);
 	}
 	
-	if (psubstream == NULL && csubstream == NULL) {
+	if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
 		snd_pcm_oss_release_file(pcm_oss_file);
 		return -EINVAL;
 	}
-	if (psubstream != NULL) {
-		psubstream->oss.file = pcm_oss_file;
-		err = snd_pcm_hw_constraints_init(psubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_init failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		if ((err = psubstream->ops->open(psubstream)) < 0) {
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		psubstream->ffile = file;
-		err = snd_pcm_hw_constraints_complete(psubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_complete failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		snd_pcm_oss_init_substream(psubstream, psetup, minor);
-	}
-	if (csubstream != NULL) {
-		csubstream->oss.file = pcm_oss_file;
-		err = snd_pcm_hw_constraints_init(csubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_init failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		if ((err = csubstream->ops->open(csubstream)) < 0) {
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		csubstream->ffile = file;
-		err = snd_pcm_hw_constraints_complete(csubstream);
-		if (err < 0) {
-			snd_printd("snd_pcm_hw_constraint_complete failed\n");
-			snd_pcm_oss_release_file(pcm_oss_file);
-			return err;
-		}
-		snd_pcm_oss_init_substream(csubstream, csetup, minor);
-	}
 
 	file->private_data = pcm_oss_file;
 	*rpcm_oss_file = pcm_oss_file;
@@ -1852,7 +1789,7 @@
 	char task_name[32];
 	struct snd_pcm *pcm;
 	struct snd_pcm_oss_file *pcm_oss_file;
-	struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
+	struct snd_pcm_oss_setup setup[2];
 	int nonblock;
 	wait_queue_t wait;
 
@@ -1873,23 +1810,15 @@
 		err = -EFAULT;
 		goto __error;
 	}
+	memset(setup, 0, sizeof(setup));
 	if (file->f_mode & FMODE_WRITE)
-		psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name);
+		snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+					   task_name, &setup[0]);
 	if (file->f_mode & FMODE_READ)
-		csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name);
+		snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
+					   task_name, &setup[1]);
 
 	nonblock = !!(file->f_flags & O_NONBLOCK);
-	if (psetup && !psetup->disable) {
-		if (psetup->nonblock)
-			nonblock = 1;
-		else if (psetup->block)
-			nonblock = 0;
-	} else if (csetup && !csetup->disable) {
-		if (csetup->nonblock)
-			nonblock = 1;
-		else if (csetup->block)
-			nonblock = 0;
-	}
 	if (!nonblock)
 		nonblock = nonblock_open;
 
@@ -1898,7 +1827,7 @@
 	mutex_lock(&pcm->open_mutex);
 	while (1) {
 		err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
-					    iminor(inode), psetup, csetup);
+					    iminor(inode), setup);
 		if (err >= 0)
 			break;
 		if (err == -EAGAIN) {
@@ -2312,13 +2241,8 @@
 
 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
 {
-	unsigned int idx;
-	struct snd_pcm_substream *substream;
 	struct snd_pcm_oss_setup *setup, *setupn;
 
-	for (idx = 0, substream = pstr->substream;
-	     idx < pstr->substream_count; idx++, substream = substream->next)
-		substream->oss.setup = NULL;
 	for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
 	     setup; setup = setupn) {
 		setupn = setup->next;
@@ -2379,21 +2303,28 @@
 			}
 		} while (*str);
 		if (setup == NULL) {
-			setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
-			if (setup) {
-				if (pstr->oss.setup_list == NULL) {
-					pstr->oss.setup_list = setup;
-				} else {
-					for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
-					setup1->next = setup;
-				}
-				template.task_name = kstrdup(task_name, GFP_KERNEL);
-			} else {
+			setup = kmalloc(sizeof(*setup), GFP_KERNEL);
+			if (! setup) {
 				buffer->error = -ENOMEM;
+				mutex_lock(&pstr->oss.setup_mutex);
+				return;
+			}
+			if (pstr->oss.setup_list == NULL)
+				pstr->oss.setup_list = setup;
+			else {
+				for (setup1 = pstr->oss.setup_list;
+				     setup1->next; setup1 = setup1->next);
+				setup1->next = setup;
+			}
+			template.task_name = kstrdup(task_name, GFP_KERNEL);
+			if (! template.task_name) {
+				kfree(setup);
+				buffer->error = -ENOMEM;
+				mutex_lock(&pstr->oss.setup_mutex);
+				return;
 			}
 		}
-		if (setup)
-			*setup = template;
+		*setup = template;
 		mutex_unlock(&pstr->oss.setup_mutex);
 	}
 }
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 3da6a38..122e10a 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -196,7 +196,7 @@
 	FORMAT(U18_3BE),
 };
 
-const char *snd_pcm_format_name(snd_pcm_format_t format)
+static const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
 	return snd_pcm_format_names[format];
 }
@@ -777,8 +777,9 @@
 	snd_pcm_tick_elapsed(substream);
 }
 
-int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
-			   struct snd_pcm_substream **rsubstream)
+int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
+			     struct file *file,
+			     struct snd_pcm_substream **rsubstream)
 {
 	struct snd_pcm_str * pstr;
 	struct snd_pcm_substream *substream;
@@ -793,7 +794,7 @@
 	*rsubstream = NULL;
 	snd_assert(pcm != NULL, return -ENXIO);
 	pstr = &pcm->streams[stream];
-	if (pstr->substream == NULL)
+	if (pstr->substream == NULL || pstr->substream_count == 0)
 		return -ENODEV;
 
 	card = pcm->card;
@@ -807,8 +808,6 @@
 	}
 	up_read(&card->controls_rwsem);
 
-	if (pstr->substream_count == 0)
-		return -ENODEV;
 	switch (stream) {
 	case SNDRV_PCM_STREAM_PLAYBACK:
 		if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
@@ -874,12 +873,13 @@
 
 	substream->runtime = runtime;
 	substream->private_data = pcm->private_data;
+	substream->ffile = file;
 	pstr->substream_opened++;
 	*rsubstream = substream;
 	return 0;
 }
 
-void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime;
 	substream->file = NULL;
@@ -1111,8 +1111,6 @@
 EXPORT_SYMBOL(snd_pcm_suspend);
 EXPORT_SYMBOL(snd_pcm_suspend_all);
 #endif
-EXPORT_SYMBOL(snd_pcm_kernel_playback_ioctl);
-EXPORT_SYMBOL(snd_pcm_kernel_capture_ioctl);
 EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
 EXPORT_SYMBOL(snd_pcm_mmap_data);
 #if SNDRV_PCM_INFO_MMAP_IOMEM
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eeba2f0..230a940 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2299,19 +2299,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
 	    runtime->channels > 1)
@@ -2374,19 +2362,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
@@ -2596,19 +2572,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
@@ -2665,20 +2629,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	snd_assert(substream->ffile != NULL, return -ENXIO);
 	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	if (substream->oss.oss) {
-		struct snd_pcm_oss_setup *setup = substream->oss.setup;
-		if (setup != NULL) {
-			if (setup->nonblock)
-				nonblock = 1;
-			else if (setup->block)
-				nonblock = 0;
-		}
-	}
-#endif
-
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 01f150f..0860c5a 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1170,7 +1170,7 @@
 	int res;
 
 	snd_power_lock(card);
-	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
 		res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
 	snd_power_unlock(card);
 	return res;
@@ -1198,7 +1198,7 @@
 
 	snd_power_lock(card);
 	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 		if (result < 0)
 			goto _unlock;
 	}
@@ -1313,13 +1313,13 @@
  *
  * Prepare the PCM substream to be triggerable.
  */
-int snd_pcm_prepare(struct snd_pcm_substream *substream)
+static int snd_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	int res;
 	struct snd_card *card = substream->pcm->card;
 
 	snd_power_lock(card);
-	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
+	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
 		res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
 	snd_power_unlock(card);
 	return res;
@@ -1410,7 +1410,7 @@
 
 	snd_power_lock(card);
 	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 		if (result < 0) {
 			snd_power_unlock(card);
 			return result;
@@ -1533,7 +1533,7 @@
 
 	snd_power_lock(card);
 	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
 		if (result < 0)
 			goto _unlock;
 	}
@@ -1995,28 +1995,65 @@
 	}
 }
 
-static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
+static void pcm_release_private(struct snd_pcm_substream *substream)
 {
-	struct snd_pcm_substream *substream;
-	struct snd_pcm_runtime *runtime;
-	struct snd_pcm_str * str;
+	struct snd_pcm_file *pcm_file = substream->file;
 
-	snd_assert(pcm_file != NULL, return -ENXIO);
-	substream = pcm_file->substream;
-	snd_assert(substream != NULL, return -ENXIO);
-	runtime = substream->runtime;
-	str = substream->pstr;
 	snd_pcm_unlink(substream);
-	if (substream->ffile != NULL) {
+	snd_pcm_remove_file(substream->pstr, pcm_file);
+	kfree(pcm_file);
+}
+
+void snd_pcm_release_substream(struct snd_pcm_substream *substream)
+{
+	snd_pcm_drop(substream);
+	if (substream->hw_opened) {
 		if (substream->ops->hw_free != NULL)
 			substream->ops->hw_free(substream);
 		substream->ops->close(substream);
-		substream->ffile = NULL;
+		substream->hw_opened = 0;
 	}
-	snd_pcm_remove_file(str, pcm_file);
-	snd_pcm_release_substream(substream);
-	kfree(pcm_file);
+	if (substream->pcm_release) {
+		substream->pcm_release(substream);
+		substream->pcm_release = NULL;
+	}
+	snd_pcm_detach_substream(substream);
+}
+
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+			   struct file *file,
+			   struct snd_pcm_substream **rsubstream)
+{
+	struct snd_pcm_substream *substream;
+	int err;
+
+	err = snd_pcm_attach_substream(pcm, stream, file, &substream);
+	if (err < 0)
+		return err;
+	substream->no_mmap_ctrl = 0;
+	err = snd_pcm_hw_constraints_init(substream);
+	if (err < 0) {
+		snd_printd("snd_pcm_hw_constraints_init failed\n");
+		goto error;
+	}
+
+	if ((err = substream->ops->open(substream)) < 0)
+		goto error;
+
+	substream->hw_opened = 1;
+
+	err = snd_pcm_hw_constraints_complete(substream);
+	if (err < 0) {
+		snd_printd("snd_pcm_hw_constraints_complete failed\n");
+		goto error;
+	}
+
+	*rsubstream = substream;
 	return 0;
+
+ error:
+	snd_pcm_release_substream(substream);
+	return err;
 }
 
 static int snd_pcm_open_file(struct file *file,
@@ -2024,52 +2061,29 @@
 			     int stream,
 			     struct snd_pcm_file **rpcm_file)
 {
-	int err = 0;
 	struct snd_pcm_file *pcm_file;
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_str *str;
+	int err;
 
 	snd_assert(rpcm_file != NULL, return -EINVAL);
 	*rpcm_file = NULL;
 
+	err = snd_pcm_open_substream(pcm, stream, file, &substream);
+	if (err < 0)
+		return err;
+
 	pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
 	if (pcm_file == NULL) {
+		snd_pcm_release_substream(substream);
 		return -ENOMEM;
 	}
-
-	if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
-		kfree(pcm_file);
-		return err;
-	}
-
 	str = substream->pstr;
 	substream->file = pcm_file;
-	substream->no_mmap_ctrl = 0;
-
+	substream->pcm_release = pcm_release_private;
 	pcm_file->substream = substream;
-
 	snd_pcm_add_file(str, pcm_file);
 
-	err = snd_pcm_hw_constraints_init(substream);
-	if (err < 0) {
-		snd_printd("snd_pcm_hw_constraints_init failed\n");
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-
-	if ((err = substream->ops->open(substream)) < 0) {
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-	substream->ffile = file;
-
-	err = snd_pcm_hw_constraints_complete(substream);
-	if (err < 0) {
-		snd_printd("snd_pcm_hw_constraints_complete failed\n");
-		snd_pcm_release_file(pcm_file);
-		return err;
-	}
-
 	file->private_data = pcm_file;
 	*rpcm_file = pcm_file;
 	return 0;
@@ -2158,10 +2172,9 @@
 	snd_assert(substream != NULL, return -ENXIO);
 	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
 	pcm = substream->pcm;
-	snd_pcm_drop(substream);
 	fasync_helper(-1, file, 0, &substream->runtime->fasync);
 	mutex_lock(&pcm->open_mutex);
-	snd_pcm_release_file(pcm_file);
+	snd_pcm_release_substream(substream);
 	mutex_unlock(&pcm->open_mutex);
 	wake_up(&pcm->open_wait);
 	module_put(pcm->card->module);
@@ -2480,11 +2493,6 @@
 	return 0;
 }
 		
-static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
-				   unsigned int cmd, void __user *arg);
-static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
-				  unsigned int cmd, void __user *arg);
-
 static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
 				 unsigned int cmd, void __user *arg)
 {
@@ -2736,41 +2744,28 @@
 	return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
 }
 
-int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream,
-				  unsigned int cmd, void *arg)
-{
-	mm_segment_t fs;
-	int result;
-	
-	fs = snd_enter_user();
-	result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
-	snd_leave_user(fs);
-	return result;
-}
-
-int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream,
-				 unsigned int cmd, void *arg)
-{
-	mm_segment_t fs;
-	int result;
-	
-	fs = snd_enter_user();
-	result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
-	snd_leave_user(fs);
-	return result;
-}
-
 int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
 			 unsigned int cmd, void *arg)
 {
+	mm_segment_t fs;
+	int result;
+	
+	fs = snd_enter_user();
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_PLAYBACK:
-		return snd_pcm_kernel_playback_ioctl(substream, cmd, arg);
+		result = snd_pcm_playback_ioctl1(substream,
+						 cmd, (void __user *)arg);
+		break;
 	case SNDRV_PCM_STREAM_CAPTURE:
-		return snd_pcm_kernel_capture_ioctl(substream, cmd, arg);
+		result = snd_pcm_capture_ioctl1(substream,
+						cmd, (void __user *)arg);
+		break;
 	default:
-		return -EINVAL;
+		result = -EINVAL;
+		break;
 	}
+	snd_leave_user(fs);
+	return result;
 }
 
 static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 8687ae3..b49a45c 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -183,7 +183,8 @@
 
  */
 
-static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
+static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+		int ack)
 {
 	unsigned long flags;
 	int timeout, ok;
@@ -218,9 +219,11 @@
 		ok = 1;
 	}
 	spin_unlock_irqrestore(&mpu->input_lock, flags);
-	if (! ok)
+	if (!ok) {
 		snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
-	// snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+		return 1;
+	}
+	return 0;
 }
 
 /*
@@ -235,12 +238,19 @@
 	if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+			goto error_out;
+		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+			goto error_out;
 	}
 	mpu->substream_input = substream;
 	set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	return 0;
+
+error_out:
+	if (mpu->open_input && mpu->close_input)
+		mpu->close_input(mpu);
+	return -EIO;
 }
 
 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
@@ -252,39 +262,52 @@
 	if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+			goto error_out;
+		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+			goto error_out;
 	}
 	mpu->substream_output = substream;
 	set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	return 0;
+
+error_out:
+	if (mpu->open_output && mpu->close_output)
+		mpu->close_output(mpu);
+	return -EIO;
 }
 
 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_mpu401 *mpu;
+	int err = 0;
 
 	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	mpu->substream_input = NULL;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+		err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
 	if (mpu->close_input)
 		mpu->close_input(mpu);
+	if (err)
+		return -EIO;
 	return 0;
 }
 
 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
 {
 	struct snd_mpu401 *mpu;
+	int err = 0;
 
 	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	mpu->substream_output = NULL;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
-		snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+		err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
 	if (mpu->close_output)
 		mpu->close_output(mpu);
+	if (err)
+		return -EIO;
 	return 0;
 }
 
@@ -316,6 +339,7 @@
 			snd_mpu401_uart_remove_timer(mpu, 1);
 		clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
 	}
+
 }
 
 /*
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ff8fef9..557c4de 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -11,6 +11,15 @@
         tristate
         select SND_PCM
 
+config SND_ADLIB
+	tristate "AdLib FM card"
+	select SND_OPL3_LIB
+	help
+	  Say Y here to include support for AdLib FM cards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-adlib.
+
 config SND_AD1816A
 	tristate "Analog Devices SoundPort AD1816A"
 	depends on SND && PNP && ISA
@@ -292,6 +301,20 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-opti93x.
 
+config SND_MIRO
+	tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
+	depends on SND
+	select SND_OPL4_LIB
+	select SND_CS4231_LIB
+	select SND_MPU401_UART
+	select SND_PCM
+	help
+	  Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro, 
+	  miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-miro.
+
 config SND_SB8
 	tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
 	depends on SND
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 05724eb..bb317cc 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -3,6 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
+snd-adlib-objs := adlib.o
 snd-als100-objs := als100.o
 snd-azt2320-objs := azt2320.o
 snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@
 snd-sscape-objs := sscape.o
 
 # Toplevel Module Dependency
+obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
 obj-$(CONFIG_SND_ALS100) += snd-als100.o
 obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
 obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 326a057..99908e4 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -193,9 +193,11 @@
 			continue;
 		device = platform_device_register_simple(SND_AD1848_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -204,14 +206,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_ad1848_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_ad1848_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_ad1848_exit(void)
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
new file mode 100644
index 0000000..1124344
--- /dev/null
+++ b/sound/isa/adlib.c
@@ -0,0 +1,164 @@
+/*
+ * AdLib FM card driver.
+ */
+
+#include <sound/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/opl3.h>
+
+#define CRD_NAME "AdLib FM"
+#define DRV_NAME "snd_adlib"
+
+MODULE_DESCRIPTION(CRD_NAME);
+MODULE_AUTHOR("Rene Herman");
+MODULE_LICENSE("GPL");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
+module_param_array(port, long, NULL, 0444);
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
+
+static struct platform_device *devices[SNDRV_CARDS];
+
+static void snd_adlib_free(struct snd_card *card)
+{
+	release_and_free_resource(card->private_data);
+}
+
+static int __devinit snd_adlib_probe(struct platform_device *device)
+{
+	struct snd_card *card;
+	struct snd_opl3 *opl3;
+
+	int error, i = device->id;
+
+	if (port[i] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
+		error = -EINVAL;
+		goto out0;
+	}
+
+	card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
+	if (!card) {
+		snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
+		error = -EINVAL;
+		goto out0;
+	}
+
+	card->private_data = request_region(port[i], 4, CRD_NAME);
+	if (!card->private_data) {
+		snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
+		error = -EBUSY;
+		goto out1;
+	}
+	card->private_free = snd_adlib_free;
+
+	error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
+	if (error < 0) {
+		snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
+		goto out1;
+	}
+
+	error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
+	if (error < 0) {
+		snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
+		goto out1;
+	}
+
+	strcpy(card->driver, DRV_NAME);
+	strcpy(card->shortname, CRD_NAME);
+	sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
+
+	snd_card_set_dev(card, &device->dev);
+
+	error = snd_card_register(card);
+	if (error < 0) {
+		snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
+		goto out1;
+	}
+
+	platform_set_drvdata(device, card);
+	return 0;
+
+out1:	snd_card_free(card);
+out0:	return error;
+}
+
+static int __devexit snd_adlib_remove(struct platform_device *device)
+{
+	snd_card_free(platform_get_drvdata(device));
+	platform_set_drvdata(device, NULL);
+	return 0;
+}
+
+static struct platform_driver snd_adlib_driver = {
+	.probe		= snd_adlib_probe,
+	.remove		= __devexit_p(snd_adlib_remove),
+
+	.driver		= {
+		.name	= DRV_NAME
+	}
+};
+
+static int __init alsa_card_adlib_init(void)
+{
+	int i, cards;
+
+	if (platform_driver_register(&snd_adlib_driver) < 0) {
+		snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
+		return -ENODEV;
+	}
+
+	for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
+		struct platform_device *device;
+
+		if (!enable[i])
+			continue;
+
+		device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
+		if (IS_ERR(device))
+			continue;
+
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
+		}
+
+		devices[i] = device;
+		cards++;
+	}
+
+	if (!cards) {
+#ifdef MODULE
+		printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
+#endif
+		platform_driver_unregister(&snd_adlib_driver);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit alsa_card_adlib_exit(void)
+{
+	int i;
+
+	for (i = 0; i < SNDRV_CARDS; i++)
+		platform_device_unregister(devices[i]);
+	platform_driver_unregister(&snd_adlib_driver);
+}
+
+module_init(alsa_card_adlib_init);
+module_exit(alsa_card_adlib_exit);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fa63048..3c1e9fd 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -693,15 +693,17 @@
 	if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
 		return err;
 
-	for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+	for (i = 0; i < SNDRV_CARDS; i++) {
 		struct platform_device *device;
-		if (is_isapnp_selected(i))
+		if (! enable[i] || is_isapnp_selected(i))
 			continue;
 		device = platform_device_register_simple(CMI8330_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		cards++;
@@ -719,14 +721,10 @@
 #ifdef MODULE
 		snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_cmi8330_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_cmi8330_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_cmi8330_exit(void)
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index a30dcd9..397310f 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -209,9 +209,11 @@
 			continue;
 		device = platform_device_register_simple(SND_CS4231_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -220,14 +222,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_cs4231_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_cs4231_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_cs4231_exit(void)
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 382bb17..f7fa779 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -780,9 +780,11 @@
 			continue;
 		device = platform_device_register_simple(CS423X_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		snd_cs423x_devices++;
@@ -802,14 +804,10 @@
 #ifdef MODULE
 		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_cs423x_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_cs423x_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_cs423x_exit(void)
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 2b69fc8..e90689e 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -213,9 +213,11 @@
 			continue;
 		device = platform_device_register_simple(ES1688_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -224,14 +226,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_es1688_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_es1688_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_es1688_exit(void)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 9fbc185..a36ec1d 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -2391,9 +2391,11 @@
 			continue;
 		device = platform_device_register_simple(ES18XX_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+	       		continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		cards++;
@@ -2411,14 +2413,10 @@
 #ifdef MODULE
 		snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_es18xx_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_es18xx_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_es18xx_exit(void)
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 26dccfe..37057a3 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -253,9 +253,11 @@
 			continue;
 		device = platform_device_register_simple(GUSCLASSIC_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -264,14 +266,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_gusclassic_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_gusclassic_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_gusclassic_exit(void)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 31dc205..05852fc 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -363,9 +363,11 @@
 			continue;
 		device = platform_device_register_simple(GUSEXTREME_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -374,14 +376,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_gusextreme_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_gusextreme_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_gusextreme_exit(void)
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index cafb9b6..fcf2c8f 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -390,9 +390,11 @@
 			continue;
 		device = platform_device_register_simple(GUSMAX_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -401,14 +403,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_gusmax_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_gusmax_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_gusmax_exit(void)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index de71b7a..4298d33 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -947,9 +947,11 @@
 #endif
 		device = platform_device_register_simple(INTERWAVE_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		cards++;
@@ -966,14 +968,10 @@
 #ifdef MODULE
 		printk(KERN_ERR "InterWave soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_interwave_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_interwave_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_interwave_exit(void)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index c906e20..6d88905 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -962,9 +962,11 @@
 #endif
 		device = platform_device_register_simple(OPL3SA2_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		snd_opl3sa2_devices++;
@@ -983,14 +985,10 @@
 #ifdef MODULE
 		snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_opl3sa2_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_opl3sa2_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_opl3sa2_exit(void)
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
index 28c6407..0e41bfd 100644
--- a/sound/isa/opti9xx/Makefile
+++ b/sound/isa/opti9xx/Makefile
@@ -6,8 +6,10 @@
 snd-opti92x-ad1848-objs := opti92x-ad1848.o
 snd-opti92x-cs4231-objs := opti92x-cs4231.o
 snd-opti93x-objs := opti93x.o
+snd-miro-objs := miro.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o
 obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o
 obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o
+obj-$(CONFIG_SND_MIRO) += snd-miro.o
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
new file mode 100644
index 0000000..83d64bc
--- /dev/null
+++ b/sound/isa/opti9xx/miro.c
@@ -0,0 +1,1458 @@
+/*
+ *   ALSA soundcard driver for Miro miroSOUND PCM1 pro
+ *                                  miroSOUND PCM12
+ *                                  miroSOUND PCM20 Radio
+ *
+ *   Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de>
+ *
+ *   Based on OSS ACI and ALSA OPTi9xx drivers
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/cs4231.h>
+#include <sound/mpu401.h>
+#include <sound/opl4.h>
+#include <sound/control.h>
+#include <sound/info.h>
+#define SNDRV_LEGACY_FIND_FREE_IRQ
+#define SNDRV_LEGACY_FIND_FREE_DMA
+#include <sound/initval.h>
+#include "miro.h"
+
+MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio");
+MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, "
+			"{Miro,miroSOUND PCM12}, "
+			"{Miro,miroSOUND PCM20 Radio}}");
+
+static int index = SNDRV_DEFAULT_IDX1;		/* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;		/* ID for this card */
+static long port = SNDRV_DEFAULT_PORT1; 	/* 0x530,0xe80,0xf40,0x604 */
+static long mpu_port = SNDRV_DEFAULT_PORT1;	/* 0x300,0x310,0x320,0x330 */
+static long fm_port = SNDRV_DEFAULT_PORT1;	/* 0x388 */
+static int irq = SNDRV_DEFAULT_IRQ1;		/* 5,7,9,10,11 */
+static int mpu_irq = SNDRV_DEFAULT_IRQ1;	/* 5,7,9,10 */
+static int dma1 = SNDRV_DEFAULT_DMA1;		/* 0,1,3 */
+static int dma2 = SNDRV_DEFAULT_DMA1;		/* 0,1,3 */
+static int wss;
+static int ide;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for miro soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for miro soundcard.");
+module_param(port, long, 0444);
+MODULE_PARM_DESC(port, "WSS port # for miro driver.");
+module_param(mpu_port, long, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver.");
+module_param(fm_port, long, 0444);
+MODULE_PARM_DESC(fm_port, "FM Port # for miro driver.");
+module_param(irq, int, 0444);
+MODULE_PARM_DESC(irq, "WSS irq # for miro driver.");
+module_param(mpu_irq, int, 0444);
+MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver.");
+module_param(dma1, int, 0444);
+MODULE_PARM_DESC(dma1, "1st dma # for miro driver.");
+module_param(dma2, int, 0444);
+MODULE_PARM_DESC(dma2, "2nd dma # for miro driver.");
+module_param(wss, int, 0444);
+MODULE_PARM_DESC(wss, "wss mode");
+module_param(ide, int, 0444);
+MODULE_PARM_DESC(ide, "enable ide port");
+
+#define OPTi9XX_HW_DETECT	0
+#define OPTi9XX_HW_82C928	1
+#define OPTi9XX_HW_82C929	2
+#define OPTi9XX_HW_82C924	3
+#define OPTi9XX_HW_82C925	4
+#define OPTi9XX_HW_82C930	5
+#define OPTi9XX_HW_82C931	6
+#define OPTi9XX_HW_82C933	7
+#define OPTi9XX_HW_LAST		OPTi9XX_HW_82C933
+
+#define OPTi9XX_MC_REG(n)	n
+
+
+struct snd_miro {
+	unsigned short hardware;
+	unsigned char password;
+	char name[7];
+
+	struct resource *res_mc_base;
+	struct resource *res_aci_port;
+
+	unsigned long mc_base;
+	unsigned long mc_base_size;
+	unsigned long pwd_reg;
+
+	spinlock_t lock;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+
+	long wss_base;
+	int irq;
+	int dma1;
+	int dma2;
+
+	long fm_port;
+
+	long mpu_port;
+	int mpu_irq;
+
+	unsigned long aci_port;
+	int aci_vendor;
+	int aci_product;
+	int aci_version;
+	int aci_amp;
+	int aci_preamp;
+	int aci_solomode;
+
+	struct mutex aci_mutex;
+};
+
+static void snd_miro_proc_init(struct snd_miro * miro);
+
+#define DRIVER_NAME "snd-miro"
+
+static struct platform_device *device;
+
+static char * snd_opti9xx_names[] = {
+	"unkown",
+	"82C928", "82C929",
+	"82C924", "82C925",
+	"82C930", "82C931", "82C933"
+};
+
+/* 
+ *  ACI control
+ */
+
+static int aci_busy_wait(struct snd_miro * miro)
+{
+	long timeout;
+	unsigned char byte;
+
+	for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) {
+		if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) {
+			if (timeout >= ACI_MINTIME)
+				snd_printd("aci ready in round %ld.\n",
+					   timeout-ACI_MINTIME);
+			return byte;
+		}
+		if (timeout >= ACI_MINTIME) {
+			long out=10*HZ;
+			switch (timeout-ACI_MINTIME) {
+			case 0 ... 9:
+				out /= 10;
+			case 10 ... 19:
+				out /= 10;
+			case 20 ... 30:
+				out /= 10;
+			default:
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(out);
+				break;
+			}
+		}
+	}
+	snd_printk(KERN_ERR "aci_busy_wait() time out\n");
+	return -EBUSY;
+}
+
+static inline int aci_write(struct snd_miro * miro, unsigned char byte)
+{
+	if (aci_busy_wait(miro) >= 0) {
+		outb(byte, miro->aci_port + ACI_REG_COMMAND);
+		return 0;
+	} else {
+		snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
+		return -EBUSY;
+	}
+}
+
+static inline int aci_read(struct snd_miro * miro)
+{
+	unsigned char byte;
+
+	if (aci_busy_wait(miro) >= 0) {
+		byte=inb(miro->aci_port + ACI_REG_STATUS);
+		return byte;
+	} else {
+		snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
+		return -EBUSY;
+	}
+}
+
+static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3)
+{
+	int write[] = {write1, write2, write3};
+	int value, i;
+
+	if (mutex_lock_interruptible(&miro->aci_mutex))
+		return -EINTR;
+
+	for (i=0; i<3; i++) {
+		if (write[i]< 0 || write[i] > 255)
+			break;
+		else {
+			value = aci_write(miro, write[i]);
+			if (value < 0)
+				goto out;
+		}
+	}
+
+	value = aci_read(miro);
+
+out:	mutex_unlock(&miro->aci_mutex);
+	return value;
+}
+
+static int aci_getvalue(struct snd_miro * miro, unsigned char index)
+{
+	return aci_cmd(miro, ACI_STATUS, index, -1);
+}
+
+static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value)
+{
+	return aci_cmd(miro, index, value, -1);
+}
+
+/*
+ *  MIXER part
+ */
+
+static int snd_miro_info_capture(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+
+	return 0;
+}
+
+static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int value;
+
+	if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) {
+		snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value);
+		return value;
+	}
+
+	ucontrol->value.integer.value[0] = value & 0x20;
+
+	return 0;
+}
+
+static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int change, value, error;
+
+	value = !(ucontrol->value.integer.value[0]);
+
+	if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) {
+		snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error);
+		return error;
+	}
+
+	change = (value != miro->aci_solomode);
+	miro->aci_solomode = value;
+	
+	return change;
+}
+
+static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 3;
+
+	return 0;
+}
+
+static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int value;
+
+	if (miro->aci_version <= 176) {
+
+		/* 
+		   OSS says it's not readable with versions < 176.
+		   But it doesn't work on my card,
+		   which is a PCM12 with aci_version = 176.
+		*/
+
+		ucontrol->value.integer.value[0] = miro->aci_preamp;
+		return 0;
+	}
+
+	if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) {
+		snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value);
+		return value;
+	}
+	
+	ucontrol->value.integer.value[0] = value;
+
+	return 0;
+}
+
+static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int error, value, change;
+
+	value = ucontrol->value.integer.value[0];
+
+	if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) {
+		snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error);
+		return error;
+	}
+
+	change = (value != miro->aci_preamp);
+	miro->aci_preamp = value;
+
+	return change;
+}
+
+static int snd_miro_info_amp(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+
+	return 0;
+}
+
+static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = miro->aci_amp;
+
+	return 0;
+}
+
+static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int error, value, change;
+
+	value = ucontrol->value.integer.value[0];
+
+	if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) {
+		snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
+		return error;
+	}
+
+	change = (value != miro->aci_amp);
+	miro->aci_amp = value;
+
+	return change;
+}
+
+#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = ctl_name, \
+  .index = ctl_index, \
+  .info = snd_miro_info_double, \
+  .get = snd_miro_get_double, \
+  .put = snd_miro_put_double, \
+  .private_value = get_right_reg | (set_right_reg << 8) \
+}
+
+static int snd_miro_info_double(struct snd_kcontrol *kcontrol, 
+				struct snd_ctl_elem_info *uinfo)
+{
+	int reg = kcontrol->private_value & 0xff;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+
+	if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) {
+
+		/* equalizer elements */
+
+		uinfo->value.integer.min = - 0x7f;
+		uinfo->value.integer.max = 0x7f;
+	} else {
+
+		/* non-equalizer elements */
+
+		uinfo->value.integer.min = 0;
+		uinfo->value.integer.max = 0x20;
+	}
+
+	return 0;
+}
+
+static int snd_miro_get_double(struct snd_kcontrol *kcontrol, 
+			       struct snd_ctl_elem_value *uinfo)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int left_val, right_val;
+
+	int right_reg = kcontrol->private_value & 0xff;
+	int left_reg = right_reg + 1;
+
+	if ((right_val = aci_getvalue(miro, right_reg)) < 0) {
+		snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
+		return right_val;
+	}
+
+	if ((left_val = aci_getvalue(miro, left_reg)) < 0) {
+		snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
+		return left_val;
+	}
+
+	if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) {
+
+		/* equalizer elements */
+
+		if (left_val < 0x80) {
+			uinfo->value.integer.value[0] = left_val;
+		} else {
+			uinfo->value.integer.value[0] = 0x80 - left_val;
+		}
+
+		if (right_val < 0x80) {
+			uinfo->value.integer.value[1] = right_val;
+		} else {
+			uinfo->value.integer.value[1] = 0x80 - right_val;
+		}
+
+	} else {
+
+		/* non-equalizer elements */
+
+		uinfo->value.integer.value[0] = 0x20 - left_val;
+		uinfo->value.integer.value[1] = 0x20 - right_val;
+	}
+
+	return 0;
+}
+
+static int snd_miro_put_double(struct snd_kcontrol *kcontrol, 
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
+	int left, right, left_old, right_old;
+	int setreg_left, setreg_right, getreg_left, getreg_right;
+	int change, error;
+
+	left = ucontrol->value.integer.value[0];
+	right = ucontrol->value.integer.value[1];
+
+	setreg_right = (kcontrol->private_value >> 8) & 0xff;
+	if (setreg_right == ACI_SET_MASTER) {
+		setreg_left = setreg_right + 1;
+	} else {
+		setreg_left = setreg_right + 8;
+	}
+
+	getreg_right = kcontrol->private_value & 0xff;
+	getreg_left = getreg_right + 1;
+
+	if ((left_old = aci_getvalue(miro, getreg_left)) < 0) {
+		snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
+		return left_old;
+	}
+
+	if ((right_old = aci_getvalue(miro, getreg_right)) < 0) {
+		snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
+		return right_old;
+	}
+
+	if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) {
+
+		/* equalizer elements */
+
+		if (left_old > 0x80) 
+			left_old = 0x80 - left_old;
+		if (right_old > 0x80) 
+			right_old = 0x80 - right_old;
+
+		if (left >= 0) {
+			if ((error = aci_setvalue(miro, setreg_left, left)) < 0) {
+				snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+					   left, error);
+				return error;
+			}
+		} else {
+			if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) {
+				snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+					   0x80 - left, error);
+				return error;
+			}
+		}
+
+		if (right >= 0) {
+			if ((error = aci_setvalue(miro, setreg_right, right)) < 0) {
+				snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+					   right, error);
+				return error;
+			}
+		} else {
+			if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) {
+				snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+					   0x80 - right, error);
+				return error;
+			}
+		}
+
+	} else {
+
+		/* non-equalizer elements */
+
+		left_old = 0x20 - left_old;
+		right_old = 0x20 - right_old;
+
+		if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) {
+			snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+				   0x20 - left, error);
+			return error;
+		}
+		if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) {
+			snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
+				   0x20 - right, error);
+			return error;
+		}
+	}
+
+	change = (left != left_old) || (right != right_old);
+
+	return change;
+}
+
+static struct snd_kcontrol_new snd_miro_controls[] = {
+MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
+MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
+MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
+MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD),
+MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH),
+MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM),
+MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
+};
+
+/* Equalizer with seven bands (only PCM20) 
+   from -12dB up to +12dB on each band */
+static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
+MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
+MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
+MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4),
+MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5),
+MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
+MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
+};
+
+static struct snd_kcontrol_new snd_miro_radio_control[] = {
+MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_line_control[] = {
+MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
+};
+
+static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+{
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Mic Boost",
+	.index = 1,
+	.info = snd_miro_info_preamp,
+	.get = snd_miro_get_preamp,
+	.put = snd_miro_put_preamp,
+}};
+
+static struct snd_kcontrol_new snd_miro_amp_control[] = {
+{
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Line Boost",
+	.index = 0,
+	.info = snd_miro_info_amp,
+	.get = snd_miro_get_amp,
+	.put = snd_miro_put_amp,
+}};
+
+static struct snd_kcontrol_new snd_miro_capture_control[] = {
+{
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "PCM Capture Switch",
+	.index = 0,
+	.info = snd_miro_info_capture,
+	.get = snd_miro_get_capture,
+	.put = snd_miro_put_capture,
+}};
+
+static unsigned char aci_init_values[][2] __initdata = {
+	{ ACI_SET_MUTE, 0x00 },
+	{ ACI_SET_POWERAMP, 0x00 },
+	{ ACI_SET_PREAMP, 0x00 },
+	{ ACI_SET_SOLOMODE, 0x00 },
+	{ ACI_SET_MIC + 0, 0x20 },
+	{ ACI_SET_MIC + 8, 0x20 },
+	{ ACI_SET_LINE + 0, 0x20 },
+	{ ACI_SET_LINE + 8, 0x20 },
+	{ ACI_SET_CD + 0, 0x20 },
+	{ ACI_SET_CD + 8, 0x20 },
+	{ ACI_SET_PCM + 0, 0x20 },
+	{ ACI_SET_PCM + 8, 0x20 },
+	{ ACI_SET_LINE1 + 0, 0x20 },
+	{ ACI_SET_LINE1 + 8, 0x20 },
+	{ ACI_SET_LINE2 + 0, 0x20 },
+	{ ACI_SET_LINE2 + 8, 0x20 },
+	{ ACI_SET_SYNTH + 0, 0x20 },
+	{ ACI_SET_SYNTH + 8, 0x20 },
+	{ ACI_SET_MASTER + 0, 0x20 },
+	{ ACI_SET_MASTER + 1, 0x20 },
+};
+
+static int __init snd_set_aci_init_values(struct snd_miro *miro)
+{
+	int idx, error;
+
+	/* enable WSS on PCM1 */
+
+	if ((miro->aci_product == 'A') && wss) {
+		if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) {
+			snd_printk(KERN_ERR "enabling WSS mode failed\n");
+			return error;
+		}
+	}
+
+	/* enable IDE port */
+
+	if (ide) {
+		if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) {
+			snd_printk(KERN_ERR "enabling IDE port failed\n");
+			return error;
+		}
+	}
+
+	/* set common aci values */
+
+	for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++)
+                if ((error = aci_setvalue(miro, aci_init_values[idx][0], 
+					  aci_init_values[idx][1])) < 0) {
+			snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", 
+				   aci_init_values[idx][0], error);
+                        return error;
+                }
+
+	miro->aci_amp = 0;
+	miro->aci_preamp = 0;
+	miro->aci_solomode = 1;
+
+	return 0;
+}
+
+static int snd_miro_mixer(struct snd_miro *miro)
+{
+	struct snd_card *card;
+	unsigned int idx;
+	int err;
+
+	snd_assert(miro != NULL && miro->card != NULL, return -EINVAL);
+
+	card = miro->card;
+
+	switch (miro->hardware) {
+	case OPTi9XX_HW_82C924:
+		strcpy(card->mixername, "ACI & OPTi924");
+		break;
+	case OPTi9XX_HW_82C929:
+		strcpy(card->mixername, "ACI & OPTi929");
+		break;
+	default:
+		snd_BUG();
+		break;
+	}
+
+	for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) {
+		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0)
+			return err;
+	}
+
+	if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) {
+		/* PCM1/PCM12 with power-amp and Line 2 */
+		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
+			return err;
+		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0)
+			return err;
+	}
+
+	if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) {
+		/* PCM12/PCM20 with mic-preamp */
+		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
+			return err;
+		if (miro->aci_version >= 176)
+			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
+				return err;
+	}
+
+	if (miro->aci_product == 'C') {
+		/* PCM20 with radio and 7 band equalizer */
+		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
+			return err;
+		for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) {
+			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static long snd_legacy_find_free_ioport(long *port_table, long size)
+{
+	while (*port_table != -1) {
+		struct resource *res;
+		if ((res = request_region(*port_table, size, 
+					  "ALSA test")) != NULL) {
+			release_and_free_resource(res);
+			return *port_table;
+		}
+		port_table++;
+	}
+	return -1;
+}
+
+static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
+{
+	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+
+	chip->hardware = hardware;
+	strcpy(chip->name, snd_opti9xx_names[hardware]);
+
+	chip->mc_base_size = opti9xx_mc_size[hardware];  
+
+	spin_lock_init(&chip->lock);
+
+	chip->wss_base = -1;
+	chip->irq = -1;
+	chip->dma1 = -1;
+	chip->dma2 = -1;
+	chip->fm_port = -1;
+	chip->mpu_port = -1;
+	chip->mpu_irq = -1;
+
+	switch (hardware) {
+	case OPTi9XX_HW_82C929:
+		chip->mc_base = 0xf8c;
+		chip->password = 0xe3;
+		chip->pwd_reg = 3;
+		break;
+
+	case OPTi9XX_HW_82C924:
+		chip->mc_base = 0xf8c;
+		chip->password = 0xe5;
+		chip->pwd_reg = 3;
+		break;
+
+	default:
+		snd_printk(KERN_ERR "sorry, no support for %d\n", hardware);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static unsigned char snd_miro_read(struct snd_miro *chip,
+				   unsigned char reg)
+{
+	unsigned long flags;
+	unsigned char retval = 0xff;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+	switch (chip->hardware) {
+	case OPTi9XX_HW_82C924:
+		if (reg > 7) {
+			outb(reg, chip->mc_base + 8);
+			outb(chip->password, chip->mc_base + chip->pwd_reg);
+			retval = inb(chip->mc_base + 9);
+			break;
+		}
+
+	case OPTi9XX_HW_82C929:
+		retval = inb(chip->mc_base + reg);
+		break;
+
+	default:
+		snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+	}
+
+	spin_unlock_irqrestore(&chip->lock, flags);
+	return retval;
+}
+
+static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
+			   unsigned char value)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	outb(chip->password, chip->mc_base + chip->pwd_reg);
+
+	switch (chip->hardware) {
+	case OPTi9XX_HW_82C924:
+		if (reg > 7) {
+			outb(reg, chip->mc_base + 8);
+			outb(chip->password, chip->mc_base + chip->pwd_reg);
+			outb(value, chip->mc_base + 9);
+			break;
+		}
+
+	case OPTi9XX_HW_82C929:
+		outb(value, chip->mc_base + reg);
+		break;
+
+	default:
+		snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
+	}
+
+	spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+
+#define snd_miro_write_mask(chip, reg, value, mask)	\
+	snd_miro_write(chip, reg,			\
+		(snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
+
+/*
+ *  Proc Interface
+ */
+
+static void snd_miro_proc_read(struct snd_info_entry * entry, 
+			       struct snd_info_buffer *buffer)
+{
+	struct snd_miro *miro = (struct snd_miro *) entry->private_data;
+	char* model = "unknown";
+
+	/* miroSOUND PCM1 pro, early PCM12 */
+
+	if ((miro->hardware == OPTi9XX_HW_82C929) &&
+	    (miro->aci_vendor == 'm') && 
+	    (miro->aci_product == 'A')) {
+		switch(miro->aci_version) {
+		case 3:
+			model = "miroSOUND PCM1 pro";
+			break;
+		default:
+			model = "miroSOUND PCM1 pro / (early) PCM12";
+			break;
+		}
+	}
+
+	/* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
+
+	if ((miro->hardware == OPTi9XX_HW_82C924) &&
+	    (miro->aci_vendor == 'm') && 
+	    (miro->aci_product == 'B')) {
+		switch(miro->aci_version) {
+		case 4:
+			model = "miroSOUND PCM12";
+			break;
+		case 176:
+			model = "miroSOUND PCM12 (Rev. E)";
+			break;
+		default:
+			model = "miroSOUND PCM12 / PCM12 pnp";
+			break;
+		}
+	}
+
+	/* miroSOUND PCM20 radio */
+
+	if ((miro->hardware == OPTi9XX_HW_82C924) &&
+	    (miro->aci_vendor == 'm') && 
+	    (miro->aci_product == 'C')) {
+		switch(miro->aci_version) {
+		case 7:
+			model = "miroSOUND PCM20 radio (Rev. E)";
+			break;
+		default:
+			model = "miroSOUND PCM20 radio";
+			break;
+		}
+	}
+
+	snd_iprintf(buffer, "\nGeneral information:\n");
+	snd_iprintf(buffer, "  model   : %s\n", model);
+	snd_iprintf(buffer, "  opti    : %s\n", miro->name);
+	snd_iprintf(buffer, "  codec   : %s\n", miro->pcm->name);
+	snd_iprintf(buffer, "  port    : 0x%lx\n", miro->wss_base);
+	snd_iprintf(buffer, "  irq     : %d\n", miro->irq);
+	snd_iprintf(buffer, "  dma     : %d,%d\n\n", miro->dma1, miro->dma2);
+
+	snd_iprintf(buffer, "MPU-401:\n");
+	snd_iprintf(buffer, "  port    : 0x%lx\n", miro->mpu_port);
+	snd_iprintf(buffer, "  irq     : %d\n\n", miro->mpu_irq);
+
+	snd_iprintf(buffer, "ACI information:\n");
+	snd_iprintf(buffer, "  vendor  : ");
+	switch(miro->aci_vendor) {
+	case 'm':
+		snd_iprintf(buffer, "Miro\n");
+		break;
+	default:
+		snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor);
+		break;
+	}
+
+	snd_iprintf(buffer, "  product : ");
+	switch(miro->aci_product) {
+	case 'A':
+		snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
+		break;
+	case 'B':
+		snd_iprintf(buffer, "miroSOUND PCM12\n");
+		break;
+	case 'C':
+		snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
+		break;
+	default:
+		snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product);
+		break;
+	}
+
+	snd_iprintf(buffer, "  firmware: %d (0x%x)\n",
+		    miro->aci_version, miro->aci_version);
+	snd_iprintf(buffer, "  port    : 0x%lx-0x%lx\n", 
+		    miro->aci_port, miro->aci_port+2);
+	snd_iprintf(buffer, "  wss     : 0x%x\n", wss);
+	snd_iprintf(buffer, "  ide     : 0x%x\n", ide);
+	snd_iprintf(buffer, "  solomode: 0x%x\n", miro->aci_solomode);
+	snd_iprintf(buffer, "  amp     : 0x%x\n", miro->aci_amp);
+	snd_iprintf(buffer, "  preamp  : 0x%x\n", miro->aci_preamp);
+}
+
+static void __init snd_miro_proc_init(struct snd_miro * miro)
+{
+	struct snd_info_entry *entry;
+
+	if (! snd_card_proc_new(miro->card, "miro", &entry))
+		snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
+}
+
+/*
+ *  Init
+ */
+
+static int __init snd_miro_configure(struct snd_miro *chip)
+{
+	unsigned char wss_base_bits;
+	unsigned char irq_bits;
+	unsigned char dma_bits;
+	unsigned char mpu_port_bits = 0;
+	unsigned char mpu_irq_bits;
+	unsigned long flags;
+
+	switch (chip->hardware) {
+	case OPTi9XX_HW_82C924:
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+		break;
+	case OPTi9XX_HW_82C929:
+		/* untested init commands for OPTi929 */
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
+		break;
+	default:
+		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
+		return -EINVAL;
+	}
+
+	switch (chip->wss_base) {
+	case 0x530:
+		wss_base_bits = 0x00;
+		break;
+	case 0x604:
+		wss_base_bits = 0x03;
+		break;
+	case 0xe80:
+		wss_base_bits = 0x01;
+		break;
+	case 0xf40:
+		wss_base_bits = 0x02;
+		break;
+	default:
+		snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base);
+		goto __skip_base;
+	}
+	snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
+
+__skip_base:
+	switch (chip->irq) {
+	case 5:
+		irq_bits = 0x05;
+		break;
+	case 7:
+		irq_bits = 0x01;
+		break;
+	case 9:
+		irq_bits = 0x02;
+		break;
+	case 10:
+		irq_bits = 0x03;
+		break;
+	case 11:
+		irq_bits = 0x04;
+		break;
+	default:
+		snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq);
+		goto __skip_resources;
+	}
+
+	switch (chip->dma1) {
+	case 0:
+		dma_bits = 0x01;
+		break;
+	case 1:
+		dma_bits = 0x02;
+		break;
+	case 3:
+		dma_bits = 0x03;
+		break;
+	default:
+		snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1);
+		goto __skip_resources;
+	}
+
+	if (chip->dma1 == chip->dma2) {
+		snd_printk(KERN_ERR "don't want to share dmas\n");
+		return -EBUSY;
+	}
+
+	switch (chip->dma2) {
+	case 0:
+	case 1:
+		break;
+	default:
+		snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2);
+		goto __skip_resources;
+	}
+	dma_bits |= 0x04;
+
+	spin_lock_irqsave(&chip->lock, flags);
+	outb(irq_bits << 3 | dma_bits, chip->wss_base);
+	spin_unlock_irqrestore(&chip->lock, flags);
+
+__skip_resources:
+	if (chip->hardware > OPTi9XX_HW_82C928) {
+		switch (chip->mpu_port) {
+		case 0:
+		case -1:
+			break;
+		case 0x300:
+			mpu_port_bits = 0x03;
+			break;
+		case 0x310:
+			mpu_port_bits = 0x02;
+			break;
+		case 0x320:
+			mpu_port_bits = 0x01;
+			break;
+		case 0x330:
+			mpu_port_bits = 0x00;
+			break;
+		default:
+			snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n",
+				   chip->mpu_port);
+			goto __skip_mpu;
+		}
+
+		switch (chip->mpu_irq) {
+		case 5:
+			mpu_irq_bits = 0x02;
+			break;
+		case 7:
+			mpu_irq_bits = 0x03;
+			break;
+		case 9:
+			mpu_irq_bits = 0x00;
+			break;
+		case 10:
+			mpu_irq_bits = 0x01;
+			break;
+		default:
+			snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n",
+				   chip->mpu_irq);
+			goto __skip_mpu;
+		}
+
+		snd_miro_write_mask(chip, OPTi9XX_MC_REG(6),
+			(chip->mpu_port <= 0) ? 0x00 :
+				0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
+			0xf8);
+	}
+__skip_mpu:
+
+	return 0;
+}
+
+static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
+{
+	int i, err;
+	unsigned char value;
+
+	for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
+
+		if ((err = snd_miro_init(chip, i)) < 0)
+			return err;
+
+		if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
+			continue;
+
+		value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
+		if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
+			if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
+				return 1;
+
+		release_and_free_resource(chip->res_mc_base);
+		chip->res_mc_base = NULL;
+
+	}
+
+	return -ENODEV;
+}
+
+static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
+{
+	unsigned char regval;
+	int i;
+
+	mutex_init(&miro->aci_mutex);
+
+	/* get ACI port from OPTi9xx MC 4 */
+
+	miro->mc_base = 0xf8c;
+	regval=inb(miro->mc_base + 4);
+	miro->aci_port = (regval & 0x10) ? 0x344: 0x354;
+
+	if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) {
+		snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", 
+			   miro->aci_port, miro->aci_port+2);
+		return -ENOMEM;
+	}
+
+        /* force ACI into a known state */
+	for (i = 0; i < 3; i++)
+		if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "can't force aci into known state.\n");
+			return -ENXIO;
+		}
+
+	if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
+	    (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
+		snd_card_free(card);
+		snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
+		return -ENXIO;
+	}
+
+	if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
+		snd_card_free(card);
+		snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", 
+			   miro->aci_port);
+		return -ENXIO;
+	}
+
+	if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 ||
+	    aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
+	    aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
+		snd_printk(KERN_ERR "can't initialize aci.\n"); 
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static void snd_card_miro_free(struct snd_card *card)
+{
+	struct snd_miro *miro = card->private_data;
+        
+	release_and_free_resource(miro->res_aci_port);
+	release_and_free_resource(miro->res_mc_base);
+}
+
+static int __init snd_miro_probe(struct platform_device *devptr)
+{
+	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+	static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
+	static int possible_irqs[] = {11, 9, 10, 7, -1};
+	static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
+	static int possible_dma1s[] = {3, 1, 0, -1};
+	static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
+
+	int error;
+	struct snd_miro *miro;
+	struct snd_cs4231 *codec;
+	struct snd_timer *timer;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct snd_rawmidi *rmidi;
+
+	if (!(card = snd_card_new(index, id, THIS_MODULE,
+				  sizeof(struct snd_miro))))
+		return -ENOMEM;
+
+	card->private_free = snd_card_miro_free;
+	miro = card->private_data;
+	miro->card = card;
+
+	if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
+		snd_card_free(card);
+		snd_printk(KERN_ERR "unable to detect aci chip\n");
+		return -ENODEV;
+	}
+
+	/* init proc interface */
+	snd_miro_proc_init(miro);
+
+	if ((error = snd_card_miro_detect(card, miro)) < 0) {
+		snd_card_free(card);
+		snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
+		return -ENODEV;
+	}
+
+	if (! miro->res_mc_base &&
+	    (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
+						"miro (OPTi9xx MC)")) == NULL) {
+		snd_card_free(card);
+		snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
+		return -ENOMEM;
+	}
+
+	miro->wss_base = port;
+	miro->fm_port = fm_port;
+	miro->mpu_port = mpu_port;
+	miro->irq = irq;
+	miro->mpu_irq = mpu_irq;
+	miro->dma1 = dma1;
+	miro->dma2 = dma2;
+
+	if (miro->wss_base == SNDRV_AUTO_PORT) {
+		if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free WSS port\n");
+			return -EBUSY;
+		}
+	}
+
+	if (miro->mpu_port == SNDRV_AUTO_PORT) {
+		if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
+			return -EBUSY;
+		}
+	}
+	if (miro->irq == SNDRV_AUTO_IRQ) {
+		if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free IRQ\n");
+			return -EBUSY;
+		}
+	}
+	if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
+		if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
+			return -EBUSY;
+		}
+	}
+	if (miro->dma1 == SNDRV_AUTO_DMA) {
+		if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free DMA1\n");
+			return -EBUSY;
+		}
+	}
+	if (miro->dma2 == SNDRV_AUTO_DMA) {
+		if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
+			snd_card_free(card);
+			snd_printk(KERN_ERR "unable to find a free DMA2\n");
+			return -EBUSY;
+		}
+	}
+
+	if ((error = snd_miro_configure(miro))) {
+		snd_card_free(card);
+		return error;
+	}
+
+	if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
+				       miro->irq, miro->dma1, miro->dma2,
+				       CS4231_HW_AD1845,
+				       0,
+				       &codec)) < 0) {
+		snd_card_free(card);
+		return error;
+	}
+
+	if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
+		snd_card_free(card);
+		return error;
+	}
+	if ((error = snd_cs4231_mixer(codec)) < 0) {
+		snd_card_free(card);
+		return error;
+	}
+	if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
+		snd_card_free(card);
+		return error;
+	}
+
+	miro->pcm = pcm;
+
+	if ((error = snd_miro_mixer(miro)) < 0) {
+		snd_card_free(card);
+		return error;
+	}
+
+	if (miro->aci_vendor == 'm') {
+		/* It looks like a miro sound card. */
+		switch (miro->aci_product) {
+		case 'A':
+			sprintf(card->shortname, 
+				"miroSOUND PCM1 pro / PCM12");
+			break;
+		case 'B':
+			sprintf(card->shortname, 
+				"miroSOUND PCM12");
+			break;
+		case 'C':
+			sprintf(card->shortname, 
+				"miroSOUND PCM20 radio");
+			break;
+		default:
+			sprintf(card->shortname, 
+				"unknown miro");
+			snd_printk(KERN_INFO "unknown miro aci id\n");
+			break;
+		}
+	} else {
+		snd_printk(KERN_INFO "found unsupported aci card\n");
+		sprintf(card->shortname, "unknown Cardinal Technologies");
+	}
+
+	strcpy(card->driver, "miro");
+	sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
+		card->shortname, miro->name, pcm->name, miro->wss_base + 4,
+		miro->irq, miro->dma1, miro->dma2);
+
+	if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT)
+		rmidi = NULL;
+	else
+		if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+				miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT,
+				&rmidi)))
+			snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port);
+
+	if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) {
+		struct snd_opl3 *opl3 = NULL;
+		struct snd_opl4 *opl4;
+		if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8, 
+				    2, &opl3, &opl4) < 0)
+			snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port);
+	}
+
+	if ((error = snd_set_aci_init_values(miro)) < 0) {
+		snd_card_free(card);
+                return error;
+	}
+
+	snd_card_set_dev(card, &devptr->dev);
+
+	if ((error = snd_card_register(card))) {
+		snd_card_free(card);
+		return error;
+	}
+
+	platform_set_drvdata(devptr, card);
+	return 0;
+}
+
+static int __devexit snd_miro_remove(struct platform_device *devptr)
+{
+	snd_card_free(platform_get_drvdata(devptr));
+	platform_set_drvdata(devptr, NULL);
+	return 0;
+}
+
+static struct platform_driver snd_miro_driver = {
+	.probe		= snd_miro_probe,
+	.remove		= __devexit_p(snd_miro_remove),
+	/* FIXME: suspend/resume */
+	.driver		= {
+		.name	= DRIVER_NAME
+	},
+};
+
+static int __init alsa_card_miro_init(void)
+{
+	int error;
+
+	if ((error = platform_driver_register(&snd_miro_driver)) < 0)
+		return error;
+	device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+	if (! IS_ERR(device)) {
+		if (platform_get_drvdata(device))
+			return 0;
+		platform_device_unregister(device);
+	}
+#ifdef MODULE
+	printk(KERN_ERR "no miro soundcard found\n");
+#endif
+	platform_driver_unregister(&snd_miro_driver);
+	return PTR_ERR(device);
+}
+
+static void __exit alsa_card_miro_exit(void)
+{
+	platform_device_unregister(device);
+	platform_driver_unregister(&snd_miro_driver);
+}
+
+module_init(alsa_card_miro_init)
+module_exit(alsa_card_miro_exit)
diff --git a/sound/isa/opti9xx/miro.h b/sound/isa/opti9xx/miro.h
new file mode 100644
index 0000000..6e1385b
--- /dev/null
+++ b/sound/isa/opti9xx/miro.h
@@ -0,0 +1,73 @@
+#ifndef _MIRO_H_
+#define _MIRO_H_
+
+#define ACI_REG_COMMAND		0	/* write register offset */
+#define ACI_REG_STATUS		1	/* read register offset */
+#define ACI_REG_BUSY		2	/* busy register offset */
+#define ACI_REG_RDS		2	/* PCM20: RDS register offset */
+#define ACI_MINTIME		500	/* ACI time out limit */
+
+#define ACI_SET_MUTE		0x0d
+#define ACI_SET_POWERAMP	0x0f
+#define ACI_SET_TUNERMUTE	0xa3
+#define ACI_SET_TUNERMONO	0xa4
+#define ACI_SET_IDE		0xd0
+#define ACI_SET_WSS		0xd1
+#define ACI_SET_SOLOMODE	0xd2
+#define ACI_SET_PREAMP		0x03
+#define ACI_GET_PREAMP		0x21
+#define ACI_WRITE_TUNE		0xa7
+#define ACI_READ_TUNERSTEREO	0xa8
+#define ACI_READ_TUNERSTATION	0xa9
+#define ACI_READ_VERSION	0xf1
+#define ACI_READ_IDCODE		0xf2
+#define ACI_INIT		0xff
+#define ACI_STATUS		0xf0
+#define ACI_S_GENERAL		0x00
+#define ACI_ERROR_OP		0xdf
+
+/* ACI Mixer */
+
+/* These are the values for the right channel GET registers.
+   Add an offset of 0x01 for the left channel register.
+   (left=right+0x01) */
+
+#define ACI_GET_MASTER		0x03
+#define ACI_GET_MIC		0x05
+#define ACI_GET_LINE		0x07
+#define ACI_GET_CD		0x09
+#define ACI_GET_SYNTH		0x0b
+#define ACI_GET_PCM		0x0d
+#define ACI_GET_LINE1		0x10	/* Radio on PCM20 */
+#define ACI_GET_LINE2		0x12
+
+#define ACI_GET_EQ1		0x22	/* from Bass ... */
+#define ACI_GET_EQ2		0x24
+#define ACI_GET_EQ3		0x26
+#define ACI_GET_EQ4		0x28
+#define ACI_GET_EQ5		0x2a
+#define ACI_GET_EQ6		0x2c
+#define ACI_GET_EQ7		0x2e	/* ... to Treble */
+
+/* And these are the values for the right channel SET registers.
+   For left channel access you have to add an offset of 0x08.
+   MASTER is an exception, which needs an offset of 0x01 */
+
+#define ACI_SET_MASTER		0x00
+#define ACI_SET_MIC		0x30
+#define ACI_SET_LINE		0x31
+#define ACI_SET_CD		0x34
+#define ACI_SET_SYNTH		0x33
+#define ACI_SET_PCM		0x32
+#define ACI_SET_LINE1		0x35	/* Radio on PCM20 */
+#define ACI_SET_LINE2		0x36
+
+#define ACI_SET_EQ1		0x40	/* from Bass ... */
+#define ACI_SET_EQ2		0x41
+#define ACI_SET_EQ3		0x42
+#define ACI_SET_EQ4		0x43
+#define ACI_SET_EQ5		0x44
+#define ACI_SET_EQ6		0x45
+#define ACI_SET_EQ7		0x46	/* ... to Treble */
+
+#endif  /* _MIRO_H_ */
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 65b28cb..8ee0d70 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -2099,8 +2099,11 @@
 			return error;
 		device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
 		if (!IS_ERR(device)) {
-			snd_opti9xx_platform_device = device;
-			return 0;
+			if (platform_get_drvdata(device)) {
+				snd_opti9xx_platform_device = device;
+				return 0;
+			}
+			platform_device_unregister(device);
 		}
 		platform_driver_unregister(&snd_opti9xx_driver);
 	}
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 21ea659..6333f90 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -720,9 +720,11 @@
 			continue;
 		device = platform_device_register_simple(SND_SB16_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		cards++;
@@ -745,14 +747,10 @@
 		snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
 #endif
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_sb16_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_sb16_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_sb16_exit(void)
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 3efa23d..141400c 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -264,9 +264,11 @@
 			continue;
 		device = platform_device_register_simple(SND_SB8_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -275,14 +277,10 @@
 #ifdef MODULE
 		snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_sb8_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_sb8_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_sb8_exit(void)
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index a60e66a..09c8e8c 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -366,9 +366,11 @@
 			continue;
 		device = platform_device_register_simple(SND_SGALAXY_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		devices[i] = device;
 		cards++;
@@ -377,14 +379,10 @@
 #ifdef MODULE
 		snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_sgalaxy_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_sgalaxy_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_sgalaxy_exit(void)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 48e5552..d2a856f 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1427,8 +1427,8 @@
 		    dma[i] == SNDRV_AUTO_DMA) {
 			printk(KERN_INFO
 			       "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
-			ret = -ENXIO;
-			goto errout;
+			sscape_unregister_all();
+			return -ENXIO;
 		}
 
 		/*
@@ -1436,17 +1436,15 @@
 		 */
 		device = platform_device_register_simple(SSCAPE_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			ret = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 	}
 	return 0;
-
- errout:
-	sscape_unregister_all();
-	return ret;
 }
 
 static void sscape_exit(void)
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 2f13cd5..7ae86f8 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -722,9 +722,11 @@
 #endif
 		device = platform_device_register_simple(WAVEFRONT_DRIVER,
 							 i, NULL, 0);
-		if (IS_ERR(device)) {
-			err = PTR_ERR(device);
-			goto errout;
+		if (IS_ERR(device))
+			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
 		}
 		platform_devices[i] = device;
 		cards++;
@@ -742,14 +744,10 @@
 #ifdef MODULE
 		printk (KERN_ERR "No WaveFront cards found or devices busy\n");
 #endif
-		err = -ENODEV;
-		goto errout;
+		snd_wavefront_unregister_all();
+		return -ENODEV;
 	}
 	return 0;
-
- errout:
-	snd_wavefront_unregister_all();
-	return err;
 }
 
 static void __exit alsa_card_wavefront_exit(void)
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 88e52dc..558c6ed 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,23 +5,9 @@
 #
 # Prompt user for primary drivers.
 
-config OBSOLETE_OSS_DRIVER
-	bool "Obsolete OSS drivers"
-	depends on SOUND_PRIME
-	help
-	  This option enables support for obsolete OSS drivers that
-	  are scheduled for removal in the near future since there
-	  are ALSA drivers for the same hardware.
-
-	  Please contact Adrian Bunk <bunk@stusta.de> if you had to
-	  say Y here because your soundcard is not properly supported
-	  by ALSA.
-
-	  If unsure, say N.
-
 config SOUND_BT878
 	tristate "BT878 audio dma"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	---help---
 	  Audio DMA support for bt878 based grabber boards.  As you might have
 	  already noticed, bt878 is listed with two functions in /proc/pci.
@@ -35,48 +21,9 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called btaudio.
 
-config SOUND_CMPCI
-	tristate "C-Media PCI (CMI8338/8738)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card using the CMI8338
-	  or the CMI8738 chipset.  Data on these chips are available at
-	  <http://www.cmedia.com.tw/>.
-
-	  A userspace utility to control some internal registers of these
-	  chips is available at
-	  <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
-
-config SOUND_CMPCI_FM
-	bool "Enable legacy FM"
-	depends on SOUND_CMPCI && X86
-	help
-	  Say Y here to enable the legacy FM (frequency-modulation) synthesizer
-	  support on a card using the CMI8338 or CMI8378 chipset. Even it is
-	  enabled, you need to set fmio as proper value to enable it.
-	  Say N here if you don't need this.
-
-config SOUND_CMPCI_MIDI
-	bool "Enable legacy MPU-401"
-	depends on SOUND_CMPCI && X86
-	help
-	  Say Y here to enable the legacy MPU401 MIDI synthesizer support on a
-	  card using the CMI8338 or CMI8378 chipset. Even it is enabled,
-	  you need to set mpuio as proper value to enable it.
-	  Say N here if you don't need this.
-
-config SOUND_CMPCI_JOYSTICK
-	bool "Enable joystick"
-	depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
-	help
-	  Say Y here in order to enable the joystick port on a sound card using
-	  the CMI8338 or the CMI8738 chipset.  You need to config the
-	  gameport support and set joystick parameter as 1 to use it.
-	  Say N here if you don't need this.
-
 config SOUND_EMU10K1
 	tristate "Creative SBLive! (EMU10K1)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	---help---
 	  Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
 	  such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -108,13 +55,6 @@
 	  series) when wired as native sound drivers with AC97 codecs.  If
 	  this driver does not work try the CS4232 driver.
 
-config SOUND_CS4281
-	tristate "Crystal Sound CS4281"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Picture and feature list at
-	  <http://www.pcbroker.com/crystal4281.html>.
-
 config SOUND_BCM_CS4297A
 	tristate "Crystal Sound CS4297a (for Swarm)"
 	depends on SOUND_PRIME && SIBYTE_SWARM
@@ -125,22 +65,9 @@
 	  note that CONFIG_KGDB should not be enabled at the same
 	  time, since it also attempts to use this UART port.
 
-config SOUND_ES1370
-	tristate "Ensoniq AudioPCI (ES1370)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
-	  ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
-	  out if your sound card uses an ES1370 without removing your
-	  computer's cover, use lspci -n and look for the PCI ID
-	  1274:5000. Since Ensoniq was bought by Creative Labs,
-	  Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
-	  This driver differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/es1370>.
-
 config SOUND_ES1371
 	tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
 	  ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -151,33 +78,6 @@
 	  slightly from OSS/Free, so PLEASE READ
 	  <file:Documentation/sound/oss/es1371>.
 
-config SOUND_ESSSOLO1
-	tristate "ESS Technology Solo1" 
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the ESS Technology
-	  Solo1 chip. To find out if your sound card uses a
-	  Solo1 chip without removing your computer's cover, use
-	  lspci -n and look for the PCI ID 125D:1969. This driver
-	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/solo1>.
-
-config SOUND_MAESTRO
-	tristate "ESS Maestro, Maestro2, Maestro2E driver"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a sound system driven by ESS's Maestro line
-	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
-	  Maestro 2E.  See <file:Documentation/sound/oss/Maestro> for more
-	  details.
-
-config SOUND_MAESTRO3
-	tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
-	depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a sound system driven by ESS's Maestro 3
-	  PCI sound chip.
-
 config SOUND_ICH
 	tristate "Intel ICH (i8xx) audio support"
 	depends on SOUND_PRIME && PCI
@@ -185,24 +85,6 @@
 	  Support for integral audio in Intel's I/O Controller Hub (ICH)
 	  chipset, as used on the 810/820/840 motherboards.
 
-config SOUND_HARMONY
-	tristate "PA Harmony audio driver"
-	depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
-	help
-	  Say 'Y' or 'M' to include support for Harmony soundchip
-	  on HP 712, 715/new and many other GSC based machines.
-
-config SOUND_SONICVIBES
-	tristate "S3 SonicVibes"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a PCI sound card utilizing the S3
-	  SonicVibes chipset. To find out if your sound card uses a
-	  SonicVibes chip without removing your computer's cover, use
-	  lspci -n and look for the PCI ID 5333:CA00. This driver
-	  differs slightly from OSS/Free, so PLEASE READ
-	  <file:Documentation/sound/oss/sonicvibes>.
-
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
 	depends on SOUND_PRIME && X86_VISWS
@@ -231,10 +113,6 @@
 	  integrated, multi-function controller chip for MIPS CPUs.  Works
 	  with the AC97 codec.
 
-config SOUND_AU1000
-	tristate "Au1000 Sound"
-	depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
-
 config SOUND_AU1550_AC97
 	tristate "Au1550 AC97 Sound"
 	depends on SOUND_PRIME && SOC_AU1550
@@ -507,7 +385,7 @@
 
 config SOUND_VIA82CXXX
 	tristate "VIA 82C686 Audio Codec"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y here to include support for the audio codec found on VIA
 	  82Cxxx-based chips. Typically these are built into a motherboard.
@@ -576,18 +454,6 @@
 	  Say M here if you have a sound card based on the Analog Devices
 	  AD1889 chip.
 
-config SOUND_SGALAXY
-	tristate "Aztech Sound Galaxy (non-PnP) cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  This module initializes the older non Plug and Play sound galaxy
-	  cards from Aztech. It supports the Waverider Pro 32 - 3D and the
-	  Galaxy Washington 16.
-
-	  If you compile the driver into the kernel, you have to add
-	  "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
-	  line.
-
 config SOUND_ADLIB
 	tristate "Adlib Cards"
 	depends on SOUND_OSS
@@ -614,7 +480,7 @@
 
 config SOUND_CS4232
 	tristate "Crystal CS4232 based (PnP) cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+	depends on SOUND_OSS
 	help
 	  Say Y here if you have a card based on the Crystal CS4232 chip set,
 	  which uses its own Plug and Play protocol.
@@ -626,42 +492,6 @@
 	  See <file:Documentation/sound/oss/CS4232> for more information on
 	  configuring this card.
 
-config SOUND_SSCAPE
-	tristate "Ensoniq SoundScape support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Answer Y if you have a sound card based on the Ensoniq SoundScape
-	  chipset. Such cards are being manufactured at least by Ensoniq, Spea
-	  and Reveal (Reveal makes also other cards).
-
-	  If you compile the driver into the kernel, you have to add
-	  "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
-	  line.
-
-config SOUND_GUS
-	tristate "Gravis Ultrasound support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here for any type of Gravis Ultrasound card, including the GUS
-	  or GUS MAX.  See also <file:Documentation/sound/oss/ultrasound> for more
-	  information on configuring this card with modules.
-
-	  If you compile the driver into the kernel, you have to add
-	  "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_GUS16
-	bool "16 bit sampling option of GUS (_NOT_ GUS MAX)"
-	depends on SOUND_GUS
-	help
-	  Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
-	  sampling at 16-bit width.
-
-config SOUND_GUSMAX
-	bool "GUS MAX support"
-	depends on SOUND_GUS
-	help
-	  Support for Gravis Ulstrasound MAX.
-
 config SOUND_VMIDI
 	tristate "Loopback MIDI device support"
 	depends on SOUND_OSS
@@ -742,7 +572,7 @@
 
 config SOUND_NM256
 	tristate "NM256AV/NM256ZX audio support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+	depends on SOUND_OSS
 	help
 	  Say M here to include audio support for the NeoMagic 256AV/256ZX
 	  chipsets. These are the audio chipsets found in the Sony
@@ -752,35 +582,6 @@
 
 	  See <file:Documentation/sound/oss/NM256> for further information.
 
-config SOUND_MAD16
-	tristate "OPTi MAD16 and/or Mozart based cards"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	---help---
-	  Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
-	  82C928 or 82C929 or 82C931) audio interface chip. These chips are
-	  quite common so it's possible that many no-name cards have one of
-	  them. In addition the MAD16 chip is used in some cards made by known
-	  manufacturers such as Turtle Beach (Tropez), Reveal (some models)
-	  and Diamond (latest ones). Note however that the Tropez sound cards
-	  have their own driver; if you have one of those, say N here and Y or
-	  M to "Full support for Turtle Beach WaveFront", below.
-
-	  If you compile the driver into the kernel, you have to add
-	  "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
-	  kernel command line.
-
-	  See also <file:Documentation/sound/oss/Opti> and
-	  <file:Documentation/sound/oss/MAD16> for more information on setting
-	  these cards up as modules.
-
-config MAD16_OLDCARD
-	bool "Support MIDI in older MAD16 based cards (requires SB)"
-	depends on SOUND_MAD16
-	help
-	  Answer Y (or M) if you have an older card based on the C928 or
-	  Mozart chipset and you want to have MIDI support. If you enable this
-	  option you also need to enable support for Sound Blaster.
-
 config SOUND_PAS
 	tristate "ProAudioSpectrum 16 support"
 	depends on SOUND_OSS
@@ -873,53 +674,9 @@
 	  You can say M here to compile this driver as a module; the module is
 	  called sb.
 
-config SOUND_AWE32_SYNTH
-	tristate "AWE32 synth"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
-	  similar sound card. See <file:Documentation/sound/oss/README.awe>,
-	  <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
-	  mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-	  for more info.
-
-config SOUND_WAVEFRONT
-	tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
-	depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
-	help
-	  Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
-	  and read the files <file:Documentation/sound/oss/Wavefront> and
-	  <file:Documentation/sound/oss/Tropez+>.
-
-config SOUND_MAUI
-	tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
-	  sound card.
-
-	  If you compile the driver into the kernel, you have to add
-	  "maui=<io>,<irq>" to the kernel command line.
-
-config MAUI_HAVE_BOOT
-	bool "Have OSWF.MOT firmware file"
-	depends on SOUND_MAUI=y && !STANDALONE
-	help
-	  Turtle Beach Maui and Tropez sound cards have a microcontroller
-	  which needs to be initialized prior to use. OSWF.MOT is a file
-	  distributed with the card's DOS/Windows drivers. Answer Y if you
-	  have this file.
-
-config MAUI_BOOT_FILE
-	string "Full pathname of OSWF.MOT firmware file"
-	depends on MAUI_HAVE_BOOT
-	default "/etc/sound/oswf.mot"
-	help
-	  Enter the full pathname of your OSWF.MOT file, starting from /.
-
 config SOUND_YM3812
 	tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+	depends on SOUND_OSS
 	---help---
 	  Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
 	  Answering Y is usually a safe and recommended choice, however some
@@ -933,18 +690,6 @@
 
 	  If unsure, say Y.
 
-config SOUND_OPL3SA1
-	tristate "Yamaha OPL3-SA1 audio controller"
-	depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
-	  usually built into motherboards. Read
-	  <file:Documentation/sound/oss/OPL3-SA> for details.
-
-	  If you compile the driver into the kernel, you have to add
-	  "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-	  command line.
-
 config SOUND_OPL3SA2
 	tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
 	depends on SOUND_OSS
@@ -959,19 +704,6 @@
 	  "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
 	  command line.
 
-config SOUND_YMFPCI
-	tristate "Yamaha YMF7xx PCI audio (native mode)"
-	depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Support for Yamaha cards including the YMF711, YMF715, YMF718,
-	  YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
-
-config SOUND_YMFPCI_LEGACY
-	bool "Yamaha PCI legacy ports support"
-	depends on SOUND_YMFPCI
-	help
-	  Support for YMF7xx PCI cards emulating an MP401.
-
 config SOUND_UART6850
 	tristate "6850 UART support"
 	depends on SOUND_OSS
@@ -1101,30 +833,6 @@
 	tristate "XpressAudio Sound Blaster emulation"
 	depends on SOUND_SB
 
-config SOUND_ALI5455
-	tristate "ALi5455 audio support"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-
-config SOUND_FORTE
-	tristate "ForteMedia FM801 driver"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you want driver support for the ForteMedia FM801 PCI
-	  audio controller (Abit AU10, Genius Sound Maker, HP Workstation
-	  zx2000, and others).
-
-config SOUND_RME96XX
-	tristate "RME Hammerfall (RME96XX) support"
-	depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-	help
-	  Say Y or M if you have a Hammerfall or Hammerfall light
-	  multichannel card from RME. If you want to access advanced
-	  features of the card, read <file:Documentation/sound/oss/rme96xx>.
-
-config SOUND_AD1980
-	tristate "AD1980 front/back switch plugin"
-	depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
-
 config SOUND_SH_DAC_AUDIO
 	tristate "SuperH DAC audio support"
 	depends on SOUND_PRIME && CPU_SH3
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 54dabf8..a4ca756 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -75,7 +75,7 @@
 
 	DBG("Setting WAV rate to %d\n", rate);
 	dev->state[AD_WAV_STATE].dmabuf.rate = rate;
-	AD1889_WRITEW(dev, AD_DSWAS, rate);
+	AD1889_WRITEW(dev, AD_DS_WAS, rate);
 
 	/* Cycle the DAC to enable the new rate */
 	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
@@ -89,14 +89,14 @@
 
 	DBG("Setting WAV format to 0x%x\n", fmt);
 
-	tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
 	if (fmt & AFMT_S16_LE) {
 		//tmp |= 0x0100; /* set WA16 */
 		tmp |= 0x0300; /* set WA16 stereo */
 	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
-	AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
+	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
 }
 
 static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
@@ -105,13 +105,13 @@
 
 	DBG("Setting ADC format to 0x%x\n", fmt);
 
-	tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
 	if (fmt & AFMT_S16_LE) {
 		tmp |= 0x0100; /* set WA16 */
 	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
-	AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
 }
 
 static void ad1889_start_wav(ad1889_state_t *state)
@@ -145,21 +145,21 @@
 	    dmabuf->rd_ptr, dmabuf->dma_len);
 
         /* load up the current register set */
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
 
 	/* TODO: for now we load the base registers with the same thing */
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt);
-	AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
 
 	/* and we're off to the races... */
-	AD1889_WRITEL(ad1889_dev, AD_DMACHSS, 0x8);
-	tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+	AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
+	tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
 	tmp |= 0x0400; /* set WAEN */
-	AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
-	(void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+	AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+	(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
 
 	dmabuf->enable |= DAC_RUNNING;
 
@@ -179,10 +179,10 @@
 		u16 tmp;
 		unsigned long cnt = dmabuf->dma_len;
 
-		tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+		tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
 		tmp &= ~0x0400; /* clear WAEN */
-		AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
-		(void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+		AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+		(void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
 		pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle, 
 				cnt, PCI_DMA_TODEVICE);
 
@@ -211,7 +211,7 @@
 
 	spin_lock_irqsave(&state->card->lock, flags);
 	
-	tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+	tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
 	if (start) {
 		state->dmabuf.enable |= ADC_RUNNING;
 		tmp |= 0x0004; /* set ADEN */
@@ -219,7 +219,7 @@
 		state->dmabuf.enable &= ~ADC_RUNNING;
 		tmp &= ~0x0004; /* clear ADEN */
 	}
-	AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+	AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
 
 	spin_unlock_irqrestore(&state->card->lock, flags);
 }
@@ -301,53 +301,53 @@
 	int len, i;
 	ad1889_dev_t *dev = data;
 	ad1889_reg_t regs[] = {
-		{ "WSMC", AD_DSWSMC, 16 },
-		{ "RAMC", AD_DSRAMC, 16 },
-		{ "WADA", AD_DSWADA, 16 },
-		{ "SYDA", AD_DSSYDA, 16 },
-		{ "WAS", AD_DSWAS, 16 },
-		{ "RES", AD_DSRES, 16 },
-		{ "CCS", AD_DSCCS, 16 },
-		{ "ADCBA", AD_DMAADCBA, 32 },
-		{ "ADCCA", AD_DMAADCCA, 32 },
-		{ "ADCBC", AD_DMAADCBC, 32 },
-		{ "ADCCC", AD_DMAADCCC, 32 },
-		{ "ADCIBC", AD_DMAADCIBC, 32 },
-		{ "ADCICC", AD_DMAADCICC, 32 },
-		{ "ADCCTRL", AD_DMAADCCTRL, 16 },
-		{ "WAVBA", AD_DMAWAVBA, 32 },
-		{ "WAVCA", AD_DMAWAVCA, 32 },
-		{ "WAVBC", AD_DMAWAVBC, 32 },
-		{ "WAVCC", AD_DMAWAVCC, 32 },
-		{ "WAVIBC", AD_DMAWAVIBC, 32 },
-		{ "WAVICC", AD_DMAWAVICC, 32 },
-		{ "WAVCTRL", AD_DMAWAVCTRL, 16 },
-		{ "DISR", AD_DMADISR, 32 },
-		{ "CHSS", AD_DMACHSS, 32 },
-		{ "IPC", AD_GPIOIPC, 16 },
-		{ "OP", AD_GPIOOP, 16 },
-		{ "IP", AD_GPIOIP, 16 },
-		{ "ACIC", AD_ACIC, 16 },
-		{ "AC97_RESET", 0x100 + AC97_RESET, 16 },
-		{ "AC97_MASTER_VOL_STEREO", 0x100 + AC97_MASTER_VOL_STEREO, 16 },
-		{ "AC97_HEADPHONE_VOL", 0x100 + AC97_HEADPHONE_VOL, 16 },
-		{ "AC97_MASTER_VOL_MONO", 0x100 + AC97_MASTER_VOL_MONO, 16 },
-		{ "AC97_MASTER_TONE", 0x100 + AC97_MASTER_TONE, 16 },
-		{ "AC97_PCBEEP_VOL", 0x100 + AC97_PCBEEP_VOL, 16 },
-		{ "AC97_PHONE_VOL", 0x100 + AC97_PHONE_VOL, 16 },
-		{ "AC97_MIC_VOL", 0x100 + AC97_MIC_VOL, 16 },
-		{ "AC97_LINEIN_VOL", 0x100 + AC97_LINEIN_VOL, 16 },
-		{ "AC97_CD_VOL", 0x100 + AC97_CD_VOL, 16 },
-		{ "AC97_VIDEO_VOL", 0x100 + AC97_VIDEO_VOL, 16 },
-		{ "AC97_AUX_VOL", 0x100 + AC97_AUX_VOL, 16 },
-		{ "AC97_PCMOUT_VOL", 0x100 + AC97_PCMOUT_VOL, 16 },
-		{ "AC97_RECORD_SELECT", 0x100 + AC97_RECORD_SELECT, 16 },
-		{ "AC97_RECORD_GAIN", 0x100 + AC97_RECORD_GAIN, 16 },
-		{ "AC97_RECORD_GAIN_MIC", 0x100 + AC97_RECORD_GAIN_MIC, 16 },
-		{ "AC97_GENERAL_PURPOSE", 0x100 + AC97_GENERAL_PURPOSE, 16 },
-		{ "AC97_3D_CONTROL", 0x100 + AC97_3D_CONTROL, 16 },
-		{ "AC97_MODEM_RATE", 0x100 + AC97_MODEM_RATE, 16 },
-		{ "AC97_POWER_CONTROL", 0x100 + AC97_POWER_CONTROL, 16 },
+		{ "WSMC", AD_DS_WSMC, 16 },
+		{ "RAMC", AD_DS_RAMC, 16 },
+		{ "WADA", AD_DS_WADA, 16 },
+		{ "SYDA", AD_DS_SYDA, 16 },
+		{ "WAS", AD_DS_WAS, 16 },
+		{ "RES", AD_DS_RES, 16 },
+		{ "CCS", AD_DS_CCS, 16 },
+		{ "ADCBA", AD_DMA_ADCBA, 32 },
+		{ "ADCCA", AD_DMA_ADCCA, 32 },
+		{ "ADCBC", AD_DMA_ADCBC, 32 },
+		{ "ADCCC", AD_DMA_ADCCC, 32 },
+		{ "ADCIBC", AD_DMA_ADCIBC, 32 },
+		{ "ADCICC", AD_DMA_ADCICC, 32 },
+		{ "ADCCTRL", AD_DMA_ADCCTRL, 16 },
+		{ "WAVBA", AD_DMA_WAVBA, 32 },
+		{ "WAVCA", AD_DMA_WAVCA, 32 },
+		{ "WAVBC", AD_DMA_WAVBC, 32 },
+		{ "WAVCC", AD_DMA_WAVCC, 32 },
+		{ "WAVIBC", AD_DMA_WAVIBC, 32 },
+		{ "WAVICC", AD_DMA_WAVICC, 32 },
+		{ "WAVCTRL", AD_DMA_WAVCTRL, 16 },
+		{ "DISR", AD_DMA_DISR, 32 },
+		{ "CHSS", AD_DMA_CHSS, 32 },
+		{ "IPC", AD_GPIO_IPC, 16 },
+		{ "OP", AD_GPIO_OP, 16 },
+		{ "IP", AD_GPIO_IP, 16 },
+		{ "ACIC", AD_AC97_ACIC, 16 },
+		{ "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
+		{ "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
+		{ "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
+		{ "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
+		{ "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
+		{ "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
+		{ "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
+		{ "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
+		{ "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
+		{ "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
+		{ "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
+		{ "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
+		{ "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
+		{ "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
+		{ "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
+		{ "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
+		{ "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
+		{ "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
+		{ "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
+		{ "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
 		{ NULL }
 	};
 
@@ -400,9 +400,9 @@
 	}
 	
 	if (dmabuf->enable & DAC_RUNNING)
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
+		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
 	else
-		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));
+		offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
 
 	return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
 }
@@ -639,9 +639,9 @@
 		if (val > 5400 && val < 48000)
 		{
 			if (file->f_mode & FMODE_WRITE)
-				AD1889_WRITEW(ad1889_dev, AD_DSWAS, val);
+				AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
 			if (file->f_mode & FMODE_READ)
-				AD1889_WRITEW(ad1889_dev, AD_DSRES, val);
+				AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
 		}
 		return 0;
 
@@ -649,22 +649,22 @@
 		if (get_user(val, p))
 			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
-			val = AD1889_READW(ad1889_dev, AD_DSWSMC);
+			val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
 			if (val) {
 				val |= 0x0200;  /* set WAST */
 			} else {
 				val &= ~0x0200; /* clear WAST */
 			}
-			AD1889_WRITEW(ad1889_dev, AD_DSWSMC, val);
+			AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
 		}
 		if (file->f_mode & FMODE_WRITE) {
-			val = AD1889_READW(ad1889_dev, AD_DSRAMC);
+			val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
 			if (val) {
 				val |= 0x0002;  /* set ADST */
 			} else {
 				val &= ~0x0002; /* clear ADST */
 			}
-			AD1889_WRITEW(ad1889_dev, AD_DSRAMC, val);
+			AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
 		}
 
 		return 0;
@@ -739,7 +739,7 @@
 		break;
 
 	case SOUND_PCM_READ_RATE:
-		return put_user(AD1889_READW(ad1889_dev, AD_DSWAS), p);
+		return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
 
 	case SOUND_PCM_READ_CHANNELS:
 	case SOUND_PCM_READ_BITS:
@@ -769,7 +769,7 @@
 
 	ad1889_set_wav_rate(ad1889_dev, 48000);
 	ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
-	AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
+	AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
 	return nonseekable_open(inode, file);
 }
 
@@ -826,15 +826,15 @@
 {
 	ad1889_dev_t *dev = ac97->private_data;
 
-	//DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + 0x100 + reg);
-	AD1889_WRITEW(dev, 0x100 + reg, val);
+	//DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
+	AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
 }
 
 static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
 {
 	ad1889_dev_t *dev = ac97->private_data;
-	//DBG("Reading from 0x%lx\n", dev->regbase + 0x100 + reg);
-	return AD1889_READW(dev, 0x100 + reg);
+	//DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
+	return AD1889_READW(dev, AD_AC97_BASE + reg);
 }	
 
 static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
@@ -883,24 +883,24 @@
 	int retry = 200;
 	ad1889_dev_t *dev = pci_get_drvdata(pcidev);
 
-	AD1889_WRITEW(dev, AD_DSCCS, 0x8000); /* turn on clock */
-	AD1889_READW(dev, AD_DSCCS); 
+	AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
+	AD1889_READW(dev, AD_DS_CCS);
 
 	WAIT_10MS();
 
-	stat = AD1889_READW(dev, AD_ACIC);
+	stat = AD1889_READW(dev, AD_AC97_ACIC);
 	stat |= 0x0002;				/* Reset Disable */
-	AD1889_WRITEW(dev, AD_ACIC, stat);
-	(void) AD1889_READW(dev, AD_ACIC);	/* flush posted write */
+	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
+	(void) AD1889_READW(dev, AD_AC97_ACIC);	/* flush posted write */
 
 	udelay(10);
 
-	stat = AD1889_READW(dev, AD_ACIC);
+	stat = AD1889_READW(dev, AD_AC97_ACIC);
 	stat |= 0x0001;				/* Interface Enable */
-	AD1889_WRITEW(dev, AD_ACIC, stat);
+	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
 
 	do {
-		if (AD1889_READW(dev, AD_ACIC) & 0x8000)	/* Ready */
+		if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000)	/* Ready */
 			break;
 		WAIT_10MS();
 		retry--;
@@ -908,16 +908,16 @@
 
 	if (!retry) {
 		printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
-			    AD1889_READW(dev, AD_ACIC));
+			    AD1889_READW(dev, AD_AC97_ACIC));
 		return -EBUSY;
 	}
 
 	/* TODO reset AC97 codec */
 	/* TODO set wave/adc pci ctrl status */
 
-	stat = AD1889_READW(dev, AD_ACIC);
+	stat = AD1889_READW(dev, AD_AC97_ACIC);
 	stat |= 0x0004;				/* Audio Stream Output Enable */
-	AD1889_WRITEW(dev, AD_ACIC, stat);
+	AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
 	return 0;
 }
 
@@ -935,10 +935,10 @@
 	u32 stat;
 	ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
 
-	stat = AD1889_READL(dev, AD_DMADISR);
+	stat = AD1889_READL(dev, AD_DMA_DISR);
 
 	/* clear ISR */
-	AD1889_WRITEL(dev, AD_DMADISR, stat);
+	AD1889_WRITEL(dev, AD_DMA_DISR, stat);
 
 	if (stat & 0x8) {		/* WAVI */
 		DBG("WAV interrupt\n");
@@ -964,15 +964,15 @@
 	u32 tmp32;
 
 	/* make sure the interrupt bits are setup the way we want */
-	tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+	tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
 	tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
 	tmp32 |= 0x6;  /* intr on count, loop */
-	AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32);
+	AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
 
 	/* unmute... */
-	tmp16 = AD1889_READW(dev, AD_DSWADA);
+	tmp16 = AD1889_READW(dev, AD_DS_WADA);
 	tmp16 &= ~0x8080;
-	AD1889_WRITEW(dev, AD_DSWADA, tmp16);
+	AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
 }
 
 static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
@@ -1005,7 +1005,7 @@
 		goto out1;
 	}
 
-	dev->regbase = ioremap_nocache(bar, AD_DSIOMEMSIZE);
+	dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
 	if (!dev->regbase) {
 		printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
 		goto out2;
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
index 861b321..0991376 100644
--- a/sound/oss/ad1889.h
+++ b/sound/oss/ad1889.h
@@ -1,57 +1,58 @@
 #ifndef _AD1889_H_
 #define _AD1889_H_
 
-#define AD_DSWSMC	0x00	/* DMA input wave/syn mixer control */
-#define AD_DSRAMC	0x02	/* DMA output resamp/ADC mixer control */
-#define AD_DSWADA	0x04	/* DMA input wave attenuation */
-#define AD_DSSYDA	0x06	/* DMA input syn attentuation */
-#define AD_DSWAS	0x08	/* wave input sample rate */
-#define AD_DSRES	0x0a	/* resampler output sample rate */
-#define AD_DSCCS	0x0c	/* chip control/status */
+#define AD_DS_WSMC	0x00	/* DMA input wave/syn mixer control */
+#define AD_DS_RAMC	0x02	/* DMA output resamp/ADC mixer control */
+#define AD_DS_WADA	0x04	/* DMA input wave attenuation */
+#define AD_DS_SYDA	0x06	/* DMA input syn attentuation */
+#define AD_DS_WAS	0x08	/* wave input sample rate */
+#define AD_DS_RES	0x0a	/* resampler output sample rate */
+#define AD_DS_CCS	0x0c	/* chip control/status */
 
-#define AD_DMARESBA	0x40	/* RES base addr */
-#define AD_DMARESCA	0x44	/* RES current addr */
-#define AD_DMARESBC	0x48	/* RES base cnt */
-#define AD_DMARESCC	0x4c	/* RES current count */
-#define AD_DMAADCBA	0x50	/* ADC */
-#define AD_DMAADCCA	0x54
-#define AD_DMAADCBC	0x58
-#define AD_DMAADCCC	0x5c
-#define AD_DMASYNBA	0x60	/* SYN */
-#define AD_DMASYNCA	0x64
-#define AD_DMASYNBC	0x68
-#define AD_DMASYNCC	0x6c
-#define AD_DMAWAVBA	0x70	/* WAV */
-#define AD_DMAWAVCA	0x74
-#define AD_DMAWAVBC	0x78
-#define AD_DMAWAVCC	0x7c
-#define AD_DMARESICC	0x80	/* RES interrupt current count */
-#define AD_DMARESIBC	0x84	/* RES interrupt base count */
-#define AD_DMAADCICC	0x88	/* ADC interrupt current count */
-#define AD_DMAADCIBC	0x8c	/* ADC interrupt base count */
-#define AD_DMASYNICC	0x90	/* SYN interrupt current count */
-#define AD_DMASYNIBC	0x94	/* SYN interrupt base count */
-#define AD_DMAWAVICC	0x98	/* WAV interrupt current count */
-#define AD_DMAWAVIBC	0x9c	/* WAV interrupt base count */
-#define AD_DMARESCTRL	0xa0	/* RES PCI control/status */
-#define AD_DMAADCCTRL	0xa8	/* ADC PCI control/status */
-#define AD_DMASYNCTRL	0xb0	/* SYN PCI control/status */
-#define AD_DMAWAVCTRL	0xb8	/* WAV PCI control/status */
-#define AD_DMADISR	0xc0	/* PCI DMA intr status */
-#define AD_DMACHSS	0xc4	/* PCI DMA channel stop status */
+#define AD_DMA_RESBA	0x40	/* RES base addr */
+#define AD_DMA_RESCA	0x44	/* RES current addr */
+#define AD_DMA_RESBC	0x48	/* RES base cnt */
+#define AD_DMA_RESCC	0x4c	/* RES current count */
+#define AD_DMA_ADCBA	0x50	/* ADC */
+#define AD_DMA_ADCCA	0x54
+#define AD_DMA_ADCBC	0x58
+#define AD_DMA_ADCCC	0x5c
+#define AD_DMA_SYNBA	0x60	/* SYN */
+#define AD_DMA_SYNCA	0x64
+#define AD_DMA_SYNBC	0x68
+#define AD_DMA_SYNCC	0x6c
+#define AD_DMA_WAVBA	0x70	/* WAV */
+#define AD_DMA_WAVCA	0x74
+#define AD_DMA_WAVBC	0x78
+#define AD_DMA_WAVCC	0x7c
+#define AD_DMA_RESICC	0x80	/* RES interrupt current count */
+#define AD_DMA_RESIBC	0x84	/* RES interrupt base count */
+#define AD_DMA_ADCICC	0x88	/* ADC interrupt current count */
+#define AD_DMA_ADCIBC	0x8c	/* ADC interrupt base count */
+#define AD_DMA_SYNICC	0x90	/* SYN interrupt current count */
+#define AD_DMA_SYNIBC	0x94	/* SYN interrupt base count */
+#define AD_DMA_WAVICC	0x98	/* WAV interrupt current count */
+#define AD_DMA_WAVIBC	0x9c	/* WAV interrupt base count */
+#define AD_DMA_RESCTRL	0xa0	/* RES PCI control/status */
+#define AD_DMA_ADCCTRL	0xa8	/* ADC PCI control/status */
+#define AD_DMA_SYNCTRL	0xb0	/* SYN PCI control/status */
+#define AD_DMA_WAVCTRL	0xb8	/* WAV PCI control/status */
+#define AD_DMA_DISR	0xc0	/* PCI DMA intr status */
+#define AD_DMA_CHSS	0xc4	/* PCI DMA channel stop status */
 
-#define AD_GPIOIPC	0xc8	/* IO port ctrl */
-#define AD_GPIOOP	0xca	/* IO output status */
-#define AD_GPIOIP	0xcc	/* IO input status */
+#define AD_GPIO_IPC	0xc8	/* IO port ctrl */
+#define AD_GPIO_OP	0xca	/* IO output status */
+#define AD_GPIO_IP	0xcc	/* IO input status */
 
 /* AC97 registers, 0x100 - 0x17f; see ac97.h */
-#define AD_ACIC		0x180	/* AC Link interface ctrl */
+#define AD_AC97_BASE    0x100   /* ac97 base register */
+#define AD_AC97_ACIC	0x180	/* AC Link interface ctrl */
 
 /* OPL3; BAR1 */
-#define AD_OPLM0AS	0x00	/* Music0 address/status */
-#define AD_OPLM0DATA	0x01	/* Music0 data */
-#define AD_OPLM1A	0x02	/* Music1 address */
-#define AD_OPLM1DATA	0x03	/* Music1 data */
+#define AD_OPL_M0AS	0x00	/* Music0 address/status */
+#define AD_OPL_M0DATA	0x01	/* Music0 data */
+#define AD_OPL_M1A	0x02	/* Music1 address */
+#define AD_OPL_M1DATA	0x03	/* Music1 data */
 /* 0x04-0x0f reserved */
 
 /* MIDI; BAR2 */
@@ -59,9 +60,9 @@
 #define AD_MISC		0x01	/* MIDI status/cmd */
 /* 0x02-0xff reserved */
 
-#define AD_DSIOMEMSIZE	512
-#define AD_OPLMEMSIZE	16
-#define AD_MIDIMEMSIZE	16
+#define AD_DS_IOMEMSIZE	512
+#define AD_OPL_MEMSIZE	16
+#define AD_MIDI_MEMSIZE	16
 
 #define AD_WAV_STATE	0
 #define AD_ADC_STATE	1
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 8131599..882ae98 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -195,8 +195,8 @@
 
 	printk(KERN_INFO "tas driver [%s])\n", driver_name);
 
-#ifndef CONFIG_I2C_KEYWEST
-	request_module("i2c-keywest");
+#ifndef CONFIG_I2C_POWERMAC
+	request_module("i2c-powermac");
 #endif
 	tas_node = find_devices("deq");
 	if (tas_node == NULL)
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 0cd44a6..3721c58 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -94,6 +94,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/dma-mapping.h>
 
 #include "hwaccess.h"
 #include "8010.h"
@@ -119,7 +120,7 @@
  
 
 /* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
-#define EMU10K1_DMA_MASK                0x1fffffff	/* DMA buffer mask for pci_alloc_consist */
+#define EMU10K1_DMA_MASK DMA_29BIT_MASK	/* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
 #define PCI_VENDOR_ID_CREATIVE 0x1102
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1e2e193..a208180 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -15,6 +15,18 @@
 	  To compile this as a module, choose M here: the module
 	  will be called snd-ad1889.
 
+config SND_ALS300
+        tristate "Avance Logic ALS300/ALS300+"
+        depends on SND
+        select SND_PCM
+        select SND_AC97_CODEC
+        select SND_OPL3_LIB
+        help
+          Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
+
+          To compile this driver as a module, choose M here: the module
+          will be called snd-als300
+
 config SND_ALS4000
 	tristate "Avance Logic ALS4000"
 	depends on SND && ISA_DMA_API
@@ -195,8 +207,9 @@
 	  will be called snd-cs46xx.
 
 config SND_CS46XX_NEW_DSP
-	bool "Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)"
-	depends on SND_CS46XX && EXPERIMENTAL
+	bool "Cirrus Logic (Sound Fusion) New DSP support"
+	depends on SND_CS46XX
+        default y
 	help
 	  Say Y here to use a new DSP image for SPDIF and dual codecs.
 
@@ -466,6 +479,19 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-pcxhr.
 
+config SND_RIPTIDE
+	tristate "Conexant Riptide"
+	depends on SND
+	depends on FW_LOADER
+	select SND_OPL3_LIB
+	select SND_MPU401_UART
+	select SND_AC97_CODEC
+	help
+	  Say 'Y' or 'M' to include support for Conexant Riptide chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-riptide
+
 config SND_RME32
 	tristate "RME Digi32, 32/8, 32 PRO"
 	depends on SND
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index a6c3cd5..cba5105 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -4,6 +4,7 @@
 #
 
 snd-ad1889-objs := ad1889.o
+snd-als300-objs := als300.o
 snd-als4000-objs := als4000.o
 snd-atiixp-objs := atiixp.o
 snd-atiixp-modem-objs := atiixp_modem.o
@@ -27,6 +28,7 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AD1889) += snd-ad1889.o
+obj-$(CONFIG_SND_ALS300) += snd-als300.o
 obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
 obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
 obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
@@ -62,6 +64,7 @@
 	mixart/ \
 	nm256/ \
 	pcxhr/ \
+	riptide/ \
 	rme9652/ \
 	trident/ \
 	ymfpci/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 278319b..d052007 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -160,6 +160,7 @@
 { 0x54584e20, 0xffffffff, "TLC320AD9xC",	NULL,		NULL },
 { 0x56494161, 0xffffffff, "VIA1612A",		NULL,		NULL }, // modified ICE1232 with S/PDIF
 { 0x56494170, 0xffffffff, "VIA1617A",		patch_vt1617a,	NULL }, // modified VT1616 with S/PDIF
+{ 0x56494182, 0xffffffff, "VIA1618",		NULL,		NULL },
 { 0x57454301, 0xffffffff, "W83971D",		NULL,		NULL },
 { 0x574d4c00, 0xffffffff, "WM9701A",		NULL,		NULL },
 { 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
new file mode 100644
index 0000000..91899f8
--- /dev/null
+++ b/sound/pci/als300.c
@@ -0,0 +1,867 @@
+/*
+ *  als300.c - driver for Avance Logic ALS300/ALS300+ soundcards.
+ *  Copyright (C) 2005 by Ash Willis <ashwillis@programmer.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *  TODO
+ *  4 channel playback for ALS300+
+ *  gameport
+ *  mpu401
+ *  opl3
+ *
+ *  NOTES
+ *  The BLOCK_COUNTER registers for the ALS300(+) return a figure related to
+ *  the position in the current period, NOT the whole buffer. It is important
+ *  to know which period we are in so we can calculate the correct pointer.
+ *  This is why we always use 2 periods. We can then use a flip-flop variable
+ *  to keep track of what period we are in.
+ */
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/opl3.h>
+
+/* snd_als300_set_irq_flag */
+#define IRQ_DISABLE		0
+#define IRQ_ENABLE		1
+
+/* I/O port layout */
+#define AC97_ACCESS		0x00
+#define AC97_READ		0x04
+#define AC97_STATUS		0x06
+#define   AC97_DATA_AVAIL		(1<<6)
+#define   AC97_BUSY			(1<<7)
+#define ALS300_IRQ_STATUS	0x07		/* ALS300 Only */
+#define   IRQ_PLAYBACK			(1<<3)
+#define   IRQ_CAPTURE			(1<<2)
+#define GCR_DATA		0x08
+#define GCR_INDEX		0x0C
+#define ALS300P_DRAM_IRQ_STATUS	0x0D		/* ALS300+ Only */
+#define MPU_IRQ_STATUS		0x0E		/* ALS300 Rev. E+, ALS300+ */
+#define ALS300P_IRQ_STATUS	0x0F		/* ALS300+ Only */
+
+/* General Control Registers */
+#define PLAYBACK_START		0x80
+#define PLAYBACK_END		0x81
+#define PLAYBACK_CONTROL	0x82
+#define   TRANSFER_START		(1<<16)
+#define   FIFO_PAUSE			(1<<17)
+#define RECORD_START		0x83
+#define RECORD_END		0x84
+#define RECORD_CONTROL		0x85
+#define DRAM_WRITE_CONTROL	0x8B
+#define   WRITE_TRANS_START		(1<<16)
+#define   DRAM_MODE_2			(1<<17)
+#define MISC_CONTROL		0x8C
+#define   IRQ_SET_BIT			(1<<15)
+#define   VMUTE_NORMAL			(1<<20)
+#define   MMUTE_NORMAL			(1<<21)
+#define MUS_VOC_VOL		0x8E
+#define PLAYBACK_BLOCK_COUNTER	0x9A
+#define RECORD_BLOCK_COUNTER	0x9B
+
+#define DEBUG_CALLS	1
+#define DEBUG_PLAY_REC	1
+
+#if DEBUG_CALLS
+#define snd_als300_dbgcalls(format, args...) printk(format, ##args)
+#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __FUNCTION__)
+#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __FUNCTION__)
+#else
+#define snd_als300_dbgcalls(format, args...)
+#define snd_als300_dbgcallenter()
+#define snd_als300_dbgcallleave()
+#endif
+
+#if DEBUG_PLAY_REC
+#define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args)
+#else
+#define snd_als300_dbgplay(format, args...)
+#endif		
+
+enum {DEVICE_ALS300, DEVICE_ALS300_PLUS};
+
+MODULE_AUTHOR("Ash Willis <ashwillis@programmer.net>");
+MODULE_DESCRIPTION("Avance Logic ALS300");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+struct snd_als300 {
+	unsigned long port;
+	spinlock_t reg_lock;
+	struct snd_card *card;
+	struct pci_dev *pci;
+
+	struct snd_pcm *pcm;
+	struct snd_pcm_substream *playback_substream;
+	struct snd_pcm_substream *capture_substream;
+
+	struct snd_ac97 *ac97;
+	struct snd_opl3 *opl3;
+
+	struct resource *res_port;
+
+	int irq;
+
+	int chip_type; /* ALS300 or ALS300+ */
+
+	char revision;	
+};
+
+struct snd_als300_substream_data {
+	int period_flipflop;
+	int control_register;
+	int block_counter_register;
+};
+
+static struct pci_device_id snd_als300_ids[] = {
+	{ 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 },
+	{ 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, snd_als300_ids);
+
+static inline u32 snd_als300_gcr_read(unsigned long port, unsigned short reg)
+{
+	outb(reg, port+GCR_INDEX);
+	return inl(port+GCR_DATA);
+}
+
+static inline void snd_als300_gcr_write(unsigned long port,
+						unsigned short reg, u32 val)
+{
+	outb(reg, port+GCR_INDEX);
+	outl(val, port+GCR_DATA);
+}
+
+/* Enable/Disable Interrupts */
+static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd)
+{
+	u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+	snd_als300_dbgcallenter();
+
+	/* boolean XOR check, since old vs. new hardware have
+	   directly reversed bit setting for ENABLE and DISABLE.
+	   ALS300+ acts like newer versions of ALS300 */
+	if (((chip->revision > 5 || chip->chip_type == DEVICE_ALS300_PLUS) ^
+						(cmd == IRQ_ENABLE)) == 0)
+		tmp |= IRQ_SET_BIT;
+	else
+		tmp &= ~IRQ_SET_BIT;
+	snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp);
+	snd_als300_dbgcallleave();
+}
+
+static int snd_als300_free(struct snd_als300 *chip)
+{
+	snd_als300_dbgcallenter();
+	snd_als300_set_irq_flag(chip, IRQ_DISABLE);
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
+	pci_disable_device(chip->pci);
+	kfree(chip);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_dev_free(struct snd_device *device)
+{
+	struct snd_als300 *chip = device->device_data;
+	return snd_als300_free(chip);
+}
+
+static irqreturn_t snd_als300_interrupt(int irq, void *dev_id,
+						struct pt_regs *regs)
+{
+	u8 status;
+	struct snd_als300 *chip = dev_id;
+	struct snd_als300_substream_data *data;
+
+	status = inb(chip->port+ALS300_IRQ_STATUS);
+	if (!status) /* shared IRQ, for different device?? Exit ASAP! */
+		return IRQ_NONE;
+
+	/* ACK everything ASAP */
+	outb(status, chip->port+ALS300_IRQ_STATUS);
+	if (status & IRQ_PLAYBACK) {
+		if (chip->pcm && chip->playback_substream) {
+			data = chip->playback_substream->runtime->private_data;
+			data->period_flipflop ^= 1;
+			snd_pcm_period_elapsed(chip->playback_substream);
+			snd_als300_dbgplay("IRQ_PLAYBACK\n");
+		}
+	}
+	if (status & IRQ_CAPTURE) {
+		if (chip->pcm && chip->capture_substream) {
+			data = chip->capture_substream->runtime->private_data;
+			data->period_flipflop ^= 1;
+			snd_pcm_period_elapsed(chip->capture_substream);
+			snd_als300_dbgplay("IRQ_CAPTURE\n");
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id,
+						struct pt_regs *regs)
+{
+	u8 general, mpu, dram;
+	struct snd_als300 *chip = dev_id;
+	struct snd_als300_substream_data *data;
+	
+	general = inb(chip->port+ALS300P_IRQ_STATUS);
+	mpu = inb(chip->port+MPU_IRQ_STATUS);
+	dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS);
+
+	/* shared IRQ, for different device?? Exit ASAP! */
+	if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0))
+		return IRQ_NONE;
+
+	if (general & IRQ_PLAYBACK) {
+		if (chip->pcm && chip->playback_substream) {
+			outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS);
+			data = chip->playback_substream->runtime->private_data;
+			data->period_flipflop ^= 1;
+			snd_pcm_period_elapsed(chip->playback_substream);
+			snd_als300_dbgplay("IRQ_PLAYBACK\n");
+		}
+	}
+	if (general & IRQ_CAPTURE) {
+		if (chip->pcm && chip->capture_substream) {
+			outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS);
+			data = chip->capture_substream->runtime->private_data;
+			data->period_flipflop ^= 1;
+			snd_pcm_period_elapsed(chip->capture_substream);
+			snd_als300_dbgplay("IRQ_CAPTURE\n");
+		}
+	}
+	/* FIXME: Ack other interrupt types. Not important right now as
+	 * those other devices aren't enabled. */
+	return IRQ_HANDLED;
+}
+
+static void __devexit snd_als300_remove(struct pci_dev *pci)
+{
+	snd_als300_dbgcallenter();
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+	snd_als300_dbgcallleave();
+}
+
+static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97,
+							unsigned short reg)
+{
+	int i;
+	struct snd_als300 *chip = ac97->private_data;
+
+	for (i = 0; i < 1000; i++) {
+		if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+			break;
+		udelay(10);
+	}
+	outl((reg << 24) | (1 << 31), chip->port+AC97_ACCESS);
+
+	for (i = 0; i < 1000; i++) {
+		if ((inb(chip->port+AC97_STATUS) & (AC97_DATA_AVAIL)) != 0)
+			break;
+		udelay(10);
+	}
+	return inw(chip->port+AC97_READ);
+}
+
+static void snd_als300_ac97_write(struct snd_ac97 *ac97,
+				unsigned short reg, unsigned short val)
+{
+	int i;
+	struct snd_als300 *chip = ac97->private_data;
+
+	for (i = 0; i < 1000; i++) {
+		if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0)
+			break;
+		udelay(10);
+	}
+	outl((reg << 24) | val, chip->port+AC97_ACCESS);
+}
+
+static int snd_als300_ac97(struct snd_als300 *chip)
+{
+	struct snd_ac97_bus *bus;
+	struct snd_ac97_template ac97;
+	int err;
+	static struct snd_ac97_bus_ops ops = {
+		.write = snd_als300_ac97_write,
+		.read = snd_als300_ac97_read,
+	};
+
+	snd_als300_dbgcallenter();
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
+		return err;
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.private_data = chip;
+
+	snd_als300_dbgcallleave();
+	return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+}
+
+/* hardware definition
+ *
+ * In AC97 mode, we always use 48k/16bit/stereo.
+ * Any request to change data type is ignored by
+ * the card when it is running outside of legacy
+ * mode.
+ */
+static struct snd_pcm_hardware snd_als300_playback_hw =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_PAUSE |
+				SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S16,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		2,
+	.channels_max =		2,
+	.buffer_bytes_max =	64 * 1024,
+	.period_bytes_min =	64,
+	.period_bytes_max =	32 * 1024,
+	.periods_min =		2,
+	.periods_max =		2,
+};
+
+static struct snd_pcm_hardware snd_als300_capture_hw =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP |
+				SNDRV_PCM_INFO_INTERLEAVED |
+				SNDRV_PCM_INFO_PAUSE |
+				SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S16,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		2,
+	.channels_max =		2,
+	.buffer_bytes_max =	64 * 1024,
+	.period_bytes_min =	64,
+	.period_bytes_max =	32 * 1024,
+	.periods_min =		2,
+	.periods_max =		2,
+};
+
+static int snd_als300_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+								GFP_KERNEL);
+
+	snd_als300_dbgcallenter();
+	chip->playback_substream = substream;
+	runtime->hw = snd_als300_playback_hw;
+	runtime->private_data = data;
+	data->control_register = PLAYBACK_CONTROL;
+	data->block_counter_register = PLAYBACK_BLOCK_COUNTER;
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_als300_substream_data *data;
+
+	data = substream->runtime->private_data;
+	snd_als300_dbgcallenter();
+	kfree(data);
+	chip->playback_substream = NULL;
+	snd_pcm_lib_free_pages(substream);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
+								GFP_KERNEL);
+
+	snd_als300_dbgcallenter();
+	chip->capture_substream = substream;
+	runtime->hw = snd_als300_capture_hw;
+	runtime->private_data = data;
+	data->control_register = RECORD_CONTROL;
+	data->block_counter_register = RECORD_BLOCK_COUNTER;
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_als300_substream_data *data;
+
+	data = substream->runtime->private_data;
+	snd_als300_dbgcallenter();
+	kfree(data);
+	chip->capture_substream = NULL;
+	snd_pcm_lib_free_pages(substream);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
+					snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+}
+
+static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_als300_playback_prepare(struct snd_pcm_substream *substream)
+{
+	u32 tmp;
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+	unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+	
+	snd_als300_dbgcallenter();
+	spin_lock_irq(&chip->reg_lock);
+	tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+	tmp &= ~TRANSFER_START;
+
+	snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n",
+						period_bytes, buffer_bytes);
+	
+	/* set block size */
+	tmp &= 0xffff0000;
+	tmp |= period_bytes - 1;
+	snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp);
+
+	/* set dma area */
+	snd_als300_gcr_write(chip->port, PLAYBACK_START,
+					runtime->dma_addr);
+	snd_als300_gcr_write(chip->port, PLAYBACK_END,
+					runtime->dma_addr + buffer_bytes - 1);
+	spin_unlock_irq(&chip->reg_lock);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_capture_prepare(struct snd_pcm_substream *substream)
+{
+	u32 tmp;
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned short period_bytes = snd_pcm_lib_period_bytes(substream);
+	unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+
+	snd_als300_dbgcallenter();
+	spin_lock_irq(&chip->reg_lock);
+	tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL);
+	tmp &= ~TRANSFER_START;
+
+	snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes,
+							buffer_bytes);
+
+	/* set block size */
+	tmp &= 0xffff0000;
+	tmp |= period_bytes - 1;
+
+	/* set dma area */
+	snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp);
+	snd_als300_gcr_write(chip->port, RECORD_START,
+					runtime->dma_addr);
+	snd_als300_gcr_write(chip->port, RECORD_END,
+					runtime->dma_addr + buffer_bytes - 1);
+	spin_unlock_irq(&chip->reg_lock);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	u32 tmp;
+	struct snd_als300_substream_data *data;
+	unsigned short reg;
+	int ret = 0;
+
+	data = substream->runtime->private_data;
+	reg = data->control_register;
+
+	snd_als300_dbgcallenter();
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		tmp = snd_als300_gcr_read(chip->port, reg);
+		data->period_flipflop = 1;
+		snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START);
+		snd_als300_dbgplay("TRIGGER START\n");
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		tmp = snd_als300_gcr_read(chip->port, reg);
+		snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START);
+		snd_als300_dbgplay("TRIGGER STOP\n");
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		tmp = snd_als300_gcr_read(chip->port, reg);
+		snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE);
+		snd_als300_dbgplay("TRIGGER PAUSE\n");
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		tmp = snd_als300_gcr_read(chip->port, reg);
+		snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE);
+		snd_als300_dbgplay("TRIGGER RELEASE\n");
+		break;
+	default:
+		snd_als300_dbgplay("TRIGGER INVALID\n");
+		ret = -EINVAL;
+	}
+	spin_unlock(&chip->reg_lock);
+	snd_als300_dbgcallleave();
+	return ret;
+}
+
+static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
+{
+	u16 current_ptr;
+	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
+	struct snd_als300_substream_data *data;
+	unsigned short period_bytes;
+
+	data = substream->runtime->private_data;
+	period_bytes = snd_pcm_lib_period_bytes(substream);
+	
+	snd_als300_dbgcallenter();
+	spin_lock(&chip->reg_lock);
+	current_ptr = (u16) snd_als300_gcr_read(chip->port,
+					data->block_counter_register) + 4;
+	spin_unlock(&chip->reg_lock);
+	if (current_ptr > period_bytes)
+		current_ptr = 0;
+	else
+		current_ptr = period_bytes - current_ptr;
+
+	if (data->period_flipflop == 0)
+		current_ptr += period_bytes;
+	snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr);
+	snd_als300_dbgcallleave();
+	return bytes_to_frames(substream->runtime, current_ptr);
+}
+
+static struct snd_pcm_ops snd_als300_playback_ops = {
+	.open =		snd_als300_playback_open,
+	.close =	snd_als300_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_als300_pcm_hw_params,
+	.hw_free =	snd_als300_pcm_hw_free,
+	.prepare =	snd_als300_playback_prepare,
+	.trigger =	snd_als300_trigger,
+	.pointer =	snd_als300_pointer,
+};
+
+static struct snd_pcm_ops snd_als300_capture_ops = {
+	.open =		snd_als300_capture_open,
+	.close =	snd_als300_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_als300_pcm_hw_params,
+	.hw_free =	snd_als300_pcm_hw_free,
+	.prepare =	snd_als300_capture_prepare,
+	.trigger =	snd_als300_trigger,
+	.pointer =	snd_als300_pointer,
+};
+
+static int __devinit snd_als300_new_pcm(struct snd_als300 *chip)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	snd_als300_dbgcallenter();
+	err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, "ALS300");
+	chip->pcm = pcm;
+
+	/* set operators */
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&snd_als300_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&snd_als300_capture_ops);
+
+	/* pre-allocation of buffers */
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+	snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+static void snd_als300_init(struct snd_als300 *chip)
+{
+	unsigned long flags;
+	u32 tmp;
+	
+	snd_als300_dbgcallenter();
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16)
+								& 0x0000000F;
+	/* Setup DRAM */
+	tmp = snd_als300_gcr_read(chip->port, DRAM_WRITE_CONTROL);
+	snd_als300_gcr_write(chip->port, DRAM_WRITE_CONTROL,
+						(tmp | DRAM_MODE_2)
+						& ~WRITE_TRANS_START);
+
+	/* Enable IRQ output */
+	snd_als300_set_irq_flag(chip, IRQ_ENABLE);
+
+	/* Unmute hardware devices so their outputs get routed to
+	 * the onboard mixer */
+	tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL);
+	snd_als300_gcr_write(chip->port, MISC_CONTROL,
+			tmp | VMUTE_NORMAL | MMUTE_NORMAL);
+
+	/* Reset volumes */
+	snd_als300_gcr_write(chip->port, MUS_VOC_VOL, 0);
+
+	/* Make sure playback transfer is stopped */
+	tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL);
+	snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL,
+			tmp & ~TRANSFER_START);
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	snd_als300_dbgcallleave();
+}
+
+static int __devinit snd_als300_create(snd_card_t *card,
+				       struct pci_dev *pci, int chip_type,
+				       struct snd_als300 **rchip)
+{
+	struct snd_als300 *chip;
+	void *irq_handler;
+	int err;
+
+	static snd_device_ops_t ops = {
+		.dev_free = snd_als300_dev_free,
+	};
+	*rchip = NULL;
+
+	snd_als300_dbgcallenter();
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+
+	if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+		pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
+		printk(KERN_ERR "error setting 28bit DMA mask\n");
+		pci_disable_device(pci);
+		return -ENXIO;
+	}
+	pci_set_master(pci);
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL) {
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+	chip->chip_type = chip_type;
+	spin_lock_init(&chip->reg_lock);
+
+	if ((err = pci_request_regions(pci, "ALS300")) < 0) {
+		kfree(chip);
+		pci_disable_device(pci);
+		return err;
+	}
+	chip->port = pci_resource_start(pci, 0);
+
+	if (chip->chip_type == DEVICE_ALS300_PLUS)
+		irq_handler = snd_als300plus_interrupt;
+	else
+		irq_handler = snd_als300_interrupt;
+
+	if (request_irq(pci->irq, irq_handler, SA_INTERRUPT|SA_SHIRQ,
+					card->shortname, (void *)chip)) {
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		snd_als300_free(chip);
+		return -EBUSY;
+	}
+	chip->irq = pci->irq;
+
+
+	snd_als300_init(chip);
+
+	if (snd_als300_ac97(chip) < 0) {
+		snd_printk(KERN_WARNING "Could not create ac97\n");
+		snd_als300_free(chip);
+		return err;
+	}
+
+	if ((err = snd_als300_new_pcm(chip)) < 0) {
+		snd_printk(KERN_WARNING "Could not create PCM\n");
+		snd_als300_free(chip);
+		return err;
+	}
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+						chip, &ops)) < 0) {
+		snd_als300_free(chip);
+		return err;
+	}
+
+	snd_card_set_dev(card, &pci->dev);
+
+	*rchip = chip;
+	snd_als300_dbgcallleave();
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_als300 *chip = card->private_data;
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	snd_pcm_suspend_all(chip->pcm);
+	snd_ac97_suspend(chip->ac97);
+
+	pci_set_power_state(pci, PCI_D3hot);
+	pci_disable_device(pci);
+	pci_save_state(pci);
+	return 0;
+}
+
+static int snd_als300_resume(struct pci_dev *pci)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_als300 *chip = card->private_data;
+
+	pci_restore_state(pci);
+	pci_enable_device(pci);
+	pci_set_power_state(pci, PCI_D0);
+	pci_set_master(pci);
+
+	snd_als300_init(chip);
+	snd_ac97_resume(chip->ac97);
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+#endif
+
+static int __devinit snd_als300_probe(struct pci_dev *pci,
+                             const struct pci_device_id *pci_id)
+{
+	static int dev;
+	struct snd_card *card;
+	struct snd_als300 *chip;
+	int err, chip_type;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+
+	if (card == NULL)
+		return -ENOMEM;
+
+	chip_type = pci_id->driver_data;
+
+	if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	card->private_data = chip;
+
+	strcpy(card->driver, "ALS300");
+	if (chip->chip_type == DEVICE_ALS300_PLUS)
+		/* don't know much about ALS300+ yet
+		 * print revision number for now */
+		sprintf(card->shortname, "ALS300+ (Rev. %d)", chip->revision);
+	else
+		sprintf(card->shortname, "ALS300 (Rev. %c)", 'A' +
+							chip->revision - 1);
+	sprintf(card->longname, "%s at 0x%lx irq %i",
+				card->shortname, chip->port, chip->irq);
+
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	pci_set_drvdata(pci, card);
+	dev++;
+	return 0;
+}
+
+static struct pci_driver driver = {
+	.name = "ALS300",
+	.id_table = snd_als300_ids,
+	.probe = snd_als300_probe,
+	.remove = __devexit_p(snd_als300_remove),
+#ifdef CONFIG_PM
+	.suspend = snd_als300_suspend,
+	.resume = snd_als300_resume,
+#endif
+};
+
+static int __init alsa_card_als300_init(void)
+{
+	return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_als300_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_als300_init)
+module_exit(alsa_card_als300_exit)
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index d65ccb1..f078b71 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 #include <sound/driver.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <sound/core.h>
@@ -277,14 +276,14 @@
 #endif
 
 /* Driver stuff. */
-static int __devinit vortex_gameport_register(vortex_t * card);
+static int vortex_gameport_register(vortex_t * card);
 static void vortex_gameport_unregister(vortex_t * card);
 #ifndef CHIP_AU8820
-static int __devinit vortex_eq_init(vortex_t * vortex);
-static int __devexit vortex_eq_free(vortex_t * vortex);
+static int vortex_eq_init(vortex_t * vortex);
+static int vortex_eq_free(vortex_t * vortex);
 #endif
 /* ALSA stuff. */
-static int __devinit snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
-static int __devinit snd_vortex_mixer(vortex_t * vortex);
-static int __devinit snd_vortex_midi(vortex_t * vortex);
+static int snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr);
+static int snd_vortex_mixer(vortex_t * vortex);
+static int snd_vortex_midi(vortex_t * vortex);
 #endif
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 9cac02e..4347e6a 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2658,7 +2658,7 @@
 
 /* Initialization */
 
-static int vortex_core_init(vortex_t * vortex)
+static int __devinit vortex_core_init(vortex_t * vortex)
 {
 
 	printk(KERN_INFO "Vortex: init.... ");
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 64fbfbb..0c86a31 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -885,7 +885,7 @@
 };
 
 /* ALSA driver entry points. Init and exit. */
-static int vortex_eq_init(vortex_t * vortex)
+static int __devinit vortex_eq_init(vortex_t * vortex)
 {
 	struct snd_kcontrol *kcontrol;
 	int err, i;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 6a13ca1..7b5baa1 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -506,7 +506,7 @@
 	int i;
 	int err, nr_capt;
 
-	if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
+	if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
 		return -ENODEV;
 
 	/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 4f65ec5..ac4e73f 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1046,7 +1046,7 @@
 		snd_cs4281_pokeBA0(chip, regL, volL);
 		change = 1;
 	}
-	if (ucontrol->value.integer.value[0] != volL) {
+	if (ucontrol->value.integer.value[1] != volR) {
 		volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK);
 		snd_cs4281_pokeBA0(chip, regR, volR);
 		change = 1;
@@ -1416,7 +1416,7 @@
 static int snd_cs4281_chip_init(struct cs4281 *chip)
 {
 	unsigned int tmp;
-	int timeout;
+	unsigned long end_time;
 	int retry_count = 2;
 
 	/* Having EPPMC.FPDN=1 prevent proper chip initialisation */
@@ -1496,7 +1496,7 @@
 	/*
 	 * Wait for the DLL ready signal from the clock logic.
 	 */
-	timeout = 100;
+	end_time = jiffies + HZ;
 	do {
 		/*
 		 *  Read the AC97 status register to see if we've seen a CODEC
@@ -1504,8 +1504,8 @@
 		 */
 		if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
 			goto __ok0;
-		msleep(1);
-	} while (timeout-- > 0);
+		schedule_timeout_uninterruptible(1);
+	} while (time_after_eq(end_time, jiffies));
 
 	snd_printk(KERN_ERR "DLLRDY not seen\n");
 	return -EIO;
@@ -1522,7 +1522,7 @@
 	/*
 	 * Wait for the codec ready signal from the AC97 codec.
 	 */
-	timeout = 100;
+	end_time = jiffies + HZ;
 	do {
 		/*
 		 *  Read the AC97 status register to see if we've seen a CODEC
@@ -1530,20 +1530,20 @@
 		 */
 		if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
 			goto __ok1;
-		msleep(1);
-	} while (timeout-- > 0);
+		schedule_timeout_uninterruptible(1);
+	} while (time_after_eq(end_time, jiffies));
 
 	snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
 	return -EIO;
 
       __ok1:
 	if (chip->dual_codec) {
-		timeout = 100;
+		end_time = jiffies + HZ;
 		do {
 			if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
 				goto __codec2_ok;
-			msleep(1);
-		} while (timeout-- > 0);
+			schedule_timeout_uninterruptible(1);
+		} while (time_after_eq(end_time, jiffies));
 		snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
 		chip->dual_codec = 0;
 	__codec2_ok: ;
@@ -1561,7 +1561,7 @@
 	 *  the codec is pumping ADC data across the AC-link.
 	 */
 
-	timeout = 100;
+	end_time = jiffies + HZ;
 	do {
 		/*
 		 *  Read the input slot valid register and see if input slots 3
@@ -1569,8 +1569,8 @@
 		 */
                 if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
                         goto __ok2;
-		msleep(1);
-	} while (timeout-- > 0);
+		schedule_timeout_uninterruptible(1);
+	} while (time_after_eq(end_time, jiffies));
 
 	if (--retry_count > 0)
 		goto __retry;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 31cb9b4..6bfa084 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -843,8 +843,11 @@
 	 .spdif_bug = 1,
 	 .ac97_chip = 1} ,
 	/* Tested by shane-alsa@cm.nu 5th Nov 2005 */
+	/* The 0x20061102 does have SB0350 written on it
+	 * Just like 0x20021102
+	 */
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
-	 .driver = "Audigy2", .name = "Audigy 2 [2006]", 
+	 .driver = "Audigy2", .name = "Audigy 2 [SB0350b]", 
 	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b42dff7..5bee3b5 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -295,7 +295,7 @@
 		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
 		return -ENOMEM;
 	}
-	unsol->workq = create_workqueue("hda_codec");
+	unsol->workq = create_singlethread_workqueue("hda_codec");
 	if (! unsol->workq) {
 		snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
 		kfree(unsol);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c096606..0ad60ae 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -81,6 +81,7 @@
 			 "{Intel, ESB2},"
 			 "{Intel, ICH8},"
 			 "{ATI, SB450},"
+			 "{ATI, SB600},"
 			 "{VIA, VT8251},"
 			 "{VIA, VT8237A},"
 			 "{SiS, SIS966},"
@@ -1619,6 +1620,7 @@
 	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
 	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
 	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
+	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
 	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 32401bd..bcfca15 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -44,6 +44,7 @@
 					 * dig_out_nid and hp_nid are optional
 					 */
 	unsigned int cur_eapd;
+	unsigned int need_dac_fix;
 
 	/* capture */
 	unsigned int num_adc_nids;
@@ -800,6 +801,10 @@
 	  .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
 	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
 	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7,
+	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */
+	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
+	  .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
 	{}
 };
 
@@ -836,10 +841,14 @@
 	case AD1986A_3STACK:
 		spec->num_mixers = 2;
 		spec->mixers[1] = ad1986a_3st_mixers;
-		spec->num_init_verbs = 2;
+		spec->num_init_verbs = 3;
 		spec->init_verbs[1] = ad1986a_3st_init_verbs;
+		spec->init_verbs[2] = ad1986a_ch2_init;
 		spec->channel_mode = ad1986a_modes;
 		spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
+		spec->need_dac_fix = 1;
+		spec->multiout.max_channels = 2;
+		spec->multiout.num_dacs = 1;
 		break;
 	case AD1986A_LAPTOP:
 		spec->mixers[0] = ad1986a_laptop_mixers;
@@ -1325,6 +1334,8 @@
 	  .config = AD1981_HP }, /* HP nx6320 */
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x309f,
 	  .config = AD1981_HP }, /* HP nx9420 AngelFire */
+	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30a2,
+	  .config = AD1981_HP }, /* HP nx9420 AngelFire */
 	{ .modelname = "basic", .config = AD1981_BASIC },
 	{}
 };
@@ -1555,6 +1566,8 @@
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct ad198x_spec *spec = codec->spec;
+	if (spec->need_dac_fix)
+		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
 	return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
 				   spec->num_channel_mode, &spec->multiout.max_channels);
 }
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4c6c9ec..66bbdb6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -52,6 +52,7 @@
 	ALC880_CLEVO,
 	ALC880_TCL_S700,
 	ALC880_LG,
+	ALC880_LG_LW,
 #ifdef CONFIG_SND_DEBUG
 	ALC880_TEST,
 #endif
@@ -131,6 +132,7 @@
 	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
 
 	/* capture source */
+	unsigned int num_mux_defs;
 	const struct hda_input_mux *input_mux;
 	unsigned int cur_mux[3];
 
@@ -172,6 +174,7 @@
 	hda_nid_t dig_in_nid;
 	unsigned int num_channel_mode;
 	const struct hda_channel_mode *channel_mode;
+	unsigned int num_mux_defs;
 	const struct hda_input_mux *input_mux;
 	void (*unsol_event)(struct hda_codec *, unsigned int);
 	void (*init_hook)(struct hda_codec *);
@@ -185,7 +188,10 @@
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
+	if (mux_idx >= spec->num_mux_defs)
+		mux_idx = 0;
+	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
 }
 
 static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
@@ -203,7 +209,8 @@
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+	unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
+	return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
 				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
 }
 
@@ -245,7 +252,8 @@
  * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
  * are requested.  Therefore order this list so that this behaviour will not
  * cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour.
+ * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
+ * March 2006.
  */
 static char *alc_pin_mode_names[] = {
 	"Mic 50pc bias", "Mic 80pc bias",
@@ -255,19 +263,27 @@
 	PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
 };
 /* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin.
+ * in the pin being assumed to be exclusively an input or an output pin.  In
+ * addition, "input" pins may or may not process the mic bias option
+ * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
+ * accept requests for bias as of chip versions up to March 2006) and/or
+ * wiring in the computer.
  */
-#define ALC_PIN_DIR_IN    0x00
-#define ALC_PIN_DIR_OUT   0x01
-#define ALC_PIN_DIR_INOUT 0x02
+#define ALC_PIN_DIR_IN              0x00
+#define ALC_PIN_DIR_OUT             0x01
+#define ALC_PIN_DIR_INOUT           0x02
+#define ALC_PIN_DIR_IN_NOMICBIAS    0x03
+#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
 
-/* Info about the pin modes supported by the three different pin directions. 
+/* Info about the pin modes supported by the different pin direction modes. 
  * For each direction the minimum and maximum values are given.
  */
-static signed char alc_pin_mode_dir_info[3][2] = {
+static signed char alc_pin_mode_dir_info[5][2] = {
 	{ 0, 2 },    /* ALC_PIN_DIR_IN */
 	{ 3, 4 },    /* ALC_PIN_DIR_OUT */
 	{ 0, 4 },    /* ALC_PIN_DIR_INOUT */
+	{ 2, 2 },    /* ALC_PIN_DIR_IN_NOMICBIAS */
+	{ 2, 4 },    /* ALC_PIN_DIR_INOUT_NOMICBIAS */
 };
 #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
 #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
@@ -329,9 +345,10 @@
 		 * input modes.
 		 *
 		 * Dynamically switching the input/output buffers probably
-		 * reduces noise slightly, particularly on input.  However,
-		 * havingboth input and output buffers enabled
-		 * simultaneously doesn't seem to be problematic.
+		 * reduces noise slightly (particularly on input) so we'll
+		 * do it.  However, having both input and output buffers
+		 * enabled simultaneously doesn't seem to be problematic if
+		 * this turns out to be necessary in the future.
 		 */
 		if (val <= 2) {
 			snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE,
@@ -483,6 +500,9 @@
 	spec->multiout.dig_out_nid = preset->dig_out_nid;
 	spec->multiout.hp_nid = preset->hp_nid;
 	
+	spec->num_mux_defs = preset->num_mux_defs;
+	if (! spec->num_mux_defs)
+		spec->num_mux_defs = 1;
 	spec->input_mux = preset->input_mux;
 
 	spec->num_adc_nids = preset->num_adc_nids;
@@ -1427,6 +1447,82 @@
 }
 
 /*
+ * LG LW20
+ *
+ * Pin assignment:
+ *   Speaker-out: 0x14
+ *   Mic-In: 0x18
+ *   Built-in Mic-In: 0x19 (?)
+ *   HP-Out: 0x1b
+ *   SPDIF-Out: 0x1e
+ */
+
+/* seems analog CD is not working */
+static struct hda_input_mux alc880_lg_lw_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Internal Mic", 0x1 },
+	},
+};
+
+static struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+	{ } /* end */
+};
+
+static struct hda_verb alc880_lg_lw_init_verbs[] = {
+	/* set capture source to mic-in */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
+	/* speaker-out */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* HP-out */
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* mic-in to input */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* built-in mic */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* jack sense */
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1},
+	{ }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_lg_lw_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x1b, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+				 0x80, present ? 0x80 : 0);
+}
+
+static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	/* Looks like the unsol event is incompatible with the standard
+	 * definition.  4bit tag is placed at 28 bit!
+	 */
+	if ((res >> 28) == 0x01)
+		alc880_lg_lw_automute(codec);
+}
+
+/*
  * Common callbacks
  */
 
@@ -2078,6 +2174,9 @@
 	{ .modelname = "lg", .config = ALC880_LG },
 	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
 
+	{ .modelname = "lg-lw", .config = ALC880_LG_LW },
+	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
+
 #ifdef CONFIG_SND_DEBUG
 	{ .modelname = "test", .config = ALC880_TEST },
 #endif
@@ -2268,6 +2367,19 @@
 		.unsol_event = alc880_lg_unsol_event,
 		.init_hook = alc880_lg_automute,
 	},
+	[ALC880_LG_LW] = {
+		.mixers = { alc880_lg_lw_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_lg_lw_init_verbs },
+		.num_dacs = 1, 
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_lg_lw_capture_source,
+		.unsol_event = alc880_lg_lw_unsol_event,
+		.init_hook = alc880_lg_lw_automute,
+	},
 #ifdef CONFIG_SND_DEBUG
 	[ALC880_TEST] = {
 		.mixers = { alc880_test_mixer },
@@ -2593,6 +2705,7 @@
 
 	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
 
+	spec->num_mux_defs = 1;
 	spec->input_mux = &spec->private_imux;
 
 	return 1;
@@ -2722,30 +2835,56 @@
 };
 
 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines.
+ * headphone jack and the internal CD lines since these are the only pins at
+ * which audio can appear.  For flexibility, also allow the option of
+ * recording the mixer output on the second ADC (ADC0 doesn't have a
+ * connection to the mixer output).
  */
-static struct hda_input_mux alc260_fujitsu_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic/Line", 0x0 },
-		{ "CD", 0x4 },
-		{ "Headphone", 0x2 },
+static struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
+	{
+		.num_items = 3,
+		.items = {
+			{ "Mic/Line", 0x0 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x2 },
+		},
 	},
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic/Line", 0x0 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x2 },
+			{ "Mixer", 0x5 },
+		},
+	},
+
 };
 
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to
- * the Fujitsu S702x, but jacks are marked differently. We won't allow
- * retasking the Headphone jack, so it won't be available here.
+/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
+ * the Fujitsu S702x, but jacks are marked differently.
  */
-static struct hda_input_mux alc260_acer_capture_source = {
-	.num_items = 3,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
+static struct hda_input_mux alc260_acer_capture_sources[2] = {
+	{
+		.num_items = 4,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x5 },
+		},
+	},
+	{
+		.num_items = 5,
+		.items = {
+			{ "Mic", 0x0 },
+			{ "Line", 0x2 },
+			{ "CD", 0x4 },
+			{ "Headphone", 0x6 },
+			{ "Mixer", 0x5 },
+		},
 	},
 };
-
 /*
  * This is just place-holder, so there's something for alc_build_pcms to look
  * at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -2806,6 +2945,9 @@
 	{ } /* end */
 };
 
+/* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12, 
+ * HP jack = 0x14, CD audio =  0x16, internal speaker = 0x10.
+ */
 static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
@@ -2822,9 +2964,28 @@
 	{ } /* end */
 };
 
+/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks.  Note that current
+ * versions of the ALC260 don't act on requests to enable mic bias from NID
+ * 0x0f (used to drive the headphone jack in these laptops).  The ALC260
+ * datasheet doesn't mention this restriction.  At this stage it's not clear
+ * whether this behaviour is intentional or is a hardware bug in chip
+ * revisions available in early 2006.  Therefore for now allow the
+ * "Headphone Jack Mode" control to span all choices, but if it turns out
+ * that the lack of mic bias for this NID is intentional we could change the
+ * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ *
+ * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
+ * don't appear to make the mic bias available from the "line" jack, even
+ * though the NID used for this jack (0x14) can supply it.  The theory is
+ * that perhaps Acer have included blocking capacitors between the ALC260
+ * and the output jack.  If this turns out to be the case for all such
+ * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
+ * to ALC_PIN_DIR_INOUT_NOMICBIAS.
+ */
 static struct snd_kcontrol_new alc260_acer_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
+	ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -3038,7 +3199,8 @@
 };
 
 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops.
+ * laptops.  ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
+ * audio = 0x16, internal speaker = 0x10.
  */
 static struct hda_verb alc260_fujitsu_init_verbs[] = {
 	/* Disable all GPIOs */
@@ -3185,10 +3347,10 @@
 	{0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
 
 	/* Do similar with the second ADC: mute capture input amp and
-	 * set ADC connection to line (on line1 pin)
+	 * set ADC connection to mic to match ALSA's default state.
 	 */
 	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
 
 	/* Mute all inputs to mixer widget (even unconnected ones) */
 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
@@ -3213,26 +3375,35 @@
 static hda_nid_t alc260_test_adc_nids[2] = {
 	0x04, 0x05,
 };
-/* This is a bit messy since the two input muxes in the ALC260 have slight
- * variations in their signal assignments.  The ideal way to deal with this
- * is to extend alc_spec.input_mux to allow a different input MUX for each
- * ADC.  For the purposes of the test model it's sufficient to just list
- * both options for affected signal indices.  The separate input mux
- * functionality only needs to be considered if a model comes along which
- * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to
- * record.
+/* For testing the ALC260, each input MUX needs its own definition since
+ * the signal assignments are different.  This assumes that the first ADC 
+ * is NID 0x04.
  */
-static struct hda_input_mux alc260_test_capture_source = {
-	.num_items = 8,
-	.items = {
-		{ "MIC1 pin", 0x0 },
-		{ "MIC2 pin", 0x1 },
-		{ "LINE1 pin", 0x2 },
-		{ "LINE2 pin", 0x3 },
-		{ "CD pin", 0x4 },
-		{ "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 },
-		{ "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 },
-		{ "HP-OUT pin (cap2 only)", 0x7 },
+static struct hda_input_mux alc260_test_capture_sources[2] = {
+	{
+		.num_items = 7,
+		.items = {
+			{ "MIC1 pin", 0x0 },
+			{ "MIC2 pin", 0x1 },
+			{ "LINE1 pin", 0x2 },
+			{ "LINE2 pin", 0x3 },
+			{ "CD pin", 0x4 },
+			{ "LINE-OUT pin", 0x5 },
+			{ "HP-OUT pin", 0x6 },
+		},
+        },
+	{
+		.num_items = 8,
+		.items = {
+			{ "MIC1 pin", 0x0 },
+			{ "MIC2 pin", 0x1 },
+			{ "LINE1 pin", 0x2 },
+			{ "LINE2 pin", 0x3 },
+			{ "CD pin", 0x4 },
+			{ "Mixer", 0x5 },
+			{ "LINE-OUT pin", 0x6 },
+			{ "HP-OUT pin", 0x7 },
+		},
         },
 };
 static struct snd_kcontrol_new alc260_test_mixer[] = {
@@ -3244,7 +3415,17 @@
 	HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
 
-	/* Modes for retasking pin widgets */
+	/* Modes for retasking pin widgets
+	 * Note: the ALC260 doesn't seem to act on requests to enable mic
+         * bias from NIDs 0x0f and 0x10.  The ALC260 datasheet doesn't
+         * mention this restriction.  At this stage it's not clear whether
+         * this behaviour is intentional or is a hardware bug in chip
+         * revisions available at least up until early 2006.  Therefore for
+         * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
+         * choices, but if it turns out that the lack of mic bias for these
+         * NIDs is intentional we could change their modes from
+         * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
+	 */
 	ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
 	ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
 	ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
@@ -3606,6 +3787,7 @@
 
 	spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
 
+	spec->num_mux_defs = 1;
 	spec->input_mux = &spec->private_imux;
 
 	/* check whether NID 0x04 is valid */
@@ -3711,7 +3893,8 @@
 		.adc_nids = alc260_dual_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
-		.input_mux = &alc260_fujitsu_capture_source,
+		.num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
+		.input_mux = alc260_fujitsu_capture_sources,
 	},
 	[ALC260_ACER] = {
 		.mixers = { alc260_acer_mixer,
@@ -3723,7 +3906,8 @@
 		.adc_nids = alc260_dual_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
-		.input_mux = &alc260_acer_capture_source,
+		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
+		.input_mux = alc260_acer_capture_sources,
 	},
 #ifdef CONFIG_SND_DEBUG
 	[ALC260_TEST] = {
@@ -3736,7 +3920,8 @@
 		.adc_nids = alc260_test_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
-		.input_mux = &alc260_test_capture_source,
+		.num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
+		.input_mux = alc260_test_capture_sources,
 	},
 #endif
 };
@@ -3828,7 +4013,6 @@
 		{ "CD", 0x4 },
 	},
 };
-
 #define alc882_mux_enum_info alc_mux_enum_info
 #define alc882_mux_enum_get alc_mux_enum_get
 
@@ -4730,6 +4914,7 @@
 		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
 
 	spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
+	spec->num_mux_defs = 1;
 	spec->input_mux = &spec->private_imux;
 
 	return 1;
@@ -5406,6 +5591,7 @@
 
 	spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
 
+	spec->num_mux_defs = 1;
 	spec->input_mux = &spec->private_imux;
 
 	spec->adc_nids = alc861_adc_nids;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b56ca40..7152607 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -310,6 +310,9 @@
 	  .pci_subdevice = 0x0b0b,
 	  .config = STAC_D945GTP3 },	/* Intel D945PSN - 3 Stack, 9221 A1 */
 	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+	  .pci_subdevice = 0x0707,
+	  .config = STAC_D945GTP5 },	/* Intel D945PSV - 5 Stack */
+       { .pci_subvendor = PCI_VENDOR_ID_INTEL,
 	  .pci_subdevice = 0x0404,
 	  .config = STAC_D945GTP5 },	/* Intel D945GTP - 5 Stack */
 	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
@@ -534,6 +537,22 @@
 	return 0;
 }
 
+static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int pincap = snd_hda_param_read(codec, nid,
+						 AC_PAR_PIN_CAP);
+	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+	if (pincap & AC_PINCAP_VREF_100)
+		return AC_PINCTL_VREF_100;
+	if (pincap & AC_PINCAP_VREF_80)
+		return AC_PINCTL_VREF_80;
+	if (pincap & AC_PINCAP_VREF_50)
+		return AC_PINCTL_VREF_50;
+	if (pincap & AC_PINCAP_VREF_GRD)
+		return AC_PINCTL_VREF_GRD;
+	return 0;
+}
+
 static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
 
 {
@@ -571,9 +590,12 @@
 
 	if (val)
 		stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
-	else
-		stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
-
+	else {
+		unsigned int pinctl = AC_PINCTL_IN_EN;
+		if (io_idx) /* set VREF for mic */
+			pinctl |= stac92xx_get_vref(codec, nid);
+		stac92xx_auto_set_pinctl(codec, nid, pinctl);
+	}
         return 1;
 }
 
@@ -767,13 +789,8 @@
 		return 0;
 
 	wid_caps = get_wcaps(codec, pin);
-	if (wid_caps & AC_WCAP_UNSOL_CAP) {
-		/* Enable unsolicited responses on the HP widget */
-		snd_hda_codec_write(codec, pin, 0,
-				AC_VERB_SET_UNSOLICITED_ENABLE,
-				STAC_UNSOL_ENABLE);
+	if (wid_caps & AC_WCAP_UNSOL_CAP)
 		spec->hp_detect = 1;
-	}
 
 	nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
 	for (i = 0; i < cfg->line_outs; i++) {
@@ -896,13 +913,8 @@
 		return 0;
 
 	wid_caps = get_wcaps(codec, pin);
-	if (wid_caps & AC_WCAP_UNSOL_CAP) {
-		/* Enable unsolicited responses on the HP widget */
-		snd_hda_codec_write(codec, pin, 0,
-				AC_VERB_SET_UNSOLICITED_ENABLE,
-				STAC_UNSOL_ENABLE);
+	if (wid_caps & AC_WCAP_UNSOL_CAP)
 		spec->hp_detect = 1;
-	}
 
 	return 0;
 }
@@ -944,6 +956,10 @@
 
 	/* set up pins */
 	if (spec->hp_detect) {
+		/* Enable unsolicited responses on the HP widget */
+		snd_hda_codec_write(codec, cfg->hp_pin, 0,
+				AC_VERB_SET_UNSOLICITED_ENABLE,
+				STAC_UNSOL_ENABLE);
 		/* fake event to set up pins */
 		codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
 	} else {
@@ -951,9 +967,13 @@
 		stac92xx_auto_init_hp_out(codec);
 	}
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
-		if (cfg->input_pins[i])
-			stac92xx_auto_set_pinctl(codec, cfg->input_pins[i],
-						 AC_PINCTL_IN_EN);
+		hda_nid_t nid = cfg->input_pins[i];
+		if (nid) {
+			unsigned int pinctl = AC_PINCTL_IN_EN;
+			if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC)
+				pinctl |= stac92xx_get_vref(codec, nid);
+			stac92xx_auto_set_pinctl(codec, nid, pinctl);
+		}
 	}
 	if (cfg->dig_out_pin)
 		stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 7e6608b..336dc48 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -87,7 +87,151 @@
 #define CS8415_C_BUFFER	0x20
 #define CS8415_ID		0x7F
 
-static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
+/* PCA9554 registers */
+#define PCA9554_DEV     0x40            /* I2C device address */
+#define PCA9554_IN      0x00            /* input port */
+#define PCA9554_OUT     0x01            /* output port */
+#define PCA9554_INVERT  0x02            /* input invert */
+#define PCA9554_DIR     0x03            /* port directions */
+
+/*
+ * Aureon Universe additional controls using PCA9554
+ */
+
+/*
+ * Send data to pca9554
+ */
+static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
+				 unsigned char data)
+{
+	unsigned int tmp;
+	int i, j;
+	unsigned char dev = PCA9554_DEV;  /* ID 0100000, write */
+	unsigned char val = 0;
+
+	tmp = snd_ice1712_gpio_read(ice);
+
+	snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
+					 AUREON_WM_RW|AUREON_WM_CS|
+					 AUREON_CS8415_CS));
+	tmp |= AUREON_WM_RW;
+	tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
+
+	tmp &= ~AUREON_SPI_MOSI;
+	tmp &= ~AUREON_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(50);
+
+	/* 
+	 * send i2c stop condition and start condition
+	 * to obtain sane state
+	 */
+	tmp |= AUREON_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(50);
+	tmp |= AUREON_SPI_MOSI;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(100);
+	tmp &= ~AUREON_SPI_MOSI;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(50);
+	tmp &= ~AUREON_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(100);
+	/*
+	 * send device address, command and value,
+	 * skipping ack cycles inbetween
+	 */
+	for (j = 0; j < 3; j++) {
+		switch(j) {
+		case 0: val = dev; break;
+		case 1: val = reg; break;
+		case 2: val = data; break;
+		}
+		for (i = 7; i >= 0; i--) {
+			tmp &= ~AUREON_SPI_CLK;
+			snd_ice1712_gpio_write(ice, tmp);
+			udelay(40);
+			if (val & (1 << i))
+				tmp |= AUREON_SPI_MOSI;
+			else
+				tmp &= ~AUREON_SPI_MOSI;
+			snd_ice1712_gpio_write(ice, tmp);
+			udelay(40);
+			tmp |= AUREON_SPI_CLK;
+			snd_ice1712_gpio_write(ice, tmp);
+			udelay(40);
+		}
+                tmp &= ~AUREON_SPI_CLK;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(40);
+		tmp |= AUREON_SPI_CLK;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(40);
+		tmp &= ~AUREON_SPI_CLK;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(40);
+	}
+	tmp &= ~AUREON_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(40);
+	tmp &= ~AUREON_SPI_MOSI;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(40);
+	tmp |= AUREON_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(50);
+	tmp |= AUREON_SPI_MOSI;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(100);
+}
+
+static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
+	return 0;
+}
+
+static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char oval, nval;
+	int change;
+
+	snd_ice1712_save_gpio_status(ice);
+	
+	oval = ice->spec.aureon.pca9554_out;
+	nval = ucontrol->value.integer.value[0];
+	if ((change = (oval != nval))) {
+		aureon_pca9554_write(ice, PCA9554_OUT, nval);
+		ice->spec.aureon.pca9554_out = nval;
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	
+	return change;
+}
+
+
+static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
+			      unsigned short val)
+{
 	unsigned int tmp;
 
 	/* Send address to XILINX chip */
@@ -146,7 +290,8 @@
 /*
  * Initialize STAC9744 chip
  */
-static int aureon_ac97_init (struct snd_ice1712 *ice) {
+static int aureon_ac97_init (struct snd_ice1712 *ice)
+{
 	int i;
 	static unsigned short ac97_defaults[] = {
 		0x00, 0x9640,
@@ -1598,7 +1743,15 @@
  		.get = aureon_ac97_vol_get,
  		.put = aureon_ac97_vol_put,
  		.private_value = AC97_VIDEO|AUREON_AC97_STEREO
- 	}
+ 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Aux Source",
+		.info = aureon_universe_inmux_info,
+		.get = aureon_universe_inmux_get,
+		.put = aureon_universe_inmux_put
+	}
+
 };
 
 	
@@ -1856,6 +2009,10 @@
 	}
 
 	snd_ice1712_restore_gpio_status(ice);
+
+        /* initialize PCA9554 pin directions & set default input*/
+	aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
+	aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
 	
 	ice->spec.aureon.master[0] = WM_VOL_MUTE;
 	ice->spec.aureon.master[1] = WM_VOL_MUTE;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index b88eeba..32f8415 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2402,7 +2402,7 @@
 	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) {
                 /* Limit active ADCs and DACs to 6;  */
                 /* Note: DXR extension not supported */
-		pci_write_config_byte(ice->pci, 0x60, 0x0a);
+		pci_write_config_byte(ice->pci, 0x60, 0x2a);
 	} else {
 		pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
 	}
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index f9b22d4..053f8e5 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,7 @@
 			unsigned int cs8415_mux;
 			unsigned short master[2];
 			unsigned short vol[8];
+			unsigned char pca9554_out;
 		} aureon;
 		/* AC97 register cache for Phase28 */
 		struct phase28_spec {
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 44393e1..9c90d90 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -831,8 +831,8 @@
 	struct snd_pcm *pcm;
 
 	struct pci_dev *pci;
-	struct m3_quirk *quirk;
-	struct m3_hv_quirk *hv_quirk;
+	const struct m3_quirk *quirk;
+	const struct m3_hv_quirk *hv_quirk;
 
 	int dacs_active;
 	int timer_users;
@@ -892,7 +892,7 @@
 
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
-static struct m3_quirk m3_quirk_list[] = {
+static const struct m3_quirk m3_quirk_list[] = {
 	/* panasonic CF-28 "toughbook" */
 	{
 		.name = "Panasonic CF-28",
@@ -950,7 +950,7 @@
 };
 
 /* These values came from the Windows driver. */
-static struct m3_hv_quirk m3_hv_quirk_list[] = {
+static const struct m3_hv_quirk m3_hv_quirk_list[] = {
 	/* Allegro chips */
 	{ 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
 	{ 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
@@ -1361,7 +1361,7 @@
 }
 
 
-static struct play_vals {
+static const struct play_vals {
 	u16 addr, val;
 } pv[] = {
 	{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1428,7 +1428,7 @@
 /*
  *    Native record driver 
  */
-static struct rec_vals {
+static const struct rec_vals {
 	u16 addr, val;
 } rv[] = {
 	{CDATA_LEFT_VOLUME, ARB_VOLUME},
@@ -1598,12 +1598,26 @@
 	if (! s->running)
 		return;
 
-	hwptr = snd_m3_get_pointer(chip, s, subs) % s->dma_size;
-	diff = (s->dma_size + hwptr - s->hwptr) % s->dma_size;
+	hwptr = snd_m3_get_pointer(chip, s, subs);
+
+	/* try to avoid expensive modulo divisions */
+	if (hwptr >= s->dma_size)
+		hwptr %= s->dma_size;
+
+	diff = s->dma_size + hwptr - s->hwptr;
+	if (diff >= s->dma_size)
+		diff %= s->dma_size;
+
 	s->hwptr = hwptr;
 	s->count += diff;
+
 	if (s->count >= (signed)s->period_size) {
-		s->count %= s->period_size;
+
+		if (s->count < 2 * (signed)s->period_size)
+			s->count -= (signed)s->period_size;
+		else
+			s->count %= s->period_size;
+
 		spin_unlock(&chip->reg_lock);
 		snd_pcm_period_elapsed(subs);
 		spin_lock(&chip->reg_lock);
@@ -1942,6 +1956,7 @@
 	do {
 		if (! (snd_m3_inb(chip, 0x30) & 1))
 			return 0;
+		cpu_relax();
 	} while (i-- > 0);
 
 	snd_printk(KERN_ERR "ac97 serial bus busy\n");
@@ -1953,16 +1968,18 @@
 {
 	struct snd_m3 *chip = ac97->private_data;
 	unsigned long flags;
-	unsigned short data;
+	unsigned short data = 0xffff;
 
 	if (snd_m3_ac97_wait(chip))
-		return 0xffff;
+		goto fail;
 	spin_lock_irqsave(&chip->ac97_lock, flags);
 	snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
 	if (snd_m3_ac97_wait(chip))
-		return 0xffff;
+		goto fail_unlock;
 	data = snd_m3_inw(chip, CODEC_DATA);
+fail_unlock:
 	spin_unlock_irqrestore(&chip->ac97_lock, flags);
+fail:
 	return data;
 }
 
@@ -2121,7 +2138,7 @@
  * DSP Code images
  */
 
-static u16 assp_kernel_image[] __devinitdata = {
+static const u16 assp_kernel_image[] __devinitdata = {
     0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4, 
     0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 
     0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 
@@ -2208,7 +2225,7 @@
  * Mini sample rate converter code image
  * that is to be loaded at 0x400 on the DSP.
  */
-static u16 assp_minisrc_image[] __devinitdata = {
+static const u16 assp_minisrc_image[] __devinitdata = {
 
     0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412, 
     0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, 
@@ -2251,7 +2268,7 @@
  */
 
 #define MINISRC_LPF_LEN 10
-static u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
+static const u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
 	0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C,
 	0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
 };
@@ -2358,7 +2375,7 @@
 	 */
 
 	/*
-	 * align instance address to 256 bytes so that it's
+	 * align instance address to 256 bytes so that its
 	 * shifted list address is aligned.
 	 * list address = (mem address >> 1) >> 7;
 	 */
@@ -2647,8 +2664,8 @@
 {
 	struct snd_m3 *chip;
 	int i, err;
-	struct m3_quirk *quirk;
-	struct m3_hv_quirk *hv_quirk;
+	const struct m3_quirk *quirk;
+	const struct m3_hv_quirk *hv_quirk;
 	static struct snd_device_ops ops = {
 		.dev_free =	snd_m3_dev_free,
 	};
@@ -2843,12 +2860,12 @@
 	}
 
 #if 0 /* TODO: not supported yet */
-	/* TODO enable midi irq and i/o */
+	/* TODO enable MIDI IRQ and I/O */
 	err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
 				  chip->iobase + MPU401_DATA_PORT, 1,
 				  chip->irq, 0, &chip->rmidi);
 	if (err < 0)
-		printk(KERN_WARNING "maestro3: no midi support.\n");
+		printk(KERN_WARNING "maestro3: no MIDI support.\n");
 #endif
 
 	pci_set_drvdata(pci, card);
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index fdc652c..c40f590 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -274,12 +274,9 @@
 
 	/* test first xilinx */
 	chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
-	if (!second) {
-		if (chipsc & PCXHR_CHIPSC_GPI_USERI) {
-			snd_printdd("no need to load first xilinx\n");
-			return 0; /* first xilinx is already present and cannot be reset */
-		}
-	} else {
+	/* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
+	/* this bit will always be 1; no possibility to test presence of first xilinx */
+	if(second) {
 		if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
 			snd_printk(KERN_ERR "error loading first xilinx\n");
 			return -EINVAL;
diff --git a/sound/pci/riptide/Makefile b/sound/pci/riptide/Makefile
new file mode 100644
index 0000000..dcd2e64
--- /dev/null
+++ b/sound/pci/riptide/Makefile
@@ -0,0 +1,3 @@
+snd-riptide-objs := riptide.o
+
+obj-$(CONFIG_SND_RIPTIDE) += snd-riptide.o
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
new file mode 100644
index 0000000..f148ee4
--- /dev/null
+++ b/sound/pci/riptide/riptide.c
@@ -0,0 +1,2223 @@
+/*
+ *   Driver for the Conexant Riptide Soundchip
+ *
+ *	Copyright (c) 2004 Peter Gruber <nokos@gmx.net>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+/*
+  History:
+   - 02/15/2004 first release
+   
+  This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100)
+  credits from the original files:
+  
+  MODULE NAME:        cnxt_rt.h                       
+  AUTHOR:             K. Lazarev  (Transcribed by KNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           02/1/2000     KNL
+
+  MODULE NAME:     int_mdl.c                       
+  AUTHOR:          Konstantin Lazarev    (Transcribed by KNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           10/01/99      KNL
+	    
+  MODULE NAME:        riptide.h                       
+  AUTHOR:             O. Druzhinin  (Transcribed by OLD)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           10/16/97      OLD
+
+  MODULE NAME:        Rp_Cmdif.cpp                       
+  AUTHOR:             O. Druzhinin  (Transcribed by OLD)
+                      K. Lazarev    (Transcribed by KNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Adopted from NT4 driver            6/22/99      OLD
+            Ported to Linux                    9/01/99      KNL
+
+  MODULE NAME:        rt_hw.c                       
+  AUTHOR:             O. Druzhinin  (Transcribed by OLD)
+                      C. Lazarev    (Transcribed by CNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           11/18/97      OLD
+            Hardware functions for RipTide    11/24/97      CNL
+            (ES1) are coded
+            Hardware functions for RipTide    12/24/97      CNL
+            (A0) are coded
+            Hardware functions for RipTide    03/20/98      CNL
+            (A1) are coded
+            Boot loader is included           05/07/98      CNL
+            Redesigned for WDM                07/27/98      CNL
+            Redesigned for Linux              09/01/99      CNL
+
+  MODULE NAME:        rt_hw.h
+  AUTHOR:             C. Lazarev    (Transcribed by CNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           11/18/97      CNL
+
+  MODULE NAME:     rt_mdl.c                       
+  AUTHOR:          Konstantin Lazarev    (Transcribed by KNL)
+  HISTORY:         Major Revision               Date        By
+            -----------------------------     --------     -----
+            Created                           10/01/99      KNL
+
+  MODULE NAME:        mixer.h                        
+  AUTHOR:             K. Kenney
+  HISTORY:         Major Revision                   Date          By
+            -----------------------------          --------     -----
+            Created from MS W95 Sample             11/28/95      KRS
+            RipTide                                10/15/97      KRS
+            Adopted for Windows NT driver          01/20/98      CNL
+*/
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/gameport.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+#include <sound/initval.h>
+
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
+MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>");
+MODULE_DESCRIPTION("riptide");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+
+#ifdef SUPPORT_JOYSTICK
+static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 };
+#endif
+static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 };
+static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 };
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Riptide soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Riptide soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Riptide soundcard.");
+#ifdef SUPPORT_JOYSTICK
+module_param_array(joystick_port, int, NULL, 0444);
+MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard.");
+#endif
+module_param_array(mpu_port, int, NULL, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver.");
+module_param_array(opl3_port, int, NULL, 0444);
+MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
+
+/*
+ */
+
+#define MPU401_HW_RIPTIDE MPU401_HW_MPU401
+#define OPL3_HW_RIPTIDE   OPL3_HW_OPL3
+
+#define PCI_EXT_CapId       0x40
+#define PCI_EXT_NextCapPrt  0x41
+#define PCI_EXT_PWMC        0x42
+#define PCI_EXT_PWSCR       0x44
+#define PCI_EXT_Data00      0x46
+#define PCI_EXT_PMSCR_BSE   0x47
+#define PCI_EXT_SB_Base     0x48
+#define PCI_EXT_FM_Base     0x4a
+#define PCI_EXT_MPU_Base    0x4C
+#define PCI_EXT_Game_Base   0x4E
+#define PCI_EXT_Legacy_Mask 0x50
+#define PCI_EXT_AsicRev     0x52
+#define PCI_EXT_Reserved3   0x53
+
+#define LEGACY_ENABLE_ALL      0x8000	/* legacy device options */
+#define LEGACY_ENABLE_SB       0x4000
+#define LEGACY_ENABLE_FM       0x2000
+#define LEGACY_ENABLE_MPU_INT  0x1000
+#define LEGACY_ENABLE_MPU      0x0800
+#define LEGACY_ENABLE_GAMEPORT 0x0400
+
+#define MAX_WRITE_RETRY  10	/* cmd interface limits */
+#define MAX_ERROR_COUNT  10
+#define CMDIF_TIMEOUT    500000
+#define RESET_TRIES      5
+
+#define READ_PORT_ULONG(p)     inl((unsigned long)&(p))
+#define WRITE_PORT_ULONG(p,x)  outl(x,(unsigned long)&(p))
+
+#define READ_AUDIO_CONTROL(p)     READ_PORT_ULONG(p->audio_control)
+#define WRITE_AUDIO_CONTROL(p,x)  WRITE_PORT_ULONG(p->audio_control,x)
+#define UMASK_AUDIO_CONTROL(p,x)  WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x)
+#define MASK_AUDIO_CONTROL(p,x)   WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x)
+#define READ_AUDIO_STATUS(p)      READ_PORT_ULONG(p->audio_status)
+
+#define SET_GRESET(p)     UMASK_AUDIO_CONTROL(p,0x0001)	/* global reset switch */
+#define UNSET_GRESET(p)   MASK_AUDIO_CONTROL(p,~0x0001)
+#define SET_AIE(p)        UMASK_AUDIO_CONTROL(p,0x0004)	/* interrupt enable */
+#define UNSET_AIE(p)      MASK_AUDIO_CONTROL(p,~0x0004)
+#define SET_AIACK(p)      UMASK_AUDIO_CONTROL(p,0x0008)	/* interrupt acknowledge */
+#define UNSET_AIACKT(p)   MASKAUDIO_CONTROL(p,~0x0008)
+#define SET_ECMDAE(p)     UMASK_AUDIO_CONTROL(p,0x0010)
+#define UNSET_ECMDAE(p)   MASK_AUDIO_CONTROL(p,~0x0010)
+#define SET_ECMDBE(p)     UMASK_AUDIO_CONTROL(p,0x0020)
+#define UNSET_ECMDBE(p)   MASK_AUDIO_CONTROL(p,~0x0020)
+#define SET_EDATAF(p)     UMASK_AUDIO_CONTROL(p,0x0040)
+#define UNSET_EDATAF(p)   MASK_AUDIO_CONTROL(p,~0x0040)
+#define SET_EDATBF(p)     UMASK_AUDIO_CONTROL(p,0x0080)
+#define UNSET_EDATBF(p)   MASK_AUDIO_CONTROL(p,~0x0080)
+#define SET_ESBIRQON(p)   UMASK_AUDIO_CONTROL(p,0x0100)
+#define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100)
+#define SET_EMPUIRQ(p)    UMASK_AUDIO_CONTROL(p,0x0200)
+#define UNSET_EMPUIRQ(p)  MASK_AUDIO_CONTROL(p,~0x0200)
+#define IS_CMDE(a)        (READ_PORT_ULONG(a->stat)&0x1)	/* cmd empty */
+#define IS_DATF(a)        (READ_PORT_ULONG(a->stat)&0x2)	/* data filled */
+#define IS_READY(p)       (READ_AUDIO_STATUS(p)&0x0001)
+#define IS_DLREADY(p)     (READ_AUDIO_STATUS(p)&0x0002)
+#define IS_DLERR(p)       (READ_AUDIO_STATUS(p)&0x0004)
+#define IS_GERR(p)        (READ_AUDIO_STATUS(p)&0x0008)	/* error ! */
+#define IS_CMDAEIRQ(p)    (READ_AUDIO_STATUS(p)&0x0010)
+#define IS_CMDBEIRQ(p)    (READ_AUDIO_STATUS(p)&0x0020)
+#define IS_DATAFIRQ(p)    (READ_AUDIO_STATUS(p)&0x0040)
+#define IS_DATBFIRQ(p)    (READ_AUDIO_STATUS(p)&0x0080)
+#define IS_EOBIRQ(p)      (READ_AUDIO_STATUS(p)&0x0100)	/* interrupt status */
+#define IS_EOSIRQ(p)      (READ_AUDIO_STATUS(p)&0x0200)
+#define IS_EOCIRQ(p)      (READ_AUDIO_STATUS(p)&0x0400)
+#define IS_UNSLIRQ(p)     (READ_AUDIO_STATUS(p)&0x0800)
+#define IS_SBIRQ(p)       (READ_AUDIO_STATUS(p)&0x1000)
+#define IS_MPUIRQ(p)      (READ_AUDIO_STATUS(p)&0x2000)
+
+#define RESP 0x00000001		/* command flags */
+#define PARM 0x00000002
+#define CMDA 0x00000004
+#define CMDB 0x00000008
+#define NILL 0x00000000
+
+#define LONG0(a)   ((u32)a)	/* shifts and masks */
+#define BYTE0(a)   (LONG0(a)&0xff)
+#define BYTE1(a)   (BYTE0(a)<<8)
+#define BYTE2(a)   (BYTE0(a)<<16)
+#define BYTE3(a)   (BYTE0(a)<<24)
+#define WORD0(a)   (LONG0(a)&0xffff)
+#define WORD1(a)   (WORD0(a)<<8)
+#define WORD2(a)   (WORD0(a)<<16)
+#define TRINIB0(a) (LONG0(a)&0xffffff)
+#define TRINIB1(a) (TRINIB0(a)<<8)
+
+#define RET(a)     ((union cmdret *)(a))
+
+#define SEND_GETV(p,b)             sendcmd(p,RESP,GETV,0,RET(b))	/* get version */
+#define SEND_GETC(p,b,c)           sendcmd(p,PARM|RESP,GETC,c,RET(b))
+#define SEND_GUNS(p,b)             sendcmd(p,RESP,GUNS,0,RET(b))
+#define SEND_SCID(p,b)             sendcmd(p,RESP,SCID,0,RET(b))
+#define SEND_RMEM(p,b,c,d)         sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d))	/* memory access for firmware write */
+#define SEND_SMEM(p,b,c)           sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0))	/* memory access for firmware write */
+#define SEND_WMEM(p,b,c)           sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0))	/* memory access for firmware write */
+#define SEND_SDTM(p,b,c)           sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c))	/* memory access for firmware write */
+#define SEND_GOTO(p,b)             sendcmd(p,PARM,GOTO,LONG0(b),RET(0))	/* memory access for firmware write */
+#define SEND_SETDPLL(p)	           sendcmd(p,0,ARM_SETDPLL,0,RET(0))
+#define SEND_SSTR(p,b,c)           sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0))	/* start stream */
+#define SEND_PSTR(p,b)             sendcmd(p,PARM,PSTR,BYTE3(b),RET(0))	/* pause stream */
+#define SEND_KSTR(p,b)             sendcmd(p,PARM,KSTR,BYTE3(b),RET(0))	/* stop stream */
+#define SEND_KDMA(p)               sendcmd(p,0,KDMA,0,RET(0))	/* stop all dma */
+#define SEND_GPOS(p,b,c,d)         sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d))	/* get position in dma */
+#define SEND_SETF(p,b,c,d,e,f,g)   sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0))	/* set sample format at mixer */
+#define SEND_GSTS(p,b,c,d)         sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_NGPOS(p,b,c,d)        sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d))
+#define SEND_PSEL(p,b,c)           sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0))	/* activate lbus path */
+#define SEND_PCLR(p,b,c)           sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0))	/* deactivate lbus path */
+#define SEND_PLST(p,b)             sendcmd(p,PARM,PLST,BYTE3(b),RET(0))
+#define SEND_RSSV(p,b,c,d)         sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0))	/* select paths for internal connections */
+#define SEND_SSRC(p,b,c,d,e)       sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0))	/* configure source */
+#define SEND_SLST(p,b)             sendcmd(p,PARM,SLST,BYTE3(b),RET(0))
+#define SEND_RSRC(p,b,c)           sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c))	/* read source config */
+#define SEND_SSRB(p,b,c)           sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0))
+#define SEND_SDGV(p,b,c,d,e)       sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0))	/* set digital mixer */
+#define SEND_RDGV(p,b,c,d)         sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d))	/* read digital mixer */
+#define SEND_DLST(p,b)             sendcmd(p,PARM,DLST,BYTE3(b),RET(0))
+#define SEND_SACR(p,b,c)           sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0))	/* set AC97 register */
+#define SEND_RACR(p,b,c)           sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c))	/* get AC97 register */
+#define SEND_ALST(p,b)             sendcmd(p,PARM,ALST,BYTE3(b),RET(0))
+#define SEND_TXAC(p,b,c,d,e,f)     sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0))
+#define SEND_RXAC(p,b,c,d)         sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d))
+#define SEND_SI2S(p,b)             sendcmd(p,PARM,SI2S,WORD2(b),RET(0))
+
+#define EOB_STATUS         0x80000000	/* status flags : block boundary */
+#define EOS_STATUS         0x40000000	/*              : stoppped */
+#define EOC_STATUS         0x20000000	/*              : stream end */
+#define ERR_STATUS         0x10000000
+#define EMPTY_STATUS       0x08000000
+
+#define IEOB_ENABLE        0x1	/* enable interrupts for status notification above */
+#define IEOS_ENABLE        0x2
+#define IEOC_ENABLE        0x4
+#define RDONCE             0x8
+#define DESC_MAX_MASK      0xff
+
+#define ST_PLAY  0x1		/* stream states */
+#define ST_STOP  0x2
+#define ST_PAUSE 0x4
+
+#define I2S_INTDEC     3	/* config for I2S link */
+#define I2S_MERGER     0
+#define I2S_SPLITTER   0
+#define I2S_MIXER      7
+#define I2S_RATE       44100
+
+#define MODEM_INTDEC   4	/* config for modem link */
+#define MODEM_MERGER   3
+#define MODEM_SPLITTER 0
+#define MODEM_MIXER    11
+
+#define FM_INTDEC      3	/* config for FM/OPL3 link */
+#define FM_MERGER      0
+#define FM_SPLITTER    0
+#define FM_MIXER       9
+
+#define SPLIT_PATH  0x80	/* path splitting flag */
+
+enum FIRMWARE {
+	DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC,
+	EXT_LIN_ADDR_REC,
+};
+
+enum CMDS {
+	GETV = 0x00, GETC, GUNS, SCID, RMEM =
+	    0x10, SMEM, WMEM, SDTM, GOTO, SSTR =
+	    0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL =
+	    0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV =
+	    0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S =
+	    0x70, ARM_SETDPLL = 0x72,
+};
+
+enum E1SOURCE {
+	ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3,
+	ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7,
+	ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11,
+	ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15,
+	INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT,
+	INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT,
+	INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT,
+	DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1,
+	ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC,
+	DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT,
+	GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL,
+	SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL,
+	SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT,
+	MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT
+};
+
+enum E2SINK {
+	LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3,
+	LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7,
+	INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN,
+	INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN,
+	DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN,
+	PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK,
+	DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2,
+	DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5,
+	DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8,
+	DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11,
+	GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN,
+	SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN,
+	MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL,
+	MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX
+};
+
+enum LBUS_SINK {
+	LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR,
+	LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION,
+	LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2,
+};
+
+enum RT_CHANNEL_IDS {
+	M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2,
+	DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE,
+	M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2,
+	CHANNEL_ID_COUNTER
+};
+
+enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD };
+
+struct lbuspath {
+	unsigned char *noconv;
+	unsigned char *stereo;
+	unsigned char *mono;
+};
+
+struct cmdport {
+	u32 data1;		/* cmd,param */
+	u32 data2;		/* param */
+	u32 stat;		/* status */
+	u32 pad[5];
+};
+
+struct riptideport {
+	u32 audio_control;	/* status registers */
+	u32 audio_status;
+	u32 pad[2];
+	struct cmdport port[2];	/* command ports */
+};
+
+struct cmdif {
+	struct riptideport *hwport;
+	spinlock_t lock;
+	unsigned int cmdcnt;	/* cmd statistics */
+	unsigned int cmdtime;
+	unsigned int cmdtimemax;
+	unsigned int cmdtimemin;
+	unsigned int errcnt;
+	int is_reset;
+};
+
+struct riptide_firmware {
+	u16 ASIC;
+	u16 CODEC;
+	u16 AUXDSP;
+	u16 PROG;
+};
+
+union cmdret {
+	u8 retbytes[8];
+	u16 retwords[4];
+	u32 retlongs[2];
+};
+
+union firmware_version {
+	union cmdret ret;
+	struct riptide_firmware firmware;
+};
+
+#define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data)
+
+#define PLAYBACK_SUBSTREAMS 3
+struct snd_riptide {
+	struct snd_card *card;
+	struct pci_dev *pci;
+	const struct firmware *fw_entry;
+
+	struct cmdif *cif;
+
+	struct snd_pcm *pcm;
+	struct snd_pcm *pcm_i2s;
+	struct snd_rawmidi *rmidi;
+	struct snd_opl3 *opl3;
+	struct snd_ac97 *ac97;
+	struct snd_ac97_bus *ac97_bus;
+
+	struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS];
+	struct snd_pcm_substream *capture_substream;
+
+	int openstreams;
+
+	int irq;
+	unsigned long port;
+	unsigned short mpuaddr;
+	unsigned short opladdr;
+#ifdef SUPPORT_JOYSTICK
+	unsigned short gameaddr;
+#endif
+	struct resource *res_port;
+
+	unsigned short device_id;
+
+	union firmware_version firmware;
+
+	spinlock_t lock;
+	struct tasklet_struct riptide_tq;
+	struct snd_info_entry *proc_entry;
+
+	unsigned long received_irqs;
+	unsigned long handled_irqs;
+#ifdef CONFIG_PM
+	int in_suspend;
+#endif
+};
+
+struct sgd {			/* scatter gather desriptor */
+	u32 dwNextLink;
+	u32 dwSegPtrPhys;
+	u32 dwSegLen;
+	u32 dwStat_Ctl;
+};
+
+struct pcmhw {			/* pcm descriptor */
+	struct lbuspath paths;
+	unsigned char *lbuspath;
+	unsigned char source;
+	unsigned char intdec[2];
+	unsigned char mixer;
+	unsigned char id;
+	unsigned char state;
+	unsigned int rate;
+	unsigned int channels;
+	snd_pcm_format_t format;
+	struct snd_dma_buffer sgdlist;
+	struct sgd *sgdbuf;
+	unsigned int size;
+	unsigned int pages;
+	unsigned int oldpos;
+	unsigned int pointer;
+};
+
+#define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+		   union cmdret *ret);
+static int getsourcesink(struct cmdif *cif, unsigned char source,
+			 unsigned char sink, unsigned char *a,
+			 unsigned char *b);
+static int snd_riptide_initialize(struct snd_riptide *chip);
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
+
+/*
+ */
+
+static struct pci_device_id snd_riptide_ids[] = {
+	{
+	 .vendor = 0x127a,.device = 0x4310,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{
+	 .vendor = 0x127a,.device = 0x4320,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{
+	 .vendor = 0x127a,.device = 0x4330,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{
+	 .vendor = 0x127a,.device = 0x4340,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{0,},
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_device_id snd_riptide_joystick_ids[] = {
+	{
+	 .vendor = 0x127a,.device = 0x4312,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{
+	 .vendor = 0x127a,.device = 0x4322,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{.vendor = 0x127a,.device = 0x4332,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{.vendor = 0x127a,.device = 0x4342,
+	 .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
+	 },
+	{0,},
+};
+#endif
+
+MODULE_DEVICE_TABLE(pci, snd_riptide_ids);
+
+/*
+ */
+
+static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
+	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+								     LS_NONE2},
+	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
+								     LS_NONE2},
+	{INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR},
+	{INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR},
+	{INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM},
+	{INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT,
+					      LS_SRC_INTERPOLATORM},
+	{INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT,
+					      LS_SRC_INTERPOLATORM},
+	{INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT,
+					      LS_SRC_INTERPOLATORM},
+	{DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM},
+	{DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM},
+	{DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT,
+								LS_NONE2},
+	{NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN},
+	{GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT,
+						  LS_MIXER_GAIN_FUNCTION},
+	{GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT,
+						  LS_MIXER_GAIN_FUNCTION},
+	{GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1},
+	{SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER},
+	{SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER},
+	{MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER},
+	{MERGER1_OUT, LS_SRC_MERGER},
+	{MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER},
+	{MERGER2_OUT, LS_SRC_MERGER},
+	{MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT,
+								     LS_NONE2},
+};
+
+static unsigned char lbus_play_opl3[] = {
+	DIGITAL_MIXER_IN0 + FM_MIXER, 0xff
+};
+static unsigned char lbus_play_modem[] = {
+	DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff
+};
+static unsigned char lbus_play_i2s[] = {
+	INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff
+};
+static unsigned char lbus_play_out[] = {
+	PDAC2ACLNK, 0xff
+};
+static unsigned char lbus_play_outhp[] = {
+	HNDSPK2ACLNK, 0xff
+};
+static unsigned char lbus_play_noconv1[] = {
+	DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_stereo1[] = {
+	INTER0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_mono1[] = {
+	INTERM0_IN, DIGITAL_MIXER_IN0, 0xff
+};
+static unsigned char lbus_play_noconv2[] = {
+	DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_stereo2[] = {
+	INTER1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_mono2[] = {
+	INTERM1_IN, DIGITAL_MIXER_IN1, 0xff
+};
+static unsigned char lbus_play_noconv3[] = {
+	DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_stereo3[] = {
+	INTER2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_play_mono3[] = {
+	INTERM2_IN, DIGITAL_MIXER_IN2, 0xff
+};
+static unsigned char lbus_rec_noconv1[] = {
+	LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_stereo1[] = {
+	DECIM0_IN, LBUS2ARM_FIFO5, 0xff
+};
+static unsigned char lbus_rec_mono1[] = {
+	DECIMM3_IN, LBUS2ARM_FIFO5, 0xff
+};
+
+static unsigned char play_ids[] = { 4, 1, 2, };
+static unsigned char play_sources[] = {
+	ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,
+};
+static struct lbuspath lbus_play_paths[] = {
+	{
+	 .noconv = lbus_play_noconv1,
+	 .stereo = lbus_play_stereo1,
+	 .mono = lbus_play_mono1,
+	 },
+	{
+	 .noconv = lbus_play_noconv2,
+	 .stereo = lbus_play_stereo2,
+	 .mono = lbus_play_mono2,
+	 },
+	{
+	 .noconv = lbus_play_noconv3,
+	 .stereo = lbus_play_stereo3,
+	 .mono = lbus_play_mono3,
+	 },
+};
+static struct lbuspath lbus_rec_path = {
+	.noconv = lbus_rec_noconv1,
+	.stereo = lbus_rec_stereo1,
+	.mono = lbus_rec_mono1,
+};
+
+#define FIRMWARE_VERSIONS 1
+static union firmware_version firmware_versions[] = {
+	{
+	 .firmware.ASIC = 3,.firmware.CODEC = 2,
+	 .firmware.AUXDSP = 3,.firmware.PROG = 773,
+	 },
+};
+
+static u32 atoh(unsigned char *in, unsigned int len)
+{
+	u32 sum = 0;
+	unsigned int mult = 1;
+	unsigned char c;
+
+	while (len) {
+		c = in[len - 1];
+		if ((c >= '0') && (c <= '9'))
+			sum += mult * (c - '0');
+		else if ((c >= 'A') && (c <= 'F'))
+			sum += mult * (c - ('A' - 10));
+		else if ((c >= 'a') && (c <= 'f'))
+			sum += mult * (c - ('a' - 10));
+		mult *= 16;
+		--len;
+	}
+	return sum;
+}
+
+static int senddata(struct cmdif *cif, unsigned char *in, u32 offset)
+{
+	u32 addr;
+	u32 data;
+	u32 i;
+	unsigned char *p;
+
+	i = atoh(&in[1], 2);
+	addr = offset + atoh(&in[3], 4);
+	if (SEND_SMEM(cif, 0, addr) != 0)
+		return -EACCES;
+	p = in + 9;
+	while (i) {
+		data = atoh(p, 8);
+		if (SEND_WMEM(cif, 2,
+			      ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0)
+							    >> 4)))
+			return -EACCES;
+		i -= 4;
+		p += 8;
+	}
+	return 0;
+}
+
+static int loadfirmware(struct cmdif *cif, unsigned char *img,
+			unsigned int size)
+{
+	unsigned char *in;
+	u32 laddr, saddr, t, val;
+	int err = 0;
+
+	laddr = saddr = 0;
+	while (size > 0 && err == 0) {
+		in = img;
+		if (in[0] == ':') {
+			t = atoh(&in[7], 2);
+			switch (t) {
+			case DATA_REC:
+				err = senddata(cif, in, laddr + saddr);
+				break;
+			case EXT_SEG_ADDR_REC:
+				saddr = atoh(&in[9], 4) << 4;
+				break;
+			case EXT_LIN_ADDR_REC:
+				laddr = atoh(&in[9], 4) << 16;
+				break;
+			case EXT_GOTO_CMD_REC:
+				val = atoh(&in[9], 8);
+				if (SEND_GOTO(cif, val) != 0)
+					err = -EACCES;
+				break;
+			case EXT_END_OF_FILE:
+				size = 0;
+				break;
+			default:
+				break;
+			}
+			while (size > 0) {
+				size--;
+				if (*img++ == '\n')
+					break;
+			}
+		}
+	}
+	snd_printdd("load firmware return %d\n", err);
+	return err;
+}
+
+static void
+alloclbuspath(struct cmdif *cif, unsigned char source,
+	      unsigned char *path, unsigned char *mixer, unsigned char *s)
+{
+	while (*path != 0xff) {
+		unsigned char sink, type;
+
+		sink = *path & (~SPLIT_PATH);
+		if (sink != E2SINK_MAX) {
+			snd_printdd("alloc path 0x%x->0x%x\n", source, sink);
+			SEND_PSEL(cif, source, sink);
+			source = lbusin2out[sink][0];
+			type = lbusin2out[sink][1];
+			if (type == LS_MIXER_IN) {
+				if (mixer)
+					*mixer = sink - DIGITAL_MIXER_IN0;
+			}
+			if (type == LS_SRC_DECIMATORM ||
+			    type == LS_SRC_DECIMATOR ||
+			    type == LS_SRC_INTERPOLATORM ||
+			    type == LS_SRC_INTERPOLATOR) {
+				if (s) {
+					if (s[0] != 0xff)
+						s[1] = sink;
+					else
+						s[0] = sink;
+				}
+			}
+		}
+		if (*path++ & SPLIT_PATH) {
+			unsigned char *npath = path;
+
+			while (*npath != 0xff)
+				npath++;
+			alloclbuspath(cif, source + 1, ++npath, mixer, s);
+		}
+	}
+}
+
+static void
+freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
+{
+	while (*path != 0xff) {
+		unsigned char sink;
+
+		sink = *path & (~SPLIT_PATH);
+		if (sink != E2SINK_MAX) {
+			snd_printdd("free path 0x%x->0x%x\n", source, sink);
+			SEND_PCLR(cif, source, sink);
+			source = lbusin2out[sink][0];
+		}
+		if (*path++ & SPLIT_PATH) {
+			unsigned char *npath = path;
+
+			while (*npath != 0xff)
+				npath++;
+			freelbuspath(cif, source + 1, ++npath);
+		}
+	}
+}
+
+static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask)
+{
+	union cmdret rptr = CMDRET_ZERO;
+	unsigned int i = MAX_WRITE_RETRY;
+	int flag = 1;
+
+	SEND_RMEM(cif, 0x02, addr, &rptr);
+	rptr.retlongs[0] &= (~mask);
+
+	while (--i) {
+		SEND_SMEM(cif, 0x01, addr);
+		SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data));
+		SEND_RMEM(cif, 0x02, addr, &rptr);
+		if ((rptr.retlongs[0] & data) == data) {
+			flag = 0;
+			break;
+		} else
+			rptr.retlongs[0] &= ~mask;
+	}
+	snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask,
+		    flag);
+	return flag;
+}
+
+static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
+		   union cmdret *ret)
+{
+	int i, j;
+	int err;
+	unsigned int time = 0;
+	unsigned long irqflags;
+	struct riptideport *hwport;
+	struct cmdport *cmdport = NULL;
+
+	snd_assert(cif, return -EINVAL);
+
+	hwport = cif->hwport;
+	if (cif->errcnt > MAX_ERROR_COUNT) {
+		if (cif->is_reset) {
+			snd_printk(KERN_ERR
+				   "Riptide: Too many failed cmds, reinitializing\n");
+			if (riptide_reset(cif, NULL) == 0) {
+				cif->errcnt = 0;
+				return -EIO;
+			}
+		}
+		snd_printk(KERN_ERR "Riptide: Initialization failed.\n");
+		return -EINVAL;
+	}
+	if (ret) {
+		ret->retlongs[0] = 0;
+		ret->retlongs[1] = 0;
+	}
+	i = 0;
+	spin_lock_irqsave(&cif->lock, irqflags);
+	while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport))
+		udelay(10);
+	if (i >= CMDIF_TIMEOUT) {
+		err = -EBUSY;
+		goto errout;
+	}
+
+	err = 0;
+	for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) {
+		cmdport = &(hwport->port[j % 2]);
+		if (IS_DATF(cmdport)) {	/* free pending data */
+			READ_PORT_ULONG(cmdport->data1);
+			READ_PORT_ULONG(cmdport->data2);
+		}
+		if (IS_CMDE(cmdport)) {
+			if (flags & PARM)	/* put data */
+				WRITE_PORT_ULONG(cmdport->data2, parm);
+			WRITE_PORT_ULONG(cmdport->data1, cmd);	/* write cmd */
+			if ((flags & RESP) && ret) {
+				while (!IS_DATF(cmdport) &&
+				       time++ < CMDIF_TIMEOUT)
+					udelay(10);
+				if (time < CMDIF_TIMEOUT) {	/* read response */
+					ret->retlongs[0] =
+					    READ_PORT_ULONG(cmdport->data1);
+					ret->retlongs[1] =
+					    READ_PORT_ULONG(cmdport->data2);
+				} else {
+					err = -ENOSYS;
+					goto errout;
+				}
+			}
+			break;
+		}
+		udelay(20);
+	}
+	if (time == CMDIF_TIMEOUT) {
+		err = -ENODATA;
+		goto errout;
+	}
+	spin_unlock_irqrestore(&cif->lock, irqflags);
+
+	cif->cmdcnt++;		/* update command statistics */
+	cif->cmdtime += time;
+	if (time > cif->cmdtimemax)
+		cif->cmdtimemax = time;
+	if (time < cif->cmdtimemin)
+		cif->cmdtimemin = time;
+	if ((cif->cmdcnt) % 1000 == 0)
+		snd_printdd
+		    ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n",
+		     cif->cmdcnt, cif->cmdtime, cif->cmdtimemin,
+		     cif->cmdtimemax, cif->errcnt);
+	return 0;
+
+      errout:
+	cif->errcnt++;
+	spin_unlock_irqrestore(&cif->lock, irqflags);
+	snd_printdd
+	    ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n",
+	     cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport),
+	     flags, cmd, parm, ret ? ret->retlongs[0] : 0,
+	     ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport),
+	     err);
+	return err;
+}
+
+static int
+setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
+{
+	union cmdret rptr = CMDRET_ZERO;
+	int i = 0;
+
+	snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
+	do {
+		SEND_SDGV(cif, num, num, rval, lval);
+		SEND_RDGV(cif, num, num, &rptr);
+		if (rptr.retwords[0] == lval && rptr.retwords[1] == rval)
+			return 0;
+	} while (i++ < MAX_WRITE_RETRY);
+	snd_printdd("sent mixer failed\n");
+	return -EIO;
+}
+
+static int getpaths(struct cmdif *cif, unsigned char *o)
+{
+	unsigned char src[E2SINK_MAX];
+	unsigned char sink[E2SINK_MAX];
+	int i, j = 0;
+
+	for (i = 0; i < E2SINK_MAX; i++) {
+		getsourcesink(cif, i, i, &src[i], &sink[i]);
+		if (sink[i] < E2SINK_MAX) {
+			o[j++] = sink[i];
+			o[j++] = i;
+		}
+	}
+	return j;
+}
+
+static int
+getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink,
+	      unsigned char *a, unsigned char *b)
+{
+	union cmdret rptr = CMDRET_ZERO;
+
+	if (SEND_RSSV(cif, source, sink, &rptr) &&
+	    SEND_RSSV(cif, source, sink, &rptr))
+		return -EIO;
+	*a = rptr.retbytes[0];
+	*b = rptr.retbytes[1];
+	snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b);
+	return 0;
+}
+
+static int
+getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate)
+{
+	unsigned char *s;
+	unsigned int p[2] = { 0, 0 };
+	int i;
+	union cmdret rptr = CMDRET_ZERO;
+
+	s = intdec;
+	for (i = 0; i < 2; i++) {
+		if (*s != 0xff) {
+			if (SEND_RSRC(cif, *s, &rptr) &&
+			    SEND_RSRC(cif, *s, &rptr))
+				return -EIO;
+			p[i] += rptr.retwords[1];
+			p[i] *= rptr.retwords[2];
+			p[i] += rptr.retwords[3];
+			p[i] /= 65536;
+		}
+		s++;
+	}
+	if (p[0]) {
+		if (p[1] != p[0])
+			snd_printdd("rates differ %d %d\n", p[0], p[1]);
+		*rate = (unsigned int)p[0];
+	} else
+		*rate = (unsigned int)p[1];
+	snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate);
+	return 0;
+}
+
+static int
+setsampleformat(struct cmdif *cif,
+		unsigned char mixer, unsigned char id,
+		unsigned char channels, unsigned char format)
+{
+	unsigned char w, ch, sig, order;
+
+	snd_printdd
+	    ("setsampleformat mixer: %d id: %d channels: %d format: %d\n",
+	     mixer, id, channels, format);
+	ch = channels == 1;
+	w = snd_pcm_format_width(format) == 8;
+	sig = snd_pcm_format_unsigned(format) != 0;
+	order = snd_pcm_format_big_endian(format) != 0;
+
+	if (SEND_SETF(cif, mixer, w, ch, order, sig, id) &&
+	    SEND_SETF(cif, mixer, w, ch, order, sig, id)) {
+		snd_printdd("setsampleformat failed\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int
+setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate)
+{
+	u32 D, M, N;
+	union cmdret rptr = CMDRET_ZERO;
+	int i;
+
+	snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0],
+		    intdec[1], rate);
+	D = 48000;
+	M = ((rate == 48000) ? 47999 : rate) * 65536;
+	N = M % D;
+	M /= D;
+	for (i = 0; i < 2; i++) {
+		if (*intdec != 0xff) {
+			do {
+				SEND_SSRC(cif, *intdec, D, M, N);
+				SEND_RSRC(cif, *intdec, &rptr);
+			} while (rptr.retwords[1] != D &&
+				 rptr.retwords[2] != M &&
+				 rptr.retwords[3] != N &&
+				 i++ < MAX_WRITE_RETRY);
+			if (i == MAX_WRITE_RETRY) {
+				snd_printdd("sent samplerate %d: %d failed\n",
+					    *intdec, rate);
+				return -EIO;
+			}
+		}
+		intdec++;
+	}
+	return 0;
+}
+
+static int
+getmixer(struct cmdif *cif, short num, unsigned short *rval,
+	 unsigned short *lval)
+{
+	union cmdret rptr = CMDRET_ZERO;
+
+	if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr))
+		return -EIO;
+	*rval = rptr.retwords[0];
+	*lval = rptr.retwords[1];
+	snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
+	return 0;
+}
+
+static void riptide_handleirq(unsigned long dev_id)
+{
+	struct snd_riptide *chip = (void *)dev_id;
+	struct cmdif *cif = chip->cif;
+	struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
+	struct snd_pcm_runtime *runtime;
+	struct pcmhw *data = NULL;
+	unsigned int pos, period_bytes;
+	struct sgd *c;
+	int i, j;
+	unsigned int flag;
+
+	if (!cif)
+		return;
+
+	for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
+		substream[i] = chip->playback_substream[i];
+	substream[i] = chip->capture_substream;
+	for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) {
+		if (substream[i] &&
+		    (runtime = substream[i]->runtime) &&
+		    (data = runtime->private_data) && data->state != ST_STOP) {
+			pos = 0;
+			for (j = 0; j < data->pages; j++) {
+				c = &data->sgdbuf[j];
+				flag = le32_to_cpu(c->dwStat_Ctl);
+				if (flag & EOB_STATUS)
+					pos += le32_to_cpu(c->dwSegLen);
+				if (flag & EOC_STATUS)
+					pos += le32_to_cpu(c->dwSegLen);
+				if ((flag & EOS_STATUS)
+				    && (data->state == ST_PLAY)) {
+					data->state = ST_STOP;
+					snd_printk(KERN_ERR
+						   "Riptide: DMA stopped unexpectedly\n");
+				}
+				c->dwStat_Ctl =
+				    cpu_to_le32(flag &
+						~(EOS_STATUS | EOB_STATUS |
+						  EOC_STATUS));
+			}
+			data->pointer += pos;
+			pos += data->oldpos;
+			if (data->state != ST_STOP) {
+				period_bytes =
+				    frames_to_bytes(runtime,
+						    runtime->period_size);
+				snd_printdd
+				    ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n",
+				     READ_AUDIO_STATUS(cif->hwport),
+				     bytes_to_frames(runtime, pos),
+				     runtime->period_size);
+				j = 0;
+				if (pos >= period_bytes) {
+					j++;
+					while (pos >= period_bytes)
+						pos -= period_bytes;
+				}
+				data->oldpos = pos;
+				if (j > 0)
+					snd_pcm_period_elapsed(substream[i]);
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_PM
+static int riptide_suspend(struct pci_dev *pci, pm_message_t state)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_riptide *chip = card->private_data;
+
+	chip->in_suspend = 1;
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	snd_pcm_suspend_all(chip->pcm);
+	snd_ac97_suspend(chip->ac97);
+	pci_set_power_state(pci, PCI_D3hot);
+	pci_disable_device(pci);
+	pci_save_state(pci);
+	return 0;
+}
+
+static int riptide_resume(struct pci_dev *pci)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_riptide *chip = card->private_data;
+
+	pci_restore_state(pci);
+	pci_enable_device(pci);
+	pci_set_power_state(pci, PCI_D0);
+	pci_set_master(pci);
+	snd_riptide_initialize(chip);
+	snd_ac97_resume(chip->ac97);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	chip->in_suspend = 0;
+	return 0;
+}
+#endif
+
+static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
+{
+	int timeout, tries;
+	union cmdret rptr = CMDRET_ZERO;
+	union firmware_version firmware;
+	int i, j, err, has_firmware;
+
+	if (!cif)
+		return -EINVAL;
+
+	cif->cmdcnt = 0;
+	cif->cmdtime = 0;
+	cif->cmdtimemax = 0;
+	cif->cmdtimemin = 0xffffffff;
+	cif->errcnt = 0;
+	cif->is_reset = 0;
+
+	tries = RESET_TRIES;
+	has_firmware = 0;
+	while (has_firmware == 0 && tries-- > 0) {
+		for (i = 0; i < 2; i++) {
+			WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
+			WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
+		}
+		SET_GRESET(cif->hwport);
+		udelay(100);
+		UNSET_GRESET(cif->hwport);
+		udelay(100);
+
+		for (timeout = 100000; --timeout; udelay(10)) {
+			if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
+				break;
+		}
+		if (timeout == 0) {
+			snd_printk(KERN_ERR
+				   "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",
+				   READ_AUDIO_STATUS(cif->hwport),
+				   IS_READY(cif->hwport), IS_GERR(cif->hwport));
+			return -EIO;
+		} else {
+			snd_printdd
+			    ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
+			     READ_AUDIO_STATUS(cif->hwport),
+			     IS_READY(cif->hwport), IS_GERR(cif->hwport));
+		}
+
+		SEND_GETV(cif, &rptr);
+		for (i = 0; i < 4; i++)
+			firmware.ret.retwords[i] = rptr.retwords[i];
+
+		snd_printdd
+		    ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
+		     firmware.firmware.ASIC, firmware.firmware.CODEC,
+		     firmware.firmware.AUXDSP, firmware.firmware.PROG);
+
+		for (j = 0; j < FIRMWARE_VERSIONS; j++) {
+			has_firmware = 1;
+			for (i = 0; i < 4; i++) {
+				if (firmware_versions[j].ret.retwords[i] !=
+				    firmware.ret.retwords[i])
+					has_firmware = 0;
+			}
+			if (has_firmware)
+				break;
+		}
+
+		if (chip != NULL && has_firmware == 0) {
+			snd_printdd("Writing Firmware\n");
+			if (!chip->fw_entry) {
+				if ((err =
+				     request_firmware(&chip->fw_entry,
+						      "riptide.hex",
+						      &chip->pci->dev)) != 0) {
+					snd_printk(KERN_ERR
+						   "Riptide: Firmware not available %d\n",
+						   err);
+					return -EIO;
+				}
+			}
+			err = loadfirmware(cif, chip->fw_entry->data,
+					   chip->fw_entry->size);
+			if (err)
+				snd_printk(KERN_ERR
+					   "Riptide: Could not load firmware %d\n",
+					   err);
+		}
+	}
+
+	SEND_SACR(cif, 0, AC97_RESET);
+	SEND_RACR(cif, AC97_RESET, &rptr);
+	snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]);
+
+	SEND_PLST(cif, 0);
+	SEND_SLST(cif, 0);
+	SEND_DLST(cif, 0);
+	SEND_ALST(cif, 0);
+	SEND_KDMA(cif);
+
+	writearm(cif, 0x301F8, 1, 1);
+	writearm(cif, 0x301F4, 1, 1);
+
+	SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER,
+		  MODEM_SPLITTER, MODEM_MIXER);
+	setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff);
+	alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL);
+
+	SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER,
+		  FM_MIXER);
+	setmixer(cif, FM_MIXER, 0x7fff, 0x7fff);
+	writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005);
+	writearm(cif, 0x301A8, 0x02, 0x00000002);
+	writearm(cif, 0x30264, 0x08, 0xffffffff);
+	alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL);
+
+	SEND_SSRC(cif, I2S_INTDEC, 48000,
+		  ((u32) I2S_RATE * 65536) / 48000,
+		  ((u32) I2S_RATE * 65536) % 48000);
+	SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER,
+		  I2S_MIXER);
+	SEND_SI2S(cif, 1);
+	alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL);
+	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL);
+	alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL);
+
+	SET_AIACK(cif->hwport);
+	SET_AIE(cif->hwport);
+	SET_AIACK(cif->hwport);
+	cif->is_reset = 1;
+	if (chip) {
+		for (i = 0; i < 4; i++)
+			chip->firmware.ret.retwords[i] =
+			    firmware.ret.retwords[i];
+	}
+
+	return 0;
+}
+
+static struct snd_pcm_hardware snd_riptide_playback = {
+	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =
+	    SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+	    | SNDRV_PCM_FMTBIT_U16_LE,
+	.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+	.rate_min = 5500,
+	.rate_max = 48000,
+	.channels_min = 1,
+	.channels_max = 2,
+	.buffer_bytes_max = (64 * 1024),
+	.period_bytes_min = PAGE_SIZE >> 1,
+	.period_bytes_max = PAGE_SIZE << 8,
+	.periods_min = 2,
+	.periods_max = 64,
+	.fifo_size = 0,
+};
+static struct snd_pcm_hardware snd_riptide_capture = {
+	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =
+	    SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8
+	    | SNDRV_PCM_FMTBIT_U16_LE,
+	.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
+	.rate_min = 5500,
+	.rate_max = 48000,
+	.channels_min = 1,
+	.channels_max = 2,
+	.buffer_bytes_max = (64 * 1024),
+	.period_bytes_min = PAGE_SIZE >> 1,
+	.period_bytes_max = PAGE_SIZE << 3,
+	.periods_min = 2,
+	.periods_max = 64,
+	.fifo_size = 0,
+};
+
+static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream
+					     *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pcmhw *data = get_pcmhwdev(substream);
+	struct cmdif *cif = chip->cif;
+	union cmdret rptr = CMDRET_ZERO;
+	snd_pcm_uframes_t ret;
+
+	SEND_GPOS(cif, 0, data->id, &rptr);
+	if (data->size && runtime->period_size) {
+		snd_printdd
+		    ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n",
+		     data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size,
+		     bytes_to_frames(runtime, rptr.retlongs[1]),
+		     bytes_to_frames(runtime,
+				     rptr.retlongs[1]) % runtime->period_size);
+		if (rptr.retlongs[1] > data->pointer)
+			ret =
+			    bytes_to_frames(runtime,
+					    rptr.retlongs[1] % data->size);
+		else
+			ret =
+			    bytes_to_frames(runtime,
+					    data->pointer % data->size);
+	} else {
+		snd_printdd("stream not started or strange parms (%d %ld)\n",
+			    data->size, runtime->period_size);
+		ret = bytes_to_frames(runtime, 0);
+	}
+	return ret;
+}
+
+static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int i, j;
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+	struct cmdif *cif = chip->cif;
+	union cmdret rptr = CMDRET_ZERO;
+
+	spin_lock(&chip->lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (!(data->state & ST_PLAY)) {
+			SEND_SSTR(cif, data->id, data->sgdlist.addr);
+			SET_AIE(cif->hwport);
+			data->state = ST_PLAY;
+			if (data->mixer != 0xff)
+				setmixer(cif, data->mixer, 0x7fff, 0x7fff);
+			chip->openstreams++;
+			data->oldpos = 0;
+			data->pointer = 0;
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (data->mixer != 0xff)
+			setmixer(cif, data->mixer, 0, 0);
+		setmixer(cif, data->mixer, 0, 0);
+		SEND_KSTR(cif, data->id);
+		data->state = ST_STOP;
+		chip->openstreams--;
+		j = 0;
+		do {
+			i = rptr.retlongs[1];
+			SEND_GPOS(cif, 0, data->id, &rptr);
+			udelay(1);
+		} while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY);
+		if (j >= MAX_WRITE_RETRY)
+			snd_printk(KERN_ERR "Riptide: Could not stop stream!");
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (!(data->state & ST_PAUSE)) {
+			SEND_PSTR(cif, data->id);
+			data->state |= ST_PAUSE;
+			chip->openstreams--;
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (data->state & ST_PAUSE) {
+			SEND_SSTR(cif, data->id, data->sgdlist.addr);
+			data->state &= ~ST_PAUSE;
+			chip->openstreams++;
+		}
+		break;
+	default:
+		spin_unlock(&chip->lock);
+		return -EINVAL;
+	}
+	spin_unlock(&chip->lock);
+	return 0;
+}
+
+static int snd_riptide_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+	struct cmdif *cif = chip->cif;
+	unsigned char *lbuspath = NULL;
+	unsigned int rate, channels;
+	int err = 0;
+	snd_pcm_format_t format;
+
+	snd_assert(cif && data, return -EINVAL);
+
+	snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id,
+		    runtime->channels, runtime->format, runtime->rate);
+
+	spin_lock_irq(&chip->lock);
+	channels = runtime->channels;
+	format = runtime->format;
+	rate = runtime->rate;
+	switch (channels) {
+	case 1:
+		if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+			lbuspath = data->paths.noconv;
+		else
+			lbuspath = data->paths.mono;
+		break;
+	case 2:
+		if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE)
+			lbuspath = data->paths.noconv;
+		else
+			lbuspath = data->paths.stereo;
+		break;
+	}
+	snd_printdd("use sgdlist at 0x%p and buffer at 0x%p\n",
+		    data->sgdlist.area, sgbuf);
+	if (data->sgdlist.area && sgbuf) {
+		unsigned int i, j, size, pages, f, pt, period;
+		struct sgd *c, *p = NULL;
+
+		size = frames_to_bytes(runtime, runtime->buffer_size);
+		period = frames_to_bytes(runtime, runtime->period_size);
+		f = PAGE_SIZE;
+		while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period)
+			f = f >> 1;
+		pages = (size + f - 1) / f;
+		data->size = size;
+		data->pages = pages;
+		snd_printdd
+		    ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n",
+		     size, pages, f, period);
+		pt = 0;
+		j = 0;
+		for (i = 0; i < pages; i++) {
+			c = &data->sgdbuf[i];
+			if (p)
+				p->dwNextLink = cpu_to_le32(data->sgdlist.addr +
+							    (i *
+							     sizeof(struct
+								    sgd)));
+			c->dwNextLink = cpu_to_le32(data->sgdlist.addr);
+			c->dwSegPtrPhys =
+			    cpu_to_le32(sgbuf->table[j].addr + pt);
+			pt = (pt + f) % PAGE_SIZE;
+			if (pt == 0)
+				j++;
+			c->dwSegLen = cpu_to_le32(f);
+			c->dwStat_Ctl =
+			    cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE |
+					IEOC_ENABLE);
+			p = c;
+			size -= f;
+		}
+		data->sgdbuf[i].dwSegLen = cpu_to_le32(size);
+	}
+	if (lbuspath && lbuspath != data->lbuspath) {
+		if (data->lbuspath)
+			freelbuspath(cif, data->source, data->lbuspath);
+		alloclbuspath(cif, data->source, lbuspath,
+			      &data->mixer, data->intdec);
+		data->lbuspath = lbuspath;
+		data->rate = 0;
+	}
+	if (data->rate != rate || data->format != format ||
+	    data->channels != channels) {
+		data->rate = rate;
+		data->format = format;
+		data->channels = channels;
+		if (setsampleformat
+		    (cif, data->mixer, data->id, channels, format)
+		    || setsamplerate(cif, data->intdec, rate))
+			err = -EIO;
+	}
+	spin_unlock_irq(&chip->lock);
+	return err;
+}
+
+static int
+snd_riptide_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+	struct snd_dma_buffer *sgdlist = &data->sgdlist;
+	int err;
+
+	snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id,
+		    sgdlist->area, (unsigned long)sgdlist->addr,
+		    (int)sgdlist->bytes);
+	if (sgdlist->area)
+		snd_dma_free_pages(sgdlist);
+	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+				       snd_dma_pci_data(chip->pci),
+				       sizeof(struct sgd) * (DESC_MAX_MASK + 1),
+				       sgdlist)) < 0) {
+		snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n",
+			   (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1));
+		return err;
+	}
+	data->sgdbuf = (struct sgd *)sgdlist->area;
+	return snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+}
+
+static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+	struct cmdif *cif = chip->cif;
+
+	if (cif && data) {
+		if (data->lbuspath)
+			freelbuspath(cif, data->source, data->lbuspath);
+		data->lbuspath = NULL;
+		data->source = 0xff;
+		data->intdec[0] = 0xff;
+		data->intdec[1] = 0xff;
+
+		if (data->sgdlist.area) {
+			snd_dma_free_pages(&data->sgdlist);
+			data->sgdlist.area = NULL;
+		}
+	}
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pcmhw *data;
+	int index = substream->number;
+
+	chip->playback_substream[index] = substream;
+	runtime->hw = snd_riptide_playback;
+	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+	data->paths = lbus_play_paths[index];
+	data->id = play_ids[index];
+	data->source = play_sources[index];
+	data->intdec[0] = 0xff;
+	data->intdec[1] = 0xff;
+	data->state = ST_STOP;
+	runtime->private_data = data;
+	return snd_pcm_hw_constraint_integer(runtime,
+					     SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct pcmhw *data;
+
+	chip->capture_substream = substream;
+	runtime->hw = snd_riptide_capture;
+	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+	data->paths = lbus_rec_path;
+	data->id = PADC;
+	data->source = ACLNK2PADC;
+	data->intdec[0] = 0xff;
+	data->intdec[1] = 0xff;
+	data->state = ST_STOP;
+	runtime->private_data = data;
+	return snd_pcm_hw_constraint_integer(runtime,
+					     SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int snd_riptide_playback_close(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+	int index = substream->number;
+
+	substream->runtime->private_data = NULL;
+	chip->playback_substream[index] = NULL;
+	kfree(data);
+	return 0;
+}
+
+static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_riptide *chip = snd_pcm_substream_chip(substream);
+	struct pcmhw *data = get_pcmhwdev(substream);
+
+	substream->runtime->private_data = NULL;
+	chip->capture_substream = NULL;
+	kfree(data);
+	return 0;
+}
+
+static struct snd_pcm_ops snd_riptide_playback_ops = {
+	.open = snd_riptide_playback_open,
+	.close = snd_riptide_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_riptide_hw_params,
+	.hw_free = snd_riptide_hw_free,
+	.prepare = snd_riptide_prepare,
+	.page = snd_pcm_sgbuf_ops_page,
+	.trigger = snd_riptide_trigger,
+	.pointer = snd_riptide_pointer,
+};
+static struct snd_pcm_ops snd_riptide_capture_ops = {
+	.open = snd_riptide_capture_open,
+	.close = snd_riptide_capture_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_riptide_hw_params,
+	.hw_free = snd_riptide_hw_free,
+	.prepare = snd_riptide_prepare,
+	.page = snd_pcm_sgbuf_ops_page,
+	.trigger = snd_riptide_trigger,
+	.pointer = snd_riptide_pointer,
+};
+
+static int __devinit
+snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	if (rpcm)
+		*rpcm = NULL;
+	if ((err =
+	     snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1,
+			 &pcm)) < 0)
+		return err;
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_riptide_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_riptide_capture_ops);
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, "RIPTIDE");
+	chip->pcm = pcm;
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+					      snd_dma_pci_data(chip->pci),
+					      64 * 1024, 128 * 1024);
+	if (rpcm)
+		*rpcm = pcm;
+	return 0;
+}
+
+static irqreturn_t
+snd_riptide_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct snd_riptide *chip = dev_id;
+	struct cmdif *cif = chip->cif;
+
+	if (cif) {
+		chip->received_irqs++;
+		if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
+		    IS_EOCIRQ(cif->hwport)) {
+			chip->handled_irqs++;
+			tasklet_hi_schedule(&chip->riptide_tq);
+		}
+		if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
+			chip->handled_irqs++;
+			snd_mpu401_uart_interrupt(irq,
+						  chip->rmidi->private_data,
+						  regs);
+		}
+		SET_AIACK(cif->hwport);
+	}
+	return IRQ_HANDLED;
+}
+
+static void
+snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+			unsigned short val)
+{
+	struct snd_riptide *chip = ac97->private_data;
+	struct cmdif *cif = chip->cif;
+	union cmdret rptr = CMDRET_ZERO;
+	int i = 0;
+
+	snd_assert(cif, return);
+
+	snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val);
+	do {
+		SEND_SACR(cif, val, reg);
+		SEND_RACR(cif, reg, &rptr);
+	} while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY);
+	if (i == MAX_WRITE_RETRY)
+		snd_printdd("Write AC97 reg failed\n");
+}
+
+static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97,
+					     unsigned short reg)
+{
+	struct snd_riptide *chip = ac97->private_data;
+	struct cmdif *cif = chip->cif;
+	union cmdret rptr = CMDRET_ZERO;
+
+	snd_assert(cif, return 0);
+
+	if (SEND_RACR(cif, reg, &rptr) != 0)
+		SEND_RACR(cif, reg, &rptr);
+	snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]);
+	return rptr.retwords[1];
+}
+
+static int snd_riptide_initialize(struct snd_riptide *chip)
+{
+	struct cmdif *cif;
+	unsigned int device_id;
+	int err;
+
+	snd_assert(chip, return -EINVAL);
+
+	cif = chip->cif;
+	if (!cif) {
+		if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL)
+			return -ENOMEM;
+		cif->hwport = (struct riptideport *)chip->port;
+		spin_lock_init(&cif->lock);
+		chip->cif = cif;
+	}
+	cif->is_reset = 0;
+	if ((err = riptide_reset(cif, chip)) != 0)
+		return err;
+	device_id = chip->device_id;
+	switch (device_id) {
+	case 0x4310:
+	case 0x4320:
+	case 0x4330:
+		snd_printdd("Modem enable?\n");
+		SEND_SETDPLL(cif);
+		break;
+	}
+	snd_printdd("Enabling MPU IRQs\n");
+	if (chip->rmidi)
+		SET_EMPUIRQ(cif->hwport);
+	return err;
+}
+
+static int snd_riptide_free(struct snd_riptide *chip)
+{
+	struct cmdif *cif;
+
+	snd_assert(chip, return 0);
+
+	if ((cif = chip->cif)) {
+		SET_GRESET(cif->hwport);
+		udelay(100);
+		UNSET_GRESET(cif->hwport);
+		kfree(chip->cif);
+	}
+	if (chip->fw_entry)
+		release_firmware(chip->fw_entry);
+	release_and_free_resource(chip->res_port);
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+	kfree(chip);
+	return 0;
+}
+
+static int snd_riptide_dev_free(struct snd_device *device)
+{
+	struct snd_riptide *chip = device->device_data;
+
+	return snd_riptide_free(chip);
+}
+
+static int __devinit
+snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
+		   struct snd_riptide **rchip)
+{
+	struct snd_riptide *chip;
+	struct riptideport *hwport;
+	int err;
+	static struct snd_device_ops ops = {
+		.dev_free = snd_riptide_dev_free,
+	};
+
+	*rchip = NULL;
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+	if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL)))
+		return -ENOMEM;
+
+	spin_lock_init(&chip->lock);
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+	chip->openstreams = 0;
+	chip->port = pci_resource_start(pci, 0);
+	chip->received_irqs = 0;
+	chip->handled_irqs = 0;
+	chip->cif = NULL;
+	tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip);
+
+	if ((chip->res_port =
+	     request_region(chip->port, 64, "RIPTIDE")) == NULL) {
+		snd_printk(KERN_ERR
+			   "Riptide: unable to grab region 0x%lx-0x%lx\n",
+			   chip->port, chip->port + 64 - 1);
+		snd_riptide_free(chip);
+		return -EBUSY;
+	}
+	hwport = (struct riptideport *)chip->port;
+	UNSET_AIE(hwport);
+
+	if (request_irq
+	    (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ,
+	     "RIPTIDE", chip)) {
+		snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
+			   pci->irq);
+		snd_riptide_free(chip);
+		return -EBUSY;
+	}
+	chip->irq = pci->irq;
+	chip->device_id = pci->device;
+	pci_set_master(pci);
+	if ((err = snd_riptide_initialize(chip)) < 0) {
+		snd_riptide_free(chip);
+		return err;
+	}
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+		snd_riptide_free(chip);
+		return err;
+	}
+
+	*rchip = chip;
+	return 0;
+}
+
+static void
+snd_riptide_proc_read(struct snd_info_entry *entry,
+		      struct snd_info_buffer *buffer)
+{
+	struct snd_riptide *chip = entry->private_data;
+	struct pcmhw *data;
+	int i;
+	struct cmdif *cif = NULL;
+	unsigned char p[256];
+	unsigned short rval = 0, lval = 0;
+	unsigned int rate;
+
+	if (!chip)
+		return;
+
+	snd_iprintf(buffer, "%s\n\n", chip->card->longname);
+	snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:",
+		    chip->device_id, chip->handled_irqs, chip->received_irqs);
+	for (i = 0; i < 64; i += 4)
+		snd_iprintf(buffer, "%c%02x: %08x",
+			    (i % 16) ? ' ' : '\n', i, inl(chip->port + i));
+	if ((cif = chip->cif)) {
+		snd_iprintf(buffer,
+			    "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d",
+			    chip->firmware.firmware.ASIC,
+			    chip->firmware.firmware.CODEC,
+			    chip->firmware.firmware.AUXDSP,
+			    chip->firmware.firmware.PROG);
+		snd_iprintf(buffer, "\nDigital mixer:");
+		for (i = 0; i < 12; i++) {
+			getmixer(cif, i, &rval, &lval);
+			snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval);
+		}
+		snd_iprintf(buffer,
+			    "\nARM Commands num: %d failed: %d time: %d max: %d min: %d",
+			    cif->cmdcnt, cif->errcnt,
+			    cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin);
+	}
+	snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams);
+	for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) {
+		if (chip->playback_substream[i]
+		    && chip->playback_substream[i]->runtime
+		    && (data =
+			chip->playback_substream[i]->runtime->private_data)) {
+			snd_iprintf(buffer,
+				    "stream: %d mixer: %d source: %d (%d,%d)\n",
+				    data->id, data->mixer, data->source,
+				    data->intdec[0], data->intdec[1]);
+			if (!(getsamplerate(cif, data->intdec, &rate)))
+				snd_iprintf(buffer, "rate: %d\n", rate);
+		}
+	}
+	if (chip->capture_substream
+	    && chip->capture_substream->runtime
+	    && (data = chip->capture_substream->runtime->private_data)) {
+		snd_iprintf(buffer,
+			    "stream: %d mixer: %d source: %d (%d,%d)\n",
+			    data->id, data->mixer,
+			    data->source, data->intdec[0], data->intdec[1]);
+		if (!(getsamplerate(cif, data->intdec, &rate)))
+			snd_iprintf(buffer, "rate: %d\n", rate);
+	}
+	snd_iprintf(buffer, "Paths:\n");
+	i = getpaths(cif, p);
+	while (i--) {
+		snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
+		i--;
+	}
+	snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_riptide_proc_init(struct snd_riptide *chip)
+{
+	struct snd_info_entry *entry;
+
+	if (!snd_card_proc_new(chip->card, "riptide", &entry))
+		snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read);
+}
+
+static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
+{
+	struct snd_ac97_bus *pbus;
+	struct snd_ac97_template ac97;
+	int err = 0;
+	static struct snd_ac97_bus_ops ops = {
+		.write = snd_riptide_codec_write,
+		.read = snd_riptide_codec_read,
+	};
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.private_data = chip;
+	ac97.scaps = AC97_SCAP_SKIP_MODEM;
+
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
+		return err;
+
+	chip->ac97_bus = pbus;
+	ac97.pci = chip->pci;
+	if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0)
+		return err;
+	return err;
+}
+
+#ifdef SUPPORT_JOYSTICK
+static int have_joystick;
+static struct pci_dev *riptide_gameport_pci;
+static struct gameport *riptide_gameport;
+
+static int __devinit
+snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+	static int dev;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	if (joystick_port[dev]) {
+		riptide_gameport = gameport_allocate_port();
+		if (riptide_gameport) {
+			if (!request_region
+			    (joystick_port[dev], 8, "Riptide gameport")) {
+				snd_printk(KERN_WARNING
+					   "Riptide: cannot grab gameport 0x%x\n",
+					   joystick_port[dev]);
+				gameport_free_port(riptide_gameport);
+				riptide_gameport = NULL;
+			} else {
+				riptide_gameport_pci = pci;
+				riptide_gameport->io = joystick_port[dev];
+				gameport_register_port(riptide_gameport);
+			}
+		}
+	}
+	dev++;
+	return 0;
+}
+
+static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
+{
+	if (riptide_gameport) {
+		if (riptide_gameport_pci == pci) {
+			release_region(riptide_gameport->io, 8);
+			riptide_gameport_pci = NULL;
+			gameport_unregister_port(riptide_gameport);
+			riptide_gameport = NULL;
+		}
+	}
+}
+#endif
+
+static int __devinit
+snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	static int dev;
+	struct snd_card *card;
+	struct snd_riptide *chip;
+	unsigned short addr;
+	int err = 0;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (card == NULL)
+		return -ENOMEM;
+	if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	card->private_data = chip;
+	if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	if ((err = snd_riptide_mixer(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL
+			      | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0)
+#ifdef SUPPORT_JOYSTICK
+			      | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT :
+				 0)
+#endif
+			      | (mpu_port[dev]
+				 ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) :
+				 0)
+			      | ((chip->irq << 4) & 0xF0));
+	if ((addr = mpu_port[dev]) != 0) {
+		pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr);
+		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
+					       addr, 0, chip->irq, 0,
+					       &chip->rmidi)) < 0)
+			snd_printk(KERN_WARNING
+				   "Riptide: Can't Allocate MPU at 0x%x\n",
+				   addr);
+		else
+			chip->mpuaddr = addr;
+	}
+	if ((addr = opl3_port[dev]) != 0) {
+		pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr);
+		if ((err = snd_opl3_create(card, addr, addr + 2,
+					   OPL3_HW_RIPTIDE, 0,
+					   &chip->opl3)) < 0)
+			snd_printk(KERN_WARNING
+				   "Riptide: Can't Allocate OPL3 at 0x%x\n",
+				   addr);
+		else {
+			chip->opladdr = addr;
+			if ((err =
+			     snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0)
+				snd_printk(KERN_WARNING
+					   "Riptide: Can't Allocate OPL3-HWDEP\n");
+		}
+	}
+#ifdef SUPPORT_JOYSTICK
+	if ((addr = joystick_port[dev]) != 0) {
+		pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr);
+		chip->gameaddr = addr;
+	}
+#endif
+
+	strcpy(card->driver, "RIPTIDE");
+	strcpy(card->shortname, "Riptide");
+#ifdef SUPPORT_JOYSTICK
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x",
+		 card->shortname, chip->port, chip->irq, chip->mpuaddr,
+		 chip->opladdr, chip->gameaddr);
+#else
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x",
+		 card->shortname, chip->port, chip->irq, chip->mpuaddr,
+		 chip->opladdr);
+#endif
+	snd_riptide_proc_init(chip);
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+	pci_set_drvdata(pci, card);
+	dev++;
+	return 0;
+}
+
+static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+	.name = "RIPTIDE",
+	.id_table = snd_riptide_ids,
+	.probe = snd_card_riptide_probe,
+	.remove = __devexit_p(snd_card_riptide_remove),
+#ifdef CONFIG_PM
+	.suspend = riptide_suspend,
+	.resume = riptide_resume,
+#endif
+};
+
+#ifdef SUPPORT_JOYSTICK
+static struct pci_driver joystick_driver = {
+	.name = "Riptide Joystick",
+	.id_table = snd_riptide_joystick_ids,
+	.probe = snd_riptide_joystick_probe,
+	.remove = __devexit_p(snd_riptide_joystick_remove),
+};
+#endif
+
+static int __init alsa_card_riptide_init(void)
+{
+	int err;
+	if ((err = pci_register_driver(&driver)) < 0)
+		return err;
+#if defined(SUPPORT_JOYSTICK)
+	if (pci_register_driver(&joystick_driver) < 0) {
+		have_joystick = 0;
+		snd_printk(KERN_INFO "no joystick found\n");
+	} else
+		have_joystick = 1;
+#endif
+	return 0;
+}
+
+static void __exit alsa_card_riptide_exit(void)
+{
+	pci_unregister_driver(&driver);
+#if defined(SUPPORT_JOYSTICK)
+	if (have_joystick)
+		pci_unregister_driver(&joystick_driver);
+#endif
+}
+
+module_init(alsa_card_riptide_init);
+module_exit(alsa_card_riptide_exit);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 1957d29..0f171dd 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2333,6 +2333,7 @@
 		{ .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
 		{ .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
 		{ .subvendor = 0x1019, .subdevice = 0xa101, .action = VIA_DXS_SRC },
+		{ .subvendor = 0x1019, .subdevice = 0xaa01, .action = VIA_DXS_SRC }, /* ECS K8T890-A */
 		{ .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
 		{ .subvendor = 0x1025, .subdevice = 0x0046, .action = VIA_DXS_SRC }, /* Acer Aspire 1524 WLMi */
 		{ .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
@@ -2373,6 +2374,7 @@
 		{ .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
 		{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
 		{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+		{ .subvendor = 0x1695, .subdevice = 0x300c, .action = VIA_DXS_SRC }, /* EPoX EP-8KRAI */
 		{ .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */
 		{ .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */
 		{ .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 77caf43..adfdce7 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -57,18 +57,12 @@
 /*
  * prototypes
  */
-static void pdacf_config(dev_link_t *link);
+static int pdacf_config(struct pcmcia_device *link);
 static void snd_pdacf_detach(struct pcmcia_device *p_dev);
 
-static void pdacf_release(dev_link_t *link)
+static void pdacf_release(struct pcmcia_device *link)
 {
-	if (link->state & DEV_CONFIG) {
-		/* release cs resources */
-		pcmcia_release_configuration(link->handle);
-		pcmcia_release_io(link->handle, &link->io);
-		pcmcia_release_irq(link->handle, &link->irq);
-		link->state &= ~DEV_CONFIG;
-	}
+	pcmcia_disable_device(link);
 }
 
 /*
@@ -76,7 +70,7 @@
  */
 static int snd_pdacf_free(struct snd_pdacf *pdacf)
 {
-	dev_link_t *link = &pdacf->link;
+	struct pcmcia_device *link = pdacf->p_dev;
 
 	pdacf_release(link);
 
@@ -96,10 +90,9 @@
 /*
  * snd_pdacf_attach - attach callback for cs
  */
-static int snd_pdacf_attach(struct pcmcia_device *p_dev)
+static int snd_pdacf_probe(struct pcmcia_device *link)
 {
 	int i;
-	dev_link_t *link;               /* Info for cardmgr */
 	struct snd_pdacf *pdacf;
 	struct snd_card *card;
 	static struct snd_device_ops ops = {
@@ -139,7 +132,7 @@
 	pdacf->index = i;
 	card_list[i] = card;
 
-	link = &pdacf->link;
+	pdacf->p_dev = link;
 	link->priv = pdacf;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -156,13 +149,7 @@
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
 
-	/* Chain drivers */
-	link->next = NULL;
-
-	link->handle = p_dev;
-	pdacf_config(link);
-
-	return 0;
+	return pdacf_config(link);
 }
 
 
@@ -209,9 +196,8 @@
 /*
  * snd_pdacf_detach - detach callback for cs
  */
-static void snd_pdacf_detach(struct pcmcia_device *p_dev)
+static void snd_pdacf_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct snd_pdacf *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "pdacf_detach called\n");
@@ -230,13 +216,11 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void pdacf_config(dev_link_t *link)
+static int pdacf_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	struct snd_pdacf *pdacf = link->priv;
 	tuple_t tuple;
 	cisparse_t *parse = NULL;
-	config_info_t conf;
 	u_short buf[32];
 	int last_fn, last_ret;
 
@@ -244,7 +228,7 @@
 	parse = kmalloc(sizeof(*parse), GFP_KERNEL);
 	if (! parse) {
 		snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
-		return;
+		return -ENOMEM;
 	}
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	tuple.Attributes = 0;
@@ -252,71 +236,51 @@
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
 	link->conf.ConfigBase = parse->config.base;
 	link->conf.ConfigIndex = 0x5;
 	kfree(parse);
 
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-	link->conf.Vcc = conf.Vcc;
-
-	/* Configure card */
-	link->state |= DEV_CONFIG;
-
-	CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
 	if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
 		goto failed;
 
-	link->dev = &pdacf->node;
-	link->state &= ~DEV_CONFIG_PENDING;
-	return;
+	link->dev_node = &pdacf->node;
+	return 0;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 failed:
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
+	pcmcia_disable_device(link);
+	return -ENODEV;
 }
 
 #ifdef CONFIG_PM
 
-static int pdacf_suspend(struct pcmcia_device *dev)
+static int pdacf_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	struct snd_pdacf *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "SUSPEND\n");
-	link->state |= DEV_SUSPEND;
 	if (chip) {
 		snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
 		snd_pdacf_suspend(chip, PMSG_SUSPEND);
 	}
 
-	snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
-
 	return 0;
 }
 
-static int pdacf_resume(struct pcmcia_device *dev)
+static int pdacf_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	struct snd_pdacf *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "RESUME\n");
-	link->state &= ~DEV_SUSPEND;
-
-	snd_printdd(KERN_DEBUG "CARD_RESET\n");
-	if (DEV_OK(link)) {
-		snd_printdd(KERN_DEBUG "requestconfig...\n");
-		pcmcia_request_configuration(link->handle, &link->conf);
+	if (pcmcia_dev_present(link)) {
 		if (chip) {
 			snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
 			snd_pdacf_resume(chip);
@@ -343,7 +307,7 @@
 	.drv		= {
 		.name	= "snd-pdaudiocf",
 	},
-	.probe		= snd_pdacf_attach,
+	.probe		= snd_pdacf_probe,
 	.remove		= snd_pdacf_detach,
 	.id_table	= snd_pdacf_ids,
 #ifdef CONFIG_PM
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 2744f18..9a14a4f 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -116,7 +116,7 @@
 	void *pcm_area;
 	
 	/* pcmcia stuff */
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 };
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 66900d2..7e0cda2 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -59,15 +59,9 @@
 
 /*
  */
-static void vxpocket_release(dev_link_t *link)
+static void vxpocket_release(struct pcmcia_device *link)
 {
-	if (link->state & DEV_CONFIG) {
-		/* release cs resources */
-		pcmcia_release_configuration(link->handle);
-		pcmcia_release_io(link->handle, &link->io);
-		pcmcia_release_irq(link->handle, &link->irq);
-		link->state &= ~DEV_CONFIG;
-	}
+	pcmcia_disable_device(link);
 }
 
 /*
@@ -132,9 +126,9 @@
 /*
  * create vxpocket instance
  */
-static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
+static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl,
+					     struct pcmcia_device *link)
 {
-	dev_link_t *link;		/* Info for cardmgr */
 	struct vx_core *chip;
 	struct snd_vxpocket *vxp;
 	static struct snd_device_ops ops = {
@@ -154,7 +148,7 @@
 
 	vxp = (struct snd_vxpocket *)chip;
 
-	link = &vxp->link;
+	vxp->p_dev = link;
 	link->priv = chip;
 
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -167,7 +161,6 @@
 	link->irq.Instance = chip;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
@@ -215,9 +208,8 @@
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static void vxpocket_config(dev_link_t *link)
+static int vxpocket_config(struct pcmcia_device *link)
 {
-	client_handle_t handle = link->handle;
 	struct vx_core *chip = link->priv;
 	struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
 	tuple_t tuple;
@@ -229,24 +221,24 @@
 	parse = kmalloc(sizeof(*parse), GFP_KERNEL);
 	if (! parse) {
 		snd_printk(KERN_ERR "vx: cannot allocate\n");
-		return;
+		return -ENOMEM;
 	}
 	tuple.Attributes = 0;
 	tuple.TupleData = (cisdata_t *)buf;
 	tuple.TupleDataMax = sizeof(buf);
 	tuple.TupleOffset = 0;
 	tuple.DesiredTuple = CISTPL_CONFIG;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
 	link->conf.ConfigBase = parse->config.base;
 	link->conf.Present = parse->config.rmask[0];
 
 	/* redefine hardware record according to the VERSION1 string */
 	tuple.DesiredTuple = CISTPL_VERS_1;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
-	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
-	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
 	if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
 		snd_printdd("VX-pocket is detected\n");
 	} else {
@@ -257,67 +249,50 @@
 		strcpy(chip->card->driver, vxp440_hw.name);
 	}
 
-	/* Configure card */
-	link->state |= DEV_CONFIG;
+	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
-	CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
-	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
-
-	chip->dev = &handle_to_dev(link->handle);
+	chip->dev = &handle_to_dev(link);
 	snd_card_set_dev(chip->card, chip->dev);
 
 	if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
 		goto failed;
 
-	link->dev = &vxp->node;
-	link->state &= ~DEV_CONFIG_PENDING;
+	link->dev_node = &vxp->node;
 	kfree(parse);
-	return;
+	return 9;
 
 cs_failed:
-	cs_error(link->handle, last_fn, last_ret);
+	cs_error(link, last_fn, last_ret);
 failed:
-	pcmcia_release_configuration(link->handle);
-	pcmcia_release_io(link->handle, &link->io);
-	pcmcia_release_irq(link->handle, &link->irq);
-	link->state &= ~DEV_CONFIG;
+	pcmcia_disable_device(link);
 	kfree(parse);
+	return -ENODEV;
 }
 
 #ifdef CONFIG_PM
 
-static int vxp_suspend(struct pcmcia_device *dev)
+static int vxp_suspend(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	struct vx_core *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "SUSPEND\n");
-	link->state |= DEV_SUSPEND;
 	if (chip) {
 		snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
 		snd_vx_suspend(chip, PMSG_SUSPEND);
 	}
-	snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
-	if (link->state & DEV_CONFIG)
-		pcmcia_release_configuration(link->handle);
 
 	return 0;
 }
 
-static int vxp_resume(struct pcmcia_device *dev)
+static int vxp_resume(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(dev);
 	struct vx_core *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "RESUME\n");
-	link->state &= ~DEV_SUSPEND;
-
-	snd_printdd(KERN_DEBUG "CARD_RESET\n");
-	if (DEV_OK(link)) {
+	if (pcmcia_dev_present(link)) {
 		//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
-		snd_printdd(KERN_DEBUG "requestconfig...\n");
-		pcmcia_request_configuration(link->handle, &link->conf);
 		if (chip) {
 			snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
 			snd_vx_resume(chip);
@@ -333,7 +308,7 @@
 
 /*
  */
-static int vxpocket_attach(struct pcmcia_device *p_dev)
+static int vxpocket_probe(struct pcmcia_device *p_dev)
 {
 	struct snd_card *card;
 	struct snd_vxpocket *vxp;
@@ -358,7 +333,7 @@
 		return -ENOMEM;
 	}
 
-	vxp = snd_vxpocket_new(card, ibl[i]);
+	vxp = snd_vxpocket_new(card, ibl[i], p_dev);
 	if (! vxp) {
 		snd_card_free(card);
 		return -ENODEV;
@@ -368,20 +343,13 @@
 	vxp->index = i;
 	card_alloc |= 1 << i;
 
-	/* Chain drivers */
-	vxp->link.next = NULL;
+	vxp->p_dev = p_dev;
 
-	vxp->link.handle = p_dev;
-	vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-	p_dev->instance = &vxp->link;
-	vxpocket_config(&vxp->link);
-
-	return 0;
+	return vxpocket_config(p_dev);
 }
 
-static void vxpocket_detach(struct pcmcia_device *p_dev)
+static void vxpocket_detach(struct pcmcia_device *link)
 {
-	dev_link_t *link = dev_to_instance(p_dev);
 	struct snd_vxpocket *vxp;
 	struct vx_core *chip;
 
@@ -413,7 +381,7 @@
 	.drv		= {
 		.name	= "snd-vxpocket",
 	},
-	.probe		= vxpocket_attach,
+	.probe		= vxpocket_probe,
 	.remove		= vxpocket_detach,
 	.id_table	= vxp_ids,
 #ifdef CONFIG_PM
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 67efae3..27ea002 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -42,7 +42,7 @@
 	int index;	/* card index */
 
 	/* pcmcia stuff */
-	dev_link_t link;
+	struct pcmcia_device	*p_dev;
 	dev_node_t node;
 };
 
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index aa09ebd..46eebf5 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -255,7 +255,7 @@
 
 #ifdef CONFIG_KMOD
 	if (current->fs->root)
-		request_module("i2c-keywest");
+		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 1146dd8..70e4ebc 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1313,7 +1313,7 @@
 
 #ifdef CONFIG_KMOD
 	if (current->fs->root)
-		request_module("i2c-keywest");
+		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
 	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 8d08b34..ce86283 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -306,8 +306,8 @@
 		cval->res = 1;
 	if (val < cval->min)
 		return 0;
-	else if (val > cval->max)
-		return (cval->max - cval->min) / cval->res;
+	else if (val >= cval->max)
+		return (cval->max - cval->min + cval->res - 1) / cval->res;
 	else
 		return (val - cval->min) / cval->res;
 }
@@ -670,6 +670,36 @@
 		}
 		if (cval->res == 0)
 			cval->res = 1;
+
+		/* Additional checks for the proper resolution
+		 *
+		 * Some devices report smaller resolutions than actually
+		 * reacting.  They don't return errors but simply clip
+		 * to the lower aligned value.
+		 */
+		if (cval->min + cval->res < cval->max) {
+			int last_valid_res = cval->res;
+			int saved, test, check;
+			get_cur_mix_value(cval, minchn, &saved);
+			for (;;) {
+				test = saved;
+				if (test < cval->max)
+					test += cval->res;
+				else
+					test -= cval->res;
+				if (test < cval->min || test > cval->max ||
+				    set_cur_mix_value(cval, minchn, test) ||
+				    get_cur_mix_value(cval, minchn, &check)) {
+					cval->res = last_valid_res;
+					break;
+				}
+				if (test == check)
+					break;
+				cval->res *= 2;
+			}
+			set_cur_mix_value(cval, minchn, saved);
+		}
+
 		cval->initialized = 1;
 	}
 	return 0;
@@ -695,7 +725,8 @@
 		if (! cval->initialized)
 			get_min_max(cval,  0);
 		uinfo->value.integer.min = 0;
-		uinfo->value.integer.max = (cval->max - cval->min) / cval->res;
+		uinfo->value.integer.max =
+			(cval->max - cval->min + cval->res - 1) / cval->res;
 	}
 	return 0;
 }
diff --git a/usr/Makefile b/usr/Makefile
index e2129cb..19d74e6 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,65 +1,48 @@
+#
+# kbuild file for usr/ - including initramfs image
+#
 
+klibcdirs:;
+
+# Generate builtin.o based on initramfs_data.o
 obj-y := initramfs_data.o
 
-hostprogs-y  := gen_init_cpio
-
-clean-files := initramfs_data.cpio.gz initramfs_list
-
 # initramfs_data.o contains the initramfs_data.cpio.gz image.
 # The image is included using .incbin, a dependency which is not
 # tracked automatically.
 $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
 
-ifdef CONFIG_INITRAMFS_ROOT_UID
-gen_initramfs_args += -u $(CONFIG_INITRAMFS_ROOT_UID)
+#####
+# Generate the initramfs cpio archive
+
+hostprogs-y := gen_init_cpio
+initramfs   := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
+ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
+                    $(CONFIG_INITRAMFS_SOURCE),-d)
+ramfs-args  := \
+        $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
+        $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
+        $(ramfs-input)
+
+# .initramfs_data.cpio.gz.d is used to identify all files included
+# in initramfs and to detect if any files are added/removed.
+# Removed files are identified by directory timestamp being updated
+# The dependency list is generated by gen_initramfs.sh -l
+ifneq ($(wildcard $(obj)/.initramfs_data.cpio.gz.d),)
+	include $(obj)/.initramfs_data.cpio.gz.d
 endif
 
-ifdef CONFIG_INITRAMFS_ROOT_GID
-gen_initramfs_args += -g $(CONFIG_INITRAMFS_ROOT_GID)
-endif
+quiet_cmd_initfs = GEN     $@
+      cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 
-# The $(shell echo $(CONFIG_INITRAMFS_SOURCE)) is to remove the
-# gratuitous begin and end quotes from the Kconfig string type.
-# Internal, escaped quotes in the Kconfig string will loose the
-# escape and become active quotes.
-quotefixed_initramfs_source := $(shell echo $(CONFIG_INITRAMFS_SOURCE))
-
-filechk_initramfs_list = $(CONFIG_SHELL) \
- $(srctree)/scripts/gen_initramfs_list.sh $(gen_initramfs_args) $(quotefixed_initramfs_source)
-
-$(obj)/initramfs_list: $(obj)/Makefile FORCE
-	$(call filechk,initramfs_list)
-
-quiet_cmd_cpio = CPIO    $@
-      cmd_cpio = ./$< $(obj)/initramfs_list > $@
-
-
-# Check if the INITRAMFS_SOURCE is a cpio archive
-ifneq (,$(findstring .cpio,$(quotefixed_initramfs_source)))
-
-# INITRAMFS_SOURCE has a cpio archive - verify that it's a single file
-ifneq (1,$(words $(quotefixed_initramfs_source)))
-$(error Only a single file may be specified in CONFIG_INITRAMFS_SOURCE (="$(quotefixed_initramfs_source)") when a cpio archive is directly specified.)
-endif
-# Now use the cpio archive directly
-initramfs_data_cpio = $(quotefixed_initramfs_source)
-targets += $(quotefixed_initramfs_source)
-
-else
-
-# INITRAMFS_SOURCE is not a cpio archive - create one
-$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio \
-                            $(initramfs-y) $(obj)/initramfs_list FORCE
-	$(call if_changed,cpio)
-
-targets += initramfs_data.cpio
-initramfs_data_cpio = $(obj)/initramfs_data.cpio
-
-endif
-
-
-$(obj)/initramfs_data.cpio.gz: $(initramfs_data_cpio) FORCE
-	$(call if_changed,gzip)
-
-targets += initramfs_data.cpio.gz
+targets := initramfs_data.cpio.gz
+$(deps_initramfs): klibcdirs
+# We rebuild initramfs_data.cpio.gz if:
+# 1) Any included file is newer then initramfs_data.cpio.gz
+# 2) There are changes in which files are included (added or deleted)
+# 3) If gen_init_cpio are newer than initramfs_data.cpio.gz
+# 4) arguments to gen_initramfs.sh changes
+$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+	$(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
+	$(call if_changed,initfs)
 
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 33dbcbf..83acd6c 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -471,6 +471,7 @@
 				"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
 				line_nr, line);
 			ec = -1;
+			break;
 		}
 
 		if ('\n' == *type) {
@@ -506,7 +507,8 @@
 				line_nr, line);
 		}
 	}
-	cpio_trailer();
+	if (ec == 0)
+		cpio_trailer();
 
 	exit(ec);
 }